Introduce __attribute__((unused)) (#defined to UNUSED_ATTR) to mark possibly unused...
[kugel-rb.git] / apps / plugins / nim.c
blobaf248167a0bee34ad7c81277228f16b87ae65cf1
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 cleanup(UNUSED_ATTR void *parameter)
127 /*Restore the old pattern*/
128 rb->lcd_unlock_pattern(h1);
129 rb->lcd_unlock_pattern(h2);
130 rb->lcd_unlock_pattern(hsmile);
131 rb->lcd_unlock_pattern(hcry);
133 /*Clear the screen*/
134 rb->lcd_clear_display();
135 rb->lcd_update();
138 /* this is the plugin entry point */
139 enum plugin_status plugin_start(UNUSED_ATTR const void* parameter)
141 int y,z,button;
142 int x,v,min;
143 bool ok;
144 bool go;
146 /* if you don't use the parameter, you can do like
147 this to avoid the compiler warning about it */
149 /*Get the pattern handle*/
150 h1=rb->lcd_get_locked_pattern();
151 h2=rb->lcd_get_locked_pattern();
152 hcry=rb->lcd_get_locked_pattern();
153 hsmile=rb->lcd_get_locked_pattern();
156 rb->splash(HZ, "NIM V1.2");
157 rb->lcd_clear_display();
159 /* Main loop */
160 while (1)
162 /* Init */
163 x=21;
164 v=1;
165 y=1;
166 end=false;
167 min=0;
169 /*Empty the event queue*/
170 rb->button_clear_queue();
172 /* Game loop */
173 while(end!=true)
177 ok=1;
178 y=1;
179 display_first_line(x);
181 rb->snprintf(str,sizeof(str),"[%d..%d]?=%d",min,v,y);
182 rb->lcd_puts(0,1,str);
183 rb->lcd_update();
185 go=false;
186 while (!go)
188 button = rb->button_get(true);
189 switch ( button )
191 case BUTTON_STOP|BUTTON_REL:
192 go = true;
193 nim_exit(NULL);
194 return PLUGIN_OK;
195 break;
197 case BUTTON_PLAY|BUTTON_REL:
198 go=true;
199 break;
201 case BUTTON_LEFT|BUTTON_REL:
202 go=false;
203 if (y>min)
204 y--;
205 break;
207 case BUTTON_RIGHT|BUTTON_REL:
208 go=false;
209 if (y<v)
210 y++;
211 break;
213 default:
214 if (rb->default_event_handler_ex(button, nim_exit,
215 NULL) == SYS_USB_CONNECTED)
216 return PLUGIN_USB_CONNECTED;
217 break;
219 display_first_line(x);
220 rb->snprintf(str,sizeof(str),"[%d..%d]?=%d",min,v,y);
221 rb->lcd_puts(0,1,str);
222 rb->lcd_update();
225 if ( (y==0) && (x<21))
227 impossible();
228 ok=false;
230 else
232 if (y!=0) /*If y=0 and x=21 jump to CPU code */
234 if ((y>v) || (y>x))
236 impossible();
237 ok=false;
239 if (y-x==0)
240 win();
241 else
243 v=y*2;
244 x-=y;
249 while (ok==false);
251 display_first_line(x);
253 /*CPU*/
254 if (x==1)
255 lose();
256 else
257 if (x==2)
258 win();
259 y=0;
260 if (end==false)
262 for (z=v;z>=1;z--)
264 if (x-z==1)
265 y=z;
267 if (y<=0)
269 for(z=v;z>=1;z--)
271 if(x-(z*3)==2)
272 y=z;
274 if ((y==0) && (x>14))
275 y=v;
276 if (y==0)
277 y=1;
279 v=y*2;
280 x-=y;
281 rb->snprintf(str,sizeof(str),"I take=%d",y);
282 rb->lcd_puts(0,1,str);
283 rb->lcd_update();
284 rb->sleep(HZ);
286 if ((x==1)&&(!end))
287 win();
288 min=1;
291 cleanup(NULL);
292 return PLUGIN_OK;
294 #endif