1
0
Fork 0
forked from len0rd/rockbox

Accept patch from FS#7174 by Mauricio Peccorini with canges by me and Igor Kuzmin, chessbox now saves played games in a pgn file called .rockbox/rocks/games/chessbox.pgn

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14575 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Nils Wallménius 2007-09-02 10:11:46 +00:00
parent c00652b0a2
commit 5ccf18019e
6 changed files with 462 additions and 30 deletions

View file

@ -672,7 +672,6 @@ void cb_start_viewer(char* filename){
curr_ply = curr_ply->prev_node; curr_ply = curr_ply->prev_node;
} else { } else {
rb->splash ( 200 , "At the begining of the game" ); rb->splash ( 200 , "At the begining of the game" );
cb_drawboard();
break; break;
} }
board[locn[curr_ply->row_from][curr_ply->column_from]] board[locn[curr_ply->row_from][curr_ply->column_from]]
@ -952,7 +951,8 @@ struct cb_command cb_getcommand (void) {
/* ---- game main loop ---- */ /* ---- game main loop ---- */
void cb_play_game(void) { void cb_play_game(void) {
struct cb_command command; struct cb_command command;
char move_buffer[10]; struct pgn_game_node *game;
char move_buffer[20];
/* init status */ /* init status */
bool exit = false; bool exit = false;
@ -961,9 +961,13 @@ void cb_play_game(void) {
/* init board */ /* init board */
GNUChess_Initialize(); GNUChess_Initialize();
/* init PGN history data structures */
game = pgn_init_game(rb);
/* restore saved position, if saved */ /* restore saved position, if saved */
cb_restoreposition(); cb_restoreposition();
/* TODO: save/restore the PGN history of unfinished games */
/* draw the board */ /* draw the board */
/* I don't like configscreens, start game inmediatly */ /* I don't like configscreens, start game inmediatly */
@ -973,17 +977,23 @@ void cb_play_game(void) {
if ( mate ) { if ( mate ) {
rb->splash ( 500 , "Checkmate!" ); rb->splash ( 500 , "Checkmate!" );
rb->button_get(true); rb->button_get(true);
pgn_store_game(rb, game);
GNUChess_Initialize(); GNUChess_Initialize();
game = pgn_init_game(rb);
cb_drawboard(); cb_drawboard();
} }
command = cb_getcommand (); command = cb_getcommand ();
switch (command.type) { switch (command.type) {
case COMMAND_MOVE: case COMMAND_MOVE:
if ( ! VerifyMove ( command.mv_s , 0 , &command.mv ) ) { if ( ! VerifyMove (opponent, command.mv_s , 0 , &command.mv, move_buffer ) ) {
rb->splash ( 50 , "Illegal move!" ); rb->splash ( 50 , "Illegal move!" );
cb_drawboard(); cb_drawboard();
} else { } else {
cb_drawboard(); cb_drawboard();
/* Add the ply to the PGN history (in algebraic notation) */
pgn_append_ply(rb, game, opponent, move_buffer, mate);
rb->splash ( 0 , "Thinking..." ); rb->splash ( 0 , "Thinking..." );
#ifdef HAVE_ADJUSTABLE_CPU_FREQ #ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost ( true ); rb->cpu_boost ( true );
@ -992,6 +1002,15 @@ void cb_play_game(void) {
#ifdef HAVE_ADJUSTABLE_CPU_FREQ #ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost ( false ); rb->cpu_boost ( false );
#endif #endif
/* Add the ply to the PGN history (in algebraic notation) and check
* for the result of the game which is only calculated in SelectMove
*/
if (move_buffer[0] != '\0'){
pgn_append_ply(rb, game, computer, move_buffer, mate);
} else {
pgn_set_result(rb, game, mate);
}
if ( wt_command == COMMAND_QUIT ) { if ( wt_command == COMMAND_QUIT ) {
exit = true; exit = true;
break; break;
@ -1002,6 +1021,7 @@ void cb_play_game(void) {
#ifdef COMMAND_RESTART #ifdef COMMAND_RESTART
case COMMAND_RESTART: case COMMAND_RESTART:
GNUChess_Initialize(); GNUChess_Initialize();
game = pgn_init_game(rb);
cb_drawboard(); cb_drawboard();
break; break;
#endif #endif
@ -1017,7 +1037,10 @@ void cb_play_game(void) {
/* init board */ /* init board */
GNUChess_Initialize(); GNUChess_Initialize();
/* init PGN history data structures */
game = pgn_init_game(rb);
/* restore saved position, if saved */ /* restore saved position, if saved */
cb_restoreposition(); cb_restoreposition();
@ -1040,6 +1063,16 @@ void cb_play_game(void) {
#ifdef HAVE_ADJUSTABLE_CPU_FREQ #ifdef HAVE_ADJUSTABLE_CPU_FREQ
rb->cpu_boost ( false ); rb->cpu_boost ( false );
#endif #endif
/* Add the ply to the PGN history (in algebraic notation) and check
* for the result of the game which is only calculated in SelectMove
*/
if (move_buffer[0] != '\0'){
pgn_append_ply(rb, game, computer, move_buffer, mate);
} else {
pgn_set_result(rb, game, mate);
}
if ( wt_command == COMMAND_QUIT ) { if ( wt_command == COMMAND_QUIT ) {
exit = true; exit = true;
break; break;
@ -1057,6 +1090,7 @@ void cb_play_game(void) {
} }
cb_saveposition(); cb_saveposition();
/* TODO: save/restore the PGN history of unfinished games */
rb->lcd_setfont(FONT_UI); rb->lcd_setfont(FONT_UI);
} }

View file

@ -188,7 +188,8 @@
#error CHESSBOX: Unsupported keypad #error CHESSBOX: Unsupported keypad
#endif #endif
#define LOG_FILE PLUGIN_DIR "/chessbox.log" #define PGN_FILE PLUGIN_GAMES_DIR "/chessbox.pgn"
#define LOG_FILE PLUGIN_GAMES_DIR "/chessbox.log"
int loghandler; int loghandler;
struct plugin_api* rb; struct plugin_api* rb;
@ -520,6 +521,180 @@ void pgn_to_coords(struct pgn_ply_node* ply){
color[locn[ply->row_from][ply->column_from]] = neutral; color[locn[ply->row_from][ply->column_from]] = neutral;
} }
void coords_to_pgn(struct pgn_ply_node* ply){
int pos = 0,i,j;
unsigned short moving_piece = board[locn[ply->row_from][ply->column_from]];
char unambiguous_position;
bool found = false;
char alg_move[5];
char move_buffer[10];
short move;
if (moving_piece == king){
/* check castling */
if (ply->column_from == 4 && ply->column_to == 6){
/* castling kingside */
rb->strcpy(ply->pgn_text,"O-O");
ply->castle = true;
} else if (ply->column_from == 4 && ply->column_to == 2){
/* castling queenside */
rb->strcpy(ply->pgn_text,"O-O-O");
} else {
if (board[locn[ply->row_to][ply->column_to]] != no_piece){
rb->snprintf(ply->pgn_text,10,"Kx%c%c",'a'+ply->column_to,
'1'+ply->row_to);
} else {
rb->snprintf(ply->pgn_text,10,"K%c%c",'a'+ply->column_to,
'1'+ply->row_to);
}
}
} else if (moving_piece == pawn){
if (ply->column_from != ply->column_to){
/* check enpassant */
if (board[locn[ply->row_to][ply->column_to]] == no_piece){
ply->enpassant = true;
}
/* check promotions when taking a piece */
if (ply->row_to == 0 || ply->row_to == 7) {
ply->promotion = true;
ply->promotion_piece = queen;
rb->snprintf(ply->pgn_text,10,"%cx%c%c=D", 'a'+ply->column_from,
'a'+ply->column_to,'1'+ply->row_to);
} else {
rb->snprintf(ply->pgn_text,10,"%cx%c%c", 'a'+ply->column_from,
'a'+ply->column_to,'1'+ply->row_to);
}
} else {
/* check promotions when not taking a piece */
if (ply->row_to == 0 || ply->row_to == 7) {
ply->promotion = true;
ply->promotion_piece = queen;
rb->snprintf(ply->pgn_text,10,"%c%c=D", 'a'+ply->column_to,
'1'+ply->row_to);
} else {
rb->snprintf(ply->pgn_text,10,"%c%c", 'a'+ply->column_to,
'1'+ply->row_to);
}
}
} else {
/* verify ambiguous moves for the different kinds of pieces */
unambiguous_position = '\0';
if (moving_piece == knight){
for (i=0;i<8;i++){
if (ply->row_to + kn_offs[i][0] >= 0 && ply->row_to + kn_offs[i][0] <= 7
&& ply->column_to + kn_offs[i][1] >= 0 && ply->column_to + kn_offs[i][1] <= 7
&& board[locn[ply->row_to + kn_offs[i][0]][ply->column_to + kn_offs[i][1]]] == knight
&& color[locn[ply->row_to + kn_offs[i][0]][ply->column_to + kn_offs[i][1]]] == ply->player
&& (ply->row_to + kn_offs[i][0] != ply->row_from
|| ply->column_to + kn_offs[i][1] != ply->column_from)){
if (ply->row_to + kn_offs[i][0] != ply->row_from){
unambiguous_position = '1' + ply->row_from;
} else {
unambiguous_position = 'a' + ply->column_from;
}
break;
}
}
}
if (moving_piece == rook || moving_piece == queen){
found = false;
for (i=0;i<4;i++){
j=1;
while (ply->row_to+(j*rk_offs[i][0]) >= 0 && ply->row_to+(j*rk_offs[i][0]) <= 7 &&
ply->column_to+(j*rk_offs[i][1]) >= 0 && ply->column_to+(j*rk_offs[i][1]) <= 7){
if (board[locn[ply->row_to+(j*rk_offs[i][0])][ply->column_to+(j*rk_offs[i][1])]] != no_piece) {
if (board[locn[ply->row_to+(j*rk_offs[i][0])][ply->column_to+(j*rk_offs[i][1])]] == moving_piece &&
color[locn[ply->row_to+(j*rk_offs[i][0])][ply->column_to+(j*rk_offs[i][1])]] == ply->player &&
(ply->row_to+(j*rk_offs[i][0]) != ply->row_from
|| ply->column_to+(j*rk_offs[i][1]) != ply->column_from)) {
if (ply->row_to+(j*rk_offs[i][0]) != ply->row_from){
unambiguous_position = '1' + ply->row_from;
} else {
unambiguous_position = 'a' + ply->column_from;
}
found = true;
}
break;
}
j++;
}
if (found) {
break;
}
}
}
if (moving_piece == bishop || (moving_piece == queen && !found)){
for (i=0;i<4;i++){
j=1;
while (ply->row_to+(j*bp_offs[i][0]) >= 0 && ply->row_to+(j*bp_offs[i][0]) <= 7 &&
ply->column_to+(j*bp_offs[i][1]) >= 0 && ply->column_to+(j*bp_offs[i][1]) <= 7){
if (board[locn[ply->row_to+(j*bp_offs[i][0])][ply->column_to+(j*bp_offs[i][1])]] != no_piece) {
if (board[locn[ply->row_to+(j*bp_offs[i][0])][ply->column_to+(j*bp_offs[i][1])]] == moving_piece &&
color[locn[ply->row_to+(j*bp_offs[i][0])][ply->column_to+(j*bp_offs[i][1])]] == ply->player &&
(ply->row_to+(j*bp_offs[i][0]) != ply->row_from
|| ply->column_to+(j*bp_offs[i][1]) != ply->column_from)) {
if (ply->row_to+(j*bp_offs[i][0]) != ply->row_from){
unambiguous_position = '1' + ply->row_from;
} else {
unambiguous_position = 'a' + ply->column_from;
}
found = true;
}
break;
}
j++;
}
if (found) {
break;
}
}
}
/* generate the first portion of the PGN text
* always as white so all uppercase, black/white considerations
* will be useful for FEN notation but not in this case
*/
if (unambiguous_position == '\0'){
if (board[locn[ply->row_to][ply->column_to]] != no_piece){
rb->snprintf(ply->pgn_text,10,"%cx%c%c",
pgn_from_piece(moving_piece,white) ,
'a'+ply->column_to, '1'+ply->row_to);
} else {
rb->snprintf(ply->pgn_text,10,"%c%c%c",
pgn_from_piece(moving_piece,white) ,
'a'+ply->column_to, '1'+ply->row_to);
}
} else {
if (board[locn[ply->row_to][ply->column_to]] != no_piece){
rb->snprintf(ply->pgn_text,10,"%c%cx%c%c",
pgn_from_piece(moving_piece,white) ,
unambiguous_position, 'a'+ply->column_to,
'1'+ply->row_to);
} else {
rb->snprintf(ply->pgn_text,10,"%c%c%c%c",
pgn_from_piece(moving_piece,white) ,
unambiguous_position, 'a'+ply->column_to,
'1'+ply->row_to);
}
}
}
/* update the board */
rb->snprintf(alg_move,5,"%c%c%c%c",'a' + ply->column_from, '1' + ply->row_from,
'a' + ply->column_to, '1' + ply->row_to);
/* The function returns false if the move is invalid, but since we're
* replaying the game, that should not be posible
*/
VerifyMove (ply->player, alg_move , 0 , &move, move_buffer );
/* add check/mate indicators */
for (pos=0;ply->pgn_text[pos] != '\0';pos++);
if (ply->checkmate) {
ply->pgn_text[pos] = '#'; pos++;
ply->pgn_text[pos] = '\0'; pos++;
} else if (move_buffer[4] == '+'){
ply->pgn_text[pos] = '+'; pos++;
ply->pgn_text[pos] = '\0'; pos++;
}
}
char * get_game_text(int selected_item, void *data, char *buffer){ char * get_game_text(int selected_item, void *data, char *buffer){
int i; int i;
struct pgn_game_node *temp_node = (struct pgn_game_node *)data; struct pgn_game_node *temp_node = (struct pgn_game_node *)data;
@ -538,11 +713,21 @@ char * get_game_text(int selected_item, void *data, char *buffer){
return buffer; return buffer;
} }
void write_pgn_token(int fhandler, char *buffer, size_t *line_length){
if (*line_length + rb->strlen(buffer) + 1 > 80){
rb->fdprintf(fhandler,"\n");
*line_length = 0;
}
rb->fdprintf(fhandler,"%s ",buffer);
*line_length += (rb->strlen(buffer) + 1);
}
/* ---- api functions ---- */ /* ---- api functions ---- */
struct pgn_game_node* pgn_list_games(struct plugin_api* api,const char* filename){ struct pgn_game_node* pgn_list_games(struct plugin_api* api,const char* filename){
int fhandler; int fhandler;
char line_buffer[128]; char line_buffer[128];
struct pgn_game_node size_node, *first_game = NULL, *curr_node = NULL, *temp_node; struct pgn_game_node size_node, *first_game = NULL;
struct pgn_game_node *curr_node = NULL, *temp_node;
unsigned short game_count = 1; unsigned short game_count = 1;
int line_count = 0; int line_count = 0;
bool header_start = true, game_start = false; bool header_start = true, game_start = false;
@ -577,7 +762,9 @@ struct pgn_game_node* pgn_list_games(struct plugin_api* api,const char* filename
} else { } else {
if (line_buffer[0] == '['){ if (line_buffer[0] == '['){
process_tag(curr_node, line_buffer); process_tag(curr_node, line_buffer);
} else if (line_buffer[0] == '\r' || line_buffer[0] == '\n' || line_buffer[0] == '\0'){ } else if (line_buffer[0] == '\r'
|| line_buffer[0] == '\n'
|| line_buffer[0] == '\0'){
if (game_start) { if (game_start) {
game_start = false; game_start = false;
} else { } else {
@ -594,7 +781,8 @@ struct pgn_game_node* pgn_list_games(struct plugin_api* api,const char* filename
return first_game; return first_game;
} }
struct pgn_game_node* pgn_show_game_list(struct plugin_api* api, struct pgn_game_node* first_game){ struct pgn_game_node* pgn_show_game_list(struct plugin_api* api,
struct pgn_game_node* first_game){
int curr_selection = 0; int curr_selection = 0;
int button; int button;
struct gui_synclist games_list; struct gui_synclist games_list;
@ -638,8 +826,10 @@ struct pgn_game_node* pgn_show_game_list(struct plugin_api* api, struct pgn_game
} }
} }
void pgn_parse_game(struct plugin_api* api, const char* filename, struct pgn_game_node* selected_game){ void pgn_parse_game(struct plugin_api* api, const char* filename,
struct pgn_ply_node size_ply, *first_ply = NULL, *temp_ply = NULL, *curr_node = NULL; struct pgn_game_node* selected_game){
struct pgn_ply_node size_ply, *first_ply = NULL;
struct pgn_ply_node *temp_ply = NULL, *curr_node = NULL;
int fhandler, i; int fhandler, i;
char line_buffer[128]; char line_buffer[128];
char token_buffer[10]; char token_buffer[10];
@ -682,16 +872,20 @@ void pgn_parse_game(struct plugin_api* api, const char* filename, struct pgn_gam
temp_ply->prev_node = curr_node; temp_ply->prev_node = curr_node;
curr_node = temp_ply; curr_node = temp_ply;
} }
rb->fdprintf(loghandler,"player: %u; pgn: %s; from: %u,%u; to: %u,%u; taken: %u.\n", rb->fdprintf(loghandler,
temp_ply->player, temp_ply->pgn_text, temp_ply->row_from, temp_ply->column_from, "player: %u; pgn: %s; from: %u,%u; to: %u,%u; taken: %u.\n",
temp_ply->row_to, temp_ply->column_to, temp_ply->taken_piece); temp_ply->player, temp_ply->pgn_text, temp_ply->row_from,
temp_ply->column_from, temp_ply->row_to,
temp_ply->column_to, temp_ply->taken_piece);
} }
} }
} }
rb->close(loghandler); rb->close(loghandler);
/* additional dummy ply to represent end of file without loosing the previous node's pointer */ /* additional dummy ply to represent end of file without
*loosing the previous node's pointer
*/
if (first_ply != NULL){ if (first_ply != NULL){
temp_ply = (struct pgn_ply_node *)pl_malloc(sizeof size_ply); temp_ply = (struct pgn_ply_node *)pl_malloc(sizeof size_ply);
temp_ply->player = neutral; temp_ply->player = neutral;
@ -701,3 +895,170 @@ void pgn_parse_game(struct plugin_api* api, const char* filename, struct pgn_gam
selected_game->first_ply = first_ply; selected_game->first_ply = first_ply;
rb->close(fhandler); rb->close(fhandler);
} }
struct pgn_game_node* pgn_init_game(struct plugin_api* api){
struct pgn_game_node game_size, *game;
struct pgn_ply_node ply_size, *ply;
struct tm *current_time;
rb = api;
if (bufptr == NULL){
pl_malloc_init();
}
/* create an "end of game" dummy ply and assign defaults */
ply = (struct pgn_ply_node *)pl_malloc(sizeof ply_size);
ply->player = neutral;
ply->pgn_text[0] = '\0';
ply->prev_node = NULL;
ply->next_node = NULL;
/* create the game and assign defaults */
game = (struct pgn_game_node *)pl_malloc(sizeof game_size);
game->game_number = 0;
rb->strcpy(game->white_player,"Player");
rb->strcpy(game->black_player,"GnuChess");
current_time = rb->get_time();
if (current_time->tm_year < 100){
rb->snprintf(game->game_date,11,"????.??.??");
} else {
rb->snprintf(game->game_date,11,"%4u.%2u.%2u",current_time->tm_year + 1900,
current_time->tm_mon + 1, current_time->tm_mday);
}
rb->strcpy(game->result,"*");
game->pgn_line = 0;
game->first_ply = ply;
game->next_node = NULL;
return game;
}
void pgn_append_ply(struct plugin_api* api, struct pgn_game_node* game,
unsigned short ply_player, char *move_buffer, bool is_mate){
struct pgn_ply_node ply_size, *ply, *temp;
rb = api;
ply = (struct pgn_ply_node *)pl_malloc(sizeof ply_size);
ply->player = ply_player;
ply->column_from = move_buffer[0] - 'a';
ply->row_from = move_buffer[1] - '1';
ply->column_to = move_buffer[2] - 'a';
ply->row_to = move_buffer[3] - '1';
ply->castle = false;
ply->promotion = false;
ply->enpassant = false;
ply->promotion_piece = no_piece;
ply->taken_piece = no_piece;
ply->draw = false;
ply->checkmate = is_mate;
/* move the pointer to the "end of game" marker ply */
for (temp=game->first_ply;temp->next_node!=NULL;temp=temp->next_node);
/* arrange the pointers to insert the ply before the marker */
ply->next_node = temp;
ply->prev_node = temp->prev_node;
if (temp->prev_node == NULL){
game->first_ply = ply;
} else {
temp->prev_node->next_node = ply;
}
temp->prev_node = ply;
}
void pgn_set_result(struct plugin_api* api, struct pgn_game_node* game,
bool is_mate){
rb = api;
struct pgn_ply_node *ply;
for(ply=game->first_ply;ply->next_node != NULL;ply=ply->next_node);
if (is_mate){
ply->prev_node->checkmate = true;
} else {
ply->prev_node->draw = true;
}
}
void pgn_store_game(struct plugin_api* api, struct pgn_game_node* game){
int fhandler;
struct pgn_ply_node *ply;
unsigned ply_count;
size_t line_length=0;
char buffer[10];
rb = api;
GNUChess_Initialize();
ply_count=0;
ply=game->first_ply;
while (ply->next_node!=NULL){
coords_to_pgn(ply);
if (ply->checkmate){
if (ply->player == white){
rb->strcpy(game->result,"1-0");
} else {
rb->strcpy(game->result,"0-1");
}
}
if (ply->draw){
rb->strcpy(game->result,"1/2-1/2");
}
ply=ply->next_node;
ply_count++;
}
fhandler = rb->open(PGN_FILE, O_WRONLY|O_CREAT|O_APPEND);
/* the first 7 tags are mandatory according to the PGN specification so we
* have to include them even if the values don't make much sense
*/
rb->fdprintf(fhandler,"[Event \"Casual Game\"]\n");
rb->fdprintf(fhandler,"[Site \"?\"]\n");
rb->fdprintf(fhandler,"[Date \"%s\"]\n",game->game_date);
rb->fdprintf(fhandler,"[Round \"?\"]\n");
rb->fdprintf(fhandler,"[White \"%s\"]\n",game->white_player);
rb->fdprintf(fhandler,"[Black \"%s\"]\n",game->black_player);
rb->fdprintf(fhandler,"[Result \"%s\"]\n",game->result);
rb->fdprintf(fhandler,"[PlyCount \"%u\"]\n",ply_count);
/* leave a blank line between the tag section and the game section */
rb->fdprintf(fhandler,"\n");
/* write the plies in several lines of up to 80 characters */
for (ply_count=0, ply=game->first_ply;ply->next_node!=NULL;
ply=ply->next_node,ply_count++){
/* write the move number */
if (ply->player == white){
rb->snprintf(buffer,10,"%u.",(ply_count/2)+1);
write_pgn_token(fhandler, buffer, &line_length);
}
/* write the actual move */
write_pgn_token(fhandler,ply->pgn_text,&line_length);
/* write the result of the game at the end */
if (ply->checkmate){
if (ply->player == white){
write_pgn_token(fhandler,"1-0",&line_length);
} else {
write_pgn_token(fhandler,"0-1",&line_length);
}
break;
} else if (ply->draw){
write_pgn_token(fhandler,"1/2-1/2",&line_length);
break;
} else if (ply->next_node->player == neutral) {
/* unknown end of the game */
write_pgn_token(fhandler,"*",&line_length);
break;
}
}
/* leave a blank line between the tag section and the game section */
rb->fdprintf(fhandler,"\n\n");
rb->close(fhandler);
}

View file

@ -33,6 +33,8 @@ struct pgn_ply_node {
bool enpassant; bool enpassant;
bool castle; bool castle;
bool promotion; bool promotion;
bool checkmate;
bool draw;
struct pgn_ply_node* prev_node; struct pgn_ply_node* prev_node;
struct pgn_ply_node* next_node; struct pgn_ply_node* next_node;
}; };
@ -54,14 +56,35 @@ struct pgn_game_node {
* the user selects a game, that obviously saves processing * the user selects a game, that obviously saves processing
* and speeds up response when the user selects the file * and speeds up response when the user selects the file
*/ */
struct pgn_game_node* pgn_list_games(struct plugin_api* api, const char* filename); struct pgn_game_node* pgn_list_games(struct plugin_api* api,
const char* filename);
/* Show the list of games found in a file and allow the user /* Show the list of games found in a file and allow the user
* to select a game to be parsed and showed * to select a game to be parsed and showed
*/ */
struct pgn_game_node* pgn_show_game_list(struct plugin_api* api, struct pgn_game_node* first_game); struct pgn_game_node* pgn_show_game_list(struct plugin_api* api,
struct pgn_game_node* first_game);
/* Parse the pgn string of a game and assign it to the move /* Parse the pgn string of a game and assign it to the move
* list in the structure * list in the structure
*/ */
void pgn_parse_game(struct plugin_api* api, const char* filename, struct pgn_game_node* selected_game); void pgn_parse_game(struct plugin_api* api, const char* filename,
struct pgn_game_node* selected_game);
/* Initialize a new game structure with default values and make
* it ready to store the history of a newly played match
*/
struct pgn_game_node* pgn_init_game(struct plugin_api* api);
/* Add a new ply to the game structure based on the positions */
void pgn_append_ply(struct plugin_api* api, struct pgn_game_node* game,
unsigned short ply_player, char *move_buffer, bool is_mate);
/* Set the result of the game if it was reached during the opponent's ply
*/
void pgn_set_result(struct plugin_api* api, struct pgn_game_node* game,
bool is_mate);
/* Store a complete game in the PGN history file
*/
void pgn_store_game(struct plugin_api* api, struct pgn_game_node* game);

View file

@ -1116,10 +1116,9 @@ static short i,alpha,beta,score,tempb,tempc,tempsf,tempst,xside,rpt;
/*OutputMove();*/ /*OutputMove();*/
short index; short index;
for (index=0;index<4;index++){ for (index=0;index<5;index++){
move_buffer[index] = mvstr1[index]; move_buffer[index] = mvstr1[index];
} }
move_buffer[index] = '\0';
if (score == -9999 || score == 9998) mate = true; if (score == -9999 || score == 9998) mate = true;
if (mate) hint = 0; if (mate) hint = 0;
@ -2231,26 +2230,30 @@ void SetTimeControl( void )
ExitChess(); ExitChess();
}*/ }*/
int VerifyMove(char s[],short iop,unsigned short *mv) int VerifyMove(short player, char s[],short iop,unsigned short *mv, char *move_buffer)
/* /*
Compare the string 's' to the list of legal moves available for the Compare the string 's' to the list of legal moves available for the
opponent. If a match is found, make the move on the board. player. If a match is found, make the move on the board. This was originally
fixed for the opponent, but allowing the player to be specified will make
possible to use GnuChess as a human vs human game verifier. It also allows
the PGN functions to verify checkmates.
*/ */
{ {
static short pnt,tempb,tempc,tempsf,tempst,cnt; static short pnt,tempb,tempc,tempsf,tempst,cnt;
static struct leaf xnode; static struct leaf xnode;
struct leaf *node; struct leaf *node;
short opponent_player = (player == white)?black:white;
*mv = 0; *mv = 0;
if (iop == 2) if (iop == 2)
{ {
UnmakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst); UnmakeMove(player,&xnode,&tempb,&tempc,&tempsf,&tempst);
return(false); return(false);
} }
cnt = 0; cnt = 0;
MoveList(opponent,2); MoveList(player,2);
pnt = TrPnt[2]; pnt = TrPnt[2];
while (pnt < TrPnt[3]) while (pnt < TrPnt[3])
{ {
@ -2264,10 +2267,10 @@ struct leaf *node;
} }
if (cnt == 1) if (cnt == 1)
{ {
MakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst); MakeMove(player,&xnode,&tempb,&tempc,&tempsf,&tempst);
if (SqAtakd(PieceList[opponent][0],computer)) if (SqAtakd(PieceList[player][0],opponent_player))
{ {
UnmakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst); UnmakeMove(player,&xnode,&tempb,&tempc,&tempsf,&tempst);
/*ShowMessage("Illegal Move!!");*/ /*ShowMessage("Illegal Move!!");*/
return(false); return(false);
} }
@ -2283,10 +2286,20 @@ struct leaf *node;
GameList[GameCnt].nodes = 0; GameList[GameCnt].nodes = 0;
ElapsedTime(1); ElapsedTime(1);
GameList[GameCnt].time = (short)et; GameList[GameCnt].time = (short)et;
TimeControl.clock[opponent] -= et; TimeControl.clock[player] -= et;
--TimeControl.moves[opponent]; --TimeControl.moves[player];
*mv = (xnode.f << 8) + xnode.t; *mv = (xnode.f << 8) + xnode.t;
algbr(xnode.f,xnode.t,false); algbr(xnode.f,xnode.t,false);
short index;
for (index=0;index<5;index++){
move_buffer[index] = mvstr1[index];
}
if (SqAtakd(PieceList[opponent_player][0],player)){
move_buffer[4] = '+';
move_buffer[5] = '\0';
}
return(true); return(true);
} }
} }

View file

@ -49,7 +49,7 @@ extern struct plugin_api* rb;
/* ---- The beginning of a GNUChess v2 APIfication ---- */ /* ---- The beginning of a GNUChess v2 APIfication ---- */
void SetTimeControl(void); void SetTimeControl(void);
void GNUChess_Initialize(void); void GNUChess_Initialize(void);
int VerifyMove(char s[],short iop,unsigned short *mv); int VerifyMove(short player, char s[],short iop,unsigned short *mv, char *move_buffer);
int SelectMove ( short side, short iop , void (*callback)(void), char *move_buffer ); int SelectMove ( short side, short iop , void (*callback)(void), char *move_buffer );
void InitializeStats ( void ); void InitializeStats ( void );
void ElapsedTime ( short iop ); void ElapsedTime ( short iop );

View file

@ -323,6 +323,7 @@ Sylvain Fourmanoit
Alex Parker Alex Parker
Mario Lang Mario Lang
Justin Foell Justin Foell
Igor Kuzmin
The libmad team The libmad team
The wavpack team The wavpack team
The ffmpeg team The ffmpeg team