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:
parent
c5ed45d8c7
commit
5572904887
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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--)
|
||||
|
|
Loading…
Reference in New Issue
Block a user