blob: 397fd0e559c3a68433f57b79d69419911adc3547 [file] [log] [blame]
Hristo Kovachev91522722006-02-22 14:24:54 +00001/***************************************************************************
2* __________ __ ___.
3* Open \______ \ ____ ____ | | _\_ |__ _______ ___
4* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7* \/ \/ \/ \/ \/
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +00008* $Id$
Hristo Kovachev91522722006-02-22 14:24:54 +00009*
William Wilgus37522ec2017-01-31 01:07:47 +010010* Copyright (C) 2006 Miguel A. Arévalo
Hristo Kovachev91522722006-02-22 14:24:54 +000011* Color graphics from eboard
12* GNUChess v2 chess engine Copyright (c) 1988 John Stanback
13*
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000014* This program is free software; you can redistribute it and/or
15* modify it under the terms of the GNU General Public License
16* as published by the Free Software Foundation; either version 2
17* of the License, or (at your option) any later version.
Hristo Kovachev91522722006-02-22 14:24:54 +000018*
19* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20* KIND, either express or implied.
21*
22****************************************************************************/
William Wilgus37522ec2017-01-31 01:07:47 +010023
Hristo Kovachev91522722006-02-22 14:24:54 +000024#include "plugin.h"
25
Thomas Martitzb0232e02009-02-26 21:24:29 +000026#if (MEMORYSIZE > 8) /* Lowmem doesn't have playback in chessbox */
27#define HAVE_PLAYBACK_CONTROL
28#endif
William Wilgus1fa7c562017-01-31 04:28:02 +010029/*#define CHESSBOX_SAVE_FILE_DBG PLUGIN_GAMES_DATA_DIR "/chessbox_dbg.save"*/
Thomas Martitzb0232e02009-02-26 21:24:29 +000030#ifdef HAVE_PLAYBACK_CONTROL
Thomas Martitz15dbde12009-02-26 17:10:27 +000031#include "lib/playback_control.h"
Thomas Martitzbb45f0e2009-02-26 17:46:01 +000032#endif
33
Hristo Kovachev91522722006-02-22 14:24:54 +000034#include "gnuchess.h"
Jens Arnold7b22e992006-04-15 11:27:47 +000035#include "opening.h"
Nils Wallménius3e190c82007-05-29 16:33:16 +000036#include "chessbox_pgn.h"
Hristo Kovachev91522722006-02-22 14:24:54 +000037
38/* type definitions */
39struct cb_command {
Dave Chapman7ceadd72006-03-03 15:01:37 +000040 int type;
41 char mv_s[5];
42 unsigned short mv;
Hristo Kovachev91522722006-02-22 14:24:54 +000043};
44
Hristo Kovachev91522722006-02-22 14:24:54 +000045/* External bitmaps */
46extern const fb_data chessbox_pieces[];
47
48
Thomas Martitzcae4ae22010-08-24 14:30:46 +000049
Hristo Kovachev91522722006-02-22 14:24:54 +000050
Marianne Arnolddf1f0d62007-10-19 09:05:18 +000051/* Tile size defined by the assigned bitmap */
Björn Stenbergc6b3d382008-11-20 11:27:31 +000052#include "pluginbitmaps/chessbox_pieces.h"
Marianne Arnolddf1f0d62007-10-19 09:05:18 +000053#define TILE_WIDTH BMPWIDTH_chessbox_pieces
54#define TILE_HEIGHT (BMPHEIGHT_chessbox_pieces/26)
Hristo Kovachev91522722006-02-22 14:24:54 +000055
56/* Calculate Offsets */
57#define XOFS ((LCD_WIDTH-8*TILE_WIDTH)/2)
58#define YOFS ((LCD_HEIGHT-8*TILE_HEIGHT)/2)
59
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +000060/* save files */
Thomas Jaroschf9f89cf2011-03-02 23:43:54 +000061#define SAVE_FILE PLUGIN_GAMES_DATA_DIR "/chessbox.save"
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +000062
Hristo Kovachev91522722006-02-22 14:24:54 +000063/* commands enum */
Dave Chapman7ceadd72006-03-03 15:01:37 +000064#define COMMAND_NOP 0
65#define COMMAND_MOVE 1
66#define COMMAND_PLAY 2
67#define COMMAND_LEVEL 3
Marcoen Hirschberg0d02c132007-05-18 22:12:34 +000068#define COMMAND_RESTART 4
Dave Chapman7ceadd72006-03-03 15:01:37 +000069#define COMMAND_QUIT 5
Marcoen Hirschberg0d02c132007-05-18 22:12:34 +000070#define COMMAND_MENU 6
71#define COMMAND_SAVE 7
72#define COMMAND_RESTORE 8
73#define COMMAND_RESUME 9
Nils Wallménius3e190c82007-05-29 16:33:16 +000074#define COMMAND_SELECT 10
75#define COMMAND_NEXT 11
76#define COMMAND_PREV 12
Solomon Peachy55729042019-07-15 10:49:55 -040077#define COMMAND_VIEW 13
78#define COMMAND_RETURN 14
Nils Wallménius3e190c82007-05-29 16:33:16 +000079
80short plugin_mode;
Dave Chapman7ceadd72006-03-03 15:01:37 +000081
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +000082/* level+1's string */
Solomon Peachy4edaf3f2019-02-06 13:16:58 -050083const char *level_string[] = { ID2P(LANG_CHESSBOX_LEVEL_1) ,
84 ID2P(LANG_CHESSBOX_LEVEL_2) ,
85 ID2P(LANG_CHESSBOX_LEVEL_3) ,
86 ID2P(LANG_CHESSBOX_LEVEL_4) ,
87 ID2P(LANG_CHESSBOX_LEVEL_5) ,
88 ID2P(LANG_CHESSBOX_LEVEL_6) ,
89 ID2P(LANG_CHESSBOX_LEVEL_7) ,
90 ID2P(LANG_CHESSBOX_LEVEL_8) ,
91 ID2P(LANG_CHESSBOX_LEVEL_9) ,
92 ID2P(LANG_CHESSBOX_LEVEL_10) };
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +000093
Dave Chapman7ceadd72006-03-03 15:01:37 +000094/* "While thinking" command */
95int wt_command = COMMAND_NOP;
Hristo Kovachev91522722006-02-22 14:24:54 +000096
Solomon Peachy75fe78c2018-12-22 22:16:32 -050097/* System event id */
98static long cb_sysevent = 0;
99
Hristo Kovachev91522722006-02-22 14:24:54 +0000100/* ---- Get the board column and row (e2 f.e.) for a physical x y ---- */
Bertrik Sikkenba03cb42011-12-31 20:29:08 +0000101static void xy2cr ( short x, short y, short *c, short *r ) {
Dave Chapman7ceadd72006-03-03 15:01:37 +0000102 if (computer == black ) {
103 *c = x ;
104 *r = y ;
105 } else {
106 *c = 7 - x ;
107 *r = 7 - y ;
108 }
Hristo Kovachev91522722006-02-22 14:24:54 +0000109}
110
111/* ---- get physical x y for a board column and row (e2 f.e.) ---- */
Bertrik Sikkenba03cb42011-12-31 20:29:08 +0000112static void cr2xy ( short c, short r, short *x, short *y ) {
Dave Chapman7ceadd72006-03-03 15:01:37 +0000113 if ( computer == black ) {
114 *x = c ;
115 *y = r ;
116 } else {
117 *x = 7 - c ;
118 *y = 7 - r ;
119 }
Hristo Kovachev91522722006-02-22 14:24:54 +0000120}
121
122/* ---- Draw a complete board ---- */
123static void cb_drawboard (void) {
124 short r , c , x , y ;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000125 short l , piece , p_color ;
126 int b_color=1;
William Wilgus37522ec2017-01-31 01:07:47 +0100127
Dave Chapman7ceadd72006-03-03 15:01:37 +0000128 rb->lcd_clear_display();
Hristo Kovachev91522722006-02-22 14:24:54 +0000129
Dave Chapman7ceadd72006-03-03 15:01:37 +0000130 for (r = 0; r < 8; r++) {
Hristo Kovachev91522722006-02-22 14:24:54 +0000131 for (c = 0; c < 8; c++) {
132 l = locn[r][c];
133 piece = board[l] ;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000134 p_color = color[l] ;
135 cr2xy ( c , r , &x , &y );
136 if ( piece == no_piece ) {
137 rb->lcd_bitmap_part ( chessbox_pieces , 0 ,
138 TILE_HEIGHT * b_color ,
William Wilgus37522ec2017-01-31 01:07:47 +0100139 STRIDE( SCREEN_MAIN,
140 BMPWIDTH_chessbox_pieces,
Karl Kurbjun5fc5b502009-08-31 04:21:21 +0000141 BMPHEIGHT_chessbox_pieces) ,
Dave Chapman7ceadd72006-03-03 15:01:37 +0000142 XOFS + x*TILE_WIDTH ,
143 YOFS + ( 7 - y )*TILE_HEIGHT ,
144 TILE_WIDTH ,
145 TILE_HEIGHT );
146 } else {
147 rb->lcd_bitmap_part ( chessbox_pieces ,
148 0 ,
149 2 * TILE_HEIGHT +
150 4 * TILE_HEIGHT * ( piece - 1 ) +
151 2 * TILE_HEIGHT * p_color +
152 TILE_HEIGHT * b_color ,
William Wilgus37522ec2017-01-31 01:07:47 +0100153 STRIDE( SCREEN_MAIN,
154 BMPWIDTH_chessbox_pieces,
Karl Kurbjun5fc5b502009-08-31 04:21:21 +0000155 BMPHEIGHT_chessbox_pieces) ,
Dave Chapman7ceadd72006-03-03 15:01:37 +0000156 XOFS + x*TILE_WIDTH ,
157 YOFS + (7 - y)*TILE_HEIGHT ,
158 TILE_WIDTH ,
159 TILE_HEIGHT );
160 }
161 b_color = (b_color == 1) ? 0 : 1 ;
Hristo Kovachev91522722006-02-22 14:24:54 +0000162 }
Dave Chapman7ceadd72006-03-03 15:01:37 +0000163 b_color = (b_color == 1) ? 0 : 1 ;
Hristo Kovachev91522722006-02-22 14:24:54 +0000164 }
William Wilgus37522ec2017-01-31 01:07:47 +0100165
Dave Chapman7ceadd72006-03-03 15:01:37 +0000166 /* draw board limits */
Jens Arnold7b22e992006-04-15 11:27:47 +0000167#if (LCD_WIDTH > TILE_WIDTH*8) && (LCD_HEIGHT > TILE_HEIGHT*8)
168 rb->lcd_drawrect(XOFS - 1, YOFS - 1, TILE_WIDTH*8 + 2, TILE_HEIGHT*8 + 2);
169#elif LCD_WIDTH > TILE_WIDTH*8
170 rb->lcd_vline(XOFS - 1, 0, LCD_HEIGHT - 1);
171 rb->lcd_vline(XOFS + 8*TILE_WIDTH, 0, LCD_HEIGHT - 1);
172#elif LCD_HEIGHT > TILE_HEIGHT*8
173 rb->lcd_hline(0, LCD_WIDTH - 1, YOFS - 1);
174 rb->lcd_hline(0, LCD_WIDTH - 1, YOFS + TILE_HEIGHT*8);
175#endif
176
Dave Chapman7ceadd72006-03-03 15:01:37 +0000177 rb->lcd_update();
Hristo Kovachev91522722006-02-22 14:24:54 +0000178}
179
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500180static short oldx, oldy = 0;
181void cb_talk(short x, short y)
182{
183 if (x != oldx || y != oldy) {
184 short c, r;
185 short l, piece, p_color;
186
187 rb->talk_shutup();
188 cr2xy(x, y, &c, &r);
189 l = locn[r][c];
190 piece = board[l];
191 p_color = color[l];
192 if (piece != no_piece) {
193 rb->talk_id (VOICE_WHITE + p_color, true);
194 if (piece >= pawn && piece <= king) {
195 rb->talk_id (VOICE_PAWN + piece - 1, true);
196 }
197 }
198 rb->talk_id (VOICE_CHAR_A + c, true);
199 rb->talk_id (VOICE_ONE + r, true);
200 oldx = x;
201 oldy = y;
202 }
203}
204
Hristo Kovachev91522722006-02-22 14:24:54 +0000205/* ---- Switch mark on board ---- */
Bertrik Sikkenba03cb42011-12-31 20:29:08 +0000206static void cb_switch ( short x , short y ) {
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500207 if (rb->global_settings->talk_menu)
208 cb_talk(x, y);
Dave Chapman7ceadd72006-03-03 15:01:37 +0000209 rb->lcd_set_drawmode ( DRMODE_COMPLEMENT );
210 rb->lcd_drawrect ( XOFS + x*TILE_WIDTH + 1 ,
211 YOFS + ( 7 - y )*TILE_HEIGHT +1 ,
212 TILE_WIDTH-2 , TILE_HEIGHT-2 );
213 rb->lcd_update();
Jens Arnold7b22e992006-04-15 11:27:47 +0000214 rb->lcd_set_drawmode ( DRMODE_SOLID );
Dave Chapman7ceadd72006-03-03 15:01:37 +0000215}
216
217/* ---- callback for capturing interaction while thinking ---- */
Bertrik Sikkenba03cb42011-12-31 20:29:08 +0000218static void cb_wt_callback ( void ) {
Dave Chapman7ceadd72006-03-03 15:01:37 +0000219 int button = BUTTON_NONE;
William Wilgus37522ec2017-01-31 01:07:47 +0100220
Dave Chapman7ceadd72006-03-03 15:01:37 +0000221 wt_command = COMMAND_NOP;
222 button = rb->button_get(false);
223 switch (button) {
Solomon Peachy75fe78c2018-12-22 22:16:32 -0500224 case SYS_POWEROFF:
225 cb_sysevent = button;
Kevin Ferrare0e027bd2006-06-30 16:43:47 +0000226#ifdef CB_RC_QUIT
227 case CB_RC_QUIT:
Solomon Peachy75fe78c2018-12-22 22:16:32 -0500228#endif
Dave Chapman7ceadd72006-03-03 15:01:37 +0000229 wt_command = COMMAND_QUIT;
230 timeout = true;
231 break;
Marcoen Hirschberg0d02c132007-05-18 22:12:34 +0000232 case CB_MENU:
233 wt_command = COMMAND_MENU;
234 timeout = true;
235 break;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000236 case CB_PLAY:
237 wt_command = COMMAND_PLAY;
238 timeout = true;
239 break;
240 }
Hristo Kovachev91522722006-02-22 14:24:54 +0000241}
242
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000243/* ---- set playing parameters depending on level ---- */
Bertrik Sikkenba03cb42011-12-31 20:29:08 +0000244static void cb_setlevel ( int lev ) {
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000245 Level = (lev > 7) ? 7 : ( (lev < 1) ? 1 : lev ) ;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000246 switch (Level) {
247 case 1 :
248 TCmoves = 60;
249 TCminutes = 5;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000250 break;
251 case 2 :
252 TCmoves = 60;
253 TCminutes = 15;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000254 break;
255 case 3 :
256 TCmoves = 60;
257 TCminutes = 30;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000258 break;
259 case 4 :
260 TCmoves = 40;
261 TCminutes = 30;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000262 break;
263 case 5 :
264 TCmoves = 40;
265 TCminutes = 60;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000266 break;
267 case 6 :
268 TCmoves = 40;
269 TCminutes = 120;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000270 break;
271 case 7 :
272 TCmoves = 40;
273 TCminutes = 240;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000274 break;
275 case 8 :
276 TCmoves = 1;
277 TCminutes = 15;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000278 break;
279 case 9 :
280 TCmoves = 1;
281 TCminutes = 60;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000282 break;
283 case 10 :
284 TCmoves = 1;
285 TCminutes = 600;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000286 break;
287 }
Hristo Kovachev91522722006-02-22 14:24:54 +0000288 TCflag = (TCmoves > 1);
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000289 SetTimeControl();
290}
291
292/* ---- increase playing level ---- */
Bertrik Sikkenba03cb42011-12-31 20:29:08 +0000293static void cb_levelup ( void ) {
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000294 if ( Level == 7 )
295 cb_setlevel ( 1 );
296 else
297 cb_setlevel ( Level+1 );
Nils Wallménius7d4cebd2008-09-24 17:48:10 +0000298 rb->splash ( HZ/2 , level_string[Level-1] );
Hristo Kovachev91522722006-02-22 14:24:54 +0000299};
300
William Wilgus1fa7c562017-01-31 04:28:02 +0100301#ifdef CHESSBOX_SAVE_FILE_DBG
302/* Save a debug file with names, variables, and sizes */
303static void cb_saveposition_dbg ( void )
304{
305 int fd;
306 short sq,i,c;
307 unsigned short temp;
308 char buf[32]="\0";
309 int ch_ct = 0;
310
311 rb->splash ( 0 , "Saving debug" );
312 fd = rb->open(CHESSBOX_SAVE_FILE_DBG, O_WRONLY|O_CREAT, 0666);
313 ch_ct = rb->snprintf(buf,31,"computer = %d, %d bytes\n",computer+1,
314 sizeof(computer));
315 rb->write(fd, buf, ch_ct);
316 ch_ct = rb->snprintf(buf,31,"opponent = %d, %d bytes\n",opponent+1,
317 sizeof(opponent));
318 rb->write(fd, buf, ch_ct);
319 ch_ct = rb->snprintf(buf,31,"Game50 = %d, %d bytes\n",Game50,
320 sizeof(Game50));
321 rb->write(fd, buf, ch_ct);
322 ch_ct = rb->snprintf(buf,31,"CastldWht = %d, %d bytes\n",castld[white],
323 sizeof(castld[white]));
324 rb->write(fd, buf, ch_ct);
325 ch_ct = rb->snprintf(buf,31,"CastldBlk = %d, %d bytes\n",castld[black],
326 sizeof(castld[black]));
327 rb->write(fd, buf, ch_ct);
328 ch_ct = rb->snprintf(buf,31,"KngMovedWht = %d, %d bytes\n",kingmoved[white],
329 sizeof(kingmoved[white]));
330 rb->write(fd, buf, ch_ct);
331 ch_ct = rb->snprintf(buf,31,"KngMovedBlk = %d, %d bytes\n",kingmoved[black],
332 sizeof(kingmoved[black]));
333 rb->write(fd, buf, ch_ct);
334 ch_ct = rb->snprintf(buf,31,"WithBook = %d, %d bytes\n",withbook,
335 sizeof(withbook));
336 rb->write(fd, buf, ch_ct);
337 ch_ct = rb->snprintf(buf,31,"Lvl = %ld, %d bytes\n",Level,
338 sizeof(Level));
339 rb->write(fd, buf, ch_ct);
340 ch_ct = rb->snprintf(buf,31,"TCflag = %d, %d bytes\n",TCflag,
341 sizeof(TCflag));
342 rb->write(fd, buf, ch_ct);
343 ch_ct = rb->snprintf(buf,31,"OpTime = %d, %d bytes\n",OperatorTime,
344 sizeof(OperatorTime));
345 rb->write(fd, buf, ch_ct);
346 ch_ct = rb->snprintf(buf,31,"TmCtlClkWht = %ld, %d bytes\n",
347 TimeControl.clock[white], sizeof(TimeControl.clock[white]));
348 rb->write(fd, buf, ch_ct);
349 ch_ct = rb->snprintf(buf,31,"TmCtlClkBlk = %ld, %d bytes\n",
350 TimeControl.clock[black], sizeof(TimeControl.clock[black]));
351 rb->write(fd, buf, ch_ct);
352 ch_ct = rb->snprintf(buf,31,"TmCtlMovesWht = %d, %d bytes\n",
353 TimeControl.moves[white], sizeof(TimeControl.moves[white]));
354 rb->write(fd, buf, ch_ct);
355 ch_ct = rb->snprintf(buf,31,"TmCtlMovesBlk = %d, %d bytes\n",
356 TimeControl.moves[black], sizeof(TimeControl.moves[black]));
357 rb->write(fd, buf, ch_ct);
358 for (sq = 0; sq < 64; sq++) {
359 if (color[sq] == neutral) c = 0; else c = color[sq]+1;
360 temp = 256*board[sq] + c ;
361 ch_ct = rb->snprintf(buf,31,"sq %02d = %d, %d bytes\n",sq, temp,
362 sizeof(temp));
363 rb->write(fd, buf, ch_ct);
364 }
Solomon Peachy55729042019-07-15 10:49:55 -0400365 for (i = 0; i < ((GameCnt + 1) & 0xFF); i++) {
William Wilgus1fa7c562017-01-31 04:28:02 +0100366 ch_ct = rb->snprintf(buf,31,"GameCt %d, %d bytes\n",i,
367 sizeof(GameCnt));
368 rb->write(fd, buf, ch_ct);
369 if (GameList[i].color == neutral)
370 {
371 c = 0;
372 ch_ct = rb->snprintf(buf,31,"color = %d, %d bytes\n",c,
373 sizeof(c));
374 rb->write(fd, buf, ch_ct);
375 }
376 else
377 c = GameList[i].color + 1;
378 ch_ct = rb->snprintf(buf,31,"gmove = %d, %d bytes\n",GameList[i].gmove,
379 sizeof(GameList[i].gmove));
380 rb->write(fd, buf, ch_ct);
381 ch_ct = rb->snprintf(buf,31,"score = %d, %d bytes\n",GameList[i].score,
382 sizeof(GameList[i].score));
383 rb->write(fd, buf, ch_ct);
384 ch_ct = rb->snprintf(buf,31,"depth = %d, %d bytes\n",GameList[i].depth,
385 sizeof(GameList[i].depth));
386 rb->write(fd, buf, ch_ct);
387 ch_ct = rb->snprintf(buf,31,"nodes = %ld, %d bytes\n",GameList[i].nodes,
388 sizeof(GameList[i].nodes));
389 rb->write(fd, buf, ch_ct);
390 ch_ct = rb->snprintf(buf,31,"time = %d, %d bytes\n",GameList[i].time,
391 sizeof(GameList[i].time));
392 rb->write(fd, buf, ch_ct);
393 ch_ct = rb->snprintf(buf,31,"piece = %d, %d bytes\n",GameList[i].piece,
394 sizeof(GameList[i].piece));
395 rb->write(fd, buf, ch_ct);
396 ch_ct = rb->snprintf(buf,31,"color = %d, %d bytes\n",c,sizeof(c));
397 rb->write(fd, buf, ch_ct);
398 }
399 rb->close(fd);
400
401}
402#endif
403
Solomon Peachy55729042019-07-15 10:49:55 -0400404/* ---- Save current position and game history ---- */
405static void cb_saveposition ( struct pgn_game_node* game ) {
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000406 int fd;
407 short sq,i,c;
408 unsigned short temp;
Solomon Peachy55729042019-07-15 10:49:55 -0400409 struct pgn_ply_node *ply;
410 char buf[4];
411
William Wilgus1fa7c562017-01-31 04:28:02 +0100412#ifdef CHESSBOX_SAVE_FILE_DBG
413 cb_saveposition_dbg();
414#endif
Solomon Peachy55729042019-07-15 10:49:55 -0400415
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500416 rb->splash ( 0 , ID2P(LANG_CHESSBOX_SAVING_POSITION) );
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000417
Solomon Peachy55729042019-07-15 10:49:55 -0400418 fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666);
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000419
420 computer++; rb->write(fd, &(computer), sizeof(computer)); computer--;
421 opponent++; rb->write(fd, &(opponent), sizeof(opponent)); opponent--;
422 rb->write(fd, &(Game50), sizeof(Game50));
423
424 rb->write(fd, &(castld[white]), sizeof(castld[white]));
425 rb->write(fd, &(castld[black]), sizeof(castld[black]));
426 rb->write(fd, &(kingmoved[white]), sizeof(kingmoved[white]));
427 rb->write(fd, &(kingmoved[black]), sizeof(kingmoved[black]));
428
Jens Arnold7b22e992006-04-15 11:27:47 +0000429 rb->write(fd, &(withbook), sizeof(withbook));
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000430 rb->write(fd, &(Level), sizeof(Level));
431 rb->write(fd, &(TCflag), sizeof(TCflag));
432 rb->write(fd, &(OperatorTime), sizeof(OperatorTime));
433
434 rb->write(fd, &(TimeControl.clock[white]),
435 sizeof(TimeControl.clock[white]) );
436 rb->write(fd, &(TimeControl.clock[black]),
437 sizeof(TimeControl.clock[black]) );
438 rb->write(fd, &(TimeControl.moves[white]),
439 sizeof(TimeControl.moves[white]) );
440 rb->write(fd, &(TimeControl.moves[black]),
441 sizeof(TimeControl.moves[black]) );
442 for (sq = 0; sq < 64; sq++) {
443 if (color[sq] == neutral) c = 0; else c = color[sq]+1;
444 temp = 256*board[sq] + c ;
445 rb->write(fd, &(temp), sizeof(temp));
446 }
Solomon Peachy55729042019-07-15 10:49:55 -0400447 c = GameCnt;
448 rb->write(fd, &(c), sizeof(c));
449 for (i = 0; i < ((GameCnt + 1) & 0xFF); i++) {
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000450 if (GameList[i].color == neutral)
451 c = 0;
452 else
453 c = GameList[i].color + 1;
454 rb->write(fd, &(GameList[i].gmove), sizeof(GameList[i].gmove));
455 rb->write(fd, &(GameList[i].score), sizeof(GameList[i].score));
456 rb->write(fd, &(GameList[i].depth), sizeof(GameList[i].depth));
457 rb->write(fd, &(GameList[i].nodes), sizeof(GameList[i].nodes));
458 rb->write(fd, &(GameList[i].time), sizeof(GameList[i].time));
459 rb->write(fd, &(GameList[i].piece), sizeof(GameList[i].piece));
460 rb->write(fd, &(c), sizeof(c));
461 }
Solomon Peachy55729042019-07-15 10:49:55 -0400462 for (ply=game->first_ply; ply!=NULL; ply=ply->next_node) {
463 buf[0] = ply->column_from + 'a';
464 buf[1] = ply->row_from + '1';
465 buf[2] = ply->column_to + 'a';
466 buf[3] = ply->row_to + '1';
467 rb->write(fd, buf, 4);
468 }
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000469 rb->close(fd);
470}
471
Solomon Peachy55729042019-07-15 10:49:55 -0400472/* ---- Restore saved position and game history ---- */
473static struct pgn_game_node* cb_restoreposition ( void ) {
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000474 int fd;
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000475 short sq;
476 unsigned short m;
Solomon Peachy55729042019-07-15 10:49:55 -0400477 short n;
478 char buf[4];
479 struct pgn_game_node* game = pgn_init_game();
William Wilgus37522ec2017-01-31 01:07:47 +0100480
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000481 if ( (fd = rb->open(SAVE_FILE, O_RDONLY)) >= 0 ) {
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500482 rb->splash ( 0 , ID2P(LANG_CHESSBOX_LOADING_POSITION) );
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000483 rb->read(fd, &(computer), sizeof(computer));
484 rb->read(fd, &(opponent), sizeof(opponent));
485 rb->read(fd, &(Game50), sizeof(Game50));
486
487 rb->read(fd, &(castld[white]), sizeof(castld[white]));
488 rb->read(fd, &(castld[black]), sizeof(castld[black]));
489 rb->read(fd, &(kingmoved[white]), sizeof(kingmoved[white]));
490 rb->read(fd, &(kingmoved[black]), sizeof(kingmoved[black]));
491
Jens Arnold7b22e992006-04-15 11:27:47 +0000492 rb->read(fd, &(withbook), sizeof(withbook));
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000493 rb->read(fd, &(Level), sizeof(Level));
494 rb->read(fd, &(TCflag), sizeof(TCflag));
495 rb->read(fd, &(OperatorTime), sizeof(OperatorTime));
496
497 rb->read(fd, &(TimeControl.clock[white]),
498 sizeof(TimeControl.clock[white]));
499 rb->read(fd, &(TimeControl.clock[black]),
500 sizeof(TimeControl.clock[black]));
501 rb->read(fd, &(TimeControl.moves[white]),
502 sizeof(TimeControl.moves[white]));
503 rb->read(fd, &(TimeControl.moves[black]),
504 sizeof(TimeControl.moves[black]));
505 for (sq = 0; sq < 64; sq++) {
506 rb->read(fd, &(m), sizeof(m));
507 board[sq] = (m >> 8); color[sq] = (m & 0xFF);
508 if (color[sq] == 0)
509 color[sq] = neutral;
510 else
511 --color[sq];
512 }
Solomon Peachy55729042019-07-15 10:49:55 -0400513 rb->read(fd, &(n), sizeof(n));
514 n++;
515 n &= 0xFF;
516 for (GameCnt = 0; GameCnt < n; GameCnt++) {
517 rb->read(fd, &(GameList[GameCnt].gmove),
518 sizeof(GameList[GameCnt].gmove));
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000519 rb->read(fd, &(GameList[GameCnt].score),
520 sizeof(GameList[GameCnt].score));
521 rb->read(fd, &(GameList[GameCnt].depth),
522 sizeof(GameList[GameCnt].depth));
523 rb->read(fd, &(GameList[GameCnt].nodes),
524 sizeof(GameList[GameCnt].nodes));
525 rb->read(fd, &(GameList[GameCnt].time),
526 sizeof(GameList[GameCnt].time));
527 rb->read(fd, &(GameList[GameCnt].piece),
528 sizeof(GameList[GameCnt].piece));
529 rb->read(fd, &(GameList[GameCnt].color),
Solomon Peachy55729042019-07-15 10:49:55 -0400530 sizeof(GameList[GameCnt].color));
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000531 if (GameList[GameCnt].color == 0)
532 GameList[GameCnt].color = neutral;
533 else
534 --GameList[GameCnt].color;
535 }
536 GameCnt--;
537 if (TimeControl.clock[white] > 0)
538 TCflag = true;
539 computer--; opponent--;
Solomon Peachy55729042019-07-15 10:49:55 -0400540 n = 0;
541 while (rb->read(fd, buf, 4) > 0)
542 pgn_append_ply(game, ((n++) & 1) ? black : white, buf, false);
543 rb->close(fd);
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000544 }
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000545 cb_setlevel(Level);
546 InitializeStats();
547 Sdepth = 0;
Solomon Peachy55729042019-07-15 10:49:55 -0400548
549 return game;
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000550}
551
Nils Wallménius3e190c82007-05-29 16:33:16 +0000552/* ---- show menu in viewer mode---- */
553static int cb_menu_viewer(void)
554{
555 int selection;
William Wilgus37522ec2017-01-31 01:07:47 +0100556
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500557 MENUITEM_STRINGLIST(menu,"Chessbox Menu",NULL,
558 ID2P(LANG_CHESSBOX_MENU_RESTART_GAME),
559 ID2P(LANG_CHESSBOX_MENU_SELECT_OTHER_GAME),
Solomon Peachy55729042019-07-15 10:49:55 -0400560 ID2P(LANG_CHESSBOX_MENU_RESUME_GAME),
561 ID2P(LANG_RETURN),
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500562 ID2P(LANG_MENU_QUIT));
William Wilgus37522ec2017-01-31 01:07:47 +0100563
Solomon Peachy55729042019-07-15 10:49:55 -0400564 switch(rb->do_menu(&menu, &selection, NULL, false))
Nils Wallménius3e190c82007-05-29 16:33:16 +0000565 {
Solomon Peachy55729042019-07-15 10:49:55 -0400566 case 0:
567 return COMMAND_RESTART;
568 case 1:
569 return COMMAND_SELECT;
570 case 3:
571 return COMMAND_RETURN;
572 case 4:
573 return COMMAND_QUIT;
Nils Wallménius3e190c82007-05-29 16:33:16 +0000574 }
Solomon Peachy55729042019-07-15 10:49:55 -0400575 return COMMAND_RESUME;
Nils Wallménius3e190c82007-05-29 16:33:16 +0000576}
577
Solomon Peachy55729042019-07-15 10:49:55 -0400578/* ---- get a command in viewer mode ---- */
Bertrik Sikkenba03cb42011-12-31 20:29:08 +0000579static struct cb_command cb_get_viewer_command (void) {
Nils Wallménius3e190c82007-05-29 16:33:16 +0000580 int button;
581 struct cb_command result = { 0, {0,0,0,0,0}, 0 };
William Wilgus37522ec2017-01-31 01:07:47 +0100582
Nils Wallménius3e190c82007-05-29 16:33:16 +0000583 /* main loop */
584 while ( true ) {
585 button = rb->button_get(true);
586 switch (button) {
Solomon Peachy75fe78c2018-12-22 22:16:32 -0500587 case SYS_POWEROFF:
588 cb_sysevent = button;
Nils Wallménius3e190c82007-05-29 16:33:16 +0000589#ifdef CB_RC_QUIT
590 case CB_RC_QUIT:
Solomon Peachy75fe78c2018-12-22 22:16:32 -0500591#endif
Nils Wallménius3e190c82007-05-29 16:33:16 +0000592 result.type = COMMAND_QUIT;
593 return result;
Sebastian Leonhardtf01fb3c2015-04-23 00:07:27 +0200594#ifdef CB_RESTART
595 case CB_RESTART:
596 result.type = COMMAND_RESTART;
597 return result;
598#endif
Nils Wallménius3e190c82007-05-29 16:33:16 +0000599 case CB_MENU:
600 result.type = cb_menu_viewer();
601 return result;
602 case CB_LEFT:
603 result.type = COMMAND_PREV;
604 return result;
605 case CB_RIGHT:
606 result.type = COMMAND_NEXT;
607 return result;
608 }
609 }
610
611}
612
613/* ---- viewer main loop ---- */
Solomon Peachy55729042019-07-15 10:49:55 -0400614static bool cb_start_viewer(const char* filename){
Nils Wallménius3e190c82007-05-29 16:33:16 +0000615 struct pgn_game_node *first_game, *selected_game;
616 struct pgn_ply_node *curr_ply;
617 bool exit_game = false;
618 bool exit_viewer = false;
Solomon Peachy55729042019-07-15 10:49:55 -0400619 bool exit_app = false;
Nils Wallménius3e190c82007-05-29 16:33:16 +0000620 struct cb_command command;
621
Andrew Mahone23d98122009-01-16 10:34:40 +0000622 first_game = pgn_list_games(filename);
Nils Wallménius3e190c82007-05-29 16:33:16 +0000623 if (first_game == NULL){
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500624 rb->splash ( HZ*2 , ID2P(LANG_CHESSBOX_NO_GAMES) );
Solomon Peachy55729042019-07-15 10:49:55 -0400625 return exit_app;
Nils Wallménius3e190c82007-05-29 16:33:16 +0000626 }
627
628 do {
Andrew Mahone23d98122009-01-16 10:34:40 +0000629 selected_game = pgn_show_game_list(first_game);
Nils Wallménius3e190c82007-05-29 16:33:16 +0000630 if (selected_game == NULL){
631 break;
632 }
633
Andrew Mahone23d98122009-01-16 10:34:40 +0000634 pgn_parse_game(filename, selected_game);
Nils Wallménius3e190c82007-05-29 16:33:16 +0000635 if (selected_game->first_ply != NULL) {
636
637 /* init board */
638 GNUChess_Initialize();
William Wilgus37522ec2017-01-31 01:07:47 +0100639
Nils Wallménius3e190c82007-05-29 16:33:16 +0000640 /* draw the board */
641 cb_drawboard();
642
643 curr_ply = selected_game->first_ply;
644 exit_game = false;
645
646 do {
647 command = cb_get_viewer_command ();
648 switch (command.type) {
649 case COMMAND_PREV:
650 /* unapply the previous ply */
651 if (curr_ply->prev_node != NULL){
652 curr_ply = curr_ply->prev_node;
653 } else {
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500654 rb->splash ( HZ*2 , ID2P(LANG_CHESSBOX_GAME_BEGINNING) );
Nils Wallménius3e190c82007-05-29 16:33:16 +0000655 break;
656 }
William Wilgus37522ec2017-01-31 01:07:47 +0100657 board[locn[curr_ply->row_from][curr_ply->column_from]]
Nils Wallménius3e190c82007-05-29 16:33:16 +0000658 = board[locn[curr_ply->row_to][curr_ply->column_to]];
659 color[locn[curr_ply->row_from][curr_ply->column_from]]
660 = color[locn[curr_ply->row_to][curr_ply->column_to]];
661 board[locn[curr_ply->row_to][curr_ply->column_to]] = no_piece;
662 color[locn[curr_ply->row_to][curr_ply->column_to]] = neutral;
663 if (curr_ply->taken_piece != no_piece && !curr_ply->enpassant){
664 board[locn[curr_ply->row_to][curr_ply->column_to]]
665 = curr_ply->taken_piece;
666 color[locn[curr_ply->row_to][curr_ply->column_to]]
667 = ((curr_ply->player==white)?black:white);
668 }
669 if (curr_ply->castle){
670 if (curr_ply->column_to == 6){
671 /* castling kingside */
672 board[locn[curr_ply->row_to][7]] = rook;
673 color[locn[curr_ply->row_to][7]] = curr_ply->player;
674 board[locn[curr_ply->row_to][5]] = no_piece;
675 color[locn[curr_ply->row_to][5]] = neutral;
676 } else {
677 /* castling queenside */
678 board[locn[curr_ply->row_to][0]] = rook;
679 color[locn[curr_ply->row_to][0]] = curr_ply->player;
680 board[locn[curr_ply->row_to][3]] = no_piece;
681 color[locn[curr_ply->row_to][3]] = neutral;
682 }
683 }
684 if (curr_ply->enpassant){
685 board[locn[curr_ply->row_from][curr_ply->column_to]] = pawn;
686 color[locn[curr_ply->row_from][curr_ply->column_to]]
687 = ((curr_ply->player==white)?black:white);
688 }
689 if (curr_ply->promotion){
690 board[locn[curr_ply->row_from][curr_ply->column_from]] = pawn;
691 color[locn[curr_ply->row_from][curr_ply->column_from]]
692 = curr_ply->player;
693 }
694
695 cb_drawboard();
696 break;
697 case COMMAND_NEXT:
698 /* apply the current move */
699 if (curr_ply->player == neutral){
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500700 rb->splash ( HZ*2 , ID2P(LANG_CHESSBOX_GAME_END) );
Nils Wallménius3e190c82007-05-29 16:33:16 +0000701 break;
702 }
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500703 if (rb->global_settings->talk_menu) {
704 rb->talk_id (VOICE_WHITE + curr_ply->player, false);
705 if (curr_ply->castle){
706 rb->talk_id (VOICE_CHESSBOX_CASTLE, true);
707 if (curr_ply->column_to == 6){
708 rb->talk_id (VOICE_CHESSBOX_KINGSIDE, true);
709 } else {
710 rb->talk_id (VOICE_CHESSBOX_QUEENSIDE, true);
711 }
712 } else {
713 rb->talk_id (VOICE_PAWN +
714 board[locn[curr_ply->row_from]
715 [curr_ply->column_from]]
716 - 1, true);
717 rb->talk_id (VOICE_CHAR_A + curr_ply->column_from,
718 true);
719 rb->talk_id (VOICE_ONE + curr_ply->row_from, true);
720 if (board[locn[curr_ply->row_to]
721 [curr_ply->column_to]] != no_piece) {
722 rb->talk_id (VOICE_CHESSBOX_CAPTURES, true);
723 rb->talk_id (VOICE_PAWN +
724 board[locn[curr_ply->row_to]
725 [curr_ply->column_to]]
726 - 1, true);
727 }
728 rb->talk_id (VOICE_CHAR_A + curr_ply->column_to,
729 true);
730 rb->talk_id (VOICE_ONE + curr_ply->row_to, true);
731 }
732 }
Nils Wallménius3e190c82007-05-29 16:33:16 +0000733 board[locn[curr_ply->row_to][curr_ply->column_to]]
734 = board[locn[curr_ply->row_from][curr_ply->column_from]];
735 color[locn[curr_ply->row_to][curr_ply->column_to]]
736 = color[locn[curr_ply->row_from][curr_ply->column_from]];
737 board[locn[curr_ply->row_from][curr_ply->column_from]] = no_piece;
738 color[locn[curr_ply->row_from][curr_ply->column_from]] = neutral;
739 if (curr_ply->castle){
740 if (curr_ply->column_to == 6){
741 /* castling kingside */
742 board[locn[curr_ply->row_to][5]] = rook;
743 color[locn[curr_ply->row_to][5]] = curr_ply->player;
744 board[locn[curr_ply->row_to][7]] = no_piece;
745 color[locn[curr_ply->row_to][7]] = neutral;
746 } else {
747 /* castling queenside */
748 board[locn[curr_ply->row_to][3]] = rook;
749 color[locn[curr_ply->row_to][3]] = curr_ply->player;
750 board[locn[curr_ply->row_to][0]] = no_piece;
751 color[locn[curr_ply->row_to][0]] = neutral;
752 }
753 }
754 if (curr_ply->enpassant){
755 board[locn[curr_ply->row_from][curr_ply->column_to]] = no_piece;
756 color[locn[curr_ply->row_from][curr_ply->column_to]] = neutral;
757 }
758 if (curr_ply->promotion){
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500759 if (rb->global_settings->talk_menu)
760 rb->talk_id (VOICE_PAWN +
761 curr_ply->promotion_piece - 1,
762 true);
Nils Wallménius3e190c82007-05-29 16:33:16 +0000763 board[locn[curr_ply->row_to][curr_ply->column_to]]
764 = curr_ply->promotion_piece;
765 color[locn[curr_ply->row_to][curr_ply->column_to]]
766 = curr_ply->player;
767 }
768 if (curr_ply->next_node != NULL){
769 curr_ply = curr_ply->next_node;
770 }
771 cb_drawboard();
772 break;
773 case COMMAND_RESTART:
774 GNUChess_Initialize();
775 cb_drawboard();
776 curr_ply = selected_game->first_ply;
Sebastian Leonhardtf01fb3c2015-04-23 00:07:27 +0200777 break;
Nils Wallménius3e190c82007-05-29 16:33:16 +0000778 case COMMAND_SELECT:
779 exit_game = true;
780 break;
781 case COMMAND_QUIT:
Solomon Peachy55729042019-07-15 10:49:55 -0400782 exit_app = true;
783 case COMMAND_RETURN:
Nils Wallménius3e190c82007-05-29 16:33:16 +0000784 exit_viewer = true;
785 break;
786 }
787 } while (!exit_game && !exit_viewer);
788 } else {
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500789 rb->splash ( HZ*2 , ID2P(LANG_CHESSBOX_PGN_PARSE_ERROR));
Nils Wallménius3e190c82007-05-29 16:33:16 +0000790 }
791 } while (!exit_viewer);
Solomon Peachy55729042019-07-15 10:49:55 -0400792 return exit_app;
Nils Wallménius3e190c82007-05-29 16:33:16 +0000793}
794
Marcoen Hirschberg0d02c132007-05-18 22:12:34 +0000795/* ---- show menu ---- */
796static int cb_menu(void)
797{
798 int selection;
William Wilgus37522ec2017-01-31 01:07:47 +0100799
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500800 MENUITEM_STRINGLIST(menu,"Chessbox Menu",NULL,
801 ID2P(LANG_CHESSBOX_MENU_NEW_GAME),
802 ID2P(LANG_CHESSBOX_MENU_RESUME_GAME),
803 ID2P(LANG_CHESSBOX_MENU_SAVE_GAME),
804 ID2P(LANG_CHESSBOX_MENU_RESTORE_GAME),
Solomon Peachy55729042019-07-15 10:49:55 -0400805 ID2P(LANG_CHESSBOX_MENU_VIEW_GAMES),
Thomas Martitzb0232e02009-02-26 21:24:29 +0000806#ifdef HAVE_PLAYBACK_CONTROL
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500807 ID2P(LANG_PLAYBACK_CONTROL),
Thomas Martitzbb45f0e2009-02-26 17:46:01 +0000808#endif
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500809 ID2P(LANG_MENU_QUIT));
William Wilgus37522ec2017-01-31 01:07:47 +0100810
Solomon Peachy55729042019-07-15 10:49:55 -0400811 switch(rb->do_menu(&menu, &selection, NULL, false))
Marcoen Hirschberg0d02c132007-05-18 22:12:34 +0000812 {
Solomon Peachy55729042019-07-15 10:49:55 -0400813 case 0:
814 return COMMAND_RESTART;
815 case 2:
816 return COMMAND_SAVE;
817 case 3:
818 return COMMAND_RESTORE;
819 case 4:
820 return COMMAND_VIEW;
821 case 5:
Thomas Martitzb0232e02009-02-26 21:24:29 +0000822#ifdef HAVE_PLAYBACK_CONTROL
Solomon Peachy55729042019-07-15 10:49:55 -0400823 playback_control(NULL);
824 break;
825 case 6:
Thomas Martitzbb45f0e2009-02-26 17:46:01 +0000826#endif
Solomon Peachy55729042019-07-15 10:49:55 -0400827 return COMMAND_QUIT;
Marcoen Hirschberg0d02c132007-05-18 22:12:34 +0000828 }
Solomon Peachy55729042019-07-15 10:49:55 -0400829 return COMMAND_RESUME;
Marcoen Hirschberg0d02c132007-05-18 22:12:34 +0000830}
831
Nils Wallménius3e190c82007-05-29 16:33:16 +0000832/* ---- get a command in game mode ---- */
Bertrik Sikkenba03cb42011-12-31 20:29:08 +0000833static struct cb_command cb_getcommand (void) {
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +0000834 static short x = 4 , y = 3 ;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000835 short c , r , l;
Andree Buschmann27d153d2011-05-01 14:44:20 +0000836 int button;
837#if defined(CB_PLAY_PRE) || defined(CB_SELECT_PRE)
838 int lastbutton = BUTTON_NONE;
839#endif
Dave Chapman7ceadd72006-03-03 15:01:37 +0000840 int marked = false , from_marked = false ;
841 short marked_x = 0 , marked_y = 0 ;
842 struct cb_command result = { 0, {0,0,0,0,0}, 0 };
William Wilgus37522ec2017-01-31 01:07:47 +0100843
Dave Chapman7ceadd72006-03-03 15:01:37 +0000844 cb_switch ( x , y );
845 /* main loop */
846 while ( true ) {
847 button = rb->button_get(true);
848 switch (button) {
Solomon Peachy75fe78c2018-12-22 22:16:32 -0500849 case SYS_POWEROFF:
850 cb_sysevent = button;
Kevin Ferrare0e027bd2006-06-30 16:43:47 +0000851#ifdef CB_RC_QUIT
852 case CB_RC_QUIT:
Solomon Peachy75fe78c2018-12-22 22:16:32 -0500853#endif
Dave Chapman7ceadd72006-03-03 15:01:37 +0000854 result.type = COMMAND_QUIT;
855 return result;
Sebastian Leonhardtf01fb3c2015-04-23 00:07:27 +0200856#ifdef CB_RESTART
857 case CB_RESTART:
858 result.type = COMMAND_RESTART;
859 return result;
860#endif
Marcoen Hirschberg0d02c132007-05-18 22:12:34 +0000861 case CB_MENU:
862 result.type = cb_menu();
863 return result;
Dave Chapman7ceadd72006-03-03 15:01:37 +0000864 case CB_LEVEL:
865 result.type = COMMAND_LEVEL;
866 return result;
867 case CB_PLAY:
Jens Arnold40d99f42006-02-24 00:51:37 +0000868#ifdef CB_PLAY_PRE
869 if (lastbutton != CB_PLAY_PRE)
870 break;
Sebastian Leonhardta507bb22015-07-20 01:50:26 +0200871 /* fallthrough */
872#endif
873#ifdef CB_PLAY_ALT
874 case CB_PLAY_ALT:
Jens Arnold40d99f42006-02-24 00:51:37 +0000875#endif
Dave Chapman7ceadd72006-03-03 15:01:37 +0000876 result.type = COMMAND_PLAY;
877 return result;
878 case CB_UP:
Sebastian Leonhardtf01fb3c2015-04-23 00:07:27 +0200879#ifdef CB_SCROLL_UP
880 case CB_SCROLL_UP:
881#endif
Dave Chapman7ceadd72006-03-03 15:01:37 +0000882 if ( !from_marked ) cb_switch ( x , y );
883 y++;
884 if ( y == 8 ) {
885 y = 0;
886 x--;
887 if ( x < 0 ) x = 7;
888 }
889 if ( marked && ( marked_x == x ) && ( marked_y == y ) ) {
890 from_marked = true ;
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500891 if (rb->global_settings->talk_menu) {
892 cb_talk(x, y);
893 rb->talk_id(VOICE_MARKED, true);
894 }
Dave Chapman7ceadd72006-03-03 15:01:37 +0000895 } else {
896 from_marked = false ;
897 cb_switch ( x , y );
898 }
899 break;
900 case CB_DOWN:
Sebastian Leonhardtf01fb3c2015-04-23 00:07:27 +0200901#ifdef CB_SCROLL_DOWN
902 case CB_SCROLL_DOWN:
903#endif
Dave Chapman7ceadd72006-03-03 15:01:37 +0000904 if ( !from_marked ) cb_switch ( x , y );
905 y--;
906 if ( y < 0 ) {
907 y = 7;
908 x++;
909 if ( x == 8 ) x = 0;
910 }
911 if ( marked && ( marked_x == x ) && ( marked_y == y ) ) {
912 from_marked = true ;
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500913 if (rb->global_settings->talk_menu) {
914 cb_talk(x, y);
915 rb->talk_id(VOICE_MARKED, true);
916 }
Dave Chapman7ceadd72006-03-03 15:01:37 +0000917 } else {
918 from_marked = false ;
919 cb_switch ( x , y );
920 }
921 break;
922 case CB_LEFT:
Sebastian Leonhardtf01fb3c2015-04-23 00:07:27 +0200923#ifdef CB_SCROLL_LEFT
924 case CB_SCROLL_LEFT:
925#endif
Dave Chapman7ceadd72006-03-03 15:01:37 +0000926 if ( !from_marked ) cb_switch ( x , y );
927 x--;
928 if ( x < 0 ) {
929 x = 7;
930 y++;
931 if ( y == 8 ) y = 0;
932 }
933 if ( marked && ( marked_x == x ) && ( marked_y == y ) ) {
934 from_marked = true ;
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500935 if (rb->global_settings->talk_menu) {
936 cb_talk(x, y);
937 rb->talk_id(VOICE_MARKED, true);
938 }
Dave Chapman7ceadd72006-03-03 15:01:37 +0000939 } else {
940 from_marked = false ;
941 cb_switch ( x , y );
942 }
943 break;
944 case CB_RIGHT:
Sebastian Leonhardtf01fb3c2015-04-23 00:07:27 +0200945#ifdef CB_SCROLL_RIGHT
946 case CB_SCROLL_RIGHT:
947#endif
Dave Chapman7ceadd72006-03-03 15:01:37 +0000948 if ( !from_marked ) cb_switch ( x , y );
949 x++;
950 if ( x == 8 ) {
951 x = 0;
952 y--;
953 if ( y < 0 ) y = 7;
954 }
955 if ( marked && ( marked_x == x ) && ( marked_y == y ) ) {
956 from_marked = true ;
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500957 if (rb->global_settings->talk_menu) {
958 cb_talk(x, y);
959 rb->talk_id(VOICE_MARKED, true);
960 }
Dave Chapman7ceadd72006-03-03 15:01:37 +0000961 } else {
962 from_marked = false ;
963 cb_switch ( x , y );
964 }
965 break;
966 case CB_SELECT:
Jens Arnold40d99f42006-02-24 00:51:37 +0000967#ifdef CB_SELECT_PRE
968 if (lastbutton != CB_SELECT_PRE)
969 break;
970#endif
Dave Chapman7ceadd72006-03-03 15:01:37 +0000971 if ( !marked ) {
972 xy2cr ( x , y , &c , &r );
Hristo Kovachev91522722006-02-22 14:24:54 +0000973 l = locn[r][c];
974 if ( ( color[l]!=computer ) && ( board[l]!=no_piece ) ) {
Dave Chapman7ceadd72006-03-03 15:01:37 +0000975 marked = true;
976 from_marked = true ;
977 marked_x = x;
978 marked_y = y;
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500979 if (rb->global_settings->talk_menu)
980 rb->talk_id(VOICE_MARKED, false);
Dave Chapman7ceadd72006-03-03 15:01:37 +0000981 }
982 } else {
983 if ( ( marked_x == x ) && ( marked_y == y ) ) {
984 marked = false;
985 from_marked = false;
Solomon Peachy4edaf3f2019-02-06 13:16:58 -0500986 if (rb->global_settings->talk_menu)
987 rb->talk_id(VOICE_UNMARKED, false);
Dave Chapman7ceadd72006-03-03 15:01:37 +0000988 } else {
989 xy2cr ( marked_x , marked_y , &c , &r );
990 result.mv_s[0] = 'a' + c;
991 result.mv_s[1] = '1' + r;
992 xy2cr ( x , y , &c , &r );
993 result.mv_s[2] = 'a' + c;
994 result.mv_s[3] = '1' + r;
995 result.mv_s[4] = '\00';
996 result.type = COMMAND_MOVE;
997 return result;
998 }
999 }
1000 break;
1001 }
Andree Buschmann27d153d2011-05-01 14:44:20 +00001002#if defined(CB_PLAY_PRE) || defined(CB_SELECT_PRE)
Dave Chapman7ceadd72006-03-03 15:01:37 +00001003 if (button != BUTTON_NONE)
Jens Arnold40d99f42006-02-24 00:51:37 +00001004 lastbutton = button;
Andree Buschmann27d153d2011-05-01 14:44:20 +00001005#endif
Dave Chapman7ceadd72006-03-03 15:01:37 +00001006 }
Hristo Kovachev91522722006-02-22 14:24:54 +00001007
1008}
1009
Solomon Peachy4edaf3f2019-02-06 13:16:58 -05001010/* Talk a move */
1011static void talk_move(char *move_buffer)
1012{
1013 if (rb->global_settings->talk_menu) {
1014 rb->talk_id (VOICE_PAWN +
1015 board[locn[move_buffer[3]-'1'][move_buffer[2]-'a']] - 1,
1016 false);
1017 rb->talk_id(VOICE_CHAR_A + move_buffer[0] - 'a', true);
1018 rb->talk_id(VOICE_ONE + move_buffer[1] - '1', true);
1019 rb->talk_id(VOICE_CHAR_A + move_buffer[2] - 'a', true);
1020 rb->talk_id(VOICE_ONE + move_buffer[3] - '1', true);
1021 if (move_buffer[4] == '+' && !mate) {
1022 rb->talk_id(VOICE_CHESSBOX_CHECK, true);
1023 }
1024 }
1025}
1026
Nils Wallménius3e190c82007-05-29 16:33:16 +00001027/* ---- game main loop ---- */
Bertrik Sikkenba03cb42011-12-31 20:29:08 +00001028static void cb_play_game(void) {
Dave Chapman7ceadd72006-03-03 15:01:37 +00001029 struct cb_command command;
Nils Wallménius5ccf1802007-09-02 10:11:46 +00001030 struct pgn_game_node *game;
1031 char move_buffer[20];
Nils Wallménius3e190c82007-05-29 16:33:16 +00001032
Dave Chapman7ceadd72006-03-03 15:01:37 +00001033 /* init status */
1034 bool exit = false;
Hristo Kovachev91522722006-02-22 14:24:54 +00001035
Dave Chapman7ceadd72006-03-03 15:01:37 +00001036 /* load opening book, soon */
Karl Kurbjund6b0c972006-11-15 06:14:27 +00001037
Dave Chapman7ceadd72006-03-03 15:01:37 +00001038 /* init board */
1039 GNUChess_Initialize();
Nils Wallménius5ccf1802007-09-02 10:11:46 +00001040
Marcoen Hirschberg789e01b2006-03-14 20:55:59 +00001041 /* restore saved position, if saved */
Solomon Peachy55729042019-07-15 10:49:55 -04001042 game = cb_restoreposition();
William Wilgus37522ec2017-01-31 01:07:47 +01001043
Dave Chapman7ceadd72006-03-03 15:01:37 +00001044 /* draw the board */
1045 /* I don't like configscreens, start game inmediatly */
1046 cb_drawboard();
Nils Wallménius3e190c82007-05-29 16:33:16 +00001047
Dave Chapman7ceadd72006-03-03 15:01:37 +00001048 while (!exit) {
1049 if ( mate ) {
Solomon Peachy4edaf3f2019-02-06 13:16:58 -05001050 rb->talk_force_enqueue_next();
1051 rb->splash ( HZ*3 , ID2P(LANG_CHESSBOX_CHECKMATE) );
Dave Chapman7ceadd72006-03-03 15:01:37 +00001052 rb->button_get(true);
Andrew Mahone23d98122009-01-16 10:34:40 +00001053 pgn_store_game(game);
Dave Chapman7ceadd72006-03-03 15:01:37 +00001054 GNUChess_Initialize();
Andrew Mahone23d98122009-01-16 10:34:40 +00001055 game = pgn_init_game();
Dave Chapman7ceadd72006-03-03 15:01:37 +00001056 cb_drawboard();
1057 }
1058 command = cb_getcommand ();
1059 switch (command.type) {
1060 case COMMAND_MOVE:
Nils Wallménius5ccf1802007-09-02 10:11:46 +00001061 if ( ! VerifyMove (opponent, command.mv_s , 0 , &command.mv, move_buffer ) ) {
Solomon Peachy4edaf3f2019-02-06 13:16:58 -05001062 rb->splash ( HZ/2 , ID2P(LANG_CHESSBOX_ILLEGAL_MOVE) );
Dave Chapman7ceadd72006-03-03 15:01:37 +00001063 cb_drawboard();
1064 } else {
1065 cb_drawboard();
Nils Wallménius5ccf1802007-09-02 10:11:46 +00001066
1067 /* Add the ply to the PGN history (in algebraic notation) */
Andrew Mahone23d98122009-01-16 10:34:40 +00001068 pgn_append_ply(game, opponent, move_buffer, mate);
Nils Wallménius5ccf1802007-09-02 10:11:46 +00001069
Solomon Peachy4edaf3f2019-02-06 13:16:58 -05001070 talk_move(move_buffer);
1071 rb->splash ( 0 , ID2P(LANG_CHESSBOX_THINKING) );
Hristo Kovachev91522722006-02-22 14:24:54 +00001072#ifdef HAVE_ADJUSTABLE_CPU_FREQ
Dave Chapman7ceadd72006-03-03 15:01:37 +00001073 rb->cpu_boost ( true );
Hristo Kovachev91522722006-02-22 14:24:54 +00001074#endif
Nils Wallménius3e190c82007-05-29 16:33:16 +00001075 SelectMove ( computer , 0 , cb_wt_callback, move_buffer);
Hristo Kovachev91522722006-02-22 14:24:54 +00001076#ifdef HAVE_ADJUSTABLE_CPU_FREQ
Dave Chapman7ceadd72006-03-03 15:01:37 +00001077 rb->cpu_boost ( false );
Hristo Kovachev91522722006-02-22 14:24:54 +00001078#endif
Nils Wallménius5ccf1802007-09-02 10:11:46 +00001079 /* Add the ply to the PGN history (in algebraic notation) and check
1080 * for the result of the game which is only calculated in SelectMove
1081 */
1082 if (move_buffer[0] != '\0'){
Andrew Mahone23d98122009-01-16 10:34:40 +00001083 pgn_append_ply(game, computer, move_buffer, mate);
Solomon Peachy4edaf3f2019-02-06 13:16:58 -05001084 talk_move(move_buffer);
Nils Wallménius5ccf1802007-09-02 10:11:46 +00001085 } else {
Andrew Mahone23d98122009-01-16 10:34:40 +00001086 pgn_set_result(game, mate);
Nils Wallménius5ccf1802007-09-02 10:11:46 +00001087 }
1088
Dave Chapman7ceadd72006-03-03 15:01:37 +00001089 if ( wt_command == COMMAND_QUIT ) {
1090 exit = true;
1091 break;
1092 }
1093 cb_drawboard();
1094 }
1095 break;
Dave Chapman7ceadd72006-03-03 15:01:37 +00001096 case COMMAND_RESTART:
1097 GNUChess_Initialize();
Andrew Mahone23d98122009-01-16 10:34:40 +00001098 game = pgn_init_game();
Dave Chapman7ceadd72006-03-03 15:01:37 +00001099 cb_drawboard();
1100 break;
Marcoen Hirschberg0d02c132007-05-18 22:12:34 +00001101 case COMMAND_RESUME:
1102 cb_drawboard();
1103 break;
1104 case COMMAND_SAVE:
Solomon Peachy55729042019-07-15 10:49:55 -04001105 cb_saveposition(game);
Marcoen Hirschberg0d02c132007-05-18 22:12:34 +00001106 cb_drawboard();
1107 break;
1108 case COMMAND_RESTORE:
1109 /* watch out, it will reset the game if no previous game was saved! */
1110
1111 /* init board */
1112 GNUChess_Initialize();
Nils Wallménius5ccf1802007-09-02 10:11:46 +00001113
Marcoen Hirschberg0d02c132007-05-18 22:12:34 +00001114 /* restore saved position, if saved */
Solomon Peachy55729042019-07-15 10:49:55 -04001115 game = cb_restoreposition();
Marcoen Hirschberg0d02c132007-05-18 22:12:34 +00001116
1117 cb_drawboard();
1118 break;
Solomon Peachy55729042019-07-15 10:49:55 -04001119 case COMMAND_VIEW:
1120 if (rb->file_exists(pgn_file)) {
1121 cb_saveposition(game);
1122 if (cb_start_viewer(pgn_file))
1123 return;
1124 GNUChess_Initialize();
1125 game = cb_restoreposition();
1126 }else{
1127 rb->splash ( HZ*2 , ID2P(LANG_CHESSBOX_NO_GAMES) );
1128 }
1129 cb_drawboard();
1130 break;
Dave Chapman7ceadd72006-03-03 15:01:37 +00001131 case COMMAND_PLAY:
Marcoen Hirschberg0d02c132007-05-18 22:12:34 +00001132 if (opponent == white) {
1133 opponent = black;
1134 computer = white;
1135 } else {
1136 opponent = white;
1137 computer = black;
1138 }
Solomon Peachy4edaf3f2019-02-06 13:16:58 -05001139 rb->splash ( 0 , ID2P(LANG_CHESSBOX_THINKING) );
Peter D'Hoye5490f6c2007-08-03 21:59:41 +00001140 ElapsedTime(1);
Hristo Kovachev91522722006-02-22 14:24:54 +00001141#ifdef HAVE_ADJUSTABLE_CPU_FREQ
Dave Chapman7ceadd72006-03-03 15:01:37 +00001142 rb->cpu_boost ( true );
Hristo Kovachev91522722006-02-22 14:24:54 +00001143#endif
Nils Wallménius3e190c82007-05-29 16:33:16 +00001144 SelectMove ( computer , 0 , cb_wt_callback , move_buffer );
Hristo Kovachev91522722006-02-22 14:24:54 +00001145#ifdef HAVE_ADJUSTABLE_CPU_FREQ
Dave Chapman7ceadd72006-03-03 15:01:37 +00001146 rb->cpu_boost ( false );
Hristo Kovachev91522722006-02-22 14:24:54 +00001147#endif
Nils Wallménius5ccf1802007-09-02 10:11:46 +00001148
1149 /* Add the ply to the PGN history (in algebraic notation) and check
1150 * for the result of the game which is only calculated in SelectMove
1151 */
1152 if (move_buffer[0] != '\0'){
Andrew Mahone23d98122009-01-16 10:34:40 +00001153 pgn_append_ply(game, computer, move_buffer, mate);
Solomon Peachy4edaf3f2019-02-06 13:16:58 -05001154 talk_move(move_buffer);
Nils Wallménius5ccf1802007-09-02 10:11:46 +00001155 } else {
Andrew Mahone23d98122009-01-16 10:34:40 +00001156 pgn_set_result(game, mate);
Nils Wallménius5ccf1802007-09-02 10:11:46 +00001157 }
1158
Dave Chapman7ceadd72006-03-03 15:01:37 +00001159 if ( wt_command == COMMAND_QUIT ) {
1160 exit = true;
1161 break;
1162 }
1163 cb_drawboard();
1164 break;
1165 case COMMAND_LEVEL:
1166 cb_levelup ( );
1167 cb_drawboard();
1168 break;
1169 case COMMAND_QUIT:
Dave Chapman7ceadd72006-03-03 15:01:37 +00001170 exit = true;
1171 break;
1172 }
1173 }
William Wilgus37522ec2017-01-31 01:07:47 +01001174
Solomon Peachy55729042019-07-15 10:49:55 -04001175 cb_saveposition(game);
Nils Wallménius3e190c82007-05-29 16:33:16 +00001176
1177}
1178
1179/*****************************************************************************
1180* plugin entry point.
1181******************************************************************************/
Andrew Mahone23d98122009-01-16 10:34:40 +00001182enum plugin_status plugin_start(const void* parameter) {
William Wilgus37522ec2017-01-31 01:07:47 +01001183
Nils Wallménius3e190c82007-05-29 16:33:16 +00001184 /* plugin init */
1185
Nils Wallménius3e190c82007-05-29 16:33:16 +00001186#if LCD_DEPTH > 1
1187 rb->lcd_set_backdrop(NULL);
1188#endif
Solomon Peachy75fe78c2018-12-22 22:16:32 -05001189 cb_sysevent = 0;
Nils Wallménius3e190c82007-05-29 16:33:16 +00001190
1191 /* end of plugin init */
1192
William Wilgus37522ec2017-01-31 01:07:47 +01001193 /* if the plugin was invoked as a viewer, parse the file and show the game list
Nils Wallménius3e190c82007-05-29 16:33:16 +00001194 * else, start playing a game
1195 */
1196 if (parameter != NULL) {
1197 cb_start_viewer((char *)parameter);
1198 } else {
1199 cb_play_game();
1200 }
1201
Solomon Peachy55729042019-07-15 10:49:55 -04001202 rb->lcd_setfont(FONT_UI);
1203
Solomon Peachy75fe78c2018-12-22 22:16:32 -05001204 if (cb_sysevent)
1205 rb->default_event_handler(cb_sysevent);
1206
Hristo Kovachev91522722006-02-22 14:24:54 +00001207 return PLUGIN_OK;
1208}