// Original work Copyright (c) 2015, 2017, Igor Dimitrijevic
// Modified work Copyright (c) 2017-2018 OpenBW Team
//////////////////////////////////////////////////////////////////////////
//
// This file is part of the BWEM Library.
// BWEM is free software, licensed under the MIT/X11 License.
// A copy of the license is provided with the library in the LICENSE file.
// Copyright (c) 2015, 2017, Igor Dimitrijevic
//
//////////////////////////////////////////////////////////////////////////
package bwem;
import bwapi.Game;
import bwapi.TilePosition;
import bwapi.WalkPosition;
import bwem.util.CheckMode;
import java.util.ArrayList;
import java.util.List;
public final class TerrainData {
private final MapData mapData;
private final TileData tileData;
TerrainData(final MapData mapData, final TileData tileData) {
this.mapData = mapData;
this.tileData = tileData;
}
public MapData getMapData() {
return this.mapData;
}
public TileData getTileData() {
return this.tileData;
}
public Tile getTile(final TilePosition tilePosition, final CheckMode checkMode) {
if (!((checkMode == CheckMode.NO_CHECK) || getMapData().isValid(tilePosition))) {
tileData.asserter.throwIllegalStateException("");
}
return getTileData()
.getTile(getMapData().getTileSize().getX() * tilePosition.getY() + tilePosition.getX());
}
public Tile getTile(final TilePosition tilePosition) {
return getTile(tilePosition, CheckMode.CHECK);
}
public MiniTile getMiniTile(final WalkPosition walkPosition, final CheckMode checkMode) {
if (!((checkMode == CheckMode.NO_CHECK) || getMapData().isValid(walkPosition))) {
tileData.asserter.throwIllegalStateException("");
}
return getTileData()
.getMiniTile(getMapData().getWalkSize().getX() * walkPosition.getY() + walkPosition.getX());
}
public MiniTile getMiniTile(final WalkPosition walkPosition) {
return getMiniTile(walkPosition, CheckMode.CHECK);
}
boolean isSeaWithNonSeaNeighbors(final WalkPosition walkPosition) {
if (!getMiniTile(walkPosition).isSea()) {
return false;
}
final WalkPosition[] deltas = {
new WalkPosition(0, -1),
new WalkPosition(-1, 0),
new WalkPosition(1, 0),
new WalkPosition(0, 1)
};
for (final WalkPosition delta : deltas) {
final WalkPosition walkPositionDelta = walkPosition.add(delta);
if (getMapData().isValid(walkPositionDelta) && !getMiniTile(walkPositionDelta,
CheckMode.NO_CHECK).isSea()) {
return true;
}
}
return false;
}
void markUnwalkableMiniTiles(final Game game) {
// Mark unwalkable minitiles (minitiles are walkable by default).
for (int y = 0; y < getMapData().getWalkSize().getY(); ++y)
for (int x = 0; x < getMapData().getWalkSize().getX(); ++x) {
if (!game.isWalkable(x, y)) {
// For each unwalkable minitile, we also mark its 8 neighbors as not walkable.
// According to some tests, this prevents from wrongly pretending one marine can go by
// some thin path.
for (int dy = -1; dy <= 1; ++dy)
for (int dx = -1; dx <= 1; ++dx) {
final WalkPosition walkPosition = new WalkPosition(x + dx, y + dy);
if (getMapData().isValid(walkPosition)) {
getMiniTile(walkPosition, CheckMode.NO_CHECK).setWalkable(false);
}
}
}
}
}
void markBuildableTilesAndGroundHeight(final Game game) {
// Mark buildable tiles (tiles are unbuildable by default).
for (int y = 0; y < getMapData().getTileSize().getY(); ++y)
for (int x = 0; x < getMapData().getTileSize().getX(); ++x) {
final TilePosition tilePosition = new TilePosition(x, y);
final WalkPosition walkPosition = tilePosition.toWalkPosition();
final Tile tile = getTile(tilePosition);
if (game.isBuildable(tilePosition, false)) {
tile.setBuildable();
// Ensures buildable ==> walkable.
for (int dy = 0; dy < 4; ++dy)
for (int dx = 0; dx < 4; ++dx) {
getMiniTile(walkPosition.add(new WalkPosition(dx, dy)), CheckMode.NO_CHECK)
.setWalkable(true);
}
}
// Add ground height and doodad information.
final int bwapiGroundHeight = game.getGroundHeight(tilePosition);
tile.setGroundHeight(bwapiGroundHeight / 2);
if (bwapiGroundHeight % 2 != 0) {
tile.setDoodad();
}
}
}
void decideSeasOrLakes() {
for (int y = 0; y < getMapData().getWalkSize().getY(); ++y)
for (int x = 0; x < getMapData().getWalkSize().getX(); ++x) {
final WalkPosition originWalkPosition = new WalkPosition(x, y);
final MiniTile originMiniTile = getMiniTile(originWalkPosition, CheckMode.NO_CHECK);
if (originMiniTile.isSeaOrLake()) {
final List