public synchronized NewPlane createRandomPlane() {
    // Get an ID
    Random rand = new Random();
    Character id = 'A';
    int roll = rand.nextInt(26);
    for (int i = 0; i <= roll || frontBuffer.containsKey(id); i++, id++) ;

    // Get an exit gate
    Gate eg =
        board
            .getPorts()
            .values()
            .toArray(new Gate[26])[rand.nextInt(board.getPorts().size())]
            .clone();

    // Get an entrance gate
    Gate ge;
    do
      ge =
          board
              .getPorts()
              .values()
              .toArray(new Gate[26])[rand.nextInt(board.getPorts().size())]
              .clone();
    while (ge.getSymbol() == eg.getSymbol());

    // Exit altitude
    int ea = rand.nextInt(9000);
    if (ea < 4000) ea = 3000;
    else ea = 7000;

    // Altitude
    int al = rand.nextInt(9000);
    if (al < 2667) al = 1000;
    else if (al < 5333) al = 5000;
    else al = 9000;

    // Set direction
    int di = 1;
    if (ge.getxCoord() == 0 && ge.getyCoord() == 0) di = 4;
    else if (ge.getxCoord() == 0 && ge.getyCoord() == board.getHeight() - 1) di = 2;
    else if (ge.getxCoord() == board.getWidth() - 1 && ge.getyCoord() == 0) di = 7;
    else if (ge.getxCoord() == board.getWidth() - 1 && ge.getyCoord() == board.getHeight() - 1)
      di = 9;
    else if (ge.getxCoord() == 0) di = 3;
    else if (ge.getxCoord() == board.getWidth() - 1) di = 8;
    else if (ge.getyCoord() == 0) di = 6;
    else if (ge.getyCoord() == board.getHeight() - 1) di = 1;

    // Return the new plane
    return (new NewPlane(ge.getSymbol(), eg.getSymbol(), di, ea, al));
  }
  private synchronized void processTick(Tick tick) {
    int x, y;

    // Fazer as opera��es primeiro por causa dos observers no swapBuffers()
    // Por os avi�es a marchar
    for (Plane p : backBuffer.values()) p.move();

    // Remover os avi�es que saem do mapa
    boolean succ = false;
    Set<Character> remover = new TreeSet<Character>();

    for (Plane p :
        backBuffer
            .values()) { // A diferen�a entre tirar logo quando ele chega na porta ou tirar depois
                         // de ter passado um epoch na porta
      x = p.getxCoord();
      y = p.getyCoord();

      if (x <= 0 || y <= 0 || y >= board.getHeight() || x >= board.getWidth()) {
        for (Gate g : board.getPorts().values())
          if (g.getxCoord() == x && g.getyCoord() == y && p.getExitAltitude() == p.getAltitude()) {
            this.successfulExits++;
            succ = true;
            break;
          }
        if (succ) succ = false;
        else this.unsuccessfulExits++;
        remover.add(p.getID());
      }
    }
    for (Character id : remover) backBuffer.remove(id);

    // Remover avi�es que colidiram no epoch anterior - est�o marcados com um '+'
    for (Plane p : frontBuffer.values())
      if (p.getSymbol() == '+') {
        backBuffer.remove(p.getID());
        this.unsuccessfulExits++;
      }

    // Testar colis�es
    for (Plane p : backBuffer.values()) {
      x = p.getxCoord();
      y = p.getyCoord();
      for (Plane p2 : backBuffer.values()) {
        int x2 = p2.getxCoord();
        int y2 = p2.getyCoord();
        if (p != p2
            && Math.abs(x - x2) <= 1
            && Math.abs(y - y2) <= 1
            && Math.abs(p.getAltitude() - p2.getAltitude()) <= 1000) {
          p.setSymbol('+');
          p2.setSymbol('+');
        } // N�o fazer 'continue;' pq pode haver 3 ou mais avi�es a colidirem
      }
    }

    // Reset avioes adicionados
    previousAdds = actualAdds;
    actualAdds = new HashMap<Gate, Integer>();

    // Trocar os buffers
    epoch++;
    swapBuffers();
  }