sim.app.pacman.PacMan Maven / Gradle / Ivy
Show all versions of mason Show documentation
/*
Copyright 2009 by Sean Luke and Vittorio Zipparo
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.app.pacman;
import sim.engine.*;
import sim.util.*;
import sim.field.continuous.*;
import sim.field.grid.*;
import java.io.*;
/** PacMan is the model for the game. The model contains three fields: a Continuous2D for the
agents, a Continuous2D for the dots, and an IntGrid2D holding the maze (1 is wall, 0 is open space).
The model holds an array of "actions", one per player, in case we want to make this a multiplayer game.
Note that you can easily modify this code to have different kinds of Pacs (internally we have invented
AI Pacs. :-). Also if you just want one pacman, not two, change the Pacs array to be of size 1 (see the
code below).
*/
public class PacMan extends SimState
{
private static final long serialVersionUID = 1;
/** Holds the ghosts and the Pac. */
public Continuous2D agents;
/** Holds Energizers and Dots. */
public Continuous2D dots;
/** The maze proper. */
public IntGrid2D maze;
/** A signal to indicate to the ghosts that they should become frightened next step around. */
boolean frightenGhosts; // signal for the ghosts
/** Desired actions from the user. Presently only actions[0] used. */
public int[] actions;
/** The number of deaths so far. */
public int deaths = 0;
/** The current level. */
public int level = 1;
/** The current score. */
public int score=0;
/** The pacs. Used by the ghosts to figure out where the closest Pac is. */
public Pac[] pacs;
/** Creates a PacMan simulation with the given random number seed. */
public PacMan(long seed)
{
super(seed);
}
/** Resets the scores, loads the maze, creates the fields, adds the dots and energizers, and resets the Pac and Ghosts. */
public void start()
{
super.start();
deaths = 0;
level = 1;
score = 0;
// String mazefile = PacMan.class.getResource("images/maze0.pbm").getPath();
// maze = new IntPBMGrid2D(mazefile);
maze = new IntGrid2D(0,0);
try { maze.setTo(TableLoader.loadPNMFile(PacMan.class.getResourceAsStream("images/maze0.pbm"))); }
catch (Exception e) { e.printStackTrace(); }
agents = new Continuous2D(1.0, maze.getWidth(), maze.getHeight());
dots = new Continuous2D(1.0, maze.getWidth(), maze.getHeight());
resetGame();
}
public int MAX_MAZES = 2;
/** Resets the game board. Doesn't change the score or deaths or level number */
public void resetGame()
{
dots.clear();
//String mazefile = PacMan.class.getResource("images/maze" + (level - 1) % MAX_MAZES + ".pbm").getPath();
//maze.read(mazefile);
//maze.read(PacMan.class.getResourceAsStream("images/maze" + (level - 1) % MAX_MAZES + ".pbm"));
try { maze.setTo(TableLoader.loadPNMFile(PacMan.class.getResourceAsStream("images/maze" + (level - 1) % MAX_MAZES + ".pbm"))); }
catch (Exception e) { e.printStackTrace(); }
// add energizers
dots.setObjectLocation(new Energizer(), new Double2D(1, 5));
dots.setObjectLocation(new Energizer(), new Double2D(26, 5));
dots.setObjectLocation(new Energizer(), new Double2D(1, 25));
dots.setObjectLocation(new Energizer(), new Double2D(26, 25));
// distribute dots. We allow dots right on the energizers, no biggie
for (int x= 0; x < maze.getWidth(); x++)
for(int y =0; y < maze.getHeight(); y++)
if (maze.field[x][y] == 0 &&
!(y==16 && x>= 12 && x <= 16)) // not in the jail
dots.setObjectLocation(new Dot(), new Double2D(x,y));
resetAgents();
}
public int pacsLeft() { int count = 0; for(int i = 0; i < pacs.length;i++) if (pacs[i] != null) count++; return count;}
public Pac pacClosestTo(MutableDouble2D location)
{
if (pacs.length == 1) return pacs[0];
Pac best = null;
int count = 1;
for(int i = 0; i < pacs.length; i++)
{
if (pacs[i] != null)
{
if (best == null ||
(best.location.distanceSq(location) > pacs[i].location.distanceSq(location) && ((count=1)==1) ||
best.location.distanceSq(location) == pacs[i].location.distanceSq(location) && random.nextBoolean( 1.0 / (++count))))
best = pacs[i];
}
}
return best;
}
/** Puts the agents back to their regular locations, and clears the schedule. */
public void resetAgents()
{
agents.clear();
schedule.clear();
// make arrays
actions = new int[] { Agent.NOTHING , Agent.NOTHING };
pacs = new Pac[2]; // set this to Pac[1] to make this one-player
// add the Pacs
if (pacs.length > 1) pacs[1] = new Pac(this, 1); // schedule pac 1 first so he appears on the bottom initially
pacs[0] = new Pac(this, 0);
// add Blinky
// yes, dead store
Blinky blinky = new Blinky(this);
// add Pinky
// yes, dead store
Pinky pinky = new Pinky(this);
// add Inky
// yes, dead store
Inky inky = new Inky(this, blinky);
// add Clyde
// yes, dead store
Clyde clyde = new Clyde(this);
// ghosts are no longer frightened
frightenGhosts = false;
}
/** Returns the desired user action. */
public int getNextAction(int tag) { return actions[tag]; }
public static void main(String[] args)
{
doLoop(PacMan.class, args);
System.exit(0);
}
}