/// <summary> /// Constructs a new MGMoveSequence given a starting position (as a FEN) /// and an optional string containing a sequence of subsequent moves (in coordiante notation). /// </summary> /// <param name="fen"></param> /// <param name="movesStr"></param> /// <returns></returns> public static PositionWithHistory FromFENAndMovesUCI(string fen, string movesStr) { MGPosition mgPos = MGPosition.FromFEN(fen); PositionWithHistory ret = new PositionWithHistory(mgPos); if (movesStr != null && movesStr != "") { string[] parts = movesStr.Split(" "); for (int i = 0; i < parts.Length; i++) { string moveStr = parts[i]; if (moveStr != "") { MGMove mgMove = MGMoveFromString.ParseMove(mgPos, moveStr); ret.Moves.Add(mgMove); mgPos.MakeMove(mgMove); } } } return(ret); }
private static void VerifyBeginningOfHistoryOverlapsWithPriorMoves(PositionWithHistory priorMoves, Span <Position> posSpan, int count) { if (count > 0) { // We expect overlap of one move between the prior moves and priorPositionEnumerator // (but we ignore Move 50 and repetitions) // TODO: consider if we can/should also expect alignment of these as well Debug.Assert(priorMoves.FinalPosition.CalcZobristHash(PositionMiscInfo.HashMove50Mode.Ignore, false) == posSpan[count - 1].CalcZobristHash(PositionMiscInfo.HashMove50Mode.Ignore, false)); } }
/// <summary> /// Returns sequence of positions, with the last move at the last position in the Span. /// /// </summary> /// <param name="posSpan"></param> /// <returns></returns> public static Span <Position> DoGetHistoryPositions(PositionWithHistory priorMoves, Span <Position> posSpan, int numPositionsFilled, int maxPositions, bool setFinalPositionRepetitionCount) { // Try to do fill in of history from moves prior to the root node of the search, if available if (numPositionsFilled < maxPositions && priorMoves != null && priorMoves.Moves.Count > 0) { VerifyBeginningOfHistoryOverlapsWithPriorMoves(priorMoves, posSpan, numPositionsFilled); Position[] priorPositions = priorMoves.GetPositions(); int numTaken = 0; while (numPositionsFilled < maxPositions && numTaken < priorPositions.Length - 1) { posSpan[numPositionsFilled++] = priorPositions[priorPositions.Length - 2 - numTaken]; numTaken++; } } if (numPositionsFilled < maxPositions) { // Do final fill in of implied prior position if the first position was en-passant // and we have room for another position before this one insert the en-passant prior position if (numPositionsFilled == 0) { if (priorMoves.FinalPosition.MiscInfo.EnPassantFileIndex != PositionMiscInfo.EnPassantFileIndexEnum.FileNone) { posSpan[numPositionsFilled++] = priorMoves.FinalPosition.PosWithEnPassantUndone(); } } else { // Check end of already existing positions bool hasEnPassantRights = posSpan[numPositionsFilled - 1].MiscInfo.EnPassantFileIndex != PositionMiscInfo.EnPassantFileIndexEnum.FileNone; if (hasEnPassantRights) { Position priorPos = posSpan[numPositionsFilled - 1]; posSpan[numPositionsFilled++] = priorPos.PosWithEnPassantUndone(); } } } if (numPositionsFilled != posSpan.Length) { posSpan = posSpan.Slice(0, numPositionsFilled); } posSpan.Reverse(); if (setFinalPositionRepetitionCount) { PositionRepetitionCalc.SetFinalPositionRepetitionCount(posSpan); } return(posSpan); }
/// <summary> /// Returns a PositionWithHistory from a specified starting FEN and sequence of move strings in SAN format. /// </summary> /// <param name="fen"></param> /// <param name="sanMoves"></param> /// <returns></returns> public static PositionWithHistory FromFENAndMovesSAN(string fen, params string[] sanMoves) { Position pos = Position.FromFEN(fen); PositionWithHistory ret = new PositionWithHistory(pos); if (sanMoves != null) { foreach (string sanMoveString in sanMoves) { Move move = pos.MoveSAN(sanMoveString); ret.AppendMove(MGMoveConverter.MGMoveFromPosAndMove(pos, move)); pos = pos.AfterMove(move); } } return(ret); }
public PositionWithHistory(PositionWithHistory copy) { InitialPosMG = copy.InitialPosMG; Moves = new List <MGMove>(copy.Moves); }