typedef char **Board;
struct Player {
int startpos, endpos;
bool contbycpu;
int search_depth;
int playingnumber;
};
struct SMove {
SMove() { }
SMove(int ox2, int oy2, int tx2, int ty2) {
ox = ox2;
oy = oy2;
tx = tx2;
ty = ty2;
}
int ox, oy, tx, ty;
};
struct SJumpCoord {
SJumpCoord() { }
SJumpCoord(int xx, int yy) {
x = xx;
y = yy;
}
int x, y;
};
void minimax(int c_player, Player *player, int num_players, Board start_board, int board_size, std::list<SJumpCoord> *movelist);
int AlphaBeta (Board pos, int current_player, int max_for, int num_players, int depth, int alpha, int beta, int board_size, Player *player, SMove &best_move, int gs);
// fills move_list with possible moves **REMOVED FOR CONVIENCE**
void Successors(Board pos, std::list<SMove> &move_list, int current_player, int board_size);
// evaluates the board (numerical value rating board) **REMOVED FOR CONVIENCE**
int Evaluate(Board pos, int current_player, int board_size, int num_players, Player *player, int gs);
// absolute value **REMOVED FOR CONVIENCE**
int abs(int x);
// value squared **REMOVED FOR CONVIENCE**
int sqred(int x);
// 0 for still running, 1-6 for corrosponding player wins **REMOVED FOR CONVIENCE**
int get_gamestate(Board board, Player player[6], int num_players, int board_size);
// frees memory set for output **REMOVED FOR CONVIENCE**
int clear_output(char **(&output), int n);
// stores player id's pieces in output **REMOVED FOR CONVIENCE**
void get_players_pieces(Board board, char **(&output), int id, int n);
// stores the position of the pieces end position in output **REMOVED FOR CONVIENCE**
int get_piece_pos(int board_size, int pos, char **(&output));
const int INF_INITY = 100000;
const int MAX_VAL = 90000;
/*
Player player[6]; // info on players
c_player; // 1-6
num_players; // 1-6
start_board; // current 'board'
board_size; // size of 'board' (note board would be declared as board[board_size*4+1][board_size*4+1]
movelist; // output
*/
void minimax(int c_player, Player *player, int num_players, Board start_board, int board_size, std::list<SJumpCoord> *movelist) {
SMove best_move; // storage for best move
AlphaBeta(start_board, c_player, c_player, num_players, player[c_player-1].search_depth, -INF_INITY, INF_INITY, board_size, player, best_move, 0);
movelist->clear(); // clear movelist
movelist->push_back(SJumpCoord(best_move.ox, best_move.oy)); // add orign to movelist
movelist->push_back(SJumpCoord(best_move.tx, best_move.ty)); // add target to movelist
}
int AlphaBeta (Board pos, int current_player, int max_for, int num_players, int depth, int alpha, int beta, int board_size, Player *player, SMove &best_move, int gs) {
if (depth == 0 || gs != 0) { // if we reached the leaf:
return Evaluate(pos, max_for, board_size, num_players, player, gs);
}
SMove next_move, new_move; // stores next move
int best = -INF_INITY, value;
std::list<SMove> succ; // storage for successor moves
Successors(pos, succ, current_player, board_size);
int next_player = current_player + 1;
if(next_player > num_players)
next_player = 1;
while(!succ.empty() && best < beta) {
new_move = succ.front();
succ.pop_front();
if(best > alpha)
alpha = best;
pos[new_move.tx][new_move.ty] = pos[new_move.ox][new_move.oy];
pos[new_move.ox][new_move.oy] = 0;
// peek next gs
int gs = get_gamestate(pos, player, num_players, board_size);
ab_depth++;
if(gs != 0 || depth -1 == 0) {
value = AlphaBeta (pos, next_player, max_for, num_players, depth-1, alpha, beta, board_size, player, next_move, gs);
} else if(next_player == max_for || current_player == max_for) {
value = -AlphaBeta (pos, next_player, max_for, num_players, depth-1, -beta, -alpha, board_size, player, next_move, gs);
} else {
value = AlphaBeta (pos, next_player, max_for, num_players, depth-1, alpha, beta, board_size, player, next_move, gs);
}
ab_depth--;
pos[new_move.ox][new_move.oy] = pos[new_move.tx][new_move.ty];
pos[new_move.tx][new_move.ty] = 0;
if(value > best) {
best = value;
best_move.ox = new_move.ox;
best_move.oy = new_move.oy;
best_move.tx = new_move.tx;
best_move.ty = new_move.ty;
}
}
return best;
}
int Evaluate(Board pos, int current_player, int board_size, int num_players, Player *player, int gs) {
char **current = NULL, **target = NULL;
if(gs != 0) {
if(gs == current_player) {
return MAX_VAL;
} else {
return -MAX_VAL;
}
}
int value = 0;
for(int i = 0; i < num_players; i++) {
get_players_pieces(pos, current, i, board_size);
int np = get_piece_pos(board_size, player[i-1].endpos, target);
for(int j = 0; j < np; j++) {
if(current_player-1 == i) {
value -= sqred(current[j][0] - target[j][0]) + sqred(current[j][1] - target[j][1]);
} else {
value += sqred(current[j][0] - target[j][0]) + sqred(current[j][1] - target[j][1]);
}
}
}
clear_output(current, board_size);
clear_output(target, board_size);
return value;
}
Minimax help (in algorithm)
Hi,
I'm trying to implement an AI into my Chinese Checkers game, and decided to use minimax trees, with alpha beta pruning.
My code is running very slowly, as well as not picking the 'best' movement (sometimes it moves back and forwards, staying still).
Any suggestions?
Thanks.
Here is my code, it is heavily based upon this article: http://chess.verhelst.org/1997/03/10/search/#alpha-beta
Slowly as in the following times were taken to minimax (ms):
1503
1352
4939
8169
21125
17781
30664
21174
35169
22374
[Edited by - Zeophlite on April 12, 2006 12:06:26 AM]
MinMax, even with AlphaBeta, is slow. A game tree will only return as good a move as it can find given a certain depth.
If I were you I would create a set of problems where you know the answer. Something like 'computer to win in 5 moves'.
Run your program against your test scenarios, and see what it does.
One thing about games such as these: if the computer has no immediate advantage in sight, it will play like crap. You might just have a very weak evaluation function.
Will
If I were you I would create a set of problems where you know the answer. Something like 'computer to win in 5 moves'.
Run your program against your test scenarios, and see what it does.
One thing about games such as these: if the computer has no immediate advantage in sight, it will play like crap. You might just have a very weak evaluation function.
Will
------------------http://www.nentari.com
Is it worth then investigating a different AI approach?
What would you suggest?
What would you suggest?
Maybe.
I would suggest you do what I said earlier. :)
Try adding more terms to your evaluation function. Focus on giving the function an incentive to make the player move towards the other side of the board.
Will
[Edited by - RPGeezus on April 12, 2006 9:01:19 AM]
I would suggest you do what I said earlier. :)
Try adding more terms to your evaluation function. Focus on giving the function an incentive to make the player move towards the other side of the board.
Will
[Edited by - RPGeezus on April 12, 2006 9:01:19 AM]
------------------http://www.nentari.com
It would be useful for you to see the results from just a simple MinMax search. If I were you, I would scrap AlphaBeta for now. Get a MinMax search working as it should, then try converting to AlphaBeta.
______Tom
Are you sure there isn't a bug you haven't catched? It sounds verry strange to me that your computer moves the pieces forth and back.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement