#include "model.h" /* * Create empty move */ s_move *create_empty_move(){ s_move * value = (s_move*) malloc(sizeof(s_move)); if ( value ) { value->inner_position = FREE; value->outer_position = FREE; value->player = NOBODY; } return value; } /* * Create an empty tictactoe */ s_tictactoe *create_empty_tictactoe() { // Create s_tictactoe structure s_tictactoe * value = (s_tictactoe*) malloc(sizeof(s_tictactoe)); if ( value ) { // create player value->winner = NOBODY; value->content = (e_player*) malloc(sizeof(e_player) * TICTACTOE_SIZE); if ( ! value->content ) { return NULL; } for ( int i=0;icontent[i] = NOBODY; } } return value; } /* * Create empty uTicTacToe */ s_utictactoe *create_empty_utictactoe (uint inception_level) { s_utictactoe * value = (s_utictactoe*) malloc(sizeof(s_utictactoe)); if ( value ) { // then initiate outer_tictactoe amd inception_level value->outer_tictactoe = create_empty_tictactoe(); value->inception_level = inception_level; value->history = NULL; // no history for now // initialize inner TTT if (inception_level == 1){ value->inner_tictactoes = NULL; } else { // As inception level can't be more than 2 (for now), inner_ttts // should be 9 simple ttt value->inner_tictactoes = (s_tictactoe**) malloc(TICTACTOE_SIZE*sizeof(s_tictactoe)); if ( ! value->inner_tictactoes ) { return NULL; } for ( int i=0; iinner_tictactoes[i]= (s_tictactoe*) malloc(sizeof(s_tictactoe)); value->inner_tictactoes[i] = create_empty_tictactoe(); } } } return value; } void free_move(s_move *p_move){ if ( p_move ) { free(p_move); p_move = NULL; } } void free_tictactoe(s_tictactoe *p_ttt){ if ( p_ttt) { free(p_ttt->content); p_ttt->content = NULL; free(p_ttt); p_ttt = NULL; } } void free_utictactoe(s_utictactoe *p_uttt){ if ( p_uttt ) { // if we have inner_ttt we need to remove inet if ( p_uttt->inner_tictactoes != NULL ) { for ( int i=0; iinner_tictactoes[i]); } free(p_uttt->inner_tictactoes); p_uttt->inner_tictactoes = NULL; } free_tictactoe(p_uttt->outer_tictactoe); free(p_uttt); p_uttt = NULL; } } e_player get_next_player_to_play(s_utictactoe *p_uttt) { if ( p_uttt->outer_tictactoe->winner != NOBODY ) { return NOBODY; } if ( p_uttt->history == NULL ) { return PLAYER_X; } else if( p_uttt->history->last_move->player == PLAYER_O){ return PLAYER_X; } else { return PLAYER_O; } } e_location get_next_outer_position(s_utictactoe *p_uttt) { if ( p_uttt->inner_tictactoes != NULL && p_uttt->history != NULL) { e_location pos = p_uttt->history->last_move->inner_position; if ( p_uttt->inner_tictactoes[pos]->winner == NOBODY ) { return pos; } } return FREE; } e_status is_move_valid(s_utictactoe *p_uttt, s_move *p_move) { // Get back thois simple test if ( p_uttt->outer_tictactoe->winner != NOBODY ) { return NO; } // this is the awaited player that played? if ( get_next_player_to_play(p_uttt) != p_move->player ) { return NO; } // the outer position is correct? if ( get_next_outer_position(p_uttt) != FREE && get_next_outer_position(p_uttt) != p_move->outer_position) { return NO; } if ( p_uttt->inception_level == 1 ) { if ( p_uttt->outer_tictactoe->content[p_move->outer_position] != NOBODY ) { return NO; } } else { // Already winned inner TTT if ( p_uttt->inner_tictactoes[p_move->outer_position]->winner != NOBODY ) { return NO; } // position in the inner position is free? if ( p_uttt->inner_tictactoes[p_move->outer_position]->content[p_move->inner_position] != NOBODY ) { return NO; } } return YES; } void set_tictactoe_winner(s_tictactoe *p_ttt){ // columns for ( int i=0; i < TICTACTOE_WIDTH; i++ ) { if (p_ttt->content[i] != NOBODY &&p_ttt->content[i] == p_ttt->content[i+1] && p_ttt->content[i] == p_ttt->content[i+6]) { p_ttt->winner = p_ttt->content[i]; return; } } //lines for ( int i=0; i < TICTACTOE_SIZE; i=i+3 ) { if (p_ttt->content[i] != NOBODY &&p_ttt->content[i] == p_ttt->content[i+1] && p_ttt->content[i] == p_ttt->content[i+2]) { p_ttt->winner = p_ttt->content[i]; return; } } //diagonale if ( p_ttt->content[0] != NOBODY && p_ttt->content[0] == p_ttt->content[4] && p_ttt->content[0] == p_ttt->content[8] ) { p_ttt->winner = p_ttt->content[0]; return; } //diagonale if ( p_ttt->content[2] != NOBODY && p_ttt->content[2] == p_ttt->content[4] && p_ttt->content[2] == p_ttt->content[6] ) { p_ttt->winner = p_ttt->content[0]; return; } // check if a move could be done, if not retuen BOTH (no winner) for (int i = 0; i < TICTACTOE_SIZE; i++){ if ( p_ttt->content[i] == NOBODY ) { return; } } p_ttt->winner = BOTH; } e_status play_move(s_utictactoe *p_uttt, s_move *p_move) { if (is_move_valid(p_uttt, p_move) == YES) { p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; list_element_s_move *value = (list_element_s_move*) malloc(sizeof(list_element_s_move)); value->last_move = p_move; if ( p_uttt->history == NULL ){ value->next = NULL; } else { value->next = p_uttt->history; } p_uttt->history = value; } else { return NO; } if ( p_uttt->inception_level == 1 ) { p_uttt->outer_tictactoe->content[p_move->outer_position] = p_move->player; } else { p_uttt->inner_tictactoes[p_move->outer_position]->content[p_move->inner_position] = p_move->player; set_tictactoe_winner(p_uttt->inner_tictactoes[p_move->outer_position]); //check if we have a winner in inner_ttt then set player to outer if ( p_uttt->inner_tictactoes[p_move->outer_position]->winner != NOBODY ) { p_uttt->outer_tictactoe->content[p_move->outer_position] = p_uttt->inner_tictactoes[p_move->outer_position]->winner; } } set_tictactoe_winner(p_uttt->outer_tictactoe); return YES; }