-/* $Id: objects.js,v 1.1 2005/07/30 07:30:34 mmondor Exp $ */
+/* $Id: objects.js,v 1.2 2005/07/30 09:02:40 mmondor Exp $ */
/*
* Copyright (c) 2005, Matthew Mondor
*/
+
+/*
+ * Describes a game item or object.
+ */
+
+var unique = 0;
+
+/* Content types */
+const CT_SOLID = (1 << 0);
+const CT_LIQUID = (1 << 1);
+/* And container type flag */
+const CT_EXPAND = (1 << 2);
+
+function Item(name, description, volume, weight, ctype)
+{
+ this.name = name;
+ this.description = description;
+ this.volume = volume;
+ this.weight = weight;
+ this.ctype = ctype;
+
+ this.index = ++unique;
+}
+
+Item.prototype = {
+ volume: function()
+ {
+ return this.volume;
+ },
+
+ weight: function()
+ {
+ return this.weight;
+ }
+};
+
+
+/*
+ * And an object to handle container Items, inheriting the Item object.
+ */
+
+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;
+
+function ContainerItem(name, description, volume, weight, ctype,
+ con_neck, con_volume_max, con_weight_max, con_ctype)
+{
+ this.base = Item;
+ this.base(name, description, volume, weight, ctype);
+
+ this.con_neck = con_neck;
+ this.con_volume_max = con_volume_max;
+ this.con_weight_max = con_weight_max;
+ this.con_volume_cur = this.con_weight_cur = 0;
+ this.con_ctype = con_ctype;
+
+ this.con_items = {};
+ this.con_items_cnt = 0;
+ this.con_open = false;
+}
+
+ContainerItem.prototype = {
+ open: function()
+ {
+ this.con_open = true;
+ },
+
+ close: function()
+ {
+ this.con_open = false;
+ },
+
+ volume: function()
+ {
+ /*
+ * Objects which expand, such as bags, need to report proper
+ * volume relating to the volume of the objects they hold.
+ * Objects which do not expand, such as boxes or bottles,
+ * need to always report the same volume.
+ */
+ return ((this.con_ctype & CT_EXPAND) != 0) ?
+ this.volume + this.con_volume :
+ this.volume;
+ },
+
+ weight: function()
+ {
+ return this.weight + this.con_weight;
+ },
+
+ add: function(item)
+ {
+ /* Can only add items to open container */
+ if (!this.con_open)
+ return E_CLOSED;
+ /* We can't add ourself in :) */
+ if (item.index == this.item.index)
+ return E_SELF;
+ /* Nor items which are already inside */
+ if (this.con_items[item.index] != undefined)
+ return E_ALREADY;
+ /* We only accept items of proper type */
+ if ((this.con_ctype & item.ctype) == 0)
+ return E_BADTYPE;
+ /* We can only hold objects which are small enough */
+ if (this.con_neck < item.volume())
+ return E_TOOLARGE;
+ if (this.con_volume_cur + item.volume() > this.con_volume_max)
+ return E_TOOLARGE;
+ /* We can only hold objects which are light enough */
+ if (this.con_weight_cur + item.weight() > 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.
+ *
+ * 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_items[item.index] = item;
+ this.con_volume_cur += item.volume();
+ this.con_weight_cur += item.weight();
+ this.con_items++;
+
+ return 0;
+ },
+
+ remove: function(item)
+ {
+ /* Can only remove items from open container */
+ if (!this.con_open)
+ return E_CLOSED;
+ /* We can only remove items which are really inside */
+ if (this.con_items[item.index] == undefined)
+ return E_NONE;
+
+ this.con_weight_cur -= item.weight();
+ this.con_volume_cur -= item.volume();
+ delete this.con_items[item.index];
+ this.con_items--;
+ }
+};