diff options
author | Nils Wallménius <nils@rockbox.org> | 2007-09-02 10:11:46 +0000 |
---|---|---|
committer | Nils Wallménius <nils@rockbox.org> | 2007-09-02 10:11:46 +0000 |
commit | 5ccf18019ed9529564300dc13313705ab35b94b3 (patch) | |
tree | 09530f364102c0e315e8df72ec60e10244f2e78c /apps/plugins/chessbox/chessbox_pgn.c | |
parent | c00652b0a222b6d5a25437b972d34d72619b00a8 (diff) | |
download | rockbox-5ccf18019ed9529564300dc13313705ab35b94b3.tar.gz rockbox-5ccf18019ed9529564300dc13313705ab35b94b3.zip |
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
Diffstat (limited to 'apps/plugins/chessbox/chessbox_pgn.c')
-rw-r--r-- | apps/plugins/chessbox/chessbox_pgn.c | 381 |
1 files changed, 371 insertions, 10 deletions
diff --git a/apps/plugins/chessbox/chessbox_pgn.c b/apps/plugins/chessbox/chessbox_pgn.c index db95210a8d..fb04f6ac38 100644 --- a/apps/plugins/chessbox/chessbox_pgn.c +++ b/apps/plugins/chessbox/chessbox_pgn.c | |||
@@ -188,7 +188,8 @@ | |||
188 | #error CHESSBOX: Unsupported keypad | 188 | #error CHESSBOX: Unsupported keypad |
189 | #endif | 189 | #endif |
190 | 190 | ||
191 | #define LOG_FILE PLUGIN_DIR "/chessbox.log" | 191 | #define PGN_FILE PLUGIN_GAMES_DIR "/chessbox.pgn" |
192 | #define LOG_FILE PLUGIN_GAMES_DIR "/chessbox.log" | ||
192 | int loghandler; | 193 | int loghandler; |
193 | 194 | ||
194 | struct plugin_api* rb; | 195 | struct plugin_api* rb; |
@@ -520,6 +521,180 @@ void pgn_to_coords(struct pgn_ply_node* ply){ | |||
520 | color[locn[ply->row_from][ply->column_from]] = neutral; | 521 | color[locn[ply->row_from][ply->column_from]] = neutral; |
521 | } | 522 | } |
522 | 523 | ||
524 | void coords_to_pgn(struct pgn_ply_node* ply){ | ||
525 | int pos = 0,i,j; | ||
526 | unsigned short moving_piece = board[locn[ply->row_from][ply->column_from]]; | ||
527 | char unambiguous_position; | ||
528 | bool found = false; | ||
529 | char alg_move[5]; | ||
530 | char move_buffer[10]; | ||
531 | short move; | ||
532 | if (moving_piece == king){ | ||
533 | /* check castling */ | ||
534 | if (ply->column_from == 4 && ply->column_to == 6){ | ||
535 | /* castling kingside */ | ||
536 | rb->strcpy(ply->pgn_text,"O-O"); | ||
537 | ply->castle = true; | ||
538 | } else if (ply->column_from == 4 && ply->column_to == 2){ | ||
539 | /* castling queenside */ | ||
540 | rb->strcpy(ply->pgn_text,"O-O-O"); | ||
541 | } else { | ||
542 | if (board[locn[ply->row_to][ply->column_to]] != no_piece){ | ||
543 | rb->snprintf(ply->pgn_text,10,"Kx%c%c",'a'+ply->column_to, | ||
544 | '1'+ply->row_to); | ||
545 | } else { | ||
546 | rb->snprintf(ply->pgn_text,10,"K%c%c",'a'+ply->column_to, | ||
547 | '1'+ply->row_to); | ||
548 | } | ||
549 | } | ||
550 | } else if (moving_piece == pawn){ | ||
551 | if (ply->column_from != ply->column_to){ | ||
552 | /* check enpassant */ | ||
553 | if (board[locn[ply->row_to][ply->column_to]] == no_piece){ | ||
554 | ply->enpassant = true; | ||
555 | } | ||
556 | /* check promotions when taking a piece */ | ||
557 | if (ply->row_to == 0 || ply->row_to == 7) { | ||
558 | ply->promotion = true; | ||
559 | ply->promotion_piece = queen; | ||
560 | rb->snprintf(ply->pgn_text,10,"%cx%c%c=D", 'a'+ply->column_from, | ||
561 | 'a'+ply->column_to,'1'+ply->row_to); | ||
562 | } else { | ||
563 | rb->snprintf(ply->pgn_text,10,"%cx%c%c", 'a'+ply->column_from, | ||
564 | 'a'+ply->column_to,'1'+ply->row_to); | ||
565 | } | ||
566 | } else { | ||
567 | /* check promotions when not taking a piece */ | ||
568 | if (ply->row_to == 0 || ply->row_to == 7) { | ||
569 | ply->promotion = true; | ||
570 | ply->promotion_piece = queen; | ||
571 | rb->snprintf(ply->pgn_text,10,"%c%c=D", 'a'+ply->column_to, | ||
572 | '1'+ply->row_to); | ||
573 | } else { | ||
574 | rb->snprintf(ply->pgn_text,10,"%c%c", 'a'+ply->column_to, | ||
575 | '1'+ply->row_to); | ||
576 | } | ||
577 | } | ||
578 | } else { | ||
579 | /* verify ambiguous moves for the different kinds of pieces */ | ||
580 | unambiguous_position = '\0'; | ||
581 | if (moving_piece == knight){ | ||
582 | for (i=0;i<8;i++){ | ||
583 | if (ply->row_to + kn_offs[i][0] >= 0 && ply->row_to + kn_offs[i][0] <= 7 | ||
584 | && ply->column_to + kn_offs[i][1] >= 0 && ply->column_to + kn_offs[i][1] <= 7 | ||
585 | && board[locn[ply->row_to + kn_offs[i][0]][ply->column_to + kn_offs[i][1]]] == knight | ||
586 | && color[locn[ply->row_to + kn_offs[i][0]][ply->column_to + kn_offs[i][1]]] == ply->player | ||
587 | && (ply->row_to + kn_offs[i][0] != ply->row_from | ||
588 | || ply->column_to + kn_offs[i][1] != ply->column_from)){ | ||
589 | if (ply->row_to + kn_offs[i][0] != ply->row_from){ | ||
590 | unambiguous_position = '1' + ply->row_from; | ||
591 | } else { | ||
592 | unambiguous_position = 'a' + ply->column_from; | ||
593 | } | ||
594 | break; | ||
595 | } | ||
596 | } | ||
597 | } | ||
598 | if (moving_piece == rook || moving_piece == queen){ | ||
599 | found = false; | ||
600 | for (i=0;i<4;i++){ | ||
601 | j=1; | ||
602 | while (ply->row_to+(j*rk_offs[i][0]) >= 0 && ply->row_to+(j*rk_offs[i][0]) <= 7 && | ||
603 | ply->column_to+(j*rk_offs[i][1]) >= 0 && ply->column_to+(j*rk_offs[i][1]) <= 7){ | ||
604 | if (board[locn[ply->row_to+(j*rk_offs[i][0])][ply->column_to+(j*rk_offs[i][1])]] != no_piece) { | ||
605 | if (board[locn[ply->row_to+(j*rk_offs[i][0])][ply->column_to+(j*rk_offs[i][1])]] == moving_piece && | ||
606 | color[locn[ply->row_to+(j*rk_offs[i][0])][ply->column_to+(j*rk_offs[i][1])]] == ply->player && | ||
607 | (ply->row_to+(j*rk_offs[i][0]) != ply->row_from | ||
608 | || ply->column_to+(j*rk_offs[i][1]) != ply->column_from)) { | ||
609 | if (ply->row_to+(j*rk_offs[i][0]) != ply->row_from){ | ||
610 | unambiguous_position = '1' + ply->row_from; | ||
611 | } else { | ||
612 | unambiguous_position = 'a' + ply->column_from; | ||
613 | } | ||
614 | found = true; | ||
615 | } | ||
616 | break; | ||
617 | } | ||
618 | j++; | ||
619 | } | ||
620 | if (found) { | ||
621 | break; | ||
622 | } | ||
623 | } | ||
624 | } | ||
625 | if (moving_piece == bishop || (moving_piece == queen && !found)){ | ||
626 | for (i=0;i<4;i++){ | ||
627 | j=1; | ||
628 | while (ply->row_to+(j*bp_offs[i][0]) >= 0 && ply->row_to+(j*bp_offs[i][0]) <= 7 && | ||
629 | ply->column_to+(j*bp_offs[i][1]) >= 0 && ply->column_to+(j*bp_offs[i][1]) <= 7){ | ||
630 | if (board[locn[ply->row_to+(j*bp_offs[i][0])][ply->column_to+(j*bp_offs[i][1])]] != no_piece) { | ||
631 | if (board[locn[ply->row_to+(j*bp_offs[i][0])][ply->column_to+(j*bp_offs[i][1])]] == moving_piece && | ||
632 | color[locn[ply->row_to+(j*bp_offs[i][0])][ply->column_to+(j*bp_offs[i][1])]] == ply->player && | ||
633 | (ply->row_to+(j*bp_offs[i][0]) != ply->row_from | ||
634 | || ply->column_to+(j*bp_offs[i][1]) != ply->column_from)) { | ||
635 | if (ply->row_to+(j*bp_offs[i][0]) != ply->row_from){ | ||
636 | unambiguous_position = '1' + ply->row_from; | ||
637 | } else { | ||
638 | unambiguous_position = 'a' + ply->column_from; | ||
639 | } | ||
640 | found = true; | ||
641 | } | ||
642 | break; | ||
643 | } | ||
644 | j++; | ||
645 | } | ||
646 | if (found) { | ||
647 | break; | ||
648 | } | ||
649 | } | ||
650 | } | ||
651 | /* generate the first portion of the PGN text | ||
652 | * always as white so all uppercase, black/white considerations | ||
653 | * will be useful for FEN notation but not in this case | ||
654 | */ | ||
655 | if (unambiguous_position == '\0'){ | ||
656 | if (board[locn[ply->row_to][ply->column_to]] != no_piece){ | ||
657 | rb->snprintf(ply->pgn_text,10,"%cx%c%c", | ||
658 | pgn_from_piece(moving_piece,white) , | ||
659 | 'a'+ply->column_to, '1'+ply->row_to); | ||
660 | } else { | ||
661 | rb->snprintf(ply->pgn_text,10,"%c%c%c", | ||
662 | pgn_from_piece(moving_piece,white) , | ||
663 | 'a'+ply->column_to, '1'+ply->row_to); | ||
664 | } | ||
665 | } else { | ||
666 | if (board[locn[ply->row_to][ply->column_to]] != no_piece){ | ||
667 | rb->snprintf(ply->pgn_text,10,"%c%cx%c%c", | ||
668 | pgn_from_piece(moving_piece,white) , | ||
669 | unambiguous_position, 'a'+ply->column_to, | ||
670 | '1'+ply->row_to); | ||
671 | } else { | ||
672 | rb->snprintf(ply->pgn_text,10,"%c%c%c%c", | ||
673 | pgn_from_piece(moving_piece,white) , | ||
674 | unambiguous_position, 'a'+ply->column_to, | ||
675 | '1'+ply->row_to); | ||
676 | } | ||
677 | } | ||
678 | } | ||
679 | /* update the board */ | ||
680 | rb->snprintf(alg_move,5,"%c%c%c%c",'a' + ply->column_from, '1' + ply->row_from, | ||
681 | 'a' + ply->column_to, '1' + ply->row_to); | ||
682 | /* The function returns false if the move is invalid, but since we're | ||
683 | * replaying the game, that should not be posible | ||
684 | */ | ||
685 | VerifyMove (ply->player, alg_move , 0 , &move, move_buffer ); | ||
686 | |||
687 | /* add check/mate indicators */ | ||
688 | for (pos=0;ply->pgn_text[pos] != '\0';pos++); | ||
689 | if (ply->checkmate) { | ||
690 | ply->pgn_text[pos] = '#'; pos++; | ||
691 | ply->pgn_text[pos] = '\0'; pos++; | ||
692 | } else if (move_buffer[4] == '+'){ | ||
693 | ply->pgn_text[pos] = '+'; pos++; | ||
694 | ply->pgn_text[pos] = '\0'; pos++; | ||
695 | } | ||
696 | } | ||
697 | |||
523 | char * get_game_text(int selected_item, void *data, char *buffer){ | 698 | char * get_game_text(int selected_item, void *data, char *buffer){ |
524 | int i; | 699 | int i; |
525 | struct pgn_game_node *temp_node = (struct pgn_game_node *)data; | 700 | 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){ | |||
538 | return buffer; | 713 | return buffer; |
539 | } | 714 | } |
540 | 715 | ||
716 | void write_pgn_token(int fhandler, char *buffer, size_t *line_length){ | ||
717 | if (*line_length + rb->strlen(buffer) + 1 > 80){ | ||
718 | rb->fdprintf(fhandler,"\n"); | ||
719 | *line_length = 0; | ||
720 | } | ||
721 | rb->fdprintf(fhandler,"%s ",buffer); | ||
722 | *line_length += (rb->strlen(buffer) + 1); | ||
723 | } | ||
724 | |||
541 | /* ---- api functions ---- */ | 725 | /* ---- api functions ---- */ |
542 | struct pgn_game_node* pgn_list_games(struct plugin_api* api,const char* filename){ | 726 | struct pgn_game_node* pgn_list_games(struct plugin_api* api,const char* filename){ |
543 | int fhandler; | 727 | int fhandler; |
544 | char line_buffer[128]; | 728 | char line_buffer[128]; |
545 | struct pgn_game_node size_node, *first_game = NULL, *curr_node = NULL, *temp_node; | 729 | struct pgn_game_node size_node, *first_game = NULL; |
730 | struct pgn_game_node *curr_node = NULL, *temp_node; | ||
546 | unsigned short game_count = 1; | 731 | unsigned short game_count = 1; |
547 | int line_count = 0; | 732 | int line_count = 0; |
548 | bool header_start = true, game_start = false; | 733 | 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 | |||
577 | } else { | 762 | } else { |
578 | if (line_buffer[0] == '['){ | 763 | if (line_buffer[0] == '['){ |
579 | process_tag(curr_node, line_buffer); | 764 | process_tag(curr_node, line_buffer); |
580 | } else if (line_buffer[0] == '\r' || line_buffer[0] == '\n' || line_buffer[0] == '\0'){ | 765 | } else if (line_buffer[0] == '\r' |
766 | || line_buffer[0] == '\n' | ||
767 | || line_buffer[0] == '\0'){ | ||
581 | if (game_start) { | 768 | if (game_start) { |
582 | game_start = false; | 769 | game_start = false; |
583 | } else { | 770 | } else { |
@@ -594,7 +781,8 @@ struct pgn_game_node* pgn_list_games(struct plugin_api* api,const char* filename | |||
594 | return first_game; | 781 | return first_game; |
595 | } | 782 | } |
596 | 783 | ||
597 | struct pgn_game_node* pgn_show_game_list(struct plugin_api* api, struct pgn_game_node* first_game){ | 784 | struct pgn_game_node* pgn_show_game_list(struct plugin_api* api, |
785 | struct pgn_game_node* first_game){ | ||
598 | int curr_selection = 0; | 786 | int curr_selection = 0; |
599 | int button; | 787 | int button; |
600 | struct gui_synclist games_list; | 788 | struct gui_synclist games_list; |
@@ -638,8 +826,10 @@ struct pgn_game_node* pgn_show_game_list(struct plugin_api* api, struct pgn_game | |||
638 | } | 826 | } |
639 | } | 827 | } |
640 | 828 | ||
641 | void pgn_parse_game(struct plugin_api* api, const char* filename, struct pgn_game_node* selected_game){ | 829 | void pgn_parse_game(struct plugin_api* api, const char* filename, |
642 | struct pgn_ply_node size_ply, *first_ply = NULL, *temp_ply = NULL, *curr_node = NULL; | 830 | struct pgn_game_node* selected_game){ |
831 | struct pgn_ply_node size_ply, *first_ply = NULL; | ||
832 | struct pgn_ply_node *temp_ply = NULL, *curr_node = NULL; | ||
643 | int fhandler, i; | 833 | int fhandler, i; |
644 | char line_buffer[128]; | 834 | char line_buffer[128]; |
645 | char token_buffer[10]; | 835 | char token_buffer[10]; |
@@ -682,16 +872,20 @@ void pgn_parse_game(struct plugin_api* api, const char* filename, struct pgn_gam | |||
682 | temp_ply->prev_node = curr_node; | 872 | temp_ply->prev_node = curr_node; |
683 | curr_node = temp_ply; | 873 | curr_node = temp_ply; |
684 | } | 874 | } |
685 | rb->fdprintf(loghandler,"player: %u; pgn: %s; from: %u,%u; to: %u,%u; taken: %u.\n", | 875 | rb->fdprintf(loghandler, |
686 | temp_ply->player, temp_ply->pgn_text, temp_ply->row_from, temp_ply->column_from, | 876 | "player: %u; pgn: %s; from: %u,%u; to: %u,%u; taken: %u.\n", |
687 | temp_ply->row_to, temp_ply->column_to, temp_ply->taken_piece); | 877 | temp_ply->player, temp_ply->pgn_text, temp_ply->row_from, |
878 | temp_ply->column_from, temp_ply->row_to, | ||
879 | temp_ply->column_to, temp_ply->taken_piece); | ||
688 | } | 880 | } |
689 | } | 881 | } |
690 | } | 882 | } |
691 | 883 | ||
692 | rb->close(loghandler); | 884 | rb->close(loghandler); |
693 | 885 | ||
694 | /* additional dummy ply to represent end of file without loosing the previous node's pointer */ | 886 | /* additional dummy ply to represent end of file without |
887 | *loosing the previous node's pointer | ||
888 | */ | ||
695 | if (first_ply != NULL){ | 889 | if (first_ply != NULL){ |
696 | temp_ply = (struct pgn_ply_node *)pl_malloc(sizeof size_ply); | 890 | temp_ply = (struct pgn_ply_node *)pl_malloc(sizeof size_ply); |
697 | temp_ply->player = neutral; | 891 | temp_ply->player = neutral; |
@@ -701,3 +895,170 @@ void pgn_parse_game(struct plugin_api* api, const char* filename, struct pgn_gam | |||
701 | selected_game->first_ply = first_ply; | 895 | selected_game->first_ply = first_ply; |
702 | rb->close(fhandler); | 896 | rb->close(fhandler); |
703 | } | 897 | } |
898 | |||
899 | struct pgn_game_node* pgn_init_game(struct plugin_api* api){ | ||
900 | struct pgn_game_node game_size, *game; | ||
901 | struct pgn_ply_node ply_size, *ply; | ||
902 | struct tm *current_time; | ||
903 | |||
904 | rb = api; | ||
905 | |||
906 | if (bufptr == NULL){ | ||
907 | pl_malloc_init(); | ||
908 | } | ||
909 | |||
910 | /* create an "end of game" dummy ply and assign defaults */ | ||
911 | ply = (struct pgn_ply_node *)pl_malloc(sizeof ply_size); | ||
912 | ply->player = neutral; | ||
913 | ply->pgn_text[0] = '\0'; | ||
914 | ply->prev_node = NULL; | ||
915 | ply->next_node = NULL; | ||
916 | |||
917 | /* create the game and assign defaults */ | ||
918 | game = (struct pgn_game_node *)pl_malloc(sizeof game_size); | ||
919 | game->game_number = 0; | ||
920 | rb->strcpy(game->white_player,"Player"); | ||
921 | rb->strcpy(game->black_player,"GnuChess"); | ||
922 | current_time = rb->get_time(); | ||
923 | if (current_time->tm_year < 100){ | ||
924 | rb->snprintf(game->game_date,11,"????.??.??"); | ||
925 | } else { | ||
926 | rb->snprintf(game->game_date,11,"%4u.%2u.%2u",current_time->tm_year + 1900, | ||
927 | current_time->tm_mon + 1, current_time->tm_mday); | ||
928 | } | ||
929 | rb->strcpy(game->result,"*"); | ||
930 | game->pgn_line = 0; | ||
931 | game->first_ply = ply; | ||
932 | game->next_node = NULL; | ||
933 | |||
934 | return game; | ||
935 | } | ||
936 | |||
937 | void pgn_append_ply(struct plugin_api* api, struct pgn_game_node* game, | ||
938 | unsigned short ply_player, char *move_buffer, bool is_mate){ | ||
939 | struct pgn_ply_node ply_size, *ply, *temp; | ||
940 | |||
941 | rb = api; | ||
942 | |||
943 | ply = (struct pgn_ply_node *)pl_malloc(sizeof ply_size); | ||
944 | ply->player = ply_player; | ||
945 | ply->column_from = move_buffer[0] - 'a'; | ||
946 | ply->row_from = move_buffer[1] - '1'; | ||
947 | ply->column_to = move_buffer[2] - 'a'; | ||
948 | ply->row_to = move_buffer[3] - '1'; | ||
949 | ply->castle = false; | ||
950 | ply->promotion = false; | ||
951 | ply->enpassant = false; | ||
952 | ply->promotion_piece = no_piece; | ||
953 | ply->taken_piece = no_piece; | ||
954 | ply->draw = false; | ||
955 | ply->checkmate = is_mate; | ||
956 | |||
957 | /* move the pointer to the "end of game" marker ply */ | ||
958 | for (temp=game->first_ply;temp->next_node!=NULL;temp=temp->next_node); | ||
959 | |||
960 | /* arrange the pointers to insert the ply before the marker */ | ||
961 | ply->next_node = temp; | ||
962 | ply->prev_node = temp->prev_node; | ||
963 | if (temp->prev_node == NULL){ | ||
964 | game->first_ply = ply; | ||
965 | } else { | ||
966 | temp->prev_node->next_node = ply; | ||
967 | } | ||
968 | temp->prev_node = ply; | ||
969 | } | ||
970 | |||
971 | void pgn_set_result(struct plugin_api* api, struct pgn_game_node* game, | ||
972 | bool is_mate){ | ||
973 | |||
974 | rb = api; | ||
975 | |||
976 | struct pgn_ply_node *ply; | ||
977 | for(ply=game->first_ply;ply->next_node != NULL;ply=ply->next_node); | ||
978 | if (is_mate){ | ||
979 | ply->prev_node->checkmate = true; | ||
980 | } else { | ||
981 | ply->prev_node->draw = true; | ||
982 | } | ||
983 | } | ||
984 | |||
985 | void pgn_store_game(struct plugin_api* api, struct pgn_game_node* game){ | ||
986 | int fhandler; | ||
987 | struct pgn_ply_node *ply; | ||
988 | unsigned ply_count; | ||
989 | size_t line_length=0; | ||
990 | char buffer[10]; | ||
991 | |||
992 | rb = api; | ||
993 | |||
994 | GNUChess_Initialize(); | ||
995 | |||
996 | ply_count=0; | ||
997 | ply=game->first_ply; | ||
998 | while (ply->next_node!=NULL){ | ||
999 | coords_to_pgn(ply); | ||
1000 | if (ply->checkmate){ | ||
1001 | if (ply->player == white){ | ||
1002 | rb->strcpy(game->result,"1-0"); | ||
1003 | } else { | ||
1004 | rb->strcpy(game->result,"0-1"); | ||
1005 | } | ||
1006 | } | ||
1007 | if (ply->draw){ | ||
1008 | rb->strcpy(game->result,"1/2-1/2"); | ||
1009 | } | ||
1010 | ply=ply->next_node; | ||
1011 | ply_count++; | ||
1012 | } | ||
1013 | |||
1014 | fhandler = rb->open(PGN_FILE, O_WRONLY|O_CREAT|O_APPEND); | ||
1015 | |||
1016 | |||
1017 | /* the first 7 tags are mandatory according to the PGN specification so we | ||
1018 | * have to include them even if the values don't make much sense | ||
1019 | */ | ||
1020 | rb->fdprintf(fhandler,"[Event \"Casual Game\"]\n"); | ||
1021 | rb->fdprintf(fhandler,"[Site \"?\"]\n"); | ||
1022 | rb->fdprintf(fhandler,"[Date \"%s\"]\n",game->game_date); | ||
1023 | rb->fdprintf(fhandler,"[Round \"?\"]\n"); | ||
1024 | rb->fdprintf(fhandler,"[White \"%s\"]\n",game->white_player); | ||
1025 | rb->fdprintf(fhandler,"[Black \"%s\"]\n",game->black_player); | ||
1026 | rb->fdprintf(fhandler,"[Result \"%s\"]\n",game->result); | ||
1027 | rb->fdprintf(fhandler,"[PlyCount \"%u\"]\n",ply_count); | ||
1028 | |||
1029 | /* leave a blank line between the tag section and the game section */ | ||
1030 | rb->fdprintf(fhandler,"\n"); | ||
1031 | |||
1032 | /* write the plies in several lines of up to 80 characters */ | ||
1033 | for (ply_count=0, ply=game->first_ply;ply->next_node!=NULL; | ||
1034 | ply=ply->next_node,ply_count++){ | ||
1035 | /* write the move number */ | ||
1036 | if (ply->player == white){ | ||
1037 | rb->snprintf(buffer,10,"%u.",(ply_count/2)+1); | ||
1038 | write_pgn_token(fhandler, buffer, &line_length); | ||
1039 | } | ||
1040 | /* write the actual move */ | ||
1041 | write_pgn_token(fhandler,ply->pgn_text,&line_length); | ||
1042 | /* write the result of the game at the end */ | ||
1043 | if (ply->checkmate){ | ||
1044 | if (ply->player == white){ | ||
1045 | write_pgn_token(fhandler,"1-0",&line_length); | ||
1046 | } else { | ||
1047 | write_pgn_token(fhandler,"0-1",&line_length); | ||
1048 | } | ||
1049 | break; | ||
1050 | } else if (ply->draw){ | ||
1051 | write_pgn_token(fhandler,"1/2-1/2",&line_length); | ||
1052 | break; | ||
1053 | } else if (ply->next_node->player == neutral) { | ||
1054 | /* unknown end of the game */ | ||
1055 | write_pgn_token(fhandler,"*",&line_length); | ||
1056 | break; | ||
1057 | } | ||
1058 | } | ||
1059 | |||
1060 | /* leave a blank line between the tag section and the game section */ | ||
1061 | rb->fdprintf(fhandler,"\n\n"); | ||
1062 | |||
1063 | rb->close(fhandler); | ||
1064 | } | ||