/** * Sets the game state from a string: the inverse of getGameState(). It reconstructs all the * game's variables from the string. * * @param gameState The game state represented as a string */ public void setGameState(String gameState) { String[] values = gameState.split(","); int index = 0; indiceDeLaberinto = Integer.parseInt(values[index++]); tiempoTotal = Integer.parseInt(values[index++]); score = Integer.parseInt(values[index++]); tiempoLvlActual = Integer.parseInt(values[index++]); cuentaElLvl = Integer.parseInt(values[index++]); pacman = new PacMan( Integer.parseInt(values[index++]), MOVE.valueOf(values[index++]), Integer.parseInt(values[index++]), Boolean.parseBoolean(values[index++])); fantasmas = new EnumMap<GHOST, Ghost>(GHOST.class); for (GHOST ghostType : GHOST.values()) fantasmas.put( ghostType, new Ghost( ghostType, Integer.parseInt(values[index++]), Integer.parseInt(values[index++]), Integer.parseInt(values[index++]), MOVE.valueOf(values[index++]))); _setPills(laberintoActua = laberintos[indiceDeLaberinto]); for (int i = 0; i < values[index].length(); i++) if (values[index].charAt(i) == '1') pills.set(i); else pills.clear(i); index++; for (int i = 0; i < values[index].length(); i++) if (values[index].charAt(i) == '1') powerPills.set(i); else powerPills.clear(i); timeOfLastGlobalReversal = Integer.parseInt(values[++index]); pacmanFueComido = Boolean.parseBoolean(values[++index]); fantasmaComido = new EnumMap<GHOST, Boolean>(GHOST.class); for (GHOST ghost : GHOST.values()) fantasmaComido.put(ghost, Boolean.parseBoolean(values[++index])); pastillaFueComida = Boolean.parseBoolean(values[++index]); pildoraPoderFueComida = Boolean.parseBoolean(values[++index]); }
private EnumMap<GHOST, MOVE> _completeGhostMoves(EnumMap<GHOST, MOVE> moves) { if (moves == null) { moves = new EnumMap<GHOST, MOVE>(GHOST.class); for (GHOST ghostType : GHOST.values()) moves.put(ghostType, fantasmas.get(ghostType).lastMoveMade); } if (moves.size() < NUM_GHOSTS) for (GHOST ghostType : GHOST.values()) if (!moves.containsKey(ghostType)) moves.put(ghostType, MOVE.NEUTRAL); return moves; }
@Override public MOVE getMove(Game game, long timeDue) { int current = game.getPacmanCurrentNodeIndex(); // Strategy 1: if any non-edible ghost is too close (less than MIN_DISTANCE), run away for (GHOST ghost : GHOST.values()) if (game.getGhostEdibleTime(ghost) == 0 && game.getGhostLairTime(ghost) == 0) if (game.getShortestPathDistance(current, game.getGhostCurrentNodeIndex(ghost)) < MIN_DISTANCE) return game.getNextMoveAwayFromTarget( game.getPacmanCurrentNodeIndex(), game.getGhostCurrentNodeIndex(ghost), DM.PATH); // Strategy 2: find the nearest edible ghost and go after them int minDistance = Integer.MAX_VALUE; GHOST minGhost = null; for (GHOST ghost : GHOST.values()) if (game.getGhostEdibleTime(ghost) > 0) { int distance = game.getShortestPathDistance(current, game.getGhostCurrentNodeIndex(ghost)); if (distance < minDistance) { minDistance = distance; minGhost = ghost; } } if (minGhost != null) // we found an edible ghost return game.getNextMoveTowardsTarget( game.getPacmanCurrentNodeIndex(), game.getGhostCurrentNodeIndex(minGhost), DM.PATH); // Strategy 3: go after the pills and power pills int[] pills = game.getPillIndices(); int[] powerPills = game.getPowerPillIndices(); ArrayList<Integer> targets = new ArrayList<Integer>(); for (int i = 0; i < pills.length; i++) // check which pills are available if (game.isPillStillAvailable(i)) targets.add(pills[i]); for (int i = 0; i < powerPills.length; i++) // check with power pills are available if (game.isPowerPillStillAvailable(i)) targets.add(powerPills[i]); int[] targetsArray = new int[targets.size()]; // convert from ArrayList to array for (int i = 0; i < targetsArray.length; i++) targetsArray[i] = targets.get(i); // return the next direction once the closest target has been identified return game.getNextMoveTowardsTarget( current, game.getClosestNodeIndexFromNodeIndex(current, targetsArray, DM.PATH), DM.PATH); }
public int getNumGhostsEaten() { int count = 0; for (GHOST ghost : GHOST.values()) if (fantasmaComido.get(ghost)) count++; return count; }
/** * Returns an exact copy of the game. This may be used for forward searches such as minimax. The * copying is relatively efficient. * * @return the game */ public Game copy() { Game copy = new Game(); copy.seed = seed; copy.rnd = new Random(seed); copy.laberintoActua = laberintoActua; copy.pills = (BitSet) pills.clone(); copy.powerPills = (BitSet) powerPills.clone(); copy.indiceDeLaberinto = indiceDeLaberinto; copy.cuentaElLvl = cuentaElLvl; copy.tiempoLvlActual = tiempoLvlActual; copy.tiempoTotal = tiempoTotal; copy.score = score; copy.fastamasComerMultiplicador = fastamasComerMultiplicador; copy.juegoTerminado = juegoTerminado; copy.timeOfLastGlobalReversal = timeOfLastGlobalReversal; copy.pacmanFueComido = pacmanFueComido; copy.pastillaFueComida = pastillaFueComida; copy.pildoraPoderFueComida = pildoraPoderFueComida; copy.pacman = pacman.copy(); copy.fantasmaComido = new EnumMap<GHOST, Boolean>(GHOST.class); copy.fantasmas = new EnumMap<GHOST, Ghost>(GHOST.class); for (GHOST ghostType : GHOST.values()) { copy.fantasmas.put(ghostType, fantasmas.get(ghostType).copy()); copy.fantasmaComido.put(ghostType, fantasmaComido.get(ghostType)); } return copy; }
/* (non-Javadoc) * @see pacman.controllers.Controller#getMove(pacman.game.Game, long) */ public EnumMap<GHOST, MOVE> getMove(Game game, long timeDue) { int pacmanIndex = game.getPacmanCurrentNodeIndex(); for (GHOST ghost : GHOST.values()) { if (game.doesGhostRequireAction(ghost)) { int currentIndex = game.getGhostCurrentNodeIndex(ghost); // if ghosts are all in close proximity and not near Ms Pac-Man, disperse if (isCrowded(game) && !closeToMsPacMan(game, currentIndex)) myMoves.put(ghost, getRetreatActions(game, ghost)); // go towards the power pill locations // if edible or Ms Pac-Man is close to power pill, move away from Ms Pac-Man else if (game.getGhostEdibleTime(ghost) > 0 || closeToPower(game)) myMoves.put( ghost, game.getApproximateNextMoveAwayFromTarget( currentIndex, pacmanIndex, game.getGhostLastMoveMade(ghost), DM.PATH)); // move away from ms pacman // else go towards Ms Pac-Man else myMoves.put( ghost, game.getApproximateNextMoveTowardsTarget( currentIndex, pacmanIndex, game.getGhostLastMoveMade(ghost), DM.PATH)); // go towards ms pacman } } return myMoves; }
/** * Checks if is crowded. * * @param game the game * @return true, if is crowded */ private boolean isCrowded(Game game) { GHOST[] ghosts = GHOST.values(); float distance = 0; for (int i = 0; i < ghosts.length - 1; i++) for (int j = i + 1; j < ghosts.length; j++) distance += game.getShortestPathDistance( game.getGhostCurrentNodeIndex(ghosts[i]), game.getGhostCurrentNodeIndex(ghosts[j])); return (distance / 6) < CROWDED_DISTANCE ? true : false; }
/** _init ghosts. */ private void _initGhosts() { fantasmas = new EnumMap<GHOST, Ghost>(GHOST.class); for (GHOST ghostType : GHOST.values()) fantasmas.put( ghostType, new Ghost( ghostType, laberintoActua.lairNodeIndex, 0, (int) (ghostType.initialLairTime * (Math.pow(LAIR_REDUCTION, cuentaElLvl % LEVEL_RESET_REDUCTION))), MOVE.NEUTRAL)); }
/** * _init. * * @param initialMaze the initial maze */ private void _init(int initialMaze) { indiceDeLaberinto = initialMaze; score = tiempoLvlActual = cuentaElLvl = tiempoTotal = 0; fastamasComerMultiplicador = 1; juegoTerminado = false; timeOfLastGlobalReversal = -1; pacmanFueComido = false; pastillaFueComida = false; pildoraPoderFueComida = false; fantasmaComido = new EnumMap<GHOST, Boolean>(GHOST.class); for (GHOST ghost : GHOST.values()) fantasmaComido.put(ghost, false); _setPills(laberintoActua = laberintos[indiceDeLaberinto]); _initGhosts(); pacman = new PacMan(laberintoActua.initialPacManNodeIndex, MOVE.LEFT, NUM_LIVES, false); }
/** _feast. */ private void _feast() { pacmanFueComido = false; for (GHOST ghost : GHOST.values()) fantasmaComido.put(ghost, false); for (Ghost ghost : fantasmas.values()) { int distance = getShortestPathDistance(pacman.currentNodeIndex, ghost.currentNodeIndex); if (distance <= EAT_DISTANCE && distance != -1) { if (ghost.edibleTime > 0) // pac-man eats ghost { score += GHOST_EAT_SCORE * fastamasComerMultiplicador; fastamasComerMultiplicador *= 2; ghost.edibleTime = 0; ghost.lairTime = (int) (COMMON_LAIR_TIME * (Math.pow(LAIR_REDUCTION, cuentaElLvl % LEVEL_RESET_REDUCTION))); ghost.currentNodeIndex = laberintoActua.lairNodeIndex; ghost.lastMoveMade = MOVE.NEUTRAL; fantasmaComido.put(ghost.type, true); } else // ghost eats pac-man { pacman.numberOfLivesRemaining--; pacmanFueComido = true; if (pacman.numberOfLivesRemaining <= 0) juegoTerminado = true; else _levelReset(); return; } } } for (Ghost ghost : fantasmas.values()) if (ghost.edibleTime > 0) ghost.edibleTime--; }
/** * Gets the game state as a string: all variables are written to a string in a pre-determined * order. The string may later be used to recreate a game state using the setGameState() method. * * <p>Variables not included: enableGlobalReversals * * @return The game state as a string */ public String getGameState() { StringBuilder sb = new StringBuilder(); sb.append( indiceDeLaberinto + "," + tiempoTotal + "," + score + "," + tiempoLvlActual + "," + cuentaElLvl + "," + pacman.currentNodeIndex + "," + pacman.lastMoveMade + "," + pacman.numberOfLivesRemaining + "," + pacman.hasReceivedExtraLife + ","); for (Ghost ghost : fantasmas.values()) sb.append( ghost.currentNodeIndex + "," + ghost.edibleTime + "," + ghost.lairTime + "," + ghost.lastMoveMade + ","); for (int i = 0; i < laberintoActua.pillIndices.length; i++) if (pills.get(i)) sb.append("1"); else sb.append("0"); sb.append(","); for (int i = 0; i < laberintoActua.powerPillIndices.length; i++) if (powerPills.get(i)) sb.append("1"); else sb.append("0"); sb.append(","); sb.append(timeOfLastGlobalReversal); sb.append(","); sb.append(pacmanFueComido); sb.append(","); for (GHOST ghost : GHOST.values()) { sb.append(fantasmaComido.get(ghost)); sb.append(","); } sb.append(pastillaFueComida); sb.append(","); sb.append(pildoraPoderFueComida); return sb.toString(); }