public override void Execute(BoardMove move) { var piece = BoardState.GetItem(move.From).Item as PawnEntity; piece.TwoStep = true; ActionProvider.Create((int)DefaultActions.MoveOnly, BoardState).Execute(move); }
private static bool TryFindMove(IEnumerable <LocatedItem <ChessPieceEntity> > items, BoardLocation destination, StandardAlgebraicNotation san, out BoardMove findMoveTo) { findMoveTo = null; var locatedItems = items as LocatedItem <ChessPieceEntity>[] ?? items.ToArray(); if (!locatedItems.Any()) { return(true); } if (locatedItems.Count() == 1) { var item = locatedItems.Single(); if (san.PromotionPiece.HasValue) { findMoveTo = item.Paths.FlattenMoves().FindMove(item.Location, destination, ChessFactory.MoveExtraData(item.Item.Player, san.PromotionPiece.Value)); } else { findMoveTo = item.FindMoveTo(destination); } return(findMoveTo != null); } return(false); }
static void Main(string[] args) { AllianceScenario allianceScenario = AllianceScenario.GetRandomAllianceScenario(); Board board = Board.GetInitialBoard(); BoardMove moves = new BoardMove(); moves.Add(board.GetMove("ber", "kie")); moves.Add(board.GetMove("bud", "rum")); moves.Add(board.GetMove("con", "bul")); moves.Add(board.GetMove("lvp", "edi")); moves.Add(board.GetMove("mar", "pie")); moves.Add(board.GetMove("mos", "stp")); moves.Add(board.GetMove("mun", "ruh")); moves.Add(board.GetMove("par", "gas")); moves.Add(board.GetMove("rom", "nap")); moves.Add(board.GetMove("ven", "tyr")); moves.Add(board.GetMove("vie", "tri")); moves.Add(board.GetMove("war", "sil")); moves.Add(board.GetMove("ank", "con")); moves.Add(board.GetMove("bre", "mao")); moves.Add(board.GetMove("edi", "nth")); moves.Add(board.GetMove("kie", "den")); moves.Add(board.GetMove("lon", "eng")); moves.Add(board.GetMove("nap", "tys")); moves.Add(board.GetMove("sev", "bla")); moves.Add(board.GetMove("stp_sc", "bot")); moves.Add(board.GetMove("tri", "alb")); moves.FillHolds(board); board.ApplyMoves(moves); board.EndTurn(); moves.Clear(); moves.Add(board.GetMove("bul", "gre")); moves.Add(board.GetMove("gas", "spa")); moves.Add(board.GetMove("kie", "hol")); moves.Add(board.GetMove("ruh", "bel")); moves.Add(board.GetMove("smy", "arm")); moves.Add(board.GetMove("stp", "nwy")); moves.Add(board.GetMove("tri", "ser")); moves.Add(board.GetMove("bot", "swe")); moves.Add(board.GetMove("con", "bul_ec")); moves.Add(board.GetMove("mao", "por")); moves.Add(board.GetMove("tys", "tun")); moves.FillHolds(board); board.ApplyMoves(moves); board.EndTurn(); //var boardMoves = BoardFutures.GetAllBoardMovesWinter(board); var probabilisticFuturesAlgorithm = new ProbabilisticFuturesAlgorithm(); int limit = 20; List <Board> futureBoards = board.GetFutures(allianceScenario, probabilisticFuturesAlgorithm); while (futureBoards.Any() && limit > 0) { limit--; board = futureBoards[0]; futureBoards = board.GetFutures(allianceScenario, probabilisticFuturesAlgorithm); } }
protected void SetupToEntity(BoardMove move, TestBoardEntity entity = null) { var locatedEntity = CreateItem(move, entity); RoBoardStateMock.Setup(m => m.GetItem(It.Is <BoardLocation>(l => move.To.Equals(l)))) .Returns(locatedEntity); }
/// <summary> /// Performs a full play cycle. /// </summary> /// <param name="player">The player who is playing.</param> /// <returns>The desired move.</returns> public BoardMove Play(Player player) { int index; UIFelliSquare pieceToMove; UIFelliSquare[] availableForSelection; BoardMove[] possibleMoves; BoardMove selectedMove = new BoardMove(); while (true) { // Get all squares that have a piece belonging to the current // player and piece has possible moves. availableForSelection = GetAllSquaresWithPiecesOfColor(player.PiecesColor); index = GetPlayerSelectSquare(availableForSelection); // If index < 0 that means the player hit escape in piece // selection... if (index < 0) { // ...signaling desire to exit the game. pieceToMove = null; break; } pieceToMove = availableForSelection[index]; // Get possible moves by the selected piece. possibleMoves = board.GetPossibleMoves(pieceToMove.Piece); // Get all possible destinations. availableForSelection = GetPossibleDestinations(possibleMoves); index = GetPlayerSelectSquare(availableForSelection); // If index < 0 that means the player hit escape in destination // selection... if (index < 0) { pieceToMove.IsHovered = false; // ...signaling desire to go back to piece selection. continue; } selectedMove = possibleMoves[index]; pieceToMove.IsHovered = false; availableForSelection[index].IsHovered = false; break; } // Returning BoardMove.Piece == null will signal an intention to // quit the game. return(new BoardMove(pieceToMove?.Piece, selectedMove.Destination, selectedMove.PieceEaten)); }
protected async Task OnBoardFieldClicked(Position position) { if (this.GameManager.IsGameReadyToPlay) { if (ChessBoardComponent.selectedPosition == null) { var pieceAtPosition = GameManager.GetPieceForViewAtPosition(position); if (pieceAtPosition != null) { if (pieceAtPosition.PieceColor == GameManager.ClientColor) { ChessBoardComponent.SelectPosition(position); ChessBoardComponent.ShowMoves(GameManager.GetPieceMoveSetAtPosition(position).Select(x => position + x.Shift)); } } } else { var move = new BoardMove((Position)ChessBoardComponent.selectedPosition, position); await GameManager.TryPerformMove(move); ChessBoardComponent.UnSelectAll(); } } }
public static IEnumerable <BoardMove> GetBoardMovesFallSpring(Board board, IEnumerable <MapNode> mapNodeSources) { if (board.Season is Winter) { throw new Exception($"Bad season {board.Season}"); } List <UnitMove> allUnitMoves = board.GetUnitMoves(); ILookup <MapNode, UnitMove> sourceNodeGroups = allUnitMoves.Where(um => mapNodeSources.Contains(um.Edge.Source)).ToLookup(um => um.Edge.Source); List <BoardMove> completedBoardMoves = new List <BoardMove>(); int depth = 0; foreach (UnitMove move in sourceNodeGroups.First()) { if (move.IsConvoy || move.IsDisband) { continue; } BoardMove workingBoardMove = new BoardMove(); workingBoardMove.Add(move); GetBoardMovesFallSpringRecursive(board, workingBoardMove, sourceNodeGroups, completedBoardMoves, depth + 1); } return(completedBoardMoves); }
private static void GetWinterBoardMovesDisbandsOnlyRecursive(Board originalBoard, BoardMove workingBoardMove, IEnumerable <UnitMove> availableMoves, HashSet <BoardMove> completedBoardMoves, PowersDictionary <int> buildDisbandCounts, int minMoves) { if (workingBoardMove.Count == minMoves) { completedBoardMoves.Add(workingBoardMove.Clone()); return; } var moveGrouping = availableMoves.ToLookup(um => um.Unit.Power); Powers power = availableMoves.First().Unit.Power; IEnumerable <UnitMove> remainingMoves; foreach (UnitMove unitMove in moveGrouping[power]) { if (workingBoardMove.Count(um => um.Unit.Power == power) == Math.Abs(buildDisbandCounts[power])) { remainingMoves = availableMoves.Where(um => um.Unit.Power != power); } else { remainingMoves = availableMoves.Where(um => um != unitMove); } BoardMove newBoardMove = workingBoardMove.Clone(); newBoardMove.Add(unitMove); GetWinterBoardMovesDisbandsOnlyRecursive(originalBoard, newBoardMove, remainingMoves, completedBoardMoves, buildDisbandCounts, minMoves); } }
public void MateTest2() { var bod = "# ---- 棋譜ファイル ----\n" + "先手:先手\n" + "後手:後手\n" + "後手の持駒:歩三 \n" + " 9 8 7 6 5 4 3 2 1\n" + "+---------------------------+\n" + "|v香v桂 ・ ・ ・ ・ ・ ・ ・|一\n" + "| ・ ・ ・ ・ ・ ・ ・ ・ ・|二\n" + "|v玉v桂v歩 金 ・ ・ ・ ・ ・|三\n" + "| ・ ・ ・ ・ ・ ・ ・ ・ ・|四\n" + "| ・ 銀 ・ 歩 ・ ・ ・ ・ ・|五\n" + "| 玉 ・ 歩 ・ 歩 香 ・ ・ ・|六\n" + "| ・v金 銀 金 ・ ・ ・ ・ ・|七\n" + "| ・ ・v馬 銀 ・ ・ ・ ・ ・|八\n" + "| 香 ・ ・ ・ ・ ・ ・ ・ ・|九\n" + "+---------------------------+\n" + "先手の持駒:飛二 角 金 銀 桂二 香 歩十一 \n" + "手数=0\n" + "後手番\n"; var board = BodBoard.Parse(bod); var move = BoardMove.CreateDrop( BWType.White, new Square(9, 5), PieceType.Hu); Assert.False(board.CanMove(move)); Assert.False(board.DoMove(move)); }
private static void GetWinterBoardMovesFullBuildsOnly(IEnumerable <UnitMove> availableMoves, List <BoardMove> buildBoardMoves, PowersDictionary <int> buildDisbandCounts) { var allPowersMoveCombos = new List <List <UnitMove> >(); int powerCount = 0; foreach (Powers currentPower in buildDisbandCounts.Where(kvp => kvp.Value > 0).Select(kvp => kvp.Key)) { powerCount++; int buildMovesForPower = buildDisbandCounts[currentPower]; int territoryBuildCount = availableMoves.Where(um => um.Unit.Power == currentPower).GroupBy(um => um.Edge.Target.Territory).Count(); int buildCount = Math.Min(buildMovesForPower, territoryBuildCount); List <List <UnitMove> > singlePowerMoveCombos; Helpers.GetAllCombinations(availableMoves.Where(um => um.Unit.Power == currentPower).ToList(), buildCount, out singlePowerMoveCombos); singlePowerMoveCombos.RemoveAll(ul => ul.GroupBy(um => um.Edge.Target.Territory).Count() != buildCount); allPowersMoveCombos.AddRange(singlePowerMoveCombos); } var boardMoveLists = new List <List <List <UnitMove> > >(); Helpers.GetAllCombinations(allPowersMoveCombos, powerCount, out boardMoveLists); boardMoveLists.RemoveAll(ll => ll.GroupBy(l2 => l2.First().Unit.Power).Count() < powerCount); foreach (List <List <UnitMove> > ll in boardMoveLists) { BoardMove workingBoardMove = new BoardMove(); foreach (UnitMove move in ll.SelectMany(l => l)) { if (!workingBoardMove.CurrentlyAllowsWinter(move, buildDisbandCounts[move.Unit.Power])) { throw new Exception($"Bad combination when building winter board move: {move}. {move.Unit.Power} allowed {buildDisbandCounts[move.Unit.Power]}"); } workingBoardMove.Add(move); } buildBoardMoves.Add(workingBoardMove); } }
public void MateTest1() { var bod = "後手の持駒:角二 桂二 歩五 \n" + " 9 8 7 6 5 4 3 2 1\n" + "+---------------------------+\n" + "|v香 ・ ・ ・ ・ ・ ・ ・v香|一\n" + "| ・ ・ ・ ・ 銀 ・v金 ・ ・|二\n" + "| ・ ・ とv歩v歩 ・ ・v歩 ・|三\n" + "| ・ ・ ・ ・ ・ ・v歩 ・v歩|四\n" + "| 歩 ・ 銀 金 ・ 飛 ・ ・ ・|五\n" + "| ・ ・ 銀 歩 ・ 金 ・v玉 歩|六\n" + "| 玉 歩 桂 ・ ・ ・ ・ ・ ・|七\n" + "| ・ ・ 歩 ・ ・ 歩 金 ・ ・|八\n" + "| 香v飛 ・ ・ ・ 銀 ・ ・ 香|九\n" + "+---------------------------+\n" + "先手の持駒:桂 歩 \n" + "手数=130"; var board = BodBoard.Parse(bod); var move = BoardMove.CreateDrop( BWType.Black, new Square(2, 7), PieceType.Hu); Assert.False(board.CanMove(move)); Assert.False(board.DoMove(move)); }
public void Should_return_false_when_wrong_piece_in_passing_location(string from, string to) { BoardLocation to1 = to.ToBoardLocation(); var move = new BoardMove(@from.ToBoardLocation(), to1, (int)DefaultActions.TakeOnly); Assert.False(_validator.ValidateMove(move, _boardState)); }
public void Should_return_true_for_valid_take() { BoardLocation to = "B7".ToBoardLocation(); var move = new BoardMove("A6".ToBoardLocation(), to, (int)ChessMoveTypes.TakeEnPassant); Assert.True(_validator.ValidateMove(move, _boardState)); }
public void BoardCloneTest() { Board board = Board.GetInitialBoard(); Board clone = board.Clone(); Assert.AreEqual(clone.OwnedSupplyCenters[Powers.Germany].Count, board.OwnedSupplyCenters[Powers.Germany].Count); BoardMove moves = new BoardMove(); moves.Add(clone.GetMove("kie", "den")); moves.Add(clone.GetMove("ber", "kie")); moves.FillHolds(clone); clone.ApplyMoves(moves); clone.EndTurn(); Assert.AreNotEqual(clone.Turn, board.Turn); moves.Clear(); moves.Add(clone.GetMove("kie", "hol")); moves.FillHolds(clone); clone.ApplyMoves(moves); clone.EndTurn(); Assert.AreNotEqual(clone.OwnedSupplyCenters[Powers.Germany].Count, board.OwnedSupplyCenters[Powers.Germany].Count); }
/// <summary> /// 駒の種類にかかわりなく、指定の位置に着手可能な指し手をすべて列挙します。 /// </summary> public IEnumerable<BoardMove> ListupMoves(BWType bwType, Square dstSquare) { // 打てる駒をすべて列挙します。 foreach (var pieceType in EnumEx.GetValues<PieceType>()) { if (GetCapturedPieceCount(pieceType, bwType) <= 0) { continue; } var move = new BoardMove() { DstSquare = dstSquare, DropPieceType = pieceType, BWType = bwType, }; // 駒打ちが可能なら、それも該当手となります。 if (CanMove(move, MoveFlags.CheckOnly)) { yield return move; } } // 移動による指し手をすべて列挙します。 foreach (var srcSquare in Board.AllSquares()) { var moves = GetAvailableMove(bwType, srcSquare, dstSquare); foreach (var move in moves) { yield return move; } } }
public void BuildUnitMoves() { Board board = Board.GetInitialBoard(); BoardMove moves = new BoardMove(); moves.Add(board.GetMove("kie", "den")); moves.Add(board.GetMove("ber", "kie")); moves.FillHolds(board); board.ApplyMoves(moves); Assert.AreEqual(3, board.OwnedSupplyCenters[Powers.Germany].Count); board.EndTurn(); Assert.AreEqual(3, board.OwnedSupplyCenters[Powers.Germany].Count); moves.Clear(); moves.Add(board.GetMove("kie", "hol")); moves.FillHolds(board); board.ApplyMoves(moves); Assert.AreEqual(3, board.OwnedSupplyCenters[Powers.Germany].Count); board.EndTurn(); Assert.AreEqual(5, board.OwnedSupplyCenters[Powers.Germany].Count); Assert.AreEqual(24, board.OwnedSupplyCenters.Where(kvp => kvp.Key != Powers.None).SelectMany(kvp => kvp.Value).Count()); var unitMoves = board.GetUnitMoves(); Assert.AreEqual(4, unitMoves.Count(um => um.IsBuild)); }
/// <summary> /// <paramref name="srcSquare"/>の駒を<paramref name="dstSquare"/> /// に動かすことが可能な指し手をすべて列挙します。 /// </summary> private IEnumerable<BoardMove> GetAvailableMove(BWType bwType, Square srcSquare, Square dstSquare) { var piece = this[srcSquare]; if (piece == null || piece.BWType != bwType) { yield break; } var move = new BoardMove() { DstSquare = dstSquare, SrcSquare = srcSquare, MovePiece = piece.Piece, BWType = bwType, }; // 成り駒でなければ、成る可能性があります。 if (!piece.IsPromoted) { move.IsPromote = true; if (CanMove(move, MoveFlags.CheckOnly)) { // yield returnなのでCloneしないとまずい。 yield return move.Clone(); } } move.IsPromote = false; if (CanMove(move, MoveFlags.CheckOnly)) { yield return move; } }
public void ClearAndAddHistoryItems(IEnumerable <HistoryItem.T> items) { Clear(); foreach (HistoryItem.T item in items) { BoardMove.T move = item.Move; PieceTypes pt = PieceTypes.ptNone; if (move.Color.Equals(Piece.Colors.Black)) { pt = PieceTypes.ptBlack; } else if (move.Color.Equals(Piece.Colors.White)) { pt = PieceTypes.ptWhite; } MoveHistoryItem vm = new MoveHistoryItem(item.ID, pt, Coord.toString(BoardMove.getSourceCoord(move)), Coord.toString(BoardMove.getTargetCoord(move)), BoardMove.getRemovedPiecesCount(move)); Add(vm); } OnPropertyChanged("Count"); OnCollectionChanged(); }
public Paths PathsFrom(BoardLocation location, int forPlayer) { var paths = new Paths(); var playerIdx = (Colours)forPlayer; foreach (var dest in new[] { location.MoveRight(playerIdx, 2), location.MoveLeft(playerIdx, 2), }) { if (dest != null) { var side = dest.X > location.X ? ChessMoveTypes.CastleKingSide : ChessMoveTypes.CastleQueenSide; paths.Add(new Path { BoardMove.Create(location, dest, (int)side) }); } } return(paths); }
public Paths PathsFrom(BoardLocation location, int forPlayer) { var paths = new Paths(); var playerIdx = (Colours)forPlayer; foreach (var dest in new[] { location.KnightVerticalMove(playerIdx, true, true), location.KnightVerticalMove(playerIdx, true, false), location.KnightVerticalMove(playerIdx, false, true), location.KnightVerticalMove(playerIdx, false, false), location.KnightHorizontalMove(playerIdx, true, true), location.KnightHorizontalMove(playerIdx, true, false), location.KnightHorizontalMove(playerIdx, false, true), location.KnightHorizontalMove(playerIdx, false, false), }) { if (dest != null) { paths.Add(new Path { BoardMove.Create(location, dest, (int)DefaultActions.MoveOrTake) }); } } return(paths); }
internal virtual void OnBoardMove(Location i_Source, Location i_Dest) { if (BoardMove != null) { BoardMove.Invoke(i_Source, i_Dest); } }
private List <MapNode> GetPath(Board board, MapNode source, BoardMove boardMove, List <KeyValuePair <MapNode, double> > orderedDistances, Func <MapNode, bool> predicate) { var allMoves = board.GetUnitMoves(); foreach (MapNode currentTarget in orderedDistances.Select(kvp => kvp.Key) .Where(predicate)) { IEnumerable <UndirectedEdge <MapNode> > rawPath; if (!_predecessorObserver.TryGetPath(currentTarget, out rawPath)) { continue; } List <MapNode> path = MakePathList(source, currentTarget, rawPath); MapNode adjacentTarget = path[1]; UnitMove unitMove = allMoves.FirstOrDefault(um => um.Edge.Target == adjacentTarget && um.Edge.Source == source); if (boardMove == null || boardMove.CurrentlyAllowsFallSpring(unitMove)) { return(path); } } // couldn't find anything return(null); }
public bool TryPerformMove(PieceColor color, BoardMove move) { if (GameState != GameState.Ended && game.CurrentPlayerColor == color && game.TryPerformMove(move)) { GameState = GameState.InProgress; if (game.GameState == GameState.Ended) { blackTimer.Stop(); whiteTimer.Stop(); GameState = GameState.Ended; Winner = game.GetWinner(); } else { if (color == PieceColor.White) { whiteTimer.HasMoved(); blackTimer.TryStart(); } else if (color == PieceColor.Black) { blackTimer.HasMoved(); whiteTimer.TryStart(); } } return(true); } return(false); }
private static IEnumerable <BoardLocation> CalcPathBetweenKingAndCastle(BoardMove move, Colours kingColour) { // TODO: This could be pulled out and tested in isolation indeed just be static lists var pathBetween = new List <BoardLocation>(); BoardLocation KingSide(Colours c, int i) => c == Colours.White ? move.From.MoveRight(c, i) : move.From.MoveLeft(c, i); BoardLocation QueenSide(Colours c, int i) => c == Colours.White ? move.From.MoveLeft(c, i) : move.From.MoveRight(c, i); var kingOwner = kingColour; if (move.From.X < move.To.X) { pathBetween.Add(KingSide(kingOwner, 1)); pathBetween.Add(KingSide(kingOwner, 2)); } else { pathBetween.Add(QueenSide(kingOwner, 1)); pathBetween.Add(QueenSide(kingOwner, 2)); } pathBetween.RemoveAll(location => location == null); return(pathBetween); }
public void DisbandWinterUnitMoves() { Board board = Board.GetInitialBoard(); BoardMove moves = new BoardMove(); moves.Add(board.GetMove("tri", "ven")); moves.Add(board.GetMove("ven", "pie")); moves.FillHolds(board); board.ApplyMoves(moves); board.EndTurn(); moves.Clear(); moves.FillHolds(board); board.ApplyMoves(moves); board.EndTurn(); Assert.AreEqual(2, board.OwnedSupplyCenters[Powers.Italy].Count); Assert.AreEqual(4, board.OwnedSupplyCenters[Powers.Austria].Count); Assert.AreEqual(22, board.OwnedSupplyCenters.Where(kvp => kvp.Key != Powers.None).SelectMany(kvp => kvp.Value).Count()); var unitMoves = board.GetUnitMoves(); Assert.AreEqual(2, unitMoves.Count(um => um.IsBuild)); Assert.AreEqual(3, unitMoves.Count(um => um.IsDisband)); }
public void Execute_can_castle_both_side(Colours colour, bool side) { int rank = colour == Colours.White ? 1 : 8; var king = new KingEntity(colour); var kingStartFile = King.StartPositionFor(colour).X; var kingDestinationFile = side ? ChessFile.G : ChessFile.C; var kingStartLoc = $"{kingStartFile}{rank}".ToBoardLocation(); var kingDestination = $"{kingDestinationFile}{rank}".ToBoardLocation(); var rook = new RookEntity(colour); var rookStartFile = side ? ChessFile.H : ChessFile.A; var rookDestinationFile = side ? ChessFile.F : ChessFile.D; var rookStart = $"{rookStartFile}{rank}".ToBoardLocation(); var rookDestination = $"{rookDestinationFile}{rank}".ToBoardLocation(); var actualKingMove = new BoardMove(kingStartLoc, kingDestination, (int)DefaultActions.MoveOnly); var actualRookMove = new BoardMove(rookStart, rookDestination, (int)DefaultActions.MoveOnly); SetupLocationReturn(kingStartLoc, king); SetupLocationReturn(rookStart, rook); SetupMockActionForMoveType((int)DefaultActions.MoveOnly); Action.Execute(actualKingMove); VerifyActionWasCreated((int)DefaultActions.MoveOnly); VerifyActionWasExecuted(actualKingMove); VerifyActionWasExecuted(actualRookMove); }
public async Task TryPerformMove(BoardMove move) { if (CanPerformMove(move)) { await PerformMove(move); } }
public IEnumerable <BoardMove> GetBoardMovesFallSpring(Board board, AllianceScenario allianceScenario) { HashSet <BoardMove> completedBoardMoves = new HashSet <BoardMove>(); if (board.Season is Winter) { throw new Exception($"Bad season {board.Season}"); } foreach (var kvp in board.OccupiedMapNodes) { BoardMove workingBoardMove = new BoardMove(); List <MapNode> path; UnitMove currentMove; if (_targeter.TryGetMoveTargetValidateWithBoardMove(board, kvp.Key, allianceScenario, workingBoardMove, out path, out currentMove)) { workingBoardMove.Add(currentMove); } else { throw new Exception("Failed to add the very first move? Really!?"); } GetFallSpringMovesRemaining(board, allianceScenario, _targeter, workingBoardMove, completedBoardMoves); } return(completedBoardMoves); }
public Paths PathsFrom(BoardLocation location, int forPlayer) { var paths = new Paths(); var playerIdx = (Colours)forPlayer; foreach (var dest in new[] { location.MoveForward(playerIdx), location.MoveForward(playerIdx)?.MoveRight(playerIdx), location.MoveRight(playerIdx), location.MoveBack(playerIdx)?.MoveRight(playerIdx), location.MoveBack(playerIdx), location.MoveBack(playerIdx)?.MoveLeft(playerIdx), location.MoveLeft(playerIdx), location.MoveLeft(playerIdx)?.MoveForward(playerIdx) }) { if (dest != null) { paths.Add(new Path { BoardMove.Create(location, dest, (int)ChessMoveTypes.KingMove) }); } } return(paths); }
public void MoveBlackTest1() { var board = MakeBoard1(BWType.Black); var move = BoardMove.CreateMove( BWType.Black, new Square(8, 3), new Square(8, 2), new Piece(PieceType.Kyo, false), true); Assert.True(board.CanMove(move)); // 駒が設定されてないと動けません。 MethodUtil.SetPropertyValue(move, "MovePiece", new Piece()); Assert.False(board.CanMove(move)); MethodUtil.SetPropertyValue(move, "MovePiece", new Piece(PieceType.Kyo, false)); // 84の駒は移動できません。 MethodUtil.SetPropertyValue(move, "SrcSquare", new Square(8, 4)); Assert.False(board.CanMove(move)); MethodUtil.SetPropertyValue(move, "SrcSquare", new Square(8, 3)); CanMoveTo(board, move, new List <Tuple <Square, bool> > { Tuple.Create(new Square(8, 2), false), Tuple.Create(new Square(8, 1), true), }); }
public void white_left_castle_correct() { var game = new ClassicGame(); ChessAssert.IsMoveCorrect(game, new BoardMove(new Position(1, 0), new Position(0, 2))); ChessAssert.IsMoveCorrect(game, new BoardMove(new Position(2, 6), new Position(2, 4))); ChessAssert.IsMoveCorrect(game, new BoardMove(new Position(2, 1), new Position(2, 3))); ChessAssert.IsMoveCorrect(game, new BoardMove(new Position(3, 6), new Position(3, 4))); ChessAssert.IsMoveCorrect(game, new BoardMove(new Position(3, 1), new Position(3, 3))); ChessAssert.IsMoveCorrect(game, new BoardMove(new Position(1, 6), new Position(1, 4))); ChessAssert.IsMoveCorrect(game, new BoardMove(new Position(2, 0), new Position(3, 1))); ChessAssert.IsMoveCorrect(game, new BoardMove(new Position(0, 6), new Position(0, 4))); ChessAssert.IsMoveCorrect(game, new BoardMove(new Position(3, 0), new Position(2, 1))); ChessAssert.IsMoveCorrect(game, new BoardMove(new Position(4, 6), new Position(4, 4))); /*-----------------------------------------------------------------------------------*/ var castleMove = new BoardMove(new Position(4, 0), new Position(2, 0)); var leftRook = game.Board.GetPiece(new Position(0, 0)); ChessAssert.IsMoveCorrect(game, castleMove); Assert.IsNull(game.Board.GetPiece(new Position(0, 0))); Assert.AreSame(leftRook, game.Board.GetPiece(new Position(3, 0))); Assert.AreEqual(leftRook.Position, new Position(3, 0)); }
public void ShouldParseFromBoardMove(string @from, string to, DefaultActions moveType, string expectedSan) { var game = ChessFactory.NewChessGame(); var move = BoardMove.Create(from.ToBoardLocation(), to.ToBoardLocation(), (int)moveType); Assert.That(StandardAlgebraicNotation.ParseFromGameMove(game.BoardState, move).ToNotation(), Is.EqualTo(expectedSan)); }
/// <summary> /// 駒の各移動先に対して、その手が指せるのかどうかをチェックします。 /// </summary> private void CanMoveTo(Board board, BoardMove move, List<Tuple<Square, bool>> availables) { for (var file = 1; file <= Board.BoardSize; ++file) { for (var rank = 1; rank <= Board.BoardSize; ++rank) { var sq = new Square(file, rank); var avail = availables.FirstOrDefault(_ => _.Item1 == sq); move.DstSquare = sq; if (avail != null) { if (avail.Item2) { // 成りが必須の場合 move.IsPromote = false; Assert.False(board.CanMove(move)); move.IsPromote = true; Assert.True(board.CanMove(move)); } else { // 成りが必須でない場合 move.IsPromote = false; Assert.True(board.CanMove(move)); move.IsPromote = true; Assert.AreEqual(Board.CanPromote(move), board.CanMove(move)); } } else { // そもそも移動できる場所ではない move.IsPromote = false; Assert.False(board.CanMove(move)); move.IsPromote = true; Assert.False(board.CanMove(move)); } } } }
/// <summary> /// Execute a board move, moving the piece, removing targeted pieces, and transforming the gamepiece. /// TODO: Let the gamerules handle this. /// </summary> /// <param name="move"></param> public void executeMove(BoardMove move) { //LocalPlayer.playerID; //Todo: Execute Move //BoardMove move = .. move.movingPiece.move(board.getSquare(move.destination)); //Byebye foreach(BoardPiece byebyePiece in move.destroyedPieces) { DestroyImmediate(byebyePiece.gameObject); } //TODO: Transform //Next turn. TODO: This should go away when it's implemented into the move. nextPlayerTurn(); }
/// <summary> /// 1手指したときに呼ばれます。 /// </summary> private void MoveDone(BoardMove move) { NotifyBoardChanging(move, false); Turn = Turn.Flip(); PrevMovedSquare = move.DstSquare; this.moveList.Add(move); // リドゥスタックの更新を行います。 var redoMove = this.redoList.LastOrDefault(); if (redoMove != null && redoMove.Equals(move)) { // 指し手がリドゥと同じなら手を一つ削るだけです。 this.redoList.RemoveAt(this.redoList.Count - 1); } else { this.redoList.Clear(); } // 局面の変化を通知します。 NotifyBoardChanged(move, false); }
/// <summary> /// 駒を強制的に成る必要があるか調べます。 /// </summary> public static bool IsPromoteForce(BoardMove move) { if (move == null) { throw new ArgumentNullException("move"); } return IsPromoteForce(move.MovePiece, move.BWType, move.DstSquare); }
/// <summary> /// 上、引、寄るの判定をします。 /// </summary> private static bool CheckRankMoveType(BoardMove bm, Move referenceMove) { if (bm.ActionType == ActionType.Drop) { return false; } var fileMove = bm.DstSquare.File - bm.SrcSquare.File; var rankMove = bm.DstSquare.Rank - bm.SrcSquare.Rank; switch (referenceMove.RankMoveType) { case RankMoveType.Back: return (bm.BWType == BWType.Black ? (rankMove > 0) : (rankMove < 0)); case RankMoveType.Up: return (bm.BWType == BWType.Black ? (rankMove < 0) : (rankMove > 0)); case RankMoveType.Sideways: return (fileMove != 0 && rankMove == 0); } return false; }
/// <summary> /// 打つ、成る、成らず、などを判定します。 /// </summary> /// <remarks> /// 駒が指定の場所に移動できない場合は自動的に打つが選ばれます。 /// (盤上に飛車がないのに、"32飛車"のときなど) /// </remarks> private static bool CheckActionType(BoardMove bm, Move referenceMove, bool canMove) { if (referenceMove.ActionType == ActionType.None) { // 指し手一覧の中に移動できる駒があれば、 // 「打」と指定しなければ打つと判定されません。 if (canMove) { // 指定無しと成らずでおkとします。 return ( bm.ActionType == ActionType.None || bm.ActionType == ActionType.Unpromote); } else { return ( bm.ActionType == ActionType.None || bm.ActionType == ActionType.Unpromote || bm.ActionType == ActionType.Drop); } } else if (referenceMove.ActionType == ActionType.Unpromote) { // 「不成」の場合は無と成らずでおkとします。 return ( bm.ActionType == ActionType.None || bm.ActionType == ActionType.Unpromote); } return (bm.ActionType == referenceMove.ActionType); }
/// <summary> /// 左、右、直の判定をします。 /// </summary> private static bool CheckRelPosType(BoardMove bm, Move referenceMove, List<BoardMove> boardMoveList) { if (bm.ActionType == ActionType.Drop) { return false; } if (bm.MovePiece == Piece.Ryu || bm.MovePiece == Piece.Uma) { // 竜、馬の場合、「直」は使わずに「右左」のみを使用します。 if (boardMoveList.Count() == 1) { return (referenceMove.RelFileType == RelFileType.None); } else { // 駒は二つしかないはずなので、相方に比べて自分が // 左にあれば「左」、右にあれば「右」となっているか // 判定します。 var other = ( ReferenceEquals(bm, boardMoveList[0]) ? boardMoveList[1] : boardMoveList[0]); var fileDif = bm.SrcSquare.File - other.SrcSquare.File; switch (referenceMove.RelFileType) { case RelFileType.Left: return (bm.BWType == BWType.Black ? (fileDif > 0) : (fileDif < 0)); case RelFileType.Right: return (bm.BWType == BWType.Black ? (fileDif < 0) : (fileDif > 0)); case RelFileType.None: return (fileDif == 0); } } } else { var fileMove = bm.DstSquare.File - bm.SrcSquare.File; var rankMove = bm.DstSquare.Rank - bm.SrcSquare.Rank; switch (referenceMove.RelFileType) { case RelFileType.Left: return (bm.BWType == BWType.Black ? (fileMove < 0) : (fileMove > 0)); case RelFileType.Right: return (bm.BWType == BWType.Black ? (fileMove > 0) : (fileMove < 0)); case RelFileType.Straight: return (bm.BWType == BWType.Black ? (rankMove < 0) : (rankMove > 0)) && (fileMove == 0); } } return false; }
/// <summary> /// 列で指し手をフィルターし、Moveに適切なRelPosTypeを設定します。 /// </summary> private static List<BoardMove> FilterFile(Move move, BoardMove referenceMove, List<BoardMove> boardMoveList) { // 駒の移動前情報が必要です。 var nextPos = referenceMove.DstSquare; var prevPos = referenceMove.SrcSquare; if (prevPos == null) { return null; } if ((move.Piece == Piece.Ryu || move.Piece == Piece.Uma) && boardMoveList.Count() == 2) { // 馬と竜の場合は'直'ではなく、右と左しか使いません。 var other = ( referenceMove == boardMoveList[0] ? boardMoveList[1] : boardMoveList[0]); // 動かす前の駒が相方に比べて右にあるか左にあるか調べます。 // 先手の場合は筋が小さい方が右です。 var relFile = prevPos.File - other.SrcSquare.File; relFile *= (referenceMove.BWType == BWType.White ? -1 : +1); if (relFile == 0) { return boardMoveList; } else if (relFile < 0) { move.RelFileType = RelFileType.Right; } else { move.RelFileType = RelFileType.Left; } return new List<BoardMove> { referenceMove }; } else { // 黒から見ると正の場合は引く or 左へ移動(右)で // 負の場合は上がる or 右へ移動(左)です。 var relFile = nextPos.File - prevPos.File; // 列の位置でフィルターします。 var tmpMoveList = boardMoveList.Where(mv => { var rel = nextPos.File - mv.SrcSquare.File; return ( relFile < 0 ? (rel < 0) : relFile > 0 ? (rel > 0) : (rel == 0)); }).ToList(); // 列情報でフィルターされた場合は、列の移動情報を付加します。 if (tmpMoveList.Count() != boardMoveList.Count()) { var relFile2 = relFile * referenceMove.BWType.Sign(); if (relFile2 < 0) { move.RelFileType = RelFileType.Left; } else if (relFile2 > 0) { move.RelFileType = RelFileType.Right; } else { // 直の場合は、左右の動きはありません。 move.RankMoveType = RankMoveType.None; move.RelFileType = RelFileType.Straight; } } return tmpMoveList; } }
/// <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; }
/// <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); } } }
/// <summary> /// <paramref name="square"/>に<paramref name="pieceType"/>を打ち、 /// なお王手されているか確認します。 /// </summary> private bool IsDropAndChecked(BWType bwType, PieceType pieceType, Square square) { var piece = this[square]; if (piece != null) { return true; } var move = new BoardMove() { DstSquare = square, DropPieceType = pieceType, BWType = bwType, }; if (DoMove(move)) { if (!IsChecked(bwType)) { Undo(); return false; } Undo(); return true; } 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> /// 指し手をXX->YYの形式から、ZZ銀上などの形に変換します。 /// </summary> /// <remarks> /// <paramref name="useSrcSquare"/>を真にすると、差し手の後に /// 古い位置の情報が付加されるようになります。(例: 32金(22)) /// </remarks> public static Move ConvertMove(this Board board, BoardMove move, bool useSrcSquare) { if (board == null) { throw new ArgumentNullException("board"); } if (move == null || !move.Validate()) { throw new ArgumentNullException("move"); } var fromPiece = ( move.ActionType == ActionType.Drop ? new Piece(move.DropPieceType) : move.MovePiece); if (fromPiece == null) { return null; } // 駒の種類と最終位置から、あり得る指し手をすべて検索します。 var boardMoveList = board.ListupMoves( fromPiece, move.BWType, move.DstSquare) .ToList(); return FilterMove( board, boardMoveList, move, fromPiece, useSrcSquare); }
/// <summary> /// 持ち駒の数を増やします。 /// </summary> private void SetPiece(BWType bwType, BoardMove tmp) { // 駒位置が"00"の場合は持ち駒となります。 if (tmp.DstSquare.File != 0) { this.board[tmp.DstSquare] = new BoardPiece(tmp.MovePiece, bwType); } else { this.board.IncCapturedPieceCount(tmp.MovePiece.PieceType, bwType); } }
public void MoveWhiteTest1() { var board = MakeBoard1(BWType.White); var move = new BoardMove { DstSquare = new Square(9, 8), SrcSquare = new Square(9, 7), MovePiece = new Piece(PieceType.Hu, false), IsPromote = true, BWType = BWType.White, }; Assert.True(board.CanMove(move)); // 84の駒は移動できません。 move.SrcSquare = new Square(8, 4); Assert.False(board.CanMove(move)); move.SrcSquare = new Square(9, 7); CanMoveTo(board, move, new List<Tuple<Square, bool>> { Tuple.Create(new Square(9, 8), false), }); }
/// <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; }
public void MoveBlackTest1() { var board = MakeBoard1(BWType.Black); var move = new BoardMove { DstSquare = new Square(8, 2), SrcSquare = new Square(8, 3), MovePiece = new Piece(PieceType.Kyo, false), IsPromote = true, BWType = BWType.Black, }; Assert.True(board.CanMove(move)); // 駒が設定されてないと動けません。 move.MovePiece = new Piece(); Assert.False(board.CanMove(move)); move.MovePiece = new Piece(PieceType.Kyo, false); // 84の駒は移動できません。 move.SrcSquare = new Square(8, 4); Assert.False(board.CanMove(move)); move.SrcSquare = new Square(8, 3); CanMoveTo(board, move, new List<Tuple<Square, bool>> { Tuple.Create(new Square(8, 2), false), Tuple.Create(new Square(8, 1), true), }); }
/// <summary> /// コンストラクタ /// </summary> public BoardChangedEventArgs(BoardMove move, bool isUndo) { Move = move; IsUndo = isUndo; }
/// <summary> /// 実際に駒が動けるか確認します。 /// </summary> private bool CanMovePiece(BoardMove move) { var relFile = move.DstSquare.File - move.SrcSquare.File; var relRank = move.DstSquare.Rank - move.SrcSquare.Rank; var piece = move.MovePiece; if (piece.IsPromoted) { // 成り駒が指定の場所に動けるか調べます。 switch (piece.PieceType) { case PieceType.Gyoku: return CanMoveWithTable(move.BWType, relFile, relRank, MoveTableGyoku); case PieceType.Hisya: if (CanMoveWithTable(move.BWType, relFile, relRank, MoveTableGyoku)) { return true; } return CanMoveHisya(move.SrcSquare, relFile, relRank); case PieceType.Kaku: if (CanMoveWithTable(move.BWType, relFile, relRank, MoveTableGyoku)) { return true; } return CanMoveKaku(move.SrcSquare, relFile, relRank); case PieceType.Kin: case PieceType.Gin: case PieceType.Kei: case PieceType.Kyo: case PieceType.Hu: return CanMoveWithTable(move.BWType, relFile, relRank, MoveTableKin); } } else { // 成り駒以外の駒が指定の場所に動けるか調べます。 switch (piece.PieceType) { case PieceType.Gyoku: return CanMoveWithTable(move.BWType, relFile, relRank, MoveTableGyoku); case PieceType.Hisya: return CanMoveHisya(move.SrcSquare, relFile, relRank); case PieceType.Kaku: return CanMoveKaku(move.SrcSquare, relFile, relRank); case PieceType.Kin: return CanMoveWithTable(move.BWType, relFile, relRank, MoveTableKin); case PieceType.Gin: return CanMoveWithTable(move.BWType, relFile, relRank, MoveTableGin); case PieceType.Kei: return CanMoveWithTable(move.BWType, relFile, relRank, MoveTableKei); case PieceType.Kyo: return CanMoveKyo(move.BWType, move.SrcSquare, relFile, relRank); case PieceType.Hu: return CanMoveWithTable(move.BWType, relFile, relRank, MoveTableHu); } } return false; }
/// <summary> /// <paramref name="srcSquare"/>の駒を<paramref name="dstSquare"/> /// に動かすことが可能な指し手を指してみて、なお王手されているか確認します。 /// </summary> private bool IsMoveAndChecked(BWType bwType, Square srcSquare, Square dstSquare) { var piece = this[srcSquare]; if (piece == null || piece.BWType != bwType) { return true; } var move = new BoardMove() { DstSquare = dstSquare, SrcSquare = srcSquare, MovePiece = piece.Piece, BWType = bwType, }; // 成り駒でなければ、成る可能性があります。 if (!piece.IsPromoted) { move.IsPromote = true; if (DoMove(move)) { if (!IsChecked(bwType)) { Undo(); return false; } Undo(); return true; } } move.IsPromote = false; if (DoMove(move)) { if (!IsChecked(bwType)) { Undo(); return false; } Undo(); return true; } return true; }
public void playerPickedMove(BoardMove chosenMove) { gameManager.executeMove(chosenMove); }
/// <summary> /// undo操作を実行します。 /// </summary> private void DoUndo(BoardMove move) { if (move.ActionType == ActionType.Drop) { // 駒打ちの場合は、その駒を駒台に戻します。 this[move.DstSquare] = null; IncCapturedPieceCount(move.DropPieceType, move.BWType); } else { var movedPiece = this[move.DstSquare]; // 駒を成った場合はそれを元に戻します。 if (move.ActionType == ActionType.Promote) { movedPiece.IsPromoted = false; } // 駒を取った場合は、その駒を元に戻します。 if (move.TookPiece != null) { this[move.DstSquare] = new BoardPiece( move.TookPiece.Clone(), move.BWType.Flip()); // 駒を取ったはずなので、その分を駒台から減らします。 DecCapturedPieceCount( move.TookPiece.PieceType, move.BWType); } else { this[move.DstSquare] = null; } this[move.SrcSquare] = movedPiece; } Turn = Turn.Flip(); PrevMovedSquare = ( this.moveList.Any() ? this.moveList.Last().DstSquare : null); }
/// <summary> /// コンストラクタ /// </summary> public BoardPieceRoutedEventArgs(RoutedEvent ev, Board board, BoardMove move) : base(ev) { Board = board; Move = move; }
/// <summary> /// その差し手を実際に実行します。 /// </summary> public bool DoMove(BoardMove move, MoveFlags flags = MoveFlags.DoMoveDefault) { flags &= ~MoveFlags.CheckOnly; return CheckAndDoMove(move, flags); }
/// <summary> /// 複数ある差し手の中から、適切なひとつの差し手を選択します。 /// </summary> /// <remarks> /// <paramref name="referenceMove"/>にはXからYに移動したという情報 /// しかないため、これを52金右などの指し手に変換します。 /// </remarks> private static Move FilterMove(this Board board, List<BoardMove> boardMoveList, BoardMove referenceMove, Piece fromPiece, bool useSrcSquare) { if (!boardMoveList.Any()) { return null; } var nextPos = referenceMove.DstSquare; var move = new Move() { BWType = referenceMove.BWType, Piece = fromPiece, File = nextPos.File, Rank = nextPos.Rank, ActionType = ( // '打', '不成'は消える可能性があります。 referenceMove.ActionType == ActionType.Promote ? referenceMove.ActionType : ActionType.None), SameAsOld = (board.PrevMovedSquare == nextPos), }; // 移動元情報を使う場合は、これで終わりです。 // (.kifファイルからの読み込み時は、駒の移動の場合は移動前情報がつき、 // 駒打ちの場合は"打"が必ずつきます) if (useSrcSquare) { move.SrcSquare = referenceMove.SrcSquare; move.ActionType = referenceMove.ActionType; return move; } // 駒打ち、成り、不成りなどでフィルターします。 var tmpMoveList = boardMoveList.Where( mv => mv.ActionType == referenceMove.ActionType) .ToList(); if (tmpMoveList.Count() != boardMoveList.Count()) { move.ActionType = referenceMove.ActionType; } if (tmpMoveList.Count() == 1) { return move; } // 段の位置でフィルターします。 tmpMoveList = FilterRank(move, referenceMove, tmpMoveList); if (tmpMoveList.Count() == 1) { return move; } // 列の位置でフィルターします。 tmpMoveList = FilterFile(move, referenceMove, tmpMoveList); if (tmpMoveList.Count() == 1) { return move; } // 不明。 return null; }
/// <summary> /// 局面の変更を通知します。 /// </summary> private void NotifyBoardChanged(BoardMove move, bool isUndo) { var handler = BoardChanged; if (handler != null) { Util.CallEvent( () => handler(this, new BoardChangedEventArgs(move, isUndo))); } this.RaisePropertyChanged("MoveCount"); this.RaisePropertyChanged("CanUndo"); this.RaisePropertyChanged("CanRedo"); }
/// <summary> /// 実際に指し手を進めます。 /// </summary> private void MakeMove(BoardMove move) { if (move == null || !move.Validate()) { return; } BoardPieceChanging.SafeRaiseEvent(this, new BoardPieceEventArgs(Board.Clone(), move)); Board.DoMove(move); BoardPieceChanged.SafeRaiseEvent(this, new BoardPieceEventArgs(Board.Clone(), move)); }
/// <summary> /// 段で指し手をフィルターし、Moveに適切なRankMoveTypeを設定します。 /// </summary> private static List<BoardMove> FilterRank(Move move, BoardMove referenceMove, List<BoardMove> boardMoveList) { // 駒の移動前情報が必要です。 var nextPos = referenceMove.DstSquare; var prevPos = referenceMove.SrcSquare; if (prevPos == null) { return null; } // 黒から見ると正の場合は引く or 左へ移動(右)で // 負の場合は上がる or 右へ移動(左)です。 var relRank = nextPos.Rank - prevPos.Rank; // 段の位置でフィルターします。 var tmpMoveList = boardMoveList.Where(mv => { var rel = nextPos.Rank - mv.SrcSquare.Rank; if (relRank < 0) { return (rel < 0); } else if (relRank > 0) { return (rel > 0); } else { return (rel == 0); } }).ToList(); // 段情報でフィルターされた場合は、段の移動情報を付加します。 if (tmpMoveList.Count() != boardMoveList.Count()) { var relRank2 = relRank * referenceMove.BWType.Sign(); if (relRank2 < 0) { move.RankMoveType = RankMoveType.Up; } else if (relRank2 > 0) { move.RankMoveType = RankMoveType.Back; } else { move.RankMoveType = RankMoveType.Sideways; } } return tmpMoveList; }