u_ttt/src/model.c
2021-10-08 17:00:14 +02:00

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;
}