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.

192 lines
6.4 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. //import java.util.Arrays;
  15. /**
  16. * @brief
  17. * This class represents the game's player who cheats.
  18. */
  19. class HeuristicPlayer extends Player {
  20. /** @name Constructors */
  21. /** @{ */
  22. public HeuristicPlayer(String name, boolean champion, Board board, int row, int column) {
  23. super(name, champion, board, row, column);
  24. path = new ArrayList<Integer[]>();
  25. }
  26. public HeuristicPlayer(String name, boolean champion, Board board, int tileId) {
  27. super(name, champion, board, tileId);
  28. path = new ArrayList<Integer[]>();
  29. }
  30. /** @} */
  31. /** @name Board's main application interface */
  32. /** @{ */
  33. /**
  34. * Utility to get the distance of a possible supply in some direction
  35. * @param currentPos The current position of the player
  36. * @param direction The direction to check
  37. * @return The distance or Const.noSupply
  38. */
  39. int supplyInDirection(int currentPos, int direction) {
  40. Position pos = new Position(Position.toRow(currentPos), Position.toCol(currentPos));
  41. for (int i=0 ; board.isWalkable(pos.getId(), direction) && i<Const.viewDistance ; ++i) {
  42. pos = new Position(Position.toRow(pos.getId()), Position.toCol(pos.getId()), direction);
  43. if (board.hasSupply(pos.getId()))
  44. return i+1;
  45. }
  46. return Const.noSupply;
  47. }
  48. /**
  49. * Utility to get the distance of a possible opponent in some direction
  50. * @param currentPos The current position of the player
  51. * @param direction The direction to check
  52. * @return The distance or Const.noOpponent
  53. */
  54. int opponetInDirection(int currentPos, int direction) {
  55. Position pos = new Position(Position.toRow(currentPos), Position.toCol(currentPos));
  56. int [][] opps = board.getOpponentMoves(playerId);
  57. for (int i=0 ; board.isWalkable(pos.getId(), direction) && i<Const.viewDistance ; ++i) {
  58. pos = new Position(Position.toRow(pos.getId()), Position.toCol(pos.getId()), direction);
  59. for (int o =0 ; o<opps.length; ++o) {
  60. if (opps[o][0] == pos.getId())
  61. return i+1;
  62. }
  63. }
  64. return Const.noOpponent;
  65. }
  66. double evaluate (int currentPos, int dice) {
  67. int opDist = opponetInDirection (currentPos, dice);
  68. int supDist = supplyInDirection(currentPos, dice);
  69. // saturate
  70. opDist = (opDist == Const.noOpponent) ? Integer.MAX_VALUE : opDist;
  71. supDist = (supDist == Const.noSupply) ? Integer.MAX_VALUE : supDist;
  72. return 1.0/supDist * Const.supplyFactor
  73. - 1.0/opDist * Const.opponentFactor;
  74. }
  75. int directionOfMax (double[] eval, int[] eval_dir, int N) {
  76. double M = Double.NEGATIVE_INFINITY;
  77. int M_idx = -1;
  78. for (int i =0; i < N ; ++i) {
  79. if (eval[i] > M) {
  80. M = eval[i];
  81. M_idx = i;
  82. }
  83. }
  84. return eval_dir[M_idx];
  85. }
  86. boolean isUnevaluated (double[] eval, int N) {
  87. for (int i =0 ; i<N ; ++i)
  88. if (eval[i] != 0 && eval[i] != Double.NEGATIVE_INFINITY)
  89. return false;
  90. return true;
  91. }
  92. // Must return a new move always
  93. int getNextMove(int currentPos) {
  94. Range dirs = new Range(DirRange.Begin, DirRange.End, DirRange.Step);
  95. int N = dirs.size();
  96. double[] eval = new double[N];
  97. int [] eval_dir = new int[N];
  98. for (int i =0, dir = dirs.get() ; dir != Const.EOR ; dir = dirs.get(), ++i) {
  99. if (board.isWalkable(currentPos, dir))
  100. eval[i] = evaluate(currentPos, dir);
  101. else
  102. eval[i] = Double.NEGATIVE_INFINITY;
  103. eval_dir[i] = dir;
  104. }
  105. int dir;
  106. if (isUnevaluated(eval, N)) {
  107. ShuffledRange r = new ShuffledRange(DirRange.Begin, DirRange.End, DirRange.Step);
  108. do
  109. dir = r.get();
  110. while (!board.isWalkable(currentPos, dir));
  111. }
  112. else {
  113. dir = directionOfMax (eval, eval_dir, N);
  114. }
  115. Position new_pos = new Position( Position.toRow(currentPos), Position.toCol(currentPos), dir );
  116. return new_pos.getId();
  117. }
  118. /**
  119. * HeuristicPlayer's move.
  120. *
  121. * A player of this kind cheats. He does not throw a dice to get a direction. In contrary he
  122. * calculates his next move very carefully.
  123. * If the player is a champion then he also picks up a possible supply from the tile.
  124. *
  125. * @param id The id of the starting tile.
  126. * @return An array containing player's final position and possible supply of that position.
  127. * The array format is:
  128. * <ul>
  129. * <li> int[0]: The tileId of the final player's position.
  130. * <li> int[1]: The row of the final player's position.
  131. * <li> int[2]: The column of the final player's position.
  132. * <li> int[3]: The supplyId in case player picked one (Const.noSupply otherwise).
  133. * </ul>
  134. */
  135. int[] move(int id) {
  136. // Initialize return array with the current data
  137. int[] ret = new int[Const.moveItems];
  138. ret[0] = getNextMove(id);
  139. ret[1] = y = Position.toRow(ret[0]);
  140. ret[2] = x = Position.toCol(ret[0]);
  141. int supplyFlag = 0;
  142. // In case of a champion player, try also to pick a supply
  143. if (champion && (ret[3] = board.tryPickSupply(ret[0])) != Const.noSupply) {
  144. ++score; // keep score
  145. ++supplyFlag;
  146. System.out.println(name + ":\t*Found a supply. [score: " + score + "]");
  147. }
  148. board.updateMove(ret, playerId);
  149. // Update supply and opponent distance
  150. int dir = Direction.get(id, ret[0]);
  151. int smin =DirRange.End, omin =DirRange.End;
  152. for (int d = DirRange.Begin ; d<DirRange.End ; d += DirRange.Step) {
  153. int s = supplyInDirection (ret[0], d);
  154. int o = opponetInDirection(ret[0], d);
  155. if (s < smin) smin = s;
  156. if (o < omin) omin = o;
  157. }
  158. Integer[] p = {dir, supplyFlag, smin, omin };
  159. path.add(p);
  160. return ret;
  161. }
  162. /** @} */
  163. /** @name Class data */
  164. /** @{ */
  165. private ArrayList<Integer[]> path; /**< our history
  166. * The integer[] format is:
  167. * { dice, tookSupply, SupplyDistance, OpponentDistance}
  168. */
  169. /** @} */
  170. }