You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

245 lines
9.5 KiB

  1. /**
  2. * @file Player.java
  3. *
  4. * @author
  5. * Anastasia Foti AEM:8959
  6. * <anastaskf@ece.auth.gr>
  7. *
  8. * @author
  9. * Christos Choutouridis AEM:8997
  10. * <cchoutou@ece.auth.gr>
  11. */
  12. package host.labyrinth;
  13. import java.util.ArrayList;
  14. /**
  15. * @brief
  16. * This class represents the game's player
  17. */
  18. class Player {
  19. /** Helper variables to keep track of the move() return values @see move() */
  20. static final int MOVE_DATA_SIZE = 4; /**< The move return data array size */
  21. static final int MOVE_TILE_ID = 0; /**< Index of the tileId information of the move */
  22. static final int MOVE_ROW = 1; /**< The index of row information */
  23. static final int MOVE_COLUMN = 2; /**< The index of column information */
  24. static final int MOVE_DICE = 3; /**< The index of dice information */
  25. /** @name Constructors */
  26. /** @{ */
  27. /**
  28. * Create a new player and put him at the row-column coordinates
  29. * @param name The name of the player
  30. * @param champion Flag to indicate if a player is a `champion`
  31. * @param board Reference to the board of the game
  32. * @param row The row coordinate of initial player position
  33. * @param column The column coordinate of initial player's position
  34. */
  35. Player(String name, boolean champion, Board board, int row, int column) throws Exception {
  36. this.playerId = board.generatePlayerId();
  37. this.name = name;
  38. this.board = board;
  39. this.score = 0;
  40. this.x = column;
  41. this.y = row;
  42. this.champion = champion;
  43. this.dirCounter= new int[DirRange.End]; // yes we spoil some memory. Java is the worst.
  44. this.path = new ArrayList<Integer[]>();
  45. int[] m = {
  46. Position.toID(row, column), row, column, Const.noSupply
  47. };
  48. board.updateMove(m, playerId);
  49. }
  50. /**
  51. * Create a new player and put him at the row-column coordinates
  52. * @param name The name of the player
  53. * @param champion Flag to indicate if a player is a `champion`
  54. * @param board Reference to the board of the game
  55. * @param tileId The tileId coordinate of player's initial position
  56. */
  57. Player(String name, boolean champion, Board board, int tileId) throws Exception {
  58. this.playerId = board.generatePlayerId();
  59. this.name = name;
  60. this.board = board;
  61. this.score = 0;
  62. this.x = Position.toCol(tileId);
  63. this.y = Position.toRow(tileId);
  64. this.champion = champion;
  65. this.dirCounter= new int[DirRange.End]; // yes we spoil some memory. Java is the worst.
  66. this.path = new ArrayList<Integer[]>();
  67. int[] m = {
  68. tileId, Position.toRow(tileId), Position.toCol(tileId), Const.noSupply
  69. };
  70. board.updateMove(m, playerId);
  71. }
  72. /** @} */
  73. /** @name Player main application interface */
  74. /** @{ */
  75. /**
  76. * Player's move.
  77. *
  78. * A player first throws a dice to get a random direction. Then checks if the direction
  79. * is walkable. If it is, then goes to that tile and update player's data.
  80. * If the player is a champion then he also picks up a possible supply from the tile.
  81. *
  82. * @param id The id of the starting tile.
  83. * @return An array containing player's final position and possible supply of that position.
  84. * The array format is:
  85. * <ul>
  86. * <li> int[0]: The tileId of the final player's position.
  87. * <li> int[1]: The row of the final player's position.
  88. * <li> int[2]: The column of the final player's position.
  89. * <li> int[3]: The dice/direction of the move.
  90. * </ul>
  91. */
  92. int[] move(int id) {
  93. // Initialize return array with the current data
  94. int[] ret = new int[MOVE_DATA_SIZE];
  95. ret[MOVE_TILE_ID] = id;
  96. ret[MOVE_ROW] = Position.toRow(id);
  97. ret[MOVE_COLUMN] = Position.toCol(id);
  98. ret[MOVE_DICE] = Direction.NONE;
  99. int supplyFlag =0, moveFlag =0;
  100. int diceDirection;
  101. do
  102. diceDirection = board.dice(); // throw the dice
  103. while (!board.isWalkable(id, diceDirection));
  104. moveFlag =1; // mark the successful move
  105. // Get next tile
  106. Position next = new Position(Position.toRow(id), Position.toCol(id), diceDirection);
  107. ret[MOVE_TILE_ID] = next.getId(); // Update move's return data
  108. ret[MOVE_ROW] = y = next.getRow();
  109. ret[MOVE_COLUMN] = x = next.getCol();
  110. ret[MOVE_DICE] = diceDirection;
  111. // In case of a champion player, try also to pick a supply
  112. if (champion && (board.tryPickSupply(next.getId()) != Const.noSupply)) {
  113. supplyFlag =1; // mark the successful supply pickup
  114. ++score; // keep score
  115. }
  116. ++dirCounter[diceDirection]; // update direction counters
  117. board.updateMove(ret, playerId);
  118. // update path
  119. Integer[] p = {
  120. ret[MOVE_TILE_ID], diceDirection, moveFlag, supplyFlag,
  121. dirCounter[Direction.UP], dirCounter[Direction.RIGHT], dirCounter[Direction.DOWN], dirCounter[Direction.LEFT],
  122. Const.noSupply, Const.noOpponent
  123. };
  124. path.add(p);
  125. return ret;
  126. }
  127. /**
  128. * Prints round information for the player
  129. */
  130. void statistics() {
  131. if (!path.isEmpty()) {
  132. Integer[] last = path.get(path.size()-1);
  133. String who = String.format("%12s", name);
  134. System.out.print(who + ": score[" + score + "]" + ", dice =" + last[1] + ", tileId =" + last[0] + " (" + Position.toRow(last[0]) + ", " + Position.toCol(last[0]) + ")");
  135. if (last[2] == 0)
  136. System.out.println(" *Can not move.");
  137. else if (last[3] != 0)
  138. System.out.println(" *Found a supply.");
  139. else
  140. System.out.println("");
  141. }
  142. }
  143. /**
  144. * Prints final statistics for the player
  145. * @note
  146. * We add this final_statistics() wrapper in order to provide polymorphism to
  147. * Player class hierarchy and to be sure that we are not braking the
  148. * Liskov substitution principle
  149. * @see https://en.wikipedia.org/wiki/Liskov_substitution_principle
  150. */
  151. void final_statistics () { }
  152. /** Utility to access player's tileID */
  153. int playerTileId() { return Position.toID(y, x); }
  154. /** Utility to access player's row position (row coordinate) */
  155. int playerRow() { return y; }
  156. /** Utility to access player's column position (column coordinate) */
  157. int playerCol() { return x; }
  158. /** @} */
  159. /**
  160. * @name Accessor/Mutator interface
  161. * @note
  162. * Please consider not to use mutator interface. Its the abstraction killer :(
  163. * We have added a bit of logic however, in order to make it a bit more safe.
  164. */
  165. /** @{ */
  166. int getPlayerId () { return playerId; }
  167. String getName() { return name; }
  168. Board getBoard () { return board; }
  169. int getScore () { return score; }
  170. int getX() { return x; }
  171. int getY() { return y; }
  172. boolean getChampion(){ return champion; }
  173. int[] getDirCounter(){ return dirCounter; }
  174. ArrayList<Integer[]> getPath() {
  175. return path;
  176. }
  177. void setPlayerId(int id) { playerId = id; }
  178. void setName(String name) { this.name = name; }
  179. void setBoard (Board board){ this.board = board; }
  180. void setScore(int score) { this.score = score; }
  181. void setX(int x) {
  182. assert (x >= 0 && x< Session.boardSize) : "X(column) coordinate must be in the range [0, Session.boardSize)";
  183. this.x = x;
  184. }
  185. void setY(int y) {
  186. assert (y >= 0 && y< Session.boardSize) : "Y(row) coordinate must be in the range [0, Session.boardSize)";
  187. this.y = y;
  188. }
  189. void setChampion (boolean champion) {
  190. this.champion = champion;
  191. }
  192. public void setDirCounter(int[] dirCounter) {
  193. this.dirCounter = dirCounter;
  194. }
  195. public void setPath(ArrayList<Integer[]> path) {
  196. this.path = path;
  197. }
  198. /** @} */
  199. /** @name Class data */
  200. /** @{ */
  201. protected int playerId; /**< The unique identifier of the player */
  202. protected String name; /**< The name of the player */
  203. protected Board board; /**< Reference to the session's boards */
  204. protected int score; /**< The current score of the player */
  205. protected int x; /**< The column coordinate of the player on the board */
  206. protected int y; /**< The row coordinate of the player on the board */
  207. protected boolean champion; /**< Champion indicate a player who plays against the Minotaur */
  208. protected int dirCounter[];
  209. protected ArrayList<Integer[]> path;
  210. /**<
  211. * our history. The integer[] format is:
  212. * <ul>
  213. * <li> Integer[0]: tileId - The tile id we choose for the move
  214. * <li> Integer[1]: dice - The dice (a.k.a direction) of move
  215. * <li> Integer[2]: moveStatus - True if it was successful (we can move in that direction)
  216. * <li> Integer[3]: tookSupply - True if we took supply
  217. * <li> Integer[4]: upCounter - Accumulator to count all the up moves
  218. * <li> Integer[5]: righrCounter - Accumulator to count all the right moves
  219. * <li> Integer[6]: downCounter - Accumulator to count all the down moves
  220. * <li> Integer[7]: leftCounter - Accumulator to count all the left moves
  221. * <li> Integer[8]: SupDistance - The distance of the nearest supply (only for heuristic players)
  222. * <li> Integer[9]: OppDistance - The distance of the nearest opponent (only for heuristic players)
  223. * </ul>
  224. * }
  225. */
  226. /** @} */
  227. }