Board.java :  » Game » settlers-of-catan » gameParts » Java Open Source

Java Open Source » Game » settlers of catan 
settlers of catan » gameParts » Board.java
package gameParts;

import gameParts.Tile.TileType;

import java.io.Serializable;
import java.util.*;

import rmi.server.IGameServer.GameState;

public class Board implements Serializable, Cloneable {

  private static final long serialVersionUID = 9092555974770706967L;

  private List<Tile> mTiles = new ArrayList<Tile>(BoardUtils.sTilesAmount);
  private int mThiefIndex;
  private Map<Integer, Settlement> mSettlements = new HashMap<Integer, Settlement>();
  private Map<String, Road> mRoads = new HashMap<String, Road>();
  private Map<Integer, City> mCities = new HashMap<Integer, City>();

  
  /**
   * default ctor calls constructor that shuffles
   */
  public Board()
  {
    this(true);
  }
  
  /**
   * Ctor, creates a new board with random tile placements 
   */
  public Board(boolean isShuffle) {
    // add new tiles by the proper amount and predefined order
    TileType[] firstTiles = {TileType.MOUNTAIN, 
        TileType.FIELD, TileType.FOREST, TileType.MOUNTAIN,
        TileType.FIELD, TileType.MEADOW, TileType.FIELD,
        TileType.MEADOW, TileType.FOREST, TileType.HILL,
        TileType.DESERT, TileType.HILL, TileType.MEADOW,
        TileType.MEADOW, TileType.FOREST, TileType.HILL,
        TileType.MOUNTAIN, TileType.FOREST, TileType.FIELD};
    for (TileType t : firstTiles)
    {
      mTiles.add(new Tile(t));
    }
    if (isShuffle)
    {
      // shuffle the tiles in the board to be placed randomly
      shuffledBoard();
    }
    else {
      int i = 0;
      for (Tile t : mTiles)
      {  
        t.setTileLetter((char)(i+'A'));
        ++i;
      }
    }
    int i = 0;
    // adding predefined dice numbers to the tiles
    int[] diceNumbers = { 5, 2, 6, 3, 8, 10, 9, 12, 11, 4, 8, 10, 9, 4, 5, 6, 3, 11 };
    for (Tile t : mTiles) {
      if (t.getType() != Tile.TileType.DESERT) {
        t.setDiceNum(diceNumbers[i]);
        ++i;
      }
    }
    // set up the robber in the desert tile
    moveRobber(getDesertTile());
  }

  @Override
  public Object clone() throws CloneNotSupportedException {
    Board clone = new Board();

    // set thief
    clone.mThiefIndex = mThiefIndex;

    // add tiles
    // they are randomly set when the board is created, so first clear the randomly generated ones
    clone.mTiles.clear();
    Iterator<Tile> tilesIter = mTiles.iterator();
    while (tilesIter.hasNext()) {
      clone.mTiles.add((Tile) tilesIter.next().clone());
    }

    // add settlements
    Iterator<Integer> mySettlementsIter = mSettlements.keySet().iterator();
    while (mySettlementsIter.hasNext()) {
      Integer settlement = mySettlementsIter.next();
      clone.mSettlements.put(settlement.intValue(), (Settlement) mSettlements.get(settlement).clone());
    }

    // add cities
    Iterator<Integer> myCitiesIter = mCities.keySet().iterator();
    while (myCitiesIter.hasNext()) {
      Integer city = myCitiesIter.next();
      clone.mCities.put(city.intValue(), (City) mCities.get(city).clone());
    }

    // add roads
    Iterator<String> myRoadsIter = mRoads.keySet().iterator();
    while (myRoadsIter.hasNext()) {
      String road = myRoadsIter.next();
      clone.mRoads.put(road + "", (Road) mRoads.get(road).clone());
    }

    return clone;
  }

