/* 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; }