Remove a viewport ambiguity by changing the screens width/heigth members into lcdwidt...
[kugel-rb.git] / apps / plugins / jackpot.c
blob38cd12e9932fd4a825e9bdac90a972f11b052feb
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Copyright Kévin Ferrare based on work by 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 ****************************************************************************/
22 #include "plugin.h"
23 #include "pluginlib_actions.h"
24 #include "picture.h"
26 PLUGIN_HEADER
28 const struct button_mapping* plugin_contexts[]={generic_actions};
29 #define NB_PICTURES 9
30 #define NB_SLOTS 3
32 #ifdef HAVE_LCD_CHARCELLS
33 #define PICTURE_ROTATION_STEPS 7
34 static unsigned char jackpot_slots_patterns[]={
35 0x00, 0x0A, 0x1F, 0x1F, 0x1F, 0x0e, 0x04, /* (+00)Heart */
36 0x00, 0x04, 0x0E, 0x1F, 0x1F, 0x04, 0x0E, /* (+07)Spade */
37 0x00, 0x04, 0x0E, 0x1F, 0x0E, 0x04, 0x00, /* (+14)Diamond */
38 0x00, 0x15, 0x0E, 0x1F, 0x0E, 0x15, 0x00, /* (+21)Club */
39 0x03, 0x04, 0x0e, 0x1F, 0x1F, 0x1F, 0x0e, /* (+28)Cherry */
40 0x00, 0x04, 0x04, 0x1F, 0x04, 0x0E, 0x1F, /* (+35)Cross */
41 0x04, 0x0E, 0x15, 0x04, 0x0A, 0x0A, 0x11, /* (+42)Man */
42 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, /* (+49)Square */
43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* (+56)Empty */
44 0x00, 0x0A, 0x1F, 0x1F, 0x1F, 0x0e, 0x04 /* (+63)Heart */
46 static unsigned long char_patterns[NB_SLOTS];
47 #define SLEEP_TIME (HZ/24)
48 #else /* bitmaps LCDs */
50 #define PICTURE_HEIGHT (BMPHEIGHT_jackpot_slots/(NB_PICTURES+1))
51 #if NB_SCREENS==1
52 #define PICTURE_ROTATION_STEPS PICTURE_HEIGHT
53 #else
54 #define REMOTE_PICTURE_HEIGHT (BMPHEIGHT_jackpot_slots_remote/(NB_PICTURES+1))
55 #define PICTURE_ROTATION_STEPS REMOTE_PICTURE_HEIGHT
56 #endif
58 /* FIXME: would be nice to have better graphics ... */
59 #include "jackpot_slots.h"
60 #if NB_SCREENS==2
61 #include "jackpot_slots_remote.h"
62 #endif
64 const struct picture jackpot_pictures[]={
65 {jackpot_slots, BMPWIDTH_jackpot_slots,PICTURE_HEIGHT},
66 #if NB_SCREENS==2
67 {jackpot_slots_remote,BMPWIDTH_jackpot_slots_remote,REMOTE_PICTURE_HEIGHT}
68 #endif
71 #define SLEEP_TIME (HZ/200)
72 #endif /* HAVE_LCD_CHARCELLS */
74 static const struct plugin_api* rb;
76 struct jackpot
78 /* A slot can display "NB_PICTURES" pictures
79 A picture is moving up, it can take PICTURE_ROTATION_STEPS
80 to move a single picture completely.
81 So values in slot_state are comprised between
82 0 and NB_PICTURES*PICTURE_ROTATION_STEPS
84 int slot_state[NB_SLOTS];
86 The real state of the picture in pixels on each screen
87 Different from slot_state because of the synchronised
88 rotation between different sized bitmaps on remote and main screen
90 int state_y[NB_SCREENS][NB_SLOTS];
91 int money;
94 #ifdef HAVE_LCD_CHARCELLS
95 void patterns_init(struct screen* display)
97 int i;
98 for(i=0;i<NB_SLOTS;i++)
99 char_patterns[i]=display->get_locked_pattern();
102 void patterns_deinit(struct screen* display)
104 /* Restore the old pattern */
105 int i;
106 for(i=0;i<NB_SLOTS;i++)
107 display->unlock_pattern(char_patterns[i]);
109 #endif /* HAVE_LCD_CHARCELLS */
111 /*Call when the program exit*/
112 void jackpot_exit(void *parameter)
114 (void)parameter;
115 #ifdef HAVE_LCD_CHARCELLS
116 patterns_deinit(rb->screens[SCREEN_MAIN]);
117 #endif /* HAVE_LCD_CHARCELLS */
120 void jackpot_init(struct jackpot* game)
122 int i,j;
123 game->money=20;
124 for(i=0;i<NB_SLOTS;i++){
125 game->slot_state[i]=(rb->rand()%NB_PICTURES)*PICTURE_ROTATION_STEPS;
126 FOR_NB_SCREENS(j)
127 game->state_y[j][i]=-1;
131 int jackpot_get_result(struct jackpot* game)
133 int i=NB_SLOTS-1;
134 int multiple=1;
135 int result=0;
136 for(;i>=0;i--)
138 result+=game->slot_state[i]*multiple/PICTURE_ROTATION_STEPS;
139 multiple*=10;
141 return(result);
144 int jackpot_get_gain(struct jackpot* game)
146 switch (jackpot_get_result(game))
148 case 111 : return(20);
149 case 000 : return(15);
150 case 333 : return(10);
151 case 222 : return(8);
152 case 555 : return(5);
153 case 777 : return(4);
154 case 251 : return(4);
155 case 510 : return(4);
156 case 686 : return(3);
157 case 585 : return(3);
158 case 282 : return(3);
159 case 484 : return(3);
160 case 787 : return(2);
161 case 383 : return(2);
162 case 80 : return(2);
164 return(0);
167 void jackpot_display_slot_machine(struct jackpot* game, struct screen* display)
169 char str[20];
170 int i;
171 bool changes=false;
172 #ifdef HAVE_LCD_CHARCELLS
173 display->putc(0, 0, '[');
174 #else
175 const struct picture* picture= &(jackpot_pictures[display->screen_type]);
176 int pos_x=(display->getwidth()-NB_SLOTS*(picture->width+1))/2;
177 int pos_y=(display->getheight()-(picture->height))/2;
178 #endif /* HAVE_LCD_CHARCELLS */
179 for(i=0;i<NB_SLOTS;i++)
181 #ifdef HAVE_LCD_CHARCELLS
182 /* the only charcell lcd is 7 pixel high */
183 int state_y=(game->slot_state[i]*7)/PICTURE_ROTATION_STEPS;
184 #else
185 int state_y=
186 (picture->height*game->slot_state[i])/PICTURE_ROTATION_STEPS;
187 #endif /* HAVE_LCD_CHARCELLS */
188 int previous_state_y=game->state_y[display->screen_type][i];
189 if(state_y==previous_state_y)
190 continue;/*no need to update the picture
191 as it's the same as previous displayed one*/
192 changes=true;
193 game->state_y[display->screen_type][i]=state_y;
194 #ifdef HAVE_LCD_CHARCELLS
195 char* current_pattern=&(jackpot_slots_patterns[state_y]);
196 display->define_pattern(char_patterns[i],
197 current_pattern);
198 display->putc(i+1, 0, char_patterns[i]);
199 #else
200 vertical_picture_draw_part(display, picture, state_y, pos_x, pos_y);
201 pos_x+=(picture->width+1);
202 #endif
204 if(changes){
205 #ifdef HAVE_LCD_CHARCELLS
206 rb->snprintf(str,sizeof(str),"$%d", game->money);
207 display->putc(++i, 0, ']');
208 display->puts(++i, 0, str);
209 #else
210 rb->snprintf(str,sizeof(str),"money : $%d", game->money);
211 display->puts(0, 0, str);
212 #endif
213 display->update();
218 void jackpot_info_message(struct screen* display, char* message)
220 #ifdef HAVE_LCD_CHARCELLS
221 display->puts_scroll(0,1,message);
222 #else
223 int xpos, ypos;
224 int message_height, message_width;
225 display->getstringsize(message, &message_width, &message_height);
226 xpos=(display->getwidth()-message_width)/2;
227 ypos=display->getheight()-message_height;
228 rb->screen_clear_area(display, 0, ypos, display->getwidth(),
229 message_height);
230 display->putsxy(xpos,ypos,message);
231 display->update();
232 #endif /* HAVE_LCD_CHARCELLS */
235 void jackpot_print_turn_result(struct jackpot* game,
236 int gain, struct screen* display)
238 char str[20];
239 if (gain==0)
241 jackpot_info_message(display, "None ...");
242 if (game->money<=0)
243 jackpot_info_message(display, "You lose...STOP to quit");
245 else
247 rb->snprintf(str,sizeof(str),"You win %d$",gain);
248 jackpot_info_message(display, str);
250 display->update();
253 void jackpot_play_turn(struct jackpot* game)
255 /* How many pattern? */
256 int nb_turns[NB_SLOTS];
257 int i,d,gain,turns_remaining=0;
258 if(game->money<=0)
259 return;
260 game->money--;
261 for(i=0;i<NB_SLOTS;i++)
263 nb_turns[i]=(rb->rand()%15+5)*PICTURE_ROTATION_STEPS;
264 turns_remaining+=nb_turns[i];
266 FOR_NB_SCREENS(d)
268 rb->screens[d]->clear_display();
269 jackpot_info_message(rb->screens[d],"Good luck");
271 /* Jackpot Animation */
272 while(turns_remaining>0)
274 for(i=0;i<NB_SLOTS;i++)
276 if(nb_turns[i]>0)
278 nb_turns[i]--;
279 game->slot_state[i]++;
280 if(game->slot_state[i]>=PICTURE_ROTATION_STEPS*NB_PICTURES)
281 game->slot_state[i]=0;
282 turns_remaining--;
285 FOR_NB_SCREENS(d)
286 jackpot_display_slot_machine(game, rb->screens[d]);
287 rb->sleep(SLEEP_TIME);
289 gain=jackpot_get_gain(game);
290 if(gain!=0)
291 game->money+=gain;
292 FOR_NB_SCREENS(d)
293 jackpot_print_turn_result(game, gain, rb->screens[d]);
296 enum plugin_status plugin_start(const struct plugin_api* api, const void* parameter)
298 rb = api;
299 int action, i;
300 struct jackpot game;
301 (void)parameter;
302 rb->srand(*rb->current_tick);
303 #ifdef HAVE_LCD_CHARCELLS
304 patterns_init(rb->screens[SCREEN_MAIN]);
305 #endif /* HAVE_LCD_CHARCELLS */
306 jackpot_init(&game);
308 FOR_NB_SCREENS(i){
309 rb->screens[i]->clear_display();
310 jackpot_display_slot_machine(&game, rb->screens[i]);
312 /*Empty the event queue*/
313 rb->button_clear_queue();
314 while (true)
316 action = pluginlib_getaction(rb, TIMEOUT_BLOCK,
317 plugin_contexts, 1);
318 switch ( action )
320 case PLA_QUIT:
321 return PLUGIN_OK;
322 case PLA_FIRE:
323 jackpot_play_turn(&game);
324 break;
326 default:
327 if (rb->default_event_handler_ex(action, jackpot_exit, NULL)
328 == SYS_USB_CONNECTED)
329 return PLUGIN_USB_CONNECTED;
330 break;
333 jackpot_exit(NULL);
334 return PLUGIN_OK;