//Return true is already exist // false if non-exist public override bool addToMap(Playfield state) { float key = getHashkey(state); //Helpfunctions.Instance.logg("end key = " + key); if (TTable.ContainsKey(key)) { foreach (Playfield existState in TTable[key]) { if (existState.isHandEqual(state, true)) { return(true); } } if (TTable[key][0].getBoardValue(true) < state.getBoardValue(true)) { //Helpfunctions.Instance.logg("orig board " + TTable[key][0].getBoardValue()); //TTable[key][0].debugMinions(); //Helpfunctions.Instance.logg("new board " + state.getBoardValue()); //state.debugMinions(); TTable[key][0] = state; } return(false); } else { TTable.Add(key, new List <Playfield>()); TTable[key].Add(state); } return(false); }
//Return true is already exist // false if non-exist public override bool addToMap(Playfield state) { float key = getHashkey(state); //Helpfunctions.Instance.logg("key:" + key); //if ("" + key == "4140817") //{ // int debug = 1; // state.debugMinions(); //} //if (state.playerFirst.ownMaxMana == 3) //{ // int debug = 1; //} if (TTable.ContainsKey(key)) { foreach (Playfield existState in TTable[key]) { if (existState.isEqual(state, true)) { return(true); } } TTable[key].Add(state); return(false); //state.printBoard(); } else { TTable.Add(key, new List <Playfield>()); TTable[key].Add(state); } return(false); }
public int PrincipalVariationSearch(int alpha, int beta, Board board, int depth, int currentDepth, bool allowNullMoveSearch) { #if TEST Test.Assert(beta > alpha); Test.Assert(depth >= 0); board.CheckBoard(); #endif if ((NodesSearched & 2047) == 0) { if (Interruptor.IsInterrupted()) { Stopped = true; return(0); } } NodesSearched++; var isRepetition = IsRepetition(board); if (isRepetition && currentDepth > 0) { return(0); } if (board.History.Length - board.LastTookPieceHistoryIndex >= 100) { return(0); } if (currentDepth >= MaxDepth) { return(EvaluationService.Evaluate(board)); } if (depth <= 0) { // quiessence next return(Quiessence(alpha, beta, board, currentDepth)); } var enemyAttacks = PossibleMovesService.AttacksService.GetAllAttacked(board, !board.WhiteToMove); var myKing = board.WhiteToMove ? board.BitBoard[ChessPiece.WhiteKing] : board.BitBoard[ChessPiece.BlackKing]; var inCheck = (enemyAttacks & myKing) != 0; if (inCheck) { depth++; } int score = -Inf; Move?pvMove = null; SearchTTEntry foundEntry; var found = TTable.TryGet(board.Key, out foundEntry); if (found && foundEntry.Key == board.Key) { pvMove = foundEntry.Move; if (foundEntry.Depth >= depth) { switch (foundEntry.Flag) { case SearchTTFlags.Beta: return(beta); break; case SearchTTFlags.Exact: return(foundEntry.Score); break; case SearchTTFlags.Alpha: return(alpha); break; } } } const int nullMoveFactor = 2; if (allowNullMoveSearch && !inCheck && currentDepth > 0 && depth >= nullMoveFactor + 1) { var haveBigPiece = false; var pieceOffset = board.WhiteToMove ? 1 : 7; for (var i = 1; i < 5; i++) { if (board.PieceCounts[pieceOffset + i] > 0) { haveBigPiece = true; break; } } if (haveBigPiece) { var nullMove = new Move(0, 0, 0); var nullBoard = board.DoMove(nullMove); score = -PrincipalVariationSearch(-beta, -beta + 1, nullBoard, depth - nullMoveFactor - 1, currentDepth + 1, false); if (Stopped) { return(0); } if (score >= beta && score > -MateThereshold && score < MateThereshold) { NullMoveCutOffs++; return(beta); } } } var potentialMoves = PossibleMovesService.GetAllPotentialMoves(board); var oldAlpha = alpha; var validMoves = 0; Move?bestMove = null; var bestScore = -Inf; score = -Inf; var bbsAfter = new Board[potentialMoves.Count]; for (var i = 0; i < potentialMoves.Count; i++) { SortNextMove(i, board, potentialMoves, currentDepth, pvMove); var potentialMove = potentialMoves[i]; var bbAfter = PossibleMovesService.DoMoveIfKingSafe(board, potentialMove); if (bbAfter == null) { continue; } bbsAfter[i] = bbAfter; validMoves++; score = -PrincipalVariationSearch(-beta, -alpha, bbAfter, depth - 1, currentDepth + 1, true); if (Stopped) { return(0); } if (score > bestScore) { bestScore = score; bestMove = potentialMove; if (score > alpha) { if (score >= beta) { #if TEST if (validMoves == 1) { FailHighFirst++; } FailHigh++; #endif if (potentialMove.TakesPiece == 0) { SearchKillers[currentDepth, 1] = SearchKillers[currentDepth, 0]; SearchKillers[currentDepth, 0] = potentialMove.Key; } var entry = new SearchTTEntry(board.Key, bestMove.Value, beta, SearchTTFlags.Beta, depth); TTable.Add(board.Key, entry); return(beta); } alpha = score; if (potentialMove.TakesPiece == 0) { SearchHistory[potentialMove.Piece, potentialMove.To] += depth; } } } } if (validMoves == 0) { if (inCheck) { return(-MateScore + currentDepth); } else { return(0); } } #if TEST Test.Assert(alpha >= oldAlpha); #endif if (alpha != oldAlpha) { var entry = new SearchTTEntry(board.Key, bestMove.Value, bestScore, SearchTTFlags.Exact, depth); TTable.Add(board.Key, entry); //PVTable[currentDepth] = new PVSResult(alpha, bbsAfter[bestMove], potentialMoves[bestMove]); } else { var entry = new SearchTTEntry(board.Key, bestMove.Value, alpha, SearchTTFlags.Alpha, depth); TTable.Add(board.Key, entry); } return(alpha); }