/* CVS: $Id: SquareOfLand.java,v 1.45 2001/03/18 19:16:33 gvijf Exp $ */ package evolution.lands; import java.util.*; import evolution.Human; import evolution.InfoList; import evolution.Evolution; import evolution.Evolver; import evolution.constructions.Construction; import evolution.events.*; import evolution.actions.*; /** * Class of squares of land. */ public class SquareOfLand implements Evolver { /** * Create a new SquareOfLand of the given type. */ public SquareOfLand(String landType, int x, int y, boolean explored) { setLandType(landType); setX(x); setY(y); if(explored) explorationState = 100; landResources = LandKnowledgeCatalog.getInst().generateLandResources(landType); EventManager.getInst().signalEvent(new SquareChangedEvt(this)); } /** * Create a new SquareOfLand of a random type. */ public SquareOfLand(int x, int y, boolean explored) { this(LandKnowledgeCatalog.getInst().getRandomType(), x, y, explored); } /** * Does this evolver produce energy? */ public boolean producesEnergy() { return false; } /** * Whats the max energy this evolver will produce in this step. */ public double maxEnergyProduction(Map m1, Map m2) { return 0; } /** * Evolve this square of land. */ public void evolve(double val) { boolean transform = false; double speed = LandKnowledgeCatalog.getInst().transformationSpeed(getLandType()); Map m = LandKnowledgeCatalog.getInst().transformsLandResources(getLandType()); Iterator it = m.keySet().iterator(); while(it.hasNext()) { String from = (String) it.next(); String to = (String) ((Object[]) m.get(from))[0]; Double v = (Double) ((Object[]) m.get(from))[1]; double value = getLandResource(from).extract(speed * v.doubleValue()); modResource(to, value); if(getLandResource(from).isBoundary()) transform = true; } if(transform) setLandType(LandKnowledgeCatalog.getInst().transformsTo(getLandType())); } /** * Return the human on this square of land. */ public Human getHuman() { return human; } /** * Set the given human on this square of land. * This is an internal method, made public to be accessible from * out of this package. */ public void _setHuman(Human human) { this.human = human; } /** * Return the construction on this square of land. */ public Construction getConstruction() { return construction; } /** * Set the given construction on this square of land. */ protected void setConstruction(Construction construction) { this.construction = construction; } /** * Is this square explored? */ public boolean isExplored() { //return true; return getExplorationState() >= 100; } /** * Checks whether this square has enough landresources to perform a * particular action. The needs are in the map. * This function results true if all the needed landresources are still * there, but does not look at the needed values. */ public boolean hasEnoughLandResources(Map neededLandResources) { Iterator it = neededLandResources.keySet().iterator(); while (it.hasNext()) { String resName = (String) it.next(); //double v = ((Double) neededLandResources.get(resName)).doubleValue(); LandResource r = getLandResource(resName); if((r == null) || (r.getValue() <= 0)) return false; } return true; } /** * Return the named landresource. * Returns null if the landresource is not here. */ public LandResource getLandResource(String resName) { return (LandResource) landResources.get(resName); } /** * Get all the landresources for this square. * Map of (String, LandResource). */ public Map getLandResources() { return landResources; } /** * Install a map of landresources. * Map of (String, LandResource). */ protected void setLandResources(Map r) { landResources = r; } /** * Check wheter this square has the named landresource. */ public boolean containsLandResource(String resourceName) { return getLandResource(resourceName) != null; } /** * Modify the named landresource by value. * If the landresource did not exist, it is created and initialized * at the given value. */ public void modResource(String resName, double value) { LandResource r = getLandResource(resName); if(r == null) { // create the land resource // and initialize it at 0 r = LandKnowledgeCatalog.getInst(). instantiateLandResource(resName, new Double(0), getLandType()); getLandResources().put(resName, r); } r.setValue(r.getValue() + value); } /** * Place a human on this square, without triggering an event. * @param human The human to place on this square. * @exception IllegalPlacementException If this spot is already taken * or the spot is unexplored. */ public void _place(Human human) throws IllegalPlacementException { if(this.human == human) return; if(this.human != null) throw new IllegalPlacementException("If you really want this spot, you'll have to kill me!"); boolean checkExplored; try { checkExplored = ActionKnowledgeCatalog.getInst().mustBeExplored(human.getAction().getName()); } catch(NullPointerException e) { // this happens when the human is created and the action is not yet assigned checkExplored = true; // in other words: humans can only be created on explored land } if(checkExplored && !isExplored()) throw new IllegalPlacementException("Stop! That square is unexplored, there may be monsters and stuff..."); SquareOfLand oldSq = human.getSquareOfLand(); _setHuman(human); human.setSquareOfLand(this); if(oldSq != null) oldSq._setHuman(null); } /** * Place a human on this square, and trigger a SquareChangedEvt. * @param human The human to place on this square. * @exception IllegalPlacementException If this spot is already taken * or the spot is unexplored. */ public void place(Human human) throws IllegalPlacementException { SquareOfLand oldSq = human.getSquareOfLand(); _place(human); EventManager.getInst().signalEvent(new SquareChangedEvt(this)); if(oldSq != null) EventManager.getInst().signalEvent(new SquareChangedEvt(oldSq)); } /** * Place a construction on this square, without triggering an event. * @exception IllegalPlacementException If this spot is already build on. */ public void _place(Construction construction) throws IllegalPlacementException { if(this.construction != null) throw new IllegalPlacementException("Hey you! This spot is already build on!"); setConstruction(construction); } /** * Place a construction on this square, and trigger a SquareChangedEvt. * @exception IllegalPlacementException If this spot is already build on. */ public void place(Construction construction) throws IllegalPlacementException { _place(construction); EventManager.getInst().signalEvent(new SquareChangedEvt(this)); } /** * Set the land type of this square of land. * precondition: the landtype must be valid. */ public void setLandType(String landType) { if(landType == getLandType()) return; // modify the land resources Map newResources = LandKnowledgeCatalog.getInst().generateLandResources(landType); Iterator it = newResources.keySet().iterator(); while(it.hasNext()) { String res = (String) it.next(); if(getLandResources().containsKey(res)) { // copy the value newResources.put(res, getLandResources().get(res)); } } setLandResources(newResources); // deregister does nothing when we are not registered Evolution.getInst().deregister(this); this.landType = landType; // if this landtype auto transforms, then register with Evolution if(LandKnowledgeCatalog.getInst().isEvolver(landType)) Evolution.getInst().register(this); EventManager.getInst().signalEvent(new SquareChangedEvt(this)); } /** * Return the land type of this square of land. */ public String getLandType() { return landType; } /** * Returns the priority of this evolver. */ public double getPriority() { return 0; } /** * Return the state of exploration of this square of land. * Returns a percentage. */ public double getExplorationState() { return explorationState; } /** * Set the state of exploration of this square of land. * @param s A percentage. */ public void setExplorationState(double s) { explorationState = (s < 0) ? 0 : ((s > 100) ? 100 : s); } /** * Return the x-coordinate of this square of land. */ public int getX() { return x; } /** * Set the x-coordinate of this square of land. */ protected void setX(int x) { this.x = x; } /** * Return the y-coordinate of this square of land. */ public int getY() { return y; } /** * Set the y-coordinate of this square of land. */ protected void setY(int y) { this.y = y; } /** * Return the state of the land on this square, * "Unexplored" if the landtype is yet unknown. */ public String getLandState() { if(isExplored()) return getLandType(); return "Unexplored"; } /** * Return the infolist for this square of land. */ public InfoList getInfo() { InfoList l = new InfoList(); if(isExplored()) { l.add("Land type", InfoList.STRING, getLandType()); Iterator it = landResources.keySet().iterator(); while(it.hasNext()) { String name = (String) it.next(); LandResource r = (LandResource) landResources.get(name); if(r.isVisible()) { if(r.getDetermination().equals("numeric")) l.add("o " + name, InfoList.VALUE, r.getVisibleValueAsString()); else l.add("o " + name, InfoList.STRING, r.getVisibleValueAsString()); } else l.add("o " + name, InfoList.STRING, r.getVisibleValueAsString()); } } else { l.add("Exploration state", InfoList.PERCENTAGE, getExplorationState()); } return l; } /** * Just for testing and debugging. */ public void printInfo() { System.out.println(this); InfoList l = getInfo(); while(l.next()) System.out.println(l.getName() + ": " + l.getString()); } /** * The landtype of this square. */ private String landType; /** * The human which is living on this square. */ private Human human = null; /** * The construction which is placed on this square. */ private Construction construction = null; /** * The explorationstate in percentage. */ private double explorationState = 0; /** * The coordinates of this square of land. */ private int x, y; /** * A hash of resource names and a reference to the land resource for this * square. */ private Map landResources = new HashMap(); }