source: branches/reyalp-ptp-live/core/games/gui_4wins.c @ 1911

Revision 1911, 16.4 KB checked in by reyalp, 12 months ago (diff)

update live view branch to trunk 1910

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