/* CVS: $Id: ActionKnowledgeCatalog.java,v 1.43 2001/03/18 19:16:33 gvijf Exp $ */ package evolution.actions; import java.util.*; import java.io.*; import evolution.*; import evolution.lands.*; import evolution.constructions.*; /** * The KnowledgeCatalog for evolution.actions. * @stereotype singleton */ public class ActionKnowledgeCatalog extends KnowledgeCatalog { /** * Create a new KnowledgeCatalog from the given file. */ protected ActionKnowledgeCatalog(String fileName) throws FileNotFoundException, IOException { super(fileName); parseActionTypes(getProperty("Actions")); parseDefaultActionType(getProperty("DefaultAction")); parseEnergyBufferActionTypes(getProperty("EnergyBufferActions")); } /** * Return the instance of this singleton. */ public static ActionKnowledgeCatalog getInst() { if(instance == null) throw new RuntimeException("ActionKnowledgeCatalog was not initialized"); return instance; } /** * Initialize this singleton from the given file. */ public static void initialize(String fileName) throws FileNotFoundException, IOException { instance = new ActionKnowledgeCatalog(fileName); } /** * The normal priority for this action. */ public double getPriority(Action action) { return (new Double(getProperty(action.getName() + ".priority", "1"))).doubleValue(); } /** * A map with as keys the resource and as value the amount the action uses. */ public Map usesResources(String actionName) { return makeStringDoubleMap(actionName + ".usesResources", ""); } /** * A map with as keys the landresource and as value the amount the * action uses. */ public Map usesLandResources(String actionName) { return makeStringDoubleMap(actionName + ".usesLandResources", ""); } /** * Which resource is transformed into which resource by a given action. * Returns a map with as key the name of the resource it transforms into and as * value an array with als first element the name of the resource * which is transformed and as second element a Double transformationvalue. */ //public Map transformsResources(String actionType) { // Map m = new HashMap(); // List lt = split(" ", getProperty(actionType + ".transformsResources", "")); // Iterator it = lt.iterator(); // while(it.hasNext()) { // String e = (String) it.next(); // List fromTo = split("-", extractName(e)); // Double value = extractValue(e); // if (! m.containsKey(fromTo.get(1))) { // Map n = new HashMap(); // //een hashmap met als sleutel de producerende resource en als waarde // //in welke verhouding er geproduceerd wordt // n.put(fromTo.get(0), value); // //een hasmap met als sleutel de geproduceerde resource (bvb energy) // //en als waarde een nieuw hashtabel die hierboven gedefinieerd is // m.put(fromTo.get(1), n); // } // else { // ((HashMap)m.get(fromTo.get(1))).put(fromTo.get(0), value); // } // } // return m; //} /** * A map with as keys the resource and as value the amount the action uses. */ public Map producesResources(String actionName) { return makeStringDoubleMap(actionName + ".producesResources", ""); } /** * A map with as keys the landresource and as value the amount the * action uses. */ public Map producesLandResources(String actionName) { return makeStringDoubleMap(actionName + ".producesLandResources", ""); } /** * Which resources are transformed into a given resource by a given construction? */ //public Object[] areTransformedInto(String resource, String actionType){ // Map map = this.getInst().transformsResources(actionType); // return (Object[]) map.get(resource); //} /** * Which resources are transformed into a given resource. */ //public List areTransformedInto(String resource) { // Iterator it = this.getInst().getActionTypes().iterator(); // List list = new ArrayList(); // while(it.hasNext()) { // String actionName = (String) it.next(); // list.add(areTransformedInto(resource, actionName)); // } // return list; //} /** * A list of resources by which this action is influenced. */ public List influencedBy(String actionName) { String property = getProperty(actionName + ".influencedBy", ""); if (property == null) return new ArrayList(); return split(" ", property); } /** * Check whether the given action must be explored or not. */ public boolean mustBeExplored(String actionName) { return (new Boolean(getProperty(actionName + ".explored", "true"))).booleanValue(); } /** * See if this action can be performed on the given square. * @param actionName Something like Resting, Fishing, ... */ public boolean canBePerformedOn(String actionName, SquareOfLand sq) { List landTypes = split(" ", getProperty(actionName + ".lands", "")); if(sq.isExplored()) { // check if there is a construction if(sq.getConstruction() != null) { // check if the action would transform the land // and ifso if the construction can stand on that land Object[] r = transformsLand(sq, actionName); if(((Boolean) r[0]).booleanValue()) { return landTypes.contains(sq.getLandType()) && ConstructionKnowledgeCatalog.getInst().canStandOnLandType( sq.getConstruction().getName(), (String) r[1]); } } return landTypes.contains(sq.getLandType()); } return !mustBeExplored(actionName) && landTypes.contains(sq.getLandType()); } /** * See if this action can perform better when the needed landresources * are high. */ public boolean isMaximizing(String actionName) { return (new Boolean(getProperty(actionName + ".maximizing", "true"))).booleanValue(); } /** * Does the given action transform the landtype of the given square? *
     * Returns Object[] {
     *   Boolean transforms        : does the action transform yes or no
     *   String toLand             : the land type we transform to
     *   String detLandResource    : the determening land resource
     *   Double limit              : the limit the land resource should have
     *                               to transform the land type
     *   Boolean lte               : must the current value be less then equal
     *                               than the limit
     *   Boolean gte               : must the current value be greater then equal
     *                               than the limit
     * 
*/ public Object[] transformsLand(SquareOfLand sq, String actionName) { // FIXME: should be cashed!!!! Boolean lte = new Boolean(false); Boolean gte = new Boolean(false); String toLand = null; String detLandResource = null; Double limit = new Double(0); List l = split(" ", getProperty(actionName + ".transformsLand", "")); Iterator it = l.iterator(); while(it.hasNext()) { String e = (String) it.next(); String lands = extractName(e); String fromLand = (String) split("-", lands).get(0); if(fromLand.equals(sq.getLandType())) { toLand = (String) split("-", lands).get(1); detLandResource = (String) split("=", extractArgument(e)).get(0); limit = new Double((String) split("=", extractArgument(e)).get(1)); if(producesLandResource(actionName, detLandResource) != null) gte = new Boolean(true); if(usesLandResource(actionName, detLandResource) != null) lte = new Boolean(true); return new Object[] {new Boolean(true), toLand, detLandResource, limit, lte, gte}; } } return new Object[] {new Boolean(false)}; } /** * Returns the amount produced by the given action of the given * land resource. * Returns null if the land resource is not produced by this action. */ public Double producesLandResource(String actionName, String resName) { List lt = split(" ", getProperty(actionName + ".producesLandResources", "")); Iterator it = lt.iterator(); while(it.hasNext()) { String e = (String) it.next(); String res = extractName(e); if(res.equals(resName)) return extractValue(e); } return null; } /** * Returns the amount used by the given action of the given * land resource. * Returns null if the land resource is not used by this action. */ public Double usesLandResource(String actionName, String resName) { List lt = split(" ", getProperty(actionName + ".usesLandResources", "")); Iterator it = lt.iterator(); while(it.hasNext()) { String e = (String) it.next(); String res = extractName(e); if(res.equals(resName)) return extractValue(e); } return null; } /** * A hash of resources/speeds for the given action. */ public Map reveals(Action action) { return new HashMap(); } /** * Does the action with this name exist? */ public boolean actionExists(String actionName) { return actionTypes.contains(actionName); } /** * Instantiate the action with the given name on the given square. * precondition: the actionName must be valid */ public Action instantiate(String actionName) { if(!actionExists(actionName)) throw new RuntimeException(actionName + " is not a valid action name"); try { // first try to dynamically load Class c = dlClassForName("actions", actionName); try { return (Action) c.newInstance(); } catch(Exception e) { throw new RuntimeException(actionName + " does not have a proper default constructor"); } } catch(ClassNotFoundException e) { // if not dynamically loadable the action is completely defined // by the config file return new SimpleAction(actionName); } } /** * An info list with all possible actions in the game. */ public InfoList getActionsInfo() { InfoList list = new InfoList(); List actionTypes = getActionTypes(); Iterator it = actionTypes.iterator(); while(it.hasNext()) { String name = (String) it.next(); //if(!name.equals("Constructing")) list.add(name, InfoList.STRING, name); } return list; } /** * Return a list of all possible actions. * This is a list of Strings. */ public List getActionTypes() { return actionTypes; } /** * Return a list of all possible actions while using the energy buffer. * This is a list of Strings. */ public List getEnergyBufferActionTypes() { return energyBufferActionTypes; } /** * Return the the name for the default action. */ public String getDefaultActionType() { return defaultActionType; } /** * Return an instance of the default action type. * This is cached version. */ public Action getDefaultAction() { if(defaultAction == null) defaultAction = instantiate(getDefaultActionType()); return defaultAction; } /** * Parse a actiontypes string. */ protected void parseActionTypes(String actionTypesString) { actionTypes = parseActionTypesInto(actionTypesString, null); SystemMessage.message(actionTypes.size() + " actiontypes loaded"); } /** * Parse a energy buffer actiontypes string. */ protected void parseEnergyBufferActionTypes(String actionTypesString) { energyBufferActionTypes = parseActionTypesInto(actionTypesString, actionTypes); } /** * Parse the default actiontype string. */ protected void parseDefaultActionType(String actionTypeString) { defaultActionType = actionTypeString; if(defaultActionType == null) throw new RuntimeException("No default actiontype found"); if(!actionTypes.contains(defaultActionType)) throw new RuntimeException("Default action type is not in the Actions property"); } /** * Parse a actiontypes string. * @param retain A List of action names. If this is not null, only * the specified actions will be extracted. */ protected List parseActionTypesInto(String actionTypesString, List retain) { List lt = split(" ", actionTypesString); Iterator it = lt.iterator(); List result = new ArrayList(); while(it.hasNext()) { String type = (String) it.next(); if((retain == null) || retain.contains(type)) { result.add(type); } } return result; } /** * An array of all the loaded actions. * These are extracted from the properties list at construction. * This is a list of Strings. */ private List actionTypes = new ArrayList(); /** * The default actiontype. * This is extracted from the properties list at construction. */ private String defaultActionType; /** * A cached version of an instantiated default action. */ private Action defaultAction; /** * The actiontypes that can be performed when using the EnergyBuffer. * These are extracted from the properties list at construction. * This is a list of Strings. */ private List energyBufferActionTypes = new ArrayList(); /** * Instance of the singleton. */ protected static ActionKnowledgeCatalog instance = null; }