Fix a dircache NULL-pointer dereference.
[kugel-rb.git] / apps / plugins / nim.c
blob460e2751e94bc20afe3eb3c08b040b3249b68ee8
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2003 Pierre Delore
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "plugin.h"
23 #ifdef HAVE_LCD_CHARCELLS
25 /* NIM game for the player
27 Rules of nim game
28 -----------------
29 There are 21 matches.
30 Two players (you and the cpu) alternately pick a certain number of matches and the one,
31 who takes the last match, loses.
34 History:
35 -------
36 V1.0 : 2003-07-22
37 First release of the game
38 V1.1 : 2003-07-22
39 I Change the patterns definition in order to have a clean code
40 V1.2 : 2003-07-30
41 Patch from JB that change:
42 . the win and lose message
43 . the BUTTON_STOP code
44 . Add a test
45 I suppress the exit variable
46 I suppress or translates the comments which were in French
47 I put min=1 at the of the main loop ( When there are 21 matches you can decide not to
48 take a match. Later you are obliged to take at least one.)
51 PLUGIN_HEADER
53 /*Pattern for the game*/
54 static unsigned char smile[]={0x00, 0x11, 0x04, 0x04, 0x00, 0x11, 0x0E}; /* :-) */
55 static unsigned char cry[] ={0x00, 0x11, 0x04, 0x04, 0x00, 0x0E, 0x11}; /* :-( */
56 static unsigned char pattern3[]={0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15}; /*3 parts*/
57 static unsigned char pattern2[]={0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}; /*2 parts*/
58 static unsigned char pattern1[]={0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}; /*1 part*/
60 static unsigned char str[12]; /*String use to display the first line*/
61 static unsigned long hsmile,hcry,h1,h2; /*Handle for the new pattern*/
63 static bool end; /*If true game is finished*/
65 /*Display that the action it's impossible*/
66 static void impossible(void)
68 rb->lcd_puts(0,1,"Impossible!");
69 rb->lcd_update();
70 rb->sleep(HZ);
71 return;
74 /*Display that the CPU lose :) */
75 static void lose(void)
77 rb->lcd_define_pattern(hsmile,smile);
78 rb->lcd_puts(0,1,"You Win!!");
79 rb->lcd_putc(8,1,hsmile);
80 rb->lcd_update();
81 end=true;
82 rb->sleep(HZ*2);
83 return;
87 /* Display that the CPU win :( */
88 static void win(void)
90 rb->lcd_define_pattern(hcry,cry);
91 rb->lcd_puts(0,1,"You Lose!!");
92 rb->lcd_putc(9,1,hcry);
93 rb->lcd_update();
94 end=true;
95 rb->sleep(HZ*2);
96 return;
100 /*Display the first line*/
101 static void display_first_line(int x)
103 int i;
105 rb->snprintf(str,sizeof(str)," =%d",x);
106 rb->lcd_puts(0,0,str);
108 rb->lcd_define_pattern(h1,pattern3);
109 for (i=0;i<x/3;i++)
110 rb->lcd_putc(i,0,h1);
112 if (x%3==2)
114 rb->lcd_define_pattern(h2,pattern2);
115 rb->lcd_putc(i,0,h2);
117 if (x%3==1)
119 rb->lcd_define_pattern(h2,pattern1);
120 rb->lcd_putc(i,0,h2);
124 /* Call when the program end */
125 static void nim_exit(void *parameter)
127 (void)parameter;
129 /*Restore the old pattern*/
130 rb->lcd_unlock_pattern(h1);
131 rb->lcd_unlock_pattern(h2);
132 rb->lcd_unlock_pattern(hsmile);
133 rb->lcd_unlock_pattern(hcry);
135 /*Clear the screen*/
136 rb->lcd_clear_display();
137 rb->lcd_update();
140 /* this is the plugin entry point */
141 enum plugin_status plugin_start(const void* parameter)
143 int y,z,button;
144 int x,v,min;
145 bool ok;
146 bool go;
148 /* if you don't use the parameter, you can do like
149 this to avoid the compiler warning about it */
150 (void)parameter;
152 /*Get the pattern handle*/
153 h1=rb->lcd_get_locked_pattern();
154 h2=rb->lcd_get_locked_pattern();
155 hcry=rb->lcd_get_locked_pattern();
156 hsmile=rb->lcd_get_locked_pattern();
159 rb->splash(HZ, "NIM V1.2");
160 rb->lcd_clear_display();
162 /* Main loop */
163 while (1)
165 /* Init */
166 x=21;
167 v=1;
168 y=1;
169 end=false;
170 min=0;
172 /*Empty the event queue*/
173 rb->button_clear_queue();
175 /* Game loop */
176 while(end!=true)
180 ok=1;
181 y=1;
182 display_first_line(x);
184 rb->snprintf(str,sizeof(str),"[%d..%d]?=%d",min,v,y);
185 rb->lcd_puts(0,1,str);
186 rb->lcd_update();
188 go=false;
189 while (!go)
191 button = rb->button_get(true);
192 switch ( button )
194 case BUTTON_STOP|BUTTON_REL:
195 go = true;
196 nim_exit(NULL);
197 return PLUGIN_OK;
198 break;
200 case BUTTON_PLAY|BUTTON_REL:
201 go=true;
202 break;
204 case BUTTON_LEFT|BUTTON_REL:
205 go=false;
206 if (y>min)
207 y--;
208 break;
210 case BUTTON_RIGHT|BUTTON_REL:
211 go=false;
212 if (y<v)
213 y++;
214 break;
216 default:
217 if (rb->default_event_handler_ex(button, nim_exit,
218 NULL) == SYS_USB_CONNECTED)
219 return PLUGIN_USB_CONNECTED;
220 break;
222 display_first_line(x);
223 rb->snprintf(str,sizeof(str),"[%d..%d]?=%d",min,v,y);
224 rb->lcd_puts(0,1,str);
225 rb->lcd_update();
228 if ( (y==0) && (x<21))
230 impossible();
231 ok=false;
233 else
235 if (y!=0) /*If y=0 and x=21 jump to CPU code */
237 if ((y>v) || (y>x))
239 impossible();
240 ok=false;
242 if (y-x==0)
243 win();
244 else
246 v=y*2;
247 x-=y;
252 while (ok==false);
254 display_first_line(x);
256 /*CPU*/
257 if (x==1)
258 lose();
259 else
260 if (x==2)
261 win();
262 y=0;
263 if (end==false)
265 for (z=v;z>=1;z--)
267 if (x-z==1)
268 y=z;
270 if (y<=0)
272 for(z=v;z>=1;z--)
274 if(x-(z*3)==2)
275 y=z;
277 if ((y==0) && (x>14))
278 y=v;
279 if (y==0)
280 y=1;
282 v=y*2;
283 x-=y;
284 rb->snprintf(str,sizeof(str),"I take=%d",y);
285 rb->lcd_puts(0,1,str);
286 rb->lcd_update();
287 rb->sleep(HZ);
289 if ((x==1)&&(!end))
290 win();
291 min=1;
294 nim_exit(NULL);
295 return PLUGIN_OK;
297 #endif