int min(AntiChess ob,int alpha,int beta,int depth,Move move){ int minimum = INFINITY; int temp; int i; obCorrection(ob); playMove(ob,move); if (depth == MaxDepth){ return heuristics(ob); } for (i=0 ; i < ob.totalMoves ; i++){ if (temp = max(ob,alpha,beta,depth+1,ob.validMoves[i]) < beta){ beta = temp; } if (alpha > beta) return beta; } return beta; }
int UltimateTicTacToeMontecarloAI::expand(int leafIndex, Nodes& nodes, int const player) const { Node& node = nodes[leafIndex]; node.children.reserve(maxChildren); Moves options = movementOptions(node.board, node.previousMove); int turn = node.previousMove > 0 ? otherPlayer(node.board.grids.at(node.previousMove)) : player; int mostPromisingChildIndex = -1; int mostPromisingChildScore = 0; while(node.children.size() < maxChildren && !options.empty()) { Move move = options.takeAt(qrand() % options.size()); int childIndex = nodes.size(); node.children.append(childIndex); Board newBoard(node.board); nodes.append( Node {0, 1, playMove(newBoard, move, turn), move, leafIndex, Node::Children()}); int score = scoreBoard(nodes.last().board, player); if(score > mostPromisingChildScore || mostPromisingChildIndex < 0) { mostPromisingChildIndex = childIndex; mostPromisingChildScore = score; } } return mostPromisingChildIndex; }
// Returns: // 0 = Legal Move // 1 = Illegal Move int Chess::playPieceMove(int sq_dest) { //get move that goes to sq_dest int i; for(i=0; i<STORE_SIZE; i++) { //If the move goes to where we want... if(moves[i].to == sq_dest) { playMove(&pos, &pos, &moves[i], pos.toPlay); return 0; } } // There was no move to play. return 1; }
static void storeMoveIfLegal(const position* const pos, move* m, const int player, move store[], int *numMoves) { position newPosition; int status; int opponent; status = playMove(pos, &newPosition, m, player); if(status != ILLEGAL) { /* move is legal */ /* check that the move does not put players king in check, which would be illegal */ if(!inCheck(&newPosition, player, newPosition.kingSquare[player])) { /* calculate evaluation */ opponent = OPPONENT(player); if(inCheck(&newPosition, opponent, newPosition.kingSquare[opponent])) { m->flags |= CHECK; m->eval += EVAL_CHECK; } store[(*numMoves)++] = *m; } } }
int UltimateTicTacToeMontecarloAI::simulate(Board board, int const previousMove, int const player) const { int turn = previousMove > 0 ? otherPlayer(board.grids.at(previousMove)) : player; GameState state = gameState(board, player); Move prev = previousMove; while(state == GameState::UNRESOLVED) { Moves options = movementOptions(board, prev); Move option = options.at(qrand() % options.size()); playMove(board, option, turn); turn = otherPlayer(turn); state = gameState(board, player); prev = option; } switch(state) { case GameState::WIN: return 1; case GameState::LOSE: return -1; default: return 0; } }
void manager::handleLeftClick(int x, int y) { /* switch (m_index) { m_boardScene->addBlackStone(x, y); m_boardScene->addWhiteStone(x, y); m_boardScene->addMark(x, y); m_boardScene->addCircle(x, y); m_boardScene->addSquare(x, y); m_boardScene->addTriangle(x, y); m_boardScene->addLabel(x, y, m_label); qDebug() << "wrong combobox current index"; }*/ std::cout << "LeftClick on (" << x << ", " << y << ")." << std::endl; if (game_.nowWinner()==Player::None()) { Move m(game_.CurrentPlayer(), Location(x, y)); bool ok = putStone(m); if (ok && auto_reply && auto_player!=Player::None()) playMove(); } else { std::cout << "Game has already finished." << std::endl; } }
int MinimaxStrategy::minimax() { Move m; MoveList list; // int maxEval, minEval; int bestEval; int eval; int sign; if(current_depth == MAX_DEPTH) return evaluate(); bestEval = -17000; // maxEval = -17000; // minEval = 17000; generateMoves(list); if(evaluate() == 16000) { if(current_depth == 0) finishedNode(0,0); pretty_print("current_depth", current_depth); return ((current_depth % 2) ==0) ? -16000 : 16000; } if((MAX_DEPTH-current_depth)%2 == 1) sign = 1; else sign = -1; while(list.getNext(m)) { if(current_depth < MAX_DEPTH) { current_depth++; playMove(m); eval=minimax(); takeBack(); current_depth--; } if(sign*eval > bestEval) { bestEval = sign*eval; if(unlikely(current_depth == 0)) { pretty_print("Eval", bestEval); foundBestMove(0, m, eval); } } #if 0 if((MAX_DEPTH - current_depth +1) % 2 == 0) { if(eval > maxEval) { maxEval=eval; if(current_depth == 0) { pretty_print("Eval", eval); foundBestMove(0, m, eval); } } } else { if(eval < minEval) { minEval=eval; if(current_depth == 0) { pretty_print("Eval2", eval); foundBestMove(0, m, eval); } } } #endif } bestEval = sign*bestEval; if(current_depth == 0) finishedNode(0,0); #if 0 if((MAX_DEPTH - current_depth +1) % 2 == 0) return maxEval; else return minEval; #endif return bestEval; }
int alphaBeta(int depth, int alpha, int beta, bool whiteToPlay) { int val, i; EVALUATE_INFO_t eval = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint32_t legalMoves = 0; PIECE_t pieceBackup; PIECE_e piece; #if ENABLE_TRANSPOSITION_TABLE int hashFlag = ALPHA_HASH_RESULT; if (val = probeHash(depth, alpha, beta) != UNKNOWN_HASH_RESULT) { cacheHits++; return val; } else { cacheMisses++; } #endif // ENABLE_TRANSPOSITION_TABLE // calculate all of the moves MOVE_t moves[MOVE_LIST_SIZE]; legalMoves += AddAllLegalMovesToMoveList(moves, &eval, whiteToPlay); if (!legalMoves && depth == currentDepth) { printf("pass"); exit(0); } if (depth == 0) { numberEvaluations++; AddAllLegalMovesToMoveList(&moves[legalMoves-1], &eval, !whiteToPlay); val = evaluateBoard(&eval); #if ENABLE_TRANSPOSITION_TABLE recordHash(depth, val, EXACT_HASH_RESULT); #endif //ENABLE_TRANSPOSITION_TABLE if (!whiteToPlay) val = val * -1; return val; } numberNodes++; // for each move for (i = 0; i < legalMoves; i++) { // backup piece so we can undo the move later piece = (moves[i].move & PIECE_MASK) >> PIECE_SHIFT; pieceBackup.piece = pieces[piece].piece; // play the move playMove(moves, i); // Check to see if this position is a win val = isWin(); if (!whiteToPlay) { val = val*-1; } if (val > DRAW_SCORE) { val = val + depth; } else if (val < 0) { val = val - depth; } else if (val == DRAW_SCORE) { val = 0; } else { // not a win or draw; search deeper //val = alphaBeta(depth - 1, alpha, beta, !whiteToPlay); val = -alphaBeta(depth - 1, -beta, -alpha, !whiteToPlay); } // undo move undoMove(pieceBackup, piece); // alpha beta pruning: if (val >= beta) { #if ENABLE_TRANSPOSITION_TABLE recordHash(depth, beta, BETA_HASH_RESULT); #endif //ENABLE_TRANSPOSITION_TABLE return beta; } if (val > alpha) { alpha = val; if (depth == currentDepth) { currMove.move = moves[i].move; currentScore = val; } #if ENABLE_TRANSPOSITION_TABLE hashFlag = EXACT_HASH_RESULT; #endif //ENABLE_TRANSPOSITION_TABLE } } #if ENABLE_TRANSPOSITION_TABLE recordHash(depth, alpha, hashFlag); #endif //ENABLE_TRANSPOSITION_TABLE return alpha; }
/* * We always try the maximize the board value */ int Board::search(int depth, int alpha, int beta) { int actValue= -14999+depth, value; Move m; MoveList list; bool depthPhase, doDepthSearch; searchCalled++; /* We make a depth search for the following move types... */ int maxType = (depth < maxDepth-1) ? Move::maxMoveType() : (depth < maxDepth) ? Move::maxPushType() : Move::maxOutType(); generateMoves(list); #ifdef MYTRACE int oldRatedPositions; int oldWonPositions; int oldSearchCalled; int oldMoveCount; int oldNormalCount; int oldPushCount; int oldOutCount; int oldCutoffCount; spyDepth = depth; moveCount += list.getLength(); /* if (spyLevel>1) { indent(depth); qDebug("%s (%6d .. %6d) MaxType %s\n", depth, (color==color1)?"O":"X", alpha,beta, (depth < maxDepth-1) ? "Moving" : (depth < maxDepth)? "Pushing" : "PushOUT" ); } */ #endif /* check for a old best move in main combination */ if (inPrincipalVariation) { m = pv[depth]; if ((m.type != Move::none) && (!list.isElement(m, 0, true))) m.type = Move::none; if (m.type == Move::none) inPrincipalVariation = false; #ifdef MYTRACE else { if (spyLevel>1) { indent(spyDepth); qDebug("Got from pv !\n" ); } } #endif } // first, play all moves with depth search depthPhase = true; while (1) { // get next move if (m.type == Move::none) { if (depthPhase) depthPhase = list.getNext(m, maxType); if (!depthPhase) if (!list.getNext(m, Move::none)) break; } // we could start with a non-depth move from principal variation doDepthSearch = depthPhase && (m.type <= maxType); #ifdef MYTRACE if (m.isOutMove()) outCount++; else if (m.isPushMove()) pushCount++; else normalCount++; if (doDepthSearch) { oldRatedPositions = ratedPositions; oldWonPositions = wonPositions; oldSearchCalled = searchCalled; oldMoveCount = moveCount; oldNormalCount = normalCount; oldPushCount = pushCount; oldOutCount = outCount; oldCutoffCount = cutoffCount; if (spyLevel>1) { indent(spyDepth); qDebug("%s [%6d .. %6d] ", (color==color1)?"O":"X", alpha,beta); m.print(); qDebug("\n"); } #ifdef SPION if (bUpdateSpy) emit update(depth, 0, m, false); #endif } #endif playMove(m); if (!isValid()) { /* Possibility (1) to win: Piece Count <9 */ value = 14999-depth; // value = ((depth < maxDepth) ? 15999:14999) - depth; #ifdef MYTRACE wonPositions++; #endif } else { if (doDepthSearch) { /* opponent searches for his maximum; but we want the * minimum: so change sign (for alpha/beta window too!) */ value = - search(depth+1,-beta,-alpha); } else { ratedPositions++; value = calcEvaluation(); } } takeBack(); /* For GUI response */ if (doDepthSearch && (maxDepth - depth >2)) emit searchBreak(); #ifdef MYTRACE if (doDepthSearch) { spyDepth = depth; if (spyLevel>1) { indent(spyDepth); if (oldSearchCalled < searchCalled) { qDebug(" %d Calls", searchCalled-oldSearchCalled); if (cutoffCount>oldCutoffCount) qDebug(" (%d Cutoffs)", cutoffCount-oldCutoffCount); qDebug(", GenMoves %d (%d/%d/%d played)", moveCount - oldMoveCount, normalCount - oldNormalCount, pushCount-oldPushCount, outCount-oldOutCount); qDebug(", Rate# %d", ratedPositions+wonPositions - oldRatedPositions - oldWonPositions); if (wonPositions > oldWonPositions) qDebug(" (%d Won)", wonPositions- oldWonPositions); qDebug("\n"); indent(spyDepth); } qDebug(" => Rated %d%s\n", value, (value>14900) ? ", WON !": (value>=beta) ? ", CUTOFF !": (value>actValue) ? ", Best !": ""); } } else { if (spyLevel>2) { indent(spyDepth); qDebug("%s (%6d .. %6d) %-25s => Rating %6d%s\n", (color==color1)?"O":"X", alpha,beta, m.name().toLatin1(), value, (value>14900) ? ", WON !": (value>=beta) ? ", CUTOFF !": (value>actValue) ? ", Best !": ""); } } if (value>=beta) cutoffCount++; #endif #ifdef SPION if (bUpdateSpy) { if (value > actValue) emit updateBest(depth, value, m, value >= beta); emit update(depth, value, m, true); } #endif if (value > actValue) { actValue = value; pv.update(depth, m); // Only update best move if not stopping search if (!breakOut && (depth == 0)) { _bestMove = m; if (bUpdateSpy) { emit updateBestMove(m, actValue); #ifdef MYTRACE if (spyLevel>0) { int i; qDebug("> New pv (Rating %d):", actValue); for(i=0;i<=maxDepth;i++) { qDebug("\n> D %d: %s", i, pv[i].name().toLatin1() ); } qDebug("\n>\n"); } #endif } } if (actValue>14900 || actValue >= beta) return actValue; /* maximize alpha */ if (actValue > alpha) alpha = actValue; } if (breakOut) depthPhase=false; m.type = Move::none; } return actValue; }
/** * Menu de sélection de l'unité * @param choice Choix de l'action pour l'unité */ void unitMenu(int choice){ char yn[2]; printf("\n"); switch(choice){ case 1: clearScreen(); // Met à jour l'affichage pour le tour gridDisp(); if(!hasAttacked && !hasMoved){ movable(white); // Fait la liste des unités pouvant se déplacer clearScreen(); // Met à jours les couleurs des unités déplaçables gridDisp(); printf("\nSe déplacer ? y/n\n"); readS(yn); printf("\n"); if(strcmp(yn,"y") == 0 || strcmp(yn,"Y") == 0) { playMove(); }else if(strcmp(yn,"n") != 0 && strcmp(yn,"N") != 0){ printf("Saisie invalide\n"); } movable(black); }else if(hasAttacked){ color(red, "Vous ne pouvez pas déplacer votre unité après avoir attaqué !\n"); }else{ color(red, "Vous ne pouvez pas déplacer une unité à nouveau !\n"); } break; case 2: clearScreen(); // Met à jour l'affichage pour le tour gridDisp(); if(!hasAttacked){ attackable(white); // Attaquants en blanc clearScreen(); // Met à jours les couleurs des unités pouvant attaquer gridDisp(); printf("\nAttaquer ? y/n\n"); readS(yn); printf("\n"); if(strcmp(yn,"y") == 0 || strcmp(yn,"Y") == 0) { playAttack(); }else if(strcmp(yn,"n") != 0 && strcmp(yn,"N") != 0){ printf("Saisie invalide\n"); } attackable(black); // Attaquants en noir }else{ color(red, "Vous ne pouvez pas réattaquer !\n"); } break; case 3: movable(white); clearScreen(); gridDisp(); printList(noPlayer); printf("\nChanger de direction ? y/n\n"); readS(yn); printf("\n"); if(strcmp(yn,"y") == 0 || strcmp(yn,"Y") == 0) { changeDirection(); }else if(strcmp(yn,"n") != 0 && strcmp(yn,"N") != 0){ printf("Saisie invalide\n"); } movable(black); clearScreen(); gridDisp(); break; } }
Move Board::moveToReach(Board* b, bool fuzzy) { Move m; /* can not move from invalid position */ int state = validState(); if ((state != valid1) && (state != valid2)) return m; if (!fuzzy) { if (b->moveNo() != _moveNo+1) { if (_verbose) printf("Board::moveToReach: moveNo %d => %d ?!\n", _moveNo, b->moveNo()); return m; } /* only time left for player can have decreased */ int opponent = (color == color1) ? color2 : color1; if (_msecsToPlay[opponent] != b->msecsToPlay(opponent)) { if (_verbose) printf("Board::moveToReach: Opponent time changed ?!\n"); return m; } if (_msecsToPlay[color] < b->msecsToPlay(color)) { if (_verbose) printf("Board::moveToReach: Player time increased ?!\n"); return m; } } /* detect move drawn */ MoveList l; generateMoves(l); if (_verbose) { printf("Board::moveToReach - %d allowed moves:\n", l.getLength()); Move found; int type = Move::none; while(l.getNext(m, Move::maxMoveType)) { playMove(m); bool isSame = hasSameFields(b); takeBack(); if (isSame) found = m; if (m.type != type) { type = m.type; printf(" %s:\n", m.typeName()); } printf(" %s%s\n", m.name(), isSame ? " <== Choosen":""); } m = found; } else { while(l.getNext(m, Move::maxMoveType)) { playMove(m); bool isSame = hasSameFields(b); takeBack(); if (isSame) break; } } return m; }
int MinimaxStrategy::minimax() { Move m; Move bestestMove; //;-p This is the cumulative best move among all threads. MoveList list; int bestEval; int eval; int sign; int move_counter=0; int i=0; if(current_depth == MAX_DEPTH) return evaluate(); bestEval = -17000; generateMoves(list); if(evaluate() == 16000) { if(current_depth == 0) finishedNode(0,0); pretty_print("current_depth", current_depth); return ((current_depth % 2) ==0) ? -16000 : 16000; } if(current_depth == 0) { for(i=0;i<thread_rank;i++) list.getNext(m); } if((MAX_DEPTH-current_depth)%2 == 1) sign = 1; else sign = -1; while(list.getNext(m)) { if(current_depth < MAX_DEPTH) { current_depth++; playMove(m); eval=minimax(); takeBack(); current_depth--; } if(sign*eval > bestEval) { bestEval = sign*eval; if(unlikely(current_depth == 0)) { pretty_print("Eval", bestEval); foundBestMove(0, m, eval); } } if(current_depth == 0) { for(i=1;i<num_threads;i++) list.getNext(m); } } bestEval = sign*bestEval; if(current_depth == 0) { if(thread_rank==0) { Move *moves=NULL; int *eval_results; moves=(Move*)malloc((num_threads -1)*sizeof(Move)); eval_results=(int*)malloc((num_threads - 1)*sizeof(int)); //all threads send value to thread 0 for(int i=1;i<num_threads;i++) { MPI_Status status; MPI_Recv((void*)&moves[i-1], sizeof(Move), MPI_BYTE, i, 10, MPI_COMM_WORLD, &status); MPI_Recv(&eval_results[i-1], 1, MPI_INT, i, 10, MPI_COMM_WORLD, &status); } bestestMove=_bestMove; for(int i=0;i<num_threads-1;i++) { if(sign*eval_results[i] > sign*bestEval) { bestEval = eval_results[i]; bestestMove=moves[i]; } } for(int i=1;i<num_threads;i++) { MPI_Send (&bestestMove, sizeof(Move), MPI_BYTE, i, 10, MPI_COMM_WORLD); MPI_Send (&bestEval, 1, MPI_INT, i, 10, MPI_COMM_WORLD); } } else { MPI_Send (&_bestMove, sizeof(Move), MPI_BYTE, 0, 10, MPI_COMM_WORLD); MPI_Send (&bestEval, 1, MPI_INT, 0, 10, MPI_COMM_WORLD); MPI_Status status; MPI_Recv(&bestestMove, sizeof(Move), MPI_BYTE, 0, 10, MPI_COMM_WORLD, &status); MPI_Recv(&bestEval, 1, MPI_INT, 0, 10, MPI_COMM_WORLD, &status); } foundBestMove(0, bestestMove, bestEval); finishedNode(0,0); } return bestEval; }
/* * We always try the maximize the board value */ int Board::search(int depth, int alpha, int beta) { int actValue=-16000, value; Move m; MoveList list; bool stop = false; /* We make a depth search for the following move types... */ int maxType = (depth < maxDepth/2) ? Move::maxMoveType() : (depth < maxDepth) ? Move::maxPushType() : Move::maxOutType(); generateMoves(list); #ifdef MYTRACE printf(">>>>>>>> Depth %d\n", depth); #endif /* check for a old best move in main combination */ if (inMainCombination) { m = mc[depth]; if (!list.isElement(m, 0)) m.type = Move::none; if (m.type == Move::none) inMainCombination = false; if (m.type > maxType) m.type = Move::none; } if (m.type == Move::none) stop = !list.getNext(m, maxType); /* depth first search */ while(!stop) { #ifdef MYTRACE indent(depth); m.print(); printf("\n"); #endif #ifdef SPION if (bUpdateSpy) emit update(depth, 0, m, false); #endif playMove(m); if (!isValid()) value = ((depth < maxDepth) ? 15999:14999) - depth; else { /* opponent searches for his maximum; but we won't the * minimum: so change sign (for alpha/beta window too!) */ value = - search(depth+1,-beta,-alpha); } takeBack(); /* For GUI response */ if (maxDepth - depth >2) emit searchBreak(); #ifdef MYTRACE indent(depth); printf("=> (%d - %d): Value %d [ %d ] for ", alpha, beta, value,actValue); m.print(); printf("\n"); #endif #ifdef SPION if (bUpdateSpy) { if (value > actValue) emit updateBest(depth, value, m, value >= beta); emit update(depth, value, m, true); } #endif if (value > actValue) { actValue = value; mc.update(depth, m); if (bUpdateSpy && depth == 0) emit updateBestMove(m, actValue); if (actValue >= beta) { #ifdef MYTRACE indent(depth); printf("CUTOFF\n"); #endif return actValue; } if (actValue > alpha) alpha = actValue; } stop = (!list.getNext(m, maxType)) || breakOut; } /* other moves: calculate rating */ while(list.getNext(m, Move::none)) { playMove(m); if (!isValid()) value = ((depth < maxDepth) ? 15999:14999) - depth; else value = calcValue(); takeBack(); #ifdef SPION if (bUpdateSpy) { if (value > actValue) emit updateBest(depth, value, m, value >= beta); emit update(depth, value, m, true); } #endif #ifdef MYTRACE indent(depth); printf("> (%d - %d): Value %d [ %d ] for ", alpha, beta, value, actValue); m.print(); printf("\n"); #endif if (value > actValue) { actValue = value; mc.update(depth, m); if (actValue >= beta) { #ifdef MYTRACE indent(depth); printf("CUTOFF\n"); #endif break; } if (actValue > alpha) alpha = actValue; } } return actValue; }
void makeMove(player you, rackRef yourRack, Trie dictionary) { strncpy(myRack, yourRack, RACK_SIZE+1); me = you; bestScore = INITIAL; dict = dictionary; word emptyWord = {INVALID_LETTER}; word startingPartialWord = {INVALID_LETTER}; int i, j; direction d; for(d=HORIZONTAL;d<=VERTICAL;d++) { D("DIRECTION: %d\n",d); findAnchors(d); for(i=0;i<BOARD_SIZE;i++) { for(j=0;j<BOARD_SIZE;j++){ strncpy(startingPartialWord, emptyWord, BOARD_SIZE); if(anchors[i][j]) { // if(getCell(i,j) != INVALID_LETTER) { D("finding word from (%d,%d)\n",i,j); int limit = findLimit(i, j, d); if(limit > 0) { leftPart(startingPartialWord, dict, findLimit(i, j, d), d, i, j); } else { int spwLength = 0; // we already have a left part int row = i; int col = j; int rowChange = 0; int colChange = 0; if(d == HORIZONTAL) { colChange = -1; } else if(d == VERTICAL) { rowChange = -1; } row += rowChange; col += colChange; while(row >= 0 && col >= 0 && row < BOARD_SIZE && col < BOARD_SIZE) { startingPartialWord[spwLength] = getCell(row, col); spwLength++; row += rowChange; col += colChange; } // reverse the part int k; for(k=0;k<spwLength;k++) { letter temp = startingPartialWord[k]; startingPartialWord[k] = startingPartialWord [spwLength-k-1]; startingPartialWord[spwLength-k-1] = temp; } // extend to the right extendRight(startingPartialWord, dict, d, i, j, FALSE); } } } } } if(bestScore == INITIAL) { D("DECIDED TO PASS\n"); playMove(me, PASS, PASS, NULL, HORIZONTAL); } else { playMove(me, bestRow, bestCol, bestWord, bestDir); } }