public class SnLBoard
{
  protected static final int numSnakes = 10;
  protected static final int spinnerSize = 6;
  protected static final int numLadders = 9; 
  protected static final int boardSize = 100;
  protected static String colors[] = 
  {
    "black", 
    "brown", 
    "red", 
    "orange", 
    "yellow", 
    "green", 
    "blue", 
    "violet", 
    "grey", 
    "white"
  };
  protected Space board[];
  protected Snake snakes[];
  protected Ladder ladders[]; 
  protected Piece players[];
  protected int numPlayers;

  public SnLBoard(int numPlayers)
  {
    this.numPlayers = numPlayers;
    if (numPlayers < 1 || numPlayers > 10)
    {
      System.out.println("Invalid number of players (10 or fewer please)");
      System.exit(1);
    }
    players = new Piece[numPlayers];
    for (int i = 0; i < numPlayers; i++)
    {
      players[i] = new Piece("A " + colors[i] + " playing piece", i+1);
    }

    ladders = new Ladder[numLadders]; 

    ladders[0] = new Ladder(1, 38);
    ladders[1] = new Ladder(4, 14);
    ladders[2] = new Ladder(9, 31);
    ladders[3] = new Ladder(21, 42);
    ladders[4] = new Ladder(28, 84);
    ladders[5] = new Ladder(36, 44);
    ladders[6] = new Ladder(51, 67);
    ladders[7] = new Ladder(71, 91); 
    ladders[8] = new Ladder(80, 100);

    snakes = new Snake[numSnakes];

    snakes[0] = new Snake(98, 78);
    snakes[1] = new Snake(96, 75);
    snakes[2] = new Snake(93, 73);
    snakes[3] = new Snake(87, 24);
    snakes[4] = new Snake(64, 60);
    snakes[5] = new Snake(62, 19);
    snakes[6] = new Snake(56, 53);
    snakes[7] = new Snake(49, 11);
    snakes[8] = new Snake(48, 26);
    snakes[9] = new Snake(16, 6);

    board = new Space[boardSize];

    for (int i = 0; i < boardSize; i++)
    {
      int boardLocation = i + 1;
      int adjust = 0;
      String description = "";

      description = "A square numbered " + boardLocation + "\n";
      for (int j = 0; j < Math.max(numLadders, numSnakes); j++)
      {

        if (j < numLadders && boardLocation == ladders[j].getBottom())
        {
          adjust = ladders[j].getTop() - ladders[j].getBottom();
          description += " The bottom rung of a ladder is here.\n";
        }
        else if(j < numSnakes && boardLocation == snakes[j].getMouth())
        {
          adjust = snakes[j].getTail() - snakes[j].getMouth();
          description += " A snake\'s head is here.  It\'s mouth is open!\n";
        }
        if (j < numLadders && boardLocation == ladders[j].getTop())
        {
          description += " The top rung of a ladder is here.\n";
        }
        if (j < numSnakes && boardLocation == snakes[j].getTail())
        {
          description += " The tail of a snake is here!\n";
        }
      }
      for (int j = 0; j < numPlayers; j++)
      {
        if(players[j].getWhere() == boardLocation)
        description = description + " " + players[j].toString() + " is here.\n";
      }
      board[i] = new Space(description, boardLocation, adjust);
    }
  }

  public String toString()
  {
    String retval = "";

    for (int i = 0; i < boardSize; i++)
    {
      retval += board[i].toString() + '\n';
    }
    return retval;
  }
  
  protected static void emit(String s)
  {
    System.out.println(s);
  }

  public int playGame(boolean verbose) // returns number of moves to finish game
  {
    Spinner s = new Spinner(spinnerSize, 1);
    boolean done = false;
    int numMoves = 0;
    int currentPlayer = 0;
    int spinVal = 0;
    int oldLoc = 0, newLoc = 0;
    String from = "";

    while(!done)
    {
      if (currentPlayer == 0) 
        numMoves++;
      oldLoc = players[currentPlayer].getWhere();
      spinVal = s.spin(); 
      newLoc = players[currentPlayer].move(spinVal);
      String prefix = "Player " + players[currentPlayer].getOrder();

      if (newLoc >= 100)
      {
        done = true;
        if (verbose)
          emit(prefix + " wins!");
        continue; //skip the rest of the body of the loop.  Go back to test the condition
      }

      if(verbose)
      {
        emit(prefix + " spins the spinner.");
        emit(s.toString());
        if (oldLoc == 0)
        {
          from = "off the board";
        }
        else
        {
          from = board[oldLoc - 1].toString();
        }
        emit(prefix + " moves " + players[currentPlayer] + " from " + from + " to " + 
            board[newLoc - 1].toString() );
      }
      oldLoc = newLoc;

      int adj = board[oldLoc-1].getAdjustment(); 
      newLoc = players[currentPlayer].move(adj);
      if (adj > 0) //We went up a ladder
      {
        if(verbose)
          emit(prefix + " climbed a ladder to " + board[newLoc - 1].toString() );
        oldLoc = newLoc; 
      }
      else if (adj < 0) //We were eaten by a snake
      {
        if(verbose)
          emit(prefix + " slid down a snake to " + board[newLoc - 1].toString() );
        oldLoc = newLoc; 
      }

      currentPlayer = (currentPlayer + 1) % numPlayers;
    }
    return numMoves;
  }      
      
         
 

  public static  void main(String args[])
  {
    int moves = 0;
    double average;
    SnLBoard snl = new SnLBoard(3);

    snl.playGame(true);
   
  }
    
}

