Coins

I'm back to this again. (Sorry.)


I still haven't found a way to easily handle coins (or tokens, or any object can


I know it an be done. It's just that I don't know how to code it.

When I am in this situation, I see if Inform 7 will handle it. If it will, that means I'm definitely slacking, because Quest can do anything Inform can do.

So... Here is the entire code of an Inform 7 game which will handle tokens as a player would expect:

"Coins" by KV

The Braying Ass is a room.  "This tavern looks like it hasn't been cleaned for at least three decades.  Besides that, it's pretty nice."


A token is a kind of thing.

10 tokens are carried by the player.

Coins
An Interactive Fiction by KV
Release 1 / Serial number 180530 / Inform 7 build 6M62 (I6/v6.33 lib 6/12N) SD

Braying Ass
This tavern looks like it hasn't been cleaned for at least three decades. Besides that, it's pretty nice.

>i
You are carrying:
ten tokens

>drop tokens
token: Dropped.
token: Dropped.
token: Dropped.
token: Dropped.
token: Dropped.
token: Dropped.
token: Dropped.
token: Dropped.
token: Dropped.
token: Dropped.

>i
You are carrying nothing.

>l
Braying Ass
This tavern looks like it hasn't been cleaned for at least three decades. Besides that, it's pretty nice.

You can see ten tokens here.

>get one token
Taken.

>get 5 tokens
token: Taken.
token: Taken.
token: Taken.
token: Taken.
token: Taken.

>i
You are carrying:
six tokens

>drop 3 tokens
token: Dropped.
token: Dropped.
token: Dropped.

>get six tokens
token: Taken.
token: Taken.
token: Taken.
token: Taken.
token: Taken.
token: Taken.

>


Have I posted this same thing before? If so, I apologize!

...but I know this can be pulled off in Quest. I'm pretty sure I'm just over-complicating things.

I'm thinking maybe it could work like Groups in Pixie's NpcLib, but I'll be [expletive deleted] if I can see how that code works.


Again, sorry to post about this again. I can usually find old posts with the search, but I looked for old posts concerning this for quite a while before giving up and creating this thread.


I had all the parts of that sorted; but never got around to turning it into something I could share.

