This source file includes following definitions.
- stone
- cursor
- isFull
- set_stone
- unset_stone
- ki_isBadColumn
- ki_3
- ki_2
- ki_findColumn
- draw_txt_message
- change_player
- win_query
- win
- draw_mode
- change_mode
- set
- move_cursor
- gui_4wins_init
- basic_module_init
- gui_4wins_kbd_process
- gui_4wins_draw
1
2 #include "camera_info.h"
3 #include "keyboard.h"
4 #include "lang.h"
5 #include "conf.h"
6 #include "gui.h"
7 #include "gui_osd.h"
8 #include "gui_draw.h"
9 #include "gui_lang.h"
10 #include "gui_batt.h"
11 #include "gui_mbox.h"
12 #include "modes.h"
13 #include "time.h"
14
15 #include "module_def.h"
16
17 void gui_game_menu_kbd_process();
18 int gui_4wins_kbd_process();
19 void gui_4wins_draw();
20
21 gui_handler GUI_MODE_4WINS =
22 { GUI_MODE_MODULE, gui_4wins_draw, gui_4wins_kbd_process, gui_game_menu_kbd_process, 0, GUI_MODE_FLAG_NODRAWRESTORE };
23
24 int rect_size = 30;
25
26 #define XBORDER (camera_screen.disp_left+FONT_WIDTH)
27 #define RECT_SIZE rect_size
28 #define STONE_SIZE (rect_size/2-5)
29 #define BORDER_TOP (FONT_HEIGHT + 10)
30 #define FIELD_HEIGHT 7
31 #define FIELD_WIDTH 7
32 #define P1_COLOR COLOR_BLUE
33 #define P2_COLOR COLOR_GREEN
34 #define BK_COLOR COLOR_GREY
35 #define FIELD_COLOR MAKE_COLOR(COLOR_GREY_LT,COLOR_GREY_LT)
36 #define TEXT_COLOR MAKE_COLOR(COLOR_GREY, COLOR_WHITE)
37 #define INFO_COLOR COLOR_GREY_LT
38 #define INFO_TEXT_COLOR MAKE_COLOR(INFO_COLOR, COLOR_WHITE)
39
40 char cursor_position,cur_player=1;
41 char field[FIELD_HEIGHT][FIELD_WIDTH];
42 char finished=0;
43 char badColumns[7];
44 char in_game=0;
45 char mode_rival=0;
46 char count_win[2]={0,0};
47
48 static void stone(int column, int row, color cl)
49 {
50 draw_ellipse((XBORDER+((column-1)*RECT_SIZE))+(RECT_SIZE/2), (BORDER_TOP+((7-row)*RECT_SIZE))+(RECT_SIZE/2), STONE_SIZE, STONE_SIZE, cl, DRAW_FILLED);
51 }
52
53 static void cursor(int column, color cl)
54 {
55 stone(column+1, 7, cl);
56 }
57
58 static char isFull(int column)
59 {
60 if (field[column - 1][6])
61 return 1;
62 else
63 return 0;
64 }
65
66 static char set_stone(int column, char player, char visible)
67 {
68 int i;
69 in_game = 1;
70 if (!isFull(column))
71 {
72 for (i = 1; field[column - 1][i]; i++)
73 ;
74 if (visible)
75 {
76 stone(column, i, (cur_player == 1) ? P1_COLOR : P2_COLOR);
77 }
78 field[column - 1][i] = player;
79 return 1;
80 }
81 else
82 return 0;
83 }
84
85 static void unset_stone(int column)
86 {
87 int i;
88 for(i=1;(i<=6)&&field[column-1][i];i++);
89 field[column-1][i-1]=0;
90 }
91
92 char ki_isBadColumn(int column)
93 {
94 if (badColumns[column - 1])
95 return column;
96 else
97 return 0;
98 }
99
100 char ki_3(char player)
101 {
102 int i,j;
103
104 for(i=0;i<=3;i++){
105 for(j=1;j<=6;j++){
106 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;
107 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;
108 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;
109 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;
110 }
111 for(j=1;j<=3;j++){
112 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;
113 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;
114 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;
115 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;
116 }
117 for(j=4;j<=6;j++){
118 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;
119 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;
120 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;
121 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;
122 }
123 }
124
125 for(i=0;i<=2;i++){
126 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;
127 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;
128 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;
129 }
130
131 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;
132 return 0;
133 }
134
135 char ki_2(char player) {
136 int i,j;
137
138 for(i=0;i<=3;i++){
139 for(j=1;j<=6;j++){
140 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;
141 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;
142 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;
143 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;
144 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;
145 }
146 for(j=1;j<=3;j++){
147 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;
148 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;
149 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;
150 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;
151 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;
152 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;
153 }
154 for(j=4;j<=6;j++){
155 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;
156 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;
157 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;
158 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;
159 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;
160 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;
161 }
162 }
163
164 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;
165 return 0;
166 }
167
168 char ki_findColumn(char mode, char player) {
169 char erg=0, cam=player, otherplayer, i, counter=0;
170 otherplayer=(player==1)?2:1;
171 switch(mode) {
172 case 'b':
173 case 1: erg=ki_3(cam);
174 if(!erg&&mode!='b') erg=ki_3(otherplayer); else break;
175 if(!erg) {
176 for(i=1;i<=7;i++) {
177 if(!isFull(i)) {
178 set_stone(i,9,0);
179 badColumns[i-1]=ki_findColumn('b',otherplayer);
180 if(!badColumns[i-1]) badColumns[i-1]=ki_findColumn('b',cam);
181 unset_stone(i);
182 } else badColumns[i-1]=9;
183 }
184 } else break;
185 erg=ki_2(cam);
186 if(!erg) erg=ki_2(otherplayer); else break;
187 if(!erg) erg=(!isFull(4)&&!ki_isBadColumn(4))?4:0; else break;
188 if(!erg) do erg=(rand()%7)+1; while((isFull(erg)||erg==0||ki_isBadColumn(erg))&&counter++<100);
189 if(counter>100) for(i=1;i<=7;i++) if(!isFull(i)) erg=i;
190 break;
191 }
192 return erg;
193 }
194
195 void draw_txt_message(char* text)
196 {
197 coord w, x, y;
198 twoColors cl = MAKE_COLOR(COLOR_RED, COLOR_WHITE);
199 w = (strlen(text) + 2) * FONT_WIDTH;
200
201 x = (camera_screen.width - w) >> 1;
202 y = ((camera_screen.height) >> 1);
203 draw_rectangle(x, y, x + w, y + FONT_HEIGHT + 8, cl, RECT_BORDER2 | DRAW_FILLED | RECT_ROUND_CORNERS);
204 draw_string_justified(x, y + 4, text, cl, 0, w, TEXT_CENTER);
205 }
206
207 static void change_player()
208 {
209 if (cur_player == 1)
210 cur_player = 2;
211 else
212 cur_player = 1;
213 cursor(cursor_position, (cur_player == 1) ? P1_COLOR : P2_COLOR);
214 }
215
216 static char win_query()
217 {
218 int i=0,j=0;
219
220 for(i=0;i<4;i++)
221 {
222 for(j=1;j<4;j++)
223 {
224
225 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;
226 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;
227
228 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;
229 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;
230 }
231 }
232
233 for(i=0;i<7;i++)
234 {
235 for(j=1;j<4;j++)
236 {
237 if(field[i][j]==2 && field[i][j+1]==2 && field[i][j+2]==2 && field[i][j+3]==2) return 1;
238 if(field[i][j]==1 && field[i][j+1]==1 && field[i][j+2]==1 && field[i][j+3]==1) return 1;
239 }
240 }
241
242 for(i=0;i<4;i++)
243 {
244 for(j=1;j<7;j++)
245 {
246 if(field[i][j]==2 && field[i+1][j]==2 && field[i+2][j]==2 && field[i+3][j]==2) return 1;
247 if(field[i][j]==1 && field[i+1][j]==1 && field[i+2][j]==1 && field[i+3][j]==1) return 1;
248 }
249 }
250
251 if (isFull(1) && isFull(2) && isFull(3) && isFull(4) && isFull(5) && isFull(6) && isFull(7)) return 9;
252
253 return 0;
254 }
255
256 void win()
257 {
258 if (win_query() == 1)
259 {
260 finished = 1;
261 count_win[cur_player - 1]++;
262 draw_txt_message(lang_str((cur_player == 1) ? LANG_CONNECT4_P1_WIN : (mode_rival) ? LANG_CONNECT4_P2_WIN : LANG_CONNECT4_CAM_WIN));
263 }
264 else if (win_query() == 9)
265 {
266 finished = 1;
267 draw_txt_message(lang_str(LANG_CONNECT4_DRAW));
268 }
269 change_player();
270 }
271
272 void draw_mode()
273 {
274 int x = camera_screen.disp_right - 15 * FONT_WIDTH;
275 draw_string_justified(x, 4 * FONT_HEIGHT, (mode_rival == 1) ? lang_str(LANG_CONNECT4_HUMAN) : "cam", TEXT_COLOR, 0, 12 * FONT_WIDTH, TEXT_LEFT | TEXT_FILL);
276 }
277
278 void change_mode()
279 {
280 cur_player = 1;
281 count_win[0] = count_win[1] = 0;
282 if (mode_rival == 1)
283 mode_rival = 0;
284 else
285 mode_rival = 1;
286 draw_mode();
287 }
288
289 void set()
290 {
291 if (finished == 0)
292 {
293 if (cursor_position == 7 && in_game == 0)
294 {
295 change_mode();
296 }
297 else
298 {
299 if (cur_player == 1 || (cur_player == 2 && mode_rival == 1))
300 if (set_stone(cursor_position + 1, cur_player, 1))
301 win();
302 if ((mode_rival == 0 && cur_player == 2) && !finished)
303 if (set_stone(ki_findColumn(1, cur_player), cur_player, 1))
304 win();
305 }
306 }
307 }
308
309 static void move_cursor(int in_x_pos)
310 {
311 cursor(cursor_position, BK_COLOR);
312 if (in_game)
313 {
314 if (cursor_position == 0 && in_x_pos < 0)
315 cursor_position = 7 + in_x_pos;
316 else
317 cursor_position = (cursor_position + in_x_pos) % 7;
318 }
319 else
320 {
321 if (cursor_position == 0 && in_x_pos < 0)
322 cursor_position = 8 + in_x_pos;
323 else
324 cursor_position = (cursor_position + in_x_pos) % 8;
325 }
326 cursor(cursor_position, (cur_player == 1) ? P1_COLOR : P2_COLOR);
327 }
328
329 int gui_4wins_init()
330 {
331 static char str[16];
332 int i = 0, j = 0;
333
334 if (camera_screen.height * 3 > camera_screen.width * 2)
335 {
336
337 rect_size = 8 * (camera_screen.height - FONT_HEIGHT - 20) / (9 * FIELD_HEIGHT);
338 }
339 else
340 {
341 rect_size = (camera_screen.height - FONT_HEIGHT - 20) / FIELD_HEIGHT;
342 }
343
344 cursor_position = 3;
345 finished = in_game = 0;
346 srand(time(NULL));
347
348 draw_rectangle(camera_screen.disp_left, 0, camera_screen.disp_right, camera_screen.height - 1, MAKE_COLOR(BK_COLOR, BK_COLOR), RECT_BORDER0 | DRAW_FILLED);
349 draw_rectangle(XBORDER, BORDER_TOP + RECT_SIZE, XBORDER + (7 * RECT_SIZE), BORDER_TOP + (7 * RECT_SIZE), FIELD_COLOR, RECT_BORDER0 | DRAW_FILLED);
350 draw_rectangle(camera_screen.disp_right - 16 * FONT_WIDTH, 5 * FONT_HEIGHT, camera_screen.disp_right - FONT_WIDTH, camera_screen.height - 10, MAKE_COLOR(INFO_COLOR, INFO_COLOR), RECT_BORDER0 | DRAW_FILLED | RECT_ROUND_CORNERS);
351 draw_string(camera_screen.disp_left + 12 * FONT_WIDTH, 0, lang_str(LANG_MENU_GAMES_CONNECT4), TEXT_COLOR);
352 draw_line(camera_screen.disp_left, FONT_HEIGHT, camera_screen.disp_right - 1, FONT_HEIGHT, COLOR_GREY_LT);
353
354 for (i = 0; i < 7; i++)
355 {
356 for (j = 0; j < 6; j++)
357 {
358 field[i][j + 1] = 0;
359 stone(i + 1, j + 1, BK_COLOR);
360 }
361 }
362 for (i = 0; i < 7; i++)
363 {
364 field[i][0] = 9;
365 }
366
367 move_cursor(0);
368 draw_string(camera_screen.disp_right - 15 * FONT_WIDTH, 3 * FONT_HEIGHT, lang_str(LANG_CONNECT4_RIVAL), TEXT_COLOR);
369 sprintf(str, "%d", count_win[0]);
370 draw_string(camera_screen.disp_right - (10 + strlen(str)) * FONT_WIDTH, camera_screen.height - 9 * FONT_HEIGHT, str, MAKE_COLOR(INFO_COLOR, P1_COLOR));
371 sprintf(str, ":");
372 draw_string(camera_screen.disp_right - 9 * FONT_WIDTH, camera_screen.height - 9 * FONT_HEIGHT, str, INFO_TEXT_COLOR);
373 sprintf(str, "%d", count_win[1]);
374 draw_string(camera_screen.disp_right - 7 * FONT_WIDTH, camera_screen.height - 9 * FONT_HEIGHT, str, MAKE_COLOR(INFO_COLOR, P2_COLOR));
375 draw_mode();
376 if (cur_player == 2 && !mode_rival)
377 set();
378
379 gui_set_mode(&GUI_MODE_4WINS);
380
381 return 1;
382 }
383
384 int basic_module_init()
385 {
386 return gui_4wins_init();
387 }
388
389
390 int gui_4wins_kbd_process()
391 {
392 switch (kbd_get_autoclicked_key())
393 {
394 case KEY_SET:
395 if (!finished)
396 set();
397 else
398 gui_4wins_init();
399 break;
400 case KEY_LEFT:
401 if (finished == 0)
402 move_cursor(-1);
403 break;
404 case KEY_RIGHT:
405 if (finished == 0)
406 move_cursor(1);
407 break;
408 }
409 return 0;
410 }
411
412 void gui_4wins_draw()
413 {
414 static char str[16];
415 sprintf(str, "Batt: %3d%%", get_batt_perc());
416 draw_string(camera_screen.disp_right - 12 * FONT_WIDTH, camera_screen.height - 2 * FONT_HEIGHT, str, INFO_TEXT_COLOR);
417 gui_osd_draw_clock(camera_screen.disp_right - 11 * FONT_WIDTH, camera_screen.height - 3 * FONT_HEIGHT, INFO_TEXT_COLOR, 1);
418 }
419
420 #include "simple_game.c"
421
422
423
424 ModuleInfo _module_info =
425 {
426 MODULEINFO_V1_MAGICNUM,
427 sizeof(ModuleInfo),
428 SIMPLE_MODULE_VERSION,
429
430 ANY_CHDK_BRANCH, 0, OPT_ARCHITECTURE,
431 ANY_PLATFORM_ALLOWED,
432
433 -LANG_MENU_GAMES_CONNECT4,
434 MTYPE_GAME,
435
436 &_librun.base,
437
438 ANY_VERSION,
439 CAM_SCREEN_VERSION,
440 ANY_VERSION,
441 ANY_VERSION,
442
443 0,
444 };