void Perft::run() { std::unique_ptr<Position> position(new Position(Notation::toPosition(Notation::STANDARDPOSITION))); int depth = MAX_DEPTH; std::cout << "Testing " << Notation::fromPosition(*position) << " at depth " << depth << std::endl; auto startTime = std::chrono::system_clock::now(); uint64_t result = miniMax(depth, *position, 0); auto endTime = std::chrono::system_clock::now(); auto duration = endTime - startTime; std::cout << "Nodes: "; std::cout << result << std::endl; std::cout << "Duration: "; std::cout << std::setfill('0') << std::setw(2) << std::chrono::duration_cast<std::chrono::hours>(duration).count() << ":"; std::cout << std::setfill('0') << std::setw(2) << (std::chrono::duration_cast<std::chrono::minutes>(duration) - std::chrono::duration_cast<std::chrono::minutes>(std::chrono::duration_cast<std::chrono::hours>(duration))).count() << ":"; std::cout << std::setfill('0') << std::setw(2) << (std::chrono::duration_cast<std::chrono::seconds>(duration) - std::chrono::duration_cast<std::chrono::seconds>(std::chrono::duration_cast<std::chrono::minutes>(duration))).count() << "."; std::cout << std::setfill('0') << std::setw(2) << (std::chrono::duration_cast<std::chrono::milliseconds>(duration) - std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::duration_cast<std::chrono::seconds>(duration))).count(); std::cout << std::endl; std::cout << "n/ms: " << result / std::chrono::duration_cast<std::chrono::milliseconds>(duration).count() << std::endl; }
void iaMinMax(t_jogador *jogador,char time,t_jogada *jogada,t_jogo *jogo,void *data) { unsigned int t0 = SDL_GetTicks(); unsigned int i; jogada->time = time; t_miniMax *parametros = data; unsigned int profundidade = parametros->profundidadeMaxima; unsigned int tempo = parametros->tempoMaximo; //double melhorValor = -5; t_jogada melhorJogada; for(i=1 ; i<profundidade && (SDL_GetTicks() - t0 < tempo); i++) { ERR("Profundidade: %d\n",i); double val = fabs(miniMax(time,jogada,jogo,-2,2,1,i,tempo,1,t0)); if(val < 2) { //melhorValor = val; memcpy(&melhorJogada,jogada,sizeof(melhorJogada)); } ERR("Valor :%lf\n",val); } memcpy(jogada,&melhorJogada,sizeof(melhorJogada)); ERR("O:%u\tD:%u\n",jogada->posOrigem,jogada->posDestino); }
uint64_t Perft::miniMax(int depth, Position& position, int ply) { if (depth == 0) { return 1; } uint64_t totalNodes = 0; bool isCheck = position.isCheck(); MoveGenerator& moveGenerator = moveGenerators[ply]; MoveList<MoveEntry>& moves = moveGenerator.getMoves(position, depth, isCheck); for (int i = 0; i < moves.size; ++i) { int move = moves.entries[i]->move; position.makeMove(move); if (!position.isCheck(Color::opposite(position.activeColor))) { totalNodes += miniMax(depth - 1, position, ply + 1); } position.undoMove(move); } return totalNodes; }
int miniMaxThread(void *minmaxData) { t_miniMaxData *d = minmaxData; d->val = miniMax(d->time,d->jogada,d->jogoOrig,d->alfa,d->beta,d->cor,d->profundidade,d->tempoMax,d->primeiro,d->t0); return 0; }
double miniMax(char time,t_jogada *jogada,t_jogo *jogoOrig,double alfa, double beta, int cor, unsigned int profundidade,unsigned int tempoMax,char primeiro,unsigned int t0) { t_jogador *jogador; int filhos = 0; if(profundidade == 0) { return funcaoHeuristica(time,jogoOrig); } else { if(SDL_GetTicks() - t0 > tempoMax) { return -2; } char outroTime = (time==P1) ? P2 : P1; t_jogo jogo; memcpy(&jogo,jogoOrig,sizeof(*jogoOrig)); t_jogada melhorJogada; if(time == P1) jogador = &jogo.p1; else jogador = &jogo.p2; unsigned int movimentos[14]; unsigned int numMov = 0; unsigned int capturas[14]; unsigned int numCapt = 0; //para cada peca do jogador, calcula seus movimentos possiveis int i; unsigned char *pecaPos[2] = {jogador->peaoPos,jogador->torrePos}; unsigned char numPeca[2] = {jogador->numPeoes,jogador->numTorres}; int t; t_jogo outroJogo; for(t=0 ; t<2 ; t++) { for(i=0 ; i<numPeca[t] ; i++ ) { filhos++; //faz uma copia do jogo original memcpy(&jogo,jogoOrig,sizeof(*jogoOrig)); memcpy(&outroJogo,jogoOrig,sizeof(*jogoOrig)); unsigned int pos = pecaPos[t][i]; movimentosPossiveis(jogo.tabuleiro,pos,movimentos,&numMov,capturas,&numCapt); unsigned int peca = jogo.tabuleiro[pos]; unsigned int k; //aplica o negamax para cada jogada possivel unsigned int j; unsigned int *tipoMovimento[2] = {capturas,movimentos}; unsigned int numMovimento[2] = {numCapt,numMov}; int m; for(m=0 ; m<2 ; m++) { for(j=0 ; j<numMovimento[m] ; j++) { //faz uma copia do jogo original memcpy(&jogo,jogoOrig,sizeof(*jogoOrig)); jogada->time = time; jogada->pecaOrigem = jogo.tabuleiro[pos]; jogada->posOrigem = pos; jogada->posDestino = tipoMovimento[m][j]; //copia a jogada t_jogada bakJogada; if(primeiro) memcpy(&bakJogada,jogada,sizeof(*jogada)); executaJogada(&jogo,jogada); double val; //verifica se a jogada levara ao termino do jogo int estado = fimDeJogo(&jogo,outroTime); if(estado == DRAW) { val = 0; } else if(estado == time) { val = 1; } else if(estado == outroTime) { val = -1; } else val = -miniMax(outroTime,jogada,&jogo,-beta,-alfa,-cor,profundidade-1,tempoMax,0,t0); if(val >= beta) { if(primeiro) memcpy(jogada,&bakJogada,sizeof(*jogada)); return val; } if (val > alfa) { if(primeiro) memcpy(&melhorJogada,&bakJogada,sizeof(*jogada)); alfa = val; } }//end for movimento }//end for tipo de movimento }//end for peca }//end for t if(primeiro) memcpy(jogada,&melhorJogada,sizeof(*jogada)); } return alfa; }
/* Returns Array={index , benifit } */ int* miniMax(char box[] , bool player) { int a[2]; int x=gameOver(box); int i,j,k,l,index; /* Base case */ if(x!=-1) { a[0]=-1; a[1]=x; return a; } /* Main Part*/ if(player==true) { int mx=-100; // Max. possible score of 'X' /*Check all possible moves*/ for(i=1;i<10;i++) { if(box[i]==' ') { /* Fill this box*/ box[i]='X'; filled++; int *a; a=miniMax(box , !player); if(mx < a[1]) { mx=a[1]; index=i; } /* Unfill this box*/ box[i]=' '; filled--; } } a[0]=index; a[1]=mx; return a; } else { int mn=+100; // Min. possible score of 'O' for(i=1;i<10;i++) { if(box[i]==' ') { box[i]='O'; filled++; int *a; a=miniMax(box , !player); if(mn > a[1]) { mn=a[1]; index=i; } box[i]=' '; filled--; } } a[0]=index; a[1]=mn; return a; } }
int main() { char box[10]={' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',}; char currentPlayer='O'; int index,i,j,x; /* Choose first move */ printf("You are Mr. O\n"); printf("Who will start game ? ( Enter 'O' or 'X') : "); scanf("%c",¤tPlayer); /* Continue game until result declares */ while(gameOver(box)==-1 && filled<9) { printMatrix(box); /* If all the boxes are filled then game is over */ if(filled == 9) { printf("...DRAW...\n"); printMatrix(box); return 0; } printf("Player %c :: ",currentPlayer=='O'?'O':'X'); if(currentPlayer=='X') { // Computer 'X' int *a; /* Check immediate state if winning is possible or not ? */ for(i=1;i<10;i++) { if(box[i]==' ') { box[i]='X'; x=gameOver(box); if(x==10) { box[i]='X'; system("cls"); displayResult(box); system("pause"); return 0; } box[i]=' '; } } a=miniMax(box , true); index=a[0]; } else { // You 'O' while(1) { scanf("%d",&index); if(box[index]!=' ') printf("Enter valid index : "); else break; } } /* Fill the BOX */ box[index]=(currentPlayer=='O'?'O':'X'); filled++; currentPlayer= (currentPlayer=='O'?'X':'O') ; system("cls"); } displayResult(box); return 0; }