/* CVS: $Id: Resource.java,v 1.17 2001/03/18 20:54:12 gvijf Exp $ */ package evolution.resources; import java.lang.Math; import java.util.*; import evolution.*; /** * A world resource. */ abstract public class Resource { /** * A linear transformation function. */ public final static int LINEAR = 0; /** * A saturation transformation function. */ public final static int SLOPE = 1; /** * Create a new world resource. * @param value The initial value. * @param min The minimum value. * @param max The maximum value. * @param function The transform input/output function, one of LINEAR, * SLOPE. */ public Resource(double value, double min, double max, int function){ setLimits(min, max, function); try { setValue(value); } catch(NotEnoughResourcesException e) { //cannot happen, this would mean there's a mistake in our config files throw new RuntimeException(value + " not in [" + min + ", " + max + "]"); } } /** * Set the limits of this resource. */ protected void setLimits(double min, double max, int function) { if(max <= min) throw new RuntimeException("A resource max must be <= than a min"); if ((min < 0) || (max < 0)) throw new RuntimeException("The minimum and maximum value of a resource can not be negative"); this.min = min; this.max = max; this.norm = max / Math.log(1 + max); this.function = function; } /** * Get the name of this world resource. */ public String getName() { return ResourceKnowledgeCatalog.getInst().stripPathFromClassName(this); } /** * Get the value of this world resource. */ public double getValue() { return value; } /** * Get the minimal value of this world resource. */ public double getMin() { return min; } /** * Modify the value of this worldresource. * This is done according to the input/output function. * If this resource does not have enough it will try to transform * some other resource to get enough. * @exception NotEnoughResourcesException If we go below the minimum * of this resource and no other resource could fill the need. */ public void modValue(double v) throws NotEnoughResourcesException { //System.err.println(getName() + ": mod(" + v + "):" + getValue()); double oldValue = getValue(); try { switch(function) { case LINEAR: setValue(getValue() + v); break; case SLOPE: if (getValue() + v < 0) setValue(getValue() + v); else setValue(norm * Math.log(1+getValue()+v)); break; default: throw new RuntimeException("Unknown function name for world resource"); } } catch(NotEnoughResourcesException e) { // proberen om een automatische omzetting te doen // van een andere world resource naar deze v += oldValue - getValue(); if(autoModOthers(v) > 0) { // if still not fullfilled throw e; } } } /** * Try to transform another resource into this one. * @param amount The amount needed from this resource. * @return The amount left. */ protected double autoModOthers(double amount) { //System.err.println(getName() + " autoMod(" + amount + ")"); List alternatives = ResourceKnowledgeCatalog.getInst().transformsFrom(getName()); //System.err.println(alternatives); Iterator it = alternatives.iterator(); while(it.hasNext()) { Object o[] = (Object[]) it.next(); Resource r = (Resource) o[0]; double ratio = ((Double) o[1]).doubleValue(); double oldValue = r.getValue(); try { r.modValue(amount * ratio); return 0; // ok a fineshed job } catch(NotEnoughResourcesException e) { // see what's left and try the next one amount += (oldValue - r.getValue()) / ratio; } } return amount; // an unfineshd job for this amount } /** * See if we have enough of this resource. * Will try to use other resources to fullfill the need. */ public boolean has(double value) { //System.err.println(getName() + ": has(" + value + "), value = " + getValue()); return (getValue() >= value) || (autoHasOthers(value - getValue()) == 0); } /** * Try to convert from other resources. */ protected double autoHasOthers(double value) { //System.err.println(getName() + ": autoHas(" + value + ")"); List alternatives = ResourceKnowledgeCatalog.getInst().transformsFrom(getName()); //System.err.println(getName() + ": " + alternatives); Iterator it = alternatives.iterator(); while(it.hasNext()) { Object o[] = (Object[]) it.next(); Resource r = (Resource) o[0]; //System.err.println(getName() + ": alt = " + r.getName() + ", " + r.getValue()); double ratio = ((Double) o[1]).doubleValue(); if(r.getValue() * ratio >= value) return 0; value += r.getValue() / ratio; } return value; // an unfineshd job for this amount } /** * Set the value of this resource. * @exception NotEnoughResourcesException If you try to set this resource * below its minimal level. */ public void setValue(double value) throws NotEnoughResourcesException { if(value > max) { this.value = max; } else if(value < min) { this.value = min; throw new NotEnoughResourcesException(); } else this.value = value; } /** * Influence a value by this resource. */ public double influence(double v) { return v*(1 + getValue()/max); } private double value; private double min; private double max; private double norm; private int function; }