  @Override
  public boolean equals(Object obj) {
    Board board = null;
    try {
      board = (Board) obj;
    } catch (Exception e) {
      return false;
    }
    if (
        (board == null) ||
        (mTiles.size() != board.mTiles.size()) ||
        (mSettlements.size() != board.mSettlements.size()) ||
        (mRoads.size() != board.mRoads.size()) ||
        (mCities.size() != board.mCities.size())
      ) {
      return false;
    }
    // check tiles
    Iterator<Tile> myTilesIter = mTiles.iterator();
    Iterator<Tile> compareTilesIter = board.mTiles.iterator();
    while (myTilesIter.hasNext()) {
      Tile my = myTilesIter.next();
      Tile compare = compareTilesIter.next();
      if (! my.equals(compare)) {
        return false;
      }
    }
    // check settlements
    Iterator<Integer> mySettlementsIter = mSettlements.keySet().iterator();
    Iterator<Integer> compareSettlementsIter = board.mSettlements.keySet().iterator();
    while (mySettlementsIter.hasNext()) {
      Integer my = mySettlementsIter.next();
      Integer compare = compareSettlementsIter.next();
      if (! mSettlements.get(my).equals(board.mSettlements.get(compare))) {
        return false;
      }
    }
    // check cities
    Iterator<Integer> myCitiesIter = mCities.keySet().iterator();
    Iterator<Integer> compareCitiesIter = board.mCities.keySet().iterator();
    while (myCitiesIter.hasNext()) {
      Integer my = myCitiesIter.next();
      Integer compare = compareCitiesIter.next();
      if (! mCities.get(my).equals(board.mCities.get(compare))) {
        return false;
      }
    }
    // check roads
    Iterator<String> myRoadsIter = mRoads.keySet().iterator();
    Iterator<String> compareRoadsIter = board.mRoads.keySet().iterator();
    while (myRoadsIter.hasNext()) {
      String my = myRoadsIter.next();
      String compare = compareRoadsIter.next();
      if (! mRoads.get(my).equals(board.mRoads.get(compare))) {
        return false;
      }
    }
    return true;
  }

  /**
   * @return the mTiles
   */
  public List<Tile> getTiles() {
    return mTiles;
  }

  /**
   * sets the tiles on the board randomly
   */
  public void shuffledBoard() {
    Collections.shuffle(mTiles);
    // add tile letter to each tile
    int i = 0;
    for (Tile t : mTiles)
    {
      t.setTileLetter((char)(i+'A'));
      ++i;
    }
  }

  /**
   * @return the char representation of the robber's location
   */
  public char getRobberLocation() {
    return (char) (mThiefIndex + 65);
  }

  /**
   * sets the robber location to the given tile
   * @param tile - the char representation of the tile 
   *               we want the robber to move to
   */
  public void moveRobber(char tile) {
    Character c = Character.toLowerCase(tile);
    int index = Character.getNumericValue(c)
        - Character.getNumericValue('a');
    this.mThiefIndex = index;
  }

  /**
   * @return the char representation of the tile in which the
   * desert is placed
   */
  public char getDesertTile() {
    int desertIndex = 0;
    int i = 0;
    for (Tile t : mTiles) {
      if (t.getType() == Tile.TileType.DESERT) {
        desertIndex = i;
        break;
      }
      ++i;
    }
    return (char) (desertIndex + 65);
  }

  /**
   * checks whether the robber can be moved to the given location
   * @param i - the enumeration of the tile to be checked
   * @return true iff the robber isn't already in the given location.
   */
  public boolean canMoveThief(int i) {
    if (i == getRobberLocation()) {
      return false;
    }
    return true;
  }

  /**
   * adds a settlement belonging to the given player 
   * on the given corner
   * @param player
   * @param tile
   * @param corner
   * @precondition - canAddSettlement(player, corner, GameState)
   */
  public void addSettlement(int player, Integer corner) {
    mSettlements.put(corner, new Settlement(player, corner));
  }

  /**
   * gets a settlement in the given corner
   * @param corner
   * @return the settlement if exists or null if the corner has
   * no settlement.
   */
  public Settlement getSettlement(Integer corner) {
    return mSettlements.get(corner);
  }

  /**
   * add road for given player between the to given corners
   * @param player
   * @param tile
   * @param corner1
   * @param corner2
   * @precondition - canAddRoad(player, corner1, corner2)
   */
  public void addRoad(int player, Integer corner1, Integer corner2) {
    String location = corner1 + ":" + corner2;
    mRoads.put(location, new Road(player, corner1, corner2));
  }

  /**
   * get road that exists between two given corners
   * @param tile
   * @param corner1
   * @param corner2
   * @return the road if exists or null if the location is empty
   */
  public Road getRoad(Integer corner1, Integer corner2) {
    Road result = mRoads.get(corner1 + ":" + corner2);
    if (result == null) {
      result = mRoads.get(corner2 + ":" + corner1);
    }
    return result;
  }

  /**
   * add city in given location for the given player
   * @param player
   * @param corner
   * @precondition - canAddCity(player, corner)
   */
  public void addCity(int player, Integer corner) {
    mCities.put(corner, new City(player, corner));
    mSettlements.remove(corner);
  }

  /**
   * gets city in given location
   * @param corner
   * @return the city if exists or null if no city exists in location
   */
  public City getCity(Integer corner) {
    return mCities.get(corner);
  }

