// Use this for initialization void Start() { highlighter = GetComponent <HighlighterScript>(); highlighter.Disable(); board = FindObjectOfType <BoardManager>(); selectedChessPiece = null; highlightAllMoves = FindObjectOfType <HighlightMoves>(); chessOverlay = GetComponent <UIChessOverlay>(); }
private void MoveChessPiece(int moveSector) { if (moveSector < 0 || moveSector > 24 || board.getPieceInSector(moveSector) != null || selectedChessPiece == null || !selectedChessPiece.AllPossibleMoves()[moveSector]) { Debug.Log("Wrong move: " + selectedChessPiece.Name + " to " + moveSector); return; } board.MoveChessPiece(selectedChessPiece.CurrentSector, moveSector); selectedChessPiece = null; }
private void SelectChessPiece(int selectSector) { if (board.getPieceInSector(selectSector) == null || selectSector < 0 || selectSector > 24) { return; } else if (board.getPieceInSector(selectSector).Owner != board.currentTurn) { return; } selectedChessPiece = board.getPieceInSector(selectSector); }
private void MoveChessPiece(int moveSector) { if (moveSector < 0 || moveSector > 24) { return; } if (selectedChessPiece.AllPossibleMoves()[moveSector]) { board.MoveChessPiece(selectedChessPiece.CurrentSector, moveSector); } selectedChessPiece = null; }
private void SelectChessPiece(int selectSector) { if (board.getPieceInSector(selectSector) == null || selectSector < 0 || selectSector > 24) { return; } else if (board.getPieceInSector(selectSector).Owner != board.currentTurn) { return; } selectedChessPiece = board.getPieceInSector(selectSector); highlightAllMoves.HighlightAllowedMoves(selectedChessPiece.AllPossibleMoves()); }
private void AttackChessPiece(int attackSector) { if (attackSector < 0 || attackSector > 24 || board.getPieceInSector(attackSector) == null) { return; } if (selectedChessPiece.Owner != board.getPieceInSector(attackSector).Owner) { BoardManager.ATTACK_RESULT result = board.AttackChessPiece(selectedChessPiece.CurrentSector, attackSector); if (result == BoardManager.ATTACK_RESULT.Kill) { Debug.Log("Kill"); highlightAllMoves.HideHighlights(); selectedChessPiece = null; } else if (result == BoardManager.ATTACK_RESULT.Push) { bool[] possiblePush = new bool[25]; for (int i = 0; i < 25; i++) { possiblePush[i] = (BoardManager.AreAdiacent(i, attackSector) && board.getPieceInSector(i) == null);; } Debug.Log("Push"); highlightAllMoves.HighlightAllowedMoves(possiblePush); selectedChessPiece = null; } else if (result == BoardManager.ATTACK_RESULT.Counterpush) { bool[] possiblePush = new bool[25]; for (int i = 0; i < 25; i++) { possiblePush[i] = (BoardManager.AreAdiacent(i, selectedChessPiece.CurrentSector) && board.getPieceInSector(i) == null); } Debug.Log("Counterpush"); highlightAllMoves.HighlightAllowedMoves(possiblePush); selectedChessPiece = null; } else if (result == BoardManager.ATTACK_RESULT.Counterkill) { Debug.Log("Counterkill"); highlightAllMoves.HideHighlights(); selectedChessPiece = null; } } }
// Use this for initialization void Start() { //TODO how to change player num (menu) playerNum = 2; //max=4 actionsLeft = 2; waitingForPush = false; pushed = null; startPos = new List <int> [4]; killedPos = new Vector3[4]; if (playerNum == 2) { startPos[0] = new List <int> { 16, 18, 20, 22 }; startPos[1] = new List <int> { 10, 8, 6, 4 }; killedPos[0] = new Vector3(6f, 0, -4f); killedPos[1] = new Vector3(6f, 0, 4f); } else if (playerNum >= 4) { startPos[0] = new List <int> { 17, 18, 19, 20 }; startPos[1] = new List <int> { 5, 6, 7, 8 }; startPos[2] = new List <int> { 11, 12, 13, 14 }; startPos[3] = new List <int> { 1, 2, 23, 24 }; killedPos[0] = new Vector3(-3f, 0, -6f); killedPos[1] = new Vector3(3f, 0, 6f); killedPos[2] = new Vector3(6f, 0, -3f); killedPos[3] = new Vector3(-6f, 0, 3f); } gameChessPieces = new DejarikChessPiece[25]; SpawnAllChessPieces(); UpdateInitialPossibleMoves(); //I choose the first turn randomly currentTurn = Mathf.RoundToInt(Random.value * (playerNum - 1) + 1f); initialized = true; }
public void PushChessPiece(int toSector) { if (!AreAdiacent(pushed.CurrentSector, toSector) || gameChessPieces[toSector] != null) { return; } else { //move mode gameChessPieces[pushed.CurrentSector] = null; pushed.transform.position = GetTileCenter(toSector); pushed.CurrentSector = toSector; gameChessPieces[toSector] = pushed; currentTurn = originalTurn; pushed = null; waitingForPush = false; UpdateAllPossibleMoves(); } }
public void MoveChessPiece(int fromSector, int toSector) { DejarikChessPiece selectedChessPiece = gameChessPieces[fromSector]; if (selectedChessPiece == null) { return; } else { //move mode gameChessPieces[fromSector] = null; selectedChessPiece.transform.position = GetTileCenter(toSector); selectedChessPiece.CurrentSector = toSector; gameChessPieces[toSector] = selectedChessPiece; } TurnCheck(); }
private void SpawnChessPiece(int index, List <GameObject> pieceList, int sector, int player) { Vector3 pos = GetTileCenter(sector); Quaternion rotation = Quaternion.identity; rotation.y = 180; GameObject go = Instantiate(pieceList[index], pos, rotation) as GameObject; pieceList.RemoveAt(index); go.transform.SetParent(transform); DejarikChessPiece pieceScript = go.GetComponent <DejarikChessPiece>(); pieceScript.CurrentSector = sector; pieceScript.Owner = player; activePieces[player - 1].Add(go); gameChessPieces[sector] = pieceScript; pieceScript.board = this; }
private void AttackChessPiece(int attackSector) { if (attackSector < 0 || attackSector > 24 || board.getPieceInSector(attackSector) == null || selectedChessPiece == null || selectedChessPiece.Owner == board.getPieceInSector(attackSector).Owner || !selectedChessPiece.AllPossibleMoves()[attackSector]) { Debug.Log("Wrong move: attack from " + selectedChessPiece.Name + " to " + attackSector); return; } BoardManager.ATTACK_RESULT result = board.AttackChessPiece(selectedChessPiece.CurrentSector, attackSector); if (result == BoardManager.ATTACK_RESULT.Kill) { Debug.Log("Kill"); selectedChessPiece = null; } else if (result == BoardManager.ATTACK_RESULT.Push) { bool[] possiblePush = new bool[25]; for (int i = 0; i < 25; i++) { possiblePush[i] = (BoardManager.AreAdiacent(i, attackSector) && board.getPieceInSector(i) == null);; } Debug.Log("Push"); selectedChessPiece = null; } else if (result == BoardManager.ATTACK_RESULT.Counterpush) { bool[] possiblePush = new bool[25]; for (int i = 0; i < 25; i++) { possiblePush[i] = (BoardManager.AreAdiacent(i, selectedChessPiece.CurrentSector) && board.getPieceInSector(i) == null); } Debug.Log("Counterpush"); selectedChessPiece = null; } else if (result == BoardManager.ATTACK_RESULT.Counterkill) { Debug.Log("Counterkill"); selectedChessPiece = null; } }
public bool Equals(DejarikChessPiece other) { return(other.Name.Equals(Name) && other.Owner == Owner); }
//This is the main Coroutine, executing every "coroutineInterval" instead of every frame private IEnumerator MainCoroutine() { //Build a minmax tree for imperfect, adversarial, stochastic alpha-beta search. //Every max/min node is separated by a chance node. //Some chance nodes have only 1 child, with probability==1 (deterministic movements) //Every turn contains two moves. //Wait for board to initialize while (!board.initialized) { yield return(new WaitForSeconds(2 * coroutineInterval)); } while (!threadInterface.initialized) { yield return(new WaitForSeconds(2 * coroutineInterval)); } DejarikChessPiece[] currentRealState = new DejarikChessPiece[25]; DejarikChessDuD[] state = new DejarikChessDuD[25]; int fromSector = -1; int toSector = -1; while (!board.gameEnded) { //version 1: we wait for our turn to calculate everything. while (board.currentTurn != this.Player_Turn) { yield return(new WaitForSeconds(6 * coroutineInterval)); } if (board.gameEnded) { break; } //We get the current state of the game for (int i = 0; i < 25; i++) { currentRealState[i] = board.getPieceInSector(i); } state = Utilities.Convert(currentRealState); Debug.Log("Collected current state of the game"); fromSector = -1; toSector = -1; //Simulating first move at level 0 bool secondMove = (board.actionsLeft == 1); if (board.waitingForPush && board.currentTurn == Player_Turn) { Debug.Log("Starting search for a push"); threadInterface.StartThread(state, secondMove, board.waitingForPush, state[board.pushed.CurrentSector], board.originalTurn); } else if (board.currentTurn == Player_Turn) { if (secondMove) { Debug.Log("Starting search for second move"); } else { Debug.Log("Starting search for first move"); } threadInterface.StartThread(state, secondMove); } yield return(new WaitForSeconds(30 * coroutineInterval)); while (threadInterface._threadRunning) { yield return(new WaitForSeconds(5 * coroutineInterval)); } fromSector = threadInterface.fromSector; toSector = threadInterface.toSector; Debug.Log("Computation over, move " + state[fromSector].Name + " to sector " + toSector); // the action of the node with value v selectedChessPiece = currentRealState[fromSector]; if (currentRealState[toSector] == null) { if (board.waitingForPush) { PushChessPiece(toSector); } else { MoveChessPiece(toSector); } } else { //attack AttackChessPiece(toSector); } yield return(new WaitForSeconds(6 * coroutineInterval)); } }
public ATTACK_RESULT AttackChessPiece(int fromSector, int toSector) { //check conditions for attack? //attack mode //get stats ready int attack = gameChessPieces[fromSector].Attack; int totalAttack = 0; int defense = gameChessPieces[toSector].Defense; int totalDefense = 0; //roll 1d6 per stat for (int i = 0; i < attack; i++) { totalAttack += Mathf.RoundToInt(Random.value * 5 + 1f); } for (int i = 0; i < defense; i++) { totalDefense += Mathf.RoundToInt(Random.value * 5 + 1f); } int result = totalAttack - totalDefense; if (result >= 7) { //attack beats defense by at least 7, attack kills defense and moves in DejarikChessPiece killedPiece = gameChessPieces[toSector]; killedPiece.transform.position = killedPos[killedPiece.Owner - 1]; killedPiece.Dead(); KillCount(killedPiece.Owner); DejarikChessPiece winnerPiece = gameChessPieces[fromSector]; gameChessPieces[fromSector] = null; winnerPiece.CurrentSector = toSector; winnerPiece.transform.position = GetTileCenter(toSector); gameChessPieces[toSector] = winnerPiece; TurnCheck(); EndCheck(); return(ATTACK_RESULT.Kill); } else if (result > 0) { //attack beats defense by equal or less than 6, push TurnCheck(); if (isAdiacentFree(toSector)) { waitingForPush = true; originalTurn = currentTurn; currentTurn = gameChessPieces[fromSector].Owner; pushed = gameChessPieces[toSector]; } return(ATTACK_RESULT.Push); } else if (result <= 0 && result > -7) { //defense counter pushes attack TurnCheck(); if (isAdiacentFree(fromSector)) { waitingForPush = true; originalTurn = currentTurn; currentTurn = gameChessPieces[toSector].Owner; pushed = gameChessPieces[fromSector]; } return(ATTACK_RESULT.Counterpush); } else { //defense kills attack DejarikChessPiece killedPiece = gameChessPieces[fromSector]; killedPiece.Dead(); killedPiece.transform.position = killedPos[killedPiece.Owner - 1]; KillCount(killedPiece.Owner); gameChessPieces[fromSector] = null; TurnCheck(); EndCheck(); return(ATTACK_RESULT.Counterkill); } }
private void EndCheck() { if (playerNum == 2) { int piecesPlayerOneLeft = 0; DejarikChessPiece playerOneChamp = null; DejarikChessPiece playerTwoChamp = null; int piecesPlayerTwoLeft = 0; for (int i = 0; i < 25; i++) { if (gameChessPieces[i] != null) { if (gameChessPieces[i].Owner == 1) { piecesPlayerOneLeft++; playerOneChamp = gameChessPieces[i]; } else { piecesPlayerTwoLeft++; playerTwoChamp = gameChessPieces[i]; } } } if (piecesPlayerTwoLeft == 1 && piecesPlayerOneLeft == 1) { //Battle to the death bool stillFighting = true; while (stillFighting) { int totalAttack = 0; int totalDefense = 0; int attack = 0; int defense = 0; if (currentTurn == 1) { attack = playerOneChamp.Attack; defense = playerTwoChamp.Defense; } else { attack = playerTwoChamp.Attack; defense = playerOneChamp.Defense; } //roll 1d6 per stat for (int i = 0; i < attack; i++) { totalAttack += Mathf.RoundToInt(Random.value * 5 + 1f); } for (int i = 0; i < defense; i++) { totalDefense += Mathf.RoundToInt(Random.value * 5 + 1f); } int result = totalAttack - totalDefense; if (result >= 7) { //player of current turn wins Debug.Log("Player " + currentTurn + " wins!"); playerWon = currentTurn; stillFighting = false; gameEnded = true; } else if (result <= -7) { //other player wins Debug.Log("Player " + ((currentTurn % playerNum) + 1) + " wins!"); playerWon = ((currentTurn % playerNum) + 1); stillFighting = false; gameEnded = true; } currentTurn = (currentTurn % playerNum) + 1; } } else if (piecesPlayerOneLeft == 0) { //player two wins Debug.Log("Player Two wins!"); playerWon = 2; gameEnded = true; } else if (piecesPlayerTwoLeft == 0) { //player one wins Debug.Log("Player One wins!"); playerWon = 1; gameEnded = true; } } }
// Update is called once per frame void Update() { UpdateHighlight(); if (board.initialized) { for (int i = 0; i < 25; i++) { if (board.getPieceInSector(i) != null) { board.getPieceInSector(i).UpdateCircle(); } } } if (board.gameEnded || (section != -1 && board.getPieceInSector(section) != null)) { if (board.gameEnded) { chessOverlay.ShowEndOverlay(board.playerWon); } else { if (!chessOverlay.isActive) { chessOverlay.ShowChessOverlay(board.getPieceInSector(section).Name); } else if (!chessOverlay.showing.Equals(board.getPieceInSector(section).Name)) { chessOverlay.HideChessOverlay(); chessOverlay.ShowChessOverlay(board.getPieceInSector(section).Name); } } } else { chessOverlay.HideChessOverlay(); } chessOverlay.UpdateTurn(board.currentTurn); if (board.currentTurn != this.Player_Turn) { highlightAllMoves.HideHighlights(); } else if (board.waitingForPush) { highlightAllMoves.HideHighlights(); bool[] possiblePush = new bool[25]; for (int i = 0; i < 25; i++) { possiblePush[i] = (BoardManager.AreAdiacent(i, board.pushed.CurrentSector) && board.getPieceInSector(i) == null); } highlightAllMoves.HighlightAllowedMoves(possiblePush); } if (Input.GetKeyUp(KeyCode.Escape)) { Application.Quit(); } if (Input.GetMouseButtonUp(0)) { if (section != -1 && board.currentTurn == this.Player_Turn) { if (selectedChessPiece == null) { //push chesspiece if (board.waitingForPush) { PushChessPiece(section); } //select chesspiece else { SelectChessPiece(section); } } else if (board.getPieceInSector(section) == null) { //move chesspiece MoveChessPiece(section); } else if (board.getPieceInSector(section).Owner == this.Player_Turn) { SelectChessPiece(section); } else { AttackChessPiece(section); } } else { selectedChessPiece = null; highlightAllMoves.HideHighlights(); } } }
//This is the main Coroutine, executing every "coroutineInterval" instead of every frame private IEnumerator MainCoroutine() { //Build a minmax tree for imperfect, adversarial, stochastic alpha-beta search. //Every max/min node is separated by a chance node. //Some chance nodes have only 1 child, with probability==1 (deterministic movements) //Every turn contains two moves. //Wait for board to initialize while (!board.initialized) { yield return(new WaitForSeconds(2 * coroutineInterval)); } DejarikChessPiece[] currentRealState = new DejarikChessPiece[25]; DejarikChessDuD[] state = new DejarikChessDuD[25]; float v = -2000f; float oldv = v; int fromSector = -1; int toSector = -1; while (!board.gameEnded) { //version 1: we wait for our turn to calculate everything. while (board.currentTurn != this.Player_Turn) { yield return(new WaitForSeconds(5 * coroutineInterval)); } Debug.Log("Starting search"); //We get the current state of the game for (int i = 0; i < 25; i++) { currentRealState[i] = board.getPieceInSector(i); if (board.getPieceInSector(i) != null) { state[i] = new DejarikChessDuD(currentRealState[i].Name, currentRealState[i].Attack, currentRealState[i].Defense, currentRealState[i].Movement, currentRealState[i].CurrentSector, currentRealState[i].Owner, currentRealState[i].pieceType, currentRealState[i].AllPossibleMoves()); } else { state[i] = null; } } //Simulating first move at level 0 float alpha = -1000f; float beta = 1000f; int turnDepth = 0; bool vFound = false; bool secondMove = (board.actionsLeft == 1); if (board.waitingForPush) { int[] possiblePushSectors = BoardManager.AdiacentSectors(board.pushed.CurrentSector); fromSector = board.pushed.CurrentSector; for (int i = 0; i < possiblePushSectors.Length; i++) { if (state[i] == null) { //we can move the piece into sector "i" DejarikChessDuD[] newState = Utilities.FakeMoveChessPiece(state, state[board.pushed.CurrentSector], i); if ((board.originalTurn == Player_Turn && !secondMove) || (board.originalTurn == Enemy_Turn && secondMove)) { //next action is taken by AI v = Utilities.Max(v, MaxValue(newState, turnDepth, secondMove, alpha, beta)); } else { //next action is taken by a Real Person (tm) v = Utilities.Max(v, MinValue(newState, turnDepth, secondMove, alpha, beta)); } if (oldv != v) { toSector = i; } if (v >= beta) { break; } if (v > alpha) { alpha = v; } oldv = v; } } } else { if (DejTree.CutOffTest(state, turnDepth)) //should be false until last move or a certain depth { v = DejTree.Eval(state); } else { v = -420f; int i = 0; for (i = 0; i < 25; i++) { if (state[i] != null && state[i].Owner == Player_Turn) { Debug.Log("Starting to evaluate actions available for piece" + state[i].Name); if (state[i].AllPossibleMoves() == null) { Debug.Log("Possible moves for " + state[i].Name + " are null"); continue; } int j = 0; for (j = 0; j < 25; j++) { if (state[i].AllPossibleMoves()[j]) { if (state[j] == null) { //We are "Moving" the piece to an empty sector. DejarikChessDuD[] newState = Utilities.FakeMoveChessPiece(state, state[i], j); if (secondMove) { //This is the last move of the turn, next move is going to be enemy v = Utilities.Max(v, MinValue(newState, turnDepth + 1, false, alpha, beta)); } else { //next move is still ai, but is the last (second) v = Utilities.Max(v, MaxValue(newState, turnDepth, true, alpha, beta)); } } else { //We are "Attacking" another piece //This is the last move of the turn, next move is going to be enemy v = Utilities.Max(v, ChanceValue(state, i, j, turnDepth, secondMove, alpha, beta, Player_Turn)); } if (oldv != v) { fromSector = i; toSector = j; } if (v >= beta) { //return v; //break out of both cycles and move on vFound = true; break; } if (v > alpha) { alpha = v; } oldv = v; Debug.Log("Finished to evaluate action " + j + " for piece" + state[i].Name); } yield return(new WaitForSeconds(coroutineInterval)); } //I need to return control to Unity Debug.Log("Finished to evaluate actions available for piece" + state[i].Name); yield return(new WaitForSeconds(coroutineInterval)); if (vFound) { break; } } } } } // the action of the node with value v selectedChessPiece = currentRealState[fromSector]; if (currentRealState[toSector] == null) { if (board.waitingForPush) { PushChessPiece(toSector); } else { MoveChessPiece(toSector); } } else { //attack AttackChessPiece(toSector); } } }