-/* $Id: objects.js,v 1.4 2005/07/30 23:17:01 mmondor Exp $ */
+/* $Id: objects.js,v 1.5 2005/07/31 00:15:06 mmondor Exp $ */
/*
* Copyright (c) 2005, Matthew Mondor
* actually be implemented in JavaScript too depending on future decisions.
*/
+/*
+ * Simple but rather realistic implementation of items and containers.
+ * We observe containers maximum allowed volume and weight, container neck
+ * size, as well as expandable containers, such as cloth bags which can expand
+ * to eventually fill their parent container too. We allow nestled
+ * containers. We also add the concept of arbitrary marks which a user might
+ * add to objects to differenciate them. Containers can be open or closed,
+ * and obviously need to be open for items to be added/removed from them.
+ * We flag containers as such to accept either only solids or liquids, or
+ * both. We could consider flowing sand or salt as a liquid in this case.
+ *
+ * XXX
+ * - For liquids, we might need to provide a special object or flag for them
+ * to be able to have a volume/weight ratio, so that we could perform
+ * actions easily such as fill bottles/bags, etc.
+ * - The code dealing with the container parents, weights and expanding volume
+ * containers needs to throughly be tested, both for success and failing
+ * cases of all kinds.
+ */
+
/*
* Describes a game item or object.
*/
+/* Used so that every item has a unique index ID */
var unique = 0;
/* Content types */
this.weight = weight;
this.ctype = ctype;
+ this.marks = [];
+
this.index = ++unique;
}
getWeight: function()
{
return this.weight;
+ },
+
+ mark: function(mark)
+ {
+ this.mark.push(mark);
}
};
*/
const E_OK = 0;
-const E_TOOLARGE = -1;
-const E_TOOHEAVY = -2;
-const E_BADTYPE = -3;
-const E_SELF = -4;
-const E_NONE = -5;
-const E_ALREADY = -6;
-const E_CLOSED = -7;
+const E_TOOLARGE = "Item too large";
+const E_TOOHEAVY = "Item too heavy";
+const E_BADTYPE = "Item is not of proper type (solid vs liquid)";
+const E_SELF = "Item could not penetrate itself";
+const E_NONE = "Item not in container";
+const E_ALREADY = "Item already in container";
+const E_CLOSED = "Container is closed";
function ContainerItem(name, description, volume, weight, ctype,
con_neck, con_volume_max, con_weight_max, con_ctype)
this.con_weight_max)
return E_TOOHEAVY;
- /*
- * XXX We need to do something special for container
- * objects... We need to adapt their possible volume left, if
- * they can expand, to the remaining allowed expansion, if
- * possible, restrained by this container's remaining room...
- * Should we link items in a parent/child manner to be able to
- * do this kind of trick? Hmm or should we just forget about
- * expandable volume objects to simplify the design?
- * contents/container would be like children/parent...
- * Objects would affect their parent container if they are
- * expandable, whenever objects are added/removed, and would
- * also verify their parent's volume/weight limits anytime.
- * We need to do this for weights anyway.
- * So if a container is inside a container, it must have a
- * parent. That parent must go up iteratively until the
- * master container is found, stopping and reverting anything
- * when reaching the limit of any parent.
- *
- * Also implement a recursive runner which maps all objects,
- * for instance for inventory purposes, but only recursing
- * through containers which are in the open state.
- */
+ this.con_volume_cur += item.getVolume();
+ this.con_weight_cur += item.getWeight();
/*
* The weight has to propagate to parent containers.
* We need to climb through the parents list to do this.
* Moreover, we need to actually reverse any changes made
* to the parents in case of any volume/weight exceeded.
- *
- * XXX Hmm perhaps that I should use another method
- * alltogether, always evaluating the volume and weight of an
- * object with all its children? The type of game is probably
- * not performance critical anyways.
*/
+ var err = E_OK;
for (var o = this.con_parent; o != undefined;
o = o.con_parent) {
- /* XXX */
- // if (o.weight + this.getWeight() > o.con_weight_max)
+ if (o.getWeight() + this.getWeight() >
+ o.con_weight_max) {
+ err = E_TOOHEAVY;
+ break;
+ }
+ o.con_weight_cur += this.getWeight();
+ if ((o.con_ctype & CT_EXPAND) != 0) {
+ if (o.getVolume() + this.getVolume() >
+ o.con_volume_max) {
+ err = E_TOOLARGE;
+ break;
+ }
+ o.con_volume_cur += this.getVolume();
+ }
+ }
+ if (err != E_OK) {
+ /*
+ * We need to revert all changes to the parents list
+ */
+ for (var t = this.con_parent; t != o;
+ t = t.con_parent) {
+ t.con_weight -= this.getWeight();
+ if ((t.con_ctype & CT_EXPAND) != 0)
+ t.con_volume_cur -= this.getVolume();
+ }
+ if (err == E_TOOLARGE)
+ o.con_weight_cur -= this.getWeight();
+
+ this.con_volume_cur -= item.getVolume();
+ this.con_weight_cur -= item.getWeight();
+
+ return err;
}
+ if (item.isContainer())
+ item.con_parent = this;
this.con_items[item.index] = item;
- this.con_volume_cur += item.getVolume();
- this.con_weight_cur += item.getWeight();
this.con_items_cnt++;
return E_OK;
if (this.con_items[item.index] == undefined)
return E_NONE;
+ /*
+ * Climb up our parents containers list to update them
+ */
+ for (var o = this.con_parent; o != undefined;
+ o = o.con_parent) {
+ o.con_weight_cur -= this.getWeight();
+ if ((o.con_ctype & CT_EXPAND) != 0)
+ o.con_volume_cur -= this.getVolume();
+ }
+
+ if (item.isContainer())
+ delete item.con_parent;
this.con_weight_cur -= item.getWeight();
this.con_volume_cur -= item.getVolume();
delete this.con_items[item.index];
this.con_items_cnt--;
return E_OK;
+ },
+
+ inventory: function()
+ {
+ /*
+ * XXX Recurse through all open containers, mapping contents.
+ */
}
};
var c = new ContainerItem('a bag', 'a soft cloth bag', 5, 5, CT_SOLID,
10, 15, 20, CT_SOLID | CT_EXPAND);
-/*
- * Open container, add item in it and then close it, reopening it again to
- * remove back the item from it and to close it once and for all.
- */
+/* Create a second container item */
+var c2 = new ContainerItem('another bag', 'another soft cloth bag', 5, 5,
+ CT_SOLID, 10, 15, 20, CT_SOLID | CT_EXPAND);
+
c.open();
print(c.add(i));
c.close();
-c.open();
-print(c.remove(i));
-c.close();
+c2.open();
+print(c2.add(c));
+c2.close();