void Board8x8::generateBishopMoves(uint row, uint col, MoveList & moveList) { uint index = getIndex(row, col); generateMoves(mBishopMovesNorthEast[index], row, col, moveList, true); generateMoves(mBishopMovesSouthWest[index], row, col, moveList, true); generateMoves(mBishopMovesNorthWest[index], row, col, moveList, true); generateMoves(mBishopMovesSouthEast[index], row, col, moveList, true); }
void Board8x8::generateRookMoves(uint row, uint col, MoveList & moveList) { uint index = getIndex(row, col); generateMoves(mRookMovesNorth[index], row, col, moveList, true); generateMoves(mRookMovesSouth[index], row, col, moveList, true); generateMoves(mRookMovesEast[index], row, col, moveList, true); generateMoves(mRookMovesWest[index], row, col, moveList, true); }
list<Movement> Knight::generateMoves(GameStatus& currentStatus){ list<Movement> moves; //top top left moves.splice(moves.end(), generateMoves(currentStatus, -1, -2)); //bottom top left moves.splice(moves.end(), generateMoves(currentStatus, -2, -1)); //top top right moves.splice(moves.end(), generateMoves(currentStatus, 1, -2)); //bottom top right moves.splice(moves.end(), generateMoves(currentStatus, 2, -1)); //top bottom right moves.splice(moves.end(), generateMoves(currentStatus, 2, -1)); //bottom bottom right moves.splice(moves.end(), generateMoves(currentStatus, 1, 2)); //top bottom left moves.splice(moves.end(), generateMoves(currentStatus, -1, 2)); //bottom bottom left moves.splice(moves.end(), generateMoves(currentStatus, -2, 1)); return moves; }
bool ChessBoard::isLegalMove(int mv) { int sqSrc, sqDst, pcSrc, pcDst; sqSrc = SRC(mv); sqDst = DST(mv); if (sqSrc==sqDst) { return false; } pcSrc = m_data[sqSrc]; pcDst = m_data[sqDst]; if (side(pcSrc)==side(pcDst)) { return false; } Moves mvs; generateMoves(sqSrc, mvs); for(int i=0; i<mvs.count(); i++) { if (mvs[i]==mv) { return true; } } return false; }
bool LosersBoard::vIsLegalMove(const Move& move) { bool isCapture = (captureType(move) != Piece::NoPiece); if (m_captureKey != key() && !isCapture) { m_captureKey = key(); m_canCapture = false; QVarLengthArray<Move> moves; generateMoves(moves); for (int i = 0; i < moves.size(); i++) { if (captureType(moves[i]) != Piece::NoPiece && WesternBoard::vIsLegalMove(moves[i])) { m_canCapture = true; break; } } } if (!isCapture && m_canCapture) return false; return WesternBoard::vIsLegalMove(move); }
int ChessBoard::test1_max(int depth, int& mv) { if (depth==0) { mv = 0; return m_vlBlack - m_vlRed; } Moves mvs; //int selfSide = m_sdPlayer; int best = -999999; generateMoves(mvs); for(int i=0; i<mvs.count(); i++) { int oldVal = m_vlBlack - m_vlRed; int pcCapture; if (makeMove(mvs[i], pcCapture)) { int temp_mv; int val = test1_min(depth-1, temp_mv); if (val>best) { best = val; mv = mvs[i]; } undoMakeMove(mvs[i], pcCapture); } int newVal = m_vlBlack - m_vlRed; Q_ASSERT(oldVal==newVal); } return best; }
/** * KI macht einen zufaelligen Zug. * Gibt 1 zurueck, wenn ein Zug ausgefuehrt wurde, sonst 0. */ char aiSimpleMove(struct GameState *gs) { char moves[28 * 16 * 2]; // keine Initialiserung! short movesCounter; generateMoves(gs, moves, &movesCounter); short found = 0; short move; for (move = 0; move < movesCounter; move += 2) { short pieceFrom = (*gs).board[moves[move]]; short pieceTo = (*gs).board[moves[move + 1]]; doMovePartial(gs, moves[move], moves[move + 1]); short check = isCheck(gs); (*gs).board[moves[move]] = pieceFrom; (*gs).board[moves[move + 1]] = pieceTo; if (check) { // Schach? moves[move] = 0; } else { found++; } } if (found == 0) { if (isCheck(gs)) { printInfo("KI ist Schachmatt!\n"); } else { printInfo("KI ist Patt gesetzt!\n"); } return 0; } short r = rand() % found; found = 0; for (move = 0; move < movesCounter; move += 2) { if (moves[move] != 0) { if (found == r) { break; } found++; } } char c1[] = "??"; char c2[] = "??"; convertIndexToCoord(moves[move], c1); convertIndexToCoord(moves[move + 1], c2); if ((*gs).board[moves[move + 1]] == 0) { printInfo("KI zieht mit %c von %s nach %s.\n", getPieceSymbolAsChar((*gs).board[moves[move]]), c1, c2); } else { printInfo("KI zieht mit %c von %s nach %s und schlaegt %c.\n", getPieceSymbolAsChar((*gs).board[moves[move]]), c1, c2, getPieceSymbolAsChar((*gs).board[moves[move + 1]])); } doMovePartial(gs, moves[move], moves[move + 1]); doMoveFinal(gs, moves[move], moves[move + 1]); return 1; }
uchar Board0x88::generateOpponentMoves(MoveList & moveList) { uchar sideToMove = mSideToMove; mSideToMove = !mSideToMove; generateMoves(moveList); mSideToMove = sideToMove; return moveList.size(); }
void ChessBoard::generateMoves(Moves& mvs) { for(int sq=0; sq<256; sq++) { int pc = m_data[sq]; if (!pc) continue; if (side(pc) == m_sdPlayer) { generateMoves(sq, mvs); } } }
long long moveTest(Board_t self, int depth) { if (depth <= 0) return 1; long long total = 0; int moveList[maxMoves]; int nrMoves = generateMoves(self, moveList); for (int i=0; i<nrMoves; i++) { makeMove(self, moveList[i]); if (wasLegalMove(self)) total += moveTest(self, depth - 1); undoMove(self); } return total; }
// This function should not be called by engines, it would be greatly inefficient // It exists simply to find the legal moves for a particular // square, such as is needed when running in a GUI uchar Board0x88::generateMoves(uchar row, uchar col, MoveList & moveList) { MoveList allMoves; uchar totalMoves = generateMoves(allMoves); for (uchar i = 0; i < totalMoves; i++) { if (allMoves[i].sourceRow == row && allMoves[i].sourceCol == col) { makeMove(allMoves[i]); if (!isCellAttacked(mKingIndex[!mSideToMove], mSideToMove) ) moveList.addMove(allMoves[i]); unmakeMove(allMoves[i]); } } return moveList.size(); }
Move Board::randomMove() { Move m; MoveList list; generateMoves(list); int l = list.getLength(); int j = (::rand() % l) +1; while(j != 0) { list.getNext(m, Move::none); j--; } return m; }
void Board8x8::generateKingMoves(uint row, uint col, MoveList & moveList) { uint index = getIndex(row, col); generateMoves(mKingMoves[index], row, col, moveList, false); bool queenSide = (mWhiteToMove) ? mWhiteCastleQueenSide : mBlackCastleQueenSide; bool kingSide = (mWhiteToMove) ? mWhiteCastleKingSide : mBlackCastleKingSide; uint rowCheck = (mWhiteToMove) ? WHITE_KING_START_ROW : BLACK_KING_START_ROW; if (kingSide && getPieceType(rowCheck, 5) == NoPiece && getPieceType(rowCheck, 6) == NoPiece) { bool canCastle = true; uint attackCol = 4; while (attackCol <= 6) { if (isCellAttacked(rowCheck, attackCol, mWhiteToMove)) { canCastle = false; break; } attackCol++; } if (canCastle) { Move newMove(rowCheck, 4, rowCheck, 6); newMove.setKingCastle(); moveList.addMove(newMove); } } if (queenSide && getPieceType(rowCheck,3) == NoPiece && getPieceType(rowCheck,2) == NoPiece && getPieceType(rowCheck,1) == NoPiece) { bool canCastle = true; uint attackCol = 4; while (attackCol >= 2) { if (isCellAttacked(rowCheck, attackCol, mWhiteToMove)) { canCastle = false; break; } attackCol--; } if (canCastle) { Move newMove(rowCheck, 4, rowCheck, 2); newMove.setQueenCastle(); moveList.addMove(newMove); } } }
Move Board::randomMove() { Move m; MoveList list; generateMoves(list); int l = list.getLength(); // FIXME: start with random seed using qsrand() somewhere int j = (qrand() % l) +1; while(j != 0) { list.getNext(m, Move::none); j--; } return m; }
bool CheckersBoard::makeMove(const std::array<std::array<uint8_t, 8>, 8> &i_board, const bool color) { //Bool to determine if move is valid bool validMove = false; //Generate moves generateMoves(color); for(Move &possible_move: move_List) { if(i_board == possible_move.move_board) { validMove = true; board = i_board; } } return validMove; }
double AI::evaluateState(fizGTableState state, turn_T turn){ set<shot> moves; generateMoves(state, moves, turn); double w[] = {1.0, .33, .15}; double sum = 0; set<shot>::iterator iter = moves.begin(); if(moves.empty()) return 1; for(int i = 0; iter != moves.end(); i++, iter++){ sum += iter->probability * w[i]; } return sum; }
int _search(searchNode* thisNode, const int maxDepth, int depth, int parentHeuristic) { thisNode->setNodeCount(nodeCounter++); if (thisNode->anyKingsMissing()) { return simpleHeuristic(thisNode->getBoard()); } int currentPlayer = (depth % 2); if (depth == maxDepth) { return simpleHeuristic(thisNode->getBoard()); } Board currentBoard = thisNode->getBoard(); std::vector<Board> possibles = generateMoves(currentBoard.getPieces(currentPlayer), currentBoard); if (possibles.size() == 0) { return simpleHeuristic(thisNode->getBoard()); } int bestHeuristic = UNSET; for (int p = 0; p < possibles.size(); ++p) { //std::cout << "depth " << depth << " trying possibles[" << p << "] whose move is " << possibles[p].getMoveName() << "\n"; searchNode* newNode = new searchNode(possibles[p]); thisNode->addChild(newNode); //std::cout << "newNode should match possibles[p] move name: " << newNode->getMoveName() << "\n"; int childHeuristic = _search(newNode,maxDepth,depth+1,bestHeuristic); newNode->setHeuristic(childHeuristic); updateBestHeuristic(currentPlayer, bestHeuristic, childHeuristic); if (parentHeuristic != UNSET) { if ( (currentPlayer == 1 && bestHeuristic < parentHeuristic) || (currentPlayer == 0 && bestHeuristic > parentHeuristic) ) { thisNode->setCutoff(true); break; } } } thisNode->setHeuristic(bestHeuristic); return bestHeuristic; }
bool ChessBoard::IsMate() { //qDebug()<<"check isMate side="<<m_sdPlayer; //int selfSide = m_sdPlayer; Moves mvs; generateMoves(mvs); for(int i=0; i<mvs.count(); i++) { //qDebug()<<"尝试解招:"<< mvString(mvs[i]); int pcCaptured = _movePiece(mvs[i]); if (!isChecked()) { _undoMovePiece(mvs[i], pcCaptured); //qDebug()<<"!!!解招:"<< mvString(mvs[i]); return false; } else{ _undoMovePiece(mvs[i], pcCaptured); } } return true; }
int ChessBoard::negaMax(int depth, int& mv) { if (depth==0) { return m_sdPlayer?m_vlBlack - m_vlRed:m_vlRed - m_vlBlack; } m_searchCallTimes++; int best = INT_MIN; Moves mvs; generateMoves(mvs); for(int i=0; i<mvs.count(); i++) { int oldVal = m_vlBlack - m_vlRed; int pcCapture; //qDebug()<<mvString(mvs[i]); if (makeMove(mvs[i], pcCapture)) { int temp_mv; int val = -1 * negaMax(depth-1, temp_mv); if (temp_mv) { //qDebug()<<mvString(temp_mv)<<" 评分"<<val; } if (val>best) { best = val; mv = mvs[i]; } undoMakeMove(mvs[i], pcCapture); //qDebug()<<"UndoMakeMove"; } int newVal = m_vlBlack - m_vlRed; Q_ASSERT(oldVal==newVal); } return best; }
int Search::printDtm() { int side = getSide(); u64 friends = side == WHITE ? getBitmap<WHITE>() : getBitmap<BLACK>(); u64 enemies = side == BLACK ? getBitmap<WHITE>() : getBitmap<BLACK>(); display(); int res = side ? getGtb().getDtm<WHITE, true>(chessboard, chessboard[RIGHT_CASTLE_IDX], 100) : getGtb().getDtm<BLACK, true>(chessboard, chessboard[RIGHT_CASTLE_IDX], 100); cout << " res: " << res; incListId(); generateCaptures(side, enemies, friends); generateMoves(side, friends | enemies); _Tmove *move; u64 oldKey = 0; cout << "\n succ. \n"; int best = -_INFINITE; for (int i = 0; i < getListSize(); i++) { move = &gen_list[listId].moveList[i]; makemove(move, false, false); cout << "\n" << decodeBoardinv(move->type, move->from, getSide()) << decodeBoardinv(move->type, move->to, getSide()) << " "; res = side ? -getGtb().getDtm<BLACK, true>(chessboard, chessboard[RIGHT_CASTLE_IDX], 100) : getGtb().getDtm<WHITE, true>(chessboard, chessboard[RIGHT_CASTLE_IDX], 100); if (res != -INT_MAX) { cout << " res: " << res; } cout << "\n"; takeback(move, oldKey, false); if (res > best) { best = res; } } if (best > 0) { best = _INFINITE - best; } else if (best < 0) { best = -(_INFINITE - best); } cout << endl; decListId(); return best; }
Move Board::randomMove() { static int i = 999; unsigned int j,l; Move m; MoveList list; /* we prefer to use QT... */ j = (QTime::currentTime()).msec(); generateMoves(list); l = list.getLength(); j = (j + i) % l +1; if ( (i+=7)>10000) i-=10000; while(j != 0) { list.getNext(m, Move::none); j--; } return m; }
void testGenerateMoves() { int _b[2][25] = { {1, 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0}, {0, 2, 2, 3, 0, 3, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} //PC }; ConstTanBoard b=ms.anBoard; printf("\n\nTEST GENERATE MOVES...\n"); printBoard((ConstTanBoard)b); int dices[2] = {4, 6}; printDices(dices); int** moves; int nMoves; moves = generateMoves((ConstTanBoard)b, dices[0], dices[1], &nMoves); int i=0; for (i=0;i<nMoves;i++) { printMove(moves[i]); } printf("MOVES: %d\n", nMoves); printf("AIlevel: %d\n\n", currentAILevel); }
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; }
void t_chessCli::run() { for (;;) { t_message message; { boost::unique_lock<boost::mutex> lock(sharedData.gameMutex); if (sharedData.gameBuffer.empty()) { sharedData.gameCondition.wait(lock); } message = sharedData.gameBuffer.back(); sharedData.gameBuffer.pop_back(); } std::cout<<"I have recieved a message"<<std::endl; switch (message.id) { case BOARD_CLICKED: { t_myVector2 pos = message.boardClicked.pos; std::cout<<"It was clicked at "<<pos<<std::endl; t_message newMessage; newMessage.id = HIGHLIGHT_SPACE; if (selected) { if (pos == selectedPos) { selected = 0; newMessage.highlightSpace.pos = selectedPos; newMessage.highlightSpace.color = 0; { boost::unique_lock<boost::mutex> lock(sharedData.clientMutex); sharedData.clientBuffer.push_front(newMessage); for (auto iter = move.begin(); iter != move.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 0; sharedData.clientBuffer.push_front(newMessage); } for (auto iter = hit.begin(); iter != hit.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 0; sharedData.clientBuffer.push_front(newMessage); } for (auto iter = castle.begin(); iter != castle.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 0; sharedData.clientBuffer.push_front(newMessage); } } move.clear(); hit.clear(); castle.clear(); } else if (std::find(move.begin(), move.end(), pos) != move.end()) { if (checkCheck(pos,selectedPos)) { std::cout<<"I am in check"<<std::endl; break; } if (turn == 0) { whitePieces.erase(selectedPos); whitePieces.insert(pos); } else { blackPieces.erase(selectedPos); blackPieces.insert(pos); } removeCastle(pos,selectedPos); selected = 0; newMessage.highlightSpace.pos = selectedPos; newMessage.highlightSpace.color = 0; { boost::unique_lock<boost::mutex> lock(sharedData.clientMutex); sharedData.clientBuffer.push_front(newMessage); for (auto iter = move.begin(); iter != move.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 0; sharedData.clientBuffer.push_front(newMessage); } for (auto iter = hit.begin(); iter != hit.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 0; sharedData.clientBuffer.push_front(newMessage); } for (auto iter = castle.begin(); iter != castle.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 0; sharedData.clientBuffer.push_front(newMessage); } newMessage.id = MOVE_PIECE; newMessage.movePiece.pos = pos; newMessage.movePiece.oldPos = selectedPos; sharedData.clientBuffer.push_front(newMessage); } move.clear(); hit.clear(); castle.clear(); board[pos.y][pos.x] = board[selectedPos.y][selectedPos.x]; board[selectedPos.y][selectedPos.x] = 0; turn = !turn; if (checkCheckmate()) { std::cout<<"I win"<<std::endl; } } else if (std::find(hit.begin(), hit.end(), pos) != hit.end()) { if (checkCheck(pos,selectedPos)) { std::cout<<"I am in check"<<std::endl; break; } if (turn == 0) { whitePieces.erase(selectedPos); whitePieces.insert(pos); blackPieces.erase(pos); } else { blackPieces.erase(selectedPos); blackPieces.insert(pos); whitePieces.erase(pos); } removeCastle(pos,selectedPos); selected = 0; newMessage.highlightSpace.pos = selectedPos; newMessage.highlightSpace.color = 0; { boost::unique_lock<boost::mutex> lock(sharedData.clientMutex); sharedData.clientBuffer.push_front(newMessage); for (auto iter = move.begin(); iter != move.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 0; sharedData.clientBuffer.push_front(newMessage); } for (auto iter = hit.begin(); iter != hit.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 0; sharedData.clientBuffer.push_front(newMessage); } for (auto iter = castle.begin(); iter != castle.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 0; sharedData.clientBuffer.push_front(newMessage); } newMessage.id = CAPTURE_PIECE; newMessage.movePiece.pos = pos; newMessage.movePiece.oldPos = selectedPos; sharedData.clientBuffer.push_front(newMessage); } move.clear(); hit.clear(); castle.clear(); board[pos.y][pos.x] = board[selectedPos.y][selectedPos.x]; board[selectedPos.y][selectedPos.x] = 0; turn = !turn; if (checkCheckmate()) { std::cout<<"I win"<<std::endl; } } else if (std::find(castle.begin(), castle.end(), pos) != castle.end()) { if (checkCheck(pos,selectedPos)) { std::cout<<"I am in check"<<std::endl; break; } if (turn == 0) { whitePieces.erase(selectedPos); whitePieces.insert(pos); } else { blackPieces.erase(selectedPos); blackPieces.insert(pos); } removeCastle(pos,selectedPos); selected = 0; newMessage.highlightSpace.pos = selectedPos; newMessage.highlightSpace.color = 0; { boost::unique_lock<boost::mutex> lock(sharedData.clientMutex); sharedData.clientBuffer.push_front(newMessage); for (auto iter = move.begin(); iter != move.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 0; sharedData.clientBuffer.push_front(newMessage); } for (auto iter = hit.begin(); iter != hit.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 0; sharedData.clientBuffer.push_front(newMessage); } for (auto iter = castle.begin(); iter != castle.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 0; sharedData.clientBuffer.push_front(newMessage); } newMessage.id = MOVE_PIECE; newMessage.movePiece.pos = pos; newMessage.movePiece.oldPos = selectedPos; sharedData.clientBuffer.push_front(newMessage); if (pos.x == 2) //left castle { newMessage.movePiece.pos.x = 3; newMessage.movePiece.oldPos.x = 0; } else { newMessage.movePiece.pos.x = 5; newMessage.movePiece.oldPos.x = 7; } sharedData.clientBuffer.push_front(newMessage); } move.clear(); hit.clear(); castle.clear(); board[pos.y][pos.x] = board[selectedPos.y][selectedPos.x]; board[selectedPos.y][selectedPos.x] = 0; if (pos.x == 2) //left { pos.x = 3; selectedPos.x = 0; board[pos.y][3] = board[selectedPos.y][0]; board[selectedPos.y][0] = 0; } else { pos.x = 5; selectedPos.x = 7; board[pos.y][5] = board[selectedPos.y][7]; board[selectedPos.y][7] = 0; } if (turn == 0) { whitePieces.erase(selectedPos); whitePieces.insert(pos); } else { blackPieces.erase(selectedPos); blackPieces.insert(pos); } turn = !turn; if (checkCheckmate()) { std::cout<<"I win"<<std::endl; } } } else if (board[pos.y][pos.x] && board[pos.y][pos.x]/8 == turn) { selected = 1; selectedPos = pos; newMessage.highlightSpace.pos = pos; newMessage.highlightSpace.color = 1; generateMoves(pos); { boost::unique_lock<boost::mutex> lock(sharedData.clientMutex); sharedData.clientBuffer.push_front(newMessage); for (auto iter = move.begin(); iter != move.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 2; sharedData.clientBuffer.push_front(newMessage); } for (auto iter = hit.begin(); iter != hit.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 3; sharedData.clientBuffer.push_front(newMessage); } for (auto iter = castle.begin(); iter != castle.end(); iter++) { newMessage.highlightSpace.pos = *iter; newMessage.highlightSpace.color = 4; sharedData.clientBuffer.push_front(newMessage); } } } break; } case QUIT_MESSAGE: std::cout<<"It told me to quit"<<std::endl; return; default: std::cout<<"And I do not know what it was"<<std::endl; } } }
void findPerftBug(const std::string& validatorPath, const ChessPosition* pP, int depth) { // allocate fen buffer; char fenBuffer[1024]; std::string fenString; // generate Move List ChessMove MoveList[MOVELIST_SIZE]; generateMoves(*pP, MoveList); PerftInfo T; if (depth <= 1) { // terminal node // generate FEN string memset(fenBuffer, 0, 1024); writeFen(fenBuffer, pP); fenString.assign(fenBuffer); std::cout << "Reached Single Position!\n"; dumpChessPosition(*pP); dumpMoveList(MoveList); T.nMoves = T.nCapture = T.nEPCapture = T.nCastle = T.nCastleLong = T.nPromotion = 0LL; perftMT(*pP, 1, 1, &T); int nResult = perftValidateWithExternal(validatorPath, fenString, 1, T.nMoves); if (nResult == PERFTVALIDATE_FALSE) { std::cout << "Engines disagree on Number of moves from this position" << std::endl; } else { std::cout << "ok" << std::endl; } std::cout << "Hit enter to continue" << std::endl; getchar(); return; } ChessMove* pM = MoveList; ChessPosition Q; while (pM->NoMoreMoves == 0) { // Set up position Q = *pP; Q.performMove(*pM); Q.switchSides(); // generate FEN string memset(fenBuffer, 0, 1024); writeFen(fenBuffer, &Q); fenString.assign(fenBuffer); std::cout << "After Move: "; if (pP->BlackToMove) std::cout << "... "; dumpMove(*pM); std::cout << "Position: " << fenString << std::endl; T.nMoves = T.nCapture = T.nEPCapture = T.nCastle = T.nCastleLong = T.nPromotion = 0LL; perftMT(Q, depth - 1, 1, &T); std::cout << "\nValidating depth: " << depth - 1 << " perft: " << T.nMoves << std::endl; int nResult = perftValidateWithExternal(validatorPath, fenString, depth - 1, T.nMoves); if (nResult == PERFTVALIDATE_FALSE) { // Investigate further ... std::cout << "WRONG !! Taking a closer look ..." << std::endl; findPerftBug(validatorPath, &Q, depth - 1); } else { std::cout << "ok"; } std::cout << "\n" << std::endl; pM++; } std::cout << "findPerftBug() finished\n\n"; }
/* * 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; }
void Board8x8::generateKnightMoves(uint row, uint col, MoveList & moveList) { uint index = getIndex(row, col); generateMoves(mKnightMoves[index], row, col, moveList, false); }
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; }
int ChessBoard::alphaBetaSearch(int depth, int alpha, int beta) { //1.到达水平线返回 if (depth==0) { return evaluate(); } m_searchCallTimes++; //2.初使化最佳值,最佳走法 int vlBest = -MATE_VALUE; int mvBest = 0; //3.生成走法,根据历史表排序 Moves mvs; generateMoves(mvs); //PrintMoves(mvs); qSort(mvs.begin(), mvs.end(), compareLessTan); //PrintMoves(mvs); //qDebug()<<"----------------------"; // 4. 逐一走这些走法,并进行递归 for(int i=0; i<mvs.count(); i++) { //列出走法 int pcCaptured; if (makeMove(mvs[i], pcCaptured)) { int vl = -alphaBetaSearch(depth - 1, -beta, -alpha); undoMakeMove(mvs[i], pcCaptured); //qDebug()<<mvString(mvs[i])<<" vl="<<vl; //进行Alpha-Beta大小判断和截断 if (vl > vlBest) { // 找到最佳值(但不能确定是Alpha、PV还是Beta走法) vlBest = vl; // "vlBest"就是目前要返回的最佳值,可能超出Alpha-Beta边界 if (vl >= beta) { // 找到一个Beta走法 mvBest = mvs[i]; // Beta走法要保存到历史表 break; // Beta截断 } if (vl > alpha) { // 找到一个PV走法 mvBest = mvs[i]; // PV走法要保存到历史表 alpha = vl; // 缩小Alpha-Beta边界 } } } } // 5. 所有走法都搜索完了,把最佳走法(不能是Alpha走法)保存到历史表,返回最佳值 if (vlBest == -MATE_VALUE) { // 如果是杀棋,就根据杀棋步数给出评价 return m_distance - MATE_VALUE; } //qDebug()<<"mvBest="<<mvBest<<" distance="<<m_distance; if (mvBest != 0) { // 如果不是Alpha走法,就将最佳走法保存到历史表 m_historyTable[mvBest] += depth * depth; if (m_distance==0) { // 搜索根节点时,总是有一个最佳走法(因为全窗口搜索不会超出边界),将这个走法保存下来 m_mvComputer = mvBest; } } return vlBest; }