/// <summary> /// Handles forced way movements for the AI. /// </summary> /// <param name="tower">The piece tower selected</param> /// <param name="moves">The list of way moves available</param> /// <returns></returns> public virtual WeightedMove ForcedWay(PieceTower tower, HashSet <TileNode> moves) { // Random way move int randomIndex = new System.Random().Next(0, moves.Count); return(new WeightedMove(tower, moves.ToArray()[randomIndex], 1)); }
/// <summary> /// Logic for handling the case for way roll on a cross or intersection on the way /// </summary> /// <returns>A thing used for courtine</returns> /// <param name="node">Node.</param> /// <param name="tower">Tower.</param> private IEnumerator WayCrossRoll(TileNode node, PieceTower tower) { // create the picker for player to choose direction on the way WayCrossPicker wcp = new WayCrossPicker(node); // AI picks a random arrow if (players[turnIndex].IsAI) { // AI delay before continuing yield return(new WaitForSeconds(AIPlayer.AIDelay)); // Get a random arrow GameObject arrow = wcp.Arrows[new System.Random().Next(0, wcp.Arrows.Length)]; // Pick the arrow arrow.GetComponent <WayCrossArrowClick>().OnMouseUpAsButton(); } // wait until the user has picked a direction yield return(new WaitUntil(() => wcp.decided == true)); // if resultLine is -1 then somehow the user has not picked a direction Debug.Assert(wcp.resultLine != -1); // Start a roll along StartCoroutine(WayRoll(node, tower, wcp.resultLine)); }
public WeightedMove(PieceTower piece, TileNode dest, int weight, int attackValue) { this.piece = piece; this.dest = dest; this.weight = weight; this.attackValue = attackValue; }
/// <summary> /// /// </summary> /// <param name="src">from this tile</param> /// <param name="dest">to this tile</param> /// <param name="srcMoves">set of legal moves for source tower</param> public PieceMove(TileNode src, MoveSet.Move destMove, HashSet <TileNode> srcMoves) { Debug.Assert(src != null, "PieceMove src is null when creating one"); this.src = src; if (destMove != null) { this.dest = destMove.GetDest(); Debug.Assert(dest != null, "PieceMove dest is null when creating one"); this.destMove = destMove; moves = srcMoves; firstTower = src.tower; secondTower = dest.tower; } }
public override WeightedMove ForcedWay(PieceTower tower, HashSet <TileNode> moves) { // Check if anything is attackable foreach (TileNode tile in moves) { if (tile.tower != null && tile.tower.owningColour != colour) { return(new WeightedMove(tower, tile, 1)); } } // Random move return(base.ForcedWay(tower, moves)); }
//AI makes a random move public WeightedMove RandomMove() { // Get a random piece List <PieceTower> availablePieces = new List <PieceTower>(moves.Keys); PieceTower randomPiece = availablePieces[new System.Random().Next(0, availablePieces.Count)]; // Get a random move from that random piece HashSet <TileNode> randomPieceMoves = new HashSet <TileNode>(randomPiece.GetMoves().Destinations); List <TileNode> randomPieceMovesList = randomPieceMoves.ToList(); // The node to move onto TileNode randomTile = randomPieceMovesList[new System.Random().Next(0, randomPieceMoves.Count)]; return(new WeightedMove(randomPiece, randomTile, 1)); }
/// <summary> /// Checks the value of each move by /// determining each tower's size /// and if they have a hook tile or not /// </summary> /// <returns> attackValue, the nurmerical value of the attac. </returns> /// <param name="piece">Piece of who's value we are determining. </param> public int WeightAttackValue(PieceTower piece) { int attackValue = 0; foreach (PieceData pieceValue in piece.pieces) { if (pieceValue.isHook()) { attackValue += 2; } else { attackValue += 1; } } return(attackValue); }
/// <summary> /// Creates the tower at the given location. /// </summary> /// <param name="colour">Colour of the piece</param> /// <param name="dir">Direction based on hexagon (0 to 5)</param> /// <param name="range">Range of the piece (1 for hook, otherwise 2 or 3)</param> /// <param name="node">TileNode location.</param> private void CreateTower(Player.PlayerColour colour, int dir, int range, TileNode node) { // node must be clear of tower Debug.Assert(node.tower == null); Player player = GetComponentInParent <TurnHandler>().getPlayerByColour(colour); // no player found with colour if (player == null) { return; } // create piece PieceData piece = CreatePiece(colour, dir, range); // create tower at node location owned by player PieceTower tower = new PieceTower(player, piece, node); // add to player player.AddTower(tower); }
/// <summary> /// Attempts to carry out the desired move. /// </summary> /// <returns></returns> public bool Execute() { // check if valid move if (!CheckValid()) { result = ResultType.Failed; return(false); } bool forcedWayMove; bool srcIsWay = src.type == TileNode.Type.Way || src.type == TileNode.Type.WayCross; bool destIsWay = dest.type == TileNode.Type.Way || dest.type == TileNode.Type.WayCross; // determine inital type #region determine move type // same position if (src == dest) { type = MoveType.Move; // move to empty tile } else if (dest.tower == null) { type = MoveType.Move; src.tower.MoveTo(destMove); // attacking move on existing tower } else { PieceTower attacker = src.tower; PieceTower victim = dest.tower; attacker.owningPlayer.capture += victim.pieces.Count; // check attack type if ((dest.type == TileNode.Type.Way || dest.type == TileNode.Type.WayCross) && (src.type == TileNode.Type.Way || src.type == TileNode.Type.WayCross)) { type = MoveType.WayAttack; } else { type = MoveType.Attack; } // Check if this move results in a win if (CheckWin()) { result = ResultType.Win; for (int i = 0; i < victim.pieces.Count; i++) { attacker.AddPiece(victim.pieces[i]); } victim.Die(); attacker.MoveTo(destMove); attacker.owningPlayer.updateScore(); victim.owningPlayer.updateScore(); return(true); } // trigger overstack UI if too many pieces if (victim.pieces.Count + attacker.pieces.Count > 6 || (victim.GetHook() != null && attacker.GetHook() != null)) { // Start the overstack UI and return immediately GameObject.Find("UICanvas").transform.Find("Overstack").GetComponent <OverstackUI>().Construct(attacker, victim); attacker.owningPlayer.HighestTower = 6; } else { // transfer all pieces to attacker for (int i = 0; i < victim.pieces.Count; i++) { attacker.AddPiece(victim.pieces[i]); } victim.Die(); attacker.MoveTo(destMove); } //update tower info attacker.owningPlayer.HighestTower = attacker.pieces.Count; // update scores attacker.owningPlayer.updateScore(); victim.owningPlayer.updateScore(); } #endregion #region checking waymove forcedWayMove = true; // if not moving to way if (!destIsWay) { forcedWayMove = false; } // endturn if moving along way (after way move) if ((srcIsWay && destIsWay) && (src.wayLine == dest.wayLine) && !destMove.hookInvolved) { forcedWayMove = false; } // check for proper forced way if (forcedWayMove) { Debug.Assert(forcedWayMove && destIsWay, "Way conditions did not match"); } #endregion if (result == ResultType.Undetermined) { if (forcedWayMove) { if (dest.type == TileNode.Type.Way) { result = ResultType.ForcedWay; } else { result = ResultType.ForcedWayCross; } } else { result = ResultType.Normal; } } return(true); }
public Board Create() { try { int countNroSquare = 0; #region Square for (int i = 1; i < nroColumn + 1; i++) { if (countNroSquare == 0 || countNroSquare == 16 || countNroSquare == 32 || countNroSquare == 48 || countNroSquare == 64) { colorSquare = colorSquareD; } if (countNroSquare == 8 || countNroSquare == 24 || countNroSquare == 40 || countNroSquare == 56) { colorSquare = colorSquareL; } foreach (string item in Row) { Square squareiitem = new Square { Name = "square" + i + item, PositionY = i.ToString(), PositionX = item, Color = colorSquare, Empty = true }; squareList.Add(squareiitem); if (colorSquare == colorSquareD) { colorSquare = colorSquareL; } else { colorSquare = colorSquareD; } countNroSquare++; } } #endregion #region Piece #region Pawn for (int p = 1; p < ((nroColumn * 2) + 1); p++) { if (nroColumn >= p) { //create piece Pawn Black PiecePawn pawnpcolorB = new PiecePawn { Name = "pawn" + p + colorB, Color = colorB, Dead = false, Img = "♟", }; pieceList.Add(pawnpcolorB); } else { var aux = (p - nroColumn); //create piece Pawn White PiecePawn pawnauxcolorW = new PiecePawn { Name = "pawn" + aux + colorW, Color = colorW, Dead = false, Img = "♙", }; pieceList.Add(pawnauxcolorW); } } #endregion #region Tower //create piece Tower Black PieceTower tower1colorB = new PieceTower { Name = "tower1" + colorB, Color = colorB, Dead = false, Img = "♜", }; PieceTower tower2colorB = new PieceTower { Name = "tower2" + colorB, Color = colorB, Dead = false, Img = "♜", }; pieceList.Add(tower1colorB); pieceList.Add(tower2colorB); //create piece Tower White PieceTower tower1colorW = new PieceTower { Name = "tower1" + colorW, Color = colorW, Dead = false, Img = "♖", }; PieceTower tower2colorW = new PieceTower { Name = "tower2" + colorW, Color = colorW, Dead = false, Img = "♖", }; pieceList.Add(tower1colorW); pieceList.Add(tower2colorW); #endregion #region Bishop //create piece Bishop Black PieceBishop bishop1colorB = new PieceBishop { Name = "bishop1" + colorB, Color = colorB, Dead = false, Img = "♝", }; PieceBishop bishop2colorB = new PieceBishop { Name = "bishop2" + colorB, Color = colorB, Dead = false, Img = "♝", }; pieceList.Add(bishop1colorB); pieceList.Add(bishop2colorB); //create piece Bishop White PieceBishop bishop1colorW = new PieceBishop { Name = "bishop1" + colorW, Color = colorW, Dead = false, Img = "♗", }; PieceBishop bishop2colorW = new PieceBishop { Name = "bishop2" + colorW, Color = colorW, Dead = false, Img = "♗", }; pieceList.Add(bishop1colorW); pieceList.Add(bishop2colorW); #endregion Bishop #region Horse //create piece Horse Black PieceHorse horse1colorB = new PieceHorse { Name = "horse1" + colorB, Color = colorB, Dead = false, Img = "♞", }; PieceHorse horse2colorB = new PieceHorse { Name = "horse2" + colorB, Color = colorB, Dead = false, Img = "♞", }; pieceList.Add(horse1colorB); pieceList.Add(horse2colorB); //create piece Horse White PieceHorse horse1colorW = new PieceHorse { Name = "horse1" + colorW, Color = colorW, Dead = false, Img = "♘", }; PieceHorse horse2colorW = new PieceHorse { Name = "horse2" + colorW, Color = colorW, Dead = false, Img = "♘", }; pieceList.Add(horse1colorW); pieceList.Add(horse2colorW); #endregion #region Queen //create piece queen Black PieceQueen queencolorB = new PieceQueen { Name = "queen" + colorB, Color = colorB, Dead = false, Img = "♛", }; pieceList.Add(queencolorB); //create piece queen White PieceKing queencolorW = new PieceKing { Name = "queen" + colorW, Color = colorW, Dead = false, Img = "♕", }; pieceList.Add(queencolorW); #endregion #region King //create piece king Black PieceKing kingcolorB = new PieceKing { Name = "king" + colorB, Color = colorB, Dead = false, Img = "♚", }; pieceList.Add(kingcolorB); //create piece king White PieceKing kingcolorW = new PieceKing { Name = "king" + colorW, Color = colorW, Dead = false, Img = "♔", }; pieceList.Add(kingcolorW); #endregion #endregion newBoard.Squares = squareList; newBoard.Pieces = pieceList; newBoard = RandomPieces(newBoard); return(newBoard); } catch (Exception ex) { return(null); } }
public void RemoveTower(PieceTower tower) { towers.Remove(tower); }
public WeightedMove(PieceTower piece, TileNode dest, int weight) { this.piece = piece; this.dest = dest; this.weight = weight; }
/// <summary> /// Called when there is a valid finish request from the overstack button. /// Handles the creation of the new tower, and removes all old pieces from the game. /// </summary> /// <param name="pieces">The considered pieces that have been validated.</param> public void Finished(List <PieceData> pieces) { // Reference to the attacking player Player player = GameObject.Find("Taoex").GetComponent <TurnHandler>().getPlayerByColour(attacker.owningColour); PieceData startingPiece = null; HashSet <TileNode> attackerMoves = attacker.GetMoves().Destinations; // Remove references to the selected pieces attacker.RemovePieces(pieces); victim.RemovePieces(pieces); // Pick the first selected attacker piece as the starting piece foreach (PieceData p in pieces) { if (p.colour == player.colour) { startingPiece = p; break; } } Debug.Assert(startingPiece != null, "Starting piece was null"); // Create the new tower PieceTower newTower = new PieceTower(player, startingPiece, destination); newTower.owningPlayer.AddTower(newTower); // Add rest of the pieces foreach (PieceData p in pieces) { if (p != startingPiece) { newTower.AddPiece(p); } } // Clear the UI foreach (Transform ga in transform) { Destroy(ga.gameObject); } // Kill off the extra pieces foreach (PieceData p in attacker.pieces) { // Take extra pieces for scoring if (!pieces.Contains(p)) { player.TakePiece(p); } // Liberate the piece if it's the attacker's colour if (p.colour == attackerColour) { if (p.getObj().GetComponent <PlacementPiece>() != null) { p.getObj().GetComponent <PlacementPiece>().Liberate(); } else { Debug.Log("PlacementPiece script was null, probably testing with sandbox mode"); Destroy(p.getObj()); } } else if (p.type == PieceData.Type.Hook) { // Return hook ReturnHook(p); } else { Destroy(p.getObj()); } } foreach (PieceData p in victim.pieces) { // Take extra pieces for scoring if (!pieces.Contains(p)) { player.TakePiece(p); } // Liberate the piece if it's the attacker's colour if (p.colour == attackerColour) { if (p.getObj().GetComponent <PlacementPiece>() != null) { p.getObj().GetComponent <PlacementPiece>().Liberate(); } else { Debug.Log("PlacementPiece script was null, probably testing with sandbox mode"); Destroy(p.getObj()); } } else if (p.type == PieceData.Type.Hook) { // Return hook ReturnHook(p); } else { Destroy(p.getObj()); } } attacker.Die(); victim.Die(); // Update player status newTower.GetNode().tower = newTower; newTower.updatePosition(); attacker.owningPlayer.updateScore(); victim.owningPlayer.updateScore(); // Reset variables hookConsidered = false; consideredPieces.Clear(); this.newTower = newTower; // Disable the dim effect GameObject.Find("UICanvas").GetComponent <RawImage>().enabled = false; done = true; }
/// <summary> /// Returns the piece to be moved and the destination /// </summary> /// <param name="piece">Piece.</param> /// <param name="dest">Destination.</param> public WeightedMove Move(PieceTower piece, TileNode dest) { return(new WeightedMove(piece, dest, 1)); }
/// <summary> /// if playing state then this is called /// </summary> /// <param name="node">A selected tilenode</param> private void PlayingAction(TileNode node) { // no tile selected if (firstSelection == null) { #region first Selection // check if the selected tower is valid for the player's turn if (node.tower != null && node.tower.owningColour == players[turnIndex].colour) { firstSelection = node; // for a valid tower, highlight the legal moves for it. foreach (TileNode moveTile in node.tower.GetMoves().Destinations) { moveTile.highlight(); } } #endregion // player has selected a tower already (first selection) } else { #region second selection // fix attempt for mystery firstSelection not clearing TileNode cfirstSelection = this.firstSelection; this.firstSelection = null; PieceTower tower = cfirstSelection.tower; moves = tower.GetMoves().Destinations; // unhighlights the legal moves from the first selected tower foreach (TileNode moveTile in moves) { moveTile.unhighlight(); } // request move to the next selected tile. PieceMove requestedMove = new PieceMove(cfirstSelection, tower.GetMoves().GetMoveObject(node), moves); // requestMove.Execute() both validates and execute it. if (requestedMove.Execute() == true) { // add the requested move (its a legal move) to the history moveHistory.Add(requestedMove); GameObject.Find("MoveHistoryPanel").GetComponent <MoveHistoryHandler>().addMove(moveHistory[moveHistory.Count - 1]); // Tower came off of the edge tile if (cfirstSelection.type == TileNode.Type.Edge && requestedMove.dest.type != TileNode.Type.Edge) { placementTiles.Add(cfirstSelection); } StartCoroutine(HandleRequestResult(requestedMove.GetResult(), node, tower)); } // reset the selection firstSelection = null; #endregion } }
/// <summary> /// Handles the result type of a piece move. /// </summary> /// <param name="result">the result type</param> /// <param name="node">the destination node</param> /// <param name="tower">the attacking tower</param> /// <returns></returns> private IEnumerator HandleRequestResult(PieceMove.ResultType result, TileNode node, PieceTower tower) { // Do something based on the result of the way move switch (result) { case PieceMove.ResultType.Normal: // Wait for overstack to finish yield return(new WaitUntil(() => OverstackUI.done)); NextTurn(); break; case PieceMove.ResultType.ForcedWay: // Wait for overstack to finish yield return(new WaitUntil(() => OverstackUI.done)); StartCoroutine(WayRoll(node, tower, node.wayLine)); break; case PieceMove.ResultType.ForcedWayCross: // Wait for overstack to finish yield return(new WaitUntil(() => OverstackUI.done)); StartCoroutine(WayCrossRoll(node, tower)); break; case PieceMove.ResultType.Win: SceneManager.LoadScene("EndMenu"); break; } }
/// <summary> /// Constructor for overstacking. /// Sets up and displays the overstack interface. /// </summary> /// <param name="attacker">The attacking piece</param> /// <param name="victim">The victim piece</param> public void Construct(PieceTower attacker, PieceTower victim) { this.attacker = attacker; this.victim = victim; destination = victim.GetNode(); attackerColour = attacker.owningColour; done = false; // Offset the piece locations float offset = 0f; for (int i = attacker.pieces.Count - 1; i >= 0; i--) { PieceData p = attacker.pieces[i]; // Duplicate the piece onto the canvas GameObject dup = GameObject.Instantiate(p.getObj()); dup.AddComponent <OverstackPieceUI>(); dup.GetComponent <OverstackPieceUI>().Piece = p; dup.transform.SetParent(transform, false); // Position on the screen Vector3 newPos = new Vector3(-250f, 150f - offset, 0f); Vector3 newRot = new Vector3(270f, 120f, 0f); // Flip pieces that are not the same colour as the attacker if (p.colour != attacker.owningColour && p.type != PieceData.Type.Hook) { newPos.y += 25f; newRot = new Vector3(-270f, 60f, 0f); dup.GetComponent <OverstackPieceUI>().Flipped = true; } // Set the position and angles dup.transform.localPosition = newPos; dup.transform.localEulerAngles = newRot; offset += 30f; } // Offset between towers offset += 30f; for (int i = victim.pieces.Count - 1; i >= 0; i--) { PieceData p = victim.pieces[i]; // Duplicate the piece onto the canvas GameObject dup = GameObject.Instantiate(p.getObj()); dup.AddComponent <OverstackPieceUI>(); dup.GetComponent <OverstackPieceUI>().Piece = p; dup.GetComponent <OverstackPieceUI>().Flipped = true; dup.transform.SetParent(transform, false); // Position on the screen Vector3 newPos = new Vector3(-250f, 175f - offset, 0f); Vector3 newRot = new Vector3(-270f, 60f, 0f); // Don't flip hook pieces or pieces that are the same colour as the attacker if (p.type == PieceData.Type.Hook || p.colour == attacker.owningColour) { newPos.y -= 25f; newRot = new Vector3(270f, 120f, 0f); dup.GetComponent <OverstackPieceUI>().Flipped = false; } // Set the location and angles dup.transform.localPosition = newPos; dup.transform.localEulerAngles = newRot; offset += 30; } offsets = new int[] { 0, 25, 50, 75, 100, 125 }; consideredPieces = new LinkedList <OverstackPieceUI>(); // Enable the backdrop and overstack button GameObject.Find("UICanvas").GetComponent <RawImage>().enabled = true; GameObject.Find("UICanvas").transform.Find("DoneOverstackBtn").gameObject.SetActive(true); // Overstacking for AI if (attacker.owningPlayer.IsAI) { StartCoroutine(((AIPlayer)attacker.owningPlayer).AIOverstack()); } }
/// <summary> /// Logic for handling a way roll move along a way line /// </summary> /// <returns>The roll.</returns> /// <param name="node">Node.</param> /// <param name="tower">Tower.</param> /// <param name="wayLineID">Way line ID.</param> private IEnumerator WayRoll(TileNode node, PieceTower tower, int wayLineID) { //moves = tower.GetWayMove(9); // Wait for overstack to finish yield return(new WaitUntil(() => OverstackUI.done)); // Create a way roll dice GameObject diceObj = Instantiate(Resources.Load("Prefabs/UI/WayDice")) as GameObject; // place the way roll dice on the UICanvas diceObj.transform.SetParent(GameObject.Find("UICanvas").transform, false); // Starts the roll DiceRollScript diceScript = diceObj.GetComponent <DiceRollScript>(); StartCoroutine(diceScript.StartRoll()); // wait until roll is complete yield return(new WaitUntil(() => diceScript.RollState == DiceRollScript.State.Ready)); // if the result is -999, some how the diceroll did not reach a result. Debug.Assert(diceObj.GetComponent <DiceRollScript>().Result != -999); // Overstacking onto way cross, fix the reference for the tower if (tower.GetNode() == null) { // Get the new tower tower = GameObject.Find("Overstack").GetComponent <OverstackUI>().NewTower; // Clear reference from overstack interface GameObject.Find("Overstack").GetComponent <OverstackUI>().NewTower = null; } // get moves along the way line with the range from the result of the roll moves = tower.GetWayMove(diceObj.GetComponent <DiceRollScript>().Result, wayLineID).Destinations; // if no moves are avalible or rolled a zero if (moves.Count == 0) { // add move to history moveHistory.Add(new PieceMove(node, tower.GetMoves().GetMoveObject(node), moves)); GameObject.Find("MoveHistoryPanel").GetComponent <MoveHistoryHandler>().addMove(moveHistory[moveHistory.Count - 1]); // reset selection state = State.Playing; firstSelection = null; // move to next player's turn NextTurn(); } else { // highlight the way move options foreach (TileNode wayTile in moves) { wayTile.highlight(); } // set state to special way state state = State.PlayingForceWay; // set first selection to current position firstSelection = node; // If the player is an AI if (players[turnIndex].IsAI) { // AI delay before continuing yield return(new WaitForSeconds(AIPlayer.AIDelay)); // Forced way move for AI StartCoroutine(ForcedWayAction(((AIPlayer)players[turnIndex]).ForcedWay(tower, moves).dest)); } } // destory the dice roll ui game object Destroy(diceObj, 1f); }
/// <summary> /// Adds a tower to this player for scoring. Only used for adding starting towers /// </summary> /// <param name="tower"></param> public void AddTower(PieceTower tower) { towers.Add(tower); }