/*
 * Player objects are general classes of algorithms for making decisions in games to be
 * implemented among other things by PlayImplementor in tandem with Game objects.
 
 * The move and update methods are to be used pairwise by PlayImplementor to obtain the 
 * player's decision and take account of received rewards respectively.
 */
public abstract class Player {
  /*
   * Each player object will keep track of its game-state and trial number in order to 
   * implement move at any time for the current situation. Each player will also have 
   * complete knowledge of the game they play.
   */
  protected int currentState;
  protected int currentTrial;
  protected final int NUM_STATES;
  protected final int NUM_PLAYERS;
  protected final int NUM_ACTIONS;
  protected final int NUM_TRIALS;
  protected final int[][][] UTILITIES;
  protected final double[][][] WORLD;
  
  /*
   * The super constructor passes in the general fields.
   */
  
  public Player(int states, int players, int actions, int trials, int[][][] feelings, double[][][] gameGraph){
    currentState = 0;
    currentTrial = 1;
    NUM_STATES = states;
    NUM_PLAYERS = players;
    NUM_ACTIONS = actions;
    NUM_TRIALS = trials;
    UTILITIES = feelings;
    WORLD = gameGraph;
  }
  
  /*
   * Move returns the player's decision in its current state. The method may be called any 
   * number of times by any number of methods with stochastically independent results. The 
   * method will throw an exception if its inputs are in error. Otherwise it will return a 
   * nonnegative integer representing its chosen action.
   
   * Update increments the fields and makes any algorithm-specific changes to internal 
   * state that correspond to receipt of rewards and change of game-state.
   
   * IsNew outputs true iff the player has not yet updated its internal state from its 
   * start state.
   
   * CanPlay outputs true iff the player is has compatible fields with the inputted game.
   */
  
  public abstract int move() throws IllegalStateException;
  public abstract void update(int action, int utility, int newState);
  public abstract boolean isNew();
  public abstract boolean canPlay(Game system);
}