Updated our source code header to explicitly mention that we are GPL v2 or
[Rockbox.git] / apps / plugins / nim.c
blobce61d7a3830530db2442dc18505f87bd7f4e3189
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*/
64 static const struct plugin_api* rb;
67 /*Display that the action it's impossible*/
68 static void impossible(void)
70 rb->lcd_puts(0,1,"Impossible!");
71 rb->lcd_update();
72 rb->sleep(HZ);
73 return;
76 /*Display that the CPU lose :) */
77 static void lose(void)
79 rb->lcd_define_pattern(hsmile,smile);
80 rb->lcd_puts(0,1,"You Win!!");
81 rb->lcd_putc(8,1,hsmile);
82 rb->lcd_update();
83 end=true;
84 rb->sleep(HZ*2);
85 return;
89 /* Display that the CPU win :( */
90 static void win(void)
92 rb->lcd_define_pattern(hcry,cry);
93 rb->lcd_puts(0,1,"You Lose!!");
94 rb->lcd_putc(9,1,hcry);
95 rb->lcd_update();
96 end=true;
97 rb->sleep(HZ*2);
98 return;
102 /*Display the first line*/
103 static void display_first_line(int x)
105 int i;
107 rb->snprintf(str,sizeof(str)," =%d",x);
108 rb->lcd_puts(0,0,str);
110 rb->lcd_define_pattern(h1,pattern3);
111 for (i=0;i<x/3;i++)
112 rb->lcd_putc(i,0,h1);
114 if (x%3==2)
116 rb->lcd_define_pattern(h2,pattern2);
117 rb->lcd_putc(i,0,h2);
119 if (x%3==1)
121 rb->lcd_define_pattern(h2,pattern1);
122 rb->lcd_putc(i,0,h2);
126 /* Call when the program end */
127 static void nim_exit(void *parameter)
129 (void)parameter;
131 /*Restore the old pattern*/
132 rb->lcd_unlock_pattern(h1);
133 rb->lcd_unlock_pattern(h2);
134 rb->lcd_unlock_pattern(hsmile);
135 rb->lcd_unlock_pattern(hcry);
137 /*Clear the screen*/
138 rb->lcd_clear_display();
139 rb->lcd_update();
142 /* this is the plugin entry point */
143 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
145 int y,z,button;
146 int x,v,min;
147 bool ok;
148 bool go;
150 /* if you don't use the parameter, you can do like
151 this to avoid the compiler warning about it */
152 (void)parameter;
154 /* if you are using a global api pointer, don't forget to copy it!
155 otherwise you will get lovely "I04: IllInstr" errors... :-) */
156 rb = api;
158 /*Get the pattern handle*/
159 h1=rb->lcd_get_locked_pattern();
160 h2=rb->lcd_get_locked_pattern();
161 hcry=rb->lcd_get_locked_pattern();
162 hsmile=rb->lcd_get_locked_pattern();
165 rb->splash(HZ, "NIM V1.2");
166 rb->lcd_clear_display();
168 /* Main loop */
169 while (1)
171 /* Init */
172 x=21;
173 v=1;
174 y=1;
175 end=false;
176 min=0;
178 /*Empty the event queue*/
179 rb->button_clear_queue();
181 /* Game loop */
182 while(end!=true)
186 ok=1;
187 y=1;
188 display_first_line(x);
190 rb->snprintf(str,sizeof(str),"[%d..%d]?=%d",min,v,y);
191 rb->lcd_puts(0,1,str);
192 rb->lcd_update();
194 go=false;
195 while (!go)
197 button = rb->button_get(true);
198 switch ( button )
200 case BUTTON_STOP|BUTTON_REL:
201 go = true;
202 nim_exit(NULL);
203 return PLUGIN_OK;
204 break;
206 case BUTTON_PLAY|BUTTON_REL:
207 go=true;
208 break;
210 case BUTTON_LEFT|BUTTON_REL:
211 go=false;
212 if (y>min)
213 y--;
214 break;
216 case BUTTON_RIGHT|BUTTON_REL:
217 go=false;
218 if (y<v)
219 y++;
220 break;
222 default:
223 if (rb->default_event_handler_ex(button, nim_exit,
224 NULL) == SYS_USB_CONNECTED)
225 return PLUGIN_USB_CONNECTED;
226 break;
228 display_first_line(x);
229 rb->snprintf(str,sizeof(str),"[%d..%d]?=%d",min,v,y);
230 rb->lcd_puts(0,1,str);
231 rb->lcd_update();
234 if ( (y==0) && (x<21))
236 impossible();
237 ok=false;
239 else
241 if (y!=0) /*If y=0 and x=21 jump to CPU code */
243 if ((y>v) || (y>x))
245 impossible();
246 ok=false;
248 if (y-x==0)
249 win();
250 else
252 v=y*2;
253 x-=y;
258 while (ok==false);
260 display_first_line(x);
262 /*CPU*/
263 if (x==1)
264 lose();
265 else
266 if (x==2)
267 win();
268 y=0;
269 if (end==false)
271 for (z=v;z>=1;z--)
273 if (x-z==1)
274 y=z;
276 if (y<=0)
278 for(z=v;z>=1;z--)
280 if(x-(z*3)==2)
281 y=z;
283 if ((y==0) && (x>14))
284 y=v;
285 if (y==0)
286 y=1;
288 v=y*2;
289 x-=y;
290 rb->snprintf(str,sizeof(str),"I take=%d",y);
291 rb->lcd_puts(0,1,str);
292 rb->lcd_update();
293 rb->sleep(HZ);
295 if ((x==1)&&(!end))
296 win();
297 min=1;
300 nim_exit(NULL);
301 return PLUGIN_OK;
303 #endif