/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2007 Copyright Kévin Ferrare based on work by Pierre Delore * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include "plugin.h" #include "lib/pluginlib_actions.h" #include "lib/picture.h" #include "lib/pluginlib_exit.h" const struct button_mapping* plugin_contexts[]={pla_main_ctx}; #define NB_PICTURES 9 #define NB_SLOTS 3 #ifdef HAVE_LCD_CHARCELLS #define PICTURE_ROTATION_STEPS 7 static unsigned char jackpot_slots_patterns[]={ 0x00, 0x0A, 0x1F, 0x1F, 0x1F, 0x0e, 0x04, /* (+00)Heart */ 0x00, 0x04, 0x0E, 0x1F, 0x1F, 0x04, 0x0E, /* (+07)Spade */ 0x00, 0x04, 0x0E, 0x1F, 0x0E, 0x04, 0x00, /* (+14)Diamond */ 0x00, 0x15, 0x0E, 0x1F, 0x0E, 0x15, 0x00, /* (+21)Club */ 0x03, 0x04, 0x0e, 0x1F, 0x1F, 0x1F, 0x0e, /* (+28)Cherry */ 0x00, 0x04, 0x04, 0x1F, 0x04, 0x0E, 0x1F, /* (+35)Cross */ 0x04, 0x0E, 0x15, 0x04, 0x0A, 0x0A, 0x11, /* (+42)Man */ 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, /* (+49)Square */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* (+56)Empty */ 0x00, 0x0A, 0x1F, 0x1F, 0x1F, 0x0e, 0x04 /* (+63)Heart */ }; static unsigned long char_patterns[NB_SLOTS]; #define SLEEP_TIME (HZ/24) #else /* bitmaps LCDs */ #define PICTURE_HEIGHT (BMPHEIGHT_jackpot_slots/(NB_PICTURES+1)) #if NB_SCREENS==1 #define PICTURE_ROTATION_STEPS PICTURE_HEIGHT #else #define REMOTE_PICTURE_HEIGHT (BMPHEIGHT_jackpot_slots_remote/(NB_PICTURES+1)) #define PICTURE_ROTATION_STEPS REMOTE_PICTURE_HEIGHT #endif /* FIXME: would be nice to have better graphics ... */ #include "pluginbitmaps/jackpot_slots.h" #if NB_SCREENS==2 #include "pluginbitmaps/jackpot_slots_remote.h" #endif const struct picture jackpot_pictures[]={ {jackpot_slots, BMPWIDTH_jackpot_slots, BMPHEIGHT_jackpot_slots, PICTURE_HEIGHT}, #if NB_SCREENS==2 {jackpot_slots_remote,BMPWIDTH_jackpot_slots_remote, BMPHEIGHT_jackpot_slots_remote, REMOTE_PICTURE_HEIGHT} #endif }; #define SLEEP_TIME (HZ/200) #endif /* HAVE_LCD_CHARCELLS */ struct jackpot { /* A slot can display "NB_PICTURES" pictures A picture is moving up, it can take PICTURE_ROTATION_STEPS to move a single picture completely. So values in slot_state are comprised between 0 and NB_PICTURES*PICTURE_ROTATION_STEPS */ int slot_state[NB_SLOTS]; /* The real state of the picture in pixels on each screen Different from slot_state because of the synchronised rotation between different sized bitmaps on remote and main screen */ int state_y[NB_SCREENS][NB_SLOTS]; int money; }; #ifdef HAVE_LCD_CHARCELLS void patterns_init(struct screen* display) { int i; for(i=0;iget_locked_pattern(); } void patterns_deinit(struct screen* display) { /* Restore the old pattern */ int i; for(i=0;iunlock_pattern(char_patterns[i]); } #endif /* HAVE_LCD_CHARCELLS */ /*Call when the program exit*/ static void jackpot_exit(void) { #ifdef HAVE_LCD_CHARCELLS patterns_deinit(rb->screens[SCREEN_MAIN]); #endif /* HAVE_LCD_CHARCELLS */ } static void jackpot_init(struct jackpot* game) { game->money=20; for(int i=0;islot_state[i]=(rb->rand()%NB_PICTURES)*PICTURE_ROTATION_STEPS; FOR_NB_SCREENS(j) game->state_y[j][i]=-1; } } static int jackpot_get_result(struct jackpot* game) { int i=NB_SLOTS-1; int multiple=1; int result=0; for(;i>=0;i--) { result+=game->slot_state[i]*multiple/PICTURE_ROTATION_STEPS; multiple*=10; } return(result); } static int jackpot_get_gain(struct jackpot* game) { switch (jackpot_get_result(game)) { case 111 : return(20); case 000 : return(15); case 333 : return(10); case 222 : return(8); case 555 : return(5); case 777 : return(4); case 251 : return(4); case 510 : return(4); case 686 : return(3); case 585 : return(3); case 282 : return(3); case 484 : return(3); case 787 : return(2); case 383 : return(2); case 80 : return(2); } return(0); } static void jackpot_display_slot_machine(struct jackpot* game, struct screen* display) { char str[20]; int i; bool changes=false; #ifdef HAVE_LCD_CHARCELLS display->putchar(0, 0, '['); #else const struct picture* picture= &(jackpot_pictures[display->screen_type]); int pos_x=(display->getwidth()-NB_SLOTS*(picture->width+1))/2; int pos_y=(display->getheight()-(picture->slide_height))/2; #endif /* HAVE_LCD_CHARCELLS */ for(i=0;islot_state[i]*7)/PICTURE_ROTATION_STEPS; #else int state_y= (picture->slide_height*game->slot_state[i])/PICTURE_ROTATION_STEPS; #endif /* HAVE_LCD_CHARCELLS */ int previous_state_y=game->state_y[display->screen_type][i]; if(state_y==previous_state_y) continue;/*no need to update the picture as it's the same as previous displayed one*/ changes=true; game->state_y[display->screen_type][i]=state_y; #ifdef HAVE_LCD_CHARCELLS char* current_pattern=&(jackpot_slots_patterns[state_y]); display->define_pattern(char_patterns[i], current_pattern); display->putchar(i+1, 0, char_patterns[i]); #else vertical_picture_draw_part(display, picture, state_y, pos_x, pos_y); pos_x+=(picture->width+1); #endif } if(changes){ #ifdef HAVE_LCD_CHARCELLS rb->snprintf(str,sizeof(str),"$%d", game->money); display->putchar(++i, 0, ']'); display->puts(++i, 0, str); #else rb->snprintf(str,sizeof(str),"money : $%d", game->money); display->puts(0, 0, str); #endif display->update(); } } static void jackpot_info_message(struct screen* display, char* message) { #ifdef HAVE_LCD_CHARCELLS display->puts_scroll(0,1,message); #else int xpos, ypos; int message_height, message_width; display->getstringsize(message, &message_width, &message_height); xpos=(display->getwidth()-message_width)/2; ypos=display->getheight()-message_height; rb->screen_clear_area(display, 0, ypos, display->getwidth(), message_height); display->putsxy(xpos,ypos,message); display->update(); #endif /* HAVE_LCD_CHARCELLS */ } static void jackpot_print_turn_result(struct jackpot* game, int gain, struct screen* display) { char str[20]; if (gain==0) { jackpot_info_message(display, "None ..."); if (game->money<=0) jackpot_info_message(display, "You lose...STOP to quit"); } else { rb->snprintf(str,sizeof(str),"You win %d$",gain); jackpot_info_message(display, str); } display->update(); } static void jackpot_play_turn(struct jackpot* game) { /* How many pattern? */ int nb_turns[NB_SLOTS]; int gain,turns_remaining=0; if(game->money<=0) return; game->money--; for(int i=0;irand()%15+5)*PICTURE_ROTATION_STEPS; turns_remaining+=nb_turns[i]; } FOR_NB_SCREENS(d) { rb->screens[d]->clear_display(); jackpot_info_message(rb->screens[d],"Good luck"); } /* Jackpot Animation */ while(turns_remaining>0) { for(int i=0;i0) { nb_turns[i]--; game->slot_state[i]++; if(game->slot_state[i]>=PICTURE_ROTATION_STEPS*NB_PICTURES) game->slot_state[i]=0; turns_remaining--; } } FOR_NB_SCREENS(d) jackpot_display_slot_machine(game, rb->screens[d]); rb->sleep(SLEEP_TIME); } gain=jackpot_get_gain(game); if(gain!=0) game->money+=gain; FOR_NB_SCREENS(d) jackpot_print_turn_result(game, gain, rb->screens[d]); } enum plugin_status plugin_start(const void* parameter) { int action; struct jackpot game; (void)parameter; atexit(jackpot_exit); rb->srand(*rb->current_tick); #ifdef HAVE_LCD_CHARCELLS patterns_init(rb->screens[SCREEN_MAIN]); #endif /* HAVE_LCD_CHARCELLS */ jackpot_init(&game); FOR_NB_SCREENS(i){ rb->screens[i]->clear_display(); jackpot_display_slot_machine(&game, rb->screens[i]); } /*Empty the event queue*/ rb->button_clear_queue(); while (true) { action = pluginlib_getaction(TIMEOUT_BLOCK, plugin_contexts, ARRAYLEN(plugin_contexts)); switch ( action ) { case PLA_CANCEL: return PLUGIN_OK; case PLA_SELECT: jackpot_play_turn(&game); break; default: exit_on_usb(action); break; } } return PLUGIN_OK; }