|
- /**
- * @file Player.java
- *
- * @author
- * Anastasia Foti AEM:8959
- * <anastaskf@ece.auth.gr>
- *
- * @author
- * Christos Choutouridis AEM:8997
- * <cchoutou@ece.auth.gr>
- */
-
- package host.labyrinth;
-
- import java.util.ArrayList;
- //import java.util.Arrays;
-
- /**
- * @brief
- * This class represents the game's player who cheats.
- */
- class HeuristicPlayer extends Player {
-
- /** @name Constructors */
- /** @{ */
- public HeuristicPlayer(String name, boolean champion, Board board, int row, int column) {
- super(name, champion, board, row, column);
- path = new ArrayList<Integer[]>();
- }
-
- public HeuristicPlayer(String name, boolean champion, Board board, int tileId) {
- super(name, champion, board, tileId);
- path = new ArrayList<Integer[]>();
- }
- /** @} */
-
- /** @name Board's main application interface */
- /** @{ */
-
- /**
- * Utility to get the distance of a possible supply in some direction
- * @param currentPos The current position of the player
- * @param direction The direction to check
- * @return The distance or Const.noSupply
- */
- int supplyInDirection(int currentPos, int direction) {
- Position pos = new Position(Position.toRow(currentPos), Position.toCol(currentPos));
-
- for (int i=0 ; board.isWalkable(pos.getId(), direction) && i<Const.viewDistance ; ++i) {
- pos = new Position(Position.toRow(pos.getId()), Position.toCol(pos.getId()), direction);
- if (board.hasSupply(pos.getId()))
- return i+1;
- }
- return Const.noSupply;
- }
-
- /**
- * Utility to get the distance of a possible opponent in some direction
- * @param currentPos The current position of the player
- * @param direction The direction to check
- * @return The distance or Const.noOpponent
- */
- int opponetInDirection(int currentPos, int direction) {
- Position pos = new Position(Position.toRow(currentPos), Position.toCol(currentPos));
- int [][] opps = board.getOpponentMoves(playerId);
-
- for (int i=0 ; board.isWalkable(pos.getId(), direction) && i<Const.viewDistance ; ++i) {
- pos = new Position(Position.toRow(pos.getId()), Position.toCol(pos.getId()), direction);
- for (int o =0 ; o<opps.length; ++o) {
- if (opps[o][0] == pos.getId())
- return i+1;
- }
- }
- return Const.noOpponent;
- }
-
- double evaluate (int currentPos, int dice) {
- int opDist = opponetInDirection (currentPos, dice);
- int supDist = supplyInDirection(currentPos, dice);
-
- // saturate
- opDist = (opDist == Const.noOpponent) ? Integer.MAX_VALUE : opDist;
- supDist = (supDist == Const.noSupply) ? Integer.MAX_VALUE : supDist;
- return 1.0/supDist * Const.supplyFactor
- - 1.0/opDist * Const.opponentFactor;
- }
-
- int directionOfMax (double[] eval, int[] eval_dir, int N) {
- double M = Double.NEGATIVE_INFINITY;
- int M_idx = -1;
- for (int i =0; i < N ; ++i) {
- if (eval[i] > M) {
- M = eval[i];
- M_idx = i;
- }
- }
- return eval_dir[M_idx];
- }
-
- boolean isUnevaluated (double[] eval, int N) {
- for (int i =0 ; i<N ; ++i)
- if (eval[i] != 0 && eval[i] != Double.NEGATIVE_INFINITY)
- return false;
- return true;
- }
-
- // Must return a new move always
- int getNextMove(int currentPos) {
- Range dirs = new Range(DirRange.Begin, DirRange.End, DirRange.Step);
- int N = dirs.size();
- double[] eval = new double[N];
- int [] eval_dir = new int[N];
-
- for (int i =0, dir = dirs.get() ; dir != Const.EOR ; dir = dirs.get(), ++i) {
- if (board.isWalkable(currentPos, dir))
- eval[i] = evaluate(currentPos, dir);
- else
- eval[i] = Double.NEGATIVE_INFINITY;
- eval_dir[i] = dir;
- }
- int dir;
- if (isUnevaluated(eval, N)) {
- ShuffledRange r = new ShuffledRange(DirRange.Begin, DirRange.End, DirRange.Step);
- do
- dir = r.get();
- while (!board.isWalkable(currentPos, dir));
- }
- else {
- dir = directionOfMax (eval, eval_dir, N);
- }
- Position new_pos = new Position( Position.toRow(currentPos), Position.toCol(currentPos), dir );
- return new_pos.getId();
- }
-
- /**
- * HeuristicPlayer's move.
- *
- * A player of this kind cheats. He does not throw a dice to get a direction. In contrary he
- * calculates his next move very carefully.
- * If the player is a champion then he also picks up a possible supply from the tile.
- *
- * @param id The id of the starting tile.
- * @return An array containing player's final position and possible supply of that position.
- * The array format is:
- * <ul>
- * <li> int[0]: The tileId of the final player's position.
- * <li> int[1]: The row of the final player's position.
- * <li> int[2]: The column of the final player's position.
- * <li> int[3]: The supplyId in case player picked one (Const.noSupply otherwise).
- * </ul>
- */
- int[] move(int id) {
- // Initialize return array with the current data
- int[] ret = new int[Const.moveItems];
- ret[0] = getNextMove(id);
- ret[1] = y = Position.toRow(ret[0]);
- ret[2] = x = Position.toCol(ret[0]);
- int supplyFlag = 0;
- // In case of a champion player, try also to pick a supply
- if (champion && (ret[3] = board.tryPickSupply(ret[0])) != Const.noSupply) {
- ++score; // keep score
- ++supplyFlag;
- System.out.println(name + ":\t*Found a supply. [score: " + score + "]");
- }
- board.updateMove(ret, playerId);
-
- // Update supply and opponent distance
- int dir = Direction.get(id, ret[0]);
- int smin =DirRange.End, omin =DirRange.End;
- for (int d = DirRange.Begin ; d<DirRange.End ; d += DirRange.Step) {
- int s = supplyInDirection (ret[0], d);
- int o = opponetInDirection(ret[0], d);
- if (s < smin) smin = s;
- if (o < omin) omin = o;
- }
- Integer[] p = {dir, supplyFlag, smin, omin };
-
- path.add(p);
- return ret;
- }
-
- /** @} */
- /** @name Class data */
- /** @{ */
- private ArrayList<Integer[]> path; /**< our history
- * The integer[] format is:
- * { dice, tookSupply, SupplyDistance, OpponentDistance}
- */
-
- /** @} */
- }
|