/* CVS: $Id: Construction.java,v 1.33 2001/03/19 04:20:13 gvijf Exp $ */ package evolution.constructions; import java.util.*; import evolution.*; import evolution.lands.*; import evolution.resources.*; import evolution.*; import evolution.actions.*; import evolution.events.*; /** * Abstract class of constructions. */ abstract public class Construction implements Evolver { /** * Create a new construction. */ protected Construction() { setSquares(new ArrayList()); } /** * Create a new construction. */ public Construction(List squares) { setSquares(squares); } /** * The checks which are made in evolve. * This is a template method. */ protected void doChecks(double percentage) throws NotEnoughResourcesException, NotEnoughLandResourcesException { if(!hasEnoughResources(percentage)) throw new NotEnoughResourcesException(); if(!hasEnoughLandResources(percentage)) throw new NotEnoughLandResourcesException(); } /** * The evolution for the construction when Evolution ticks time. * @param percentage The percentage of production. */ public void evolve(double percentage) { setWorking(false); if(percentage == 0) { // if we have to produce 0%, then we can return immediately return; } try { doChecks(percentage); // consume resources + land resources modifyResources(getUsesResources(), -1.0*percentage); // can throw NotEnoughResourcesException modifyLandResources(getSquares(), getUsesLandResources(), -1.0*percentage); // can throw NotEnoughLandResourcesException // produce resources (+ land resources) // in ons spel worden er voorlopig nooit lan resources geproduceerd modifyResources(getProducesResources(), 1.0*percentage); _evolve(percentage); } catch (NotEnoughResourcesException e){ } catch (NotEnoughLandResourcesException e) { // In ons spel is het momenteel zo dat je nu nooit de world-resources // moet herstellen: de enige construction die land resources gebruikt // zijn immers de coalmines, en die gebruiken geen world resources. // daarom ook dat eerst alles geconsumeerd wordt vooraleer de constructie // iets gaat produceren... } setWorking(true); } /** * Modify the world resources for this construction. * @param resources A Map of (String, Double) resources to modify. * @param mul A multiplier for the values in the map. */ protected void modifyResources(Map resources, double mul) throws NotEnoughResourcesException { System.err.println(getName() + ": " + mul + " * " + resources); Iterator it = resources.keySet().iterator(); while(it.hasNext()) { String resName = (String) it.next(); ResourceKnowledgeCatalog.getInst().modResource(resName, mul * ((Double) resources.get(resName)).doubleValue()); } } /** * Modify the land resources for this construction. * @param resources A Map of (String, Double) resources to modify. * @param mul A multiplier for the values in the map. */ protected void modifyLandResources(List squares, Map resources, double mul) throws NotEnoughLandResourcesException { System.err.println(getName() + ": " + mul + " * " + resources); Iterator it1 = squares.iterator(); while (it1.hasNext()) { SquareOfLand square = (SquareOfLand) it1.next(); Iterator it = resources.keySet().iterator(); while(it.hasNext()) { String resName = (String) it.next(); square.modResource(resName, mul * ((Double) resources.get(resName)).doubleValue()); } } } /** * Additional things which should be done when this construction's evolve * method is called. * Template method. */ protected abstract void _evolve(double percentage); /** * Checks whether this construction had enough worldresources to be performed. */ public boolean hasEnoughResources(double percentage) { Map neededResources = getUsesResources(); Iterator it = neededResources.keySet().iterator(); while (it.hasNext()) { String key = (String) it.next(); double resourceValue = ((Double) neededResources.get(key)).doubleValue(); try { if (!World.getInst().getResource(key).has(resourceValue * percentage)) { setWorking(false); System.err.println(getName() + " is missing " + key); return false; } } catch (NoSuchResourceException e) { //can't happen } } setWorking(true); return true; } /** * Checks whether this construction had enough landresources to be performed. */ public boolean hasEnoughLandResources(double percentage) { return true; } /** * */ //public double getTotalLandResource(String name) { // Iterator it = getSquares().iterator(); // double res = 0; // while (it.hasNext()) { // LandResource lr = ((LandResource) ((SquareOfLand) it.next()).getLandResource(name)); // res += lr.getValue(); // } // return res; //} /** * Does this evolver produce energy? */ public boolean producesEnergy() { List prodresnames = producesResourcesNames(); Iterator it = prodresnames.iterator(); while (it.hasNext()) { if (ConstructionKnowledgeCatalog.getInst().isEnergyResource((String)it.next())) { return true; } } return false; } /** * Return the maximum energy production of this evolver. * @param maxProduction A (String, Double) map wich holds the maximal * production of worldresources. * @param leftOver A (String, Double) map wich holds the actual status * of worldresources in calculating the maximum energy production. */ public double maxEnergyProduction(Map maxProduction, Map leftOver) { Map producesResources = ConstructionKnowledgeCatalog.getInst().producesResources(getName()); Map usesResources = ConstructionKnowledgeCatalog.getInst().usesResources(getName()); System.err.println("prio = " + getPriority()); System.err.println("max " + getName() + ": " + producesResources); System.err.println("max " + getName() + ": " + usesResources); Iterator it1 = usesResources.keySet().iterator(); while (it1.hasNext()) { String name = (String) it1.next(); double left = ((Double) leftOver.get(name)).doubleValue(); double needed = ((Double) usesResources.get(name)).doubleValue(); if(left >= needed) { leftOver.put(name, new Double(left - needed)); } else return 0; } Iterator it2 = producesResources.keySet().iterator(); while (it2.hasNext()) { String name = (String) it2.next(); double v = ((Double) producesResources.get(name)).doubleValue(); double p = ((Double) maxProduction.get(name)).doubleValue(); double u = ((Double) leftOver.get(name)).doubleValue(); maxProduction.put(name, new Double(p + v)); leftOver.put(name, new Double(u + v)); } return ((Double) maxProduction.get("Energy")).doubleValue(); } /** * Returns a map of the names of resources that are produced * by this action. */ protected Map getProducesResources() { return ConstructionKnowledgeCatalog.getInst().producesResources(getName()); } /** * Returns a map of the names of resources that are used * by this action. */ protected Map getUsesResources() { return ConstructionKnowledgeCatalog.getInst().usesResources(getName()); } /** * Returns a map of the names of landresources that are used * by this action. */ protected Map getUsesLandResources() { return ConstructionKnowledgeCatalog.getInst().usesLandResources(getName()); } /** * Returns the name of the construction. */ public String getName() { return ConstructionKnowledgeCatalog.getInst().stripPathFromClassName(this); } /** * Returns the size of the construction. */ public int getSize() { return getSquares().size(); } /** * Returns the priority of this construction. */ public double getPriority() { return ConstructionKnowledgeCatalog.getInst().getPriority(this); } /* * Return the construction state. * If the construction is being build this is "C" + the construction name. * If the construction is in production this is just the construction name. */ public String getState() { if(isBeingBuild()) return "C" + getName(); if(!isWorking()) return "Not" + getName(); return getName(); } /** * An InfoList with the properties of this building. */ public InfoList getInfo() { InfoList result = new InfoList(); result.add("Type", InfoList.STRING, getName()); if(isBeingBuild()) { result.add("Construction state", InfoList.PERCENTAGE, getConstructionState()); } else { result.add("Producing", InfoList.BOOLEAN, isWorking()); } return result; } /** * Is this construction being build? */ public boolean isBeingBuild() { return constructed < 100; } /** * Is this construction in production state? */ public boolean isProduction() { return constructed >= 100; } /** * Construct some percents of this construction. * @param inc The percentage to construct. */ public void construct(double inc) { constructed += inc; if(constructed >= 100) { constructed = 100; SystemMessage.message("A " + getName() + " construction is now alive and will start producing!"); Evolution.getInst().register(this); signalStateChange(); } // System.err.println(getName() + ".constructed = " + constructed + "%"); } /** * Signal a SquareChangedEvt on every square of this construction. */ protected void signalStateChange() { Iterator it = getSquares().iterator(); while(it.hasNext()) { EventManager.getInst().signalEvent(new SquareChangedEvt( (SquareOfLand) it.next())); } } /** * The percentage of construction. */ public double getConstructionState() { return constructed; } /** * A list with the names of the resources produced by this construction. */ public List producesResourcesNames() { return ConstructionKnowledgeCatalog.getInst().producesResourcesNames(this.getName()); } /** * The squares where this construction is build on. */ public List getSquares() { return squares; } /** * Set the squares where this construction is standing. */ protected void setSquares(List squares) { this.squares = squares; //System.err.println("Construction on: " + squares); Iterator it = squares.iterator(); while(it.hasNext()) { SquareOfLand square = (SquareOfLand) it.next(); try { square.place(this); } catch(IllegalPlacementException e) { // if this happens, we are in deep shit throw new RuntimeException("Could not place construction"); } } } /** * Change the working state of this construction. */ protected void setWorking(boolean w) { if(w != working) { working = w; signalStateChange(); } } /** * Is this construction working? */ public boolean isWorking() { return working; } /** * Percentage of how much of this building has been build. */ private double constructed; /** * The list of squares this construction is build on. */ private List squares; /** * Is this consruction working? */ private boolean working; }