package settlers.game;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import settlers.game.DefaultGameEnums.BuildingTypes;
import settlers.game.DefaultGameEnums.TileTypes;
import settlers.game.GameCommands.GameCommand;
import settlers.game.data.MapCoord;
import settlers.game.data.SettlerGameData;
import settlers.game.data.SettlerPlayerData;
import settlers.game.map.SettlerMap;
public class SettlerGame {
public SettlerGameData data = new SettlerGameData();
private Random rollGenerator = new Random();
int currentPlayer;
GamePhases currentPhase = GamePhases.PREGAME;
public enum GamePhases {
/**
* Before the game starts when players can be added etc
*/
PREGAME,
/**
* The initial placement of 2 roads and settlements per player
*/
INITIAL_BUILD,
/**
* The game up until it ends
*/
NORMAL_PLAY,
/**
* A winner has been found no more moves need to be made.
*/
GAME_OVER
}
public SettlerGame() {
data.mapObjects.add(new MapObject(BuildingTypes.THIEF, SettlerMap
.findFirstInstance(TileTypes.DESERT, data.map)));
}
/**
* Stops accepting players and starts the initial build phase
*/
public void StartGame() {
if (currentPhase == GamePhases.PREGAME) {
currentPhase = GamePhases.INITIAL_BUILD;
} else {
System.out.println("Game already started.");
}
}
public SettlerPlayerData playerWithName(String name) {
for (int i = 0; i < data.players.size(); i++) {
if (data.players.get(i).getName() == name) {
return data.players.get(i);
}
}
System.out.println("Player " + name + " not found.");
return null;
}
/**
* Based on activatedTiles add the resources produced by the activated
* buildings
*/
public void findResourcesGivenByTiles(MapCoord[] activatedTiles) {
Iterator<?> iterator1 = data.mapObjects.iterator();
MapObject current;
int[][] resources = new int[data.players.size()][5];
while (iterator1.hasNext()) {
current = (MapObject) iterator1.next();
// TODO make add resources method
for (int i = 0; i < current.location.length; i++) {
for (int j = 0; j < activatedTiles.length; j++) {
if (current.getType() == BuildingTypes.THIEF
&& sameLocation(current.location[0],
activatedTiles[j])) {
} else {
if (sameLocation(current.location[i], activatedTiles[j])
&& current.location.length == 3)
switch (data.map.getTileAt(activatedTiles[j])) {
case ORE:
case BRICK:
case LUMBER:
case WOOL:
case WHEAT:
break;
addResource(current.player, data.map
.getTileAt(activatedTiles[j]), current
.getType().resourcesProduced());
}
}
}
}
}
public void addPlayer(String name) {
if (currentPhase == GamePhases.PREGAME) {
for (int i = 0; i < data.players.size(); i++) {
if (data.players.get(i).getName() == name) {
System.out.println("Player with that name already exists");
return;
}
}
data.players.add((new SettlerPlayerData(name)));
System.out.println("Player " + name + " added.");
}
}
public void endTurn() {
if (currentPhase != GamePhases.INITIAL_BUILD){
int roll = rollDice();
findResourcesGivenByTiles(SettlerMap.tilesActivatedByRoll(roll,
data.map));
}
currentPlayer++;
if (currentPlayer > data.players.size())
currentPlayer =0;
}
public Map<TileTypes, Integer> getCost(BuildingTypes type) {
Map<TileTypes, Integer> resourceCost = new HashMap<TileTypes, Integer>();
switch (type) {
case SETTLEMENT:
resourceCost.put(TileTypes.BRICK, 1);
resourceCost.put(TileTypes.LUMBER, 1);
resourceCost.put(TileTypes.WHEAT, 1);
resourceCost.put(TileTypes.WOOL, 1);
break;
case CITY:
resourceCost.put(TileTypes.ORE, 3);
resourceCost.put(TileTypes.WHEAT, 2);
break;
case ROAD:
resourceCost.put(TileTypes.BRICK, 1);
resourceCost.put(TileTypes.LUMBER, 1);
break;
}
return resourceCost;
}
public void addResource(int player, TileTypes resource, int amount) {
if (assertPlayerExists(player)) {
for (TileTypes tileType : TileTypes.values()) {
if (tileType.isResource() && resource == tileType) {
data.players.get(player).addResource(resource, amount);
System.out.println("Player " + player + " recieved "
+ amount + " of " + resource);
return;
}
}
System.out.println("Specified tile type is not a resource.");
} else {
System.out.println("Player does not exist.");
}
// TODO update players about new resources
}
/**
* Checks if the player can build a building of type at location.
*
* @param player
* The player referenced by their number
* @param type
* the building type
* @param location
* where to build it
* @return true if the player can build type at location
*/
public boolean canBuild(int player, BuildingTypes type, MapCoord[] location) {
Iterator<?> iterator1 = data.mapObjects.iterator();
MapObject current;
while (iterator1.hasNext()) {
current = (MapObject) iterator1.next();
if (Arrays.toString(current.location).equals(
Arrays.toString(location))
&& current.getType() != BuildingTypes.CITY) {
System.out.println("Already a building at this location.");
return false;
}
// roads can only be build adjacent to a city or settlement of that
// player
}
if (assertPlayerExists(player)) {
if (SettlerMap.isIntersection(data.map.isOriginDown, location)) {
// are there enough resources?
Map<TileTypes, Integer> cost = getCost(type);
Iterator<?> iterator = cost.keySet().iterator();
TileTypes currentResource;
while (iterator.hasNext()) {
currentResource = (TileTypes) iterator.next();
if (data.players.get(player).getResourceAmount(
currentResource) < cost.get(currentResource)) {
System.out.println("Not enough resouces");
return false;
}
}
switch (type) {
case ROAD:
if (!canBuildRoad(player, location))
return false;
break;
case SETTLEMENT:
if (!(currentPhase == GamePhases.INITIAL_BUILD)) {
if (!canBuildSettlement(player, location)) {
return false;
}
}
break;
case CITY:
if (!canBuildCity(player, location))
return false;
}
return true;
} else {
System.out.println("Invalid Intersection");
}
} else {
System.out.println("Player does not exist");
}
return false;
}
public boolean canBuildRoad(int player, MapCoord[] location) {
// TODO only build settlements next to roads of that player
Iterator<?> iterator = data.mapObjects.iterator();
MapObject current;
int x = 1;
if (x == 1)
return true;
while (iterator.hasNext()) {
current = (MapObject) iterator.next();
if (current.player == player) {
// roads can only be build adjacent to a city or settlement of
// that player
if (SettlerMap.tilesVeticallyAdjacent(data.map.isOriginDown,
location[0], location[1])) { // if the road is vertical
if (current.location.length == 3) {// if its a settlement or
// city
if (SettlerMap.isPartofDownRow(data.map.isOriginDown,
location[0].getX())) { // if its is a down row
if (current.location[0].getX() == location[1]
.getX() - 1
&& current.location[0].getY() == location[1]
.getY()
&& current.location[1].getX() == location[0]
.getX()
&& current.location[1].getY() == location[0]
.getY()
&& current.location[2].getX() == location[1]
.getX()
&& current.location[2].getY() == location[1]
.getY()) { // Settlement is to the
// left
return true;
} else if (current.location[2].getX() == location[1]
.getX() + 1
&& current.location[2].getY() == location[1]
.getY()
&& current.location[0].getX() == location[0]
.getX()
&& current.location[0].getY() == location[0]
.getY()
&& current.location[1].getX() == location[1]
.getX()
&& current.location[1].getY() == location[1]
.getY()) { // Settlement is to the
// Right
return true;
}
} else { // if it is an up row
if (current.location[0].getX() == location[0]
.getX() - 1
&& current.location[0].getY() == location[0]
.getY()
&& current.location[1].getX() == location[0]
.getX()
&& current.location[1].getY() == location[0]
.getY()
&& current.location[2].getX() == location[1]
.getX()
&& current.location[2].getY() == location[1]
.getY()) { // Settlement is to the
// left
return true;
} else if (current.location[2].getX() == location[0]
.getX() + 1
&& current.location[2].getY() == location[0]
.getY()
&& current.location[0].getX() == location[0]
.getX()
&& current.location[0].getY() == location[0]
.getY()
&& current.location[1].getX() == location[1]
.getX()
&& current.location[1].getY() == location[1]
.getY()) { // Settlement is to the
// right
return true;
}
}
} else if (current.getType().equals(BuildingTypes.ROAD)) {
if (SettlerMap.isPartofDownRow(data.map.isOriginDown,
location[0].getX())) { // down row
if (current.location[0].getX() == location[1]
.getX() - 1
&& // Diagonal Right on left
current.location[0].getY() == location[1]
.getY()
&& current.location[1].getX() == location[0]
.getX()
&& current.location[1].getY() == location[0]
.getY())
return true;
else if (current.location[0].getX() == location[1]
.getX() - 1
&& // Diagonal Left on left
current.location[0].getY() == location[1]
.getY()
&& current.location[1].getX() == location[1]
.getX()
&& current.location[1].getY() == location[1]
.getY())
return true;
else if (current.location[0].getX() == location[0]
.getX()
&& // Diagonal Left on Right
current.location[0].getY() == location[0]
.getY()
&& current.location[1].getX() == location[1]
.getX() + 1
&& current.location[1].getY() == location[1]
.getY())
return true;
else if (current.location[0].getX() == location[1]
.getX()
&& // Diagonal Right on Right
current.location[0].getY() == location[1]
.getY()
&& current.location[1].getX() == location[1]
.getX() + 1
&& current.location[1].getY() == location[1]
.getY())
return true;
} else { // up row
if (current.location[0].getX() == location[0]
.getX() - 1
&& // Diagonal Right on left
current.location[0].getY() == location[0]
.getY()
&& current.location[1].getX() == location[0]
.getX()
&& current.location[1].getY() == location[0]
.getY())
return true;
else if (current.location[0].getX() == location[1]
.getX() - 1
&& // Diagonal Left on left
current.location[0].getY() == location[0]
.getY()
&& current.location[1].getX() == location[1]
.getX()
&& current.location[1].getY() == location[1]
.getY())
return true;
else if (current.location[0].getX() == location[0]
.getX()
&& // Diagonal Left on Right
current.location[0].getY() == location[0]
.getY()
&& current.location[1].getX() == location[0]
.getX() + 1
&& current.location[1].getY() == location[0]
.getY())
return true;
else if (current.location[0].getX() == location[1]
.getX()
&& // Diagonal Right on Right
current.location[0].getY() == location[1]
.getY()
&& current.location[1].getX() == location[1]
.getX() + 1
&& current.location[1].getY() == location[0]
.getY())
return true;
}
}
} else if (SettlerMap.tilesDiagonalLeft(data.map.isOriginDown,
location[0], location[1])) {// sees if there are
// settlements above or
// below the diagonal left
// road
if (current.location.length == 3) {
if (current.location[0].getX() == location[0].getX()
&& // below
current.location[0].getY() == location[0]
.getY()
&& current.location[1].getX() == location[0]
.getX()
&& current.location[1].getY() == location[0]
.getY() + 1
&& current.location[2].getX() == location[1]
.getX()
&& current.location[2].getY() == location[1]
.getY())
return true;
else if (current.location[0].getX() == location[0]
.getX()
&& // above
current.location[0].getY() == location[0]
.getY()
&& current.location[1].getX() == location[1]
.getX()
&& current.location[1].getY() == location[1]
.getY() - 1
&& current.location[2].getX() == location[1]
.getX()
&& current.location[2].getY() == location[1]
.getY())
return true;
} else if (current.getType().equals(BuildingTypes.ROAD)) {// if
// theres
// a
// road
// beside
// it
if (current.location[0].getX() == location[0].getX()
&& // Horizontal on left
current.location[0].getY() == location[0]
.getY()
&& current.location[1].getX() == location[0]
.getX()
&& current.location[1].getY() == location[0]
.getY() + 1)
return true;
else if (current.location[0].getX() == location[0]
.getX()
&& // Diagonal Right below
current.location[0].getY() == location[0]
.getY() + 1
&& current.location[1].getX() == location[1]
.getX()
&& current.location[1].getY() == location[1]
.getY())
return true;
else if (current.location[0].getX() == location[1]
.getX()
&& // Horizontal on Right
current.location[0].getY() == location[1]
.getY() - 1
&& current.location[1].getX() == location[1]
.getX()
&& current.location[1].getY() == location[1]
.getY())
return true;
else if (current.location[0].getX() == location[0]
.getX()
&& // diagonal right above
current.location[0].getY() == location[0]
.getY()
&& current.location[1].getX() == location[1]
.getX()
&& current.location[1].getY() == location[1]
.getY() - 1)
return true;
}
} else if (SettlerMap.tilesDiagonalRight(data.map.isOriginDown,
location[0], location[1])) { // sees if there are
// settlements above or
// below the diagonal
// right road
if (current.location.length == 3) {
if (current.location[0].getX() == location[0].getX()
&& // below
current.location[0].getY() == location[0]
.getY()
&& current.location[1].getX() == location[1]
.getX()
&& current.location[1].getY() == location[1]
.getY()
&& current.location[2].getX() == location[1]
.getX()
&& current.location[2].getY() == location[1]
.getY() + 1)
return true;
else if (current.location[0].getX() == location[0]
.getX()
&& // above
current.location[0].getY() == location[0]
.getY() - 1
&& current.location[1].getX() == location[0]
.getX()
&& current.location[1].getY() == location[0]
.getY()
&& current.location[2].getX() == location[1]
.getX()
&& current.location[2].getY() == location[1]
.getY())
return true;
} else if (current.getType().equals(BuildingTypes.ROAD)) {
if (current.location[0].getX() == location[0].getX()
&& // Horizontal Left
current.location[0].getY() == location[0]
.getY() - 1
&& current.location[1].getX() == location[0]
.getX()
&& current.location[1].getY() == location[0]
.getY())
return true;
else if (current.location[0].getX() == location[0]
.getX()
&& // diagonal right above
current.location[0].getY() == location[0]
.getY() - 1
&& current.location[1].getX() == location[1]
.getX()
&& current.location[1].getY() == location[1]
.getY())
return true;
else if (current.location[0].getX() == location[1]
.getX()
&& // Horizontal Right
current.location[0].getY() == location[1]
.getY()
&& current.location[1].getX() == location[1]
.getX()
&& current.location[1].getY() == location[1]
.getY() + 1)
return true;
else if (current.location[0].getX() == location[0]
.getX()
&& // diagonal left Below
current.location[0].getY() == location[0]
.getY()
&& current.location[1].getX() == location[1]
.getX()
&& current.location[1].getY() == location[1]
.getY() + 1)
return true;
}
}
}
}
System.out.println("No " + BuildingTypes.SETTLEMENT
+ "s or CITIES adjacent to ROAD");
return false;
}
public boolean sameLocation(MapCoord one, MapCoord two) {
if (one.getX() == two.getX() && one.getY() == two.getY())
return true;
else
return false;
}
public boolean canBuildSettlement(int player, MapCoord[] location) {
Iterator<?> iterator = data.mapObjects.iterator();
MapObject current;
while (iterator.hasNext()) {
current = (MapObject) iterator.next();
// settlements can only be build next to that player's roads
if (current.player == player
&& current.getType() == BuildingTypes.ROAD) {
if (sameLocation(current.location[0], location[0])
|| sameLocation(current.location[0], location[1])
|| sameLocation(current.location[0], location[2]))
if (sameLocation(current.location[1], location[0])
|| sameLocation(current.location[1], location[1])
|| sameLocation(current.location[1], location[2]))
if (anyBuildingsAdjacent(location) == true) {
notifyPlayer(player,
"Cannot build settlement next to existing settlement or city");
return false;
} else
return true;
}
}
System.out.println("No ROAD adjacent to proposed SETTLEMENT");
return false;
}
public void notifyPlayer(int player, String message) {
System.out.println(message);
}
/**
* No settlement of city can be build directly adjacent to another
* settlement or city
*
* @param location
* of proposed building
* @return true if there is a building directly adjacent, false if not
*/
public boolean anyBuildingsAdjacent(MapCoord[] location) {
Iterator<?> iterator = data.mapObjects.iterator();
MapObject current;
while (iterator.hasNext()) {
current = (MapObject) iterator.next();
if (current.location.length == 3) { // if its a settlement
if (current.location[0].getX() == location[0].getX()
&& current.location[0].getY() == location[0].getY() - 1
&& current.location[1].getX() == location[0].getX()
&& current.location[1].getY() == location[0].getY()
&& current.location[2].getX() == location[1].getX()
&& current.location[2].getY() == location[1].getY()) {
// north settlement facing left
return true;
} else if (current.location[0].getX() == location[0].getX()
&& current.location[0].getY() == location[0].getY()
&& current.location[1].getX() == location[0].getX()
&& current.location[1].getY() == location[0].getY() + 1
&& current.location[2].getX() == location[2].getX()
&& current.location[2].getY() == location[2].getY()) {
// south settlement facing left
return true;
} else if (SettlerMap.isPartofDownRow(data.map.isOriginDown,
location[0].getX())
&& current.location[0].getX() == location[1].getX()
&& current.location[0].getY() == location[1].getY()
&& current.location[1].getX() == location[2].getX()
&& current.location[1].getY() == location[2].getY()
&& current.location[2].getX() == location[2].getX() + 1
&& current.location[2].getY() == location[1].getY()) {
// east settlement facing left down row
return true;
} else if (SettlerMap.isPartofDownRow(data.map.isOriginDown,
location[0].getX()) == false
&& current.location[0].getX() == location[1].getX()
&& current.location[0].getY() == location[1].getY()
&& current.location[1].getX() == location[2].getX()
&& current.location[1].getY() == location[2].getY()
&& current.location[2].getX() == location[1].getX() + 1
&& current.location[2].getY() == location[2].getY()) {
// east settlement facing left up row
return true;
} else if (SettlerMap.isPartofDownRow(data.map.isOriginDown,
location[0].getX())
&& current.location[0].getX() == location[1].getX() - 1
&& current.location[0].getY() == location[1].getY()
&& current.location[1].getX() == location[0].getX()
&& current.location[1].getY() == location[0].getY()
&& current.location[2].getX() == location[1].getX()
&& current.location[2].getY() == location[1].getY()) {
// West settlement facing Right down row
return true;
} else if (SettlerMap.isPartofDownRow(data.map.isOriginDown,
location[0].getX()) == false
&& current.location[0].getX() == location[1].getX() - 1
&& current.location[0].getY() == location[2].getY()
&& current.location[1].getX() == location[0].getX()
&& current.location[1].getY() == location[0].getY()
&& current.location[2].getX() == location[1].getX()
&& current.location[2].getY() == location[1].getY()) {
// West settlement facing Right up row
return true;
} else if (current.location[0].getX() == location[0].getX()
&& current.location[0].getY() == location[0].getY()
&& current.location[1].getX() == location[2].getX()
&& current.location[1].getY() == location[2].getY() - 1
&& current.location[2].getX() == location[2].getX()
&& current.location[2].getY() == location[2].getY()) {
// North settlement facing right
return true;
} else if (current.location[0].getX() == location[1].getX()
&& current.location[0].getY() == location[1].getY()
&& current.location[1].getX() == location[2].getX()
&& current.location[1].getY() == location[2].getY()
&& current.location[2].getX() == location[2].getX()
&& current.location[2].getY() == location[2].getY() + 1) {
// South Settlement facing right
return true;
}
}
}
return false;
}
public boolean canBuildCity(int player, MapCoord[] location) {
Iterator<?> iterator = data.mapObjects.iterator();
MapObject current;
while (iterator.hasNext()) {
current = (MapObject) iterator.next();
// cities can only be build on top of settlements
if (current.player == player
&& current.getType() == BuildingTypes.SETTLEMENT) {
if (sameLocation(current.location[0], location[0])
&& sameLocation(current.location[1], location[1])
&& sameLocation(current.location[2], location[2])) {
current.setType(BuildingTypes.CITY);
return true;
}
}
}
System.out.println("You do not have a settlement here to upgrade.");
return false;
}
public boolean build(int player, BuildingTypes object, MapCoord[] location) {
if (canBuild(player, object, location)) {
data.mapObjects.add(new MapObject(object, location, player));
Map<TileTypes, Integer> cost = getCost(object);
removeResources(player, cost);
System.out.println("Player " + player + " built a " + object
+ " at " + Arrays.toString(location));
return true;
}
return false;
}
public void removeResources(int player, Map<TileTypes, Integer> cost) {
Iterator<?> iterator = cost.keySet().iterator();
TileTypes currentResource;
while (iterator.hasNext()) {
currentResource = (TileTypes) iterator.next();
data.players.get(player).removeResources(currentResource,
cost.get(currentResource));
}
}
public boolean assertPlayerExists(int player) {
if (data.players.size() >= player)
return true;
else
return false;
}
public int rollDice() {
int roll = rollGenerator.nextInt(6) + rollGenerator.nextInt(6) + 2;
System.out.print(roll);
return roll;
}
/**
* Calculates the victory points a player has based on their buildings
*
* @param player
* @return the victory points that player has
*/
public int getVictoryPoints(int player) {
int victoryP = 0;
Iterator<?> iterator1 = data.mapObjects.iterator();
MapObject current;
while (iterator1.hasNext()) {
current = (MapObject) iterator1.next();
victoryP += current.getType().victoryPointValue();
}
return player;
}
public void processGameCommand(String command, int player) {
String[] temp = command.split(" ");
System.out.println("Game: have comamnd: " + command);
if (temp[0].equalsIgnoreCase(GameCommand.BUILD.command())) {
processBuildCommand(command.substring(
GameCommand.BUILD.command().length()).trim(), player);
} else if (temp[0].equalsIgnoreCase("roll")) {
System.out.println(rollDice());
} else if (temp[0].equalsIgnoreCase(GameCommand.ADDPLAYER.command())) {
if (temp.length == 2)
addPlayer(temp[1]);
else
System.out.println("To many tokens.");
} else if (temp[0].equalsIgnoreCase(GameCommand.GET_MAP.command())) {
System.out.println(data.map.tileMapAsString());
} else if (temp[0].equalsIgnoreCase(GameCommand.GET_MAP_OBJECTS
.command())) {
System.out.println(data.mapObjects.toString());
} else if (temp[0].equalsIgnoreCase(GameCommand.ADD_RESOURCE.command())) {
processAddResource(command.substring(
GameCommand.ADD_RESOURCE.command().length()).trim(), player);
} else if (temp[0].equalsIgnoreCase(GameCommand.GET_PLAYER_RESOURCES
.command())) {
printPlayerResources(player);
} else {
System.out.println("unable to process command");
}
}
private void printPlayerResources(int player) {
if (assertPlayerExists(player)) {
System.out.println(data.players.get(player).resourceToString());
} else {
System.out.println("player " + player + "does not exist");
}
}
private void processAddResource(String command, int player) {
String[] temp = command.split(" ");
if (temp.length != 2)
return;
for (TileTypes tileType : TileTypes.values()) {
if (tileType.isResource()) {
if (tileType.toString().equalsIgnoreCase(temp[0])) {
if (isInteger(temp[1])) {
addResource(player, tileType, Integer.parseInt(temp[1]));
return;
}
}
}
}
System.out.println("Error processing command: " + command);
}
private void processBuildCommand(String command, int player) {
String[] temp = command.split(" ");
for (BuildingTypes building : BuildingTypes.values()) {
/*
* Is the current building user buildable? Is the current building
* specified in the command? Does the command have the right number
* of coordinates?
*/
if (building.isUserBuildable()
&& building.toString().equalsIgnoreCase(temp[0])
&& (temp.length - 1) == building.coords()) {
/*
* remove the building type part from the command and send the
* rest of the command to be decoded into a MapCoord[]
*/
MapCoord[] coords = MapCoord.arrayFromString(command
.substring(building.toString().length()));
if (coords == null) {
notifyPlayer(player,
"malformed map coordinates for building");
break; // already found matching building
}
if (canBuild(player, building, coords)) {
build(player, building, coords);
}
break;
}
}
}
/**
* @param input
* string to be tested
* @return true if the string is an integer
*/
public boolean isInteger(String input) {
try {
Integer.parseInt(input);
return true;
} catch (NumberFormatException e) {
return false;
}
}
}