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.

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