chessbox: Fixes and enhancements

- Unfinished game is now saved along with current position.
- All savings are automatically done on shutdown.
- Implemented facility to view played games.
- Fixed bug that prevented program from the very first move.

Patch by Igor Poretsky

Change-Id: I997b97752e4362ed953309bea985d071f9db229b
This commit is contained in:
Solomon Peachy 2019-07-15 10:49:55 -04:00
parent c5ed45d8c7
commit 5572904887
5 changed files with 117 additions and 83 deletions

View File

@ -15259,3 +15259,20 @@ id: VOICE_BAT_BENCH_KEYS
recording: "Recording Directory"
</voice>
</phrase>
<phrase>
id: LANG_CHESSBOX_MENU_VIEW_GAMES
desc: in the chessbox menu
user: core
<source>
*: none
lcd_bitmap: "View Played Games"
</source>
<dest>
*: none
lcd_bitmap: "View Played Games"
</dest>
<voice>
*: none
lcd_bitmap: "View Played Games"
</voice>
</phrase>

View File

@ -74,6 +74,8 @@ extern const fb_data chessbox_pieces[];
#define COMMAND_SELECT 10
#define COMMAND_NEXT 11
#define COMMAND_PREV 12
#define COMMAND_VIEW 13
#define COMMAND_RETURN 14
short plugin_mode;
@ -360,7 +362,7 @@ static void cb_saveposition_dbg ( void )
sizeof(temp));
rb->write(fd, buf, ch_ct);
}
for (i = 0; i <= GameCnt; i++) {
for (i = 0; i < ((GameCnt + 1) & 0xFF); i++) {
ch_ct = rb->snprintf(buf,31,"GameCt %d, %d bytes\n",i,
sizeof(GameCnt));
rb->write(fd, buf, ch_ct);
@ -399,17 +401,21 @@ static void cb_saveposition_dbg ( void )
}
#endif
/* ---- Save current position ---- */
static void cb_saveposition ( void ) {
/* ---- Save current position and game history ---- */
static void cb_saveposition ( struct pgn_game_node* game ) {
int fd;
short sq,i,c;
unsigned short temp;
struct pgn_ply_node *ply;
char buf[4];
#ifdef CHESSBOX_SAVE_FILE_DBG
cb_saveposition_dbg();
#endif
rb->splash ( 0 , ID2P(LANG_CHESSBOX_SAVING_POSITION) );
fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT, 0666);
fd = rb->open(SAVE_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666);
computer++; rb->write(fd, &(computer), sizeof(computer)); computer--;
opponent++; rb->write(fd, &(opponent), sizeof(opponent)); opponent--;
@ -438,7 +444,9 @@ static void cb_saveposition ( void ) {
temp = 256*board[sq] + c ;
rb->write(fd, &(temp), sizeof(temp));
}
for (i = 0; i <= GameCnt; i++) {
c = GameCnt;
rb->write(fd, &(c), sizeof(c));
for (i = 0; i < ((GameCnt + 1) & 0xFF); i++) {
if (GameList[i].color == neutral)
c = 0;
else
@ -451,14 +459,24 @@ static void cb_saveposition ( void ) {
rb->write(fd, &(GameList[i].piece), sizeof(GameList[i].piece));
rb->write(fd, &(c), sizeof(c));
}
for (ply=game->first_ply; ply!=NULL; ply=ply->next_node) {
buf[0] = ply->column_from + 'a';
buf[1] = ply->row_from + '1';
buf[2] = ply->column_to + 'a';
buf[3] = ply->row_to + '1';
rb->write(fd, buf, 4);
}
rb->close(fd);
}
/* ---- Restore saved position ---- */
static void cb_restoreposition ( void ) {
/* ---- Restore saved position and game history ---- */
static struct pgn_game_node* cb_restoreposition ( void ) {
int fd;
short sq;
unsigned short m;
short n;
char buf[4];
struct pgn_game_node* game = pgn_init_game();
if ( (fd = rb->open(SAVE_FILE, O_RDONLY)) >= 0 ) {
rb->splash ( 0 , ID2P(LANG_CHESSBOX_LOADING_POSITION) );
@ -492,9 +510,12 @@ static void cb_restoreposition ( void ) {
else
--color[sq];
}
GameCnt = MAX_GAME_CNT - 1; /*uchar rollsover to 0 after 255*/
while (rb->read(fd, &(GameList[++GameCnt].gmove),
sizeof(GameList[GameCnt].gmove)) > 0) {
rb->read(fd, &(n), sizeof(n));
n++;
n &= 0xFF;
for (GameCnt = 0; GameCnt < n; GameCnt++) {
rb->read(fd, &(GameList[GameCnt].gmove),
sizeof(GameList[GameCnt].gmove));
rb->read(fd, &(GameList[GameCnt].score),
sizeof(GameList[GameCnt].score));
rb->read(fd, &(GameList[GameCnt].depth),
@ -506,7 +527,7 @@ static void cb_restoreposition ( void ) {
rb->read(fd, &(GameList[GameCnt].piece),
sizeof(GameList[GameCnt].piece));
rb->read(fd, &(GameList[GameCnt].color),
sizeof(GameList[GameCnt].color));
sizeof(GameList[GameCnt].color));
if (GameList[GameCnt].color == 0)
GameList[GameCnt].color = neutral;
else
@ -516,47 +537,45 @@ static void cb_restoreposition ( void ) {
if (TimeControl.clock[white] > 0)
TCflag = true;
computer--; opponent--;
n = 0;
while (rb->read(fd, buf, 4) > 0)
pgn_append_ply(game, ((n++) & 1) ? black : white, buf, false);
rb->close(fd);
}
rb->close(fd);
cb_setlevel(Level);
InitializeStats();
Sdepth = 0;
return game;
}
/* ---- show menu in viewer mode---- */
static int cb_menu_viewer(void)
{
int selection;
int result = 0;
bool menu_quit = false;
MENUITEM_STRINGLIST(menu,"Chessbox Menu",NULL,
ID2P(LANG_CHESSBOX_MENU_RESTART_GAME),
ID2P(LANG_CHESSBOX_MENU_SELECT_OTHER_GAME),
ID2P(LANG_CHESSBOX_MENU_RESUME_GAME),
ID2P(LANG_RETURN),
ID2P(LANG_MENU_QUIT));
while(!menu_quit)
switch(rb->do_menu(&menu, &selection, NULL, false))
{
switch(rb->do_menu(&menu, &selection, NULL, false))
{
case 0:
menu_quit = true;
result = COMMAND_RESTART;
break;
case 1:
result = COMMAND_SELECT;
menu_quit = true;
break;
case 2:
result = COMMAND_QUIT;
menu_quit = true;
break;
}
case 0:
return COMMAND_RESTART;
case 1:
return COMMAND_SELECT;
case 3:
return COMMAND_RETURN;
case 4:
return COMMAND_QUIT;
}
return result;
return COMMAND_RESUME;
}
/* ---- get a command in game mode ---- */
/* ---- get a command in viewer mode ---- */
static struct cb_command cb_get_viewer_command (void) {
int button;
struct cb_command result = { 0, {0,0,0,0,0}, 0 };
@ -592,17 +611,18 @@ static struct cb_command cb_get_viewer_command (void) {
}
/* ---- viewer main loop ---- */
static void cb_start_viewer(char* filename){
static bool cb_start_viewer(const char* filename){
struct pgn_game_node *first_game, *selected_game;
struct pgn_ply_node *curr_ply;
bool exit_game = false;
bool exit_viewer = false;
bool exit_app = false;
struct cb_command command;
first_game = pgn_list_games(filename);
if (first_game == NULL){
rb->splash ( HZ*2 , ID2P(LANG_CHESSBOX_NO_GAMES) );
return;
return exit_app;
}
do {
@ -759,6 +779,8 @@ static void cb_start_viewer(char* filename){
exit_game = true;
break;
case COMMAND_QUIT:
exit_app = true;
case COMMAND_RETURN:
exit_viewer = true;
break;
}
@ -767,57 +789,44 @@ static void cb_start_viewer(char* filename){
rb->splash ( HZ*2 , ID2P(LANG_CHESSBOX_PGN_PARSE_ERROR));
}
} while (!exit_viewer);
return exit_app;
}
/* ---- show menu ---- */
static int cb_menu(void)
{
int selection;
int result = 0;
bool menu_quit = false;
MENUITEM_STRINGLIST(menu,"Chessbox Menu",NULL,
ID2P(LANG_CHESSBOX_MENU_NEW_GAME),
ID2P(LANG_CHESSBOX_MENU_RESUME_GAME),
ID2P(LANG_CHESSBOX_MENU_SAVE_GAME),
ID2P(LANG_CHESSBOX_MENU_RESTORE_GAME),
ID2P(LANG_CHESSBOX_MENU_VIEW_GAMES),
#ifdef HAVE_PLAYBACK_CONTROL
ID2P(LANG_PLAYBACK_CONTROL),
#endif
ID2P(LANG_MENU_QUIT));
while(!menu_quit)
switch(rb->do_menu(&menu, &selection, NULL, false))
{
switch(rb->do_menu(&menu, &selection, NULL, false))
{
case 0:
menu_quit = true;
result = COMMAND_RESTART;
break;
case 1:
result = COMMAND_RESUME;
menu_quit = true;
break;
case 2:
result = COMMAND_SAVE;
menu_quit = true;
break;
case 3:
result = COMMAND_RESTORE;
menu_quit = true;
break;
case 4:
case 0:
return COMMAND_RESTART;
case 2:
return COMMAND_SAVE;
case 3:
return COMMAND_RESTORE;
case 4:
return COMMAND_VIEW;
case 5:
#ifdef HAVE_PLAYBACK_CONTROL
playback_control(NULL);
break;
case 5:
playback_control(NULL);
break;
case 6:
#endif
result = COMMAND_QUIT;
menu_quit = true;
break;
}
return COMMAND_QUIT;
}
return result;
return COMMAND_RESUME;
}
/* ---- get a command in game mode ---- */
@ -1029,12 +1038,8 @@ static void cb_play_game(void) {
/* init board */
GNUChess_Initialize();
/* init PGN history data structures */
game = pgn_init_game();
/* restore saved position, if saved */
cb_restoreposition();
/* TODO: save/restore the PGN history of unfinished games */
game = cb_restoreposition();
/* draw the board */
/* I don't like configscreens, start game inmediatly */
@ -1097,7 +1102,7 @@ static void cb_play_game(void) {
cb_drawboard();
break;
case COMMAND_SAVE:
cb_saveposition();
cb_saveposition(game);
cb_drawboard();
break;
case COMMAND_RESTORE:
@ -1106,12 +1111,21 @@ static void cb_play_game(void) {
/* init board */
GNUChess_Initialize();
/* init PGN history data structures */
game = pgn_init_game();
/* restore saved position, if saved */
cb_restoreposition();
game = cb_restoreposition();
cb_drawboard();
break;
case COMMAND_VIEW:
if (rb->file_exists(pgn_file)) {
cb_saveposition(game);
if (cb_start_viewer(pgn_file))
return;
GNUChess_Initialize();
game = cb_restoreposition();
}else{
rb->splash ( HZ*2 , ID2P(LANG_CHESSBOX_NO_GAMES) );
}
cb_drawboard();
break;
case COMMAND_PLAY:
@ -1158,9 +1172,7 @@ static void cb_play_game(void) {
}
}
cb_saveposition();
/* TODO: save/restore the PGN history of unfinished games */
rb->lcd_setfont(FONT_UI);
cb_saveposition(game);
}
@ -1187,6 +1199,8 @@ enum plugin_status plugin_start(const void* parameter) {
cb_play_game();
}
rb->lcd_setfont(FONT_UI);
if (cb_sysevent)
rb->default_event_handler(cb_sysevent);

View File

@ -22,9 +22,9 @@
#include "plugin.h"
#include "chessbox_pgn.h"
#define PGN_FILE PLUGIN_GAMES_DATA_DIR "/chessbox.pgn"
#define LOG_FILE PLUGIN_GAMES_DATA_DIR "/chessbox.log"
int loghandler;
const char *pgn_file = PLUGIN_GAMES_DATA_DIR "/chessbox.pgn";
short kn_offs[8][2] = {{2,1},{2,-1},{-2,1},{-2,-1},{1,2},{1,-2},{-1,2},{-1,-2}};
short rk_offs[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};
@ -889,7 +889,7 @@ void pgn_store_game(struct pgn_game_node* game){
ply_count++;
}
fhandler = rb->open(PGN_FILE, O_WRONLY|O_CREAT|O_APPEND, 0666);
fhandler = rb->open(pgn_file, O_WRONLY|O_CREAT|O_APPEND, 0666);
/* the first 7 tags are mandatory according to the PGN specification so we

View File

@ -649,7 +649,7 @@
/* structure to represent the plies */
struct pgn_ply_node {
unsigned short player;
char pgn_text[9];
char pgn_text[11];
unsigned short row_from;
unsigned short column_from;
unsigned short row_to;
@ -677,6 +677,9 @@ struct pgn_game_node {
struct pgn_game_node* next_node;
};
/* File for saving games */
extern const char* pgn_file;
/* Return the list of games in a PGN file.
* Parsing of the games themselves is postponed until
* the user selects a game, that obviously saves processing

View File

@ -1167,12 +1167,12 @@ void OpeningBook()
m = 0;
while ( o_c < MAX_OPENING ) {
m_c = 0 ;
for (j = 0; j <= GameCnt; j++) {
for (j = 0; j < ((GameCnt + 1) & 0xFF); j++) {
if ( GameList[j].gmove != OBook[o_c][m_c] ) break;
m_c++;
}
/* I added ( m != OBook[o_c][m_c] ) trying to get more random games */
if ( ( j > GameCnt ) && ( m != OBook[o_c][m_c] ) ) {
if ( ( j >= ((GameCnt + 1) & 0xFF) ) && ( m != OBook[o_c][m_c] ) ) {
r=rb->rand();
if ( r > r0 ) {
r0 = r; m = OBook[o_c][m_c];
@ -2066,7 +2066,7 @@ register short i,c,f,t;
short b[64];
unsigned short m;
*cnt = c = 0;
if (GameCnt > Game50+3)
if (((GameCnt + 1) & 0xFF) > Game50+4)
{
for (i = 0; i < 64; b[i++] = 0);
for (i = GameCnt; i > Game50; i--)