  /**
   * return the tile by the given char
   * @param tile
   * @return
   * @precondition - tile < 'S'
   */
  public Tile getTileByChar(char tile) {
    Character c = Character.toLowerCase(tile);
    int index = Character.getNumericValue(c)
        - Character.getNumericValue('a');
    return mTiles.get(index);
  }

  /**
   * 
   */
  public String toString() 
  {
    StringBuffer str = new StringBuffer();    
    str.append("Tiles:\n");
    for (Tile t : mTiles) {
      str.append(t.toString() + "\n");      
    }
    str.append("Settlements:\n");
    for (Integer k : mSettlements.keySet()) {
      str.append("player: "
          + ((BasePart) mSettlements.get(k)).getPlayerID()
          + ", corner: " + k + "\n");
    }
    str.append("Cities:\n");
    for (Integer k : mCities.keySet()) {
      str.append("player: " + ((BasePart) mCities.get(k)).getPlayerID()
          + ", corner: " + k + "\n");
    }
    str.append("Roads:\n");
    for (String k : mRoads.keySet()) {
      str.append("player: " + ((BasePart) mRoads.get(k)).getPlayerID()
          + ", location: " + k + "\n");
    }
    str.append("Robber: " + this.getRobberLocation() + "\n");
    return str.toString();
  }

  /**
   * gets the tiles the have the dice number given in the roll
   * @param roll
   * @return list of tiles corresponding with the results
   * @precondition - 2 < roll < 12
   */
  public List<Tile> getDiceResult(int roll) {
    List<Tile> result = new ArrayList<Tile>();
    for (Tile t : mTiles)
    {
      if (t.getDiceNum() == roll)
      {
        result.add(t);
      }
    }
    return result;
  }

  /**
   * @param player - the ID of the player to check for
   * @param corner - the number of the corner to check for
   * @param state - the state of the game
   * @return True iff player can build a settlement in corner when the game is in the given state
   */
  public boolean canAddSettlement(int player, int corner, GameState state) {
    if (! BoardUtils.cornerIsValid(corner)) {
      return false;
    }
    if ((getSettlement(corner) != null) || (getCity(corner) != null)) {
      return false;
    }
    for (int i=0; i<BoardUtils.getCornerNeighborsAmount(corner); ++i) {
      if (getSettlement(BoardUtils.getCornerNeighbors(corner)[i]) != null) {
        return false;
      }
    }
    switch(state) {
      case INIT: {
        return true;
      }
      case INGAME: {
        int[] neighbors = BoardUtils.getCornerNeighbors(corner);
        for (int i=0; i<neighbors.length; ++i) {
          Road road = getRoad(corner, neighbors[i]);
          if ((road != null) && (road.getPlayerID() == player)) {
            return true;
          }
        }
        return false;
      }
      default: {
        return false;
      }
    }
  }

  /**
   * @param player - the ID of the player to check for
   * @param corner - the number of the corner to check for
   * @param state - the state of the game
   * @return True iff player can build a city in corner when the game is in the given state
   */
  public boolean canAddCity(int player, int corner, GameState state) {
    if (state != GameState.INGAME) {
      return false;
    }
    Settlement s = getSettlement(corner);
    if ((s != null) && (player == s.getPlayerID())) {
      return true;
    }
    return false;
  }

  /**
   * @param player - the ID of the player to check for
   * @param corner1 - the first side of the wanted road
   * @param corner2 - the second side of the wanted road
   * @param state - the state of the game
   * @return True iff player can build a road between corner1 and corner2 when the game is in the given state
   */
  public boolean canAddRoad(int player, int corner1, int corner2, GameState state) {
    if (!BoardUtils.cornersAreNeighbors(corner1, corner2)) {
      return false;
    }
    if (getRoad(corner1, corner2) != null) {
      return false;
    }
    switch (state) {
      case INIT: {
        Settlement s1 = getSettlement(corner1);
        Settlement s2 = getSettlement(corner2);
        return (((s1 != null) && (s1.getPlayerID() == player)) || ((s2 != null) && (s2.getPlayerID() == player)));
      }
      case INGAME: {
        return (cornerHasPlayerRoad(player, corner1) || cornerHasPlayerRoad(player, corner2));
      }
      default: {
        return false;
      }
    }
  }

  private boolean cornerHasPlayerRoad(int player, int corner) {
    int[] neighbors = BoardUtils.getCornerNeighbors(corner);
    for (int i=0; i<neighbors.length; ++i) {
      Road road = getRoad(corner, neighbors[i]);
      if ((road != null) && (road.getPlayerID() == player)) {
        return true;
      }
    }
    return false;
  }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.