Add TP2
This commit is contained in:
parent
887b7098bc
commit
89dce59af6
13 changed files with 1289 additions and 0 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -10,6 +10,9 @@
|
||||||
|
|
||||||
# Ignore les executables
|
# Ignore les executables
|
||||||
r0
|
r0
|
||||||
|
rand_player
|
||||||
|
player_A
|
||||||
|
player_B
|
||||||
|
|
||||||
# Ajoute les gitignores
|
# Ajoute les gitignores
|
||||||
!**/.gitignore
|
!**/.gitignore
|
||||||
|
|
6
TP2/Makefile
Normal file
6
TP2/Makefile
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
CC=g++
|
||||||
|
CFLAGS=-std=c++11 -Wall -O2
|
||||||
|
|
||||||
|
##### BREAKTHROUGH
|
||||||
|
rand_player: mybt.h rand_player.cpp
|
||||||
|
$(CC) $(CFLAGS) rand_player.cpp -o $@
|
48
TP2/README.txt
Normal file
48
TP2/README.txt
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/////////////////////////////////
|
||||||
|
/// TP recherche arborescente ///
|
||||||
|
/////////////////////////////////
|
||||||
|
|
||||||
|
objectif : ecrire le meilleur programme qui joue à breakthrough
|
||||||
|
(quel algorithme utilisé, comment implémenter une version rapide, comment améliorer le programme)
|
||||||
|
(tous les précalculs sont autorisés mais un seul cpu est autorisé pendant le tournoi)
|
||||||
|
(l'allocation mémoire est limitée à 1Go par programme)
|
||||||
|
|
||||||
|
Nous jouerons probablement à breakthrough 6x4 mais cela peut évoluer...
|
||||||
|
|
||||||
|
Nous jouerons tous ensemble en mode tournoi à double élimination.
|
||||||
|
Quand nous auront 2 ou 3 groupes restant, nous les ferons jouer tous contre tous et le moins bon sera éliminé à chaque round.
|
||||||
|
En cas d'égalité, nous regarderons les scores, puis les temps de calcul utilisé.
|
||||||
|
|
||||||
|
Chaque groupe de TP pourra inscrire un programme au tournoi.
|
||||||
|
Le seeding round sera un premier tour sans élimination.
|
||||||
|
|
||||||
|
(exemple pour 12 équipes)
|
||||||
|
SEEDING ROUND ROUND-1 ROUND-2 ROUND-3
|
||||||
|
============= ===================== ========== ==========
|
||||||
|
G1 vs G2 Victoire1 vs Victoire2 ... ...
|
||||||
|
G3 vs G4 Victoire3 vs Victoire4 ... ... (dès qu'une équipe à 2 défaite, elle est éliminée)
|
||||||
|
G5 vs G6 Victoire5 vs Victoire6 ...
|
||||||
|
G7 vs G8 Defaite1 vs Defaite2 (3 élmininations)
|
||||||
|
G9 vs G10 Defaite3 vs Defaite4
|
||||||
|
G11 vs G12 Defaite5 vs Defaite6
|
||||||
|
|
||||||
|
A breakthrough, toutes les pièces sont des pions
|
||||||
|
|
||||||
|
Fichiers fournis pour ce TP :
|
||||||
|
* mybt.h définit les structures bt_piece_t, bt_move_t et bt_t
|
||||||
|
* bt_piece_t qui modélise une piece
|
||||||
|
* bt_move_t qui modélise un coup
|
||||||
|
* bt_t qui modélise le plateau et ses contraintes
|
||||||
|
* rand_player.cpp est un joueur aléaoire qui supporte le breakthrough text protocol btp
|
||||||
|
* le protocol btp permet de controler un programme pour jouer a breakthrough
|
||||||
|
* game1.txt est un exemple de fichier de commandes btp
|
||||||
|
* run_many_games.pike est un programme pike permettant de faire jouer ensemble des programmes supportant le btp
|
||||||
|
* Makefile permet de compiler le rand_player
|
||||||
|
* mk_stats.sh permet de lancer plusieurs parties, stocker les logs et les stats
|
||||||
|
|
||||||
|
Pour le moment, on posera pour contrainte de répondre le coup à jouer en 1 sec
|
||||||
|
Au delà de 1 sec, l'absence de réponse sera considérée comme un abandon
|
||||||
|
|
||||||
|
Au dela de la competition, chaque groupe doit rendre :
|
||||||
|
+ les sources de son programme
|
||||||
|
+ un rapport en 1 page (ou +) présentant les particularités/optimisations de son programme
|
50
TP2/data/scores.txt
Normal file
50
TP2/data/scores.txt
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
(./rand_player -11 24.00) (./rand_player 11 24.00) => ./rand_player win
|
||||||
|
(./rand_player -11 24.00) (./rand_player 11 24.00) => ./rand_player win
|
||||||
|
(./rand_player 12 24.00) (./rand_player -12 24.00) => ./rand_player win
|
||||||
|
(./rand_player -10 24.00) (./rand_player 10 24.00) => ./rand_player win
|
||||||
|
(./rand_player -11 24.00) (./rand_player 11 24.00) => ./rand_player win
|
||||||
|
(./rand_player 13 24.00) (./rand_player -13 24.00) => ./rand_player win
|
||||||
|
(./rand_player -10 24.00) (./rand_player 10 24.00) => ./rand_player win
|
||||||
|
(./rand_player 8 24.00) (./rand_player -8 24.00) => ./rand_player win
|
||||||
|
(./rand_player -8 24.00) (./rand_player 8 24.00) => ./rand_player win
|
||||||
|
(./rand_player 12 24.00) (./rand_player -12 24.00) => ./rand_player win
|
||||||
|
(./rand_player 12 24.00) (./rand_player -12 24.00) => ./rand_player win
|
||||||
|
(./rand_player 13 24.00) (./rand_player -13 24.00) => ./rand_player win
|
||||||
|
(./rand_player 13 24.00) (./rand_player -13 24.00) => ./rand_player win
|
||||||
|
(./rand_player -13 24.00) (./rand_player 13 24.00) => ./rand_player win
|
||||||
|
(./rand_player 14 24.00) (./rand_player -14 24.00) => ./rand_player win
|
||||||
|
(./rand_player 13 24.00) (./rand_player -13 24.00) => ./rand_player win
|
||||||
|
(./rand_player -10 24.00) (./rand_player 10 24.00) => ./rand_player win
|
||||||
|
(./rand_player -11 24.00) (./rand_player 11 24.00) => ./rand_player win
|
||||||
|
(./rand_player 10 24.00) (./rand_player -10 24.00) => ./rand_player win
|
||||||
|
(./rand_player 15 24.00) (./rand_player -15 24.00) => ./rand_player win
|
||||||
|
(./rand_player 12 24.00) (./rand_player -12 24.00) => ./rand_player win
|
||||||
|
(./rand_player -11 24.00) (./rand_player 11 24.00) => ./rand_player win
|
||||||
|
(./rand_player -13 24.00) (./rand_player 13 24.00) => ./rand_player win
|
||||||
|
(./rand_player 15 24.00) (./rand_player -15 24.00) => ./rand_player win
|
||||||
|
(./rand_player 13 24.00) (./rand_player -13 24.00) => ./rand_player win
|
||||||
|
(./rand_player -12 24.00) (./rand_player 12 24.00) => ./rand_player win
|
||||||
|
(./rand_player 9 24.00) (./rand_player -9 24.00) => ./rand_player win
|
||||||
|
(./rand_player 9 24.00) (./rand_player -9 24.00) => ./rand_player win
|
||||||
|
(./rand_player -14 24.00) (./rand_player 14 24.00) => ./rand_player win
|
||||||
|
(./rand_player 10 24.00) (./rand_player -10 24.00) => ./rand_player win
|
||||||
|
(./rand_player 12 24.00) (./rand_player -12 24.00) => ./rand_player win
|
||||||
|
(./rand_player 10 24.00) (./rand_player -10 24.00) => ./rand_player win
|
||||||
|
(./rand_player -13 24.00) (./rand_player 13 24.00) => ./rand_player win
|
||||||
|
(./rand_player 11 24.00) (./rand_player -11 24.00) => ./rand_player win
|
||||||
|
(./rand_player 9 24.00) (./rand_player -9 24.00) => ./rand_player win
|
||||||
|
(./rand_player -12 24.00) (./rand_player 12 24.00) => ./rand_player win
|
||||||
|
(./rand_player 10 24.00) (./rand_player -10 24.00) => ./rand_player win
|
||||||
|
(./rand_player -13 24.00) (./rand_player 13 24.00) => ./rand_player win
|
||||||
|
(./rand_player -12 24.00) (./rand_player 12 24.00) => ./rand_player win
|
||||||
|
(./rand_player -13 24.00) (./rand_player 13 24.00) => ./rand_player win
|
||||||
|
(./rand_player 9 24.00) (./rand_player -9 24.00) => ./rand_player win
|
||||||
|
(./rand_player 13 24.00) (./rand_player -13 24.00) => ./rand_player win
|
||||||
|
(./rand_player 11 24.00) (./rand_player -11 24.00) => ./rand_player win
|
||||||
|
(./rand_player -10 24.00) (./rand_player 10 24.00) => ./rand_player win
|
||||||
|
(./rand_player -12 24.00) (./rand_player 12 24.00) => ./rand_player win
|
||||||
|
(./rand_player -8 24.00) (./rand_player 8 24.00) => ./rand_player win
|
||||||
|
(./rand_player -11 24.00) (./rand_player 11 24.00) => ./rand_player win
|
||||||
|
(./rand_player 10 24.00) (./rand_player -10 24.00) => ./rand_player win
|
||||||
|
(./rand_player 13 24.00) (./rand_player -13 24.00) => ./rand_player win
|
||||||
|
(./rand_player 15 24.00) (./rand_player -15 24.00) => ./rand_player win
|
26
TP2/game1.txt
Normal file
26
TP2/game1.txt
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
// simple game on 6x4 board
|
||||||
|
// a3a-5a4a 2b3b-4a3b 2c3b-6a5a 3a4a-5b4a 3b4a-6b5b 4a5b-6c5b 1a2a-5a4a 2a3a-5b4b 3a4b-5c4b 1b2b-????
|
||||||
|
echo OFF
|
||||||
|
newgame 6 4
|
||||||
|
play 2a3a
|
||||||
|
play 5a4a
|
||||||
|
play 2b3b
|
||||||
|
play 4a3b
|
||||||
|
play 2c3b
|
||||||
|
play 6a5a
|
||||||
|
play 3a4a
|
||||||
|
showboard
|
||||||
|
play 5b4a
|
||||||
|
play 3b4a
|
||||||
|
play 6b5b
|
||||||
|
play 4a5b
|
||||||
|
play 6c5b
|
||||||
|
play 1a2a
|
||||||
|
play 5a4a
|
||||||
|
play 2a3a
|
||||||
|
play 5b4b
|
||||||
|
play 3a4b
|
||||||
|
play 5c4b
|
||||||
|
play 1b2b
|
||||||
|
showboard
|
||||||
|
quit
|
47
TP2/mk_stats.sh
Normal file
47
TP2/mk_stats.sh
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
PRG_1=./player_A
|
||||||
|
PRG_2=./player_B
|
||||||
|
GAME_DIR=new_stats
|
||||||
|
NB_GAMES_PER_SIDE=10
|
||||||
|
NBL=6
|
||||||
|
NBC=4
|
||||||
|
|
||||||
|
if [ -d ${GAME_DIR} ]
|
||||||
|
then
|
||||||
|
echo "GAME_DIR ever here"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
mkdir ${GAME_DIR}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e ${PRG_1} ]
|
||||||
|
then
|
||||||
|
echo "PRG_1 is missing"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e ${PRG_2} ]
|
||||||
|
then
|
||||||
|
echo "PRG_2 is missing"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
pike run_many_games.pike -f ${PRG_1} -s ${PRG_2} -o ${GAME_DIR} -n ${NB_GAMES_PER_SIDE} -l ${NBL} -c ${NBC} 2>${GAME_DIR}/log1.txt 1>&2
|
||||||
|
pike run_many_games.pike -f ${PRG_2} -s ${PRG_1} -o ${GAME_DIR} -n ${NB_GAMES_PER_SIDE} -l ${NBL} -c ${NBC} 2>${GAME_DIR}/log2.txt 1>&2
|
||||||
|
|
||||||
|
echo " ================" > ${GAME_DIR}/resume.txt
|
||||||
|
echo " NB_GAMES_PER_SIDE ${NB_GAMES_PER_SIDE}" >> ${GAME_DIR}/resume.txt
|
||||||
|
echo " NBL ${NBL}" >> ${GAME_DIR}/resume.txt
|
||||||
|
echo " NBC ${NBC}" >> ${GAME_DIR}/resume.txt
|
||||||
|
echo "" >> ${GAME_DIR}/resume.txt
|
||||||
|
echo " number of wins" >> ${GAME_DIR}/resume.txt
|
||||||
|
echo " ================" >> ${GAME_DIR}/resume.txt
|
||||||
|
STR_WIN1=$(echo ${PRG_1} win)
|
||||||
|
NB_WIN1=$(grep "${STR_WIN1}" ${GAME_DIR}/scores.txt | wc -l)
|
||||||
|
echo " "${PRG_1}" is "${NB_WIN1} >> ${GAME_DIR}/resume.txt
|
||||||
|
|
||||||
|
STR_WIN2=$(echo ${PRG_2} win)
|
||||||
|
NB_WIN2=$(grep "${STR_WIN2}" ${GAME_DIR}/scores.txt | wc -l)
|
||||||
|
echo " "${PRG_2}" is "${NB_WIN2} >> ${GAME_DIR}/resume.txt
|
||||||
|
echo " ================" >> ${GAME_DIR}/resume.txt
|
307
TP2/mybt.h
Normal file
307
TP2/mybt.h
Normal file
|
@ -0,0 +1,307 @@
|
||||||
|
#ifndef MYBT_H
|
||||||
|
#define MYBT_H
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <random>
|
||||||
|
#define WHITE 0
|
||||||
|
#define BLACK 1
|
||||||
|
#define EMPTY 2
|
||||||
|
char* cboard = (char*)"o@.";
|
||||||
|
|
||||||
|
struct bt_piece_t {
|
||||||
|
int line; int col;
|
||||||
|
};
|
||||||
|
struct bt_move_t {
|
||||||
|
int line_i; int col_i;
|
||||||
|
int line_f; int col_f;
|
||||||
|
|
||||||
|
// all moves are printed without ambiguity
|
||||||
|
// white in its color
|
||||||
|
// black in red color
|
||||||
|
void print(FILE* _fp, bool _white, int _nbl) {
|
||||||
|
if(_white) {
|
||||||
|
fprintf(_fp, "%d%c%d%c", _nbl-line_i, 'a'+col_i, _nbl-line_f, 'a'+col_f);
|
||||||
|
} else {
|
||||||
|
fprintf(_fp, "\x1B[31m%d%c%d%c\x1B[0m", _nbl-line_i, 'a'+col_i, _nbl-line_f, 'a'+col_f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string tostr(int _nbl) {
|
||||||
|
char ret[16];
|
||||||
|
snprintf(ret, sizeof(ret), "%d%c%d%c", _nbl-line_i, 'a'+col_i, _nbl-line_f, 'a'+col_f);
|
||||||
|
return std::string(ret);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// alloc default 10x10
|
||||||
|
// standard game in 8x8
|
||||||
|
#define MAX_LINES 10
|
||||||
|
#define MAX_COLS 10
|
||||||
|
|
||||||
|
// rules reminder :
|
||||||
|
// pieces moves from 1 square in diag and in front
|
||||||
|
// pieces captures only in diag
|
||||||
|
// i.e. to go forward, square must be empty
|
||||||
|
|
||||||
|
struct bt_t {
|
||||||
|
int nbl;
|
||||||
|
int nbc;
|
||||||
|
int board[MAX_LINES][MAX_COLS];
|
||||||
|
int turn;
|
||||||
|
|
||||||
|
bt_piece_t white_pieces[2*MAX_LINES];
|
||||||
|
int nb_white_pieces;
|
||||||
|
bt_piece_t black_pieces[2*MAX_LINES];
|
||||||
|
int nb_black_pieces;
|
||||||
|
bt_move_t moves[3*2*MAX_LINES];
|
||||||
|
int nb_moves;
|
||||||
|
// last turn of moves update
|
||||||
|
int turn_of_last_moves_update;
|
||||||
|
|
||||||
|
void init(int _nbl, int _nbc);
|
||||||
|
void init_pieces();
|
||||||
|
void print_board(FILE* _fp);
|
||||||
|
void print_turn_and_moves(FILE* _fp);
|
||||||
|
void update_moves();
|
||||||
|
void update_moves(int _color);
|
||||||
|
|
||||||
|
bool white_can_move_right(int _line, int _col);
|
||||||
|
bool white_can_move_forward(int _line, int _col);
|
||||||
|
bool white_can_move_left(int _line, int _col);
|
||||||
|
bool black_can_move_right(int _line, int _col);
|
||||||
|
bool black_can_move_forward(int _line, int _col);
|
||||||
|
bool black_can_move_left(int _line, int _col);
|
||||||
|
|
||||||
|
bt_move_t get_rand_move();
|
||||||
|
bool can_play(bt_move_t _m);
|
||||||
|
void play(bt_move_t _m);
|
||||||
|
int endgame();
|
||||||
|
double score(int _color);
|
||||||
|
void playout(bool _log);
|
||||||
|
std::string mkH1();
|
||||||
|
std::string mkH2();
|
||||||
|
long long int mkH3();
|
||||||
|
|
||||||
|
// déclarées mais non définies
|
||||||
|
double eval();
|
||||||
|
bt_move_t minimax(double _sec);
|
||||||
|
bt_move_t alphabeta(double _sec);
|
||||||
|
bt_move_t mcts(double _sec);
|
||||||
|
bt_move_t mcts_ppa(double _sec);
|
||||||
|
bt_move_t nmcs(double _sec);
|
||||||
|
bt_move_t nrpa(double _sec);
|
||||||
|
|
||||||
|
void add_move(int _li, int _ci, int _lf, int _cf) {
|
||||||
|
moves[nb_moves].line_i = _li; moves[nb_moves].col_i = _ci;
|
||||||
|
moves[nb_moves].line_f = _lf; moves[nb_moves].col_f = _cf;
|
||||||
|
nb_moves++;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void bt_t::init(int _nbl, int _nbc) {
|
||||||
|
if(_nbl > MAX_LINES || _nbc > MAX_COLS) {
|
||||||
|
fprintf(stderr, "ERROR : MAX_LINES or MAX_COLS exceeded\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
nbl = _nbl; nbc = _nbc;
|
||||||
|
turn = 0;
|
||||||
|
turn_of_last_moves_update = -1;
|
||||||
|
for(int i = 0; i < nbl; i++)
|
||||||
|
for(int j = 0; j < nbc; j++) {
|
||||||
|
if(i <= 1 ) {
|
||||||
|
board[i][j] = BLACK;
|
||||||
|
} else if(i < _nbl-2) {
|
||||||
|
board[i][j] = EMPTY;
|
||||||
|
} else {
|
||||||
|
board[i][j] = WHITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
init_pieces();
|
||||||
|
update_moves();
|
||||||
|
}
|
||||||
|
void bt_t::init_pieces() {
|
||||||
|
nb_white_pieces = 0;
|
||||||
|
nb_black_pieces = 0;
|
||||||
|
for(int i = 0; i < nbl; i++)
|
||||||
|
for(int j = 0; j < nbc; j++) {
|
||||||
|
if(board[i][j] == WHITE) {
|
||||||
|
white_pieces[nb_white_pieces].line = i;
|
||||||
|
white_pieces[nb_white_pieces].col = j;
|
||||||
|
nb_white_pieces++;
|
||||||
|
} else if(board[i][j] == BLACK) {
|
||||||
|
black_pieces[nb_black_pieces].line = i;
|
||||||
|
black_pieces[nb_black_pieces].col = j;
|
||||||
|
nb_black_pieces++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// again print black in red (as bg is black... black is printed in red)
|
||||||
|
void bt_t::print_board(FILE* _fp = stderr) {
|
||||||
|
fprintf(_fp, " \x1B[34m");
|
||||||
|
for(int j = 0; j < nbc; j++) {
|
||||||
|
fprintf(_fp, "%c ", 'a'+j);
|
||||||
|
}
|
||||||
|
fprintf(_fp, "\x1B[0m\n");
|
||||||
|
for(int i = 0; i < nbl; i++) {
|
||||||
|
fprintf(_fp, "\x1B[34m%2d\x1B[0m ", (nbl-i));
|
||||||
|
for(int j = 0; j < nbc; j++) {
|
||||||
|
if(board[i][j] == BLACK)
|
||||||
|
fprintf(_fp, "\x1B[31m%c\x1B[0m ", cboard[board[i][j]]);
|
||||||
|
else
|
||||||
|
fprintf(_fp, "%c ", cboard[board[i][j]]);
|
||||||
|
}
|
||||||
|
fprintf(_fp, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void bt_t::print_turn_and_moves(FILE* _fp = stderr) {
|
||||||
|
fprintf(_fp,"turn:%d\nmoves:", turn);
|
||||||
|
for(int i = 0; i < nb_moves; i++) {
|
||||||
|
moves[i].print(_fp, turn%2 == 1, nbl);
|
||||||
|
fprintf(_fp, " ");
|
||||||
|
}
|
||||||
|
fprintf(_fp, "\n");
|
||||||
|
}
|
||||||
|
void bt_t::update_moves() {
|
||||||
|
if(turn%2 == 0) update_moves(WHITE);
|
||||||
|
else update_moves(BLACK);
|
||||||
|
}
|
||||||
|
void bt_t::update_moves(int _color) {
|
||||||
|
if(turn_of_last_moves_update == turn) return; // MAJ ever done
|
||||||
|
turn_of_last_moves_update = turn;
|
||||||
|
nb_moves = 0;
|
||||||
|
if(_color==WHITE) {
|
||||||
|
for(int i = 0; i < nb_white_pieces; i++) {
|
||||||
|
int li = white_pieces[i].line;
|
||||||
|
int ci = white_pieces[i].col;
|
||||||
|
if(white_can_move_right(li, ci)) add_move(li, ci, li-1, ci+1);
|
||||||
|
if(white_can_move_forward(li, ci)) add_move(li, ci, li-1, ci);
|
||||||
|
if(white_can_move_left(li, ci)) add_move(li, ci, li-1, ci-1);
|
||||||
|
}
|
||||||
|
} else if(_color == BLACK) {
|
||||||
|
for(int i = 0; i < nb_black_pieces; i++) {
|
||||||
|
int li = black_pieces[i].line;
|
||||||
|
int ci = black_pieces[i].col;
|
||||||
|
if(black_can_move_right(li, ci)) add_move(li, ci, li+1, ci+1);
|
||||||
|
if(black_can_move_forward(li, ci)) add_move(li, ci, li+1, ci);
|
||||||
|
if(black_can_move_left(li, ci)) add_move(li, ci, li+1, ci-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool bt_t::white_can_move_right(int _line, int _col) {
|
||||||
|
if(_line == 0) return false;
|
||||||
|
if(_col == nbc-1) return false;
|
||||||
|
if(board[_line-1][_col+1] != WHITE) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool bt_t::white_can_move_forward(int _line, int _col) {
|
||||||
|
if(_line == 0) return false;
|
||||||
|
if(board[_line-1][_col] == EMPTY) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool bt_t::white_can_move_left(int _line, int _col) {
|
||||||
|
if(_line == 0) return false;
|
||||||
|
if(_col == 0) return false;
|
||||||
|
if(board[_line-1][_col-1] != WHITE) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool bt_t::black_can_move_right(int _line, int _col) {
|
||||||
|
if(_line == nbl-1) return false;
|
||||||
|
if(_col == nbc-1) return false;
|
||||||
|
if(board[_line+1][_col+1] != BLACK) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool bt_t::black_can_move_forward(int _line, int _col) {
|
||||||
|
if(_line == nbl-1) return false;
|
||||||
|
if(board[_line+1][_col] == EMPTY) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool bt_t::black_can_move_left(int _line, int _col) {
|
||||||
|
if(_line == nbl-1) return false;
|
||||||
|
if(_col == 0) return false;
|
||||||
|
if(board[_line+1][_col-1] != BLACK) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bt_move_t bt_t::get_rand_move() {
|
||||||
|
update_moves();
|
||||||
|
int r = ((int)rand())%nb_moves;
|
||||||
|
return moves[r];
|
||||||
|
}
|
||||||
|
bool bt_t::can_play(bt_move_t _m) {
|
||||||
|
int dx = abs(_m.col_f - _m.col_i);
|
||||||
|
if(dx > 1) return false;
|
||||||
|
int dy = abs(_m.line_f - _m.line_i);
|
||||||
|
if(dy > 1) return false;
|
||||||
|
if(_m.line_i < 0 || _m.line_i >= nbl) return false;
|
||||||
|
if(_m.line_f < 0 || _m.line_f >= nbl) return false;
|
||||||
|
if(_m.col_i < 0 || _m.col_i >= nbc) return false;
|
||||||
|
if(_m.col_f < 0 || _m.col_f >= nbc) return false;
|
||||||
|
int color_i = board[_m.line_i][_m.col_i];
|
||||||
|
int color_f = board[_m.line_f][_m.col_f];
|
||||||
|
if(color_i == EMPTY) return false;
|
||||||
|
if(color_i == color_f) return false;
|
||||||
|
if(turn%2==0 && color_i == BLACK) return false;
|
||||||
|
if(turn%2==1 && color_i == WHITE) return false;
|
||||||
|
if(_m.col_i == _m.col_f && color_f != EMPTY) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bt_t::play(bt_move_t _m) {
|
||||||
|
int color_i = board[_m.line_i][_m.col_i];
|
||||||
|
int color_f = board[_m.line_f][_m.col_f];
|
||||||
|
board[_m.line_f][_m.col_f] = color_i;
|
||||||
|
board[_m.line_i][_m.col_i] = EMPTY;
|
||||||
|
if(color_i == WHITE) {
|
||||||
|
for(int i = 0; i < nb_white_pieces; i++) {
|
||||||
|
if(white_pieces[i].line == _m.line_i && white_pieces[i].col == _m.col_i) {
|
||||||
|
white_pieces[i].line = _m.line_f;
|
||||||
|
white_pieces[i].col = _m.col_f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(color_f == BLACK) {
|
||||||
|
for(int i = 0; i < nb_black_pieces; i++) {
|
||||||
|
if(black_pieces[i].line == _m.line_f && black_pieces[i].col == _m.col_f) {
|
||||||
|
black_pieces[i] = black_pieces[nb_black_pieces-1];
|
||||||
|
nb_black_pieces--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(color_i == BLACK) {
|
||||||
|
for(int i = 0; i < nb_black_pieces; i++) {
|
||||||
|
if(black_pieces[i].line == _m.line_i &&
|
||||||
|
black_pieces[i].col == _m.col_i) {
|
||||||
|
black_pieces[i].line = _m.line_f;
|
||||||
|
black_pieces[i].col = _m.col_f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(color_f == WHITE) {
|
||||||
|
for(int i = 0; i < nb_white_pieces; i++) {
|
||||||
|
if(white_pieces[i].line == _m.line_f &&
|
||||||
|
white_pieces[i].col == _m.col_f) {
|
||||||
|
white_pieces[i] = white_pieces[nb_white_pieces-1];
|
||||||
|
nb_white_pieces--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
turn++;
|
||||||
|
}
|
||||||
|
int bt_t::endgame() {
|
||||||
|
for(int i = 0; i < nbc; i++) {
|
||||||
|
if(board[0][i] == WHITE) return WHITE;
|
||||||
|
}
|
||||||
|
for(int i = 0; i < nbc; i++) {
|
||||||
|
if(board[nbl-1][i] == BLACK) return BLACK;
|
||||||
|
}
|
||||||
|
return EMPTY;
|
||||||
|
}
|
||||||
|
double bt_t::score(int _color) {
|
||||||
|
int state = endgame();
|
||||||
|
if(state == EMPTY) return 0.0;
|
||||||
|
if(_color == state) return 1.0;
|
||||||
|
return -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* MYBT_H */
|
100
TP2/new_stats/log1.txt
Normal file
100
TP2/new_stats/log1.txt
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
nb_turn: 26 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . . . .
|
||||||
|
5 [31m@[0m [31m@[0m o [31m@[0m
|
||||||
|
4 [31m@[0m o . .
|
||||||
|
3 o [31m@[0m . o
|
||||||
|
2 . . . .
|
||||||
|
1 o [31m@[0m . .
|
||||||
|
a b c d
|
||||||
|
(./player_A -11 24.00) (./player_B 11 24.00) => ./player_B win
|
||||||
|
================= player2 WIN
|
||||||
|
nb_turn: 26 timers : [31m24.00[0m : 24.00
|
||||||
|
6 [31m@[0m . . .
|
||||||
|
5 . . . [31m@[0m
|
||||||
|
4 [31m@[0m o o [31m@[0m
|
||||||
|
3 . o [31m@[0m o
|
||||||
|
2 . . . .
|
||||||
|
1 [31m@[0m . . o
|
||||||
|
a b c d
|
||||||
|
(./player_A -11 24.00) (./player_B 11 24.00) => ./player_B win
|
||||||
|
================= player2 WIN
|
||||||
|
nb_turn: 25 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . . . o
|
||||||
|
5 o [31m@[0m . .
|
||||||
|
4 . [31m@[0m [31m@[0m [31m@[0m
|
||||||
|
3 . . o [31m@[0m
|
||||||
|
2 . o [31m@[0m o
|
||||||
|
1 . . . o
|
||||||
|
a b c d
|
||||||
|
(./player_A 12 24.00) (./player_B -12 24.00) => ./player_A win
|
||||||
|
================= player1 WIN
|
||||||
|
nb_turn: 28 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . . . .
|
||||||
|
5 . [31m@[0m . .
|
||||||
|
4 [31m@[0m o . [31m@[0m
|
||||||
|
3 o o . [31m@[0m
|
||||||
|
2 . . o .
|
||||||
|
1 . [31m@[0m o .
|
||||||
|
a b c d
|
||||||
|
(./player_A -10 24.00) (./player_B 10 24.00) => ./player_B win
|
||||||
|
================= player2 WIN
|
||||||
|
nb_turn: 22 timers : [31m24.00[0m : 24.00
|
||||||
|
6 [31m@[0m [31m@[0m . .
|
||||||
|
5 . . . [31m@[0m
|
||||||
|
4 o [31m@[0m o o
|
||||||
|
3 . o . .
|
||||||
|
2 . . . o
|
||||||
|
1 . . [31m@[0m o
|
||||||
|
a b c d
|
||||||
|
(./player_A -11 24.00) (./player_B 11 24.00) => ./player_B win
|
||||||
|
================= player2 WIN
|
||||||
|
nb_turn: 19 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . o [31m@[0m .
|
||||||
|
5 . . [31m@[0m [31m@[0m
|
||||||
|
4 [31m@[0m . [31m@[0m .
|
||||||
|
3 . o [31m@[0m o
|
||||||
|
2 o . . o
|
||||||
|
1 . . o o
|
||||||
|
a b c d
|
||||||
|
(./player_A 13 24.00) (./player_B -13 24.00) => ./player_A win
|
||||||
|
================= player1 WIN
|
||||||
|
nb_turn: 30 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . . [31m@[0m .
|
||||||
|
5 [31m@[0m . . o
|
||||||
|
4 . . [31m@[0m .
|
||||||
|
3 [31m@[0m o . o
|
||||||
|
2 [31m@[0m . . .
|
||||||
|
1 o . [31m@[0m .
|
||||||
|
a b c d
|
||||||
|
(./player_A -10 24.00) (./player_B 10 24.00) => ./player_B win
|
||||||
|
================= player2 WIN
|
||||||
|
nb_turn: 29 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . . o .
|
||||||
|
5 . [31m@[0m . .
|
||||||
|
4 . . o .
|
||||||
|
3 . [31m@[0m o o
|
||||||
|
2 . . [31m@[0m .
|
||||||
|
1 o . . .
|
||||||
|
a b c d
|
||||||
|
(./player_A 8 24.00) (./player_B -8 24.00) => ./player_A win
|
||||||
|
================= player1 WIN
|
||||||
|
nb_turn: 30 timers : [31m24.00[0m : 24.00
|
||||||
|
6 [31m@[0m . . .
|
||||||
|
5 . . . .
|
||||||
|
4 [31m@[0m . o [31m@[0m
|
||||||
|
3 o . [31m@[0m o
|
||||||
|
2 . . . .
|
||||||
|
1 . [31m@[0m . .
|
||||||
|
a b c d
|
||||||
|
(./player_A -8 24.00) (./player_B 8 24.00) => ./player_B win
|
||||||
|
================= player2 WIN
|
||||||
|
nb_turn: 19 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . [31m@[0m [31m@[0m o
|
||||||
|
5 . . . [31m@[0m
|
||||||
|
4 o . [31m@[0m .
|
||||||
|
3 o . . [31m@[0m
|
||||||
|
2 . . . o
|
||||||
|
1 o . o o
|
||||||
|
a b c d
|
||||||
|
(./player_A 12 24.00) (./player_B -12 24.00) => ./player_A win
|
||||||
|
================= player1 WIN
|
100
TP2/new_stats/log2.txt
Normal file
100
TP2/new_stats/log2.txt
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
nb_turn: 26 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . . . .
|
||||||
|
5 [31m@[0m [31m@[0m o [31m@[0m
|
||||||
|
4 [31m@[0m o . .
|
||||||
|
3 o [31m@[0m . o
|
||||||
|
2 . . . .
|
||||||
|
1 o [31m@[0m . .
|
||||||
|
a b c d
|
||||||
|
(./player_B -11 24.00) (./player_A 11 24.00) => ./player_A win
|
||||||
|
================= player2 WIN
|
||||||
|
nb_turn: 26 timers : [31m24.00[0m : 24.00
|
||||||
|
6 [31m@[0m . . .
|
||||||
|
5 . . . [31m@[0m
|
||||||
|
4 [31m@[0m o o [31m@[0m
|
||||||
|
3 . o [31m@[0m o
|
||||||
|
2 . . . .
|
||||||
|
1 [31m@[0m . . o
|
||||||
|
a b c d
|
||||||
|
(./player_B -11 24.00) (./player_A 11 24.00) => ./player_A win
|
||||||
|
================= player2 WIN
|
||||||
|
nb_turn: 25 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . . . o
|
||||||
|
5 o [31m@[0m . .
|
||||||
|
4 . [31m@[0m [31m@[0m [31m@[0m
|
||||||
|
3 . . o [31m@[0m
|
||||||
|
2 . o [31m@[0m o
|
||||||
|
1 . . . o
|
||||||
|
a b c d
|
||||||
|
(./player_B 12 24.00) (./player_A -12 24.00) => ./player_B win
|
||||||
|
================= player1 WIN
|
||||||
|
nb_turn: 28 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . . . .
|
||||||
|
5 . [31m@[0m . .
|
||||||
|
4 [31m@[0m o . [31m@[0m
|
||||||
|
3 o o . [31m@[0m
|
||||||
|
2 . . o .
|
||||||
|
1 . [31m@[0m o .
|
||||||
|
a b c d
|
||||||
|
(./player_B -10 24.00) (./player_A 10 24.00) => ./player_A win
|
||||||
|
================= player2 WIN
|
||||||
|
nb_turn: 22 timers : [31m24.00[0m : 24.00
|
||||||
|
6 [31m@[0m [31m@[0m . .
|
||||||
|
5 . . . [31m@[0m
|
||||||
|
4 o [31m@[0m o o
|
||||||
|
3 . o . .
|
||||||
|
2 . . . o
|
||||||
|
1 . . [31m@[0m o
|
||||||
|
a b c d
|
||||||
|
(./player_B -11 24.00) (./player_A 11 24.00) => ./player_A win
|
||||||
|
================= player2 WIN
|
||||||
|
nb_turn: 19 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . o [31m@[0m .
|
||||||
|
5 . . [31m@[0m [31m@[0m
|
||||||
|
4 [31m@[0m . [31m@[0m .
|
||||||
|
3 . o [31m@[0m o
|
||||||
|
2 o . . o
|
||||||
|
1 . . o o
|
||||||
|
a b c d
|
||||||
|
(./player_B 13 24.00) (./player_A -13 24.00) => ./player_B win
|
||||||
|
================= player1 WIN
|
||||||
|
nb_turn: 30 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . . [31m@[0m .
|
||||||
|
5 [31m@[0m . . o
|
||||||
|
4 . . [31m@[0m .
|
||||||
|
3 [31m@[0m o . o
|
||||||
|
2 [31m@[0m . . .
|
||||||
|
1 o . [31m@[0m .
|
||||||
|
a b c d
|
||||||
|
(./player_B -10 24.00) (./player_A 10 24.00) => ./player_A win
|
||||||
|
================= player2 WIN
|
||||||
|
nb_turn: 29 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . . o .
|
||||||
|
5 . [31m@[0m . .
|
||||||
|
4 . . o .
|
||||||
|
3 . [31m@[0m o o
|
||||||
|
2 . . [31m@[0m .
|
||||||
|
1 o . . .
|
||||||
|
a b c d
|
||||||
|
(./player_B 8 24.00) (./player_A -8 24.00) => ./player_B win
|
||||||
|
================= player1 WIN
|
||||||
|
nb_turn: 30 timers : [31m24.00[0m : 24.00
|
||||||
|
6 [31m@[0m . . .
|
||||||
|
5 . . . .
|
||||||
|
4 [31m@[0m . o [31m@[0m
|
||||||
|
3 o . [31m@[0m o
|
||||||
|
2 . . . .
|
||||||
|
1 . [31m@[0m . .
|
||||||
|
a b c d
|
||||||
|
(./player_B -8 24.00) (./player_A 8 24.00) => ./player_A win
|
||||||
|
================= player2 WIN
|
||||||
|
nb_turn: 19 timers : [31m24.00[0m : 24.00
|
||||||
|
6 . [31m@[0m [31m@[0m o
|
||||||
|
5 . . . [31m@[0m
|
||||||
|
4 o . [31m@[0m .
|
||||||
|
3 o . . [31m@[0m
|
||||||
|
2 . . . o
|
||||||
|
1 o . o o
|
||||||
|
a b c d
|
||||||
|
(./player_B 12 24.00) (./player_A -12 24.00) => ./player_B win
|
||||||
|
================= player1 WIN
|
10
TP2/new_stats/resume.txt
Normal file
10
TP2/new_stats/resume.txt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
================
|
||||||
|
NB_GAMES_PER_SIDE 10
|
||||||
|
NBL 6
|
||||||
|
NBC 4
|
||||||
|
|
||||||
|
number of wins
|
||||||
|
================
|
||||||
|
./player_A is 10
|
||||||
|
./player_B is 10
|
||||||
|
================
|
20
TP2/new_stats/scores.txt
Normal file
20
TP2/new_stats/scores.txt
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
(./player_A -11 24.00) (./player_B 11 24.00) => ./player_B win
|
||||||
|
(./player_A -11 24.00) (./player_B 11 24.00) => ./player_B win
|
||||||
|
(./player_A 12 24.00) (./player_B -12 24.00) => ./player_A win
|
||||||
|
(./player_A -10 24.00) (./player_B 10 24.00) => ./player_B win
|
||||||
|
(./player_A -11 24.00) (./player_B 11 24.00) => ./player_B win
|
||||||
|
(./player_A 13 24.00) (./player_B -13 24.00) => ./player_A win
|
||||||
|
(./player_A -10 24.00) (./player_B 10 24.00) => ./player_B win
|
||||||
|
(./player_A 8 24.00) (./player_B -8 24.00) => ./player_A win
|
||||||
|
(./player_A -8 24.00) (./player_B 8 24.00) => ./player_B win
|
||||||
|
(./player_A 12 24.00) (./player_B -12 24.00) => ./player_A win
|
||||||
|
(./player_B -11 24.00) (./player_A 11 24.00) => ./player_A win
|
||||||
|
(./player_B -11 24.00) (./player_A 11 24.00) => ./player_A win
|
||||||
|
(./player_B 12 24.00) (./player_A -12 24.00) => ./player_B win
|
||||||
|
(./player_B -10 24.00) (./player_A 10 24.00) => ./player_A win
|
||||||
|
(./player_B -11 24.00) (./player_A 11 24.00) => ./player_A win
|
||||||
|
(./player_B 13 24.00) (./player_A -13 24.00) => ./player_B win
|
||||||
|
(./player_B -10 24.00) (./player_A 10 24.00) => ./player_A win
|
||||||
|
(./player_B 8 24.00) (./player_A -8 24.00) => ./player_B win
|
||||||
|
(./player_B -8 24.00) (./player_A 8 24.00) => ./player_A win
|
||||||
|
(./player_B 12 24.00) (./player_A -12 24.00) => ./player_B win
|
109
TP2/rand_player.cpp
Normal file
109
TP2/rand_player.cpp
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <string.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include "mybt.h"
|
||||||
|
|
||||||
|
bt_t B;
|
||||||
|
int boardwidth = 0;
|
||||||
|
int boardheight = 0;
|
||||||
|
bool white_turn = true;
|
||||||
|
|
||||||
|
#ifndef VERBOSE_RAND_PLAYER
|
||||||
|
#define VERBOSE_RAND_PLAYER
|
||||||
|
bool verbose = true;
|
||||||
|
bool showboard_at_each_move = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void help() {
|
||||||
|
fprintf(stderr, " quit\n");
|
||||||
|
fprintf(stderr, " echo ON | OFF\n");
|
||||||
|
fprintf(stderr, " help\n");
|
||||||
|
fprintf(stderr, " name <PLAYER_NAME>\n");
|
||||||
|
fprintf(stderr, " newgame <NBCOL> <NBLINE>\n");
|
||||||
|
fprintf(stderr, " genmove\n");
|
||||||
|
fprintf(stderr, " play <L0C0L1C1>\n");
|
||||||
|
fprintf(stderr, " showboard\n");
|
||||||
|
}
|
||||||
|
void name() {
|
||||||
|
printf("= rand_player\n\n");
|
||||||
|
}
|
||||||
|
void newgame() {
|
||||||
|
if((boardheight < 1 || boardheight > 10) && (boardwidth < 1 || boardwidth > 10)) {
|
||||||
|
fprintf(stderr, "boardsize is %d %d ???\n", boardheight, boardwidth);
|
||||||
|
printf("= \n\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
B.init(boardheight, boardwidth);
|
||||||
|
white_turn = true;
|
||||||
|
if(verbose) fprintf(stderr, "ready to play on %dx%d board\n", boardheight, boardwidth);
|
||||||
|
printf("= \n\n");
|
||||||
|
}
|
||||||
|
void showboard() {
|
||||||
|
B.print_board(stderr);
|
||||||
|
printf("= \n\n");
|
||||||
|
}
|
||||||
|
void genmove() {
|
||||||
|
int ret = B.endgame();
|
||||||
|
if(ret != EMPTY) {
|
||||||
|
fprintf(stderr, "game finished\n");
|
||||||
|
if(ret == WHITE) fprintf(stderr, "white player wins\n");
|
||||||
|
else fprintf(stderr, "black player wins\n");
|
||||||
|
printf("= \n\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bt_move_t m = B.get_rand_move();
|
||||||
|
B.play(m);
|
||||||
|
if(verbose) {
|
||||||
|
m.print(stderr, white_turn, B.nbl);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
white_turn = !white_turn;
|
||||||
|
printf("= %s\n\n", m.tostr(B.nbl).c_str());
|
||||||
|
}
|
||||||
|
void play(char a, char b, char c, char d) {
|
||||||
|
bt_move_t m;
|
||||||
|
m.line_i = boardheight-(a-'0');
|
||||||
|
m.col_i = b-'a';
|
||||||
|
m.line_f = boardheight-(c-'0');
|
||||||
|
m.col_f = d-'a';
|
||||||
|
if(B.can_play(m)) {
|
||||||
|
B.play(m);
|
||||||
|
if(verbose) {
|
||||||
|
m.print(stderr, white_turn, B.nbl);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
white_turn = !white_turn;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "CANT play %d %d %d %d ?\n", m.line_i, m.col_i, m.line_f, m.col_f);
|
||||||
|
}
|
||||||
|
if(showboard_at_each_move) showboard();
|
||||||
|
printf("= \n\n");
|
||||||
|
}
|
||||||
|
int main(int _ac, char** _av) {
|
||||||
|
bool echo_on = false;
|
||||||
|
setbuf(stdout, 0);
|
||||||
|
setbuf(stderr, 0);
|
||||||
|
if(verbose) fprintf(stderr, "rand_player started\n");
|
||||||
|
char a,b,c,d; // for play cmd
|
||||||
|
for (std::string line; std::getline(std::cin, line);) {
|
||||||
|
if(verbose) fprintf(stderr, "rand_player receive %s\n", line.c_str());
|
||||||
|
if(echo_on) if(verbose) fprintf(stderr, "%s\n", line.c_str());
|
||||||
|
if(line.compare("quit") == 0) { printf("= \n\n"); break; }
|
||||||
|
else if(line.compare("echo ON") == 0) echo_on = true;
|
||||||
|
else if(line.compare("echo OFF") == 0) echo_on = false;
|
||||||
|
else if(line.compare("help") == 0) help();
|
||||||
|
else if(line.compare("name") == 0) name();
|
||||||
|
else if(sscanf(line.c_str(), "newgame %d %d\n", &boardheight, &boardwidth) == 2) newgame();
|
||||||
|
else if(line.compare("genmove") == 0) genmove();
|
||||||
|
else if(sscanf(line.c_str(), "play %c%c%c%c\n", &a,&b,&c,&d) == 4) play(a,b,c,d);
|
||||||
|
else if(line.compare("showboard") == 0) showboard();
|
||||||
|
else if(line.compare(0,2,"//") == 0) ; // just comments
|
||||||
|
else fprintf(stderr, "???\n");
|
||||||
|
if(echo_on) printf(">");
|
||||||
|
}
|
||||||
|
if(verbose) fprintf(stderr, "bye.\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
463
TP2/run_many_games.pike
Normal file
463
TP2/run_many_games.pike
Normal file
|
@ -0,0 +1,463 @@
|
||||||
|
#!/usr/bin/env pike
|
||||||
|
|
||||||
|
// pike run_many_games.pike -f ./rand_player -s ./rand_player -v 1 -p 1 -l 6 -c 4
|
||||||
|
|
||||||
|
// "Options:\n"
|
||||||
|
// " -n, --number=NB_GAMES the number of games to play\n"
|
||||||
|
// " -l, --nbl=NB_LINES the number of lines on the board\n"
|
||||||
|
// " -c, --nbc=NB_COLS the number of cols on the board\n"
|
||||||
|
// " -f, --first=COMMAND_LINE\n"
|
||||||
|
// " -s, --second=COMMAND_LINE command lines to run the two engines with.\n\n"
|
||||||
|
// " -o, --outputdir=OUTPUT_DIRECTORY (default ouput is data)\n"
|
||||||
|
// " --help display this help and exit.\n"
|
||||||
|
// " -v, --verbose=LEVEL 1 - print moves, 2 and higher - draw boards.\n"
|
||||||
|
// " -p, --pause=SECONDS 1 - sleep(1), 2 and more - sleep(2 and more).\n";
|
||||||
|
|
||||||
|
#define DUMP_GTP_PIPES 0
|
||||||
|
|
||||||
|
class btp_server { // breakthrough text protocol server
|
||||||
|
int server_is_up;
|
||||||
|
private Stdio.File file_out; // reading without buffer (stream mode)
|
||||||
|
private Stdio.FILE file_in; // reading with buffer (line per line mode)
|
||||||
|
string command_line;
|
||||||
|
string|int engine_name; // just for fun
|
||||||
|
|
||||||
|
void create(string _command_line) {
|
||||||
|
file_out = Stdio.File();
|
||||||
|
file_in = Stdio.FILE();
|
||||||
|
command_line = _command_line;
|
||||||
|
array error = catch {
|
||||||
|
Process.create_process(command_line / " ",
|
||||||
|
([ "stdin" : file_out->pipe(),
|
||||||
|
"stdout" : file_in->pipe() ])); };
|
||||||
|
if (error) {
|
||||||
|
werror(error[0]); werror("Command line was `%s'.\n", command_line);
|
||||||
|
destruct(this_object());
|
||||||
|
} else {
|
||||||
|
array error = catch {
|
||||||
|
engine_name = get_name();
|
||||||
|
server_is_up = 1;
|
||||||
|
};
|
||||||
|
if (error) {
|
||||||
|
werror("Engine `%s' crashed at startup.\nPerhaps command line is wrong.\n", command_line);
|
||||||
|
destruct(this_object());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
array send_command(string command) {
|
||||||
|
#if DUMP_GTP_PIPES
|
||||||
|
werror("[%s%s] %s\n", full_engine_name ? full_engine_name + ", " : "", command);
|
||||||
|
#endif
|
||||||
|
command = String.trim_all_whites(command);
|
||||||
|
sscanf(command, "%[0-9]", string id);
|
||||||
|
if (command[0] == '#' || command == id) return ({ 0, "" });
|
||||||
|
file_out->write("%s\n", command);
|
||||||
|
string response = file_in->gets();
|
||||||
|
if (!response) {
|
||||||
|
server_is_up = 0;
|
||||||
|
error("Engine `%s' playing crashed!", command_line);
|
||||||
|
}
|
||||||
|
#if DUMP_GTP_PIPES
|
||||||
|
werror("%s\n", response);
|
||||||
|
#endif
|
||||||
|
array result;
|
||||||
|
int id_length = strlen(id);
|
||||||
|
if (response && response[..id_length] == "=" + id)
|
||||||
|
result = ({ 0, response[id_length + 1 ..] });
|
||||||
|
else if (response && response[..id_length] == "?" + id)
|
||||||
|
result = ({ 1, response[id_length + 1 ..] });
|
||||||
|
else
|
||||||
|
result = ({ -1, response });
|
||||||
|
result[1] = String.trim_all_whites(result[1]);
|
||||||
|
while (1) {
|
||||||
|
response = file_in->gets();
|
||||||
|
#if DUMP_GTP_PIPES
|
||||||
|
werror("%s\n", response);
|
||||||
|
#endif
|
||||||
|
if (response == "") {
|
||||||
|
if (result[0] < 0) {
|
||||||
|
werror("Warning, unrecognized response to command `%s':\n", command);
|
||||||
|
werror("%s\n", result[1]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
result[1] += "\n" + response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string get_name() {
|
||||||
|
return send_command("name")[1];
|
||||||
|
}
|
||||||
|
string generate_move() {
|
||||||
|
return send_command("genmove")[1];
|
||||||
|
}
|
||||||
|
void new_game(int _nbl, int _nbc) {
|
||||||
|
send_command("newgame "+_nbl+" "+_nbc);
|
||||||
|
}
|
||||||
|
void move(string _movestr) {
|
||||||
|
send_command("play " +_movestr);
|
||||||
|
}
|
||||||
|
void quit() {
|
||||||
|
send_command("quit");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ENDGAME_WHITE_WIN 0
|
||||||
|
#define ENDGAME_BLACK_WIN 0
|
||||||
|
#define ENDGAME_WHITE_WIN 0
|
||||||
|
|
||||||
|
class btp_game {
|
||||||
|
private btp_server p0;
|
||||||
|
private btp_server p1;
|
||||||
|
private int verbose;
|
||||||
|
private int in_game_pause;
|
||||||
|
|
||||||
|
public int nb_games;
|
||||||
|
|
||||||
|
public string p0_name;
|
||||||
|
public int p0_score;
|
||||||
|
public int p0_new_win;
|
||||||
|
public int p0_wins;
|
||||||
|
|
||||||
|
public string p1_name;
|
||||||
|
public int p1_score;
|
||||||
|
public int p1_new_win;
|
||||||
|
public int p1_wins;
|
||||||
|
|
||||||
|
public int nb_turn;
|
||||||
|
public int board_nbl = 0;
|
||||||
|
public int board_nbc = 0;
|
||||||
|
bool board_alloc = false;
|
||||||
|
public string board; // board length = board_nbl*board_nbc
|
||||||
|
|
||||||
|
float p0_remaining_time;
|
||||||
|
float p1_remaining_time;
|
||||||
|
|
||||||
|
public string output_dir = "data"; // default dir
|
||||||
|
|
||||||
|
void create(string command_line_player0, string command_line_player1,
|
||||||
|
int game_nbl, int game_nbc,
|
||||||
|
string new_output_dir, int _in_game_pause, int _verbose) {
|
||||||
|
in_game_pause = _in_game_pause;
|
||||||
|
verbose = _verbose;
|
||||||
|
p0 = btp_server(command_line_player0);
|
||||||
|
if (p0) p1 = btp_server(command_line_player1);
|
||||||
|
if (!p0 || !p1) {
|
||||||
|
werror("!p0 || !p1"); finalize(); exit(0);
|
||||||
|
}
|
||||||
|
board_nbl = game_nbl;
|
||||||
|
board_nbc = game_nbc;
|
||||||
|
nb_games = 0;
|
||||||
|
p0_name = command_line_player0; p0_new_win = 0; p0_wins = 0;
|
||||||
|
p1_name = command_line_player1; p1_new_win = 0; p1_wins = 0;
|
||||||
|
|
||||||
|
if(new_output_dir != "") {
|
||||||
|
output_dir = new_output_dir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void show_endgame() {
|
||||||
|
print_board();
|
||||||
|
werror("(%s %d %.2f) (%s %d %.2f) ",
|
||||||
|
p0_name, p0_score, p0_remaining_time,
|
||||||
|
p1_name, p1_score, p1_remaining_time);
|
||||||
|
if(p0_new_win == 1) {
|
||||||
|
werror("=> "+p0_name+" win\n");
|
||||||
|
} else if(p1_new_win == 1) {
|
||||||
|
werror("=> "+p1_name+" win\n");
|
||||||
|
} else {
|
||||||
|
werror("=> draw game\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void print_score(string file_name) {
|
||||||
|
Stdio.File o = Stdio.File();
|
||||||
|
if(!o->open(file_name,"wac")) {
|
||||||
|
write("Failed to open file.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
o->write(" (%s %d %.2f) (%s %d %.2f) ",
|
||||||
|
p0_name, p0_score, p0_remaining_time,
|
||||||
|
p1_name, p1_score, p1_remaining_time);
|
||||||
|
if(p0_new_win == 1) {
|
||||||
|
o->write("=> "+p0_name+" win\n");
|
||||||
|
} else if(p1_new_win == 1) {
|
||||||
|
o->write("=> "+p1_name+" win\n");
|
||||||
|
} else {
|
||||||
|
o->write("=> draw game\n");
|
||||||
|
}
|
||||||
|
o->close();
|
||||||
|
}
|
||||||
|
// @ is black player and o is white player
|
||||||
|
void init_board() {
|
||||||
|
nb_turn = 0;
|
||||||
|
p0_remaining_time = 24.0;
|
||||||
|
p1_remaining_time = 24.0;
|
||||||
|
if(board_alloc == false) {
|
||||||
|
for(int i = 0; i < board_nbl*board_nbc; i++)
|
||||||
|
board = board+".";
|
||||||
|
board_alloc = true;
|
||||||
|
} else {
|
||||||
|
for(int i = 0; i < board_nbl*board_nbc; i++)
|
||||||
|
board[i] = '.';
|
||||||
|
}
|
||||||
|
for(int i = 0; i < 2*board_nbc; i++)
|
||||||
|
board[i] = '@';
|
||||||
|
for(int i = (board_nbl-2)*board_nbc; i < board_nbl*board_nbc; i++)
|
||||||
|
board[i] = 'o';
|
||||||
|
}
|
||||||
|
void print_board() {
|
||||||
|
bool color_print = true;
|
||||||
|
if(color_print) {
|
||||||
|
werror("nb_turn: %d timers : \x1b[31m%.2f\x1b[0m : %.2f\n",
|
||||||
|
nb_turn, p0_remaining_time, p1_remaining_time);
|
||||||
|
} else {
|
||||||
|
werror("nb_turn: %d timers : %.2f : %.2f\n",
|
||||||
|
nb_turn, p0_remaining_time, p1_remaining_time);
|
||||||
|
}
|
||||||
|
for(int i = 0; i < board_nbl; i++) {
|
||||||
|
werror(""+(board_nbl-i)+" ");
|
||||||
|
for(int j = 0; j < board_nbc; j++) {
|
||||||
|
if(color_print) {
|
||||||
|
if(board[i*board_nbc+j] == '@') {
|
||||||
|
werror("\x1b[31m%c\x1b[0m ", board[i*board_nbc+j]);
|
||||||
|
} else {
|
||||||
|
werror("%c ",board[i*board_nbc+j]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
werror("%c ",board[i*board_nbc+j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
werror("\n");
|
||||||
|
}
|
||||||
|
werror(" ");
|
||||||
|
for(int j = 0; j < board_nbc; j++)
|
||||||
|
werror("%c ", 'a'+j);
|
||||||
|
werror("\n");
|
||||||
|
}
|
||||||
|
bool play_move(string move) {
|
||||||
|
if(verbose >= 1) werror("==== play_move "+move+"\n");
|
||||||
|
if(move == "PASS") { nb_turn ++; return true; }
|
||||||
|
int strpos = 0;
|
||||||
|
int line_i = board_nbl-(move[0]-'0');
|
||||||
|
int col_i = move[1]-'a';
|
||||||
|
int line_f = board_nbl-(move[2]-'0');
|
||||||
|
int col_f = move[3]-'a';
|
||||||
|
if(verbose >= 2) werror("==== play at "+line_i+" "+col_i+" "+line_f+" "+col_f+"\n");
|
||||||
|
if(line_i < 0 || line_f < 0) return false;
|
||||||
|
if(line_i >= board_nbl || line_f >= board_nbl) return false;
|
||||||
|
if(col_i < 0 || col_f < 0) return false;
|
||||||
|
if(col_i >= board_nbc || col_f >= board_nbc) return false;
|
||||||
|
if(abs(line_f-line_i) > 1) return false;
|
||||||
|
if(abs(col_f-col_i) > 1) return false;
|
||||||
|
if(nb_turn%2==0) {
|
||||||
|
board[line_i*board_nbc+col_i] = '.';
|
||||||
|
board[line_f*board_nbc+col_f] = 'o';
|
||||||
|
} else {
|
||||||
|
board[line_i*board_nbc+col_i] = '.';
|
||||||
|
board[line_f*board_nbc+col_f] = '@';
|
||||||
|
}
|
||||||
|
nb_turn ++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool endgame() {
|
||||||
|
for(int i = 0; i < board_nbc; i++)
|
||||||
|
if(board[i] == 'o') return true;
|
||||||
|
for(int i = (board_nbl-1)*board_nbc; i < board_nbl*board_nbc; i++)
|
||||||
|
if(board[i] == '@') return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int count_pawn_on_board() {
|
||||||
|
int ret = 0;
|
||||||
|
for(int i = 0; i < board_nbl*board_nbc; i++) {
|
||||||
|
if(board[i] != '.') ret += 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
void play() {
|
||||||
|
if (verbose >= 2) werror("\nBeginning a new game.\n");
|
||||||
|
p0_new_win = 0;
|
||||||
|
p1_new_win = 0;
|
||||||
|
p0_score = 0;
|
||||||
|
p1_score = 0;
|
||||||
|
p0->new_game(board_nbl, board_nbc);
|
||||||
|
p1->new_game(board_nbl, board_nbc);
|
||||||
|
init_board();
|
||||||
|
|
||||||
|
// perform a match
|
||||||
|
string p0_move = "";
|
||||||
|
string p1_move = "";
|
||||||
|
while(true) {
|
||||||
|
if(verbose >= 1) print_board();
|
||||||
|
array(int) Ti = System.gettimeofday();
|
||||||
|
p0_move = p0->generate_move();
|
||||||
|
if(verbose >= 2) werror("P0_move received : "+p0_move+"\n");
|
||||||
|
array(int) Tf = System.gettimeofday();
|
||||||
|
float ms = (float)((Tf[0] - Ti[0]))+(float)(Tf[1] - Ti[1])/1000000;
|
||||||
|
p0_remaining_time -= ms;
|
||||||
|
if(p0_remaining_time < 0.0) {
|
||||||
|
p0_new_win = 0; p1_new_win = 1;
|
||||||
|
werror(" ===> "+p0_name+" time exceeded\n");
|
||||||
|
print_board();
|
||||||
|
werror(" ===> "+p1_name+" WIN\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(play_move(p0_move) == false) {
|
||||||
|
p0_new_win = 0; p1_new_win = 1;
|
||||||
|
werror(" ===> "+p0_name+" try to play "+p0_move+"\n");
|
||||||
|
print_board();
|
||||||
|
werror(" ===> "+p1_name+" WIN\n");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if(verbose >= 2) {
|
||||||
|
werror("==== ok\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p1->move(p0_move);
|
||||||
|
if(endgame()) {
|
||||||
|
if(verbose >= 2) {
|
||||||
|
werror("=== endgame DETECTED\n");
|
||||||
|
print_board();
|
||||||
|
}
|
||||||
|
p0_new_win = 1;
|
||||||
|
p0_score = count_pawn_on_board();
|
||||||
|
p1_new_win = 0;
|
||||||
|
p1_score = -count_pawn_on_board();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(p0_move == "PASS" && p1_move == "PASS") {
|
||||||
|
if(verbose >= 2) werror("=== all players PASS DETECTED\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(verbose >= 2) print_board();
|
||||||
|
Ti = System.gettimeofday();
|
||||||
|
p1_move = p1->generate_move();
|
||||||
|
if(verbose >= 2) werror("P1_move received : "+p1_move+"\n");
|
||||||
|
Tf = System.gettimeofday();
|
||||||
|
ms = (float)((Tf[0] - Ti[0]))+(float)(Tf[1] - Ti[1])/1000000;
|
||||||
|
p1_remaining_time -= ms;
|
||||||
|
if(p1_remaining_time < 0.0) {
|
||||||
|
p1_new_win = 0; p0_new_win = 1;
|
||||||
|
werror(" ===> "+p1_name+" time exceeded\n");
|
||||||
|
print_board();
|
||||||
|
werror(" ===> "+p0_name+" WIN\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(play_move(p1_move) == false) {
|
||||||
|
p1_new_win = 0; p0_new_win = 1;
|
||||||
|
werror(" ===> "+p1_name+" try to play "+p1_move+"\n");
|
||||||
|
print_board();
|
||||||
|
werror(" ===> "+p0_name+" WIN\n");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if(verbose >= 2) {
|
||||||
|
werror("==== ok\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p0->move(p1_move);
|
||||||
|
if(in_game_pause > 0)
|
||||||
|
sleep(in_game_pause);
|
||||||
|
if(endgame()) {
|
||||||
|
if(verbose >= 2) {
|
||||||
|
werror("=== endgame DETECTED\n");
|
||||||
|
print_board();
|
||||||
|
}
|
||||||
|
p1_new_win = 1;
|
||||||
|
p1_score = count_pawn_on_board();
|
||||||
|
p0_new_win = 0;
|
||||||
|
p0_score = -count_pawn_on_board();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(p0_move == "PASS" && p1_move == "PASS") {
|
||||||
|
if(verbose >= 2) werror("=== all players PASS DETECTED\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void finalize() {
|
||||||
|
p0->quit(); p1->quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_many_games(btp_game game, int _nb_games_to_play, int verbose) {
|
||||||
|
game->nb_games = 0;
|
||||||
|
for (int k = 0; k < _nb_games_to_play; k++) {
|
||||||
|
game->play();
|
||||||
|
if(game->p0_new_win == 1) {
|
||||||
|
game->show_endgame();
|
||||||
|
werror("================= player1 WIN\n");
|
||||||
|
game->p0_wins ++;
|
||||||
|
}
|
||||||
|
if(game->p1_new_win == 1) {
|
||||||
|
game->show_endgame();
|
||||||
|
werror("================= player2 WIN\n");
|
||||||
|
game->p1_wins ++;
|
||||||
|
}
|
||||||
|
if(game->p0_new_win == 0 && game->p1_new_win == 0) {
|
||||||
|
werror("================= noone WIN\n");
|
||||||
|
}
|
||||||
|
game->nb_games ++;
|
||||||
|
game->print_score(game->output_dir+"/scores.txt");
|
||||||
|
}
|
||||||
|
game->finalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
string help_message =
|
||||||
|
"Usage: %s [OPTION]... [FILE]...\n\n"
|
||||||
|
"Runs one or many matches between two programs text protocol engines.\n"
|
||||||
|
"`--white' and `--black' options are mandatory.\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -n, --number=NB_GAMES the number of games to play\n"
|
||||||
|
" -l, --nbl=NB_LINES the number of lines on the board\n"
|
||||||
|
" -c, --nbc=NB_COLS the number of cols on the board\n"
|
||||||
|
" -f, --first=COMMAND_LINE\n"
|
||||||
|
" -s, --second=COMMAND_LINE command lines to run the two engines with.\n\n"
|
||||||
|
" -o, --outputdir=OUTPUT_DIRECTORY (default ouput is data)\n"
|
||||||
|
" --help display this help and exit.\n"
|
||||||
|
" -v, --verbose=LEVEL 1 - print moves, 2 and higher - draw boards.\n"
|
||||||
|
" -p, --pause=SECONDS 1 - sleep(1), 2 and more - sleep(2 and more).\n";
|
||||||
|
|
||||||
|
int main(int argc, array(string) argv) {
|
||||||
|
string hint = sprintf("Try `%s --help' for more information.\n",
|
||||||
|
basename(argv[0]));
|
||||||
|
if (Getopt.find_option(argv, UNDEFINED, "help")) {
|
||||||
|
write(help_message, basename(argv[0]));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
string str_p0 = Getopt.find_option(argv, "f", "first", UNDEFINED, "");
|
||||||
|
if (str_p0 == "") {
|
||||||
|
werror("First player is not specified.\n" + hint);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
string str_p1 = Getopt.find_option(argv, "s", "second", UNDEFINED, "");
|
||||||
|
if (str_p1 == "") {
|
||||||
|
werror("Second player is not specified.\n" + hint);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
string str_nb_games = Getopt.find_option(argv, "n", "games", UNDEFINED, "");
|
||||||
|
string str_nbl = Getopt.find_option(argv, "l", "nbl", UNDEFINED, "");
|
||||||
|
string str_nbc = Getopt.find_option(argv, "c", "nbc", UNDEFINED, "");
|
||||||
|
string str_output_dir = Getopt.find_option(argv, "o", "outputdir", UNDEFINED, "");
|
||||||
|
int verbose = (int) Getopt.find_option(argv, "v", "verbose", UNDEFINED, "0");
|
||||||
|
int in_game_pause = (int) Getopt.find_option(argv, "p", "pause", UNDEFINED, "0");
|
||||||
|
|
||||||
|
int game_nbl = 8; // default
|
||||||
|
int game_nbc = 8; // default
|
||||||
|
int nb_games = 1; // default
|
||||||
|
if (str_nbl != "") {
|
||||||
|
sscanf(str_nbl, "%d", game_nbl);
|
||||||
|
if(game_nbl <= 0) game_nbl = 8;
|
||||||
|
}
|
||||||
|
if (str_nbc != "") {
|
||||||
|
sscanf(str_nbc, "%d", game_nbc);
|
||||||
|
if(game_nbc <= 0) game_nbc = 8;
|
||||||
|
}
|
||||||
|
if (str_nb_games != "") {
|
||||||
|
sscanf(str_nb_games, "%d", nb_games);
|
||||||
|
if(nb_games <= 0) nb_games = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
btp_game game = btp_game(str_p0, str_p1, game_nbl, game_nbc, str_output_dir, in_game_pause, verbose);
|
||||||
|
if (game) {
|
||||||
|
run_many_games(game, nb_games, verbose);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Reference in a new issue