// true on tile being 5x5 grid away from wall bool FarFromWall(Coord tile) { if (edgeTiles.Contains(tile)) { return(false); } for (int x = tile.tileX - 2; x <= tile.tileX + 2; x++) { for (int y = tile.tileY - 2; y <= tile.tileY + 2; y++) { if (tile.Equals(new Coord(x, y))) { continue; } if (edgeTiles.Contains(new Coord(x, y))) { return(false); } } } return(true); }
public bool OnMoveEnded() { if (!oldCoord.Equals(coord)) { bool available = GridManager.instance.IsAreaAvailable(coord, GetSize(), gameObject.GetInstanceID()); if (available) { GridManager.instance.UpdateBuilding(this, UpdateType.CHANGE); state = BuildingState.IDLE; GridManager.instance.ClearGrid(); return(true); } else { return(false); } } else { state = BuildingState.IDLE; GridManager.instance.VisualizeGridMap(coord, GetSize(), gameObject.GetInstanceID()); return(true); } }
public override async Task <Move> getMove() { //Get all unit categories List <Coord> units = findAllUnits(); List <Coord> enemies = filterEnemies(units); List <Coord> allies = filterAllies(units); List <Coord> available = filterHasMove(allies); // Select a unit based on type Coord unitCoord = new Coord(0, 0); Unit curUnit = null; foreach (Coord coord in available) { Unit unit = battlefield.units[coord.x, coord.y]; if (unit is HealerUnit) { unitCoord = coord; curUnit = unit; break; } else if (unit is MeleeUnit) { unitCoord = coord; curUnit = unit; } else if (!(curUnit is MeleeUnit)) { unitCoord = coord; curUnit = unit; } } if (curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield).Count == 0 && curUnit.getTargets(unitCoord.x, unitCoord.y, battlefield, character).Count == 0) { return(new Move(unitCoord, unitCoord)); } if (VIPs.Contains(curUnit)) { // Debug.Log("VIP"); // Evade HashSet <Coord> dangerZone = enemyAttackZone(enemies); HashSet <Coord> safeZone = safeMoves(unitCoord, dangerZone); if (safeZone.Count > 0) { int bestScore = Int32.MaxValue; Coord bestCoord = null; foreach (Coord coord in safeZone) { int distScore = sumDistances(coord, allies); if (distScore < bestScore) { bestScore = distScore; bestCoord = coord; } } return(new Move(unitCoord, bestCoord)); } else { int bestScore = 0; Coord bestCoord = null; List <Coord> moves = curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield); moves.Add(unitCoord); foreach (Coord coord in moves) { int distScore = sumDistances(coord, enemies); if (distScore > bestScore) { bestScore = distScore; bestCoord = coord; } } return(new Move(unitCoord, bestCoord)); } } //Decide action based on type if (curUnit is HealerUnit) { Coord bestTarget = null; float bestScore = 0; if (curUnit.hasMovedThisTurn) { foreach (Coord target in curUnit.getTargets(unitCoord.x, unitCoord.y, battlefield, character)) { Unit targetUnit = battlefield.units[target.x, target.y]; float score = targetUnit.maxHealth / targetUnit.getHealth(); if (score > bestScore) { bestTarget = target; bestScore = score; } } return(new Move(unitCoord, bestTarget)); } if (curUnit.getHealth() < curUnit.maxHealth * -0.4) { // TODO // Flee } else { List <Coord> injured = filterInjured(allies, 0.6f); if (injured.Count > 0) { HashSet <Coord> attackZone = curUnit.getTotalAttackZone(unitCoord.x, unitCoord.y, battlefield, character); attackZone.IntersectWith(injured); List <Coord> targets = new List <Coord>(attackZone); if (targets.Count > 0) { bestTarget = null; bestScore = 0; foreach (Coord target in targets) { Unit targetUnit = battlefield.units[target.x, target.y]; float score = targetUnit.maxHealth / targetUnit.getHealth(); if (score > bestScore) { bestTarget = target; bestScore = score; } } // If unit has already moved heal best target if (curUnit.hasMovedThisTurn) { return(new Move(unitCoord, bestTarget)); } // Else choose best tile to move to HashSet <Coord> adjacentTiles = new HashSet <Coord>(); adjacentTiles.Add(new Coord(bestTarget.x + 1, bestTarget.y)); adjacentTiles.Add(new Coord(bestTarget.x - 1, bestTarget.y)); adjacentTiles.Add(new Coord(bestTarget.x, bestTarget.y + 1)); adjacentTiles.Add(new Coord(bestTarget.x, bestTarget.y - 1)); adjacentTiles.IntersectWith(curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield)); // Hardcoded hack for time efficiency if (manhattanDistance(unitCoord, bestTarget) == 1) { adjacentTiles.Add(unitCoord); } Coord bestCoord = null; int tileDef = Int32.MinValue; foreach (Coord coord in adjacentTiles) { if (tileDef < ConstantTables.TileDefense[(int)battlefield.map[coord.x, coord.y].Peek().tileType]) { tileDef = ConstantTables.TileDefense[(int)battlefield.map[coord.x, coord.y].Peek().tileType]; bestCoord = coord; } } if (unitCoord.Equals(bestCoord)) { return(new Move(unitCoord, bestTarget)); } return(new Move(unitCoord, bestCoord)); } else { // Find nearest injured and move to them bestTarget = nearestCoord(unitCoord, injured); Coord bestCoord = nearestCoord(bestTarget, curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield)); return(new Move(unitCoord, bestCoord)); } } else { // Evade around the capture point HashSet <Coord> dangerZone = enemyAttackZone(enemies); HashSet <Coord> safeZone = safeMoves(unitCoord, dangerZone); if (safeZone.Count > 0) { bestScore = Int32.MaxValue; Coord bestCoord = null; foreach (Coord coord in safeZone) { int distScore = manhattanDistance(capturePoint, coord); if (distScore < bestScore) { bestScore = distScore; bestCoord = coord; } } return(new Move(unitCoord, bestCoord)); } else { bestScore = 0; Coord bestCoord = null; List <Coord> moves = curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield); moves.Add(unitCoord); foreach (Coord coord in moves) { int distScore = manhattanDistance(capturePoint, coord); if (distScore > bestScore) { bestScore = distScore; bestCoord = coord; } } return(new Move(unitCoord, bestCoord)); } } } } else if (curUnit is MeleeUnit) { if (curUnit.getHealth() < curUnit.maxHealth * -0.4) { // TODO // Flee } else { // Seek an enemy to attack if health is high HashSet <Coord> attackZone = curUnit.getTotalAttackZone(unitCoord.x, unitCoord.y, battlefield, character); attackZone.IntersectWith(enemies); List <Coord> targets = new List <Coord>(attackZone); float bestScore = 0; Coord bestTarget = null; if (targets.Count > 0) { // If targets are in range find best foreach (Coord target in targets) { Tile enemyTile = battlefield.map[target.x, target.y].Peek(); Unit enemy = battlefield.units[target.x, target.y]; AIBattle battle = new AIBattle(curUnit, enemy, enemyTile, target, battlefield); if (battle.score > bestScore) { bestScore = battle.score; bestTarget = target; } } // If unit has already moved attack best target if (curUnit.hasMovedThisTurn) { return(new Move(unitCoord, bestTarget)); } // Else choose best tile to move to HashSet <Coord> adjacentTiles = new HashSet <Coord>(); adjacentTiles.Add(new Coord(bestTarget.x + 1, bestTarget.y)); adjacentTiles.Add(new Coord(bestTarget.x - 1, bestTarget.y)); adjacentTiles.Add(new Coord(bestTarget.x, bestTarget.y + 1)); adjacentTiles.Add(new Coord(bestTarget.x, bestTarget.y - 1)); adjacentTiles.IntersectWith(curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield)); // Hardcoded hack for time efficiency if (manhattanDistance(unitCoord, bestTarget) == 1) { adjacentTiles.Add(unitCoord); } Coord bestCoord = null; int tileDef = Int32.MinValue; foreach (Coord coord in adjacentTiles) { if (tileDef < ConstantTables.TileDefense[(int)battlefield.map[coord.x, coord.y].Peek().tileType]) { tileDef = ConstantTables.TileDefense[(int)battlefield.map[coord.x, coord.y].Peek().tileType]; bestCoord = coord; } } if (unitCoord.Equals(bestCoord)) { return(new Move(unitCoord, bestTarget)); } return(new Move(unitCoord, bestCoord)); } else { // Move towards defence point List <Coord> moves = curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield); moves.Add(unitCoord); Coord bestCoord = nearestCoord(capturePoint, moves); return(new Move(unitCoord, bestCoord)); } } } else if (curUnit is RangedUnit) { if (curUnit.getHealth() < curUnit.maxHealth * -0.4) { // TODO // Flee } else { // Seek an enemy to attack if health is high HashSet <Coord> attackZone = curUnit.getTotalAttackZone(unitCoord.x, unitCoord.y, battlefield, character); attackZone.IntersectWith(enemies); List <Coord> targets = new List <Coord>(attackZone); float bestScore = 0; Coord bestTarget = null; if (targets.Count > 0) { // If targets are in range find best foreach (Coord target in targets) { Tile enemyTile = battlefield.map[target.x, target.y].Peek(); Unit enemy = battlefield.units[target.x, target.y]; AIBattle battle = new AIBattle(curUnit, enemy, enemyTile, target, battlefield); if (battle.score > bestScore) { bestScore = battle.score; bestTarget = target; } } return(new Move(unitCoord, bestTarget)); } else { // Move towards defence point List <Coord> moves = curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield); moves.Add(unitCoord); Coord bestCoord = nearestCoord(capturePoint, moves); return(new Move(unitCoord, bestCoord)); } } } else if (curUnit is StatusUnit) { if (curUnit.getHealth() < curUnit.maxHealth * -0.4) { // TODO // Flee } else { // Seek an enemy to attack if health is high HashSet <Coord> attackZone = curUnit.getTotalAttackZone(unitCoord.x, unitCoord.y, battlefield, character); attackZone.IntersectWith(enemies); List <Coord> targets = new List <Coord>(attackZone); float bestScore = 0; Coord bestTarget = null; if (targets.Count > 0) { // If targets are in range find best foreach (Coord target in targets) { Tile enemyTile = battlefield.map[target.x, target.y].Peek(); Unit enemy = battlefield.units[target.x, target.y]; AIBattle battle = new AIBattle(curUnit, enemy, enemyTile, target, battlefield); if (battle.score > bestScore) { bestScore = battle.score; bestTarget = target; } } return(new Move(unitCoord, bestTarget)); } else { // Move towards defence point List <Coord> moves = curUnit.getValidMoves(unitCoord.x, unitCoord.y, battlefield); moves.Add(unitCoord); Coord bestCoord = nearestCoord(capturePoint, moves); return(new Move(unitCoord, bestCoord)); } } } //Just so the player can keep track of what's happening await Task.Delay(300); return(new Move()); }
public override bool Equals(object obj) { LivingThing objToLT = ((LivingThing)obj); return(id.Equals(objToLT.id) && position.Equals(objToLT.position)); }
void HandleMovement() { if (!player.isMoving) { player.input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); player.input.Normalize(); // se nao tem input do jogador if (player.input == Vector3.zero) { return; } Coord newPos = new Coord(player.gridPos.r, player.gridPos.c); if (Mathf.Abs(player.input.x) > Mathf.Abs(player.input.z)) { // anda nas linhas if (player.input.x > 0) // ir para baixo { newPos.r = Mathf.Clamp(player.gridPos.r + 1, 0, numRows - 1); } else // ir para cima { newPos.r = Mathf.Clamp(player.gridPos.r - 1, 0, numRows - 1); } } else { // anda nas colunas if (player.input.z > 0) // ir para direita { newPos.c = Mathf.Clamp(player.gridPos.c + 1, 0, numColumns - 1); } else // ir para esquerda { newPos.c = Mathf.Clamp(player.gridPos.c - 1, 0, numColumns - 1); } } // checar se precisa de fato mover if (newPos.Equals(player.gridPos) || tiles[newPos.r, newPos.c].isOccuppied) { return; } // move o player player.isMoving = true; tiles[player.gridPos.r, player.gridPos.c].isOccuppied = false; Vector3 tweenEnd = tiles[newPos.r, newPos.c].transform.position; tweenEnd.y = player.transform.position.y; Go.to(player.transform, player.moveDuration, new GoTweenConfig() .position(tweenEnd) .setEaseType(GoEaseType.BackInOut)) .setOnCompleteHandler(move => { player.isMoving = false; player.gridPos = newPos; tiles[newPos.r, newPos.c].isOccuppied = true; }); } }
public void GeneratorMap() { currentMap = maps[mapIndex]; tileMap = new Transform[currentMap.mapSize.x, currentMap.mapSize.y]; System.Random prng = new System.Random(currentMap.seed); //生成地图坐标 allTileCoords = new List <Coord>(); for (int x = 0; x < currentMap.mapSize.x; x++) { for (int y = 0; y < currentMap.mapSize.y; y++) { allTileCoords.Add(new Coord(x, y)); } } shuffledTileCorrds = new Queue <Coord>(Utility.ShuffleArray(allTileCoords.ToArray(), currentMap.seed)); // string holderName = "GeneratedMap"; if (transform.Find(holderName)) { DestroyImmediate(transform.Find(holderName).gameObject); } Transform mapHolder = new GameObject(holderName).transform; mapHolder.parent = transform; //生成tile for (int x = 0; x < currentMap.mapSize.x; x++) { for (int y = 0; y < currentMap.mapSize.y; y++) { Vector3 tilePosion = CoordsToPosition(x, y); Transform newTile = Instantiate(tilePrefab, tilePosion, Quaternion.Euler(Vector3.right * 90)) as Transform; newTile.localScale = Vector3.one * (1 - outlinePrecent) * tileSize; newTile.parent = mapHolder; tileMap[x, y] = newTile; } } //生成障碍物 bool[,] obstacleMap = new bool[currentMap.mapSize.x, currentMap.mapSize.y]; int obstacleCount = (int)(currentMap.mapSize.x * currentMap.mapSize.y * currentMap.obstaclePercent); int currentObstacleCount = 0; List <Coord> allOpenCoords = new List <Coord>(allTileCoords); for (int i = 0; i < obstacleCount; i++) { Coord randomCoord = GetRandomCoord(); obstacleMap[randomCoord.x, randomCoord.y] = true; currentObstacleCount++; if (!randomCoord.Equals(currentMap.mapCentre) && MapIsFullyAccessible(obstacleMap, currentObstacleCount)) { //高度 float obstacleHeight = Mathf.Lerp(currentMap.minObstacleHeight, currentMap.maxObstacleHeight, (float)prng.NextDouble()); Vector3 obstaclePosition = CoordsToPosition(randomCoord.x, randomCoord.y); Transform newObstacle = Instantiate(obstaclePrefab, obstaclePosition + Vector3.up * obstacleHeight / 2f, Quaternion.identity) as Transform; newObstacle.parent = mapHolder; newObstacle.localScale = new Vector3((1 - outlinePrecent) * tileSize, obstacleHeight, (1 - outlinePrecent) * tileSize); //颜色 Renderer obstacleRender = newObstacle.GetComponent <Renderer>(); Material obstacleMaterial = new Material(obstacleRender.sharedMaterial); float colourPercent = randomCoord.y / (float)currentMap.mapSize.y; obstacleMaterial.color = Color.Lerp(currentMap.foregroundColour, currentMap.backgroundColour, colourPercent); obstacleRender.sharedMaterial = obstacleMaterial; allOpenCoords.Remove(randomCoord); } else { obstacleMap[randomCoord.x, randomCoord.y] = false; currentObstacleCount--; } } shuffledOpenTileCooeds = new Queue <Coord>(Utility.ShuffleArray(allOpenCoords.ToArray(), currentMap.seed)); //生成navmeshMask,阻止抛出地图外 Transform maskLeft = Instantiate(navmeshMaskPre, Vector3.left * (currentMap.mapSize.x + maxMapSize.x) / 4f * tileSize, Quaternion.identity) as Transform; maskLeft.parent = mapHolder; maskLeft.localScale = new Vector3((maxMapSize.x - currentMap.mapSize.x) / 2f, 1, currentMap.mapSize.y) * tileSize; Transform maskRight = Instantiate(navmeshMaskPre, Vector3.right * (currentMap.mapSize.x + maxMapSize.x) / 4f * tileSize, Quaternion.identity) as Transform; maskRight.parent = mapHolder; maskRight.localScale = new Vector3((maxMapSize.x - currentMap.mapSize.x) / 2f, 1, currentMap.mapSize.y) * tileSize; Transform maskTop = Instantiate(navmeshMaskPre, Vector3.forward * (currentMap.mapSize.y + maxMapSize.y) / 4f * tileSize, Quaternion.identity) as Transform; maskTop.parent = mapHolder; maskTop.localScale = new Vector3(maxMapSize.x, 1, (maxMapSize.y - currentMap.mapSize.y) / 2f) * tileSize; Transform maskBottom = Instantiate(navmeshMaskPre, Vector3.back * (currentMap.mapSize.y + maxMapSize.y) / 4f * tileSize, Quaternion.identity) as Transform; maskBottom.parent = mapHolder; maskBottom.localScale = new Vector3(maxMapSize.x, 1, (maxMapSize.y - currentMap.mapSize.y) / 2f) * tileSize; navmeshFloor.localScale = new Vector3(maxMapSize.x, maxMapSize.y) * tileSize; mapFloor.localScale = new Vector3(currentMap.mapSize.x * tileSize, currentMap.mapSize.y * tileSize); }
public void ShouldBeEqual() { Coord coordOne = new Coord(2, 2); Coord CoordTwo = new Coord(2, 2); Assert.IsTrue(coordOne.Equals(CoordTwo)); }
public void Fill(int midY) { if (Halt) { CurrentCommand = null; return; } if (CurrentVoxel != null) { var target = new Coord(CurrentVoxel.X, CurrentVoxel.Y + 1, CurrentVoxel.Z); if (target.Equals(Position)) { CurrentCommand = new Fill(0, -1, 0); CurrentVoxel = null; } else { Move(target.X, target.Y, target.Z); } return; } HashSet <Coord> voxelsToFill; YToVoxels.TryGetValue(Position.Y - 1, out voxelsToFill); if (voxelsToFill == null || voxelsToFill.Count == 0) { var nextY = Position.Y + 1; var shouldStop = !TopMost && nextY >= midY; if (YToVoxels.Count > 0) { shouldStop |= nextY > YToVoxels.Keys.Max() + 1; } if (shouldStop) { CurrentCommand = null; Halt = true; } else { Move(Position.X, nextY, Position.Z); } return; } Coord bestVoxel = null; int bestDistance = int.MaxValue; foreach (var voxel in voxelsToFill) { var candDist = voxel.DistTo(Position); if (bestVoxel == null || candDist < bestDistance) { bestVoxel = voxel; bestDistance = candDist; } } voxelsToFill.Remove(bestVoxel); CurrentVoxel = bestVoxel; CurrentCommand = new Wait(); }
public void GenerateBoard() { allTileCoords = new List <Coord>(); for (int x = 0; x < mapSize.x; x++) { for (int y = 0; y < mapSize.y; y++) { allTileCoords.Add(new Coord(x, y)); } } shuffledTileCords = new Queue <Coord>(Utility.ShuffleArray(allTileCoords.ToArray(), seed)); mapCentre = new Coord((int)mapSize.x / 2, (int)mapSize.y / 2); string holderName = "GeneratedMap"; if (transform.Find(holderName)) { DestroyImmediate(transform.Find(holderName).gameObject); } Transform mapHolder = new GameObject(holderName).transform; mapHolder.parent = transform; for (int x = 0; x < mapSize.x; x++) { for (int y = 0; y < mapSize.y; y++) { Vector3 pos = CoordToPosition(x, y); Transform newGrid = Instantiate(gridPrefab, pos, Quaternion.identity) as Transform; newGrid.localScale = Vector3.one * (1 - borderThickness) * tileSize; newGrid.parent = mapHolder; Utility.RandomColor(ref newGrid); } } bool[,] obstacleMap = new bool[(int)mapSize.x, (int)mapSize.y]; int obstacleCount = (int)(mapSize.x * mapSize.y * obstacleRatio); int currentObstacleCount = 0; for (int i = 0; i < obstacleCount; i++) { Coord randomCoord = GetRandomCoord(); obstacleMap[randomCoord.x, randomCoord.y] = true; currentObstacleCount++; if (!randomCoord.Equals(mapCentre) && MapIsFullyAccessible(obstacleMap, currentObstacleCount)) { Vector3 obstaclePos = CoordToPosition(randomCoord.x, randomCoord.y); Transform newObstacle = Instantiate(obstaclePrefab, obstaclePos + Vector3.back * .5f, Quaternion.identity) as Transform; newObstacle.localScale = Vector3.one * (1 - borderThickness) * tileSize; newObstacle.parent = mapHolder; } else { obstacleMap[randomCoord.x, randomCoord.y] = false; currentObstacleCount--; } } }
private void CreatePath() { Tile currentTile = tileByCoord[startCoord]; List <Tile> alreadyAdded = new List <Tile>(); Stack <Tile> tempPath = new Stack <Tile>(); tempPath.Push(currentTile); alreadyAdded.Add(currentTile); int failTimer = 0; while (currentTile != tileByCoord[endCoord]) { failTimer++; for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { Coord neighbourPos = new Coord(currentTile.Position.X - x, currentTile.Position.Y - y); if (IsInMap(neighbourPos) && tileByCoord[neighbourPos].IsWalkable && !neighbourPos.Equals(startCoord) && !neighbourPos.Equals(currentTile.Position) && IsVerticalOrHorizontal(x, y) && !alreadyAdded.Contains(tileByCoord[new Coord(neighbourPos.X, neighbourPos.Y)])) { Tile neighbour = tileByCoord[new Coord(neighbourPos.X, neighbourPos.Y)]; alreadyAdded.Add(neighbour); tempPath.Push(neighbour); currentTile = neighbour; } } } if (failTimer > 200) { Debug.Log("PATH GENERATION FAILED. Check Tiles + Start + End"); break; } } path = tempPath; }
public bool IsHere(Coord c) { return(c.Equals(Coord)); }
public bool Equals(PathAggregator other) { return(Coord.Equals(other.Coord)); }