From 0e6473d7082c4b63dd2f561134d4236f44b1b120 Mon Sep 17 00:00:00 2001 From: sgr Date: Sun, 18 Feb 2024 01:18:12 +0900 Subject: [PATCH] =?UTF-8?q?AI=E3=81=8C=E5=85=88=E6=89=8B=E3=81=AE=E3=81=A8?= =?UTF-8?q?=E3=81=8D=E3=81=AE=E6=8C=99=E5=8B=95=E8=AA=BF=E6=9F=BB=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GameSceneScreen/GameSceneController.cs | 40 +- .../Popup/ConfigPopupController.cs | 10 +- Assets/Scripts/Shogi/Cell.cs | 5 +- Assets/Scripts/Shogi/Piece.cs | 7 +- Assets/Scripts/Utils/Converter.cs | 417 +++++++++--------- 5 files changed, 256 insertions(+), 223 deletions(-) diff --git a/Assets/Scripts/GameSceneScreen/GameSceneController.cs b/Assets/Scripts/GameSceneScreen/GameSceneController.cs index 2b0abd9..ed70acd 100644 --- a/Assets/Scripts/GameSceneScreen/GameSceneController.cs +++ b/Assets/Scripts/GameSceneScreen/GameSceneController.cs @@ -103,7 +103,7 @@ private void SetCells() } } - private async UniTask InitBoard(string boardJsonPath = "", BoardType boardType = BoardType.NoHandicap, bool isBlackTurn = true) + private async UniTask InitBoard(string boardJsonPath = "", BoardType boardType = BoardType.NoHandicap, bool isAIFirst = false) { ClearPieces(); capturePieceAreaData = new CapturePieceAreaData(); @@ -112,7 +112,8 @@ private async UniTask InitBoard(string boardJsonPath = "", BoardType boardType = gameState = new GameState(boardType); gameState.ShowBoard(); battleAI = new RandomAI(); - this.isBlackTurn = isBlackTurn; + this.isBlackTurn = true; + this.isAIFirst = isAIFirst; if (String.IsNullOrEmpty(boardJsonPath)) { @@ -127,7 +128,16 @@ private async UniTask InitBoard(string boardJsonPath = "", BoardType boardType = var piece = Instantiate(piecePrefab, cells[data.y, data.x].transform); piece.GetComponent().sprite = Resources.Load("ShogiUI/Piece/" + data.pieceType); piece.GetComponent().pieceType = PieceData.StrToPieceType(data.pieceType); - piece.GetComponent().piecePotition = new PieceData.PiecePotition(data.x, data.y); + if(isAIFirst) + { + // AIが先手の場合、blackpieceとwhitepieceの配置を逆にする + piece.GetComponent().piecePotition = new PieceData.PiecePotition(8 - data.x, 8 - data.y); + } + else + { + piece.GetComponent().piecePotition = new PieceData.PiecePotition(data.x, data.y); + } + piece.GetComponent().OnClickAction += UniTask.UnityAction(async () => { if (!IsPlayerTurn()) @@ -139,7 +149,7 @@ private async UniTask InitBoard(string boardJsonPath = "", BoardType boardType = } - if (!isBlackTurn) + if (isAIFirst) { await GetAIAction(); } @@ -191,8 +201,8 @@ private async UniTask SelectPiece(Piece piece) return; } - var from = selectedPiece.SqPos; - var to = piece.SqPos; + var from = selectedPiece.SqPos(isAIFirst); + var to = piece.SqPos(isAIFirst); // 合法手かどうかを判定する var move = Util.MakeMove(from, to); @@ -287,15 +297,15 @@ private async UniTask MovePiece(Cell cell, bool isBlack) if (selectedPiece.IsCaptured()) { var pt = Converter.PieceTypeToDropPiece(selectedPiece.pieceType); - var to = cell.SqPos; + var to = cell.SqPos(isAIFirst); move = Util.MakeMoveDrop(pt, to); decidedMove = move; } else { // 盤上の駒を移動する場合 - var from = selectedPiece.SqPos; - var to = cell.SqPos; + var from = selectedPiece.SqPos(isAIFirst); + var to = cell.SqPos(isAIFirst); move = Util.MakeMove(from, to); movePromote = Util.MakeMovePromote(from, to); decidedMove = move; @@ -451,6 +461,7 @@ private Piece GetCapturedPiece(PieceType pieceType, bool isBlack) private bool IsPlayerTurn() { + // 「先手のターンかつAIが後手」「後手のターンかつAIが先手」の場合、プレイヤーは手番を持っている return isBlackTurn != isAIFirst; } @@ -468,9 +479,20 @@ private async UniTask GetAIAction() var to = move.To(); var toX = Converter.SquareToX(to); var toY = Converter.SquareToY(to); + Debug.Log("fromX:" + fromX + " fromY:" + fromY + " toX:" + toX + " toY:" + toY); isPieceSelected = true; + /* + if(isAIFirst) + { + fromX = 8 - fromX; + fromY = 8 - fromY; + toX = 8 - toX; + toY = 8 - toY; + } + */ + // 駒を打つ場合 if (move.IsDrop()) { diff --git a/Assets/Scripts/GameSceneScreen/Popup/ConfigPopupController.cs b/Assets/Scripts/GameSceneScreen/Popup/ConfigPopupController.cs index 6339b98..a7ad102 100644 --- a/Assets/Scripts/GameSceneScreen/Popup/ConfigPopupController.cs +++ b/Assets/Scripts/GameSceneScreen/Popup/ConfigPopupController.cs @@ -15,7 +15,7 @@ public class ConfigPopupController : MonoBehaviour [SerializeField] private Button closeButton; [SerializeField] private Button firstPlayerButton; [SerializeField] private Button secondPlayerButton; - private bool isBlackTurn = true; + private bool isAIFirst = false; public UnityAction action; @@ -96,7 +96,7 @@ private void StartGame() boardType = BoardType.NoHandicap; break; } - action.Invoke(boardJsonPath, boardType, isBlackTurn); + action.Invoke(boardJsonPath, boardType, isAIFirst); ClosePanel(); } @@ -108,7 +108,7 @@ private void ClosePanel() private void ChooseFirstPlayer() { - isBlackTurn = true; + isAIFirst = false; firstPlayerButton.image.color = new Color32(101, 173, 211, 255); secondPlayerButton.image.color = new Color32(255, 255, 255, 255); firstPlayer.text = "▲先手"; @@ -117,7 +117,7 @@ private void ChooseFirstPlayer() private void ChooseSecondPlayer() { - isBlackTurn = false; + isAIFirst = true; firstPlayerButton.image.color = new Color32(255, 255, 255, 255); secondPlayerButton.image.color = new Color32(101, 173, 211, 255); firstPlayer.text = "△後手"; @@ -141,7 +141,7 @@ private void DropdownValueChanged(TMP_Dropdown change) secondPlayerButton.gameObject.SetActive(false); firstPlayer.text = "△後手"; secondPlayer.text = "▲先手"; - isBlackTurn = true; + isAIFirst = true; } } } \ No newline at end of file diff --git a/Assets/Scripts/Shogi/Cell.cs b/Assets/Scripts/Shogi/Cell.cs index df51fa1..c61b32e 100644 --- a/Assets/Scripts/Shogi/Cell.cs +++ b/Assets/Scripts/Shogi/Cell.cs @@ -14,7 +14,10 @@ public class Cell : MonoBehaviour, IPointerClickHandler public int y; public UnityAction OnClickAction; - public Square SqPos => Converter.PosToSquare(x, y); + public Square SqPos(bool isAIFirst) + { + return Converter.PosToSquare(x, y, isAIFirst); + } public void OnPointerClick(PointerEventData eventData) diff --git a/Assets/Scripts/Shogi/Piece.cs b/Assets/Scripts/Shogi/Piece.cs index d099339..ffc0188 100644 --- a/Assets/Scripts/Shogi/Piece.cs +++ b/Assets/Scripts/Shogi/Piece.cs @@ -12,9 +12,12 @@ public class Piece : MonoBehaviour, IPointerClickHandler public UnityAction OnClickAction; public bool isPromoted = false; - public Square SqPos => Converter.PosToSquare(piecePotition.x, piecePotition.y); public GameObject Outline => outline; - + + public Square SqPos(bool isAIFirst) + { + return Converter.PosToSquare(piecePotition.x, piecePotition.y, isAIFirst); + } public void OnPointerClick(PointerEventData eventData) { diff --git a/Assets/Scripts/Utils/Converter.cs b/Assets/Scripts/Utils/Converter.cs index f58e6f5..5779dda 100644 --- a/Assets/Scripts/Utils/Converter.cs +++ b/Assets/Scripts/Utils/Converter.cs @@ -4,215 +4,220 @@ public class Converter { - /// - /// ポジションデータを符号に変換する - /// - /// - /// - /// - /// - public static string PosToSign(int x, int y, bool isBlack = true) - { - string file = ""; - string rank = ""; - if (isBlack) - { - file = (9 - x).ToString(); - rank = NumToKanji(y + 1); - } - else - { - file = (x + 1).ToString(); - rank = NumToKanji(9 - y); - } - - return file + rank; - } - - /// - /// 数字を漢数字に変換する - /// - /// - /// - public static string NumToKanji(int num) - { - switch (num) - { - case 1: - return "一"; - case 2: - return "二"; - case 3: - return "三"; - case 4: - return "四"; - case 5: - return "五"; - case 6: - return "六"; - case 7: - return "七"; - case 8: - return "八"; - case 9: - return "九"; - default: - return ""; - } - } - - /// - /// PieceTypeをMyShogiのPieceに変換する - /// - /// - /// - /// - /// - public static MSPiece PieceTypeToPiece(PieceType pieceType, bool isPromoted) - { - if (isPromoted) - { - switch (pieceType) - { - case PieceType.BlackPawn: - return MSPiece.B_PRO_PAWN; - case PieceType.BlackLance: - return MSPiece.B_PRO_LANCE; - case PieceType.BlackKnight: - return MSPiece.B_PRO_KNIGHT; - case PieceType.BlackSilver: - return MSPiece.B_PRO_SILVER; - case PieceType.BlackRook: - return MSPiece.B_DRAGON; - case PieceType.BlackBishop: - return MSPiece.B_HORSE; - case PieceType.WhitePawn: - return MSPiece.W_PRO_PAWN; - case PieceType.WhiteLance: - return MSPiece.W_PRO_LANCE; - case PieceType.WhiteKnight: - return MSPiece.W_PRO_KNIGHT; - case PieceType.WhiteSilver: - return MSPiece.W_PRO_SILVER; - case PieceType.WhiteRook: - return MSPiece.W_DRAGON; - case PieceType.WhiteBishop: - return MSPiece.W_HORSE; - default: - throw new Exception("Invalid piece type"); - } - } - - switch (pieceType) - { - case PieceType.BlackPawn: - return MSPiece.B_PAWN; - case PieceType.BlackLance: - return MSPiece.B_LANCE; - case PieceType.BlackKnight: - return MSPiece.B_KNIGHT; - case PieceType.BlackSilver: - return MSPiece.B_SILVER; - case PieceType.BlackGold: - return MSPiece.B_GOLD; - case PieceType.BlackRook: - return MSPiece.B_ROOK; - case PieceType.BlackBishop: - return MSPiece.B_BISHOP; - case PieceType.BlackKing: - return MSPiece.B_KING; - case PieceType.WhitePawn: - return MSPiece.W_PAWN; - case PieceType.WhiteLance: - return MSPiece.W_LANCE; - case PieceType.WhiteKnight: - return MSPiece.W_KNIGHT; - case PieceType.WhiteSilver: - return MSPiece.W_SILVER; - case PieceType.WhiteGold: - return MSPiece.W_GOLD; - case PieceType.WhiteRook: - return MSPiece.W_ROOK; - case PieceType.WhiteBishop: - return MSPiece.W_BISHOP; - case PieceType.WhiteKing: - return MSPiece.W_KING; - default: - throw new Exception("Invalid piece type"); - } - } + /// + /// ポジションデータを符号に変換する + /// + /// + /// + /// + /// + public static string PosToSign(int x, int y, bool isBlack = true) + { + string file = ""; + string rank = ""; + if (isBlack) + { + file = (9 - x).ToString(); + rank = NumToKanji(y + 1); + } + else + { + file = (x + 1).ToString(); + rank = NumToKanji(9 - y); + } - public static MSPiece PieceTypeToDropPiece(PieceType pieceType) - { - switch (pieceType) - { - case PieceType.BlackPawn: - case PieceType.WhitePawn: - return MSPiece.PAWN; - case PieceType.BlackLance: - case PieceType.WhiteLance: - return MSPiece.LANCE; - case PieceType.BlackKnight: - case PieceType.WhiteKnight: - return MSPiece.KNIGHT; - case PieceType.BlackSilver: - case PieceType.WhiteSilver: - return MSPiece.SILVER; - case PieceType.BlackGold: - case PieceType.WhiteGold: - return MSPiece.GOLD; - case PieceType.BlackBishop: - case PieceType.WhiteBishop: - return MSPiece.BISHOP; - case PieceType.BlackRook: - case PieceType.WhiteRook: - return MSPiece.ROOK; - default: - throw new Exception("Invalid piece type"); - } - } - - public static PieceType DropPieceToPieceType(MSPiece piece, bool isAIFirst) - { - switch (piece) - { - case MSPiece.PAWN: - return isAIFirst ? PieceType.BlackPawn : PieceType.WhitePawn; - case MSPiece.LANCE: - return isAIFirst ? PieceType.BlackLance : PieceType.WhiteLance; - case MSPiece.KNIGHT: - return isAIFirst ? PieceType.BlackKnight : PieceType.WhiteKnight; - case MSPiece.SILVER: - return isAIFirst ? PieceType.BlackSilver : PieceType.WhiteSilver; - case MSPiece.GOLD: - return isAIFirst ? PieceType.BlackGold : PieceType.WhiteGold; - case MSPiece.BISHOP: - return isAIFirst ? PieceType.BlackBishop : PieceType.WhiteBishop; - case MSPiece.ROOK: - return isAIFirst ? PieceType.BlackRook : PieceType.WhiteRook; - default: - throw new Exception("Invalid piece type"); - } - } + return file + rank; + } + /// + /// 数字を漢数字に変換する + /// + /// + /// + public static string NumToKanji(int num) + { + switch (num) + { + case 1: + return "一"; + case 2: + return "二"; + case 3: + return "三"; + case 4: + return "四"; + case 5: + return "五"; + case 6: + return "六"; + case 7: + return "七"; + case 8: + return "八"; + case 9: + return "九"; + default: + return ""; + } + } - public static Square PosToSquare(int x, int y) - { - var file = (File)(8 - x); - var rank = (Rank)(y); - return Util.MakeSquare(file, rank); - } + /// + /// PieceTypeをMyShogiのPieceに変換する + /// + /// + /// + /// + /// + public static MSPiece PieceTypeToPiece(PieceType pieceType, bool isPromoted) + { + if (isPromoted) + { + switch (pieceType) + { + case PieceType.BlackPawn: + return MSPiece.B_PRO_PAWN; + case PieceType.BlackLance: + return MSPiece.B_PRO_LANCE; + case PieceType.BlackKnight: + return MSPiece.B_PRO_KNIGHT; + case PieceType.BlackSilver: + return MSPiece.B_PRO_SILVER; + case PieceType.BlackRook: + return MSPiece.B_DRAGON; + case PieceType.BlackBishop: + return MSPiece.B_HORSE; + case PieceType.WhitePawn: + return MSPiece.W_PRO_PAWN; + case PieceType.WhiteLance: + return MSPiece.W_PRO_LANCE; + case PieceType.WhiteKnight: + return MSPiece.W_PRO_KNIGHT; + case PieceType.WhiteSilver: + return MSPiece.W_PRO_SILVER; + case PieceType.WhiteRook: + return MSPiece.W_DRAGON; + case PieceType.WhiteBishop: + return MSPiece.W_HORSE; + default: + throw new Exception("Invalid piece type"); + } + } - public static int SquareToX(Square square) - { - var file = (int)square.ToFile(); - return 8 - file; - } - - public static int SquareToY(Square square) - { - var rank = (int)square.ToRank(); - return rank; - } + switch (pieceType) + { + case PieceType.BlackPawn: + return MSPiece.B_PAWN; + case PieceType.BlackLance: + return MSPiece.B_LANCE; + case PieceType.BlackKnight: + return MSPiece.B_KNIGHT; + case PieceType.BlackSilver: + return MSPiece.B_SILVER; + case PieceType.BlackGold: + return MSPiece.B_GOLD; + case PieceType.BlackRook: + return MSPiece.B_ROOK; + case PieceType.BlackBishop: + return MSPiece.B_BISHOP; + case PieceType.BlackKing: + return MSPiece.B_KING; + case PieceType.WhitePawn: + return MSPiece.W_PAWN; + case PieceType.WhiteLance: + return MSPiece.W_LANCE; + case PieceType.WhiteKnight: + return MSPiece.W_KNIGHT; + case PieceType.WhiteSilver: + return MSPiece.W_SILVER; + case PieceType.WhiteGold: + return MSPiece.W_GOLD; + case PieceType.WhiteRook: + return MSPiece.W_ROOK; + case PieceType.WhiteBishop: + return MSPiece.W_BISHOP; + case PieceType.WhiteKing: + return MSPiece.W_KING; + default: + throw new Exception("Invalid piece type"); + } + } + + public static MSPiece PieceTypeToDropPiece(PieceType pieceType) + { + switch (pieceType) + { + case PieceType.BlackPawn: + case PieceType.WhitePawn: + return MSPiece.PAWN; + case PieceType.BlackLance: + case PieceType.WhiteLance: + return MSPiece.LANCE; + case PieceType.BlackKnight: + case PieceType.WhiteKnight: + return MSPiece.KNIGHT; + case PieceType.BlackSilver: + case PieceType.WhiteSilver: + return MSPiece.SILVER; + case PieceType.BlackGold: + case PieceType.WhiteGold: + return MSPiece.GOLD; + case PieceType.BlackBishop: + case PieceType.WhiteBishop: + return MSPiece.BISHOP; + case PieceType.BlackRook: + case PieceType.WhiteRook: + return MSPiece.ROOK; + default: + throw new Exception("Invalid piece type"); + } + } + + public static PieceType DropPieceToPieceType(MSPiece piece, bool isAIFirst) + { + switch (piece) + { + case MSPiece.PAWN: + return isAIFirst ? PieceType.BlackPawn : PieceType.WhitePawn; + case MSPiece.LANCE: + return isAIFirst ? PieceType.BlackLance : PieceType.WhiteLance; + case MSPiece.KNIGHT: + return isAIFirst ? PieceType.BlackKnight : PieceType.WhiteKnight; + case MSPiece.SILVER: + return isAIFirst ? PieceType.BlackSilver : PieceType.WhiteSilver; + case MSPiece.GOLD: + return isAIFirst ? PieceType.BlackGold : PieceType.WhiteGold; + case MSPiece.BISHOP: + return isAIFirst ? PieceType.BlackBishop : PieceType.WhiteBishop; + case MSPiece.ROOK: + return isAIFirst ? PieceType.BlackRook : PieceType.WhiteRook; + default: + throw new Exception("Invalid piece type"); + } + } + + + public static Square PosToSquare(int x, int y, bool isAIFirst) + { + // 筋はMyShogiが右上スタートで、本アプリでは左上スタート[0~8]で表現している。 + + // fileはx座標で、何筋目かを表す。AIが後手番の場合、8-xで変換する必要がある。 + var file = isAIFirst ? (File)x : (File)8 - x; + + // rankはy座標で、何段目かを表す。AIが先手番の場合、8-yで変換する必要がある。 + var rank = isAIFirst ? (Rank)8 - y : (Rank)y; + return Util.MakeSquare(file, rank); + } + + public static int SquareToX(Square square) + { + var file = (int)square.ToFile(); + return 8 - file; + } + + public static int SquareToY(Square square) + { + var rank = (int)square.ToRank(); + return rank; + } } \ No newline at end of file