/** * @file HeuristicPlayer.java * * @author * Anastasia Foti AEM:8959 * * * @author * Christos Choutouridis AEM:8997 * */ package host.labyrinth; /** * @brief * This class represents the game's player who cheats. */ class HeuristicPlayer extends Player { /** @name Constructors */ /** @{ */ /** * Create a new player and put him at the row-column coordinates * @param name The name of the player * @param champion Flag to indicate if a player is a `champion` * @param board Reference to the board of the game * @param row The row coordinate of initial player position * @param column The column coordinate of initial player's position */ public HeuristicPlayer(String name, boolean champion, Board board, int row, int column) throws Exception { super(name, champion, board, row, column); } /** * Create a new player and put him at the row-column coordinates * @param name The name of the player * @param champion Flag to indicate if a player is a `champion` * @param board Reference to the board of the game * @param tileId The tileId coordinate of player's initial position */ public HeuristicPlayer(String name, boolean champion, Board board, int tileId) throws Exception { super(name, champion, board, tileId); } /** @} */ /** @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 *
  • int[0]: The tileId of the final player's position. *
  • int[1]: The row of the final player's position. *
  • int[2]: The column of the final player's position. *
  • int[3]: The dice/direction of the move. * */ @Override int[] move(int id) { // Initialize return array with the current data int[] ret = getNextMove(id); y = Position.toRow(ret[MOVE_TILE_ID]); x = Position.toCol(ret[MOVE_TILE_ID]); int supplyFlag =0, moveFlag =1; // In case of a champion player, try also to pick a supply if (champion && (board.tryPickSupply(ret[MOVE_TILE_ID]) != Const.noSupply)) { ++score; // keep score ++supplyFlag; } ++dirCounter[ret[MOVE_DICE]]; // update direction counters board.updateMove(ret, playerId); // Update supply and opponent distance int smin =DirRange.End, omin =DirRange.End; for (int d = DirRange.Begin ; d= 0 && s < smin) smin = s; if (o >= 0 && o < omin) omin = o; } // update path Integer[] p = { ret[MOVE_TILE_ID], ret[MOVE_DICE], moveFlag, supplyFlag, dirCounter[Direction.UP], dirCounter[Direction.RIGHT], dirCounter[Direction.DOWN], dirCounter[Direction.LEFT], (smin != DirRange.End)? smin:Const.noSupply, (omin != DirRange.End)? omin:Const.noOpponent }; path.add(p); return ret; } /** * Prints round information for the player */ void statistics() { if (!path.isEmpty()) { Integer[] last = path.get(path.size()-1); String who = String.format("%12s", name); System.out.print(who + ": score[" + score + "]" + ", dice =" + last[1] + ", tileId =" + last[0] + " (" + Position.toRow(last[0]) + ", " + Position.toCol(last[0]) + ")"); if (last[2] == 0) System.out.println(" *Can not move."); else if (last[3] != 0) System.out.println(" *Found a supply."); else System.out.println(""); // extra prints for heuristic if (last[8] != Const.noSupply) System.out.println(" supply =" + last[8]); else System.out.println(" supply = blind"); if (last[9] != Const.noOpponent) System.out.println(" opponent =" + last[9]); else System.out.println(" opponent = blind"); } } /** * Prints final statistics for the player */ void final_statistics () { String who = String.format("%12s", name); System.out.println(); System.out.println(who + ": score[" + score + "]"); System.out.println(" Moves up: " + dirCounter[Direction.UP]); System.out.println(" Moves right: " + dirCounter[Direction.RIGHT]); System.out.println(" Moves down: " + dirCounter[Direction.DOWN]); System.out.println(" Moves left: " + dirCounter[Direction.LEFT]); } /** @} */ /** * A small utility to extract the direction of maximum evaluation result. * * We search into the \c eval results and find the index of the maximum evaluation. * Then we return the direction of \c eval_dir matrix at the same index we found. * * @param eval Array with evaluation results for each direction * @param eval_dir Array with the matching direction to \c eval array * @param N The size of both arrays * @return The direction of maximum evaluation. If \c eval is empty returns the first item \c eval[0] * @note * This function should not be called if there is at least one evaluation result in \c eval */ private int directionOfMax (double[] eval, int[] eval_dir, int N) { double M = Double.NEGATIVE_INFINITY; int M_idx = 0; for (int i =0; i < N ; ++i) { if (eval[i] > M) { M = eval[i]; M_idx = i; } } return eval_dir[M_idx]; } /** * A small utility to check if there is at least one evaluation result in the \c eval array * @param eval The array to check * @param N The size of the array * @return True if there is none, false otherwise */ private boolean isUnevaluated (double[] eval, int N) { for (int i =0 ; i