/// <summary> /// Broadcasts the given <paramref name="tiles"/> at the specified coordinates to all active players. /// </summary> /// <param name="players">The player service.</param> /// <param name="x">The top-left tile's X coordinate.</param> /// <param name="y">The top-left tile's Y coordinate.</param> /// <param name="tiles">The tiles to broadcast.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="players"/> or <paramref name="tiles"/> are <see langword="null"/>. /// </exception> /// <exception cref="NotSupportedException"><paramref name="tiles"/> is not square.</exception> public static void BroadcastTiles(this IPlayerService players, int x, int y, ITileSlice tiles) { if (players is null) { throw new ArgumentNullException(nameof(players)); } if (tiles is null) { throw new ArgumentNullException(nameof(tiles)); } if (tiles.Width != tiles.Height) { // TODO: implement this when the section packet is implemented. throw new NotSupportedException("Tiles is not square"); } var packet = new TileSquare { X = (short)x, Y = (short)y, Tiles = tiles }; for (var i = 0; i < players.Count; ++i) { players[i].SendPacket(packet); } }
public void PacketReceive_TileSquarePacket_EventCanceled() { var packet = new TileSquare { X = 100, Y = 256, Tiles = new NetworkTileSlice(3, 3) }; var sender = Mock.Of <IPlayer>(); PacketReceive_EventCanceled <TileSquare, TileSquareEvent>(packet, sender); }
public void PacketReceive_TileSquarePacket_EventTriggered() { var packet = new TileSquare { X = 100, Y = 256, Tiles = new NetworkTileSlice(3, 3) }; var sender = Mock.Of <IPlayer>(); PacketReceive_EventTriggered <TileSquare, TileSquareEvent>(packet, sender, evt => evt.Player == sender && evt.X == 100 && evt.Y == 256 && evt.Tiles.Width == 3 && evt.Tiles.Height == 3); }
/// <summary> /// When any square is clicked, we check if the square is free and it is the player's turn /// And then we place a move and tell the AI to take a turn. /// </summary> /// <param name="square"></param> public void PlayerClickedSquare(GameObject square) { TileSquare tileSquare = square.GetComponent <TileSquare>(); if (nextPlayer == PieceType.player) { if (tileSquare.CurrentPiece == PieceType.none) { PlaceMove(tileSquare, PieceType.player); } } }
/// <summary> /// Creating the original game board. Setting up the squares and saving them. /// </summary> /// <param name="turnSelected">int value to determine if player is first or second</param> public void InitBoard(int turnSelected) { menuScreen.SetActive(false); isPlayerX = turnSelected == 1; dimension = NUM_ROWS_COLS; if (squares == null) { // Setup the inital board squares squares = new TileSquare[dimension][]; for (int i = 0; i < dimension; i++) { squares[i] = new TileSquare[dimension]; for (int j = 0; j < dimension; j++) { TileSquare tileSquare = GameObject.Instantiate(square).GetComponent <TileSquare>(); tileSquare.coords = new Coords(i, j); tileSquare.isPlayerX = isPlayerX; tileSquare.CurrentPiece = PieceType.none; squares[i][j] = tileSquare; tileSquare.transform.SetParent(grid.transform); tileSquare.buttonComponent.onClick.AddListener(() => PlayerClickedSquare(tileSquare.gameObject)); } } } else { for (int i = 0; i < dimension; i++) { for (int j = 0; j < dimension; j++) { TileSquare current = squares[i][j]; current.isPlayerX = isPlayerX; current.CurrentPiece = PieceType.none; } } } // This starts the game if (!isPlayerX) { StartCoroutine(AITurn()); } else { nextPlayer = PieceType.player; } }
public override unsafe void Initialize() { base.Initialize(); GameEngine.firstClick = true; isLost = false; isWon = false; tiles = new Tile[(int)fieldSize.X][][]; for (int i = 0; i < fieldSize.X; i++) { tiles[i] = new Tile[(int)fieldSize.Y][]; for (int j = 0; j < fieldSize.Y; j++) { tiles[i][j] = new Tile[1]; tiles[i][j][0] = new TileSquare(new Vector3(i * 16, j * 16, 0), new Vector3(16, 16, 0)); } } }
private void PlaceMove(TileSquare square, PieceType piece) { square.CurrentPiece = piece; if (CheckForWinner(square)) { GameOver(piece == PieceType.player); } else { prevPlayer = piece; pieceLocations.Add(square); if (piece == PieceType.player) { nextPlayer = PieceType.ai; StartCoroutine(AITurn()); } else { nextPlayer = PieceType.player; } } }
/// <summary> /// Sends the given <paramref name="tiles"/> at the specified coordinates to the player. /// </summary> /// <param name="player">The player.</param> /// <param name="x">The top-left tile's X coordinate.</param> /// <param name="y">The top-left tile's Y coordinate.</param> /// <param name="tiles">The tiles to send.</param> /// <exception cref="ArgumentNullException"> /// <paramref name="player"/> or <paramref name="tiles"/> are <see langword="null"/>. /// </exception> /// <exception cref="NotSupportedException"><paramref name="tiles"/> is not square.</exception> public static void SendTiles(this IPlayer player, int x, int y, ITileSlice tiles) { if (player is null) { throw new ArgumentNullException(nameof(player)); } if (tiles is null) { throw new ArgumentNullException(nameof(tiles)); } if (tiles.Width != tiles.Height) { // TODO: implement this when the section packet is implemented. throw new NotSupportedException("Tiles is not square"); } var packet = new TileSquare { X = (short)x, Y = (short)y, Tiles = tiles }; player.SendPacket(packet); }
public override unsafe void Initialize() { base.Initialize(); GameEngine.firstClick = true; isLost = false; isWon = false; tiles = new Tile[(int)fieldSize.X][][]; for (int i = 0; i < fieldSize.X; i++) { tiles[i] = new Tile[(int)fieldSize.Y][]; for (int j = 0; j < fieldSize.Y; j++) { tiles[i][j] = new Tile[1]; tiles[i][j][0] = new TileSquare(new Vector3(i * 16, j * 16, 0), new Vector3(16, 16, 0)); if (Math.Pow(i - radius + .5, 2) + Math.Pow(j - radius + .5, 2) > radsqr) { tiles[i][j][0].CurrentState = -20; } } } }
/// <summary> /// Use the last move to determine if there was a winner beacuse of it /// </summary> /// <param name="lastMove">the last move made</param> /// <returns></returns> private bool CheckForWinner(TileSquare lastMove) { TileSquare[] row = squares[lastMove.coords.row]; List <TileSquare> col = new List <TileSquare>(); List <TileSquare> rDiag = new List <TileSquare>(); List <TileSquare> lDiag = new List <TileSquare>(); int lowerNum = Mathf.Min(lastMove.coords.row, lastMove.coords.col); Coords diagR = new Coords(lastMove.coords.row - lowerNum, lastMove.coords.col - lowerNum); lowerNum = Mathf.Min(lastMove.coords.row, dimension - lastMove.coords.col - 1); Coords diagL = new Coords(lastMove.coords.row - lowerNum, lastMove.coords.col + lowerNum); int numInARow = 0; for (int i = 0; i < row.Length; i++) { col.Add(squares[i][lastMove.coords.col]); if (diagR.row + i < row.Length && diagR.col + i < row.Length) { rDiag.Add(squares[diagR.row + i][diagR.col + i]); } if (diagL.row + i < row.Length && diagL.col - i >= 0) { lDiag.Add(squares[diagL.row + i][diagL.col - i]); } if (lastMove.CurrentPiece != row[i].CurrentPiece) { numInARow = 0; continue; } numInARow++; if (numInARow == NUM_TO_WIN) { return(true); } } int numInACol = 0; for (int j = 0; j < col.Count; j++) { if (lastMove.CurrentPiece != col[j].CurrentPiece) { numInACol = 0; continue; } numInACol++; if (numInACol == NUM_TO_WIN) { return(true); } } int numInRDiag = 0; if (rDiag.Count >= NUM_TO_WIN) { for (int k = 0; k < rDiag.Count; k++) { if (lastMove.CurrentPiece != rDiag[k].CurrentPiece) { numInRDiag = 0; continue; } numInRDiag++; if (numInRDiag == NUM_TO_WIN) { return(true); } } } int numInLDiag = 0; if (lDiag.Count >= NUM_TO_WIN) { for (int m = 0; m < lDiag.Count; m++) { if (lastMove.CurrentPiece != lDiag[m].CurrentPiece) { numInLDiag = 0; continue; } numInLDiag++; if (numInLDiag == NUM_TO_WIN) { return(true); } } } return(false); }
public void Awake() { //create a memory pointer to the TileMap Tilemap tilemap = GetComponent <Tilemap>(); //creates a memory pointer to the cellBounds component of tilemap BoundsInt bounds = tilemap.cellBounds; //creates an array of pointers to each of the tilemap blocks TileBase[] allTiles = tilemap.GetTilesBlock(bounds); tileInfo = new TileSquare[bounds.size.x, bounds.size.y]; //loop through each position for x for (int x = 0; x < bounds.size.x; x++) { for (int y = 0; y < bounds.size.y; y++) { //find the tile at grid position x,y (this is a 1D array so //there is a conversion process) TileBase tile = allTiles[x + y * bounds.size.x]; //if a tile isn't null then movement costs can be set if (tile != null) { tileInfo[x, y] = new TileSquare(); //if the tile is grassland or plain set move costs as follows if (tile.name.StartsWith("Grass")) { //infantry movement cost tileInfo[x, y].InfCost = 1; //cavalry movement cost tileInfo[x, y].CavCost = 1; //flying unit movement cost tileInfo[x, y].FlyCost = 1; //amphibious unit movement cost tileInfo[x, y].AmphCost = 1; //serpent unit movement cost tileInfo[x, y].SerpCost = 1; } //if the tile is a dwelling, set move costs as follows else if (tile.name.StartsWith("House")) { //infantry movement cost tileInfo[x, y].InfCost = 1; //cavalry movement cost tileInfo[x, y].CavCost = 1; //flying unit movement cost tileInfo[x, y].FlyCost = 1; //amphibious unit movement cost tileInfo[x, y].AmphCost = 1; //serpent unit movement cost tileInfo[x, y].SerpCost = 1; } //if the tile is a single tree/small copse, set move costs as follows else if (tile.name.StartsWith("Tree")) { //infantry movement cost tileInfo[x, y].InfCost = 1; //cavalry movement cost tileInfo[x, y].CavCost = 2; //flying unit movement cost tileInfo[x, y].FlyCost = 1; //amphibious unit movement cost tileInfo[x, y].AmphCost = 1; //serpent unit movement cost tileInfo[x, y].SerpCost = 2; } //if the tile is a dense forest/jungle, set move costs as follows else if (tile.name.StartsWith("forest")) { //infantry movement cost tileInfo[x, y].InfCost = 1; //cavalry movement cost tileInfo[x, y].CavCost = 3; //flying unit movement cost tileInfo[x, y].FlyCost = 1; //amphibious unit movement cost tileInfo[x, y].AmphCost = 1; //serpent unit movement cost tileInfo[x, y].SerpCost = 2; } //if the tile is part of the sea/ocean, set move costs as follows else if (tile.name.StartsWith("Sea")) { //infantry movement cost tileInfo[x, y].InfCost = 3; //cavalry movement cost tileInfo[x, y].CavCost = 3; //flying unit movement cost tileInfo[x, y].FlyCost = 1; //amphibious unit movement cost tileInfo[x, y].AmphCost = 1; //serpent unit movement cost tileInfo[x, y].SerpCost = 3; } //if the tile is part of the beach, set the move cost as follows else if (tile.name.StartsWith("Beach")) { //infantry movement cost tileInfo[x, y].InfCost = 2; //cavalry movement cost tileInfo[x, y].CavCost = 2; //flying unit movement cost tileInfo[x, y].FlyCost = 1; //amphibious unit movement cost tileInfo[x, y].AmphCost = 1; //serpent unit movement cost tileInfo[x, y].SerpCost = 1; } //if the tile is part of the desert, set the move cost as follows else if (tile.name.StartsWith("Desert")) { //infantry movement cost tileInfo[x, y].InfCost = 2; //cavalry movement cost tileInfo[x, y].CavCost = 2; //flying unit movement cost tileInfo[x, y].FlyCost = 1; //amphibious unit movement cost tileInfo[x, y].AmphCost = 1; //serpent unit movement cost tileInfo[x, y].SerpCost = 1; } //if the tile is part of a mountain, set the move cost as follows else if (tile.name.StartsWith("Mountain")) { //infantry movement cost tileInfo[x, y].InfCost = 3; //cavalry movement cost tileInfo[x, y].CavCost = 4; //flying unit movement cost tileInfo[x, y].FlyCost = 1; //amphibious unit movement cost tileInfo[x, y].AmphCost = 4; //serpent unit movement cost tileInfo[x, y].SerpCost = 2; } //if the tile is part of a shallow river, set the move cost as follows else if (tile.name.StartsWith("ShallowRiver")) { //infantry movement cost tileInfo[x, y].InfCost = 2; //cavalry movement cost tileInfo[x, y].CavCost = 1; //flying unit movement cost tileInfo[x, y].FlyCost = 1; //amphibious unit movement cost tileInfo[x, y].AmphCost = 1; //serpent unit movement cost tileInfo[x, y].SerpCost = 2; } //if the tile is part of a deep river, set the move cost as follows else if (tile.name.StartsWith("DeepRiver")) { //infantry movement cost tileInfo[x, y].InfCost = 3; //cavalry movement cost tileInfo[x, y].CavCost = 3; //flying unit movement cost tileInfo[x, y].FlyCost = 1; //amphibious unit movement cost tileInfo[x, y].AmphCost = 1; //serpent unit movement cost tileInfo[x, y].SerpCost = 3; } //if valid tile cannot be found but the tile is not null, something has been named incorrectly //set movement to 900 to make impassable and for location in debug. else { //infantry movement cost tileInfo[x, y].InfCost = 900; //cavalry movement cost tileInfo[x, y].CavCost = 900; //flying unit movement cost tileInfo[x, y].FlyCost = 900; //amphibious unit movement cost tileInfo[x, y].AmphCost = 900; //serpent unit movement cost tileInfo[x, y].SerpCost = 900; Debug.Log("x:" + x + " y:" + y + " tile has been incorrectly named"); } } //if a tile is null (empty), then else { //can be used for debugging null tiles Debug.Log("x:" + x + " y:" + y + " tile: (null)"); } } } }