Update the Swedish translation.
[kugel-rb.git] / apps / plugins / snake.c
blob6acbb808aa665107b7f104e3959fc2d09d6333d1
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Itai Shaked
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
21 Snake!
23 by Itai Shaked
25 ok, a little explanation -
26 board holds the snake and apple position - 1+ - snake body (the number
27 represents the age [1 is the snake's head]).
28 -1 is an apple, and 0 is a clear spot.
29 dir is the current direction of the snake - 0=up, 1=right, 2=down, 3=left;
33 #include "plugin.h"
34 #ifdef HAVE_LCD_BITMAP
36 PLUGIN_HEADER
38 /* variable button definitions */
39 #if CONFIG_KEYPAD == RECORDER_PAD
40 #define SNAKE_QUIT BUTTON_OFF
41 #define SNAKE_UP BUTTON_UP
42 #define SNAKE_DOWN BUTTON_DOWN
43 #define SNAKE_PLAYPAUSE BUTTON_PLAY
45 #elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
46 #define SNAKE_QUIT BUTTON_OFF
47 #define SNAKE_UP BUTTON_UP
48 #define SNAKE_DOWN BUTTON_DOWN
49 #define SNAKE_PLAYPAUSE BUTTON_SELECT
51 #elif CONFIG_KEYPAD == ONDIO_PAD
52 #define SNAKE_QUIT BUTTON_OFF
53 #define SNAKE_UP BUTTON_UP
54 #define SNAKE_DOWN BUTTON_DOWN
55 #define SNAKE_PLAYPAUSE BUTTON_MENU
57 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
58 (CONFIG_KEYPAD == IRIVER_H300_PAD)
59 #define SNAKE_QUIT BUTTON_OFF
60 #define SNAKE_UP BUTTON_UP
61 #define SNAKE_DOWN BUTTON_DOWN
62 #define SNAKE_PLAYPAUSE BUTTON_ON
64 #define SNAKE_RC_QUIT BUTTON_RC_STOP
66 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \
67 (CONFIG_KEYPAD == IPOD_3G_PAD)
68 #define SNAKE_QUIT (BUTTON_SELECT|BUTTON_MENU)
69 #define SNAKE_UP BUTTON_MENU
70 #define SNAKE_DOWN BUTTON_PLAY
71 #define SNAKE_PLAYPAUSE BUTTON_SELECT
73 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
74 #define SNAKE_QUIT BUTTON_POWER
75 #define SNAKE_UP BUTTON_UP
76 #define SNAKE_DOWN BUTTON_DOWN
77 #define SNAKE_PLAYPAUSE BUTTON_PLAY
79 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
80 #define SNAKE_QUIT BUTTON_POWER
81 #define SNAKE_UP BUTTON_UP
82 #define SNAKE_DOWN BUTTON_DOWN
83 #define SNAKE_PLAYPAUSE BUTTON_SELECT
85 #elif (CONFIG_KEYPAD == SANSA_E200_PAD)
86 #define SNAKE_QUIT BUTTON_POWER
87 #define SNAKE_UP BUTTON_UP
88 #define SNAKE_DOWN BUTTON_DOWN
89 #define SNAKE_PLAYPAUSE BUTTON_SELECT
91 #elif (CONFIG_KEYPAD == IRIVER_H10_PAD)
92 #define SNAKE_QUIT BUTTON_POWER
93 #define SNAKE_UP BUTTON_SCROLL_UP
94 #define SNAKE_DOWN BUTTON_SCROLL_DOWN
95 #define SNAKE_PLAYPAUSE BUTTON_PLAY
97 #else
98 #error "lacks keymapping"
99 #endif
101 #define BOARD_WIDTH (LCD_WIDTH/4)
102 #define BOARD_HEIGHT (LCD_HEIGHT/4)
104 static int board[BOARD_WIDTH][BOARD_HEIGHT],snakelength;
105 static unsigned int score,hiscore=0,level=1;
106 static short dir,frames,apple,dead=0;
107 static struct plugin_api* rb;
109 void die (void)
111 char pscore[17];
112 rb->lcd_clear_display();
113 rb->snprintf(pscore,sizeof(pscore),"Your score: %d",score);
114 rb->lcd_puts(0,0,"Oops...");
115 rb->lcd_puts(0,1, pscore);
116 if (score>hiscore) {
117 hiscore=score;
118 rb->lcd_puts(0,2,"New High Score!");
120 else {
121 rb->snprintf(pscore,sizeof(pscore),"High Score: %d",hiscore);
122 rb->lcd_puts(0,2,pscore);
124 rb->lcd_update();
125 rb->sleep(3*HZ);
126 dead=1;
129 void colission (short x, short y)
131 switch (board[x][y]) {
132 case 0:
133 break;
134 case -1:
135 snakelength+=2;
136 score+=level;
137 apple=0;
138 break;
139 default:
140 die();
141 break;
143 if (x==BOARD_WIDTH || x<0 || y==BOARD_HEIGHT || y<0)
144 die();
147 void move_head (short x, short y)
149 switch (dir) {
150 case 0:
151 y-=1;
152 break;
153 case 1:
154 x+=1;
155 break;
156 case 2:
157 y+=1;
158 break;
159 case 3:
160 x-=1;
161 break;
163 colission (x,y);
164 if (dead)
165 return;
166 board[x][y]=1;
167 rb->lcd_fillrect(x*4,y*4,4,4);
170 void frame (void)
172 short x,y,head=0;
173 for (x=0; x<BOARD_WIDTH; x++) {
174 for (y=0; y<BOARD_HEIGHT; y++) {
175 switch (board[x][y]) {
176 case 1:
177 if (!head) {
178 move_head(x,y);
179 if (dead)
180 return;
181 board[x][y]++;
182 head=1;
184 break;
185 case 0:
186 break;
187 case -1:
188 break;
189 default:
190 if (board[x][y]==snakelength) {
191 board[x][y]=0;
192 rb->lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
193 rb->lcd_fillrect(x*4,y*4,4,4);
194 rb->lcd_set_drawmode(DRMODE_SOLID);
196 else
197 board[x][y]++;
198 break;
202 rb->lcd_update();
205 void redraw (void)
207 short x,y;
208 rb->lcd_clear_display();
209 for (x=0; x<BOARD_WIDTH; x++) {
210 for (y=0; y<BOARD_HEIGHT; y++) {
211 switch (board[x][y]) {
212 case -1:
213 rb->lcd_fillrect((x*4)+1,y*4,2,4);
214 rb->lcd_fillrect(x*4,(y*4)+1,4,2);
215 break;
216 case 0:
217 break;
218 default:
219 rb->lcd_fillrect(x*4,y*4,4,4);
220 break;
224 rb->lcd_update();
227 void game_pause (void) {
228 int button;
229 rb->lcd_clear_display();
230 rb->lcd_putsxy(3,12,"Game Paused");
231 #if CONFIG_KEYPAD == RECORDER_PAD
232 rb->lcd_putsxy(3,22,"[Play] to resume");
233 #elif CONFIG_KEYPAD == ONDIO_PAD
234 rb->lcd_putsxy(3,22,"[Mode] to resume");
235 #endif
236 rb->lcd_putsxy(3,32,"[Off] to quit");
237 rb->lcd_update();
238 while (1) {
239 button=rb->button_get(true);
240 switch (button) {
241 #ifdef SNAKE_RC_QUIT
242 case SNAKE_RC_QUIT:
243 #endif
244 case SNAKE_QUIT:
245 dead=1;
246 return;
247 case SNAKE_PLAYPAUSE:
248 redraw();
249 rb->sleep(HZ/2);
250 return;
251 default:
252 if (rb->default_event_handler(button)==SYS_USB_CONNECTED) {
253 dead=2;
254 return;
256 break;
262 void game (void) {
263 int button;
264 short x,y;
265 while (1) {
266 frame();
267 if (dead)
268 return;
269 frames++;
270 if (frames==10) {
271 frames=0;
272 if (!apple) {
273 do {
274 x=rb->rand() % BOARD_WIDTH;
275 y=rb->rand() % BOARD_HEIGHT;
276 } while (board[x][y]);
277 apple=1;
278 board[x][y]=-1;
279 rb->lcd_fillrect((x*4)+1,y*4,2,4);
280 rb->lcd_fillrect(x*4,(y*4)+1,4,2);
284 rb->sleep(HZ/level);
286 button=rb->button_get(false);
288 #ifdef HAS_BUTTON_HOLD
289 if (rb->button_hold())
290 button = SNAKE_PLAYPAUSE;
291 #endif
293 switch (button) {
294 case SNAKE_UP:
295 if (dir!=2) dir=0;
296 break;
297 case BUTTON_RIGHT:
298 if (dir!=3) dir=1;
299 break;
300 case SNAKE_DOWN:
301 if (dir!=0) dir=2;
302 break;
303 case BUTTON_LEFT:
304 if (dir!=1) dir=3;
305 break;
306 #ifdef SNAKE_RC_QUIT
307 case SNAKE_RC_QUIT:
308 #endif
309 case SNAKE_QUIT:
310 dead=1;
311 return;
312 case SNAKE_PLAYPAUSE:
313 game_pause();
314 break;
315 default:
316 if (rb->default_event_handler(button)==SYS_USB_CONNECTED) {
317 dead=2;
318 return;
320 break;
325 void game_init(void) {
326 int selection=0;
327 short x,y;
328 bool menu_quit = false;
330 for (x=0; x<BOARD_WIDTH; x++) {
331 for (y=0; y<BOARD_HEIGHT; y++) {
332 board[x][y]=0;
335 dead=0;
336 apple=0;
337 snakelength=4;
338 score=0;
339 board[11][7]=1;
341 MENUITEM_STRINGLIST(menu,"Snake Menu",NULL,"Start New Game","Starting Level",
342 "Quit");
344 while (!menu_quit) {
345 switch(rb->do_menu(&menu, &selection))
347 case 0:
348 menu_quit = true; /* start playing */
349 break;
351 case 1:
352 rb->set_int("Starting Level", "", UNIT_INT, &level, NULL,
353 1, 1, 9, NULL );
354 break;
356 default:
357 dead=1; /* quit program */
358 menu_quit = true;
359 break;
365 enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
367 (void)(parameter);
368 rb = api;
370 game_init();
371 rb->lcd_clear_display();
372 game();
373 return (dead==1)?PLUGIN_OK:PLUGIN_USB_CONNECTED;
376 #endif