/* * tree.c: game-tree-related functions * Copyright (C) 2015, Haldean Brown * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */#include"grandmaster.h"#include"grandmaster_internal.h"#include"gametree.h"#include<stdlib.h>#include<string.h>voidinit_gametree(structgame_tree*gt){gt->n_states=1;gt->states=calloc(1,sizeof(structstate_node*));gt->n_games=0;gt->games=NULL;gt->states[0]=calloc(1,sizeof(structstate_node));gt->states[0]->n_children=0;gt->states[0]->children=NULL;gt->states[0]->parent=NULL;gt->states[0]->move=calloc(1,sizeof(structmove));get_root(gt->states[0]->move);}game_id_tnew_game(structgame_tree*gt,player_id_twhite,player_id_tblack){structgame**new_games;inti;new_games=realloc(gt->games,(gt->n_games+1)*sizeof(structgame*));if(new_games==NULL){returnNO_GAME;}i=gt->n_games;gt->games=new_games;gt->n_games++;gt->games[i]=calloc(1,sizeof(structgame));gt->games[i]->id=i;gt->games[i]->player_white=white;gt->games[i]->player_black=black;gt->games[i]->current=gt->states[0];returngt->games[i]->id;}boolmoves_equivalent(structmove*m1,structmove*m2){if(m1->parent!=m2->parent)returnfalse;if(m1->start.rank!=m2->start.rank)returnfalse;if(m1->start.file!=m2->start.file)returnfalse;if(m1->end.rank!=m2->end.rank)returnfalse;if(m1->end.file!=m2->end.file)returnfalse;returntrue;}boolmake_move(structgame_tree*gt,game_id_tgame_id,constchar*notation){structgame*game;structmove*move;structmove*t;structstate_node**new_children;structstate_node**new_states;size_ti;size_tj;game=get_game(gt,game_id);move=NULL;parse_algebraic(notation,game->current->move,&move);if(move==NULL)returnfalse;for(i=0;i<game->current->n_children;i++){t=game->current->children[i]->move;if(moves_equivalent(move,t)){free_move(move);game->current=game->current->children[i];returntrue;}}new_states=realloc(gt->states,(gt->n_states+1)*sizeof(structstate_node*));if(new_states==NULL)returnfalse;i=gt->n_states;gt->n_states++;gt->states=new_states;gt->states[i]=calloc(1,sizeof(structstate_node));gt->states[i]->move=move;gt->states[i]->n_children=0;gt->states[i]->children=NULL;gt->states[i]->parent=game->current;new_children=realloc(game->current->children,(game->current->n_children+1)*sizeof(structstate_node*));if(new_children==NULL)returnfalse;game->current->children=new_children;j=game->current->n_children;game->current->n_children++;game->current->children[j]=gt->states[i];game->current=gt->states[i];returntrue;}structgame*get_game(structgame_tree*gt,game_id_tgame){size_ti;for(i=0;i<gt->n_games;i++){if(gt->games[i]->id==game)returngt->games[i];}returnNULL;}voidget_root(structmove*out){memset(out,0,sizeof(structmove));out->player=BLACK;out->post_board=calloc(1,sizeof(structboard));load_default_board(out->post_board);build_access_map(out,out->post_board->access_map);}voidfree_move_tree(structmove*move){if(move->parent!=NULL)free_move_tree(move->parent);free_move(move);}voidfree_move(structmove*move){if(move->post_board!=NULL){if(move->post_board->access_map!=NULL)free(move->post_board->access_map);free(move->post_board);}if(move->algebraic!=NULL)free(move->algebraic);free(move);}