*** empty log message ***
authorMatthew Mondor <mmondor@pulsar-zone.net>
Sun, 31 Jul 2005 00:15:06 +0000 (00:15 +0000)
committerMatthew Mondor <mmondor@pulsar-zone.net>
Sun, 31 Jul 2005 00:15:06 +0000 (00:15 +0000)
tests/js-test/js/game/objects.js

index 03894b0..deedcf0 100644 (file)
@@ -1,4 +1,4 @@
-/* $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 */
@@ -33,6 +54,8 @@ function Item(name, description, volume, weight, ctype)
        this.weight = weight;
        this.ctype = ctype;
 
+       this.marks = [];
+
        this.index = ++unique;
 }
 
@@ -50,6 +73,11 @@ Item.prototype = {
        getWeight: function()
        {
                return this.weight;
+       },
+
+       mark: function(mark)
+       {
+               this.mark.push(mark);
        }
 };
 
@@ -59,13 +87,13 @@ Item.prototype = {
  */
 
 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)
@@ -153,28 +181,8 @@ ContainerItem.prototype = {
                    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.
@@ -185,21 +193,47 @@ ContainerItem.prototype = {
                 * 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;
@@ -215,12 +249,31 @@ ContainerItem.prototype = {
                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.
+                */
        }
 };
 
@@ -237,13 +290,13 @@ var i = new Item('a ring', 'the one ring', 5, 5, CT_SOLID);
 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();