@Override
  public synchronized boolean equals(Object obj) {
    if (this == obj) return true;
    if (obj == null) return false;
    if (getClass() != obj.getClass()) return false;
    GameState other = (GameState) obj;
    if (backBuffer == null) {
      if (other.backBuffer != null) return false;
    } else if (!backBuffer.equals(other.backBuffer)) return false;
    if (epoch != other.epoch) return false;
    if (frontBuffer == null) {
      if (other.frontBuffer != null) return false;
    } else if (!frontBuffer.equals(other.frontBuffer)) return false;
    if (successfulExits != other.successfulExits) return false;
    if (unsuccessfulExits != other.unsuccessfulExits) return false;

    // Compare frontBuffer
    Map<Character, Plane> o = other.getFrontBuffer();
    if (frontBuffer.size() != o.size()) return (false);
    Iterator<Character> it = frontBuffer.keySet().iterator();
    Iterator<Character> it2 = o.keySet().iterator();
    char c1, c2;
    while (it.hasNext()) {
      c1 = it.next();
      c2 = it2.next();
      if (c1 != c2 || !frontBuffer.get(c1).equals(o.get(c2))) return (false);
    }

    // Compare backBuffer
    o = other.getBackBuffer();
    if (backBuffer.size() != o.size()) return (false);
    it = backBuffer.keySet().iterator();
    it2 = o.keySet().iterator();
    while (it.hasNext()) {
      c1 = it.next().charValue();
      c2 = it2.next().charValue();
      if (c1 != c2 || !backBuffer.get(c1).equals(o.get(c2))) return (false);
    }

    // Compare board
    Board b = other.getBoard();
    if (b.getHeight() != board.getHeight()
        || b.getWidth() != board.getWidth()
        || b.getPorts().size() != board.getPorts().size()) return (false);
    it = board.getPorts().keySet().iterator();
    it2 = b.getPorts().keySet().iterator();
    while (it.hasNext()) {
      c1 = it.next().charValue();
      c2 = it.next().charValue();
      if (c1 != c2 || !b.getPorts().get(c1).equals(board.getPorts().get(c2))) return (false);
    }

    return true;
  }
  // Processed by ReveiverDispatcher
  private synchronized void processStateMsg(StateMessage statemsg) {
    // Get the new GameState that comes in the message
    GameState gameState = statemsg.getGame();

    // Change everything
    frontBuffer = new HashMap<Character, Plane>();
    for (Map.Entry<Character, Plane> e : gameState.getFrontBuffer().entrySet())
      frontBuffer.put(e.getKey(), e.getValue());

    backBuffer = new HashMap<Character, Plane>();
    for (Map.Entry<Character, Plane> e : gameState.getBackBuffer().entrySet())
      backBuffer.put(e.getKey(), e.getValue());

    this.successfulExits = gameState.getSuccessfulExits();
    this.unsuccessfulExits = gameState.getUnsucessfulExits();
    this.epoch = gameState.getEpoch();
    this.board = gameState.getBoard();

    // Notify Screen that the GameState has changed
    Map<Character, Plane> obs = new HashMap<Character, Plane>();
    for (Map.Entry<Character, Plane> e : frontBuffer.entrySet())
      obs.put(e.getKey().charValue(), e.getValue().clone());
    setChanged();
    notifyObservers(obs);
  }
  public GameState(GameState gameState) {
    frontBuffer = new HashMap<Character, Plane>();
    for (Map.Entry<Character, Plane> e : gameState.getFrontBuffer().entrySet())
      frontBuffer.put(e.getKey(), e.getValue());

    backBuffer = new HashMap<Character, Plane>();
    for (Map.Entry<Character, Plane> e : gameState.getBackBuffer().entrySet())
      backBuffer.put(e.getKey(), e.getValue());

    this.successfulExits = gameState.getSuccessfulExits();
    this.unsuccessfulExits = gameState.getUnsucessfulExits();
    this.epoch = gameState.getEpoch();
    this.board = gameState.getBoard();

    previousAdds = new HashMap<Gate, Integer>();
    for (Map.Entry<Gate, Integer> e : gameState.getPreviousAdds().entrySet())
      previousAdds.put(e.getKey().clone(), e.getValue().intValue());

    actualAdds = new HashMap<Gate, Integer>();
    for (Map.Entry<Gate, Integer> e : gameState.getActualAdds().entrySet())
      actualAdds.put(e.getKey().clone(), e.getValue().intValue());
  }