diff options
-rw-r--r-- | apps/plugins/sliding_puzzle.c | 317 |
1 files changed, 317 insertions, 0 deletions
diff --git a/apps/plugins/sliding_puzzle.c b/apps/plugins/sliding_puzzle.c new file mode 100644 index 0000000000..73b1ae3b08 --- /dev/null +++ b/apps/plugins/sliding_puzzle.c | |||
@@ -0,0 +1,317 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id: puzzle.c,v 1.1 2003/01/19 00:19:56 | ||
9 | * | ||
10 | * Copyright (C) 2002 Vicentini Martin | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include "plugin.h" | ||
20 | #ifdef HAVE_LCD_BITMAP | ||
21 | |||
22 | static struct plugin_api* rb; | ||
23 | static int spots[20]; | ||
24 | static int hole = 19, moves; | ||
25 | static char s[5]; | ||
26 | static bool pic = true; | ||
27 | static unsigned char *ptr; | ||
28 | static unsigned char picture[20][32] = { | ||
29 | { 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0xf8, 0xd9, | ||
30 | 0x10, 0xb0, 0x60, 0xc0, 0x80, 0x00, 0x30, 0x78, | ||
31 | 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x07, | ||
32 | 0xbf, 0xf8, 0x43, 0x1c, 0x61, 0x5e, 0xfc, 0xfc }, | ||
33 | |||
34 | { 0x68, 0xc8, 0x48, 0x08, 0x98, 0x90, 0xb0, 0xa4, | ||
35 | 0xa0, 0xc0, 0xc0, 0x88, 0x14, 0x08, 0x00, 0x00, | ||
36 | 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x03, | ||
37 | 0x00, 0x00, 0x30, 0x48, 0x79, 0x33, 0x06, 0x1c }, | ||
38 | |||
39 | { 0x20, 0x00, 0x06, 0x09, 0x09, 0x06, 0x00, 0x80, | ||
40 | 0x40, 0x80, 0x00, 0x08, 0x14, 0x08, 0x20, 0x00, | ||
41 | 0x60, 0x30, 0x18, 0xf9, 0x70, 0x00, 0x00, 0x00, | ||
42 | 0xf9, 0x18, 0x30, 0x60, 0x30, 0x18, 0x06, 0x32 }, | ||
43 | |||
44 | { 0x00, 0x80, 0x42, 0xa0, 0x50, 0x90, 0x88, 0x88, | ||
45 | 0x84, 0xa4, 0xa4, 0x64, 0x24, 0x18, 0x00, 0x40, | ||
46 | 0x79, 0x4a, 0x31, 0x02, 0x05, 0x2a, 0xd5, 0xaa, | ||
47 | 0x55, 0xaa, 0x55, 0xab, 0x56, 0xac, 0x58, 0xb0 }, | ||
48 | |||
49 | { 0x04, 0x0a, 0x04, 0x00, 0x80, 0x80, 0xc0, 0xc8, | ||
50 | 0x40, 0xc2, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, | ||
51 | 0x60, 0x38, 0x9c, 0xe7, 0x59, 0x0c, 0xc4, 0xfc, | ||
52 | 0x3f, 0x07, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00 }, | ||
53 | |||
54 | { 0x00, 0x04, 0x00, 0x00, 0x80, 0xe0, 0x78, 0x1e, | ||
55 | 0xa7, 0xd9, 0xcc, 0x76, 0x3b, 0x0d, 0x1f, 0xff, | ||
56 | 0x00, 0x00, 0x00, 0x00, 0x03, 0x13, 0x03, 0x03, | ||
57 | 0x11, 0x29, 0x10, 0x00, 0x04, 0x2a, 0x0b, 0x0b }, | ||
58 | |||
59 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, | ||
60 | 0xc0, 0x8e, 0x10, 0x00, 0x80, 0x80, 0x60, 0x38, | ||
61 | 0x0a, 0x08, 0x05, 0x05, 0x07, 0x03, 0x03, 0x03, | ||
62 | 0x03, 0x03, 0x01, 0x11, 0x01, 0x00, 0x00, 0x80 }, | ||
63 | |||
64 | { 0x0e, 0x18, 0x31, 0x3e, 0x1c, 0x00, 0x00, 0x1c, | ||
65 | 0x3e, 0x31, 0x18, 0x0c, 0x0c, 0x18, 0x30, 0x20, | ||
66 | 0x00, 0x00, 0x08, 0x14, 0x08, 0x00, 0x02, 0x80, | ||
67 | 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00 }, | ||
68 | |||
69 | { 0x60, 0xc0, 0x48, 0xc7, 0x60, 0xb8, 0x57, 0xaa, | ||
70 | 0x55, 0xaa, 0x55, 0xaa, 0xd5, 0xaa, 0x75, 0x3a, | ||
71 | 0x00, 0x00, 0x01, 0x23, 0x05, 0x05, 0x09, 0x0a, | ||
72 | 0x0b, 0x0a, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00 }, | ||
73 | |||
74 | { 0xe5, 0x8d, 0x18, 0x30, 0x41, 0xc1, 0x8f, 0xfe, | ||
75 | 0xf0, 0x81, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x00, | ||
76 | 0x00, 0x01, 0x03, 0x02, 0x06, 0x06, 0x04, 0x04, | ||
77 | 0x04, 0x05, 0x07, 0x06, 0x00, 0x00, 0x00, 0x00 }, | ||
78 | |||
79 | { 0x00, 0x00, 0x00, 0x10, 0x28, 0x10, 0x00, 0x04, | ||
80 | 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, | ||
81 | 0xc0, 0xb0, 0x18, 0xcc, 0x24, 0x86, 0x42, 0x22, | ||
82 | 0x31, 0x69, 0xd1, 0xa9, 0x51, 0xa1, 0x41, 0x02 }, | ||
83 | |||
84 | { 0x00, 0x00, 0x00, 0x00, 0x40, 0xa1, 0x40, 0x00, | ||
85 | 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
86 | 0x12, 0x16, 0x5c, 0x58, 0xf0, 0xc0, 0x00, 0x00, | ||
87 | 0x06, 0x09, 0x09, 0x86, 0x60, 0x18, 0xc4, 0xf2 }, | ||
88 | |||
89 | { 0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0x40, 0x40, | ||
90 | 0x40, 0x40, 0x40, 0x40, 0xc0, 0x80, 0x8c, 0x12, | ||
91 | 0x6a, 0xa5, 0x95, 0xd2, 0xca, 0xc9, 0xe9, 0xe9, | ||
92 | 0xe1, 0xe9, 0xe1, 0xe1, 0x62, 0x62, 0xc5, 0xc5 }, | ||
93 | |||
94 | { 0x12, 0x0c, 0x00, 0x80, 0x80, 0x40, 0x40, 0x40, | ||
95 | 0x40, 0x40, 0x40, 0x82, 0x85, 0x02, 0x00, 0x00, | ||
96 | 0x8a, 0x32, 0x6f, 0xd6, 0xaa, 0x55, 0x83, 0x01, | ||
97 | 0x81, 0x01, 0x81, 0x82, 0x82, 0x0d, 0xbe, 0xdc }, | ||
98 | |||
99 | { 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, | ||
100 | 0x41, 0x00, 0x00, 0x00, 0x02, 0x05, 0x02, 0x00, | ||
101 | 0x00, 0x00, 0x01, 0x02, 0x01, 0x04, 0x00, 0x60, | ||
102 | 0x90, 0x90, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 }, | ||
103 | |||
104 | { 0x3f, 0x6a, 0xc0, 0x9f, 0x20, 0x27, 0x48, 0x4b, | ||
105 | 0x47, 0x22, 0x50, 0x0f, 0x95, 0x4a, 0x25, 0x90, | ||
106 | 0x07, 0x0f, 0x17, 0x23, 0x43, 0x42, 0x44, 0x40, | ||
107 | 0x44, 0x40, 0x42, 0x40, 0x60, 0x30, 0x3c, 0x1f }, | ||
108 | |||
109 | { 0xd0, 0x50, 0x11, 0xb9, 0xef, 0x07, 0x80, 0x40, | ||
110 | 0x30, 0x98, 0x9c, 0xbf, 0x60, 0xc7, 0x0d, 0x36, | ||
111 | 0x59, 0x11, 0x21, 0x23, 0x22, 0x21, 0x30, 0x10, | ||
112 | 0x0d, 0x42, 0x01, 0x80, 0x00, 0x40, 0x03, 0x0c }, | ||
113 | |||
114 | { 0xc3, 0x81, 0x81, 0x00, 0x00, 0x01, 0x03, 0x03, | ||
115 | 0x03, 0x03, 0x02, 0x01, 0x00, 0x00, 0x80, 0x80, | ||
116 | 0x10, 0x91, 0x23, 0x23, 0x67, 0xe6, 0xe6, 0xa6, | ||
117 | 0xa6, 0xa6, 0xa6, 0xa6, 0xb3, 0x93, 0x59, 0x49 }, | ||
118 | |||
119 | { 0xc1, 0x71, 0xff, 0x54, 0x0a, 0x02, 0x06, 0x0e, | ||
120 | 0x0e, 0x0a, 0x06, 0x02, 0x02, 0xc5, 0x7b, 0x17, | ||
121 | 0x24, 0x10, 0x3b, 0x7f, 0x92, 0xa6, 0xa4, 0xa4, | ||
122 | 0xa4, 0xa4, 0xa4, 0x66, 0x23, 0x11, 0x12, 0x0c }, | ||
123 | |||
124 | { 0x55, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, | ||
125 | 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0xaa, | ||
126 | 0x55, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, | ||
127 | 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xaa } | ||
128 | }; | ||
129 | |||
130 | /* draws a spot at the coordinates (x,y), range of p is 1-20 */ | ||
131 | static void draw_spot(int p, int x, int y) { | ||
132 | if (pic || p==20) { | ||
133 | ptr = picture[p-1]; | ||
134 | rb->lcd_bitmap (ptr, x, y, 16, 8, true); | ||
135 | ptr += 16; | ||
136 | rb->lcd_bitmap (ptr, x, y+8, 16, 8, true); | ||
137 | } else { | ||
138 | rb->lcd_drawrect(x, y, 16, 16); | ||
139 | rb->lcd_clearrect(x+1, y+1, 14, 14); | ||
140 | rb->snprintf(s, sizeof(s), "%d", p); | ||
141 | rb->lcd_putsxy(x+2, y+4, s); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /* check if the puzzle is solved */ | ||
146 | static bool puzzle_finished(void) { | ||
147 | int i; | ||
148 | for (i=0; i<20; i++) | ||
149 | if (spots[i] != (i+1)) | ||
150 | return false; | ||
151 | return true; | ||
152 | } | ||
153 | |||
154 | /* move a piece in any direction */ | ||
155 | static void move_spot(int x, int y) { | ||
156 | int i; | ||
157 | spots[hole] = spots[hole-x-5*y]; | ||
158 | hole -= (x+5*y); | ||
159 | moves++; | ||
160 | rb->snprintf(s, sizeof(s), "%d", moves); | ||
161 | rb->lcd_putsxy(85, 20, s); | ||
162 | |||
163 | for (i=4; i<=16; i+=4) { | ||
164 | draw_spot(20, (hole%5)*16, (hole/5)*16); | ||
165 | draw_spot(spots[hole], (hole%5)*16 + x*i, (hole/5)*16 + y*i); | ||
166 | rb->lcd_update(); | ||
167 | } | ||
168 | spots[hole] = 20; | ||
169 | } | ||
170 | |||
171 | /* initializes the puzzle */ | ||
172 | static void puzzle_init(void) { | ||
173 | int i, r, temp, tsp[20]; | ||
174 | moves = 0; | ||
175 | rb->lcd_clear_display(); | ||
176 | rb->lcd_drawrect(80, 0, 32, 64); | ||
177 | rb->lcd_putsxy(81, 10, "Moves"); | ||
178 | rb->snprintf(s, sizeof(s), "%d", moves); | ||
179 | rb->lcd_putsxy(85, 20, s); | ||
180 | |||
181 | // shuffle spots | ||
182 | for (i=19; i>=0; i--) { | ||
183 | r = (*rb->current_tick % (i+1)); | ||
184 | |||
185 | temp = spots[r]; | ||
186 | spots[r] = spots[i]; | ||
187 | spots[i] = temp; | ||
188 | |||
189 | if (spots[i]==20) | ||
190 | hole = i; | ||
191 | } | ||
192 | |||
193 | // test if the puzzle is solvable | ||
194 | for (i=0; i<20; i++) | ||
195 | tsp[i] = spots[i]; | ||
196 | r=0; | ||
197 | if (((4-hole%5) + (3-hole/5))%2 == 1) | ||
198 | ++r; | ||
199 | for (i=0; i<15; i++) { | ||
200 | while (tsp[i] != (i+1)) { | ||
201 | temp = tsp[i]; | ||
202 | tsp[i] = tsp[temp-1]; | ||
203 | tsp[temp-1] = temp; | ||
204 | ++r; | ||
205 | } | ||
206 | } | ||
207 | |||
208 | // if the random puzzle isn't solvable just change two spots | ||
209 | if (r%2 == 1) { | ||
210 | if (spots[0]!=20 && spots[1]!=20) { | ||
211 | temp = spots[0]; | ||
212 | spots[0] = spots[1]; | ||
213 | spots[1] = temp; | ||
214 | } else { | ||
215 | temp = spots[2]; | ||
216 | spots[2] = spots[3]; | ||
217 | spots[3] = temp; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | // draw spots to the lcd | ||
222 | for (i=0; i<20; i++) | ||
223 | draw_spot(spots[i], (i%5)*16, (i/5)*16); | ||
224 | rb->lcd_update(); | ||
225 | } | ||
226 | |||
227 | /* the main game loop */ | ||
228 | static int puzzle_loop(void) { | ||
229 | int i; | ||
230 | puzzle_init(); | ||
231 | while(true) { | ||
232 | switch (rb->button_get(true)) { | ||
233 | case BUTTON_OFF: | ||
234 | /* get out of here */ | ||
235 | return PLUGIN_OK; | ||
236 | |||
237 | case BUTTON_F1: | ||
238 | /* mix up the pieces */ | ||
239 | puzzle_init(); | ||
240 | break; | ||
241 | |||
242 | case BUTTON_F2: | ||
243 | /* change picture */ | ||
244 | pic = (pic==true?false:true); | ||
245 | for (i=0; i<20; i++) | ||
246 | draw_spot(spots[i], (i%5)*16, (i/5)*16); | ||
247 | rb->lcd_update(); | ||
248 | break; | ||
249 | |||
250 | case BUTTON_LEFT: | ||
251 | if ((hole%5)<4 && !puzzle_finished()) | ||
252 | move_spot(-1, 0); | ||
253 | break; | ||
254 | |||
255 | case BUTTON_RIGHT: | ||
256 | if ((hole%5)>0 && !puzzle_finished()) | ||
257 | move_spot(1, 0); | ||
258 | break; | ||
259 | |||
260 | case BUTTON_UP: | ||
261 | if ((hole/5)<3 && !puzzle_finished()) | ||
262 | move_spot(0, -1); | ||
263 | break; | ||
264 | |||
265 | case BUTTON_DOWN: | ||
266 | if ((hole/5)>0 && !puzzle_finished()) | ||
267 | move_spot(0, 1); | ||
268 | break; | ||
269 | |||
270 | case SYS_USB_CONNECTED: | ||
271 | rb->usb_screen(); | ||
272 | return PLUGIN_USB_CONNECTED; | ||
273 | } | ||
274 | } | ||
275 | } | ||
276 | |||
277 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | ||
278 | { | ||
279 | int i, w, h; | ||
280 | |||
281 | TEST_PLUGIN_API(api); | ||
282 | (void)parameter; | ||
283 | rb = api; | ||
284 | |||
285 | /* print title */ | ||
286 | rb->lcd_getstringsize("Sliding Puzzle", &w, &h); | ||
287 | w = (w+1)/2; | ||
288 | h = (h+1)/2; | ||
289 | rb->lcd_clear_display(); | ||
290 | rb->lcd_putsxy(LCD_WIDTH/2-w, (LCD_HEIGHT/2)-h, "Sliding Puzzle"); | ||
291 | rb->lcd_update(); | ||
292 | rb->sleep(HZ); | ||
293 | |||
294 | /* print instructions */ | ||
295 | rb->lcd_clear_display(); | ||
296 | rb->lcd_putsxy(3, 18, "[OFF] to stop"); | ||
297 | rb->lcd_putsxy(3, 28, "[F1] shuffle"); | ||
298 | rb->lcd_putsxy(3, 38, "[F2] change pic"); | ||
299 | rb->lcd_update(); | ||
300 | rb->sleep(HZ*2); | ||
301 | |||
302 | rb->lcd_clear_display(); | ||
303 | rb->lcd_drawrect(80, 0, 32, 64); | ||
304 | rb->lcd_putsxy(81, 10, "Moves"); | ||
305 | for (i=0; i<20; i++) { | ||
306 | spots[i]=(i+1); | ||
307 | draw_spot(spots[i], (i%5)*16, (i/5)*16); | ||
308 | } | ||
309 | hole = 19; | ||
310 | pic = true; | ||
311 | rb->lcd_update(); | ||
312 | rb->sleep(HZ*2); | ||
313 | |||
314 | return puzzle_loop(); | ||
315 | } | ||
316 | |||
317 | #endif | ||