/// <summary> /// Make an additional special move from the latest snapshot (Without generating the next snapshot) /// </summary> /// <param name="specialRule">The special rule used</param> /// <param name="position">The specified piece's data</param> /// <param name="resultPositions">The returning result of positions</param> /// <returns> /// TRUE if move is valid. /// </returns> private bool AdditionalMove(ChessPieceSpecialRule specialRule, ChessPosition position, out ChessPosition[] resultPositions) { resultPositions = null; if (specialRule == ChessPieceSpecialRule.CastlingLeft || specialRule == ChessPieceSpecialRule.CastlingRight) { int xFromCoord = position.coord.x; int xToCoord = position.coord.x; if (specialRule == ChessPieceSpecialRule.CastlingLeft) { xFromCoord = 0; xToCoord -= 1; } else if (specialRule == ChessPieceSpecialRule.CastlingRight) { xFromCoord = ChessSettings.boardSize - 1; xToCoord += 1; } ChessCoordinate rookFromCoord = new ChessCoordinate(xFromCoord, position.coord.y); ChessCoordinate rookToCoord = new ChessCoordinate(xToCoord, position.coord.y); return(Move(rookFromCoord, rookToCoord, out resultPositions)); } return(true); }
/// <summary> /// Check whether the special rule is matching for the specific piece /// </summary> /// <param name="specialRule">The special rule used</param> /// <param name="position">The specified piece's data</param> /// <param name="from">The specified piece's coordinate</param> /// <param name="to">The destination's coordinate</param> /// <returns> /// TRUE if move is valid regarding special rule. /// </returns> public bool IsValidSpecialRule(ChessPieceSpecialRule specialRule, ChessPosition position, ChessCoordinate from, ChessCoordinate to) { if (specialRule == ChessPieceSpecialRule.None) { return(true); } // Pawn - Move 2 square when starting from initial position if (specialRule == ChessPieceSpecialRule.Pawn2Squares) { if (position.hasMoved) { return(false); } return(true); } if (specialRule == ChessPieceSpecialRule.CastlingLeft || specialRule == ChessPieceSpecialRule.CastlingRight) { if (position.hasMoved) { return(false); } int xCoord = position.coord.x; if (specialRule == ChessPieceSpecialRule.CastlingLeft) { xCoord = 0; } else if (specialRule == ChessPieceSpecialRule.CastlingRight) { xCoord = ChessSettings.boardSize - 1; } int rookCoord = new ChessCoordinate(xCoord, position.coord.y).ToArrayCoord(); if (!piecesDict.ContainsKey(rookCoord)) { return(false); } if (!piecesDict[rookCoord].Type.IsRook()) { return(false); } if (piecesDict[rookCoord].HasMoved) { return(false); } return(true); } return(false); }
void RunMove() { if (GameManager.Instance.Move(from, to)) { ChessCoordinate newTo = to - from; from.x = to.x; from.y = to.y; to.x += newTo.x; to.y += newTo.y; } }
/// <summary> /// Make a move from the latest snapshot /// </summary> /// <param name="from">Current position's coordinate</param> /// <param name="to">Destination position's coordinate</param> /// <returns> /// TRUE if move has successfully been executed. /// </returns> public bool Move(ChessCoordinate from, ChessCoordinate to) { ChessPosition[] resultPositions; if (Move(from, to, out resultPositions)) { GenNextSnapshot(resultPositions); AIManager.Instance.MakeMove(); return(true); } return(false); }
public void PlacePiece(PlayerType senderType, ChessCoordinate coordinate) { if (coordinate.XPosition < 0 || coordinate.XPosition > 14 || coordinate.YPosition < 0 || coordinate.YPosition > 14 || Timer < 0.3f || chessStatus[coordinate.XPosition, coordinate.YPosition] != 0 || !ValidateTurn(senderType) || gameEnded) { return; } chessStatus[coordinate.XPosition, coordinate.YPosition] = (int)senderType; stackCoordinate.Push(coordinate); board.PlacePiece(coordinate, isOffensiveTurn); if (IsWin(coordinate)) { board.ShowEnd(isOffensiveTurn); gameEnded = true; } isOffensiveTurn = !isOffensiveTurn; Timer = 0; }
/// <summary> /// /// </summary> /// <param name="xPosition">以棋盘左下角为(0,0)点的X坐标</param> /// <param name="yPosition">以棋盘左下角为(0,0)点的Y坐标</param> /// <param name="isOffensiveTurn"></param> public void PlacePiece(ChessCoordinate coordinate, bool isOffensiveTurn) { int xTransform = coordinate.XPosition - 7; int yTransform = coordinate.YPosition - 7; GameObject newPiece = Instantiate(isOffensiveTurn ? prefabBlackPiece : prefabWhitePiece, new Vector3(xTransform, yTransform), Quaternion.identity); pilotDot.position = new Vector3(xTransform, yTransform); newPiece.transform.parent = transform; pieces.Push(new ExtendPiece() { XTransform = xTransform, YTransform = yTransform, Piece = newPiece }); if (pieces.Count >= 2) { btnRetract.interactable = true; } }
bool IsWin(ChessCoordinate coordinate) { if (SamePiece(coordinate.XPosition, coordinate.YPosition, 1, 0) >= 5) { return(true); } if (SamePiece(coordinate.XPosition, coordinate.YPosition, 0, 1) >= 5) { return(true); } if (SamePiece(coordinate.XPosition, coordinate.YPosition, 1, 1) >= 5) { return(true); } if (SamePiece(coordinate.XPosition, coordinate.YPosition, 1, -1) >= 5) { return(true); } return(false); }
public ChessBoardSnapshot[] FindPossibleMoves(ChessBoardSnapshot boardSnapshot, ChessPlayerType playerType) { List <ChessBoardSnapshot> ret = new List <ChessBoardSnapshot>(); Dictionary <int, ChessPosition> boardDict = boardSnapshot.ToDictionary(); foreach (KeyValuePair <int, ChessPosition> kvp in boardDict) { ChessPosition position = kvp.Value; if (position.type.IsDifferentTeamAs(playerType)) { continue; } ChessCoordinate from = position.coord; ChessPieceMove[] possibleMoves = GameManager.Instance.profilesDict[position.type].possibleMoves; for (int j = 0; j < possibleMoves.Length; j++) { ChessCoordinate to = from + possibleMoves[j].move; int k = 1; while ( to.IsWithinRange() && (possibleMoves[j].repeatTimes < 0 || k <= possibleMoves[j].repeatTimes) ) { if (GameManager.Instance.IsValidSpecialRule(possibleMoves[j].specialRule, position, from, to)) { // When there are only finite amount of moves, set only when reached destination if (possibleMoves[j].repeatTimes < 0 || k == possibleMoves[j].repeatTimes) { bool isLastMove = false; if (possibleMoves[j].pattern == ChessPieceMovePattern.Normal) { if (boardDict.ContainsKey(to.ToArrayCoord())) { if (boardDict[to.ToArrayCoord()].type.IsSameTeamAs(position.type)) { break; } isLastMove = true; } } else if (possibleMoves[j].pattern == ChessPieceMovePattern.MoveOnly) { if (boardDict.ContainsKey(to.ToArrayCoord())) { break; } } else if (possibleMoves[j].pattern == ChessPieceMovePattern.CaptureOnly) { if (!boardDict.ContainsKey(to.ToArrayCoord())) { break; } if (boardDict[to.ToArrayCoord()].type.IsSameTeamAs(position.type)) { break; } } // Pawn Promotion if (position.type.IsPawn()) { if ( position.type == ChessPieceType.WhitePawn && position.coord.y == 0 ) { position.type = ChessPieceType.WhiteQueen; } else if ( position.type == ChessPieceType.BlackPawn && position.coord.y == 7 ) { position.type = ChessPieceType.BlackQueen; } } ret.Add(GameManager.Instance.AdjustBoard ( boardSnapshot, position.type.ToIcon() + " " + from.x + "," + from.y + "-->" + to.x + "," + to.y, new ChessPosition(ChessPieceType.None, from, true), new ChessPosition(position.type, to, true) )); if (isLastMove) { break; } } else { if (boardDict.ContainsKey(to.ToArrayCoord())) { break; } } } to += possibleMoves[j].move; k++; } } } return(ret.ToArray()); }
/// <summary> /// Check whether it's a valid move for the specified piece /// </summary> /// <param name="position">The specified piece's data</param> /// <param name="from">The specified piece's coordinate</param> /// <param name="to">The destination's coordinate</param> /// <param name="specialRule">The special rule used</param> /// <returns> /// TRUE if move is valid. /// </returns> public bool IsValidMove(ChessPosition position, ChessCoordinate from, ChessCoordinate to, out ChessPieceSpecialRule specialRule) { specialRule = ChessPieceSpecialRule.None; ChessPieceMove[] possibleMoves = profilesDict[position.type].possibleMoves; for (int i = 0; i < possibleMoves.Length; i++) { specialRule = possibleMoves[i].specialRule; if (!IsValidSpecialRule(possibleMoves[i].specialRule, position, from, to)) { continue; } ChessCoordinate temp = from + possibleMoves[i].move; int j = 0; while ( temp.IsWithinRange() && (possibleMoves[i].repeatTimes < 0 || j < possibleMoves[i].repeatTimes) ) { if (temp == to) { if (possibleMoves[i].pattern == ChessPieceMovePattern.Normal) { if (piecesDict.ContainsKey(temp.ToArrayCoord())) { if (piecesDict[temp.ToArrayCoord()].Type.IsSameTeamAs(position.type)) { break; } } return(true); } else if (possibleMoves[i].pattern == ChessPieceMovePattern.MoveOnly) { if (piecesDict.ContainsKey(temp.ToArrayCoord())) { break; } return(true); } else if (possibleMoves[i].pattern == ChessPieceMovePattern.CaptureOnly) { if (!piecesDict.ContainsKey(temp.ToArrayCoord())) { break; } if (piecesDict[temp.ToArrayCoord()].Type.IsSameTeamAs(position.type)) { break; } return(true); } } else { if (piecesDict.ContainsKey(temp.ToArrayCoord())) { break; } } temp += possibleMoves[i].move; j++; } } return(false); }
/// <summary> /// Make a move from the latest snapshot (Without generating the next snapshot) /// </summary> /// <param name="from">Current position's coordinate</param> /// <param name="to">Destination position's coordinate</param> /// <param name="resultPositions">The returning result of positions</param> /// <returns> /// TRUE if move is valid. /// </returns> private bool Move(ChessCoordinate from, ChessCoordinate to, out ChessPosition[] resultPositions) { resultPositions = null; if (!from.IsWithinRange()) { Debug.LogWarning("Failed to execute Move.\nReason: (" + from.x + ", " + from.y + ") is not within RANGE."); return(false); } if (!to.IsWithinRange()) { Debug.LogWarning("Failed to execute Move.\nReason: (" + to.x + ", " + to.y + ") is not within RANGE."); return(false); } if (!piecesDict.ContainsKey(from.ToArrayCoord())) { Debug.LogWarning("Failed to execute Move.\nReason: (" + from.x + ", " + from.y + ") is EMPTY."); return(false); } ChessPieceScript selectedPiece = piecesDict[from.ToArrayCoord()]; ChessPieceSpecialRule specialRule = ChessPieceSpecialRule.None; ChessPosition[] castlingPositions; if ( !IsValidMove(selectedPiece.Position, from, to, out specialRule) || !AdditionalMove(specialRule, selectedPiece.Position, out castlingPositions) ) { Debug.LogWarning("Failed to execute Move.\nReason: " + selectedPiece.Type + " (" + from.x + ", " + from.y + ") --> (" + to.x + ", " + to.y + ") is INVALID."); return(false); } selectedPiece.Coord = to; selectedPiece.HasMoved = true; // Pawn Promotion if (selectedPiece.Type.IsPawn()) { if ( selectedPiece.Type == ChessPieceType.WhitePawn && selectedPiece.Coord.y == 0 ) { selectedPiece.Type = ChessPieceType.WhiteQueen; } else if ( selectedPiece.Type == ChessPieceType.BlackPawn && selectedPiece.Coord.y == 7 ) { selectedPiece.Type = ChessPieceType.BlackQueen; } } if (piecesDict.ContainsKey(to.ToArrayCoord())) { Destroy(piecesDict[to.ToArrayCoord()].gameObject); } piecesDict.Remove(from.ToArrayCoord()); piecesDict.Remove(to.ToArrayCoord()); piecesDict.Add(to.ToArrayCoord(), selectedPiece); List <ChessPosition> resultPositionsList = new List <ChessPosition>() { new ChessPosition(ChessPieceType.None, from), new ChessPosition(selectedPiece.Type, to) }; if (castlingPositions != null) { for (int i = 0; i < castlingPositions.Length; i++) { resultPositionsList.Add(castlingPositions[i]); } } resultPositions = resultPositionsList.ToArray(); Debug.Log("Succeeded to execute Move.\n" + selectedPiece.Type + " (" + from.x + ", " + from.y + ") --> (" + to.x + ", " + to.y + ")."); return(true); }