Making 2 Sequential Menus, Program Forgets Choice from 1st menu

Dcoder
10 Dec 2016, 01:17

This is a continuation of my previous post from yesterday --

http://textadventures.co.uk/forum/quest/topic/cvl4pkshieugtcn80rjkyg/how-to-make-showmenu-display-inventory-objectlists

First of all, thank you Pertex for your help. I incorporated your code and it works. After some tinkering, both menus show up.

To recap: I've made a "trade" verb that brings up 2 menus: one displays the player's inventory (asking what the player offers) and the other displays a merchant's sell list (asking what the player wants). Here's the updated code:

givableList = NewStringList()
foreach (item, ScopeInventory()) {
  list add (givableList, item.name)
}
ShowMenu ("What do you offer?", givableList, true) {
  OfferedItem = GetObject(result)
  receivableList = NewStringList()
  foreach (item, ScopeVisible()) {
    if (HasAttribute(item, "MerchantSell")) {
      list add (receivableList, item.name)
    }
  }
  ShowMenu ("What do you want?", receivableList, true) {
    WantedItem = GetObject(result)
    if (OfferedItem = "fuzzy_moss" or OfferedItem = "fragrant_herbs") {
      MoveObject (OfferedItem, Inactive)
      AddToInventory (WantedItem)
    }
    else {
      msg ("The merchant does not want that.")
    }
  }
}

The only snag now is that I get this error after I make the 2nd choice (WantedItem):

Error running script: Error compiling expression 'OfferedItem = "fuzzy_moss" or OfferedItem = "fragrant_herbs"': Unknown object or variable 'OfferedItem'

I'm assuming that this error comes up because Quest has already forgotten what "OfferedItem" is from the 1st menu choice. So I need a way to make Quest remember both the "OfferedItem" and "WantedItem" data simultaneously in order to finish the trade. Is there a way(s) to do that? Any code would be helpful. Thanks in advance.


hegemonkhan
10 Dec 2016, 07:10

your 'Offered_Item' Object Variable holds an Object Value // because it's Value is an Object reference, the Variable is thus an Object Variable (quest is able to parse the Value and thus determine/make the Variable's Type to be matching its Value), just for your information/understanding

whereas, when you do, OfferedItem = "fuzzy_moss" or OfferedItem = "fragrant_herbs", the "fuzzy_moss" and "fragrant_herbs are String Values, thus you've got a mismatch of data/Attribute Types, so either do, OfferedItem.name = "fuzzy_moss" or OfferedItem.name = "fragrant_herbs", or, OfferedItem = fuzzy_moss or OfferedItem = fragrant_herbs

if you still get an error, then you got a scope issue, which means you got to use Attribute VARIABLES (NAME_OF_OBJECT.NAME_OF_ATTRIBUTE ---or--- NAME_OF_OBJECT.NAME_OF_ATTRIBUTE = VALUE_OR_EXPRESSION), as they're global/permanent (so long as the Object containing them exists of course), for example:

(Variable VARIABLES are local: NAME_OF_Variable ---or--- NAME_OF_Variable = VALUE_OR_EXPRESSION)

game.givableList = NewStringList()
foreach (item, ScopeInventory()) {
  list add (game.givableList, item.name)
}
ShowMenu ("What do you offer?", game.givableList, true) {
  game.OfferedItem = GetObject(result)
  game.receivableList = NewStringList()
  foreach (item, ScopeVisible()) {
    if (HasAttribute(item, "MerchantSell")) {
      list add (game.receivableList, item.name)
    }
  }
  ShowMenu ("What do you want?", game.receivableList, true) {
    game.WantedItem = GetObject(result)
    if (game.OfferedItem.name = "fuzzy_moss" or game.OfferedItem.name = "fragrant_herbs") {
      MoveObject (game.OfferedItem, Inactive)
      AddToInventory (game.WantedItem)
    }
    else {
      msg ("The merchant does not want that.")
    }
  }
}

Dcoder
10 Dec 2016, 08:53

Thank you much, Hegemon. The second solution worked! I also implemented your first correction, making string values consistent with themselves, and the same with object values. So anytime I see quotes or ".name", that indicates a string value.

And adding the prefix "game." makes something a global attribute or attribute variable. Just out of curiosity, do you know where the "game.givableList", "game.OfferedItem", etc. attribute variables are stored in the editor program? I didn't see them under the game or player attributes tab.

Thanks again for your help. I know it must get repetitive explaining the same concepts over and over again!


hegemonkhan
10 Dec 2016, 14:59

you can use/have any Object contain Attributes, for examples:

game.state = 0
player.life = 999
orc.dead = false
HK.strength = 100
Dcoder.endurance = 100
global_data_object.sex_list = split ("male;female", ";")

Attribute VARIABLE's syntax:

NAME_OF_OBJECT.NAME_OF_ATTRIBUTE
~or~
NAME_OF_OBJECT.NAME_OF_ATTRIBUTE = VALUE_OR_EXPRESSION


I believe you can't find them under the 'whatever/game' Object's 'Attribute' Tab's 'Attribute' Box, as you're doing them as scripting (they'll get created+set when the scripts are run/executed/activated. scripting = runtime)

if you want to create them prior to and thus for/at compile-time:

directly in code:

<game name="example_game">
  <attr name="state" type="int">0</attr>
</game>

<object name="room">
  <object name="player">
    <attr name="life" type="int">999</attr>
  </object>
</object>

<object name="orc">
  <attr name="parent" type="object">room</attr>
  <attr name="dead" type="boolean">false</attr>
</object>

<object name="HK">
  <attr name="parent" type="object">room</attr>
  <attr name="strength" type="int">100</attr>
</object>

<object name="Dcoder">
  <attr name="parent" type="object">room</attr>
  <attr name="endurance" type="int">100</attr>
</object>

<object name="global_data_object">
  <attr name="sex_list" type="simplestringlist">male;female</attr>
</object>

or, via the GUI/Editor: 'whatever' Object -> 'Attributes' Tab -> Attributes -> Add -> (set it up)


using either of these methods, should have them showing up in the GUI/Editor's 'whatever' Object's 'Attribute' Tab's 'Attribute' Box


P.S.

you don't have to have all of your VARIABLES be Attributes, I just did that in my example of your code, to be safe. You can just find the Variable/s causing the issue, and jsut have those be Attributes.

Variables are local, onc their containing scripting is finished/terminated, they're deleted/destroyed (so they can't be used outside of their containing scripting), and thus they have what is called: local scope.


P.S.S.

yes, quest recognizes/parses anything within/encased-in double quotes as a String Value

anything not in double quotes is recognized/parsed as an Object Value, except for the special/reserved keywords of 'true' and 'false' as these are for a Boolean Attribute's Values, and maybe a few other exceptions too, but let's keep this simple/brief, lol.


P.S.S.S.

VARIABLES: 3 types (keeping this simple)
-> Variables (local): NAME_OF_Variable --or-- NAME_OF_Variable = VALUE_OR_EXPRESSION
-> Attributes (global - so long as the Object exists/still exists): NAME_OF_OBJECT.NAME_OF_Attribute --or-- NAME_OF_OBJECT.NAME_OF_Attribute = VALUE_OR_EXPRESSION
-> Parameters: deals with Functions and Commands


Dcoder
11 Dec 2016, 01:20

Thank you, sensei!