My method is to turn the token into a transparent container; and have the changedparent script put them inside each other and rename them (so the outermost one has the alias "ten tokens" (with the alt "tokens"), the one inside that is named "nine tokens", and so on down to the innermost "one token" (alts "1 token" and "token").
Then you have a turnscript (the same one that indents your listalias) add a prefix to the listalias, which causes updateList to skip it. So even though they're in a container, you only see the top one. The bit that gave me trouble was hiding the inner items from the "You can see" list; which is a real pain if you can't override the functions in CoreDescriptions. I managed it in JS, but in code so ugly that I wouldn't share it. Really needs polishing.


My method is to turn the token into a transparent container; and have the changedparent script put them inside each other and rename them...

Yeah! That's what I was searching for!

I'll be patient if it's a work-in-progress, though.

I managed it in JS, but in code so ugly that I wouldn't share it.

That poor code!

You have your way with her when no one is looking, but you won't take her out in public!


PS

What's the name of your new book, mrangel?


What's the name of your new book, mrangel?

The latest one is Inside the Box. Went from "pre-order" to "live" 8 minutes ago :D And I'm uploading a new version with a few typos corrected (oops) right now. Hopefully the Kindle thing will manage to update everyone's copy automatically.


EDIT: This is stupid. See below.

... as I was looking back at this just now, I see an easier way to do it.
token.contentsprefix = ":HIDECONTENTS:"

realAddText = addText;
function addText(t) {
  while (t.match(/\(:HIDECONTENTS:[^\(\)]+\)/)) {
    t = t.replace(/\s*\(:HIDECONTENTS:[^\(\)]+\)\s*/);
  }
  realAddText(t);
}

Hiding the extra elements in the side panes is probably a trivial modification to your existing turnscript. Code fragment:

if (GetBoolean(obj, "stacking") and Equal(obj.prototype, obj.parent.prototype)) {
  // the same thing you're doing to hide scenery objects in the inventory
}

Cool!

I'll try this out shortly.


So your "ten tokens", "three tokens", "token", etc. objects are all in scope, all reachable, but we have javascript so that only the top-level one shows up in the inventory/room/panes.

Then the stacking scripts themselves:

stackable_object.changedparent => {
  if (not this.parent = null) {
    stackable = FilterByAttribute(GetDirectChildren(this.parent), "prototype", this.prototype)
    if (ListCount(stackable) > 1) {
      stackparent = ListItem(stackable, 0)
      list remove (stackable, stackparent)
      foreach (o, stackable) {
        o.parent = stackparent
      }
    }
    if (Equal(this.parent.prototype, this.prototype)) {
      do (this.parent, "updateStackAlias")
    }
  }
  if (not oldvalue = null) {
    if (Equal(oldvalue.prototype, this.prototype)) {
      do (oldvalue, "updateStackAlias")
    }
  }
  do (this, "updateStackAlias")
}

stackable_object.updateStackAlias => {
  if (HasAttribute(this, "stackalias")) {
    this.alt = ListExclude(this.alt, this.stackalias)
  }
  this.stackalias = NewStringList()
  count = ListCount(FilterByAttribute(GetAllChildObjects(this), "prototype", this.prototype)) + 1
  if (count = 1) {
    this.alias = this.singular
    this.listalias = this.singular
    list add (this.stackalias, this.singular)
    list add (this.stackalias, "one "+this.singular)
    list add (this.stackalias, "1 "+this.singular)
  }
  else {
    if (not Equal(this.prototype, this.parent.prototype)) {
      list add (this.stackalias, "all "+this.plural)
    }
    this.alias = ToWords(count) + " " + this.plural
    this.listalias = this.plural + " ("+count+")"
    list add (this.stackalias, this.plural)
    list add (this.stackalias, ToWords(count)+" "+this.plural)
    list add (this.stackalias, ""+count+" "+this.plural)
    list add (this.stackalias, this.listalias)
  }
  this.alt = ListCombine (this.alt, this.stackalias)
}

(Noting that if you type "get bananas", it'll give you a disambiguation menu asking how many you want)


I still haven't tried this code...

...but I am currently reading this:

Inside the Box by Angel Wedge


I just realised I'm doing this really inefficiently.
You don't need to mess about overriding updateList to make an object disappear; just make all but one of the stacked objects scenery. (Assuming you already have the fix so that scenery objects in the inventory are hidden)

I think this should be all you need (apply usual disclaimer; top-of-head coding, not tested):

(note: can't remember how this works with clones. If you clone a stackable object, you need to ensure that its changedparent script is called, because I don't remember if 'changed' scripts are called for clones when they are first assigned a value)

<function name="MakeStackable" parameters="object">
  object.changedparent => {
    this.hasbeenmoved = true
    if (not this.parent = null) {
      stackable = FilterByAttribute(GetDirectChildren(this.parent), "prototype", this.prototype)
      if (ListCount(stackable) > 1) {
        // GetDirectChildren returns the objects in the same order they will appear in a disambiguation menu
        // if the player types "get bananas". I think this is the most sensible order to put them in.
        if (Equal(this.prototype, this.parent.prototype)) {
          stackparent = ListItem(stackable, ListCount(stackable)-1)
        }
        else {
          stackparent = ListItem(stackable, 0)
        }
        list remove (stackable, stackparent)
        foreach (o, stackable) {
          o.parent = stackparent
        }
      }
      if (Equal(this.parent.prototype, this.prototype)) {
        do (this.parent, "updateStackAlias")
      }
    }
    if (not oldvalue = null) {
      if (Equal(oldvalue.prototype, this.prototype)) {
        do (oldvalue, "updateStackAlias")
      }
    }
    do (this, "updateStackAlias")
  }

  object.updateStackAlias => {
    if (not this.parent = null) {
      if (Equal(this.prototype, this.parent.prototype)) {
        if (not GetBoolean(this, "scenery")) {
          this.isreallyscenery = false
        }
        this.scenery = true
      }
      else {
        this.scenery = GetBoolean (this, "isreallyscenery")
      }
    }
    if (HasAttribute(this, "stackalias")) {
      this.alt = ListExclude(this.alt, this.stackalias)
    }
    this.stackalias = NewStringList()
    count = ListCount(FilterByAttribute(GetAllChildObjects(this), "prototype", this.prototype)) + 1
    if (count = 1) {
      this.alias = this.singular
      this.listalias = this.singular
      list add (this.stackalias, this.singular)
      list add (this.stackalias, "one "+this.singular)
      list add (this.stackalias, "1 "+this.singular)
    }
    else {
      if (not Equal(this.prototype, this.parent.prototype)) {
        list add (this.stackalias, "all "+this.plural)
        list add (this.stackalias, "the "+this.plural)
      }
      this.alias = ToWords(count) + " " + this.plural
      this.listalias = this.plural + " ("+count+")"
      list add (this.stackalias, this.plural)
      list add (this.stackalias, ToWords(count)+" "+this.plural)
      list add (this.stackalias, ""+count+" "+this.plural)
      list add (this.stackalias, this.listalias)
    }
    this.alt = ListCombine (this.alt, this.stackalias)
  }

  if (not object.parent = null) {
    if (Equal(object.prototype, object.parent.prototype)) {
      object.scenery = true;
    }
  }
  if (not HasString(object, "plural")) {
    object.plural = GetDisplayAlias(object)+"s"
  }
  if (not HasString(object, "singular")) {
    object.singular = GetDisplayAlias(object)+"s"
  }
  object.isreallyscenery = GetBoolean(object, "scenery")
  do (object, "updateStackAlias")
</function>

And thanks KV :D So far that book has 1 sale and 23 pages read on Kindle Unlimited, earning me an impressive £1.79


If you have the Kindle app in your phone, you should marvel at the Word Runner.

One word at a time? I thought it was going to scroll the text... or turn the page at a set interval...


This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums