0
I am coding a chess game only in pure C. The game itself is ready, I am for some time trying to develop the algorithm of Minimax. Currently the algorithm is almost ready, but it is not returning and I think the problem is in the function of Minimax.
Current code below, I tried to run it, but when the AI tries to play, simply the game ends, it appears to be a loop again, but I did not identify it.
// liberando o lixo acumulado
void LiberarMemoria(Lista_ia* root){
Jogadas* next = root->head;
while(next != NULL){
Jogadas* tmp = next;
next = next->prox;
free(tmp);
}
free(root);
}
// Simulate 5 turn ahead for choose the best current move
Jogadas *minimax(int tabuleiro[TAM][TAM], int depth, int Player, Jogadas* novaJogada){
// Copy the board for don't change it
int i, j, copia[TAM][TAM];
for(i=0; i<=9; i++){
for(j=0; j<=9; j++){
copia[i][j] = tabuleiro[i][j];
}
}
copia[novaJogada->lin_dps][novaJogada->col_dps] = copia[novaJogada->lin_atual][novaJogada->col_atual];
copia[novaJogada->lin_atual][novaJogada->col_atual] = 0;
if(gameover(tabuleiro) == 1){
// Se o Player 2 (Computer) jogou e ganhou, agr seria a vez do player 1
if (Player == 1){
novaJogada->pontuacao = -99999;
return novaJogada;
}
else{
novaJogada->pontuacao = 99999;
return novaJogada;
}
}
if(depth == 0){
return novaJogada;
}
Lista_ia *Moves = inicializarLista();
verificar_jogadas_possiveis(copia, Moves, Player);
Jogadas *tmp;
// Simulating the current Player 2 (Computer) move
if(Player == 2){
novaJogada->pontuacao = -9999;
for(tmp = Moves->head; tmp != NULL; tmp = tmp->prox){
Jogadas *BestMove = minimax(copia, depth - 1, 1, tmp);
if(BestMove->pontuacao > novaJogada->pontuacao){
novaJogada->pontuacao = BestMove->pontuacao;
}
}
LiberarMemoria(Moves);
return novaJogada;
}
// Simulating the best Player 1 move
else{
novaJogada->pontuacao = 9999;
for(tmp = Moves->head; tmp != NULL; tmp = tmp->prox){
Jogadas *BestMove = minimax(copia, depth - 1, 2, tmp);
if(BestMove->pontuacao < novaJogada->pontuacao){
novaJogada->pontuacao = BestMove->pontuacao;
}
}
LiberarMemoria(Moves);
return novaJogada;
}
}
Jogadas *IniciarMinMax(int tabuleiro[TAM][TAM], int depth, int Player){
Lista_ia *Moves = inicializarLista();
// Copy the board for don't change it
int i, j, copia[TAM][TAM];
for(i=0; i<=9; i++){
for(j=0; j<=9; j++){
copia[i][j] = tabuleiro[i][j];
}
}
verificar_jogadas_possiveis(copia, Moves, Player);
Jogadas* bestMove = NULL;
Jogadas* tmp;
for(tmp = Moves->head; tmp != NULL; tmp = tmp->prox){
// iniciando busca
Jogadas *current = minimax(copia, depth, Player, tmp);
if(bestMove == NULL || current->pontuacao > bestMove->pontuacao){
bestMove = current;
}
}
// clonando resultado para retornar antes de liberar a memoria
Jogadas *result = (Jogadas*)malloc(sizeof(Jogadas));
result->lin_atual = bestMove->lin_atual;
result->col_atual = bestMove->col_atual;
result->lin_dps = bestMove->lin_dps;
result->col_dps = bestMove->col_dps;
result->pontuacao = bestMove->pontuacao;
LiberarMemoria(Moves);
return result;
}
Additional information you requested to help me with the problem.
typedef struct jogadas{
int lin_atual;
int col_atual;
int lin_dps;
int col_dps;
int pontuacao;
struct jogadas *prox;
}Jogadas;
typedef struct turno{
int turn;
struct turno *prox;
}Turno;
typedef struct lista_ia{
struct jogadas *head;
}Lista_ia;
void verificar_jogadas_possiveis(int tabuleiro[TAM][TAM], Lista_ia *Allmoves, int Player){
int i, j, m, n;
Jogadas *tmp;
for(i=1; i<9; i++){
for(j=1; j<9; j++){
if(checar_peca_inimiga(tabuleiro[i][j]) == Player){
for(m=1; m<9; m++){
for(n=1; n<9; n++){
tmp = (Jogadas*)malloc(sizeof(Jogadas));
tmp->lin_atual = i;
tmp->col_atual = j;
tmp->lin_dps = m;
tmp->col_dps = n;
if(validar_jogada(tabuleiro, tmp) == 1){
//tmp->pontuacao += pontuar_jogadas(tabuleiro, m, n);
tmp->pontuacao = 0;
tmp->prox = Allmoves->head;
Allmoves->head = tmp;
}
}
}
}
}
}
// Free memory space
free(tmp);
}
NOTE: the for is correct, I had forgotten but the board is a matrix 10x10 where the edges serve only to guide the player from where to play, as a naval battle... A, B, C, D... and 1, 2, 3, 4... etc.
"It fails and closes"... What mistake?
– Leandro Angelo
Apparently it enters a loop, because even error does not appear any, it only says that the program is no longer responding.
– dfop02
Not entering the merit of the program semantics: the ending condition of the recursion
minimax
is returning a pointer ofJogadas
without being initialized. Perhaps it would be returnedNULL
was it better? I just think.– Marcelo Shiniti Uchimura
A clear mistake is the size of the board
for(int i = 0; i <=9; i++)
should bei < 8
. Put some logs inside that loop to find where you’re locking, looking so it gets tricky if you mean what’s going on.– Christian Beregula
Could you tell how deep your search goes? When I was in college I did a game of chess tbm, and since there was almost no optimization in the code and the position evaluation algorithm was extremely slow, if I put him to look for something deeper than 5, he would easily spend 15 minutes looking for a move.
– Christian Beregula
The depth at first is 5 too. About for and other logical errors I have corrected, but is the structure itself of Minimax correct? It doesn’t work at all.
– dfop02
What the pointer
prox
ofJogadas
does? Does it point to the next move, or to other possible moves in the same turn? Yourfor
that calls recursion does not seem to make sense. Thetmp
What’s it for? Where does he check the current "score" to compare which is the best move? There’s a lot that doesn’t make sense yet. Posta sua structJogadas
and the functionverificar_jogadas_possiveis
to see if it helps to understand some things.– Christian Beregula
I added the information you asked for. The Prox pointer points to the next move within the list of moves of the same player. The tmp there serves to get a pass through all the moves within the list of structs Moves, I can not do in a simpler way. The score is made based on who you kill in the simulation, pawn are 10 points, horse 30, etc...
– dfop02
take a look now if the code I got from some help.
– Christian Beregula
I made all the modifications and the agr code seems to be more optimized, but I’m still in doubt about where "Play" should be. It still doesn’t work but I think we’re on the right track, I did some tests and it returns some moves but things have nothing unfortunately, I posted the current code to re-analyze.
– dfop02
You should not perform the moves on
tabuleiro
but rather in thecopia
. Before returning tonovaJogada
you must assign the value of the current position of the board to it. Thefree
within its functionverificar_jogadas_possiveis
time or another will cause inexplicable errors, why go release a valid move. Now to play you just need to create a list of movesLista_ia
before calling Minimax, and passing one by one to him, and then choosing the best.– Christian Beregula
I fixed the part of performing the simulated move, and on the check_moves I already corrected, only n edited here on the site. Can you explain better the final part you said about making a new List_ia, or give an example? I feel we are close to finally solving.
– dfop02
I still haven’t been able to come up with a plausible test result despite countless attempts, someone else can help?
– dfop02
What exactly would it be
Ainda não consegui chegar a um resultado plausivel
?– Christian Beregula
The chosen moves are not yet good... he kills himself or plays badly, it seems even random despite my efforts =/
– dfop02