public List <string> getPosHistory() { List <string> ret = new List <string>(); Position pos2 = new Position(pos /*this.pos*/); for (int i = currentMove; i > 0; i--) { pos2.unMakeMove(moveList[i - 1], uiInfoList[i - 1]); } ret.Add(TextIO.toFEN(pos2)); // Store initial FEN string moves = ""; for (int i = 0; i < moveList.Count; i++) { Move move = moveList[i]; string strMove = TextIO.moveTostring(pos2, move, false); moves += " " + strMove; UndoInfo ui = new UndoInfo(); pos2.makeMove(move, ui); } ret.Add(moves); // Store move list string int numUndo = moveList.Count - currentMove; ret.Add(((int)numUndo).ToString()); return(ret); }
/** Search a position and return the best move and score. Used for test suite processing. */ public TwoReturnValues <Move, string> searchPosition(Position pos, int maxTimeMillis) { // Create a search object ulong[] posHashList = new ulong[200]; tt.nextGeneration(); Search sc = new Search(pos, posHashList, 0, tt); // Determine all legal moves MoveGen.MoveList moves = new MoveGen().pseudoLegalMoves(pos); MoveGen.RemoveIllegal(pos, moves); sc.scoreMoveList(moves, 0); // Find best move using iterative deepening sc.timeLimit(maxTimeMillis, maxTimeMillis); Move bestM = sc.iterativeDeepening(moves, -1, -1, false); // Extract PV string PV = TextIO.moveTostring(pos, bestM, false) + " "; UndoInfo ui = new UndoInfo(); pos.makeMove(bestM, ui); PV += tt.extractPV(pos); pos.unMakeMove(bestM, ui); // tt.printStats(); // Return best move and PV return(new TwoReturnValues <Move, string>(bestM, PV)); }
/** Check if a draw claim is allowed, possibly after playing "move". * @param move The move that may have to be made before claiming draw. * @return The draw string that claims the draw, or empty string if draw claim not valid. */ private string canClaimDraw(Position pos, ulong[] posHashList, int posHashListSize, Move move) { string drawStr = ""; if (Search.canClaimDraw50(pos)) { drawStr = "draw 50"; } else if (Search.canClaimDrawRep(pos, posHashList, posHashListSize, posHashListSize)) { drawStr = "draw rep"; } else { string strMove = TextIO.moveTostring(pos, move, false); posHashList[posHashListSize++] = pos.zobristHash(); UndoInfo ui = new UndoInfo(); pos.makeMove(move, ui); if (Search.canClaimDraw50(pos)) { drawStr = "draw 50 " + strMove; } else if (Search.canClaimDrawRep(pos, posHashList, posHashListSize, posHashListSize)) { drawStr = "draw rep " + strMove; } pos.unMakeMove(move, ui); } return(drawStr); }
/** Return a string describing all book moves. */ public string getAllBookMoves(Position pos) { string ret = ""; List <BookEntry> bookMoves = bookMap[pos.zobristHash()]; if (bookMoves != null) { BookEntry be; for (int i = 0; i < bookMoves.Count; i++) { be = bookMoves[i]; string moveStr = TextIO.moveTostring(pos, be.move, false); ret = ret + (moveStr + "(" + be.count.ToString() + ") "); } } return(ret); }
private bool handleDrawCmd(string drawCmd) { if (drawCmd.StartsWith("rep") || drawCmd.StartsWith("50")) { bool rep = drawCmd.StartsWith("rep"); Move m = null; string ms = drawCmd.Substring(drawCmd.IndexOf(" ") + 1); if (ms.Length > 0) { m = TextIO.stringToMove(pos, ms); } bool valid; if (rep) { valid = false; List <Position> oldPositions = new List <Position>(); Position tmpPos; if (m != null) { UndoInfo ui = new UndoInfo(); tmpPos = new Position(pos); tmpPos.makeMove(m, ui); oldPositions.Add(tmpPos); } oldPositions.Add(pos); tmpPos = pos; for (int i = currentMove - 1; i >= 0; i--) { tmpPos = new Position(tmpPos); tmpPos.unMakeMove(moveList[i], uiInfoList[i]); oldPositions.Add(tmpPos); } int repetitions = 0; Position firstPos = oldPositions[0]; for (int i = 0; i < oldPositions.Count; i++) { Position p = oldPositions[i]; if (p.drawRuleEquals(firstPos)) { repetitions++; } } if (repetitions >= 3) { valid = true; } } else { Position tmpPos = new Position(pos); if (m != null) { UndoInfo ui = new UndoInfo(); tmpPos.makeMove(m, ui); } valid = tmpPos.halfMoveClock >= 100; } if (valid) { drawState = rep ? GameState.DRAW_REP : GameState.DRAW_50; drawStateMoveStr = null; if (m != null) { drawStateMoveStr = TextIO.moveTostring(pos, m, false); } } else { pendingDrawOffer = true; if (m != null) { processstring(ms); } } return(true); } else if (drawCmd.StartsWith("offer ")) { pendingDrawOffer = true; string ms = drawCmd.Substring(drawCmd.IndexOf(" ") + 1); if (TextIO.stringToMove(pos, ms) != null) { processstring(ms); } return(true); } else if (drawCmd == "accept") { if (haveDrawOffer()) { drawState = GameState.DRAW_AGREE; } return(true); } else { return(false); } }
public string getMoveListstring(bool compressed) { string ret = ""; // Undo all moves in move history. Position pos2 = new Position(pos /*this.pos*/); for (int i = currentMove; i > 0; i--) { pos2.unMakeMove(moveList[i - 1], uiInfoList[i - 1]); } // Print all moves string whiteMove = ""; string blackMove = ""; for (int i = 0; i < currentMove; i++) { Move move = moveList[i]; string strMove = TextIO.moveTostring(pos2, move, false); if (drawOfferList[i]) { strMove += " (d)"; } if (pos2.whiteMove) { whiteMove = strMove; } else { blackMove = strMove; if (whiteMove.Length == 0) { whiteMove = "..."; } if (compressed) { ret += pos2.fullMoveCounter.ToString() + ". " + whiteMove + " " + blackMove + " "; } else { ret += pos2.fullMoveCounter.ToString() + ". " + whiteMove.PadRight(10) + " " + blackMove.PadRight(10) + " "; } whiteMove = ""; blackMove = ""; } UndoInfo ui = new UndoInfo(); pos2.makeMove(move, ui); } if ((whiteMove.Length > 0) || (blackMove.Length > 0)) { if (whiteMove.Length == 0) { whiteMove = "..."; } if (compressed) { ret += pos2.fullMoveCounter.ToString() + ". " + whiteMove + " " + blackMove + " "; } else { ret += pos2.fullMoveCounter.ToString() + ". " + whiteMove.PadRight(10) + " " + blackMove.PadRight(10) + " "; } } string gameResult = getPGNResultstring(); if (gameResult != "*") { ret += gameResult; } return(ret); }
/// <summary> /// Extract the PV starting from pos, using hash entries, both exact scores and bounds. /// </summary> /// <param name="pos"></param> /// <returns></returns> public string extractPV(Position pos) { pos = new Position(pos); string ret = ""; bool first = true; TTEntry ent = probe(pos.historyHash()); UndoInfo ui = new UndoInfo(); List <ulong> hashHistory = new List <ulong>(); bool repetition = false; while (ent.type != TTEntry.T_EMPTY) { string type = ""; if (ent.type == TTEntry.T_LE) { type = "<"; } else if (ent.type == TTEntry.T_GE) { type = ">"; } Move m = new Move(0, 0, 0); ent.getMove(m); MoveGen MG = new MoveGen(); MoveGen.MoveList moves = MG.pseudoLegalMoves(pos); MoveGen.RemoveIllegal(pos, moves); bool contains = false; for (int mi = 0; mi < moves.size; mi++) { if (moves.m[mi].equals(m)) { contains = true; break; } } if (!contains) { break; } string moveStr = TextIO.moveTostring(pos, m, false); if (repetition) { break; } if (!first) { ret += " "; } ret += type + moveStr; pos.makeMove(m, ui); if (hashHistory.Contains(pos.zobristHash())) { repetition = true; } hashHistory.Add(pos.zobristHash()); ent = probe(pos.historyHash()); first = false; } return(ret); }
public string getCommand(Position pos, bool drawOffer, List <Position> history) { // Create a search object ulong[] posHashList = new ulong[200 + history.Count]; int posHashListSize = 0; for (int i = 0; i < history.Count; i++) { Position p = history[i]; posHashList[posHashListSize++] = p.zobristHash(); } tt.nextGeneration(); Search sc = new Search(pos, posHashList, posHashListSize, tt); // Determine all legal moves MoveGen.MoveList moves = new MoveGen().pseudoLegalMoves(pos); MoveGen.RemoveIllegal(pos, moves); sc.scoreMoveList(moves, 0); // Test for "game over" if (moves.size == 0) { // Switch sides so that the human can decide what to do next. return("swap"); } if (bookEnabled) { Move bookMove = book.getBookMove(pos); if (bookMove != null) { SystemHelper.println("Book moves: " + book.getAllBookMoves(pos)); return(TextIO.moveTostring(pos, bookMove, true)); } } // Find best move using iterative deepening currentSearch = sc; sc.setListener(listener); Move bestM; if ((moves.size == 1) && (canClaimDraw(pos, posHashList, posHashListSize, moves.m[0]) == "")) { bestM = moves.m[0]; bestM.score = 0; } else if (randomMode) { bestM = findSemiRandomMove(sc, moves); } else { sc.timeLimit(minTimeMillis, maxTimeMillis); bestM = sc.iterativeDeepening(moves, maxDepth, maxNodes, verbose); } currentSearch = null; // tt.printStats(); string strMove = TextIO.moveTostring(pos, bestM, true); bestmv = bestM; // Claim draw if appropriate if (bestM.score <= 0) { string drawClaim = canClaimDraw(pos, posHashList, posHashListSize, bestM); if (drawClaim != "") { strMove = drawClaim; } } return(strMove); }