250 lines
6.9 KiB
C
250 lines
6.9 KiB
C
#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;i<TICTACTOE_SIZE; i++){
|
|
value->content[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; i<TICTACTOE_SIZE; i++) {
|
|
//value->inner_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; i<TICTACTOE_SIZE; i++) {
|
|
free_tictactoe(p_uttt->inner_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;
|
|
}
|