Dumb but not dumber IA
This commit is contained in:
parent
033a436be2
commit
87e7ff5829
7 changed files with 145 additions and 34 deletions
|
@ -24,4 +24,9 @@ typedef enum {
|
||||||
ALMOST,
|
ALMOST,
|
||||||
} e_status;
|
} e_status;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HUMAN,
|
||||||
|
RANDOM,
|
||||||
|
CLEVER,
|
||||||
|
} e_tactic;
|
||||||
#endif /*COMMON*/
|
#endif /*COMMON*/
|
||||||
|
|
17
include/ia.h
Normal file
17
include/ia.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef IA_H
|
||||||
|
#define IA_H
|
||||||
|
#include "common.h"
|
||||||
|
#include "model.h"
|
||||||
|
/*!
|
||||||
|
* This function modify the move in parameter in order to get a valid move (1) randomly if tactic is 0 or
|
||||||
|
* (2) in a clever way if tactic is 1 in the corresponding utictactoe u.
|
||||||
|
*
|
||||||
|
* \param p_uttt a pointer on a s_utictactoe.
|
||||||
|
* \param p_move a pointer on a s_move to be modified.
|
||||||
|
* \param tactic an e_tactic set to 0 for random strategy and 1 for clever one.
|
||||||
|
*/
|
||||||
|
void best_move(s_utictactoe* p_uttt, s_move* p_move, e_tactic tactic);
|
||||||
|
|
||||||
|
s_tictactoe * clone_ttt( s_tictactoe * p_ttt );
|
||||||
|
e_location get_best_random_position( s_tictactoe * p_uttt, e_player player);
|
||||||
|
#endif
|
|
@ -25,8 +25,9 @@ int elocation_to_coord(e_location l);
|
||||||
* \param p_move a pointer on a s_move to be modified.
|
* \param p_move a pointer on a s_move to be modified.
|
||||||
* \param v a pointer on the view to use.
|
* \param v a pointer on the view to use.
|
||||||
*/
|
*/
|
||||||
void set_next_player_move(s_move * p_move, p_view v);
|
void set_next_player_move(s_move * p_move, p_view v, e_tactic tactic);
|
||||||
|
|
||||||
|
void display_winner(p_view v);
|
||||||
/*!
|
/*!
|
||||||
* This function free all the memory used by a given view which
|
* This function free all the memory used by a given view which
|
||||||
* reference is given.
|
* reference is given.
|
||||||
|
|
|
@ -3,4 +3,4 @@ set(CMAKE_C_FLAGS "-std=c99 -lncurses -g -Wall")
|
||||||
set(CMAKE_INSTALL_PREFIX ".")
|
set(CMAKE_INSTALL_PREFIX ".")
|
||||||
include_directories(../include)
|
include_directories(../include)
|
||||||
project(utictactoe)
|
project(utictactoe)
|
||||||
add_executable(${PROJECT_NAME} utictactoe.c model.c view.c)
|
add_executable(${PROJECT_NAME} utictactoe.c model.c view.c ia.c)
|
||||||
|
|
76
src/ia.c
Normal file
76
src/ia.c
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include "model.h"
|
||||||
|
#include "view.h"
|
||||||
|
#include "ia.h"
|
||||||
|
|
||||||
|
void best_move (s_utictactoe * p_uttt, s_move * m ,e_tactic tactic)
|
||||||
|
{
|
||||||
|
//do{
|
||||||
|
if ( p_uttt->inception_level == 1 ) {
|
||||||
|
m->outer_position = get_best_random_position(
|
||||||
|
p_uttt->outer_tictactoe,
|
||||||
|
m->player
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m->outer_position = get_next_outer_position(p_uttt);
|
||||||
|
if ( m->outer_position == FREE ) {
|
||||||
|
do {
|
||||||
|
m->outer_position = (e_location)(TOPLEFT + rand() % TICTACTOE_SIZE);
|
||||||
|
} while(p_uttt->inner_tictactoes[m->outer_position]->winner != NOBODY);
|
||||||
|
}
|
||||||
|
|
||||||
|
m->inner_position = get_best_random_position(
|
||||||
|
p_uttt->inner_tictactoes[m->outer_position],
|
||||||
|
m->player
|
||||||
|
);
|
||||||
|
}
|
||||||
|
//} while (is_move_valid(p_uttt,m) != YES);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_tictactoe * clone_ttt( s_tictactoe * p_ttt ) {
|
||||||
|
s_tictactoe * t = create_empty_tictactoe();
|
||||||
|
for (int i=0; i<TICTACTOE_SIZE; i++){
|
||||||
|
t->content[i] = p_ttt->content[i];
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
e_location get_best_random_position (s_tictactoe * p_ttt, e_player player) {
|
||||||
|
mvwprintw(stdscr, 13, 0, " ");
|
||||||
|
s_tictactoe * c_ttt = clone_ttt(p_ttt);
|
||||||
|
e_player opponent = ( player == PLAYER_O )?PLAYER_X:PLAYER_O;
|
||||||
|
|
||||||
|
// Check if IA player can win
|
||||||
|
for(int i=0; i<TICTACTOE_SIZE; i++) {
|
||||||
|
if(c_ttt->content[i] == NOBODY) {
|
||||||
|
c_ttt->content[i] = player;
|
||||||
|
set_tictactoe_winner(c_ttt);
|
||||||
|
if ( c_ttt->winner != NOBODY ) {
|
||||||
|
free_tictactoe(c_ttt);
|
||||||
|
mvwprintw(stdscr, 13, 0, "Je vais gagner ");
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
c_ttt->content[i] = NOBODY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// avoid loosing
|
||||||
|
for(int i=0; i<TICTACTOE_SIZE; i++) {
|
||||||
|
if(c_ttt->content[i] == NOBODY) {
|
||||||
|
c_ttt->content[i] = opponent;
|
||||||
|
set_tictactoe_winner(c_ttt);
|
||||||
|
if ( c_ttt->winner != NOBODY ) {
|
||||||
|
free_tictactoe(c_ttt);
|
||||||
|
mvwprintw(stdscr, 13, 0, "Je ne peux pas te laisser gagner!");
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
c_ttt->content[i] = NOBODY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have not a winnner move...
|
||||||
|
free_tictactoe(c_ttt);
|
||||||
|
return (e_location)(rand() % TICTACTOE_SIZE);
|
||||||
|
}
|
|
@ -9,6 +9,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
|
#include "ia.h"
|
||||||
|
|
||||||
#define OPTIONAL_ARGUMENT_IS_PRESENT \
|
#define OPTIONAL_ARGUMENT_IS_PRESENT \
|
||||||
((optarg == NULL && optind < argc && argv[optind][0] != '-') \
|
((optarg == NULL && optind < argc && argv[optind][0] != '-') \
|
||||||
|
@ -46,15 +47,15 @@ int check_int_value ( char *value, int min, int max){
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
int optc;
|
int optc;
|
||||||
int cross_ai, round_ai = 0;
|
e_tactic tactic_cross = HUMAN, tactic_round = HUMAN;
|
||||||
int inception_level = 0;
|
int inception_level = 2;
|
||||||
bool verbose, contest_mode = false;
|
bool verbose, contest_mode = false;
|
||||||
char * contest_file;
|
char * contest_file;
|
||||||
static struct option long_opts[] =
|
static struct option long_opts[] =
|
||||||
{
|
{
|
||||||
{"inception-level", optional_argument, 0, 'i'},
|
{"inception-level", optional_argument, 0, 'i'},
|
||||||
{"cross-ai", required_argument, 0, 'x'},
|
{"tactic_cross", required_argument, 0, 'x'},
|
||||||
{"round-ai", required_argument, 0, 'o'},
|
{"tactic_round", required_argument, 0, 'o'},
|
||||||
{"contest", required_argument, 0, 'c'},
|
{"contest", required_argument, 0, 'c'},
|
||||||
{"verbose", no_argument, 0, 'v'},
|
{"verbose", no_argument, 0, 'v'},
|
||||||
{"version", no_argument, 0, 'V'},
|
{"version", no_argument, 0, 'V'},
|
||||||
|
@ -80,8 +81,8 @@ int main(int argc, char* argv[]) {
|
||||||
case 'x':
|
case 'x':
|
||||||
printf ("cross ai\n");
|
printf ("cross ai\n");
|
||||||
if ( optarg ) {
|
if ( optarg ) {
|
||||||
cross_ai = check_int_value(optarg, 0, 1);
|
tactic_cross = check_int_value(optarg, 0, 2);
|
||||||
if ( cross_ai == -1 ) {
|
if ( tactic_cross == -1 ) {
|
||||||
fprintf(stderr, "Error: incorrect cross ai value\n");
|
fprintf(stderr, "Error: incorrect cross ai value\n");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -96,8 +97,8 @@ int main(int argc, char* argv[]) {
|
||||||
case 'o':
|
case 'o':
|
||||||
printf ("round ai\n");
|
printf ("round ai\n");
|
||||||
if ( optarg ) {
|
if ( optarg ) {
|
||||||
round_ai = check_int_value(optarg, 0, 1);
|
tactic_round = check_int_value(optarg, 0, 2);
|
||||||
if ( round_ai == -1 ) {
|
if ( tactic_round == -1 ) {
|
||||||
fprintf(stderr, "Error: incorrect round ai value\n");
|
fprintf(stderr, "Error: incorrect round ai value\n");
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
@ -141,35 +142,23 @@ int main(int argc, char* argv[]) {
|
||||||
exit (EXIT_FAILURE);
|
exit (EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s_utictactoe *s = create_empty_utictactoe(1);
|
srand(time(NULL));
|
||||||
|
s_utictactoe *s = create_empty_utictactoe(inception_level);
|
||||||
s_move *m = create_empty_move();
|
s_move *m = create_empty_move();
|
||||||
p_view v = create_view(s);
|
p_view v = create_view(s);
|
||||||
while (s->outer_tictactoe->winner == NOBODY) {
|
|
||||||
m->player = get_next_player_to_play(s);
|
|
||||||
m->outer_position=get_next_outer_position(s);
|
|
||||||
set_next_player_move(m,v);
|
|
||||||
play_move(s, m);
|
|
||||||
}
|
|
||||||
free_view(v);
|
|
||||||
draw_utictactoe(s);
|
|
||||||
draw_utictactoe_history(s);
|
|
||||||
printf("The winner is : %c\n", s->outer_tictactoe->winner);
|
|
||||||
free_move(m);
|
|
||||||
free_utictactoe(s);
|
|
||||||
|
|
||||||
s = create_empty_utictactoe(2);
|
|
||||||
m = create_empty_move();
|
|
||||||
v = create_view(s);
|
|
||||||
while (s->outer_tictactoe->winner == NOBODY) {
|
while (s->outer_tictactoe->winner == NOBODY) {
|
||||||
m->player = get_next_player_to_play(s);
|
m->player = get_next_player_to_play(s);
|
||||||
m->outer_position=get_next_outer_position(s);
|
m->outer_position = get_next_outer_position(s);
|
||||||
set_next_player_move(m,v);
|
if (m->player == PLAYER_X) {
|
||||||
|
set_next_player_move(m, v, tactic_cross);
|
||||||
|
} else {
|
||||||
|
set_next_player_move(m, v, tactic_round);
|
||||||
|
}
|
||||||
play_move(s, m);
|
play_move(s, m);
|
||||||
m->outer_position = m->inner_position;
|
|
||||||
}
|
}
|
||||||
|
display_winner(v);
|
||||||
|
getchar();//just to pause before quitting the program
|
||||||
free_view(v);
|
free_view(v);
|
||||||
draw_utictactoe_history(s);
|
|
||||||
printf("The winner is : %c\n", s->outer_tictactoe->winner);
|
|
||||||
free_move(m);
|
free_move(m);
|
||||||
free_utictactoe(s);
|
free_utictactoe(s);
|
||||||
}
|
}
|
||||||
|
|
27
src/view.c
27
src/view.c
|
@ -1,6 +1,7 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
#include "view.h"
|
#include "view.h"
|
||||||
|
#include "ia.h"
|
||||||
|
|
||||||
struct view{
|
struct view{
|
||||||
s_utictactoe * p_uttt;
|
s_utictactoe * p_uttt;
|
||||||
|
@ -66,8 +67,15 @@ void draw_ttt(WINDOW * w, s_tictactoe * u){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_next_player_move(s_move * m, p_view v)
|
void set_next_player_move(s_move * m, p_view v, e_tactic tactic )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// computer player
|
||||||
|
if(tactic != HUMAN) {
|
||||||
|
best_move(v->p_uttt, m, tactic);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
char * s="Player to play:%c";
|
char * s="Player to play:%c";
|
||||||
int in_x = 3, out_x = 3;
|
int in_x = 3, out_x = 3;
|
||||||
int out_y = 2, in_y = 2;
|
int out_y = 2, in_y = 2;
|
||||||
|
@ -120,7 +128,7 @@ void set_next_player_move(s_move * m, p_view v)
|
||||||
wrefresh(v->w_uttt);
|
wrefresh(v->w_uttt);
|
||||||
if (v->p_uttt->inception_level == 2) wrefresh(v->w_ttt);
|
if (v->p_uttt->inception_level == 2) wrefresh(v->w_ttt);
|
||||||
wrefresh(stdscr);
|
wrefresh(stdscr);
|
||||||
|
|
||||||
ch = wgetch(stdscr);
|
ch = wgetch(stdscr);
|
||||||
|
|
||||||
switch(ch)
|
switch(ch)
|
||||||
|
@ -242,6 +250,21 @@ int elocation_to_coord(e_location l){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void display_winner(p_view v){
|
||||||
|
int ch = ' ';
|
||||||
|
draw_ttt(v->w_uttt, v->p_uttt->outer_tictactoe);
|
||||||
|
wrefresh(v->w_uttt);
|
||||||
|
if (v->p_uttt->inception_level == 2){
|
||||||
|
draw_ttt(v->w_ttt, v->p_uttt->inner_tictactoes[TOPLEFT]);
|
||||||
|
}
|
||||||
|
wrefresh(stdscr);
|
||||||
|
do {
|
||||||
|
mvwprintw(stdscr, 1, 0, "le gagnant est : %c, apputez sur 'entree' pour quitter",
|
||||||
|
v->p_uttt->outer_tictactoe->winner);
|
||||||
|
ch = wgetch(stdscr);
|
||||||
|
} while (ch != '\n');
|
||||||
|
|
||||||
|
}
|
||||||
void free_view(p_view v){
|
void free_view(p_view v){
|
||||||
delwin(v->w_uttt);
|
delwin(v->w_uttt);
|
||||||
v->w_uttt = NULL;
|
v->w_uttt = NULL;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue