private void DumpMapToScreen(TileState[,] map) { for (var i = 0; i < map.GetLength(1); i++) { var sb = new StringBuilder(); for (var j = 0; j < map.GetLength(0); j++) { switch (map[j, i]) { case TileState.Sand: sb.Append("."); break; case TileState.Clay: sb.Append("#"); break; case TileState.FlowingWater: sb.Append("|"); break; case TileState.StillWater: sb.Append("~"); break; } } Console.WriteLine(sb.ToString()); } }
public static bool IsTilePlayable(TileState[,] board, IndexPair index, TileState turnTo, int directionZ, int directionX, int depth) { if (index.z + (directionZ * depth) >= board.GetLength(0)) { return(false); } if (index.x + (directionX * depth) >= board.GetLength(1)) { return(false); } if (index.z + (directionZ * depth) < 0) { return(false); } if (index.x + (directionX * depth) < 0) { return(false); } switch (turnTo) { case TileState.Black: if (board[index.z + (directionZ * depth), index.x + (directionX * depth)] == TileState.Black && depth > 1) { return(true); } else if (board[index.z + (directionZ * depth), index.x + (directionX * depth)] == TileState.White) { return(IsTilePlayable(board, index, turnTo, directionZ, directionX, ++depth)); } else { return(false); } case TileState.White: if (board[index.z + (directionZ * depth), index.x + (directionX * depth)] == TileState.White && depth > 1) { return(true); } else if (board[index.z + (directionZ * depth), index.x + (directionX * depth)] == TileState.Black) { return(IsTilePlayable(board, index, turnTo, directionZ, directionX, ++depth)); } else { return(false); } case TileState.Empty: Debug.LogError("Empty tile should not be tested as playable."); break; default: break; } return(false); }
//Returns a copy of a board public static TileState[,] CopyBoard(TileState[,] board) { TileState[,] result = new TileState[board.GetLength(0), board.GetLength(1)]; for (int i = 0; i < board.GetLength(1); i++) { for (int j = 0; j < board.GetLength(0); j++) { result[j, i] = board[j, i]; } } return(result); }
public static TileState[,] CloneBoardState(TileState[,] boardState) { TileState[,] clonedBoard = new TileState[boardState.GetLength(0), boardState.GetLength(1)]; for (int i = 0; i < boardState.GetLength(0); i++) { for (int j = 0; j < boardState.GetLength(1); j++) { clonedBoard[i, j] = boardState[i, j]; } } return(clonedBoard); }
public static bool IsBoardPlayable(TileState[,] board, TileState colorCheck) { for (int i = 0; i < board.GetLength(1); i++) { for (int j = 0; j < board.GetLength(0); j++) { if (IsTilePlayable(board, new IndexPair(j, i), colorCheck)) { return(true); } } } return(false); }
public static bool IsTilePlayable(TileState[,] board, IndexPair index, TileState turnTo) { if (index.z >= board.GetLength(0)) { return(false); } if (index.x >= board.GetLength(1)) { return(false); } if (board[index.z, index.x] != TileState.Empty) { return(false); } if (IsTilePlayable(board, index, turnTo, 0, 1, 1)) { return(true); } if (IsTilePlayable(board, index, turnTo, 1, 1, 1)) { return(true); } if (IsTilePlayable(board, index, turnTo, 1, 0, 1)) { return(true); } if (IsTilePlayable(board, index, turnTo, 1, -1, 1)) { return(true); } if (IsTilePlayable(board, index, turnTo, 0, -1, 1)) { return(true); } if (IsTilePlayable(board, index, turnTo, -1, -1, 1)) { return(true); } if (IsTilePlayable(board, index, turnTo, -1, 0, 1)) { return(true); } if (IsTilePlayable(board, index, turnTo, -1, 1, 1)) { return(true); } return(false); }
public static List <IndexPair> GetPlayableTiles(TileState[,] board, TileState colorCheck) { List <IndexPair> playableTiles = new List <IndexPair>(); for (int i = 0; i < board.GetLength(1); i++) { for (int j = 0; j < board.GetLength(0); j++) { if (IsTilePlayable(board, new IndexPair(j, i), colorCheck)) { playableTiles.Add(new IndexPair(j, i)); } } } return(playableTiles); }
public static IndexPair CalculateMove(TileState[,] board, TileState color, int depth) { Debug.Log("Starting MiniMax-search for " + color + "..."); int alpha = int.MinValue; int beta = int.MaxValue; List <IndexPair> availableMoves = Judge.GetPlayableTiles(board, color); if (availableMoves.Count == 0) { return(new IndexPair(board.GetLength(0), board.GetLength(1))); } IndexPair moveToReturn = availableMoves[0]; for (int i = 1; i < availableMoves.Count; i++) { switch (color) { case TileState.Black: int maxValue = MiniMax(Judge.SimulateTurn(board, availableMoves[0], color), TileState.White, depth - 1, alpha, beta); if (MiniMax(Judge.SimulateTurn(board, availableMoves[i], color), TileState.White, depth - 1, alpha, beta) > maxValue) { moveToReturn = availableMoves[i]; } break; case TileState.White: int minValue = MiniMax(Judge.SimulateTurn(board, availableMoves[0], color), TileState.Black, depth - 1, alpha, beta); if (MiniMax(Judge.SimulateTurn(board, availableMoves[i], color), TileState.Black, depth - 1, alpha, beta) < minValue) { moveToReturn = availableMoves[i]; } break; default: Debug.LogError("Color not valid."); break; } } Debug.Log("Nodes examined: " + nodeCount); Debug.Log("Depth reached: " + depthReached); Debug.Log("MiniMax-search done."); depthReached = 10; nodeCount = 0; return(moveToReturn); }
public Coordinate NextShot(TileState[,] gameBoard) { // board is always square if (gameBoard.GetLength(0) != gameBoard.GetLength(1)) { throw new ArgumentOutOfRangeException($"gameBoard must have square dimentions " + $"not {gameBoard.GetLength(0)} by {gameBoard.GetLength(1)}"); } if (gameBoard.GetLength(0) != _boardSize) { throw new ArgumentException("gameBoard is not the same as the size provided in constructor"); } Random rnd = new Random(); Coordinate randomCoordinate = ValidTiles[rnd.Next(ValidTiles.Count)]; ValidTiles.Remove(randomCoordinate); return(randomCoordinate); }
private int GetScore(TileState[,] map) { var totalTrees = 0; var totalLumber = 0; for (var i = 0; i < map.GetLength(0); i++) { for (var j = 0; j < map.GetLength(1); j++) { if (map[i, j] == TileState.Trees) { totalTrees++; } else if (map[i, j] == TileState.Lumber) { totalLumber++; } } } return(totalTrees * totalLumber); }
public static int EvaluateBoard(TileState[,] board, TileState color) { int nrOfWhites = 0, nrOfBlacks = 0; for (int i = 0; i < board.GetLength(1); i++) { for (int j = 0; j < board.GetLength(0); j++) { if (board[j, i] == TileState.Black) { nrOfBlacks++; } else if (board[j, i] == TileState.White) { nrOfWhites++; } } } int evalValue = nrOfBlacks - nrOfWhites; return(evalValue); }
public static List <int[]> FindWinningMoves(TileState[,] boardState, Player player) { List <int[]> winningMoves = new List <int[]>(); for (int i = 0; i < boardState.GetLength(0); i++) { for (int j = 0; j < boardState.GetLength(1); j++) { Move move = new Move(i, j, player); if (boardState[i, j] == TileState.EMPTY) { TileState[,] newBoard = MakeMove(boardState, move); if (CheckPlayerWin(newBoard, player)) { winningMoves.Add(new int[2] { i, j }); } } } } return(winningMoves); }
private TileState[] GetNeighbours(TileState[,] map, int x, int y) { var points = new List <(int x, int y)> { (x - 1, y), (x - 1, y - 1), (x, y - 1), (x + 1, y - 1), (x + 1, y), (x + 1, y + 1), (x, y + 1), (x - 1, y + 1), }.Where(it => it.x >= 0 && it.x < map.GetLength(0) && it.y >= 0 && it.y < map.GetLength(1)) .Select(it => map[it.x, it.y]).ToArray(); return(points); }
public static List <int[]> FindEdges(TileState[,] boardState) { int s = boardState.GetLength(0); List <int[]> edgeTiles = new List <int[]>(); for (int i = 0; i < s; i++) { for (int j = 0; j < s; j++) { if (IsEdgeTile(boardState, i, j)) { edgeTiles.Add(new int[] { i, j }); } } } return(edgeTiles); }
public static List <int[]> FindCorners(TileState[,] boardState) { int s = boardState.GetLength(0) - 1; return(new List <int[]>() { new int[2] { 0, 0 }, new int[2] { 0, s }, new int[2] { s, 0 }, new int[2] { s, s }, }); }
//NOTE: pass in real-world positions into here- not array positions, we will convert from real-world to array in the function private IEnumerator FindPathCoroutine(Vector2 givenStartPosition, Vector2 givenEndPosition, TileState[,] givenPathfindingMap) { m_start = new Vector2(Mathf.RoundToInt(givenStartPosition.x / m_tileSize), Mathf.RoundToInt(givenStartPosition.y / m_tileSize)); m_end = new Vector2(Mathf.RoundToInt(givenEndPosition.x / m_tileSize), Mathf.RoundToInt(givenEndPosition.y / m_tileSize)); m_visitedTiles = new int[givenPathfindingMap.GetLength(0), givenPathfindingMap.GetLength(1)]; m_openTiles = new List <Tile>(); m_startTile = new Tile(); m_endTile = new Tile(); m_startTile.m_position = m_start; m_endTile.m_position = m_end; m_currentTile = m_startTile; m_visitedTiles[(int)m_currentTile.m_position.x, (int)m_currentTile.m_position.y] = 1; m_iterationCount = 0; while (m_currentTile.m_position != m_endTile.m_position) { m_iterationCount++; m_cheapestTileCost = float.MaxValue; foreach (Tile tile in FindAdjacentTiles(m_currentTile, m_endTile, givenPathfindingMap)) { bool tileAlreadyExists = false; for (int i = 0; i < m_openTiles.Count; i++) { //if the tile already exists if (m_openTiles[i].m_position == tile.m_position) { m_openTiles[i].m_pathCost = tile.m_pathCost; tileAlreadyExists = true; } } if (!tileAlreadyExists) { m_openTiles.Insert(0, tile); //put at front of list, as recently looked at adjacent tiles are likely to be most efficient to be looked at next } } foreach (Tile tile in m_openTiles) { if ((tile.m_pathCost + (int)tile.m_directDistance) < m_cheapestTileCost) { m_cheapestTileCost = tile.m_pathCost + (int)tile.m_directDistance; m_currentTile = tile; } } m_visitedTiles[(int)m_currentTile.m_position.x, (int)m_currentTile.m_position.y] = 1; m_openTiles.Remove(m_currentTile); if (m_iterationCount > 100) //this prevents too much work being carried out in one frame, so the game won't freeze { m_iterationCount = 0; yield return(null); } if (m_openTiles.Count == 0) //explored all tiles, means we've tried to get to a blocked area { m_pathfindingInformation = new PathfindingInformation(); m_pathfindingInformation.m_canReachTile = false; StopCoroutine("FindPathCoroutine"); } } }
private bool IsWithinMapBounds(int givenX, int givenY) { return(givenX >= 0 && givenX < m_pathfindingMap.GetLength(0) && givenY >= 0 && givenY < m_pathfindingMap.GetLength(1)); }
public static bool SimulateLane(TileState[,] board, IndexPair index, TileState turnTo, int directionZ, int directionX, int depth) { int z = index.z + (directionZ * depth); int x = index.x + (directionX * depth); if (z >= board.GetLength(0)) { return(false); } if (x >= board.GetLength(1)) { return(false); } if (z < 0) { return(false); } if (x < 0) { return(false); } switch (turnTo) { case TileState.Black: if (board[z, x] == TileState.Empty) { return(false); } if (board[z, x] == TileState.Black && depth > 1) { return(true); } if (board[z, x] == TileState.White) { if (SimulateLane(board, index, turnTo, directionZ, directionX, ++depth)) { board[z, x] = TileState.Black; return(true); } else { return(false); } } break; case TileState.White: if (board[z, x] == TileState.Empty) { return(false); } if (board[z, x] == TileState.White && depth > 1) { return(true); } if (board[z, x] == TileState.Black) { if (SimulateLane(board, index, turnTo, directionZ, directionX, ++depth)) { board[z, x] = TileState.White; return(true); } else { return(false); } } break; case TileState.Empty: Debug.LogError("Empty tile should not be tested as playable."); break; default: break; } return(false); }
public static bool IsEdgeTile(TileState[,] boardState, int x, int y) { int s = boardState.GetLength(0) - 1; return(x == 0 || y == 0 || x == s || y == s); }
public static bool IsInBounds(TileState[,] boardState, int x, int y) { return(x >= 0 && x < boardState.GetLength(0) && y >= 0 && y < boardState.GetLength(0)); }
public static Player GetWinner(TileState[,] boardState, out List <int[]> winningCoords) { int size = boardState.GetLength(0); winningCoords = new List <int[]>(); List <int[]> tileSet = new List <int[]>(); // Check rows for (int r = 0; r < size; r++) { tileSet.Clear(); TileState lead = TileState.EMPTY; bool win = true; for (int c = 0; c < size; c++) { tileSet.Add(new int[2] { c, r }); // Winning rows can't have empty tiles if (boardState[c, r] == TileState.EMPTY) { win = false; break; } // Get the leader from first tile in row if (c == 0) { lead = boardState[c, r]; } else if (boardState[c, r] != lead) { // No win if tile doesn't match lead win = false; break; } } // Win check for row if (win && lead != TileState.EMPTY) { winningCoords = tileSet; return((Player)lead); } } // Check Columns for (int c = 0; c < size; c++) { tileSet.Clear(); TileState leadState = TileState.EMPTY; bool win = true; for (int r = 0; r < size; r++) { tileSet.Add(new int[2] { c, r }); // Winning columns can't have empty tiles if (boardState[c, r] == TileState.EMPTY) { win = false; break; } // Get the leader from the first tile in column if (r == 0) { leadState = boardState[c, r]; } // No win possible if tile doesn't match the lead else if (boardState[c, r] != leadState) { win = false; break; } } // Win check for column if (win && leadState != TileState.EMPTY) { winningCoords = tileSet; return((Player)leadState); } } // Check first diagonal tileSet.Clear(); TileState d1Lead = TileState.EMPTY; bool d1Win = true; for (int d = 0; d < size; d++) { tileSet.Add(new int[2] { d, d }); // Get the diagonal lead if (d == 0) { d1Lead = boardState[d, d]; // No win if first tile is empty if (d1Lead == TileState.EMPTY) { d1Win = false; break; } } // No win if other diagonal tiles don't match else if (boardState[d, d] != d1Lead) { d1Win = false; break; } } if (d1Win && d1Lead != TileState.EMPTY) { winningCoords = tileSet; return((Player)d1Lead); } // Check second diagonal tileSet.Clear(); TileState d2Lead = TileState.EMPTY; bool d2Win = true; for (int d = 0; d < size; d++) { tileSet.Add(new int[2] { size - (d + 1), d }); // Get the diagonal lead if (d == 0) { d2Lead = boardState[size - (d + 1), d]; // No win if first tile is empty if (d2Lead == TileState.EMPTY) { d2Win = false; break; } } // No win if other diagonal tiles don't match else if (boardState[size - (d + 1), d] != d2Lead) { d2Win = false; break; } } if (d2Win && d2Lead != TileState.EMPTY) { winningCoords = tileSet; return((Player)d2Lead); } // If the board is full, whoever has the most tiles wins if (CheckFull(boardState)) { List <int[]> p1Tiles = new List <int[]>(); List <int[]> p2Tiles = new List <int[]>(); for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { if (boardState[i, j] == TileState.P1) { p1Tiles.Add(new int[2] { i, j }); } else if (boardState[i, j] == TileState.P2) { p2Tiles.Add(new int[2] { i, j }); } } } int p1Score = p1Tiles.Count; int p2Score = p2Tiles.Count; if (p1Score + p2Score == size * size) { if (p1Score > p2Score) { winningCoords = p1Tiles; return(Player.P1); } else if (p2Score > p1Score) { winningCoords = p2Tiles; return(Player.P2); } } } // If we get here, there is no winner return(Player.NONE); }