From be0cbc940641264fe536ea1b3c1153f627367f55 Mon Sep 17 00:00:00 2001 From: Nils Wallménius Date: Tue, 29 May 2007 16:37:15 +0000 Subject: Oops forgot to svn add new files git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13516 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/chessbox/chessbox_pgn.c | 702 +++++++++++++++++++++++++++++++++++ apps/plugins/chessbox/chessbox_pgn.h | 67 ++++ 2 files changed, 769 insertions(+) create mode 100644 apps/plugins/chessbox/chessbox_pgn.c create mode 100644 apps/plugins/chessbox/chessbox_pgn.h (limited to 'apps') diff --git a/apps/plugins/chessbox/chessbox_pgn.c b/apps/plugins/chessbox/chessbox_pgn.c new file mode 100644 index 0000000000..0cdd8d82e5 --- /dev/null +++ b/apps/plugins/chessbox/chessbox_pgn.c @@ -0,0 +1,702 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* Copyright (C) 2007 Mauricio Peccorini +* +* All files in this archive are subject to the GNU General Public License. +* See the file COPYING in the source tree root for full license agreement. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ + +#include "chessbox_pgn.h" +#include "plugin.h" + +/* button definitions */ +#if (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) +#define CB_SELECT BUTTON_SELECT +#define CB_UP BUTTON_MENU +#define CB_DOWN BUTTON_PLAY +#define CB_LEFT BUTTON_LEFT +#define CB_RIGHT BUTTON_RIGHT +#define CB_PLAY (BUTTON_SELECT | BUTTON_PLAY) +#define CB_LEVEL (BUTTON_SELECT | BUTTON_RIGHT) +#define CB_RESTART (BUTTON_SELECT | BUTTON_LEFT) +#define CB_MENU (BUTTON_SELECT | BUTTON_MENU) + +#define CB_SCROLL_UP (BUTTON_SCROLL_FWD|BUTTON_REPEAT) +#define CB_SCROLL_DOWN (BUTTON_SCROLL_BACK|BUTTON_REPEAT) +#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) +#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD +#define CB_SELECT BUTTON_SELECT +#define CB_UP BUTTON_UP +#define CB_DOWN BUTTON_DOWN +#define CB_LEFT BUTTON_LEFT +#define CB_RIGHT BUTTON_RIGHT +#define CB_PLAY BUTTON_PLAY +#define CB_LEVEL BUTTON_REC +#define CB_RESTART (BUTTON_SELECT | BUTTON_PLAY) +#define CB_MENU BUTTON_POWER + +#define CB_SCROLL_UP (BUTTON_UP|BUTTON_REPEAT) +#define CB_SCROLL_DOWN (BUTTON_DOWN|BUTTON_REPEAT) +#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) +#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) + +#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) +#define CB_SELECT BUTTON_SELECT +#define CB_UP BUTTON_UP +#define CB_DOWN BUTTON_DOWN +#define CB_LEFT BUTTON_LEFT +#define CB_RIGHT BUTTON_RIGHT +#define CB_PLAY BUTTON_ON +#define CB_LEVEL BUTTON_MODE +#define CB_RESTART BUTTON_REC +#define CB_MENU BUTTON_OFF + +#define CB_RC_QUIT BUTTON_RC_STOP + +#define CB_SCROLL_UP (BUTTON_UP|BUTTON_REPEAT) +#define CB_SCROLL_DOWN (BUTTON_DOWN|BUTTON_REPEAT) +#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) +#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD +#define CB_SELECT BUTTON_SELECT +#define CB_UP BUTTON_UP +#define CB_DOWN BUTTON_DOWN +#define CB_LEFT BUTTON_LEFT +#define CB_RIGHT BUTTON_RIGHT +#define CB_PLAY BUTTON_PLAY +#define CB_LEVEL BUTTON_EQ +#define CB_MENU BUTTON_MODE + +#define CB_SCROLL_UP (BUTTON_UP|BUTTON_REPEAT) +#define CB_SCROLL_DOWN (BUTTON_DOWN|BUTTON_REPEAT) +#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) +#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == RECORDER_PAD +#define CB_SELECT BUTTON_PLAY +#define CB_UP BUTTON_UP +#define CB_DOWN BUTTON_DOWN +#define CB_LEFT BUTTON_LEFT +#define CB_RIGHT BUTTON_RIGHT +#define CB_PLAY BUTTON_ON +#define CB_LEVEL BUTTON_F1 +#define CB_RESTART BUTTON_F3 +#define CB_MENU BUTTON_OFF + +#define CB_SCROLL_UP (BUTTON_UP|BUTTON_REPEAT) +#define CB_SCROLL_DOWN (BUTTON_DOWN|BUTTON_REPEAT) +#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) +#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD +#define CB_SELECT BUTTON_SELECT +#define CB_UP BUTTON_UP +#define CB_DOWN BUTTON_DOWN +#define CB_LEFT BUTTON_LEFT +#define CB_RIGHT BUTTON_RIGHT +#define CB_PLAY BUTTON_ON +#define CB_LEVEL BUTTON_F1 +#define CB_RESTART BUTTON_F3 +#define CB_MENU BUTTON_OFF + +#define CB_SCROLL_UP (BUTTON_UP|BUTTON_REPEAT) +#define CB_SCROLL_DOWN (BUTTON_DOWN|BUTTON_REPEAT) +#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) +#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == ONDIO_PAD +#define CB_SELECT_PRE BUTTON_MENU +#define CB_SELECT (BUTTON_MENU|BUTTON_REL) +#define CB_UP BUTTON_UP +#define CB_DOWN BUTTON_DOWN +#define CB_LEFT BUTTON_LEFT +#define CB_RIGHT BUTTON_RIGHT +#define CB_PLAY_PRE BUTTON_MENU +#define CB_PLAY (BUTTON_MENU|BUTTON_REPEAT) +#define CB_LEVEL (BUTTON_MENU|BUTTON_OFF) +#define CB_RESTART (BUTTON_MENU|BUTTON_LEFT) +#define CB_MENU BUTTON_OFF + +#define CB_SCROLL_UP (BUTTON_UP|BUTTON_REPEAT) +#define CB_SCROLL_DOWN (BUTTON_DOWN|BUTTON_REPEAT) +#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) +#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) + +#elif (CONFIG_KEYPAD == GIGABEAT_PAD) +#define CB_SELECT BUTTON_SELECT +#define CB_UP BUTTON_UP +#define CB_DOWN BUTTON_DOWN +#define CB_LEFT BUTTON_LEFT +#define CB_RIGHT BUTTON_RIGHT +#define CB_PLAY BUTTON_POWER +#define CB_LEVEL BUTTON_MENU +#define CB_MENU BUTTON_A + +#define CB_SCROLL_UP (BUTTON_UP|BUTTON_REPEAT) +#define CB_SCROLL_DOWN (BUTTON_DOWN|BUTTON_REPEAT) +#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) +#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == IRIVER_H10_PAD +#define CB_SELECT BUTTON_REW +#define CB_UP BUTTON_SCROLL_UP +#define CB_DOWN BUTTON_SCROLL_DOWN +#define CB_LEFT BUTTON_LEFT +#define CB_RIGHT BUTTON_RIGHT +#define CB_PLAY BUTTON_PLAY +#define CB_LEVEL BUTTON_FF +#define CB_RESTART (BUTTON_REW | BUTTON_PLAY) +#define CB_MENU BUTTON_POWER + +#define CB_SCROLL_UP (BUTTON_SCROLL_UP|BUTTON_REPEAT) +#define CB_SCROLL_DOWN (BUTTON_SCROLL_DOWN|BUTTON_REPEAT) +#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) +#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) + +#elif CONFIG_KEYPAD == SANSA_E200_PAD +#define CB_SELECT BUTTON_SELECT +#define CB_UP BUTTON_UP +#define CB_DOWN BUTTON_DOWN +#define CB_LEFT BUTTON_LEFT +#define CB_RIGHT BUTTON_RIGHT +#define CB_PLAY (BUTTON_SELECT | BUTTON_RIGHT) +#define CB_LEVEL BUTTON_REC +#define CB_RESTART (BUTTON_SELECT | BUTTON_REPEAT) +#define CB_MENU BUTTON_POWER + +#define CB_SCROLL_UP (BUTTON_SCROLL_UP|BUTTON_REPEAT) +#define CB_SCROLL_DOWN (BUTTON_SCROLL_DOWN|BUTTON_REPEAT) +#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) +#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) + +#else + #error CHESSBOX: Unsupported keypad +#endif + +#define LOG_FILE PLUGIN_DIR "/chessbox.log" +int loghandler; + +struct plugin_api* rb; + +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}}; +short bp_offs[4][2] = {{1,1},{-1,1},{1,-1},{-1,-1}}; + +/* global vars for pl_malloc() */ +void *bufptr = NULL; +ssize_t bufleft; + +/* simple function to "allocate" memory in pluginbuffer. + * (borrowed from dict.c) + */ +void *pl_malloc(ssize_t size) +{ + void *ptr; + ptr = bufptr; + + if (bufleft < size) + { + return NULL; + } + else + { + bufptr += size; + return ptr; + } +} + +/* init function for pl_malloc() */ +void pl_malloc_init(void) +{ + bufptr = rb->plugin_get_buffer((size_t *)&bufleft); +} + +void process_tag(struct pgn_game_node* game, char* buffer){ + char tag_type[20]; + char tag_value[255]; + short pos=0, pos2=0; + while (buffer[pos+1] != ' '){ + tag_type[pos] = buffer[pos+1]; + pos++; + } + tag_type[pos] = '\0'; + pos+=3; + while (buffer[pos] != '"'){ + tag_value[pos2] = buffer[pos]; + pos++; pos2++; + } + + /* truncate tag values that are too large */ + if (pos2 > 19){ + pos2 = 19; + } + tag_value[pos2] = '\0'; + + if (rb->strcmp(tag_type,"White") == 0){ + rb->strcpy(game->white_player, tag_value); + } + if (rb->strcmp(tag_type,"Black") == 0){ + rb->strcpy(game->black_player, tag_value); + } + if (rb->strcmp(tag_type,"Result") == 0){ + rb->strcpy(game->result, tag_value); + } + if (rb->strcmp(tag_type,"Date") == 0){ + rb->strcpy(game->game_date, tag_value); + } +} + +unsigned short get_next_token(const char* line_buffer, unsigned short initial_pos, + char* token_buffer){ + unsigned short pos, token_pos=0; + for (pos = initial_pos;line_buffer[pos] == ' ' || line_buffer[pos] == '.';pos++); + do { + token_buffer[token_pos] = line_buffer[pos]; + pos++; token_pos++; + } while (line_buffer[pos] != ' ' && line_buffer[pos] != '.' + && line_buffer[pos] != '\0'); + /* ignore annotations */ + while (token_buffer[token_pos-1] == '!' || token_buffer[token_pos-1] == '?'){ + token_pos--; + } + token_buffer[token_pos] = '\0'; + return pos; +} + +unsigned short piece_from_pgn(char pgn_piece){ + switch (pgn_piece){ + case 'R': + return rook; + case 'N': + return knight; + case 'B': + return bishop; + case 'Q': + return queen; + case 'K': + return king; + } + return no_piece; +} + +char pgn_from_piece(unsigned short piece, unsigned short color){ + char pgn_piece = ' '; + switch (piece){ + case pawn: + pgn_piece = 'P'; + break; + case rook: + pgn_piece = 'R'; + break; + case knight: + pgn_piece = 'N'; + break; + case bishop: + pgn_piece = 'B'; + break; + case queen: + pgn_piece = 'Q'; + break; + case king: + pgn_piece = 'K'; + break; + case no_piece: + pgn_piece = ' '; + break; + } + if (color == black && pgn_piece != ' '){ + pgn_piece += 32; + } + return pgn_piece; +} + +void pgn_to_coords(struct pgn_ply_node* ply){ + unsigned short str_length = rb->strlen(ply->pgn_text); + char str[10]; + rb->strcpy(str,ply->pgn_text); + ply->column_from = 0xFF; + ply->row_from = 0xFF; + ply->column_to = 0xFF; + ply->row_to = 0xFF; + ply->taken_piece = no_piece; + ply->promotion_piece = no_piece; + ply->enpassant = false; + ply->castle = false; + ply->promotion = false; + unsigned short i, j, piece; + bool found = false; + + if (str_length >= 3 && (str[0] == 'O' || str[0] == '0') && str[1] == '-' + && (str[2] == 'O' || str[2] == '0')) { + /* castling */ + ply->castle = true; + if (str_length >= 5 && str[3] == '-' && (str[4] == 'O' || str[4] == '0')){ + /* castle queenside */ + if (ply->player == white){ + ply->row_from = 0; ply->column_from = 4; + ply->row_to = 0; ply->column_to = 2; + /* update the rook's position, the king's position will be updated later */ + board[locn[0][3]] = rook; color[locn[0][3]] = white; + board[locn[0][0]] = no_piece; color[locn[0][0]] = neutral; + } else { + ply->row_from = 7; ply->column_from = 4; + ply->row_to = 7; ply->column_to = 2; + board[locn[7][3]] = rook; color[locn[7][3]] = black; + board[locn[7][0]] = no_piece; color[locn[7][0]] = neutral; + } + } else { + /* castle kingside */ + if (ply->player == white){ + ply->row_from = 0; ply->column_from = 4; + ply->row_to = 0; ply->column_to = 6; + board[locn[0][5]] = rook; color[locn[0][5]] = white; + board[locn[0][7]] = no_piece; color[locn[0][7]] = neutral; + } else { + ply->row_from = 7; ply->column_from = 4; + ply->row_to = 7; ply->column_to = 6; + board[locn[7][5]] = rook; color[locn[7][5]] = black; + board[locn[7][7]] = no_piece; color[locn[7][7]] = neutral; + } + } + } else if (str[0] >= 'a' && str[0] <= 'h'){ + /* pawns */ + ply->column_from = str[0] - 'a'; + if (str[1] == 'x'){ + ply->row_from = str[3] - '1' + ((ply->player==white)?-1:1); + ply->row_to = str[3] - '1'; + ply->column_to = str[2] - 'a'; + if (board[locn[ply->row_to][ply->column_to]] == no_piece){ + /* en-passant, remove the pawn */ + ply->enpassant = true; + board[locn[ply->row_from][ply->column_to]] = no_piece; + color[locn[ply->row_from][ply->column_to]] = neutral; + ply->taken_piece = pawn; + } else { + ply->taken_piece = board[locn[ply->row_to][ply->column_to]]; + } + } else { + ply->column_to = ply->column_from; + ply->row_from = str[1] - '1' + ((ply->player==white)?-1:1); + ply->row_to = str[1] - '1'; + } + if (board[locn[ply->row_from][ply->column_from]] == no_piece){ + /* the pawn moved two squares */ + ply->row_from += ((ply->player==white)?-1:1); + } + if (ply->row_to == 7 || ply->row_to == 0){ + /* promotion */ + if (str[2] == '='){ + ply->promotion_piece = piece_from_pgn(str[3]); + } else { + ply->promotion_piece = piece_from_pgn(str[5]); + } + /* change the piece in the original position and wait + * for the code at the end to move it + */ + board[locn[ply->row_from][ply->column_from]] = ply->promotion_piece; + } + } else { + /* the other pieces */ + piece = piece_from_pgn(str[0]); + if (str[2] == 'x'){ + /* taken a piece and move was ambiguous */ + ply->column_to = str[3] - 'a'; + ply->row_to = str[4] - '1'; + ply->taken_piece = board[locn[ply->row_to][ply->column_to]]; + if (str[1] >= 'a' && str[1] <= 'h') { + ply->column_from = str[1] - 'a'; + } else { + ply->row_from = str[1] - '1'; + } + } else if (str[1] == 'x') { + /* taken a piece */ + ply->column_to = str[2] - 'a'; + ply->row_to = str[3] - '1'; + ply->taken_piece = board[locn[ply->row_to][ply->column_to]]; + } else if (str_length >= 4 && str[3] >= '0' && str[3] <= '9'){ + /* no piece taken and move was ambiguous */ + ply->column_to = str[2] - 'a'; + ply->row_to = str[3] - '1'; + if (str[1] >= 'a' && str[1] <= 'h') { + ply->column_from = str[1] - 'a'; + } else { + ply->row_from = str[1] - '1'; + } + } else { + /* regular move */ + ply->column_to = str[1] - 'a'; + ply->row_to = str[2] - '1'; + } + if (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_from == 0xFF || ply->row_from == ply->row_to + kn_offs[i][0]) + && (ply->column_from == 0xFF || ply->column_from == ply->column_to + kn_offs[i][1])) { + ply->row_from = ply->row_to + kn_offs[i][0]; + ply->column_from = ply->column_to + kn_offs[i][1]; + } + } + } + if (piece == rook || piece == queen || piece == king){ + for (i=0;i<4;i++){ + j = 1; + found = false; + 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])]] == piece && + color[locn[ply->row_to+(j*rk_offs[i][0])][ply->column_to+(j*rk_offs[i][1])]] == ply->player && + (ply->row_from == 0xFF || ply->row_from == ply->row_to+(j*rk_offs[i][0])) && + (ply->column_from == 0xFF || ply->column_from == ply->column_to+(j*rk_offs[i][1]))) { + ply->row_from = ply->row_to+(j*rk_offs[i][0]); + ply->column_from = ply->column_to+(j*rk_offs[i][1]); + found = true; + } + break; + } + j++; + } + if (found) { + break; + } + } + } + if (piece == bishop || ((piece == queen || piece == king) && !found)){ + for (i=0;i<4;i++){ + j = 1; + found = false; + 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])]] == piece && + color[locn[ply->row_to+(j*bp_offs[i][0])][ply->column_to+(j*bp_offs[i][1])]] == ply->player && + (ply->row_from == 0xFF || ply->row_from == ply->row_to+(j*bp_offs[i][0])) && + (ply->column_from == 0xFF || ply->column_from == ply->column_to+(j*bp_offs[i][1]))) { + ply->row_from = ply->row_to+(j*bp_offs[i][0]); + ply->column_from = ply->column_to+(j*bp_offs[i][1]); + found = true; + } + break; + } + j++; + } + if (found) { + break; + } + } + } + } + + /* leave a very complete log of the parsing of the game while it gets stable */ + for (i=0;i<8;i++){ + for (j=0;j<8;j++) { + rb->fdprintf(loghandler,"%c",pgn_from_piece(board[locn[7-i][j]],color[locn[7-i][j]])); + } + rb->fdprintf(loghandler,"\n"); + } + + /* update the board */ + board[locn[ply->row_to][ply->column_to]] = board[locn[ply->row_from][ply->column_from]]; + color[locn[ply->row_to][ply->column_to]] = color[locn[ply->row_from][ply->column_from]]; + board[locn[ply->row_from][ply->column_from]] = no_piece; + color[locn[ply->row_from][ply->column_from]] = neutral; +} + +char * get_game_text(int selected_item, void *data, char *buffer){ + int i; + struct pgn_game_node *temp_node = (struct pgn_game_node *)data; + char text_buffer[50]; + + for (i=0;inext_node; + } + if (temp_node == NULL){ + return NULL; + } + rb->snprintf(text_buffer, 50,"%s vs. %s (%s)", temp_node->white_player, + temp_node->black_player, temp_node->game_date); + + rb->strcpy(buffer, text_buffer); + return buffer; +} + +/* ---- api functions ---- */ +struct pgn_game_node* pgn_list_games(struct plugin_api* api,const char* filename){ + int fhandler; + char line_buffer[128]; + struct pgn_game_node size_node, *first_game = NULL, *curr_node = NULL, *temp_node; + unsigned short game_count = 1; + int line_count = 0; + bool header_start = true, game_start = false; + rb = api; + + if ( (fhandler = rb->open(filename, O_RDONLY)) == 0 ) return NULL; + + if (bufptr == NULL){ + pl_malloc_init(); + } + while (rb->read_line(fhandler, line_buffer, sizeof line_buffer) > 0){ + line_count++; + /* looking for a game header */ + if (header_start) { + /* a new game header is found */ + if (line_buffer[0] == '['){ + temp_node = (struct pgn_game_node *)pl_malloc(sizeof size_node); + temp_node->next_node = NULL; + if (curr_node == NULL) { + first_game = curr_node = temp_node; + } else { + curr_node->next_node = temp_node; + curr_node = temp_node; + } + process_tag(curr_node, line_buffer); + curr_node->game_number = game_count; + curr_node->pgn_line = 0; + game_count++; + header_start = false; + game_start = true; + } + } else { + if (line_buffer[0] == '['){ + process_tag(curr_node, line_buffer); + } else if (line_buffer[0] == '\r' || line_buffer[0] == '\n' || line_buffer[0] == '\0'){ + if (game_start) { + game_start = false; + } else { + header_start = true; + } + } else { + if (curr_node->pgn_line == 0) { + curr_node->pgn_line = line_count; + } + } + } + } + rb->close(fhandler); + return 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 button; + struct gui_synclist games_list; + int i; + struct pgn_game_node *temp_node = first_game; + + rb=api; + + for (i=0;temp_node != NULL;i++){ + temp_node = temp_node->next_node; + } + + + rb->gui_synclist_init(&games_list, &get_game_text, first_game, false, 1); + rb->gui_synclist_set_title(&games_list, "Games", NOICON); + rb->gui_synclist_set_icon_callback(&games_list, NULL); + rb->gui_synclist_set_nb_items(&games_list, i); + rb->gui_synclist_limit_scroll(&games_list, true); + rb->gui_synclist_select_item(&games_list, 0); + + while (true) { + rb->gui_syncstatusbar_draw(rb->statusbars, true); + rb->gui_synclist_draw(&games_list); + curr_selection = rb->gui_synclist_get_sel_pos(&games_list); + button = rb->get_action(CONTEXT_LIST,TIMEOUT_BLOCK); + if (rb->gui_synclist_do_button(&games_list,button,LIST_WRAP_OFF)){ + continue; + } + switch (button) { + case ACTION_STD_OK: + temp_node = first_game; + for (i=0;inext_node; + } + return temp_node; + break; + case ACTION_STD_CANCEL: + return NULL; + break; + } + } +} + +void pgn_parse_game(struct plugin_api* api, const char* filename, struct pgn_game_node* selected_game){ + struct pgn_ply_node size_ply, *first_ply = NULL, *temp_ply = NULL, *curr_node = NULL; + int fhandler, i; + char line_buffer[128]; + char token_buffer[10]; + unsigned short pos; + unsigned short curr_player = white; + rb = api; + + fhandler = rb->open(filename, O_RDONLY); + + /* seek the line where the pgn of the selected game starts */ + for (i=1;ipgn_line;i++){ + rb->read_line(fhandler, line_buffer, sizeof line_buffer); + } + + loghandler = rb->open(LOG_FILE, O_WRONLY | O_CREAT); + + GNUChess_Initialize(); + + while (rb->read_line(fhandler, line_buffer, sizeof line_buffer) > 0){ + if (line_buffer[0] == '\r' || line_buffer[0] == '\n' || line_buffer[0] == '\0'){ + break; + } + pos = 0; + while (pos < rb->strlen(line_buffer)){ + pos = get_next_token(line_buffer, pos, token_buffer); + if ((token_buffer[0] >= 'A' && token_buffer[0] <= 'Z') + || (token_buffer[0] >= 'a' && token_buffer[0] <= 'z') + || (token_buffer[0] == '0' && token_buffer[2] != '1')){ + temp_ply = (struct pgn_ply_node *)pl_malloc(sizeof size_ply); + temp_ply->player = curr_player; + curr_player = (curr_player==white)?black:white; + rb->strcpy(temp_ply->pgn_text, token_buffer); + pgn_to_coords(temp_ply); + temp_ply->prev_node = NULL; + temp_ply->next_node = NULL; + if (first_ply == NULL) { + first_ply = curr_node = temp_ply; + } else { + curr_node->next_node = temp_ply; + temp_ply->prev_node = curr_node; + curr_node = temp_ply; + } + rb->fdprintf(loghandler,"player: %u; pgn: %s; from: %u,%u; to: %u,%u; taken: %u.\n", + 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); + + /* additional dummy ply to represent end of file without loosing the previous node's pointer */ + if (first_ply != NULL){ + temp_ply = (struct pgn_ply_node *)pl_malloc(sizeof size_ply); + temp_ply->player = neutral; + temp_ply->prev_node = curr_node; + curr_node->next_node = temp_ply; + } + selected_game->first_ply = first_ply; + rb->close(fhandler); +} diff --git a/apps/plugins/chessbox/chessbox_pgn.h b/apps/plugins/chessbox/chessbox_pgn.h new file mode 100644 index 0000000000..541bbc8b81 --- /dev/null +++ b/apps/plugins/chessbox/chessbox_pgn.h @@ -0,0 +1,67 @@ +/*************************************************************************** +* __________ __ ___. +* Open \______ \ ____ ____ | | _\_ |__ _______ ___ +* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +* \/ \/ \/ \/ \/ +* $Id$ +* +* Copyright (C) 2007 Mauricio Peccorini +* +* All files in this archive are subject to the GNU General Public License. +* See the file COPYING in the source tree root for full license agreement. +* +* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +* KIND, either express or implied. +* +****************************************************************************/ + +#include "plugin.h" +#include "gnuchess.h" + +/* structure to represent the plies */ +struct pgn_ply_node { + unsigned short player; + char pgn_text[9]; + unsigned short row_from; + unsigned short column_from; + unsigned short row_to; + unsigned short column_to; + unsigned short taken_piece; + unsigned short promotion_piece; + bool enpassant; + bool castle; + bool promotion; + struct pgn_ply_node* prev_node; + struct pgn_ply_node* next_node; +}; + +/* structure to list the games */ +struct pgn_game_node { + unsigned short game_number; + char white_player[20]; + char black_player[20]; + char game_date[11]; + char result[8]; + int pgn_line; + struct pgn_ply_node* first_ply; + struct pgn_game_node* next_node; +}; + +/* 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 + * and speeds up response when the user selects the file + */ +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 + * 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); + +/* Parse the pgn string of a game and assign it to the move + * list in the structure + */ +void pgn_parse_game(struct plugin_api* api, const char* filename, struct pgn_game_node* selected_game); -- cgit v1.2.3