source: branches/reyalp-flt/core/gui_4wins.c @ 1513

Revision 1513, 16.4 KB checked in by philmoz, 2 years ago (diff)

Cleanup of code for handling CHDK 'gui' mode.

  • Property svn:eol-style set to native
Line 
1//Conect4: Kettmeister, CHDKLover german forum (forum.chdk-treff.de)
2#include "stdlib.h"
3#include "keyboard.h"
4#include "platform.h"
5#include "core.h"
6#include "lang.h"
7#include "conf.h"
8#include "gui.h"
9#include "gui_osd.h"
10#include "gui_draw.h"
11#include "gui_lang.h"
12#include "gui_batt.h"
13#include "gui_mbox.h"
14#include "gui_4wins.h"
15
16#include "module_load.h"
17
18void gui_module_menu_kbd_process();
19void gui_4wins_kbd_process();
20void gui_4wins_draw(int enforce_redraw);
21
22gui_handler GUI_MODE_4WINS =
23    /*GUI_MODE_4WINS*/  { GUI_MODE_MODULE,  gui_4wins_draw,       gui_4wins_kbd_process,      gui_module_menu_kbd_process, GUI_MODE_FLAG_NODRAWRESTORE, GUI_MODE_MAGICNUM };
24
25
26#define BORDER           20
27#define XBORDER          (camera_info.ts_button_border+BORDER)
28#define RECT_SIZE        30
29#define BORDER_TOP       RECT_SIZE
30#define FIELD_HEIGHT 7
31#define FIELD_WIDTH      7
32#define P1_COLOR         MAKE_COLOR(COLOR_HISTO_B_PLAY,COLOR_HISTO_B_PLAY)
33#define P2_COLOR         MAKE_COLOR(COLOR_HISTO_G_PLAY,COLOR_HISTO_G_PLAY)
34#define BG_COLOR         MAKE_COLOR(COLOR_GREY,COLOR_GREY)
35#define FIELD_COLOR      MAKE_COLOR(COLOR_SPLASH_GREY,COLOR_SPLASH_GREY)//(füllfarbe,rand)
36#define TEXT_COLOR   MAKE_COLOR(BG_COLOR, COLOR_WHITE)
37#define INFO_COLOR   MAKE_COLOR(COLOR_SPLASH_GREY, COLOR_SPLASH_GREY)
38#define INFO_TEXT_COLOR   MAKE_COLOR(INFO_COLOR, COLOR_WHITE)
39
40char cursor_position,cur_player=1;
41char field[FIELD_HEIGHT][FIELD_WIDTH];
42char finished=0;
43char badColumns[7];
44char in_game=0;
45char mode_rival=0; //1=person 0=cam
46char count_win[2]={0,0};
47
48//-------------------------------------------------------------------
49static char isFull(int column)
50{
51        if(field[column-1][6])
52                return 1;
53        else
54                return 0;
55}
56
57static char set_stone(int column, char player, char visible)
58{
59        int i;
60    in_game=1;
61        if(!isFull(column))
62        {
63                for(i=1;field[column-1][i];i++);                        //1 ist wichtig (0=Fundament)
64                if (visible) {
65                        draw_filled_ellipse((XBORDER+((column-1)*RECT_SIZE))+15, (BORDER+((6-i)*RECT_SIZE))+15+BORDER_TOP, 10,10, (cur_player==1)?P1_COLOR:P2_COLOR);
66                }
67                field[column-1][i]=player;
68                return 1;
69        }
70        else return 0;
71}
72/*====================      KI   ===========================*/
73static void unset_stone(int column)
74{
75  int i;
76  for(i=1;field[column-1][i]&&i<=6;i++);                        //1 ist wichtig (0=Fundament)
77  field[column-1][i-1]=0;
78}
79
80char ki_isBadColumn(int column){
81  if(badColumns[column-1]) return column; else return 0;
82}
83
84char ki_3(char player) {
85  int i,j;
86  //waagerecht und Diagonal (über Anstieg)
87  for(i=0;i<=3;i++){            // column
88    for(j=1;j<=6;j++){          //row
89      if(field[i][j]==player&&field[i+1][j]==player&&field[i+2][j]==player&&field[i+3][j]==0&&field[i+3][j-1]) return i+4;      //***-
90      if(field[i][j]==player&&field[i+1][j]==player&&field[i+2][j]==0&&field[i+3][j]==player&&field[i+2][j-1]) return i+3;      //**-*
91      if(field[i][j]==player&&field[i+1][j]==0&&field[i+2][j]==player&&field[i+3][j]==player&&field[i+1][j-1]) return i+2;      //*-**
92      if(field[i][j]==0&&field[i+1][j]==player&&field[i+2][j]==player&&field[i+3][j]==player&&field[i][j-1]) return i+1;        //-***
93    }
94    for(j=1;j<=3;j++){
95      if(field[i][j]==player&&field[i+1][j+1]==player&&field[i+2][j+2]==player&&field[i+3][j+3]==0&&field[i+3][j+3-1]) return i+4;      //***-
96      if(field[i][j]==player&&field[i+1][j+1]==player&&field[i+2][j+2]==0&&field[i+3][j+3]==player&&field[i+2][j+2-1]) return i+3;      //**-*
97      if(field[i][j]==player&&field[i+1][j+1]==0&&field[i+2][j+2]==player&&field[i+3][j+3]==player&&field[i+1][j+1-1]) return i+2;      //*-**
98      if(field[i][j]==0&&field[i+1][j+1]==player&&field[i+2][j+2]==player&&field[i+3][j+3]==player&&field[i][j-1]) return i+1;          //-***
99    }
100    for(j=4;j<=6;j++){
101        if(field[i][j]==player&&field[i+1][j-1]==player&&field[i+2][j-2]==player&&field[i+3][j-3]==0&&field[i+3][j-3-1]) return i+4;    //***-
102        if(field[i][j]==player&&field[i+1][j-1]==player&&field[i+2][j-2]==0&&field[i+3][j-3]==player&&field[i+2][j-2-1]) return i+3;    //**-*
103        if(field[i][j]==player&&field[i+1][j-1]==0&&field[i+2][j-2]==player&&field[i+3][j-3]==player&&field[i+1][j-1-1]) return i+2;    //*-**
104        if(field[i][j]==0&&field[i+1][j-1]==player&&field[i+2][j-2]==player&&field[i+3][j-3]==player&&field[i][j-1]) return i+1;                //-***
105    }
106  }
107  //Unterreihentrick in allen ebenen
108  for(i=0;i<=2;i++){
109    for(j=1;j<=6;j++) if(field[i][j]==0&&field[i+1][j]==player&&field[i+2][j]==0&&field[i+3][j]==player&&field[i+4][j]==0&&field[i][j-1]&&field[i+2][j-1]&&field[i+4][j-1]) return i+3; //_*_*_
110    for(j=1;j<=3;j++) if(field[i][j]==0&&field[i+1][j+1]==player&&field[i+2][j+2]==0&&field[i+3][j+3]==player&&field[i+4][j+4]==0&&field[i][j-1]&&field[i+2][j+2-1]&&field[i+4][j+4-1]) return i+3;     //_*_*_
111    for(j=4;j<=6;j++) if(field[i][j]==0&&field[i+1][j-1]==player&&field[i+2][j-2]==0&&field[i+3][j-3]==player&&field[i+4][j-4]==0&&field[i][j-1]&&field[i+2][j-2-1]&&field[i+4][j-4-1]) return i+3;     //_*_*_
112  }
113  //senkrecht
114  for(i=0;i<=6;i++) for(j=1;j<=3;j++) if(field[i][j]==player&&field[i][j+1]==player&&field[i][j+2]==player&&field[i][j+3]==0) return i+1;
115  return 0;
116}
117
118char ki_2(char player) {
119  int i,j;
120  //waagerecht und Diagonal über Anstieg
121  for(i=0;i<=3;i++){            //column
122    for(j=1;j<=6;j++){          //row
123      if(field[i][j]==player&&field[i+1][j]==player&&field[i+2][j]==0&&field[i+3][j]==0&&(field[i+2][j-1]||field[i+3][j-1])&&!ki_isBadColumn(i+3)) return i+3;  //**-- return und if ändern
124      if(field[i][j]==player&&field[i+1][j]==0&&field[i+2][j]==0&&field[i+3][j]==player&&(field[i+1][j-1]||field[i+2][j-1])&&!ki_isBadColumn(i+2)) return i+2;  //*--* (i+3 geht auch)
125      if(field[i][j]==0&&field[i+1][j]==0&&field[i+2][j]==player&&field[i+3][j]==player&&(field[i][j-1]||field[i+1][j-1])&&!ki_isBadColumn(i+2)) return i+2;    //--**
126      if(field[i][j]==0&&field[i+1][j]==player&&field[i+2][j]==0&&field[i+3][j]==player&&(field[i][j-1]||field[i+2][j-1])&&!ki_isBadColumn(i+3)) return i+3;    //-*-*
127      if(field[i][j]==player&&field[i+1][j]==0&&field[i+2][j]==player&&field[i+3][j]==0&&(field[i+1][j-1]||field[i+3][j-1])&&!ki_isBadColumn(i+2)) return i+2;  //*-*-
128    }
129    for(j=1;j<=3;j++){
130      if(field[i][j]==player&&field[i+1][j+1]==player&&field[i+2][j+2]==0&&field[i+3][j+3]==0&&field[i+2][j+2-1]&&!ki_isBadColumn(i+3)) return i+3;     //**-- return und if ändern
131      if(field[i][j]==player&&field[i+1][j+1]==player&&field[i+2][j+2]==0&&field[i+3][j+3]==0&&field[i+3][j+3-1]&&!ki_isBadColumn(i+3)) return i+4;     //**-- return und if ändern
132      if(field[i][j]==player&&field[i+1][j+1]==0&&field[i+2][j+2]==0&&field[i+3][j+3]==player&&(field[i+1][j+1-1]||field[i+2][j+2-1])&&!ki_isBadColumn(i+2)) return i+2;        //*--* (i+3 geht auch)
133      if(field[i][j]==0&&field[i+1][j+1]==0&&field[i+2][j+2]==player&&field[i+3][j+3]==player&&(field[i][j-1]||field[i+1][j+1-1])&&!ki_isBadColumn(i+2)) return i+2;    //--**
134      if(field[i][j]==0&&field[i+1][j+1]==player&&field[i+2][j+2]==0&&field[i+3][j+3]==player&&(field[i][j-1]||field[i+2][j+2-1])&&!ki_isBadColumn(i+3)) return i+3;    //-*-*
135      if(field[i][j]==player&&field[i+1][j+1]==0&&field[i+2][j+2]==player&&field[i+3][j+3]==0&&(field[i+1][j+1-1]||field[i+3][j+3-1])&&!ki_isBadColumn(i+2)) return i+2;        //*-*-
136    }
137    for(j=4;j<=6;j++){
138      if(field[i][j]==player&&field[i+1][j-1]==player&&field[i+2][j-2]==0&&field[i+3][j-3]==0&&field[i+2][j-2-1]&&!ki_isBadColumn(i+3)) return i+3;     //**-- return und if ändern
139      if(field[i][j]==player&&field[i+1][j-1]==player&&field[i+2][j-2]==0&&field[i+3][j-3]==0&&field[i+3][j-3-1]&&!ki_isBadColumn(i+3)) return i+4;     //**-- return und if ändern
140      if(field[i][j]==player&&field[i+1][j-1]==0&&field[i+2][j-2]==0&&field[i+3][j-3]==player&&(field[i+1][j-1-1]||field[i+2][j-2-1])&&!ki_isBadColumn(i+2)) return i+2;        //*--* (i+3 geht auch)
141      if(field[i][j]==0&&field[i+1][j-1]==0&&field[i+2][j-2]==player&&field[i+3][j-3]==player&&(field[i][j-1]||field[i+1][j-1-1])&&!ki_isBadColumn(i+2)) return i+2;    //--**
142      if(field[i][j]==0&&field[i+1][j-1]==player&&field[i+2][j-2]==0&&field[i+3][j-3]==player&&(field[i][j-1]||field[i+2][j-2-1])&&!ki_isBadColumn(i+3)) return i+3;    //-*-*
143      if(field[i][j]==player&&field[i+1][j-1]==0&&field[i+2][j-2]==player&&field[i+3][j-3]==0&&(field[i+1][j-1-1]||field[i+3][j-3-1])&&!ki_isBadColumn(i+2)) return i+2;        //*-*-
144    }
145  }
146  //senkrecht
147  for(i=0;i<=6;i++) for(j=1;j<=3;j++) if(field[i][j]==player&&field[i][j+1]==player&&field[i][j+2]==0&&!ki_isBadColumn(i+1)) return i+1;
148  return 0;
149}
150
151char ki_findColumn(char mode, char player) {                                                    //player = 1|2
152  char erg=0, cam=player, otherplayer, i, counter=0;
153  otherplayer=(player==1)?2:1;
154  switch(mode) {
155  case 'b':
156  case 1: erg=ki_3(cam);                                                                                                //ich3
157          if(!erg&&mode!='b') erg=ki_3(otherplayer); else break;                //du3
158          if(!erg) {                                                                                                    //ungünstige Spalten ermitteln
159            for(i=1;i<=7;i++) {
160              if(!isFull(i)) {
161                set_stone(i,9,0);                                                                               //Stein setzen 9=irgendwas
162                badColumns[i-1]=ki_findColumn('b',otherplayer);                 //ungünstige Spalten ermitteln b=bad
163                if(!badColumns[i-1]) badColumns[i-1]=ki_findColumn('b',cam);
164                unset_stone(i);
165              } else badColumns[i-1]=9;                                                         //9=full
166            }
167          } else break;
168          erg=ki_2(cam);                                                                                                //ich2 (für passivere Methode vertauschen)
169          if(!erg) erg=ki_2(otherplayer); else break;                                   //du2
170          if(!erg) erg=(!isFull(4)&&!ki_isBadColumn(4))?4:0; else break;//mitte
171          if(!erg) do erg=(rand()%7)+1; while((isFull(erg)||erg==0||ki_isBadColumn(erg))&&counter++<100);       //zufall
172          if(counter>100) for(i=1;i<=7;i++) if(!isFull(i)) erg=i;
173          break;
174  }
175  return erg;
176}
177/*======================= K I   END ===============================*/
178void draw_txt_message(char* text) {
179    coord w, x, y;
180    int l;
181    color cl = MAKE_COLOR(COLOR_RED, COLOR_WHITE);
182    l=strlen(text);
183    w=l*FONT_WIDTH+10;
184
185    x = (screen_width-camera_info.ts_button_border-w)>>1; y = ((screen_height)>>1);
186    draw_filled_round_rect(x, y, x+w, y+FONT_HEIGHT+6, MAKE_COLOR(COLOR_RED, COLOR_RED));
187    draw_string(x+((w-strlen(text)*FONT_WIDTH)>>1), y+4, text, cl);
188}
189//-------------------------------------------------------------------
190static void change_player()
191{
192        if (cur_player==1) cur_player=2; else cur_player=1;
193        draw_filled_ellipse((XBORDER+((cursor_position)*RECT_SIZE))+15, BORDER+10, 10,10, (cur_player==1)?P1_COLOR:P2_COLOR);
194}
195//-------------------------------------------------------------------
196static char win_query()
197{
198        int i=0,j=0;
199
200        for(i=0;i<4;i++)
201        {
202                for(j=1;j<4;j++)
203                {
204                        // '1'
205                        if(field[i][j]==1 && field[i+1][j+1]==1 && field[i+2][j+2]==1 && field[i+3][j+3]==1) return 1; // diagonal  > 
206                        if(field[i][j+3]==1 && field[i+1][j+2]==1 && field[i+2][j+1]==1 && field[i+3][j]==1) return 1; // diagonal  >  /
207                        // '2'
208                        if(field[i][j]==2 && field[i+1][j+1]==2 && field[i+2][j+2]==2 && field[i+3][j+3]==2) return 1;// diagonal  > 
209                        if(field[i][j+3]==2 && field[i+1][j+2]==2 && field[i+2][j+1]==2 && field[i+3][j]==2) return 1;// diagonal  >  /
210                }
211        }
212       
213        for(i=0;i<7;i++)
214        {
215                for(j=1;j<4;j++)
216                {
217                        if(field[i][j]==2 && field[i][j+1]==2 && field[i][j+2]==2 && field[i][j+3]==2) return 1; // vertical  >  |
218                        if(field[i][j]==1 && field[i][j+1]==1 && field[i][j+2]==1 && field[i][j+3]==1) return 1; // vertical  >  |
219                }
220        }
221       
222        for(i=0;i<4;i++)
223        {
224                for(j=1;j<7;j++)
225                {
226                        if(field[i][j]==2 && field[i+1][j]==2 && field[i+2][j]==2 && field[i+3][j]==2) return 1; // horizontal  >  -
227                        if(field[i][j]==1 && field[i+1][j]==1 && field[i+2][j]==1 && field[i+3][j]==1) return 1;        // horizontal  >  -
228                }
229        }
230
231        if (isFull(1) && isFull(2) && isFull(3) && isFull(4) && isFull(5) && isFull(6) && isFull(7)) return 9;
232       
233        return 0;
234}
235//-------------------------------------------------------------------
236void win() {
237  if(win_query()==1){
238    finished=1;
239    count_win[cur_player-1]++;
240    draw_txt_message(lang_str((cur_player==1)?LANG_CONNECT4_P1_WIN:(mode_rival)?LANG_CONNECT4_P2_WIN:LANG_CONNECT4_CAM_WIN));
241  }     else if (win_query()==9) {
242    finished=1;
243    draw_txt_message(lang_str(LANG_CONNECT4_DRAW));
244  }
245  change_player();
246}
247//-------------------------------------------------------------------
248void draw_mode()
249{
250    int x = (camera_info.ts_button_border/FONT_WIDTH) + 30;
251        draw_txt_string(x, 4, "            ", TEXT_COLOR);
252        if (mode_rival==1)
253                draw_txt_string(x, 4, lang_str(LANG_CONNECT4_HUMAN), TEXT_COLOR);
254        else
255                draw_txt_string(x, 4, "cam", TEXT_COLOR);
256}
257//-------------------------------------------------------------------
258void change_mode()
259{
260        cur_player=1;
261        count_win[0]=count_win[1]=0;
262        if(mode_rival==1)
263                mode_rival=0;   //CAM
264        else
265                mode_rival=1;   //HUMAN
266        draw_mode();
267}
268//-------------------------------------------------------------------
269void set()
270{
271        if(finished==0)
272        {
273                if(cursor_position==7 && in_game==0)   
274                {
275                        change_mode();
276                }
277                else
278                {
279                        if(cur_player==1 || (cur_player==2 && mode_rival==1)) if(set_stone(cursor_position+1,cur_player,1)) win();
280                        if((mode_rival==0 && cur_player==2) && !finished) if(set_stone(ki_findColumn(1, cur_player),cur_player, 1)) win();
281                }
282        }
283}
284//-------------------------------------------------------------------
285static void move_cursor(int in_x_pos)
286{
287        draw_filled_ellipse((XBORDER+((cursor_position)*RECT_SIZE))+15, BORDER+10, 10,10,BG_COLOR);
288        if(in_game)
289        {
290                if(cursor_position==0 && in_x_pos<0)
291                        cursor_position=7+in_x_pos;
292                else
293                        cursor_position=(cursor_position+in_x_pos)%7;
294        }
295        else
296        {
297                if(cursor_position==0 && in_x_pos<0)
298                        cursor_position=8+in_x_pos;
299                else
300                        cursor_position=(cursor_position+in_x_pos)%8;
301        }
302        draw_filled_ellipse((XBORDER+((cursor_position)*RECT_SIZE))+15, BORDER+10, 10,10, (cur_player==1)?P1_COLOR:P2_COLOR);
303}
304//-------------------------------------------------------------------
305int gui_4wins_init()
306{
307        static char str[16];
308        int i=0,j=0;
309
310        cursor_position=3;
311        finished=in_game=0;
312        srand(time(NULL));
313       
314        draw_filled_rect(0, 0, screen_width, screen_height, BG_COLOR);          // draw backgraund
315        draw_filled_rect(XBORDER, BORDER+BORDER_TOP, XBORDER+(7*RECT_SIZE), BORDER+(6*RECT_SIZE)+BORDER_TOP, FIELD_COLOR);
316        draw_filled_round_rect(camera_info.ts_button_border+240, 90, camera_info.ts_button_border+360-BORDER, 240-10, INFO_COLOR);
317    draw_txt_string((camera_info.ts_button_border/FONT_WIDTH)+12, 0, lang_str(LANG_MENU_GAMES_CONNECT4), TEXT_COLOR);
318    draw_line(camera_info.ts_button_border,15,camera_info.ts_button_border+360,15,COLOR_SPLASH_GREY);
319
320        for(i=0;i<7;i++)
321        {
322                for(j=0;j<6;j++)
323                {
324                        field[i][j+1]=0;
325                        draw_filled_ellipse(XBORDER+(i*RECT_SIZE)+(RECT_SIZE/2), BORDER+(j*RECT_SIZE)+(RECT_SIZE/2)+BORDER_TOP, 10, 10, BG_COLOR);
326                }
327        }
328        for(i=0;i<7;i++)
329        {
330                field[i][0]=9;
331        }
332
333        move_cursor(0);
334        draw_txt_string((camera_info.ts_button_border/FONT_WIDTH)+30, 3, lang_str(LANG_CONNECT4_RIVAL), TEXT_COLOR);
335    sprintf(str, "%d",count_win[0]);
336        draw_txt_string((screen_width-camera_info.ts_button_border)/FONT_WIDTH-2-10, screen_height/FONT_HEIGHT-9, str, MAKE_COLOR(INFO_COLOR, P1_COLOR));
337    sprintf(str, ":");
338        draw_txt_string((screen_width-camera_info.ts_button_border)/FONT_WIDTH-2-7, screen_height/FONT_HEIGHT-9, str, INFO_TEXT_COLOR);
339    sprintf(str, "%d",count_win[1]);
340        draw_txt_string((screen_width-camera_info.ts_button_border)/FONT_WIDTH-2-4, screen_height/FONT_HEIGHT-9, str, MAKE_COLOR(INFO_COLOR, P2_COLOR));
341        draw_mode();
342        if(cur_player==2&&!mode_rival) set();
343
344    gui_set_mode(&GUI_MODE_4WINS);
345
346        return 1;
347}
348
349int basic_module_init() {
350  return gui_4wins_init();
351}
352
353//-------------------------------------------------------------------
354void gui_4wins_kbd_process()
355{
356        switch (kbd_get_autoclicked_key())
357        {
358                case KEY_SET:
359                    if(!finished) set(); else gui_4wins_init();
360                        break;
361                case KEY_LEFT:
362                        if(finished==0)
363                                move_cursor(-1);
364                        break;
365                case KEY_RIGHT:
366                        if(finished==0)
367                                move_cursor(1);
368                        break;
369        }
370}
371//-------------------------------------------------------------------
372void gui_4wins_draw(int enforce_redraw) {
373  static char str[16];
374  sprintf(str, "%3d%%", get_batt_perc());
375  draw_txt_string((screen_width-camera_info.ts_button_border)/FONT_WIDTH-2-13, screen_height/FONT_HEIGHT-2, str, INFO_TEXT_COLOR);
376  gui_osd_draw_clock(camera_info.ts_button_border+290,208,INFO_TEXT_COLOR);
377}
378
379extern int module_idx;
380void gui_module_menu_kbd_process() {
381        gui_default_kbd_process_menu_btn();
382        module_async_unload(module_idx);
383}
384
385/******************** Module Information structure ******************/
386
387struct ModuleInfo _module_info = {      MODULEINFO_V1_MAGICNUM,
388                                                                        sizeof(struct ModuleInfo),
389
390                                                                        ANY_CHDK_BRANCH, 0,                     // Requirements of CHDK version
391                                                                        ANY_PLATFORM_ALLOWED,           // Specify platform dependency
392                                                                        0,                                                      // flag
393                                                                        -LANG_MENU_GAMES_CONNECT4,      // Module name
394                                                                        1, 0,                                           // Module version
395                                                                        (int32_t) "Game"
396                                                                 };
Note: See TracBrowser for help on using the repository browser.