Extract config file saving code to a function; Do not write the NUL character to...
[kugel-rb.git] / apps / plugins / nim.c
blob70cf8dcec417871395c56801592d9c7842397c04
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"
22 #include "lib/pluginlib_exit.h"
24 /* NIM game for the player
26 Rules of nim game
27 -----------------
28 There are 21 matches.
29 Two players (you and the cpu) alternately pick a certain number of matches and the one,
30 who takes the last match, loses.
33 History:
34 -------
35 V1.0 : 2003-07-22
36 First release of the game
37 V1.1 : 2003-07-22
38 I Change the patterns definition in order to have a clean code
39 V1.2 : 2003-07-30
40 Patch from JB that change:
41 . the win and lose message
42 . the BUTTON_STOP code
43 . Add a test
44 I suppress the exit variable
45 I suppress or translates the comments which were in French
46 I put min=1 at the of the main loop ( When there are 21 matches you can decide not to
47 take a match. Later you are obliged to take at least one.)
52 /*Pattern for the game*/
53 static unsigned char smile[]={0x00, 0x11, 0x04, 0x04, 0x00, 0x11, 0x0E}; /* :-) */
54 static unsigned char cry[] ={0x00, 0x11, 0x04, 0x04, 0x00, 0x0E, 0x11}; /* :-( */
55 static unsigned char pattern3[]={0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15}; /*3 parts*/
56 static unsigned char pattern2[]={0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}; /*2 parts*/
57 static unsigned char pattern1[]={0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}; /*1 part*/
59 static unsigned long hsmile,hcry,h1,h2; /*Handle for the new pattern*/
61 static bool end; /*If true game is finished*/
63 /*Display that the action it's impossible*/
64 static void impossible(void)
66 rb->lcd_puts(0,1,"Impossible!");
67 rb->lcd_update();
68 rb->sleep(HZ);
69 return;
72 /*Display that the CPU lose :) */
73 static void lose(void)
75 rb->lcd_define_pattern(hsmile,smile);
76 rb->lcd_puts(0,1,"You Win!!");
77 rb->lcd_putc(8,1,hsmile);
78 rb->lcd_update();
79 end=true;
80 rb->sleep(HZ*2);
81 return;
85 /* Display that the CPU win :( */
86 static void win(void)
88 rb->lcd_define_pattern(hcry,cry);
89 rb->lcd_puts(0,1,"You Lose!!");
90 rb->lcd_putc(9,1,hcry);
91 rb->lcd_update();
92 end=true;
93 rb->sleep(HZ*2);
94 return;
98 /*Display the first line*/
99 static void display_first_line(int x)
101 int i;
103 rb->lcd_putsf(0,0," =%d",x);
105 rb->lcd_define_pattern(h1,pattern3);
106 for (i=0;i<x/3;i++)
107 rb->lcd_putc(i,0,h1);
109 if (x%3==2)
111 rb->lcd_define_pattern(h2,pattern2);
112 rb->lcd_putc(i,0,h2);
114 if (x%3==1)
116 rb->lcd_define_pattern(h2,pattern1);
117 rb->lcd_putc(i,0,h2);
121 /* Call when the program end */
122 static void nim_exit(void)
124 /*Restore the old pattern*/
125 rb->lcd_unlock_pattern(h1);
126 rb->lcd_unlock_pattern(h2);
127 rb->lcd_unlock_pattern(hsmile);
128 rb->lcd_unlock_pattern(hcry);
130 /*Clear the screen*/
131 rb->lcd_clear_display();
132 rb->lcd_update();
135 /* this is the plugin entry point */
136 enum plugin_status plugin_start(const void* parameter)
138 int y,z,button;
139 int x,v,min;
140 bool ok;
141 bool go;
142 atexit(nim_exit);
144 /* if you don't use the parameter, you can do like
145 this to avoid the compiler warning about it */
146 (void)parameter;
148 /*Get the pattern handle*/
149 h1=rb->lcd_get_locked_pattern();
150 h2=rb->lcd_get_locked_pattern();
151 hcry=rb->lcd_get_locked_pattern();
152 hsmile=rb->lcd_get_locked_pattern();
155 rb->splash(HZ, "NIM V1.2");
156 rb->lcd_clear_display();
158 /* Main loop */
159 while (1)
161 /* Init */
162 x=21;
163 v=1;
164 y=1;
165 end=false;
166 min=0;
168 /*Empty the event queue*/
169 rb->button_clear_queue();
171 /* Game loop */
172 while(end!=true)
176 ok=1;
177 y=1;
178 display_first_line(x);
180 rb->lcd_putsf(0,1,"[%d..%d]?=%d",min,v,y);
181 rb->lcd_update();
183 go=false;
184 while (!go)
186 button = rb->button_get(true);
187 switch ( button )
189 case BUTTON_STOP|BUTTON_REL:
190 go = true;
191 return PLUGIN_OK;
192 break;
194 case BUTTON_PLAY|BUTTON_REL:
195 go=true;
196 break;
198 case BUTTON_LEFT|BUTTON_REL:
199 go=false;
200 if (y>min)
201 y--;
202 break;
204 case BUTTON_RIGHT|BUTTON_REL:
205 go=false;
206 if (y<v)
207 y++;
208 break;
210 default:
211 exit_on_usb(button);
212 break;
214 display_first_line(x);
215 rb->lcd_putsf(0,1,"[%d..%d]?=%d",min,v,y);
216 rb->lcd_update();
219 if ( (y==0) && (x<21))
221 impossible();
222 ok=false;
224 else
226 if (y!=0) /*If y=0 and x=21 jump to CPU code */
228 if ((y>v) || (y>x))
230 impossible();
231 ok=false;
233 if (y-x==0)
234 win();
235 else
237 v=y*2;
238 x-=y;
243 while (ok==false);
245 display_first_line(x);
247 /*CPU*/
248 if (x==1)
249 lose();
250 else
251 if (x==2)
252 win();
253 y=0;
254 if (end==false)
256 for (z=v;z>=1;z--)
258 if (x-z==1)
259 y=z;
261 if (y<=0)
263 for(z=v;z>=1;z--)
265 if(x-(z*3)==2)
266 y=z;
268 if ((y==0) && (x>14))
269 y=v;
270 if (y==0)
271 y=1;
273 v=y*2;
274 x-=y;
275 rb->lcd_putsf(0,1,"I take=%d",y);
276 rb->lcd_update();
277 rb->sleep(HZ);
279 if ((x==1)&&(!end))
280 win();
281 min=1;
284 return PLUGIN_OK;