// when game is initialized the game can start playing, this is main loop in
  // which will the game stay will somebody wins
  private void startGame() {
    // while there is still anybody playing loop this
    while (Game.anyPlayerPlaying()) {
      if (Game.getCurrentPlayer().isPlaying()) {
        if (Game.getCurrentPlayer().didYouWon()) {
          // somebody won, change him to "non-playing" state as well so the loop
          // will exit properly
          UI.anounceWinner(Game.getCurrentPlayer());

          Game.getCurrentPlayer().giveUp();
        } else {

          // in all other cases display board and his options depending on jail
          // status

          UI.displayBoard();

          if (Game.getCurrentPlayer().getJailTime() > 0) {
            jailOptions();
          } else {
            playerOptions();
          }
        }
      }
      Game.nextPlayer();
    }
  }
  // Includes stepping forwards and backwards
  public void step(int steps) {
    // make steps, check if you passed go, collect money
    // call tileActions();

    this.position += steps;
    if (this.position < 0) {
      this.position += Game.getBoard().boardSize();
    }
    // anton fix from > to >= if it's equal to 40 it needs to be set to 0 already
    if (this.position >= Game.getBoard().boardSize()) {
      this.position = this.position % Game.getBoard().boardSize();
      StdOut.println("Passed GO. Collect €2M.");
      Game.getBank().getMoneyFromBank(2000000L);
    }

    UI.displayBoard();
    Game.getBoard().tileActions();
  }
  /*
   * We modified Scrabble.java to allow it to play 2 bots together,
   * We also added some functionality like printing average times
   */
  public static void main(String[] args) throws FileNotFoundException {

    Board board = new Board();
    Pool pool = new Pool();
    Player[] players = new Player[NUM_PLAYERS];
    UI ui = new UI();
    Robot Bobbot = new MoreComprehensiveBot();
    Robot Marthabot = new Bot();
    int currentPlayerId = 0, prevPlayerId;
    Player currentPlayer, prevPlayer;
    Frame currentFrame, prevFrame;
    Word word;
    char lowestTile;
    boolean tileDraw = false;
    String letters;
    char[] tiles = new char[NUM_PLAYERS];
    int commandCode, checkCode, totalWordScore;
    boolean frameWasFull, turnOver = false, gameOver = false, allOverPassLimit;
    int[] unusedScore = new int[NUM_PLAYERS];
    int totalUnused;
    boolean prevWasPlay = false, challengeDone = false;
    Dictionary dictionary = new Dictionary();

    // Initialize players
    ui.displayGameStart();
    for (int i = 0; i < NUM_PLAYERS; i++) {
      players[i] = new Player();
    }
    players[BOBBOT_ID].setName("Bob");
    players[MARTHABOT_ID].setName("Martha");

    // Decide who starts
    do {
      for (int i = 0; i < NUM_PLAYERS; i++) {
        tiles[i] = pool.getRandomTile().getFace();
        ui.displayTile(players[i], tiles[i]);
      }
      lowestTile = tiles[0];
      currentPlayerId = 0;
      tileDraw = false;
      for (int i = 1; i < NUM_PLAYERS; i++) {
        if (tiles[i] < lowestTile) {
          lowestTile = tiles[i];
          currentPlayerId = i;
          tileDraw = false;
        } else if (tiles[i] == lowestTile) {
          tileDraw = true;
        }
      }
      if (!tileDraw) {
        ui.displayStarter(players[currentPlayerId]);
      } else {
        ui.displayStarterDraw();
      }
    } while (tileDraw);

    // Play the game
    gameOver = false;
    do {
      currentPlayer = players[currentPlayerId];
      currentFrame = currentPlayer.getFrame();
      currentFrame.refill(pool);
      ui.displayBoard(board);
      ui.displayScores(players);
      ui.displayPoolSize(pool);
      challengeDone = false;
      do {
        if (currentPlayerId == BOBBOT_ID) {
          ui.displayPrompt(currentPlayer);
          commandCode = Bobbot.getCommand(currentPlayer, board, dictionary);
          ui.displayCommand(players[BOBBOT_ID], commandCode, Bobbot.getWord(), Bobbot.getLetters());
        } else {
          ui.displayPrompt(currentPlayer);
          commandCode = Marthabot.getCommand(currentPlayer, board, dictionary);
          ui.displayCommand(
              players[MARTHABOT_ID], commandCode, Marthabot.getWord(), Marthabot.getLetters());
        }
        switch (commandCode) {
          case UI.COMMAND_QUIT:
            turnOver = true;
            gameOver = true;
            break;
          case UI.COMMAND_PASS:
            turnOver = true;
            currentPlayer.pass();
            turnOver = true;
            allOverPassLimit = true;
            for (int i = 0; i < NUM_PLAYERS; i++) {
              allOverPassLimit = allOverPassLimit && players[i].isOverPassLimit();
            }
            if (allOverPassLimit) {
              gameOver = true;
            }
            prevWasPlay = false;
            break;
          case UI.COMMAND_HELP:
            ui.displayHelp();
            turnOver = false;
            break;
          case UI.COMMAND_EXCHANGE:
            if (currentPlayerId == BOBBOT_ID) {
              letters = Bobbot.getLetters();
            } else {
              letters = Marthabot.getLetters();
            }
            if (!currentFrame.isAvailable(letters)) {
              ui.displayError(UI.EXCHANGE_NOT_AVAILABLE);
              turnOver = false;
            } else if (pool.size() < letters.length()) {
              ui.displayError(UI.EXCHANGE_NOT_ENOUGH_IN_POOL);
              turnOver = false;
            } else {
              currentFrame.exchange(letters, pool);
              turnOver = true;
              prevWasPlay = false;
            }
            break;
          case UI.COMMAND_PLAY:
            if (currentPlayerId == BOBBOT_ID) {
              word = Bobbot.getWord();
            } else {
              word = Marthabot.getWord();
            }
            checkCode = board.checkWord(word, currentFrame);
            if (checkCode != UI.WORD_OK) {
              ui.displayError(checkCode);
              turnOver = false;
            } else {
              frameWasFull = currentFrame.isFull();
              totalWordScore = board.setWord(word, currentFrame);
              if (currentFrame.isEmpty() && frameWasFull) {
                totalWordScore = totalWordScore + BONUS;
              }
              ui.displayWordScore(totalWordScore);
              currentPlayer.addScore(totalWordScore);
              turnOver = true;
              prevWasPlay = true;
              if (currentFrame.isEmpty() && pool.isEmpty()) {
                gameOver = true;
              }
            }
            break;
          case UI.COMMAND_CHALLENGE:
            if (challengeDone) {
              ui.displayError(UI.CHALLENGE_REPEAT);
              turnOver = false;
            } else if (board.isFirstPlay()) {
              ui.displayError(UI.CHALLENGE_FIRST_PLAY);
              turnOver = false;
            } else if (!prevWasPlay) {
              ui.displayError(UI.CHALLENGE_PREV_NOT_PLAY);
              turnOver = false;
            } else if (!dictionary.areWords(board.getWords())) {
              ui.displayChallengeSuccess();
              prevPlayerId = currentPlayerId - 1;
              if (prevPlayerId < 0) {
                prevPlayerId = NUM_PLAYERS - 1;
              }
              prevPlayer = players[prevPlayerId];
              prevFrame = prevPlayer.getFrame();
              board.undo();
              prevPlayer.undo();
              prevFrame.undo();
              ui.displayBoard(board);
              ui.displayScores(players);
              ui.displayPoolSize(pool);
              challengeDone = true;
              turnOver = false;
            } else {
              ui.displayChallengeFail();
              turnOver = true;
              challengeDone = true;
              prevWasPlay = false;
            }
            break;
        }
      } while (!turnOver);
      if (!gameOver) {
        currentPlayerId++;
        if (currentPlayerId > NUM_PLAYERS - 1) {
          currentPlayerId = 0;
        }
      }
    } while (!gameOver);

    totalUnused = 0;
    for (int i = 0; i < NUM_PLAYERS; i++) {
      unusedScore[i] = players[i].unusedLettersScore();
      players[i].addScore(-unusedScore[i]);
      totalUnused = totalUnused + unusedScore[i];
    }
    if (unusedScore[currentPlayerId] == 0) {
      players[currentPlayerId].addScore(totalUnused);
    }
    ui.displayResult(players);
    System.out.println("Avg time for Bob: " + computeAvgTime(Bobbot));
    System.out.println("Avg time for Martha: " + computeAvgTime(Marthabot));
    System.out.println("GAME OVER");

    return;
  }
  private void debugOptions() {
    int choice = this.displayDebugMenu();
    while (choice != 0) {
      switch (choice) {
        case 1:
          Game.setDebugDice(!Game.getDebugDice());
          break;

        case 2:
          UI.displayBoard();
          int pos = -1;

          // keep asking while it's not positive number
          while ((pos = UI.askNgetInt("Where you want to jump?")) < 0) ;

          // if it's too big, inside the jump it will be fixed with MODULO
          Game.getCurrentPlayer().jumpTo(pos);
          break;

        case 3:
          Game.getBoard().tileActions();
          break;

        case 4:
          Long cash = -1L;

          while ((cash = UI.askNgetLong("How much cash you want to have?")) < 0) {
            // keep asking while it's not positive number
          }

          Game.getCurrentPlayer().setCash(cash);

          break;

        case 5:
          UI.displayBoard();
          int jail = -1;

          while ((jail = UI.askNgetInt("Jail time. How much?")) < 0) {
            // keep asking while it's not positive number
          }

          Game.getCurrentPlayer().setJailTime(jail);
          break;

        case 6:
          Game.getCardsCommunity().pickCard();
          break;

        case 7:
          Game.getCardsChance().pickCard();
          break;

        case 8:
          StdOut.println();
          StdOut.println("Community deck size: " + Game.getCardsCommunity().getCards().size());
          StdOut.println("Chance deck size:    " + Game.getCardsChance().getCards().size());
          StdOut.println();
          UI.pause();
          break;

        case 9:
          // it will allow you to switch even to non playing player, so be
          // careful
          ArrayList<Player> playersPlaying = Game.getPlayers();
          int swapTo =
              UI.displayMenuNGetChoice("Players", UI.playersToItems(playersPlaying), false, true);
          Game.setPlayersTurn(swapTo);
          break;

        case 10:
          UI.displayBoard();
          break;

        case 11:
          StdOut.println("Houses :" + Game.getBank().getAvailableHouses());
          StdOut.println("Hotels :" + Game.getBank().getAvailableHotels());
          Game.getBank()
              .setAvailableHouses(UI.askNgetInt("How many houses you want to have spare?"));
          Game.getBank()
              .setAvailableHotels(UI.askNgetInt("How many hotels you want to have spare?"));
          break;

        case 0:
        default:
          break;
      }
      if (choice != 0) choice = this.displayDebugMenu();
    }
  }