Reverting parts of r19760 that was mistakenly committed.
[kugel-rb.git] / apps / plugins / nim.c
blob1500407f4908070f52bb47e8395d71b695d740c3
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 /* FIXME: Why only for charcell? */
24 #ifdef HAVE_LCD_CHARCELLS
26 /* NIM game for the player
28 Rules of nim game
29 -----------------
30 There are 21 matches.
31 Two players (you and the cpu) alternately pick a certain number of matches and the one,
32 who takes the last match, loses.
35 History:
36 -------
37 V1.0 : 2003-07-22
38 First release of the game
39 V1.1 : 2003-07-22
40 I Change the patterns definition in order to have a clean code
41 V1.2 : 2003-07-30
42 Patch from JB that change:
43 . the win and lose message
44 . the BUTTON_STOP code
45 . Add a test
46 I suppress the exit variable
47 I suppress or translates the comments which were in French
48 I put min=1 at the of the main loop ( When there are 21 matches you can decide not to
49 take a match. Later you are obliged to take at least one.)
52 PLUGIN_HEADER
54 /*Pattern for the game*/
55 static unsigned char smile[]={0x00, 0x11, 0x04, 0x04, 0x00, 0x11, 0x0E}; /* :-) */
56 static unsigned char cry[] ={0x00, 0x11, 0x04, 0x04, 0x00, 0x0E, 0x11}; /* :-( */
57 static unsigned char pattern3[]={0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15}; /*3 parts*/
58 static unsigned char pattern2[]={0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}; /*2 parts*/
59 static unsigned char pattern1[]={0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}; /*1 part*/
61 static unsigned char str[12]; /*String use to display the first line*/
62 static unsigned long hsmile,hcry,h1,h2; /*Handle for the new pattern*/
64 static bool end; /*If true game is finished*/
65 static const struct plugin_api* rb;
68 /*Display that the action it's impossible*/
69 static void impossible(void)
71 rb->lcd_puts(0,1,"Impossible!");
72 rb->lcd_update();
73 rb->sleep(HZ);
74 return;
77 /*Display that the CPU lose :) */
78 static void lose(void)
80 rb->lcd_define_pattern(hsmile,smile);
81 rb->lcd_puts(0,1,"You Win!!");
82 rb->lcd_putc(8,1,hsmile);
83 rb->lcd_update();
84 end=true;
85 rb->sleep(HZ*2);
86 return;
90 /* Display that the CPU win :( */
91 static void win(void)
93 rb->lcd_define_pattern(hcry,cry);
94 rb->lcd_puts(0,1,"You Lose!!");
95 rb->lcd_putc(9,1,hcry);
96 rb->lcd_update();
97 end=true;
98 rb->sleep(HZ*2);
99 return;
103 /*Display the first line*/
104 static void display_first_line(int x)
106 int i;
108 rb->snprintf(str,sizeof(str)," =%d",x);
109 rb->lcd_puts(0,0,str);
111 rb->lcd_define_pattern(h1,pattern3);
112 for (i=0;i<x/3;i++)
113 rb->lcd_putc(i,0,h1);
115 if (x%3==2)
117 rb->lcd_define_pattern(h2,pattern2);
118 rb->lcd_putc(i,0,h2);
120 if (x%3==1)
122 rb->lcd_define_pattern(h2,pattern1);
123 rb->lcd_putc(i,0,h2);
127 /* Call when the program end */
128 static void nim_exit(void *parameter)
130 (void)parameter;
132 /*Restore the old pattern*/
133 rb->lcd_unlock_pattern(h1);
134 rb->lcd_unlock_pattern(h2);
135 rb->lcd_unlock_pattern(hsmile);
136 rb->lcd_unlock_pattern(hcry);
138 /*Clear the screen*/
139 rb->lcd_clear_display();
140 rb->lcd_update();
143 /* this is the plugin entry point */
144 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
146 int y,z,button;
147 int x,v,min;
148 bool ok;
149 bool go;
151 /* if you don't use the parameter, you can do like
152 this to avoid the compiler warning about it */
153 (void)parameter;
155 /* if you are using a global api pointer, don't forget to copy it!
156 otherwise you will get lovely "I04: IllInstr" errors... :-) */
157 rb = api;
159 /*Get the pattern handle*/
160 h1=rb->lcd_get_locked_pattern();
161 h2=rb->lcd_get_locked_pattern();
162 hcry=rb->lcd_get_locked_pattern();
163 hsmile=rb->lcd_get_locked_pattern();
166 rb->splash(HZ, "NIM V1.2");
167 rb->lcd_clear_display();
169 /* Main loop */
170 while (1)
172 /* Init */
173 x=21;
174 v=1;
175 y=1;
176 end=false;
177 min=0;
179 /*Empty the event queue*/
180 rb->button_clear_queue();
182 /* Game loop */
183 while(end!=true)
187 ok=1;
188 y=1;
189 display_first_line(x);
191 rb->snprintf(str,sizeof(str),"[%d..%d]?=%d",min,v,y);
192 rb->lcd_puts(0,1,str);
193 rb->lcd_update();
195 go=false;
196 while (!go)
198 button = rb->button_get(true);
199 switch ( button )
201 case BUTTON_STOP|BUTTON_REL:
202 go = true;
203 nim_exit(NULL);
204 return PLUGIN_OK;
205 break;
207 case BUTTON_PLAY|BUTTON_REL:
208 go=true;
209 break;
211 case BUTTON_LEFT|BUTTON_REL:
212 go=false;
213 if (y>min)
214 y--;
215 break;
217 case BUTTON_RIGHT|BUTTON_REL:
218 go=false;
219 if (y<v)
220 y++;
221 break;
223 default:
224 if (rb->default_event_handler_ex(button, nim_exit,
225 NULL) == SYS_USB_CONNECTED)
226 return PLUGIN_USB_CONNECTED;
227 break;
229 display_first_line(x);
230 rb->snprintf(str,sizeof(str),"[%d..%d]?=%d",min,v,y);
231 rb->lcd_puts(0,1,str);
232 rb->lcd_update();
235 if ( (y==0) && (x<21))
237 impossible();
238 ok=false;
240 else
242 if (y!=0) /*If y=0 and x=21 jump to CPU code */
244 if ((y>v) || (y>x))
246 impossible();
247 ok=false;
249 if (y-x==0)
250 win();
251 else
253 v=y*2;
254 x-=y;
259 while (ok==false);
261 display_first_line(x);
263 /*CPU*/
264 if (x==1)
265 lose();
266 else
267 if (x==2)
268 win();
269 y=0;
270 if (end==false)
272 for (z=v;z>=1;z--)
274 if (x-z==1)
275 y=z;
277 if (y<=0)
279 for(z=v;z>=1;z--)
281 if(x-(z*3)==2)
282 y=z;
284 if ((y==0) && (x>14))
285 y=v;
286 if (y==0)
287 y=1;
289 v=y*2;
290 x-=y;
291 rb->snprintf(str,sizeof(str),"I take=%d",y);
292 rb->lcd_puts(0,1,str);
293 rb->lcd_update();
294 rb->sleep(HZ);
296 if ((x==1)&&(!end))
297 win();
298 min=1;
301 nim_exit(NULL);
302 return PLUGIN_OK;
304 #endif