public void TestEquality( int a1, int b1, MoveFlags f1, int a2, int b2, MoveFlags f2, bool areEqual ) { var left = new Move(a1, b1, f1); var right = new Move(a2, b2, f2); Assert.AreEqual(areEqual, left == right); Assert.AreNotEqual(areEqual, left != right); Assert.AreEqual(areEqual, left.Equals(right)); Assert.AreEqual(areEqual, right == left); Assert.AreNotEqual(areEqual, right != left); Assert.AreEqual(areEqual, right.Equals(left)); }
/// <summary> /// 将棋盤の局面を進めます。 /// </summary> public void DoMove(Move move, MoveFlags flags = MoveFlags.DoMoveDefault) { if (Shogi == null) { return; } using (LazyLock()) { if (!CanMove || !Board.DoMove(move, flags)) { return; } FormsUtil.UIProcess(() => Shogi.SetBoard(Board, move)); } }
/// <summary> /// 駒打ちの動作が行えるか調べ、必要なら実行します。 /// </summary> private bool CheckAndMakeDrop(Move move, MoveFlags flags) { if (GetHand(move.DropPieceType, move.BWType) <= 0) { return(false); } // 駒を打つ場所に駒があれば、当然失敗です。 var piece = this[move.DstSquare]; if (piece != null) { return(false); } // 駒が置けるか確かめます。 if (!CanDrop(move.BWType, move.DstSquare, move.DropPieceType)) { return(false); } // 打ち歩詰のチェックを行います。 if (EnumEx.HasFlag(flags, MoveFlags.CheckPawnDropCheckMate) && move.DropPieceType == PieceType.Hu && IsPawnDropCheckMate(move.BWType, move.DstSquare)) { return(false); } if (!EnumEx.HasFlag(flags, MoveFlags.CheckOnly)) { // 駒を盤面に置き、持ち駒から駒を減らします。 this[move.DstSquare] = new BoardPiece( move.DropPieceType, false, move.BWType); DecHand(move.DropPieceType, move.BWType); MoveDone(move); } return(true); }
/// <summary> /// 指し手が実際に着手可能か確認します。 /// </summary> private bool CanMove(Move move, MoveFlags flags = MoveFlags.DoMoveDefault) { var tmp = Board.Clone(); // 成り・不成りの選択ダイアログを出す前に // 駒の移動ができるか調べておきます。 // 失敗したら移動中だった駒は元の位置に戻されます。 if (!tmp.DoMove(move, flags)) { return(false); } // 通常モードの場合、今指した側の玉が王手されていたら // その手は採用しません。(王手放置禁止) if (EditMode == EditMode.Normal && tmp.IsChecked(tmp.Turn.Flip())) { return(false); } return(true); }
public static Move CreateMove(int targetPosition, int fromPosition, Piece capturedPiece, Piece promotion, MoveFlags moveFlags, Board board) { //return new Move() { // targetPosition = (byte)targetPosition, // fromPosition = (byte)fromPosition, // capturedPiece = (byte)capturedPiece, // moveFlags = (byte)moveFlags, // promotion = (byte)promotion, // previousCastlingBits = (byte)board.CastlingBits, // previousEnpassant = (byte)board.EnPassantTarget, // previousHalfMove = (byte)board.HalfTurnCounter //}; return(new Move( (byte)targetPosition, (byte)fromPosition, (byte)capturedPiece, (byte)promotion, (byte)moveFlags, (byte)board.CastlingBits, (byte)board.EnPassantTarget, (byte)board.HalfTurnCounter )); }
public MoveUShort(Square from, Square to, MoveFlags flags) { _moveData = (ushort)(((uint)flags & 0xf) << 12 | ((uint)from & 0x3f) << 6 | ((uint)to & 0x3f)); }
private bool AddMove(int totalOrder) { // Infer move flags from state of the working tableau. MoveFlags flags = MoveFlags.Empty; if (WorkingTableau.DiscardPiles.Count != 0) { flags |= MoveFlags.Discards; } if (WorkingTableau.NumberOfSpaces > FindTableau.NumberOfSpaces) { flags |= MoveFlags.CreatesSpace; } if (WorkingTableau.NumberOfSpaces < FindTableau.NumberOfSpaces) { flags |= MoveFlags.UsesSpace; } for (int column = 0; column < WorkingTableau.NumberOfPiles; column++) { Pile pile = WorkingTableau[column]; if (pile.Count == 1 && pile[0].IsEmpty) { flags |= MoveFlags.TurnsOverCard; break; } } #if false // Check which move is better. if (best != -1) { Move previous = Candidates[best]; int previousChangeInSpaces = previous.Flags.ChangeInSpaces(); int currentChangeInSpaces = flags.ChangeInSpaces(); if (previousChangeInSpaces >= currentChangeInSpaces) { if (previousChangeInSpaces > currentChangeInSpaces) { return(false); } int previousTurnsOverCard = previous.Flags.TurnsOverCard() ? 1 : 0; int currentTurnsOverCard = flags.TurnsOverCard() ? 1 : 0; if (previousTurnsOverCard >= currentTurnsOverCard) { if (previousTurnsOverCard > currentTurnsOverCard) { return(false); } int previousOrder = previous.ToRow; int currentOrder = totalOrder; if (previousOrder >= currentOrder) { return(false); } } } // Clear out the previous best move. Candidates[best] = Move.Empty; } #endif // Add the scoring move and the accumulated supplementary moves. best = Candidates.Count; Algorithm.ProcessCandidate(new Move(MoveType.CompositeSinglePile, flags, from, 0, 0, totalOrder, -1, AddSupplementary(SupplementaryMoves))); return(flags.CreatesSpace()); }
public static bool Discards(this MoveFlags flags) { return((flags & MoveFlags.Discards) == MoveFlags.Discards); }
public static bool UndoHolding(this MoveFlags flags) { return((flags & MoveFlags.UndoHolding) == MoveFlags.UndoHolding); }
public void TestCastle(bool castle, MoveFlags flags) { var move = new Move(0, 0, flags); Assert.AreEqual(castle, move.Castle); Assert.AreEqual(true, move.Valid); }
public void TestInvalidMove(bool valid, MoveFlags flags) { var move = new Move(0, 0, flags); Assert.AreEqual(valid, move.Valid); }
/// <summary> /// 駒打ちの動作が行えるか調べ、必要なら実行します。 /// </summary> private bool CheckAndDoDrop(BoardMove move, MoveFlags flags) { if (GetCapturedPieceCount(move.DropPieceType, move.BWType) <= 0) { return false; } // 駒を打つ場所に駒があれば、当然失敗です。 var piece = this[move.DstSquare]; if (piece != null) { return false; } // 駒が置けるか確かめます。 if (!CanDrop(move.BWType, move.DstSquare, move.DropPieceType)) { return false; } if (!EnumEx.HasFlag(flags, MoveFlags.CheckOnly)) { // 駒を盤面に置き、持ち駒から駒を減らします。 this[move.DstSquare] = new BoardPiece( move.DropPieceType, false, move.BWType); DecCapturedPieceCount(move.DropPieceType, move.BWType); MoveDone(move); } return true; }
/// <summary> /// 駒の移動のみの動作を調べるか実際にそれを行います。 /// </summary> private bool CheckAndDoMoveOnly(BoardMove move, MoveFlags flags) { // 駒の移動元に自分の駒がなければダメ var srcPiece = this[move.SrcSquare]; if (srcPiece == null || srcPiece.BWType != move.BWType) { return false; } // 駒の移動先に自分の駒があったらダメ var dstPiece = this[move.DstSquare]; if (dstPiece != null && dstPiece.BWType == move.BWType) { return false; } // これはエラーだけど。。。w if (srcPiece.Piece != move.MovePiece) { return false; } // 各駒が動ける位置に移動するかどうか確認します。 if (!CanMovePiece(move)) { return false; } if (move.ActionType == ActionType.Promote) { // 成れない場合は帰ります。 if (!CanPromote(move)) return false; } else { // 成らないといけない場合は帰ります。 if (IsPromoteForce(move)) return false; } if (!EnumEx.HasFlag(flags, MoveFlags.CheckOnly)) { var pieceType = srcPiece.PieceType; // 移動先に駒があれば、それを自分のものにします。 if (dstPiece != null) { IncCapturedPieceCount(dstPiece.PieceType, move.BWType); // 取った駒を記憶しておきます。 move.TookPiece = dstPiece.Piece; } // 移動後の駒の成り/不成りを決定します。 var promoted = ( srcPiece.IsPromoted || move.ActionType == ActionType.Promote); this[move.DstSquare] = new BoardPiece( pieceType, promoted, move.BWType); // 移動前の位置からは駒をなくします。 this[move.SrcSquare] = null; MoveDone(move); } return true; }
/// <summary> /// その差し手を実際に実行します。 /// </summary> public bool DoMove(BoardMove move, MoveFlags flags = MoveFlags.DoMoveDefault) { flags &= ~MoveFlags.CheckOnly; return CheckAndDoMove(move, flags); }
/// <summary> /// 駒を動かすか、または駒が動かせるか調べます。 /// </summary> private bool CheckAndDoMove(BoardMove move, MoveFlags flags) { if (move == null || !move.Validate()) { throw new ArgumentNullException("move"); } using (LazyLock()) { // 手番があわなければ失敗とします。 if (EnumEx.HasFlag(flags, MoveFlags.CheckTurn)) { if (this.turn == BWType.None || this.turn != move.BWType) { return false; } } if (move.ActionType == ActionType.Drop) { return CheckAndDoDrop(move, flags); } else { return CheckAndDoMoveOnly(move, flags); } } }
private static void addConversionMoves(MoveList[] moveLists, Square startPosition, MoveDirections dir, Square position, MoveFlags moveFlags) { moveFlags |= MoveFlags.Conversion; moveLists[(byte)startPosition].Add(new Move(moveFlags, dir, startPosition, position, position, PieceType.Queen)); moveLists[(byte)startPosition].Add(new Move(moveFlags, dir, startPosition, position, position, PieceType.Rook)); moveLists[(byte)startPosition].Add(new Move(moveFlags, dir, startPosition, position, position, PieceType.Bishop)); moveLists[(byte)startPosition].Add(new Move(moveFlags, dir, startPosition, position, position, PieceType.Knight)); }
public void TestEnPassantTarget(int from, int to, MoveFlags flags, int enPassantTarget) { var move = new Move(from, to, flags); Assert.AreEqual(enPassantTarget, move.EnPassantTarget); }
public void TestQuietMove(bool quiet, MoveFlags flags) { var move = new Move(0, 0, flags); Assert.AreEqual(quiet, move.QuietMove); }
public Move(Position from, Position to, MoveFlags flags) : this(from, to, flags, PieceType.None) { }
internal DetailedMove(Square from, Square to, Piece piece, MoveFlags flags, Type promotion, string san, string fen) : base(from, to, piece, flags, promotion) { SAN = san; FEN = fen; }
public void AddMove(int fromPosition, int targetPosition, MoveFlags moveBits, List <Move> moves) { Piece takenPiece = GetPiece(targetPosition); moves.Add(MoveHelper.CreateMove(targetPosition, fromPosition, takenPiece, Piece.EMPTY, moveBits, this)); }
public void TestEnPassantTarget( int from, int to, MoveFlags flags, int enPassantTarget ) { var move = new Move(from, to, flags); Assert.AreEqual(enPassantTarget, move.EnPassantTarget); }
public void Move(Move move) { int toPosition = move.targetPosition; int fromPosition = move.fromPosition; bool isWhitesTurn = IsWhiteTurnBool; Piece piece = GetPiece(fromPosition); Piece pieceType = piece & Piece.PIECE_MASK; Piece takenPiece = GetPiece(toPosition); Piece promotion = (Piece)move.promotion; MoveFlags moveFlags = (MoveFlags)move.moveFlags; if ((moveFlags & MoveFlags.BIG_PAWN_MOVE) == MoveFlags.BIG_PAWN_MOVE) { // when making a big pawn move mark the square behind the moving pawn vulnerable to if (isWhitesTurn) { EnPassantTarget = (byte)(toPosition - BoardStateOffset.ROW_OFFSET); } else { EnPassantTarget = (byte)(toPosition + BoardStateOffset.ROW_OFFSET); } } else { EnPassantTarget = EnPassant.NO_ENPASSANT; } switch (pieceType) { case Piece.PAWN: if ((moveFlags & MoveFlags.ENPASSANT) == MoveFlags.ENPASSANT) { // When taking with enpassant remove the piece if (isWhitesTurn) { SetPiece(toPosition - BoardStateOffset.ROW_OFFSET, Piece.EMPTY); } else { SetPiece(toPosition + BoardStateOffset.ROW_OFFSET, Piece.EMPTY); } } break; case Piece.KING: if ((moveFlags & MoveFlags.CASTLING) == MoveFlags.CASTLING) { if (BoardPosition.PositionColumn(toPosition) < BoardPosition.E_COLUMN) { // if position is less than E_COLUMN then we are castling queen side // copy the rook from the square so we correctly handle the color SetPiece(toPosition + 1, GetPiece(toPosition - 2)); SetPiece(toPosition - 2, Piece.EMPTY); } else { // otherwise we are castling king side // copy the rook from the square so we correctly handle the color SetPiece(toPosition - 1, GetPiece(toPosition + 1)); SetPiece(toPosition + 1, Piece.EMPTY); } } SetKingPosition(IsWhiteTurn, (byte)toPosition); break; } // remove opportunity to castle based on the position on the board CastlingBits = CastlingBits & CastlingHelper.castleLookup[toPosition] & CastlingHelper.castleLookup[fromPosition]; // move piece to new position if (promotion == Piece.EMPTY) { SetPiece(toPosition, piece); } else { SetPiece(toPosition, promotion | (Piece)IsWhiteTurn); } // remove piece from previous position SetPiece(fromPosition, Piece.EMPTY); if (pieceType == Piece.PAWN || ((takenPiece & Piece.PIECE_MASK) != Piece.EMPTY)) { HalfTurnCounter = 0; } else { HalfTurnCounter++; } //if (!isWhitesTurn) { // // increment fullMoveClock after blacks turn // TurnCounter++; //} // flip turn IsWhiteTurn = (byte)(IsWhiteTurn ^ 1); }
public static bool UsesSpace(this MoveFlags flags) { return((flags & MoveFlags.UsesSpace) == MoveFlags.UsesSpace); }
public void UndoMove(Move move) { int targetPosition = move.targetPosition; int fromPosition = move.fromPosition; int theirColor = IsWhiteTurn; int ourColor = IsWhiteTurn ^ 1; bytes[fromPosition] = bytes[targetPosition]; bytes[targetPosition] = move.capturedPiece; Piece movedPiece = GetPiece(fromPosition); CastlingBits previous = (CastlingBits)move.previousCastlingBits; bytes[BoardStateOffset.HALF_TURN_COUNTER] = move.previousHalfMove; bytes[BoardStateOffset.CASTLING] = move.previousCastlingBits; bytes[BoardStateOffset.EN_PASSANT_FIELD] = move.previousEnpassant; MoveFlags moveFlags = (MoveFlags)move.moveFlags; if ((moveFlags & MoveFlags.ENPASSANT) == MoveFlags.ENPASSANT) { // when undoing a enpassant move spawn their pawn back // we abuse that isWhite is a integer which is 1 on whites turn and 0 and blacks turn // if it was black move then we have to spawn it one row above // if it was whites move we spawn it one move below // keep in mind the IsWhiteTurn is currently opposite of who made the move int enpassantSpawnPosition = targetPosition - BoardStateOffset.ROW_OFFSET + 2 * BoardStateOffset.ROW_OFFSET * IsWhiteTurn; SetPiece(enpassantSpawnPosition, Piece.PAWN | (Piece)theirColor); // when capturing with enpassant don't place the captured piece back since it was taken from another square bytes[targetPosition] = (byte)Piece.EMPTY; } if (move.promotion != 0) { bytes[fromPosition] = (byte)(Piece.PAWN | (Piece)ourColor); } // if black made a move decrement the turn counter // we abuse that isWhite is a integer which is 1 on whites turn and 0 and blacks turn //TurnCounter -= IsWhiteTurn; if ((movedPiece & Piece.PIECE_MASK) == Piece.KING) { if ((moveFlags & MoveFlags.CASTLING) == MoveFlags.CASTLING) { // if the target move is less than the kingsposition it is queenside castling, // otherwise it is kingside castle if (targetPosition < fromPosition) { // copy the rook back to its starting position bytes[fromPosition - 4] = bytes[fromPosition - 1]; bytes[fromPosition - 1] = 0; } else { bytes[fromPosition + 3] = bytes[fromPosition + 1]; bytes[fromPosition + 1] = 0; } } SetKingPosition(ourColor, (byte)fromPosition); } // switch turn back to whites turn IsWhiteTurn = (byte)ourColor; }
public static bool TurnsOverCard(this MoveFlags flags) { return((flags & MoveFlags.TurnsOverCard) == MoveFlags.TurnsOverCard); }
/// <summary> /// その指し手が実際に実現できるか調べます。 /// </summary> public bool CanMove(Move move, MoveFlags flags = MoveFlags.CanMoveDefault) { flags |= MoveFlags.CheckOnly; return(CheckAndMakeMove(move, flags)); }
/// <summary> /// 特殊な指し手の着手が行えるか調べ、必要なら実行します。 /// </summary> private bool CheckAndMakeSpecialMove(BoardMove move, MoveFlags flags) { if (!EnumEx.HasFlag(flags, MoveFlags.CheckOnly)) { MoveDone(move); } return true; }
/// <summary> /// その指し手を実際に実行します。 /// </summary> public bool DoMove(Move move, MoveFlags flags = MoveFlags.DoMoveDefault) { flags &= ~MoveFlags.CheckOnly; return(CheckAndMakeMove(move, flags)); }
public MoveUInt(Square from, Square to, MoveFlags flags) { _moveData = ((uint)flags & 0xf) << 12 | ((uint)from & 0x3f) << 6 | ((uint)to & 0x3f); }
public Move(MoveType type, MoveFlags flags, int from, int fromRow, int to, int toRow) : this(type, flags, from, fromRow, to, toRow, -1, -1) { }
/// <summary> /// 駒の移動のみの動作を調べるか実際にそれを行います。 /// </summary> private bool CheckAndMakeMoveOnly(Move move, MoveFlags flags) { // 駒の移動元に自分の駒がなければダメ var srcPiece = this[move.SrcSquare]; if (srcPiece == null || srcPiece.BWType != move.BWType) { return(false); } // 駒の移動先に自分の駒があったらダメ var dstPiece = this[move.DstSquare]; if (dstPiece != null && dstPiece.BWType == move.BWType) { return(false); } // これはエラーだけど。。。w if (srcPiece.Piece != move.MovePiece) { return(false); } // 各駒が動ける位置に移動するかどうか確認します。 if (!CanMovePiece(move)) { return(false); } if (move.ActionType == ActionType.Promote) { // 成れない場合は帰ります。 if (!CanPromote(move)) { return(false); } } else { // 成らないといけない場合は帰ります。 if (IsPromoteForce(move)) { return(false); } } if (!EnumEx.HasFlag(flags, MoveFlags.CheckOnly)) { var pieceType = srcPiece.PieceType; // 移動先に駒があれば、それを自分のものにします。 if (dstPiece != null) { IncHand(dstPiece.PieceType, move.BWType); // 取った駒を記憶しておきます。 move.TookPiece = dstPiece.Piece; } // 移動後の駒の成り/不成りを決定します。 var promoted = ( srcPiece.IsPromoted || move.ActionType == ActionType.Promote); this[move.DstSquare] = new BoardPiece( pieceType, promoted, move.BWType); // 移動前の位置からは駒をなくします。 this[move.SrcSquare] = null; // 前回の指し手と位置が同じか調べます。 move.HasSameSquareAsPrev = (move.DstSquare == PrevMovedSquare); MoveDone(move); } return(true); }
/// <summary> /// 指し手が実際に着手可能か確認します。 /// </summary> private bool CanMove(BoardMove move, MoveFlags flags = MoveFlags.DoMoveDefault) { var tmp = Board.Clone(); // 成り・不成りの選択ダイアログを出す前に // 駒の移動ができるか調べておきます。 // 失敗したら移動中だった駒は元の位置に戻されます。 if (!tmp.DoMove(move, flags)) { return false; } // 通常モードの場合、今指した側の玉が王手されていたら // その手は採用しません。(王手放置禁止) if (EditMode == EditMode.Normal && tmp.IsChecked(tmp.Turn.Flip())) { return false; } return true; }
public void MovesImport() { string file_path = moves_input.GetComponentsInChildren <Text>()[1].text; string full_path = Path.Combine(import_path, file_path); imported_moves = new List <Move>(); try { StreamReader input_stream = new StreamReader(full_path); while (!input_stream.EndOfStream) { string line = input_stream.ReadLine().Replace(@"\", ""); // Line is a comment if (line[0] == '#') { } // Line is a move else { Move current_move = ScriptableObject.CreateInstance <Move>(); string[] parts = line.Split(','); int line_length = parts.Length; // Name current_move.name = parts[2]; // Move Effect int effect_code = int.Parse(parts[3], System.Globalization.NumberStyles.HexNumber); current_move.move_effect = (MoveEffects)effect_code; // Base Power current_move.base_power = int.Parse(parts[4]); // Type current_move.type = (Pokemon.Types)Enum.Parse(typeof(Pokemon.Types), parts[5], true); // Damage Category current_move.damage_category = (DamageCategories)Enum.Parse(typeof(DamageCategories), parts[6], true); // Accuracy current_move.accuracy = int.Parse(parts[7]); // Total PP current_move.total_pp = int.Parse(parts[8]); // Effect Chance current_move.effect_chance = int.Parse(parts[9]); // Target current_move.target = (Targets)Enum.Parse(typeof(Targets), parts[10], true); // Priority current_move.priority = int.Parse(parts[11]); // Move Flags string flags_string = parts[12]; MoveFlags flags = new MoveFlags(); if (flags_string.Contains('a')) { flags.makes_physical_contact = true; } if (flags_string.Contains('b')) { flags.can_protect_against = true; } if (flags_string.Contains('c')) { flags.magic_coat_can_reflect = true; } if (flags_string.Contains('d')) { flags.snatch_can_steal = true; } if (flags_string.Contains('e')) { flags.mirror_move_can_copy = true; } if (flags_string.Contains('f')) { flags.damage_no_flinch_chance = true; } if (flags_string.Contains('g')) { flags.thaws_if_frozen = true; } if (flags_string.Contains('h')) { flags.has_high_crit_rate = true; } if (flags_string.Contains('i')) { flags.is_biting = true; } if (flags_string.Contains('j')) { flags.is_punching = true; } if (flags_string.Contains('k')) { flags.is_sound_based = true; } if (flags_string.Contains('l')) { flags.is_powder_based = true; } if (flags_string.Contains('m')) { flags.is_pulse_based = true; } if (flags_string.Contains('n')) { flags.is_bomb_based = true; } if (flags_string.Contains('o')) { flags.is_dance = true; } current_move.move_flags = flags; // Description int description_parts = line_length - 14; string description = parts[13].TrimStart('"'); for (int i = 0; i < description_parts; i++) { description += "," + parts[14 + i]; } current_move.description = description.TrimEnd('"'); imported_moves.Add(current_move); } } } catch (Exception e) { Debug.Log(e); return; } string moves_path = Settings.MOVES_FILE_PATH; for (int i = 0; i < imported_moves.Count; i++) { Move new_move = imported_moves[i]; AssetDatabase.CreateAsset(new_move, Path.Combine(moves_path, new_move.name) + ".asset"); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); EditorUtility.FocusProjectWindow(); Selection.activeObject = new_move; } }
/// <summary> /// Construct a move /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="flags"> </param> public Move(int from, int to, MoveFlags flags = MoveFlags.QuietMove) { From = @from; To = to; _flags = flags; }
public void TestGetPromotion(PieceType piece, MoveFlags flags) { var move = new Move(0, 0, flags); Assert.AreEqual(piece, move.Promotion); Assert.AreEqual(true, move.Valid); }
public void TestCaptures(bool captures, MoveFlags flags) { var move = new Move(0, 0, flags); Assert.AreEqual(captures, move.Captures); Assert.AreEqual(true, move.Valid); }
public Move(int from, int to, MoveFlags flags) { _data = (ushort)from; _data |= (ushort)(to << 6); _data |= (ushort)((byte)flags << 12); }
public void TestDoublePawnPush(bool push, MoveFlags flags) { var move = new Move(0, 0, flags); Assert.AreEqual(push, move.DoublePawnPush); Assert.AreEqual(true, move.Valid); }
/// <summary> /// 駒を動かすか、または駒が動かせるか調べます。 /// </summary> private bool CheckAndMakeMove(BoardMove move, MoveFlags flags) { if (move == null || !move.Validate()) { throw new ArgumentNullException("move"); } // 投了などの特殊な指し手がある場合はゲームが既に終了しているので // 指し手を進めることはできません。 if (HasSpecialMove) { if (flags.HasFlag(MoveFlags.CheckOnly)) { // CheckOnlyの場合は、ここで失敗させません。 } else if (flags.HasFlag(MoveFlags.AutoRemoveSpecialMove)) { // 特殊な指し手を取り除きます。 RemoveSpecialMove(); } else { return false; } } using (LazyLock()) { // 手番があわなければ失敗とします。 if (EnumEx.HasFlag(flags, MoveFlags.CheckTurn)) { if (this.turn == BWType.None || this.turn != move.BWType) { return false; } } if (move.IsSpecialMove) { return CheckAndMakeSpecialMove(move, flags); } else if (move.ActionType == ActionType.Drop) { return CheckAndMakeDrop(move, flags); } else { return CheckAndMakeMoveOnly(move, flags); } } }
public static ulong ApplyMove(Board board, Move move, ulong boardHash) { var fromPiece = board.GetPiece(move.fromPosition); var toPiece = board.GetPiece(move.targetPosition); var toPosition = move.targetPosition; var fromPosition = move.fromPosition; var promotion = ((Piece)move.promotion == Piece.EMPTY) ? fromPiece : (Piece)move.promotion | (fromPiece & Piece.IS_WHITE); // remove the from piece boardHash ^= pieceHash(fromPosition, fromPiece); // add nothing to fromPosition boardHash ^= pieceHash(fromPosition, Piece.EMPTY); // remove the previous piece at the target location boardHash ^= pieceHash(toPosition, toPiece); // add the moved piece to the target position boardHash ^= pieceHash(toPosition, promotion); // switch turn boardHash ^= whiteTurn; MoveFlags moveFlags = (MoveFlags)move.moveFlags; if ((moveFlags & MoveFlags.BIG_PAWN_MOVE) == MoveFlags.BIG_PAWN_MOVE) { // toPosition -16 if white and + 16 when black. boardHash ^= enpassantHash(toPosition + BoardStateOffset.ROW_OFFSET - BoardStateOffset.ROW_OFFSET * 2 * board.IsWhiteTurn); } if (board.EnPassantTarget != EnPassant.NO_ENPASSANT) { // if there is a enpassant target on the board then unmark the enpassant target boardHash ^= enpassantHash(board.EnPassantTarget); } if (((MoveFlags)move.moveFlags & MoveFlags.ENPASSANT) == MoveFlags.ENPASSANT) { int enpassantSpawnPosition = move.targetPosition - BoardStateOffset.ROW_OFFSET + 2 * BoardStateOffset.ROW_OFFSET * board.IsWhiteTurn; // toPosition -16 if white and + 16 when black. int takenPosition = toPosition + BoardStateOffset.ROW_OFFSET - BoardStateOffset.ROW_OFFSET * 2 * board.IsWhiteTurn; boardHash ^= pieceHash(takenPosition, Piece.EMPTY); boardHash ^= pieceHash(takenPosition, board.GetPiece(takenPosition)); } var nextCastlingBits = board.CastlingBits & CastlingHelper.castleLookup[toPosition] & CastlingHelper.castleLookup[fromPosition]; if (nextCastlingBits != board.CastlingBits) { // remove the previous castlingOptions; boardHash ^= castlingOptions[(int)board.CastlingBits]; // apply the new castlingOptions boardHash ^= castlingOptions[(int)nextCastlingBits]; } if ((moveFlags & MoveFlags.CASTLING) == MoveFlags.CASTLING) { // if the target move is less than the kingsposition it is queenside castling, // otherwise it is kingside castle if (toPosition < fromPosition) { // remove the rook boardHash ^= pieceHash(fromPosition - 4, board.GetPiece(fromPosition - 4)); // remove the rook boardHash ^= pieceHash(fromPosition - 4, Piece.EMPTY); // place nothing where the rook once was // add the rook boardHash ^= pieceHash(fromPosition - 1, board.GetPiece(fromPosition - 4)); // place the rook boardHash ^= pieceHash(fromPosition - 1, Piece.EMPTY); // remove the nothing } else { // remove the rook boardHash ^= pieceHash(fromPosition + 3, board.GetPiece(fromPosition + 3)); // remove the rook boardHash ^= pieceHash(fromPosition + 3, Piece.EMPTY); // place nothing where the rook once was // add the rook boardHash ^= pieceHash(fromPosition + 1, board.GetPiece(fromPosition + 3)); // place the rook boardHash ^= pieceHash(fromPosition + 1, Piece.EMPTY); // remove the nothing } } return(boardHash); }
public Move(MoveType type, MoveFlags flags, int from, int fromRow, int to, int toRow, int holdingNext, int next) : this() { Type = type; Flags = flags; From = from; FromRow = fromRow; To = to; ToRow = toRow; HoldingNext = holdingNext; Next = next; Score = 0; }
public static bool CreatesSpace(this MoveFlags flags) { return((flags & MoveFlags.CreatesSpace) == MoveFlags.CreatesSpace); }
public static bool PreservesSpace(this MoveFlags flags) { return((flags & (MoveFlags.CreatesSpace | MoveFlags.UsesSpace)) == MoveFlags.Empty); }
/// <summary> /// その指し手が実際に実現できるか調べます。 /// </summary> public bool CanMove(BoardMove move, MoveFlags flags = MoveFlags.CanMoveDefault) { flags |= MoveFlags.CheckOnly; return CheckAndMakeMove(move, flags); }