/* CVS: $Id: WorldController.java,v 1.17 2001/03/19 10:29:31 gvijf Exp $ */ package evolution; import java.io.*; import java.util.*; import evolution.lands.*; import evolution.actions.*; import evolution.constructions.*; import evolution.events.*; /** * A class of world controllers. * This is a facade. */ public class WorldController implements evolution.events.Observer { /** * Create a new worldcontroller (and a new world). * The world will be created in the pause mode, so one needs * to call startGame() to start playing. * @param width The width of the game board * @param height The height of the game board * @param configFile The main configuration file on which this world * should be based. From this configuration file the path is stripped * and used as the resource path to load other config files and images. */ public WorldController(String configFile, int width, int height) throws FileNotFoundException, IOException { world = new World(this, configFile, width, height); initState(); EventManager.getInst().subscribe(this, HumanDiedEvt.class); } /** * Called when an event happens this observer is interested in. */ public void update(Event evt) { if(evt instanceof HumanDiedEvt) { SystemMessage.message("One died! You have " + getHumanSelection().size() + " humans left in your selection"); } } // actions which control the game /** * Start the game. * Does nothing if the game is already started. */ public void startGame() { continueGame(); } /** * Resume the game. */ public void continueGame() { Evolution.getInst().resume(); } /** * Pause the game. */ public void pauseGame() { Evolution.getInst().pause(); } /** * Is the game running? */ public boolean isRunning() { return Evolution.getInst().isRunning(); } // actions which manipulate the humans on the board /** * Select an action to be performed. * @exception NoHumanSelectionException If there are no humans selected * to perform the given action when a square would be selected. */ public void selectActionType(String actionName) { if(!ActionKnowledgeCatalog.getInst().actionExists(actionName)) throw new RuntimeException("Unknown action '" + actionName + "' selected"); if(getHumanSelection().empty()) SystemMessage.message("You must select some humans to perform " + actionName + ",\nbut I think you know what you are doing, right?"); setActionName(actionName); setConstructionName(null); SystemMessage.message("action = " + actionName); } /** * Select a construction to be constructed. * @exception NoHumanSelectionException If there are no humans selected * to perform the action when a square would be selected. */ public void selectConstructionType(String constructionName) { selectActionType("Constructing"); if(!ConstructionKnowledgeCatalog.getInst().constructionExists(constructionName)) throw new RuntimeException("Unknown construction '" + constructionName + "' selected"); setConstructionName(constructionName); SystemMessage.message("construction = " + constructionName); } /** * Specify the shape the construction should have. * e.g. "1x1:1", "2x2:1101", "3x2:111111101" */ public void selectConstructionShape(String shape) { setConstructionShape(shape); } /** * Toggle creating a human. */ public void createHuman() { setCreateHuman(!isCreateHuman()); } /** * Select a square of land. *
* If there is no human on the square
* if we were to create a human
* => the human is created
* elseif there are humans selected
* => one or more humans will be popped of the selection and
* start performing the action.
* else
* => the square is selected
* else
* if the human is selected
* => let it perform the selected action
* else
* => the human is added to the selection and the square is selected
*
* Precondition: the x, y must denote a valid square.
* @exception IllegalPlacementException The popped human can not stand
* on the given type of land. The human will stay were ever he was and
* stays selected.
*/
public void selectSquareOfLand(int x, int y) throws IllegalPlacementException {
setSelectedSquare(world.getGameBoard().getSquare(x, y));
//System.err.println("Selected + " + getSelectedSquare() + ", human = " +
// getSelectedSquare().getHuman() + ", construction = " +
// getSelectedSquare().getConstruction());
if(getSelectedSquare().getHuman() == null) {
if(isCreateHuman()) {
try {
world.createHuman(getSelectedSquare());
getSelectedSquare().getHuman().setAction(getActionName());
getHumanSelection().select(getSelectedSquare().getHuman());
} catch(CreationPowerInsufficientException e) {
SystemMessage.message(e.getMessage());
}
} else {
if(!getHumanSelection().empty()) {
startAction();
} else {
// nothing to do
}
}
} else {
//System.err.println("a human");
if(getHumanSelection().isSelected(getSelectedSquare().getHuman())) {
//System.err.println("is selected, let him perform " + getActionName());
startAction();
//System.err.println("ok");
} else {
//System.err.println("not selected, select");
getHumanSelection().select(getSelectedSquare().getHuman());
//System.err.println("ok");
SystemMessage.message("You have " + getHumanSelection().size() + " humans selected");
}
}
setCreateHuman(false);
}
/**
* Start the selected action.
*/
protected void startAction() throws IllegalPlacementException {
if(getConstructionName() != null) {
if(getConstructionShape() == null) {
SystemMessage.message("Please select the shape for your " + getConstructionName());
return;
}
//System.err.println("start building a " + getConstructionName());
//SystemMessage.message("Hey jules, I don't know how to build a construction yet! But I'll try...");
int n = Math.min(ConstructionKnowledgeCatalog.getInst().
countSquares(getConstructionShape()), getHumanSelection().size());
SystemMessage.message("Ok, using " + n + " humans to construct a faboulous " + getConstructionName());
List humans = new ArrayList();
for(int i = 0; i < n; i++) humans.add(getHumanSelection().pop());
try {
ConstructionKnowledgeCatalog.getInst().build(
getConstructionName(), getConstructionShape(),
humans, getSelectedSquare());
} catch(IllegalPlacementException e) {
for(int i = 0; i < n; i++)
getHumanSelection().select((Human) humans.get(n-i-1));
throw e;
}
setConstructionName(null);
setConstructionShape(null);
//resetActionName();
} else {
Human human = getHumanSelection().pop();
SquareOfLand oldSquare = human.getSquareOfLand();
try {
if(getSelectedSquare() != oldSquare) {
getSelectedSquare().place(human);
}
SystemMessage.message("I command you, go " + getActionName());
human.setAction(getActionName());
} catch(IllegalPlacementException e) {
// add the human back to the selection
getHumanSelection().select(human);
throw e;
}
}
if(getHumanSelection().empty()) {
SystemMessage.message("If I were you, I would search some lazy humans to command...");
} else {
SystemMessage.message("Still " + getHumanSelection().size() + " humans to command!");
}
}
/**
* Clear the selected humans.
*/
public void clearSelection() {
getHumanSelection().clear();
}
/**
* Modify the visionrange of this worldcontroller.
*/
public void modifyVisionRange(int value) {
while (!humanSelection.empty()) {
Human human = humanSelection.pop();
try {
human.setVisionRange(human.getVisionRange() + value);
}
catch (InvalidVisionRangeException exc) {
SystemMessage.message(exc.getMessage());
}
}
}
// information requests about the current selected square
/**
* Get an infolist with all the world resources.
*/
public InfoList getResourcesInfo() {
return getWorld().getResourcesInfo();
}
/**
* Get an infolist with info about the selected square.
*/
public InfoList getSquareInfo() {
if(getSelectedSquare() == null) return new InfoList();
return getSelectedSquare().getInfo();
}
/**
* Get an infolist with info about the selected human.
*/
public InfoList getHumanInfo() {
if((getSelectedSquare() == null) || (getSelectedSquare().getHuman() == null))
return new InfoList();
return getSelectedSquare().getHuman().getInfo();
}
/**
* Get an infolist with info about the selected construction.
*/
public InfoList getConstructionInfo() {
if((getSelectedSquare() == null) || (getSelectedSquare().getConstruction() == null))
return new InfoList();
return getSelectedSquare().getConstruction().getInfo();
}
/**
* The shapes the given construction can be build in.
* Returns a List of Strings according to the shape spec.
* e.g. {"1x1:1", "2x2:1101", "3x2:111111101"}
*/
public List getConstructionShapes(String constructionName) {
return ConstructionKnowledgeCatalog.getInst().getConstructionShapes(constructionName);
}
// information about the objects in this game
/**
* All available actions.
*/
public InfoList getActionsInfo() {
return ActionKnowledgeCatalog.getInst().getActionsInfo();
}
/**
* All available constructions.
*/
public InfoList getConstructionsInfo() {
// the action to build a construction is hardwired as 'Constructing'
if(!ActionKnowledgeCatalog.getInst().actionExists("Constructing")) {
return new InfoList();
}
return ConstructionKnowledgeCatalog.getInst().getConstructionsInfo();
}
/**
* The resource path.
*/
public String getResourcePath() {
return KnowledgeCatalog.getResourcePath();
}
/**
* Get the width of this world.
*/
public int getWidth() {
return getWorld().getWidth();
}
/**
* Get the height of this world.
*/
public int getHeight() {
return getWorld().getHeight();
}
/**
* Let all the squares fire a changed event.
*/
public void refresh() {
getWorld().refresh();
}
/**
* Is the given human selected?
*/
public boolean isSelected(Human human) {
return getHumanSelection().isSelected(human);
}
/**
* Is the given human actively selected?
*/
public boolean isActiveSelected(Human human) {
return getHumanSelection().isActiveSelected(human);
}
// the things we use to do this
/**
* Return to the initial state of this worldcontroller.
*/
protected void initState() {
humanSelection = new HumanSelection();
selectedSquare = world.getGameBoard().getSquare(0, 0);
resetActionName();
setConstructionName(null);
setCreateHuman(false);
}
/**
* Return the human selection of this human.
*/
protected HumanSelection getHumanSelection() {
return humanSelection;
}
/**
* Return the square of land that is currently selected.
*/
protected SquareOfLand getSelectedSquare() {
return selectedSquare;
}
/**
* Set the selected square of land to the given square of land.
*/
protected void setSelectedSquare(SquareOfLand square) {
selectedSquare = square;
}
/**
* Return the name of the currently selected action.
*/
protected String getActionName() {
return actionName;
}
/**
* Set the selected action to the given action.
*/
protected void setActionName(String actionName) {
this.actionName = actionName;
}
/**
* Set the selected action to the default action.
*/
protected void resetActionName() {
String actionName = ActionKnowledgeCatalog.getInst().getDefaultActionType();
setActionName(actionName);
SystemMessage.message("action = " + actionName);
}
/**
* Return the currently selected construction name.
*/
protected String getConstructionName() {
return constructionName;
}
/**
* Set the selected construction name to the given construction name.
*/
protected void setConstructionName(String constructionName) {
this.constructionName = constructionName;
}
/**
* Return the selected construction shape.
*/
protected String getConstructionShape() {
return constructionShape;
}
/**
* Set the selected construction shape to the given construction shape.
*/
protected void setConstructionShape(String constructionShape) {
this.constructionShape = constructionShape;
}
/**
* Return whether we are going to create a human with the next
* square selection
*/
protected boolean isCreateHuman() {
return createHuman;
}
/**
* Set the boolean value that determines whether we are going
* to create a human with the next square selection
*/
protected void setCreateHuman(boolean b) {
createHuman = b;
}
/**
* return the world (= singleton !) of this worldcontroller.
*/
protected World getWorld() {
return world;
}
/**
* The human selection.
*/
private HumanSelection humanSelection;
/**
* The selected square of land.
*/
private SquareOfLand selectedSquare;
/**
* The action name which was selected.
*/
private String actionName;
/**
* The construction name which was selected.
*/
private String constructionName = null;
/**
* The construction shape which was selected.
*/
private String constructionShape = null;
/**
* Are we gonna create a human with the next square selection?
*/
private boolean createHuman;
/**
* Just for easy referencing, but remember: world is a singleton.
*/
private World world;
}