Pre-release
Adventure.js Docs Downloads
Score: 0 Moves: 0
// Substance.js
(function () {
  /*global adventurejs A*/
  "use strict";

  /**
   * @ajspath adventurejs.Atom.Asset.Matter.Substance
   * @augments adventurejs.Matter
   * @class adventurejs.Substance
   * @ajsconstruct MyGame.createAsset({ "class":"Substance", "name":"foo", [...] })
   * @ajsconstructedby adventurejs.Game#createAsset
   * @ajsnavheading BaseClasses
   * @param {String} game_name Name of top level game instance that is scoped to window.
   * @param {String} name Instance name.
   * @summary Solids, Liquids, Slurries, and Gasses, baby.
   * @tutorial Substances_AboutSubstances
   * @todo How is gas volume measured? Is it something other than ml?
   * @todo State conversion
   * @todo Slurries
   * @todo is_edible / is_potable
   * @classdesc
   * <p>
   * <strong>Substance</strong> is a low-level subclass of
   * {@link adventurejs.Asset|Asset}, and the base class for
   * all
   * {@link adventurejs.Solid|Solids},
   * {@link adventurejs.Liquid|Liquids},
   * {@link adventurejs.Slurry|Slurries}, and
   * {@link adventurejs.Gas|Gasses}.
   * Substance is one of the pillars of the
   * {@link adventurejs.Game|Game} world,
   * along with
   * {@link adventurejs.Tangible|Tangibles} and
   * {@link adventurejs.Intangible|Intangibles}.
   * Substances fall somewhere between Tangibles and
   * Intangibles. Instances of Substances are quasi-global;
   * as with Intangibles,
   * player can refer to Substances regardless of their
   * physical availability, and be understood by the parser.
   * Yet, as with Tangibles, Substances exist in the physical
   * world. Substances have no physical aspect of their own,
   * but are defined by the Vessels that contain them.
   * A <strong>glass</strong> of water. A <strong>pile</strong>
   * of dirt. A <strong>cylinder</strong> of gas.
   * Technically, Substances are infinite. For example,
   * an instance of Water represents all Water,
   * everywhere in the Game, whether it's in a glass or a lake.
   * Substances can be added and divided;
   * Vessels can be emptied and filled.
   * </p>
   * <h3 class="examples">Example:</h3>
   * <p>
   * Rather than subclassing Substance directly, authors should
   * use Solid, Liquid, Gas, or Slurry.
   * </p>
   * <pre class="display"><code class="language-javascript">MyGame.createAsset({
   *   class: "Slurry",
   *   name: "frogurt",
   *   description: "The frogurt is full of vitamins and minerals.
   *   That's good. The frogurt is also cursed. That's bad. ",
   * });
   * </code></pre>
   **/
  class Substance extends adventurejs.Matter {
    constructor(name, game_name) {
      super(name, game_name);
      this.class = "Substance";

      this.is = new adventurejs.Substance_Is("is", this.game_name, this.id).set(
        {
          parent_id: this.id,
        }
      );

      this.setIOV({ throw: { with_nothing: true } });
      this.setIOV({ flick: { with_nothing: true } });
      this.setDOV({ throw: { with_nothing: true } });
      this.setDOV({ flick: { with_anything: true } });

      this.can = this.can || {};
      this.can.be_poured_into = false;
      this.mixwith = {};

      this.melting_temperature = 0; // water // TODO lookup table
      this.boiling_temperature = 100; // water // TODO lookup table

      // Specific heat capacity is a measure of the amount of heat necessary
      // to raise the temperature of one gram of a pure substance by one degree K.
      this.specific_heat = 4.2; // water = 4186, commonly(?) rounded to 4.2Kj or 4200j
      // TODO lookup table
      // specific heats of common liquids and substances:
      // https://www.engineeringtoolbox.com/specific-heat-fluids-d_151.html
      // https://www.engineeringtoolbox.com/specific-heat-capacity-d_391.html

      // Heat Capacity is the amount of heat required to increase the temperature
      // of a mass of substance by one degree K.
      this.heat_capacity = 4.2;
      // TODO this should calculate specific_heat * mass
      // ( which is volume * grams-per-ml - water is roughly 1 gram per ml )

      this.state = this.game.settings.states.LIQUID; // liquid is default
      // but when we do state transitions we're just going to swap substances
      // 2023.05.18 I guess I toyed with changing states and then abandoned it
      // but leaving this in as it seems like it might be worth future exploration
      this.states_ids = {};

      // In reality density of liquids changes with temperature
      // but we're keeping it simple.
      this.density = 1; // water = 1(ish)
    } // function Substance(id)

    initialize(game) {
      super.initialize(game);

      /*
      mixwiths are object ids but as with most object id
      references we allow authors to enter them as
      non-serialized strings. In this case, both the key 
      and the value are ids, so we need to serialize both.
    */
      var keys = Object.keys(this.mixwith);
      for (var i = keys.length - 1; i > -1; i--) {
        var key = keys[i];
        var serialized_key = A.serialize(key);
        var serialized_with = A.serialize(this.mixwith[key]);
        this.mixwith[serialized_key] = serialized_with;
      }
      return true;
    } // p.initialize
  }
  adventurejs.Substance = Substance;
})();

/*

is global - sort of
- can always refer to it though it might not be present
is not a thing
all water is water

what if you color it?
then it becomes a different substance?

pour one substance into another
either they become a third substance
or one substance dissipates into the other
probably depending on viscosity?
water and oil don't mix
water and dirt becomes mud

sponges?
simulate leakage or evaporation - damp_level decrements over time

if you take a handful of a substance does the handful temporarily become an object?

fullness is a property of the object rather than an object in itself?

disambiguation from bodies of water

*/