mirror of https://github.com/FreeCol/freecol.git
611 lines
27 KiB
Java
611 lines
27 KiB
Java
package net.sf.freecol.server.generator;
|
|
|
|
import static net.sf.freecol.common.model.Constants.INFINITY;
|
|
import static net.sf.freecol.common.util.CollectionUtils.find;
|
|
import static net.sf.freecol.common.util.CollectionUtils.minimize;
|
|
import static net.sf.freecol.common.util.CollectionUtils.transform;
|
|
import static net.sf.freecol.common.util.RandomUtils.getRandomMember;
|
|
import static net.sf.freecol.common.util.RandomUtils.randomShuffle;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Random;
|
|
import java.util.Set;
|
|
import java.util.function.ToIntFunction;
|
|
import java.util.logging.Logger;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.StreamSupport;
|
|
|
|
import net.sf.freecol.common.debug.FreeColDebugger;
|
|
import net.sf.freecol.common.i18n.Messages;
|
|
import net.sf.freecol.common.model.AbstractUnit;
|
|
import net.sf.freecol.common.model.Area;
|
|
import net.sf.freecol.common.model.Building;
|
|
import net.sf.freecol.common.model.BuildingType;
|
|
import net.sf.freecol.common.model.Colony;
|
|
import net.sf.freecol.common.model.Europe;
|
|
import net.sf.freecol.common.model.EuropeanNationType;
|
|
import net.sf.freecol.common.model.Game;
|
|
import net.sf.freecol.common.model.Goods;
|
|
import net.sf.freecol.common.model.GoodsType;
|
|
import net.sf.freecol.common.model.Map;
|
|
import net.sf.freecol.common.model.Nation;
|
|
import net.sf.freecol.common.model.Player;
|
|
import net.sf.freecol.common.model.Role;
|
|
import net.sf.freecol.common.model.Specification;
|
|
import net.sf.freecol.common.model.Tile;
|
|
import net.sf.freecol.common.model.TileImprovement;
|
|
import net.sf.freecol.common.model.TileImprovementType;
|
|
import net.sf.freecol.common.model.TileType;
|
|
import net.sf.freecol.common.model.Unit;
|
|
import net.sf.freecol.common.model.UnitType;
|
|
import net.sf.freecol.common.option.GameOptions;
|
|
import net.sf.freecol.server.model.ServerBuilding;
|
|
import net.sf.freecol.server.model.ServerColony;
|
|
import net.sf.freecol.server.model.ServerPlayer;
|
|
import net.sf.freecol.server.model.ServerUnit;
|
|
|
|
/**
|
|
* Handles the starting placement of European units.
|
|
*/
|
|
class EuropeanStartingPositionsGenerator {
|
|
|
|
private static final Logger logger = Logger.getLogger(EuropeanStartingPositionsGenerator.class.getName());
|
|
private final Random random;
|
|
|
|
|
|
EuropeanStartingPositionsGenerator(Random random) {
|
|
this.random = random;
|
|
}
|
|
|
|
|
|
/**
|
|
* Creates and places the European units as determined by the map settings.
|
|
*
|
|
* The non-naval are placed on land if there are no starting naval unit able to
|
|
* carry them, and in Europe if there's a starting naval unit but no more room.
|
|
*
|
|
* Naval units are placed in Europe if non-naval units are placed on land.
|
|
*
|
|
* @param map The {@code Map} to place the european units on.
|
|
* @param players The players in the game. Starting units are still only created
|
|
* for non-REF European players.
|
|
*/
|
|
void createEuropeanUnits(Map map, List<Player> players) {
|
|
final List<Player> europeanPlayers = players.stream()
|
|
.filter(p -> p.isEuropean() && !p.isREF())
|
|
.collect(Collectors.toList());
|
|
if (europeanPlayers.isEmpty()) {
|
|
throw new RuntimeException("No players to generate units for!");
|
|
}
|
|
|
|
Collections.shuffle(europeanPlayers, random);
|
|
|
|
final java.util.Map<Player, StartingUnits> playerStartingUnits = determineStartingUnits(europeanPlayers);
|
|
final java.util.Map<Player, Tile> playerStartingTiles = determineStartingTiles(map, europeanPlayers, playerStartingUnits);
|
|
|
|
for (Player player : europeanPlayers) {
|
|
final Tile start = playerStartingTiles.get(player);
|
|
final StartingUnits startingUnits = playerStartingUnits.get(player);
|
|
|
|
placeUnitsAtStartingLocation(player, start, startingUnits);
|
|
}
|
|
}
|
|
|
|
|
|
private java.util.Map<Player, StartingUnits> determineStartingUnits(List<Player> europeanPlayers) {
|
|
final java.util.Map<Player, StartingUnits> playerStartingUnits = new HashMap<>();
|
|
for (Player player : europeanPlayers) {
|
|
playerStartingUnits.put(player, new StartingUnits(player, random));
|
|
}
|
|
return playerStartingUnits;
|
|
}
|
|
|
|
private java.util.Map<Player, Tile> determineStartingTiles(Map map, List<Player> europeanPlayers, java.util.Map<Player, StartingUnits> playerStartingUnits) {
|
|
final Specification spec = map.getSpecification();
|
|
final Game game = map.getGame();
|
|
|
|
final boolean mapDefinedStartingPositionsAvailable = isMapDefinedStartingPositionsAvailableFor(europeanPlayers, game);
|
|
|
|
if (!mapDefinedStartingPositionsAvailable) {
|
|
return determineStartingTilesWithoutUsingPredeterminedPositions(map, europeanPlayers, playerStartingUnits);
|
|
}
|
|
|
|
final java.util.Map<Player, Tile> startingPositions = determineStartingTilesUsingMapDefinedPositions(europeanPlayers, playerStartingUnits, game);
|
|
if (startingPositions.size() < playerStartingUnits.size()) {
|
|
logger.info("Unable to use map defined starting positions - possibly caused by overlapping nation areas.");
|
|
return determineStartingTilesWithoutUsingPredeterminedPositions(map, europeanPlayers, playerStartingUnits);
|
|
}
|
|
return startingPositions;
|
|
}
|
|
|
|
|
|
private java.util.Map<Player, Tile> determineStartingTilesUsingMapDefinedPositions(List<Player> europeanPlayers, java.util.Map<Player, StartingUnits> playerStartingUnits, Game game) {
|
|
final Specification spec = game.getSpecification();
|
|
final int positionType = spec.getInteger(GameOptions.STARTING_POSITIONS);
|
|
switch (positionType) {
|
|
case GameOptions.STARTING_POSITIONS_CLASSIC:
|
|
return playerMapStartingAreaAndEnsureDistance(europeanPlayers, playerStartingUnits, game);
|
|
case GameOptions.STARTING_POSITIONS_RANDOM:
|
|
return randomMapStartingArea(europeanPlayers, playerStartingUnits, game);
|
|
case GameOptions.STARTING_POSITIONS_HISTORICAL:
|
|
return playerMapStartingArea(europeanPlayers, playerStartingUnits, game);
|
|
default:
|
|
throw new IllegalStateException("Unknown positionType=" + positionType);
|
|
}
|
|
}
|
|
|
|
|
|
private java.util.Map<Player, Tile> playerMapStartingAreaAndEnsureDistance(List<Player> europeanPlayers,
|
|
java.util.Map<Player, StartingUnits> playerStartingUnits, final Game game) {
|
|
final int MINIMUM_DISTANCE_BETWEEN_PLAYERS = 10;
|
|
final int MAX_TRIES = 10;
|
|
for (int i=0; i<MAX_TRIES; i++) {
|
|
final java.util.Map<Player, Tile> startingTiles = playerMapStartingArea(europeanPlayers, playerStartingUnits, game);
|
|
final boolean satisfiesMinimumDistance = startingTiles.values().stream()
|
|
.noneMatch(t -> startingTiles.values().stream().anyMatch(t2 -> t != t2 && t.getDistanceTo(t2) < MINIMUM_DISTANCE_BETWEEN_PLAYERS));
|
|
if (satisfiesMinimumDistance) {
|
|
return startingTiles;
|
|
}
|
|
}
|
|
logger.info("Not able to secure minimum starting distance between European players.");
|
|
return playerMapStartingArea(europeanPlayers, playerStartingUnits, game);
|
|
}
|
|
|
|
|
|
private java.util.Map<Player, Tile> playerMapStartingArea(List<Player> europeanPlayers, java.util.Map<Player, StartingUnits> playerStartingUnits, final Game game) {
|
|
final java.util.Map<Player, Tile> startingTiles = new HashMap<>();
|
|
for (Player player : europeanPlayers) {
|
|
final StartingUnits startingUnits = playerStartingUnits.get(player);
|
|
final boolean prefersLand = startingUnits.getCarriers().isEmpty();
|
|
final Area startingArea = game.getNationStartingArea(player.getNation());
|
|
|
|
List<Tile> possibleStartingTiles = startingArea.getTiles().stream()
|
|
.filter(t -> t.isLand() == prefersLand)
|
|
.collect(Collectors.toList());
|
|
if (possibleStartingTiles.isEmpty()) {
|
|
possibleStartingTiles = startingArea.getTiles();
|
|
}
|
|
|
|
while (!possibleStartingTiles.isEmpty()) {
|
|
final int randomIndex = random.nextInt(possibleStartingTiles.size());
|
|
final Tile startingTile = possibleStartingTiles.get(randomIndex);
|
|
if (!startingTiles.values().contains(startingTile)) {
|
|
startingTiles.put(player, startingTile);
|
|
break;
|
|
}
|
|
possibleStartingTiles.remove(randomIndex);
|
|
}
|
|
}
|
|
return startingTiles;
|
|
}
|
|
|
|
private java.util.Map<Player, Tile> randomMapStartingArea(List<Player> europeanPlayers, java.util.Map<Player, StartingUnits> playerStartingUnits, final Game game) {
|
|
final java.util.Map<Player, Tile> startingTiles = new HashMap<>();
|
|
|
|
final Set<Tile> tilesToChooseFrom = new HashSet<>();
|
|
for (Player player : europeanPlayers) {
|
|
final Area startingArea = game.getNationStartingArea(player.getNation());
|
|
if (startingArea != null) {
|
|
tilesToChooseFrom.addAll(startingArea.getTiles());
|
|
}
|
|
}
|
|
|
|
final List<Tile> randomLandTilesToChooseFrom = tilesToChooseFrom.stream()
|
|
.filter(t -> t.isLand())
|
|
.collect(Collectors.toList());
|
|
Collections.shuffle(randomLandTilesToChooseFrom, random);
|
|
int indexLand = 0;
|
|
|
|
final List<Tile> randomOceanTilesToChooseFrom = tilesToChooseFrom.stream()
|
|
.filter(t -> !t.isLand())
|
|
.collect(Collectors.toList());
|
|
Collections.shuffle(randomOceanTilesToChooseFrom, random);
|
|
int indexOcean = 0;
|
|
|
|
for (Player player : europeanPlayers) {
|
|
final StartingUnits startingUnits = playerStartingUnits.get(player);
|
|
final boolean prefersLand = startingUnits.getCarriers().isEmpty();
|
|
final Tile startingTile;
|
|
if (prefersLand && indexLand < randomLandTilesToChooseFrom.size()) {
|
|
startingTile = randomLandTilesToChooseFrom.get(indexLand);
|
|
indexLand++;
|
|
} else if (!prefersLand && indexOcean < randomOceanTilesToChooseFrom.size()) {
|
|
startingTile = randomOceanTilesToChooseFrom.get(indexOcean);
|
|
indexOcean++;
|
|
} else if (indexLand < randomLandTilesToChooseFrom.size()) {
|
|
startingTile = randomLandTilesToChooseFrom.get(indexLand);
|
|
indexLand++;
|
|
} else {
|
|
startingTile = randomOceanTilesToChooseFrom.get(indexOcean);
|
|
indexOcean++;
|
|
}
|
|
|
|
startingTiles.put(player, startingTile);
|
|
}
|
|
return startingTiles;
|
|
}
|
|
|
|
|
|
private boolean isMapDefinedStartingPositionsAvailableFor(List<Player> europeanPlayers, Game game) {
|
|
final Specification spec = game.getSpecification();
|
|
boolean mapDefinedStartingPositions = spec.getBoolean(GameOptions.MAP_DEFINED_STARTING_POSITIONS);
|
|
final int positionType = spec.getInteger(GameOptions.STARTING_POSITIONS);
|
|
|
|
int numAreas = 0;
|
|
if (mapDefinedStartingPositions) {
|
|
for (Player player : europeanPlayers) {
|
|
final Area area = game.getNationStartingArea(player.getNation());
|
|
if (area == null || area.getTiles().isEmpty()) {
|
|
logger.info("No map defined starting area for: " + player.getNationId());
|
|
if (positionType == GameOptions.STARTING_POSITIONS_CLASSIC
|
|
|| positionType == GameOptions.STARTING_POSITIONS_HISTORICAL) {
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
numAreas++;
|
|
}
|
|
}
|
|
if (numAreas < europeanPlayers.size()) {
|
|
mapDefinedStartingPositions = false;
|
|
}
|
|
return mapDefinedStartingPositions;
|
|
}
|
|
|
|
private java.util.Map<Player, Tile> determineStartingTilesWithoutUsingPredeterminedPositions(Map map, List<Player> europeanPlayers, java.util.Map<Player, StartingUnits> playerStartingUnits) {
|
|
final Specification spec = map.getSpecification();
|
|
final int positionType = spec.getInteger(GameOptions.STARTING_POSITIONS);
|
|
final int number = europeanPlayers.size();
|
|
|
|
// Make lists of candidate starting tiles on the east and west
|
|
// of the map, then break them up by land and "sea" (revisit
|
|
// if we get a map with a lake on the edge)
|
|
List<Tile> eastTiles = new ArrayList<>();
|
|
List<Tile> westTiles = new ArrayList<>();
|
|
List<Tile> eastLandTiles = new ArrayList<>();
|
|
List<Tile> westLandTiles = new ArrayList<>();
|
|
List<Tile> eastSeaTiles = new ArrayList<>();
|
|
List<Tile> westSeaTiles = new ArrayList<>();
|
|
map.collectStartingTiles(eastTiles, westTiles);
|
|
for (Tile t : eastTiles) {
|
|
if (t.isLand()) eastLandTiles.add(t); else eastSeaTiles.add(t);
|
|
}
|
|
for (Tile t : westTiles) {
|
|
if (t.isLand()) westLandTiles.add(t); else westSeaTiles.add(t);
|
|
}
|
|
|
|
// Now consider what type of positions we are selecting from
|
|
switch (positionType) {
|
|
case GameOptions.STARTING_POSITIONS_CLASSIC:
|
|
// Break the lists up into at least <number> candidate
|
|
// positions and shuffle. Empty the relevant list on failure.
|
|
sampleTiles(eastLandTiles, number);
|
|
sampleTiles(eastSeaTiles, number);
|
|
sampleTiles(westLandTiles, number);
|
|
sampleTiles(westSeaTiles, number);
|
|
break;
|
|
case GameOptions.STARTING_POSITIONS_RANDOM:
|
|
// Random starts are the same as classic but do not
|
|
// distinguish between east and west
|
|
eastLandTiles.addAll(westLandTiles);
|
|
eastSeaTiles.addAll(westSeaTiles);
|
|
sampleTiles(eastLandTiles, number);
|
|
sampleTiles(eastSeaTiles, number);
|
|
break;
|
|
case GameOptions.STARTING_POSITIONS_HISTORICAL:
|
|
break; // Historic positions retain all the possible tiles
|
|
}
|
|
|
|
final java.util.Map<Player, Tile> playerStartingTiles = new HashMap<>();
|
|
for (Player player : europeanPlayers) {
|
|
boolean startEast = player.getNation().getStartsOnEastCoast();
|
|
boolean startAtSea = !playerStartingUnits.get(player).getCarriers().isEmpty();
|
|
|
|
// Select a starting position from the available tiles
|
|
Tile start = null;
|
|
switch (positionType) {
|
|
case GameOptions.STARTING_POSITIONS_CLASSIC:
|
|
// Classic mode respects coast preference, the lists
|
|
// are pre-sampled and shuffled
|
|
start = ((startAtSea)
|
|
? ((startEast) ? eastSeaTiles : westSeaTiles)
|
|
: ((startEast) ? eastLandTiles : westLandTiles)).remove(0);
|
|
break;
|
|
case GameOptions.STARTING_POSITIONS_RANDOM:
|
|
// Random mode is as classic but ignores coast
|
|
// preference, the east lists already contain the west
|
|
start = ((startAtSea) ? eastSeaTiles : eastLandTiles).remove(0);
|
|
break;
|
|
case GameOptions.STARTING_POSITIONS_HISTORICAL:
|
|
start = (startAtSea)
|
|
? findHistoricalStartingPosition(player, map,
|
|
eastSeaTiles, westSeaTiles)
|
|
: findHistoricalStartingPosition(player, map,
|
|
eastLandTiles, westLandTiles);
|
|
break;
|
|
}
|
|
if (start == null) {
|
|
throw new RuntimeException("Failed to find start tile "
|
|
+ ((startAtSea) ? "at sea" : "on land")
|
|
+ " for player " + player);
|
|
}
|
|
playerStartingTiles.put(player, start);
|
|
}
|
|
return playerStartingTiles;
|
|
}
|
|
|
|
|
|
private void placeUnitsAtStartingLocation(Player player, Tile start, StartingUnits startingUnits) {
|
|
final Map map = player.getGame().getMap();
|
|
final Specification spec = map.getSpecification();
|
|
|
|
player.setEntryTile(start);
|
|
|
|
final Europe europe = player.getEurope();
|
|
final ServerPlayer serverPlayer = (ServerPlayer) player;
|
|
if (!start.isLand()) { // All aboard!
|
|
for (Unit u : startingUnits.getCarriers()) {
|
|
u.setLocation(start);
|
|
serverPlayer.exploreForUnit(u);
|
|
}
|
|
passengers: for (Unit unit : startingUnits.getPassengers()) {
|
|
for (Unit carrier : startingUnits.getCarriers()) {
|
|
if (carrier.canAdd(unit)) {
|
|
unit.setLocation(carrier);
|
|
continue passengers;
|
|
}
|
|
}
|
|
// no space left on carriers
|
|
unit.setLocation(europe);
|
|
}
|
|
for (Unit u : startingUnits.getOtherNaval()) {
|
|
u.setLocation(start);
|
|
serverPlayer.exploreForUnit(u);
|
|
}
|
|
} else { // Land ho!
|
|
for (Unit u : startingUnits.getPassengers()) {
|
|
u.setLocation(start);
|
|
serverPlayer.exploreForUnit(u);
|
|
}
|
|
for (Unit u : startingUnits.getOtherNaval()) {
|
|
u.setLocation(europe);
|
|
}
|
|
}
|
|
|
|
if (FreeColDebugger.isInDebugMode(FreeColDebugger.DebugMode.INIT)) {
|
|
createDebugUnits(map, player, start);
|
|
spec.setInteger(GameOptions.STARTING_MONEY, 10000);
|
|
}
|
|
|
|
// Start our REF player entry tile somewhere near to our
|
|
// starting tile, but do not place their units.
|
|
// They are assumed to always be on naval transport.
|
|
final Player ourREF = player.getREFPlayer();
|
|
if (ourREF == null) {
|
|
return;
|
|
}
|
|
final int distance = 10;
|
|
final List<Tile> refTiles = StreamSupport.stream(map.getCircleTiles(start, true, distance).spliterator(), false)
|
|
.filter(t -> !t.isLand())
|
|
.collect(Collectors.toList());
|
|
final Tile startRef = getRandomMember(logger, ourREF + " start", refTiles, random);
|
|
|
|
ourREF.setEntryTile(startRef);
|
|
}
|
|
|
|
/**
|
|
* Find the best historical starting position for a player from lists
|
|
* of tiles.
|
|
*
|
|
* @param player The {@code Player} to find a tile for.
|
|
* @param map The {@code Map} to search.
|
|
* @param east A list of starting {@code Tile}s on the east of the map.
|
|
* @param west A list of starting {@code Tile}s on the west of the map.
|
|
* @return The best {@code Tile} found, or null if none suitable.
|
|
*/
|
|
private Tile findHistoricalStartingPosition(final Player player,
|
|
final Map map,
|
|
List<Tile> east,
|
|
List<Tile> west) {
|
|
final Nation nation = player.getNation();
|
|
final int latY = map.getRow(nation.getPreferredLatitude());
|
|
List<Tile> tiles = (nation.getStartsOnEastCoast()) ? east : west;
|
|
if (tiles.isEmpty()) return null;
|
|
final ToIntFunction<Tile> dist = t -> Math.abs(t.getY() - latY);
|
|
final Comparator<Tile> closest = Comparator.comparingInt(dist);
|
|
Tile ret = minimize(tiles, closest);
|
|
tiles.remove(ret); // chosen tile is no longer a candidate
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Sample a list of tiles to pick spread out starting positions.
|
|
* Shuffle the result or clear it if there were too few tiles.
|
|
*
|
|
* @param tiles The list of {@code Tile}s to sample.
|
|
* @param number The number of players, which determines the spacing.
|
|
* @return True if there were enough tiles in the list.
|
|
*/
|
|
private boolean sampleTiles(List<Tile> tiles, int number) {
|
|
final int n = tiles.size();
|
|
final int step = n / number;
|
|
if (step <= 1) {
|
|
tiles.clear();
|
|
return false;
|
|
}
|
|
List<Tile> samples = new ArrayList<>();
|
|
// The offset start prevents selecting right on the poles
|
|
for (int i = step/2; i < n; i += step) {
|
|
samples.add(tiles.get(i));
|
|
}
|
|
tiles.clear();
|
|
tiles.addAll(samples);
|
|
randomShuffle(logger, "Starting tiles", tiles, random);
|
|
return true;
|
|
}
|
|
|
|
private List<Unit> createDebugUnits(Map map, Player player, Tile startTile) {
|
|
final Game game = map.getGame();
|
|
final Specification spec = game.getSpecification();
|
|
List<Unit> ret = new ArrayList<>(20);
|
|
// In debug mode give each player a few more units and a colony.
|
|
UnitType unitType = spec.getUnitType("model.unit.galleon");
|
|
Unit galleon = new ServerUnit(game, startTile, player, unitType);
|
|
galleon.setName(player.getNameForUnit(unitType, random));
|
|
ret.add(galleon);
|
|
unitType = spec.getUnitType("model.unit.privateer");
|
|
Unit privateer = new ServerUnit(game, startTile, player, unitType);
|
|
ret.add(privateer);
|
|
privateer.setName(player.getNameForUnit(unitType, random));
|
|
((ServerPlayer)player).exploreForUnit(privateer);
|
|
unitType = spec.getUnitType("model.unit.freeColonist");
|
|
ret.add(new ServerUnit(game, galleon, player, unitType));
|
|
unitType = spec.getUnitType("model.unit.veteranSoldier");
|
|
ret.add(new ServerUnit(game, galleon, player, unitType));
|
|
unitType = spec.getUnitType("model.unit.jesuitMissionary");
|
|
ret.add(new ServerUnit(game, galleon, player, unitType));
|
|
|
|
Tile colonyTile = null;
|
|
for (Tile tempTile : map.getCircleTiles(startTile, true, INFINITY)) {
|
|
if (tempTile.isPolar()) continue; // No initial polar colonies
|
|
if (player.canClaimToFoundSettlement(tempTile)) {
|
|
colonyTile = tempTile;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (colonyTile == null) {
|
|
return ret;
|
|
}
|
|
colonyTile.setType(find(spec.getTileTypeList(), t -> !t.isWater()));
|
|
unitType = spec.getUnitType("model.unit.expertFarmer");
|
|
Unit buildColonyUnit = new ServerUnit(game, colonyTile,
|
|
player, unitType);
|
|
ret.add(buildColonyUnit);
|
|
String colonyName = Messages.message(player.getNationLabel())
|
|
+ " " + Messages.message("Colony");
|
|
Colony colony = new ServerColony(game, player, colonyName, colonyTile);
|
|
player.addSettlement(colony);
|
|
colony.placeSettlement(true);
|
|
for (Tile tile : transform(colonyTile.getSurroundingTiles(1,1), t ->
|
|
(!t.hasSettlement()
|
|
&& (t.getOwner() == null || !t.getOwner().isEuropean())))) {
|
|
tile.changeOwnership(player, colony);
|
|
if (tile.hasLostCityRumour()) tile.removeLostCityRumour();
|
|
}
|
|
buildColonyUnit.setLocation(colony);
|
|
Tile ct = buildColonyUnit.getWorkTile();
|
|
if (ct != null) {
|
|
for (TileType t : transform(spec.getTileTypeList(),
|
|
tt -> !tt.isWater())) {
|
|
ct.setType(t);
|
|
TileImprovementType plowType = map.getSpecification()
|
|
.getTileImprovementType("model.improvement.plow");
|
|
TileImprovement plow = new TileImprovement(game, ct, plowType, null);
|
|
plow.setTurnsToComplete(0);
|
|
ct.add(plow);
|
|
break;
|
|
}
|
|
}
|
|
BuildingType schoolType = spec.getBuildingType("model.building.schoolhouse");
|
|
Building schoolhouse = new ServerBuilding(game, colony, schoolType);
|
|
colony.addBuilding(schoolhouse);
|
|
|
|
unitType = spec.getUnitType("model.unit.elderStatesman");
|
|
Unit statesman = new ServerUnit(game, colonyTile, player, unitType);
|
|
ret.add(statesman);
|
|
statesman.setLocation(colony.getWorkLocationFor(statesman,
|
|
statesman.getType().getExpertProduction()));
|
|
|
|
unitType = spec.getUnitType("model.unit.expertLumberJack");
|
|
Unit lumberjack = new ServerUnit(game, colony, player, unitType);
|
|
ret.add(lumberjack);
|
|
Tile lt = lumberjack.getWorkTile();
|
|
if (lt != null) {
|
|
TileType tt = find(spec.getTileTypeList(), TileType::isForested);
|
|
if (tt != null) lt.setType(tt);
|
|
lumberjack.changeWorkType(lumberjack.getType()
|
|
.getExpertProduction());
|
|
}
|
|
|
|
unitType = spec.getUnitType("model.unit.masterCarpenter");
|
|
ret.add(new ServerUnit(game, colony, player, unitType));
|
|
|
|
unitType = spec.getUnitType("model.unit.seasonedScout");
|
|
Unit scout = new ServerUnit(game, colonyTile, player, unitType);
|
|
ret.add(scout);
|
|
((ServerPlayer)player).exploreForUnit(scout);
|
|
|
|
unitType = spec.getUnitType("model.unit.veteranSoldier");
|
|
ret.add(new ServerUnit(game, colonyTile, player, unitType));
|
|
ret.add(new ServerUnit(game, colonyTile, player, unitType));
|
|
unitType = spec.getUnitType("model.unit.artillery");
|
|
ret.add(new ServerUnit(game, colonyTile, player, unitType));
|
|
ret.add(new ServerUnit(game, colonyTile, player, unitType));
|
|
ret.add(new ServerUnit(game, colonyTile, player, unitType));
|
|
unitType = spec.getUnitType("model.unit.treasureTrain");
|
|
Unit train = new ServerUnit(game, colonyTile, player, unitType);
|
|
ret.add(train);
|
|
train.setTreasureAmount(10000);
|
|
unitType = spec.getUnitType("model.unit.wagonTrain");
|
|
Unit wagon = new ServerUnit(game, colonyTile, player, unitType);
|
|
ret.add(wagon);
|
|
GoodsType cigarsType = spec.getGoodsType("model.goods.cigars");
|
|
Goods cigards = new Goods(game, wagon, cigarsType, 5);
|
|
wagon.add(cigards);
|
|
unitType = spec.getUnitType("model.unit.jesuitMissionary");
|
|
ret.add(new ServerUnit(game, colonyTile, player, unitType));
|
|
ret.add(new ServerUnit(game, colonyTile, player, unitType));
|
|
|
|
((ServerPlayer)player).exploreForSettlement(colony);
|
|
return ret;
|
|
}
|
|
|
|
private static final class StartingUnits {
|
|
|
|
private final List<Unit> carriers = new ArrayList<>();
|
|
private final List<Unit> passengers = new ArrayList<>();
|
|
private final List<Unit> otherNaval = new ArrayList<>();
|
|
|
|
StartingUnits(Player player, Random random) {
|
|
final Game game = player.getGame();
|
|
final Specification spec = player.getSpecification();
|
|
List<AbstractUnit> unitList = ((EuropeanNationType) player.getNationType()).getStartingUnits();
|
|
for (AbstractUnit startingUnit : unitList) {
|
|
UnitType type = startingUnit.getType(spec);
|
|
Role role = startingUnit.getRole(spec);
|
|
Unit newUnit = new ServerUnit(game, null, player, type, role);
|
|
newUnit.setName(player.getNameForUnit(type, random));
|
|
if (newUnit.isNaval()) {
|
|
if (newUnit.canCarryUnits()) {
|
|
newUnit.setState(Unit.UnitState.ACTIVE);
|
|
carriers.add(newUnit);
|
|
} else {
|
|
otherNaval.add(newUnit);
|
|
}
|
|
} else {
|
|
newUnit.setState(Unit.UnitState.SENTRY);
|
|
passengers.add(newUnit);
|
|
}
|
|
}
|
|
}
|
|
|
|
List<Unit> getCarriers() {
|
|
return carriers;
|
|
}
|
|
|
|
List<Unit> getPassengers() {
|
|
return passengers;
|
|
}
|
|
|
|
List<Unit> getOtherNaval() {
|
|
return otherNaval;
|
|
}
|
|
}
|
|
}
|