|
12 | 12 |
|
13 | 13 | package bwem; |
14 | 14 |
|
| 15 | +import bwapi.Game; |
15 | 16 | import bwapi.TilePosition; |
16 | 17 | import bwapi.WalkPosition; |
17 | 18 | import bwem.util.CheckMode; |
18 | 19 |
|
19 | | -public abstract class TerrainData { |
| 20 | +import java.util.ArrayList; |
| 21 | +import java.util.List; |
| 22 | + |
| 23 | +public final class TerrainData { |
20 | 24 | private final MapData mapData; |
21 | 25 | private final TileData tileData; |
22 | 26 |
|
@@ -78,4 +82,113 @@ boolean isSeaWithNonSeaNeighbors(final WalkPosition walkPosition) { |
78 | 82 |
|
79 | 83 | return false; |
80 | 84 | } |
| 85 | + |
| 86 | + void markUnwalkableMiniTiles(final Game game) { |
| 87 | + // Mark unwalkable minitiles (minitiles are walkable by default). |
| 88 | + for (int y = 0; y < getMapData().getWalkSize().getY(); ++y) |
| 89 | + for (int x = 0; x < getMapData().getWalkSize().getX(); ++x) { |
| 90 | + if (!game.isWalkable(x, y)) { |
| 91 | + // For each unwalkable minitile, we also mark its 8 neighbors as not walkable. |
| 92 | + // According to some tests, this prevents from wrongly pretending one marine can go by |
| 93 | + // some thin path. |
| 94 | + for (int dy = -1; dy <= 1; ++dy) |
| 95 | + for (int dx = -1; dx <= 1; ++dx) { |
| 96 | + final WalkPosition walkPosition = new WalkPosition(x + dx, y + dy); |
| 97 | + if (getMapData().isValid(walkPosition)) { |
| 98 | + getMiniTile(walkPosition, CheckMode.NO_CHECK).setWalkable(false); |
| 99 | + } |
| 100 | + } |
| 101 | + } |
| 102 | + } |
| 103 | + } |
| 104 | + |
| 105 | + void markBuildableTilesAndGroundHeight(final Game game) { |
| 106 | + // Mark buildable tiles (tiles are unbuildable by default). |
| 107 | + for (int y = 0; y < getMapData().getTileSize().getY(); ++y) |
| 108 | + for (int x = 0; x < getMapData().getTileSize().getX(); ++x) { |
| 109 | + final TilePosition tilePosition = new TilePosition(x, y); |
| 110 | + final WalkPosition walkPosition = tilePosition.toWalkPosition(); |
| 111 | + final Tile tile = getTile(tilePosition); |
| 112 | + |
| 113 | + if (game.isBuildable(tilePosition, false)) { |
| 114 | + tile.setBuildable(); |
| 115 | + |
| 116 | + // Ensures buildable ==> walkable. |
| 117 | + for (int dy = 0; dy < 4; ++dy) |
| 118 | + for (int dx = 0; dx < 4; ++dx) { |
| 119 | + getMiniTile(walkPosition.add(new WalkPosition(dx, dy)), CheckMode.NO_CHECK) |
| 120 | + .setWalkable(true); |
| 121 | + } |
| 122 | + } |
| 123 | + |
| 124 | + // Add ground height and doodad information. |
| 125 | + final int bwapiGroundHeight = game.getGroundHeight(tilePosition); |
| 126 | + tile.setGroundHeight(bwapiGroundHeight / 2); |
| 127 | + if (bwapiGroundHeight % 2 != 0) { |
| 128 | + tile.setDoodad(); |
| 129 | + } |
| 130 | + } |
| 131 | + } |
| 132 | + |
| 133 | + void decideSeasOrLakes() { |
| 134 | + for (int y = 0; y < getMapData().getWalkSize().getY(); ++y) |
| 135 | + for (int x = 0; x < getMapData().getWalkSize().getX(); ++x) { |
| 136 | + final WalkPosition originWalkPosition = new WalkPosition(x, y); |
| 137 | + final MiniTile originMiniTile = getMiniTile(originWalkPosition, CheckMode.NO_CHECK); |
| 138 | + |
| 139 | + if (originMiniTile.isSeaOrLake()) { |
| 140 | + final List<WalkPosition> toSearch = new ArrayList<>(); |
| 141 | + toSearch.add(originWalkPosition); |
| 142 | + |
| 143 | + final List<MiniTile> seaExtent = new ArrayList<>(); |
| 144 | + originMiniTile.setSea(); |
| 145 | + seaExtent.add(originMiniTile); |
| 146 | + |
| 147 | + int topLeftX = originWalkPosition.getX(); |
| 148 | + int topLeftY = originWalkPosition.getY(); |
| 149 | + int bottomRightX = originWalkPosition.getX(); |
| 150 | + int bottomRightY = originWalkPosition.getY(); |
| 151 | + |
| 152 | + while (!toSearch.isEmpty()) { |
| 153 | + final WalkPosition current = toSearch.remove(toSearch.size() - 1); |
| 154 | + if (current.getX() < topLeftX) topLeftX = current.getX(); |
| 155 | + if (current.getY() < topLeftY) topLeftY = current.getY(); |
| 156 | + if (current.getX() > bottomRightX) bottomRightX = current.getX(); |
| 157 | + if (current.getY() > bottomRightY) bottomRightY = current.getY(); |
| 158 | + |
| 159 | + final WalkPosition[] deltas = { |
| 160 | + new WalkPosition(0, -1), |
| 161 | + new WalkPosition(-1, 0), |
| 162 | + new WalkPosition(1, 0), |
| 163 | + new WalkPosition(0, 1) |
| 164 | + }; |
| 165 | + for (final WalkPosition delta : deltas) { |
| 166 | + final WalkPosition nextWalkPosition = current.add(delta); |
| 167 | + if (getMapData().isValid(nextWalkPosition)) { |
| 168 | + final MiniTile nextMiniTile = getMiniTile(nextWalkPosition, CheckMode.NO_CHECK); |
| 169 | + if (nextMiniTile.isSeaOrLake()) { |
| 170 | + toSearch.add(nextWalkPosition); |
| 171 | + if (seaExtent.size() <= bwem.util.BwemExt.LAKE_MAX_MINI_TILES) { |
| 172 | + seaExtent.add(nextMiniTile); |
| 173 | + } |
| 174 | + nextMiniTile.setSea(); |
| 175 | + } |
| 176 | + } |
| 177 | + } |
| 178 | + } |
| 179 | + |
| 180 | + if ((seaExtent.size() <= bwem.util.BwemExt.LAKE_MAX_MINI_TILES) |
| 181 | + && (bottomRightX - topLeftX <= bwem.util.BwemExt.LAKE_MAX_WIDTH_IN_MINI_TILES) |
| 182 | + && (bottomRightY - topLeftY <= bwem.util.BwemExt.LAKE_MAX_WIDTH_IN_MINI_TILES) |
| 183 | + && (topLeftX >= 2) |
| 184 | + && (topLeftY >= 2) |
| 185 | + && (bottomRightX < getMapData().getWalkSize().getX() - 2) |
| 186 | + && (bottomRightY < getMapData().getWalkSize().getY() - 2)) { |
| 187 | + for (final MiniTile miniTile : seaExtent) { |
| 188 | + miniTile.setLake(); |
| 189 | + } |
| 190 | + } |
| 191 | + } |
| 192 | + } |
| 193 | + } |
81 | 194 | } |
0 commit comments