This repository has been archived on 2023-04-18. You can view files and clone it, but cannot push or open issues or pull requests.
iaj/TP2/mybt.h
2023-02-16 20:35:32 +01:00

307 lines
8.7 KiB
C++

#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 */