/** * This handler is meant to simulate the changing of an object's * "state", such as melting, grinding, etc. In reality, rather than * changing the source object, the transform() method clones a * completely new object, based on the internal lookup table; it is * the caller's responsibility to dest the source object and put the * new one in its place. * <p> * The handler's lookup table is stored in a series of files: * any files in /obj/state_change ending in .dat will be added * to the table when the handler is loaded. See /include/state_change.h * for field definitions. The data files are loaded by the data * handler, and can contain fancy things like expressions and function * pointers. * @author Jeremy * @see /include/state_change.h * @see /handlers/data.c */ #include <state_change.h> #define PROP "state name" // I can't think of anyplace good to put this #define DATA_DIR "/obj/state_change/" mapping table = ([ ]); /** * This method returns the entire lookup table. It is mainly for * debugging. * @return the state_change lookup table */ mixed query_table() { return table; } /** @ignore yes */ void create() { string *files; int i; seteuid("/secure/master"->creator_file(file_name(this_object()))); files = ({ "base.hdr" }); files += get_dir(DATA_DIR + "*.dat"); for (i = 0; i < sizeof(files); i++) { files[i] = DATA_DIR + files[i]; } table += "/handlers/data"->compile_data(files); } /* create() */ // TODO: this should be able to clone and return an array of objects. // TODO: being able to pass in an argument for the func field would be nice. /** * This method is generally called by the object doing the state * change (e.g., a food grinder). It looks up the specified source * object in the table and clones the "transformed" object as specified. * <p> * The table is indexed by the source object as follows: if the source * object has a property "state name", the value of this is used. If * not, the object's medium alias (if any, regardless of whether the * object is continuous) is used. Failing these, the object's short * description is used. The first one resulting in a valid string is * concatenated with the transformation string (with a ":" between) * and the result is used as the index. If the lookup fails, 0 is * returned. * <p> * Note that the resulting object is only cloned. It is the responsibility * of the caller to dest the source and put the result in its place. * @param ob the source object * @param transformation a string specifying the transformation (e.g., "grind") * @return the result of the transformation */ object transform( object ob, string transformation ) { string index, name; object ret; class state_change c; function f; int *weight_unit; // First try a property if (!stringp(name = ob->query_property(PROP))) // Next see if it has a medium alias (this would be the norm) if (!stringp(name = ob->query_medium_alias())) // Finally, use the short name = ob->short(); index = transformation + ":" + name; if (undefinedp(table[index])) return 0; c = table[index]; ret = clone_object(c->result); foreach (f in c->func) evaluate(f, ob, ret); if (ret->query_continuous()) { if (ob->query_continuous()) { ret->set_amount(to_int(ob->query_amount() * c->factor)); } else { weight_unit = ret->query_weight_unit(); ret->set_amount(to_int(ob->query_weight() * c->factor * weight_unit[1] / weight_unit[0])); } } else { if (ob->query_continuous()) { weight_unit = ob->query_weight_unit(); ret->set_weight(to_int(ob->query_amount() * c->factor * weight_unit[0] / weight_unit[1])); } else { ret->set_weight(to_int(ob->query_weight() * c->factor)); } } return ret; } /* transform() */