Repeating Menu + Added Choices

Hey everyone. I was just wondering if it was possible to create a menu that has choices which I can make repeat again and again until cancellation. Also, upon choosing a choice it will add or hide other choices.

An example would be...

What would you like to do?
Stand Up
Sit Down
Sprawl Out On the Ground
Handstand
Cancel

Player Picks "Stand Up" - Menu Appears Again.
What would you like to do?
Go for a Walk
Go for a Run
Sit Down
Sprawl Out On the Ground
Handstand
Cancel

Makes sense? Whatcha guys think?

Anonynn.


Hello!

How about this?

<command name="you_must_choose">
    <pattern>test menu</pattern>
    <script><![CDATA[
      todo = NewStringList()
      list add (todo, "jump")
      list add (todo, "this")
      list add (todo, "that")
      list add (todo, "the other")
      ShowMenu ("What to do?", todo, false) {
        if (result = "jump") {
          menu2
        }
        else {
          msg ("You have chosen:<br/>" + result + ".")
        }
      }
    ]]></script>
  </command>
  <function name="menu2"><![CDATA[
    todo2 = NewStringList()
    list add (todo2, "new this")
    list add (todo2, "new that")
    list add (todo2, "new the other")
    ShowMenu ("What to do now?", todo2, false) {
      msg ("You have chosen:<br/>" + result + ".")
    }
  ]]></function>

NOTE: The false in ShowMenu is making the player choose something in this example. If it were set to true (which is the default, when set up in the GUI (I think)), it would allow the player to ignore the menu.


Hm. I'm not sure. I need a way to make choices appear and disappear in the same menu.

How would all that work?

Anonynn.


EDIT

See next post:
[click here](#e5b2849d-7082-473a-b680-c64b4102ada2 "THIS GOES TO THE NEXT POST IN THIS THREAD") or scroll &#8659;&#8659;&#8659;

See next post:

click here or scroll ⇓⇓⇓


Here we go...

Just change around what happens IF......

Change the list items/order...

You can make it MUCH more complicated to get through.

CLICK HERE TO VIEW THE CODE (which is not unlike the code Anonynn requested)
<!--Saved by Quest 5.7.6404.15496-->
<asl version="550">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Menu Changing EXAMPLE">
    <gameid>af5eb6de-2cdb-473d-95bc-3c2972838341</gameid>
    <version>1.0</version>
    <firstpublished>2017</firstpublished>
    <attr name="autodescription_youarein" type="int">0</attr>
    <attr name="autodescription_youcansee" type="int">0</attr>
    <attr name="autodescription_youcango" type="int">0</attr>
    <attr name="autodescription_description" type="int">0</attr>
    <attr name="autodescription_youarein_useprefix" type="boolean">false</attr>
    <showpanes type="boolean">false</showpanes>
    <showcommandbar />
    <showlocation type="boolean">false</showlocation>
    <start type="script">
      player.todo = Split("jump|clap|whistle", "|")
      ShowMenu ("What to do?", player.todo, false) {
        if (result = "jump") {
          player.todo = Split("sing|clap|whistle", "|")
          menu2
        }
        if (result = "clap") {
          player.todo = Split("jump|sing|whistle", "|")
          menu2
        }
        if (result = "whistle") {
          player.todo = Split("sing|jump|clap", "|")
          menu2
        }
      }
    </start>
    <description>example game</description>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
  </object>
  <command name="menume">
    <pattern>menume</pattern>
    <script>
      player.todo = Split("jump|clap|whistle", "|")
      ShowMenu ("What to do?", player.todo, false) {
        if (result = "jump") {
          player.todo = Split("sing|clap|whistle", "|")
          menu2
        }
        if (result = "clap") {
          player.todo = Split("jump|sing|whistle", "|")
          menu2
        }
        if (result = "whistle") {
          player.todo = Split("sing|jump|clap", "|")
          menu2
        }
      }
    </script>
  </command>
  <function name="menu2">
    ShowMenu ("What to do?", player.todo, false) {
      if (result = "jump") {
        player.todo = Split("sing|clap|whistle", "|")
        menu2
      }
      if (result = "sing") {
        player.todo = Split("jump|dance|whistle", "|")
        menu2
      }
      if (result = "clap") {
        player.todo = Split("sing|whistle|jump", "|")
        menu2
      }
      if (result = "whistle") {
        player.todo = Split("jump|clap|sing", "|")
        menu2
      }
      if (result = "dance") {
        player.todo = Split("jump|bow|whistle", "|")
        menu2
      }
      if (result = "bow") {
        msg ("You bow.")
        msg ("(Good job!)")
        msg ("{command:menume:Click here to do it again} (or enter MENUME).")
        msg ("")
        msg ("{command:quit:QUIT}")
      }
    }
  </function>
</asl>

Test it out:
http://textadventures.co.uk/games/view/hehrr_xpnuyiq2hdkztmfq/menu-changing-example


So I could do something like...

list remove (todo2, "old choice")
list add (todo, "new choice")

How might something like that look in code?

  todo = NewStringList()
  list add (todo, "jump")
  list add (todo, "this")
  list add (todo, "that")
  list add (todo, "the other")
  ShowMenu ("What to do?", todo, false) {
    if (result = "jump") {
    list remove (todo2, "jump")
    list add (todo, "new choice")
    }

Is that different from embedding menu's within menus? (which I'm trying to avoid)


Here it is with your example selections (or a loose draft of it, at any rate):


CLICK HERE TO VIEW EXAMPLE

START SCRIPT

      game.todo = Split("stand up|sit down|sprawl out|cancel", "|")
      ShowMenu ("What to do?", game.todo, false) {
        if (result = "stand up") {
          menu2
        }
        if (result = "sit down") {
          msg ("You sit down.")
        }
        if (result = "sprawl out") {
          msg ("You sprawl out.")
        }
        if (result = "cancel") {
        msg ("Canceled.")
        msg ("{command:menume:DO IT AGAIN}")
      }
      }

COMMAND

**NAME: **menume

      game.todo = Split("stand up|sit down|sprawl out|cancel", "|")
      ShowMenu ("What to do?", game.todo, false) {
        if (result = "stand up") {
          menu2
        }
        if (result = "sit down") {
          msg ("You sit down.")
          msg ("{command:menume:DO IT AGAIN}")
        }
        if (result = "sprawl out") {
          msg ("You sprawl out.")
          msg ("{command:menume:DO IT AGAIN}")
        }
        if (result = "cancel") {
        msg ("Canceled.")
        msg ("{command:menume:DO IT AGAIN}")
      }
      }

FUNCTION:

**NAME: **menu2

    game.todo2 = Split("go for a walk|go for a run|sit down|sprawl out|cancel", "|")
    ShowMenu ("What to do now?", game.todo2, false) {
      if (result = "go for a walk") {
        msg ("You walk.")
        msg ("{command:menume:DO IT AGAIN}")
      }
      if (result = "go for a run") {
        msg ("You run around.")
        msg ("{command:menume:DO IT AGAIN}")
      }
      if (result = "sit down") {
          msg ("You sit down.")
          //here's where you can change the list and call the function again, if you wish; 
//you could also call a new function with a list for SIT DOWN, etc...
          msg ("{command:menume:DO IT AGAIN}")  //remove this line once you add/change the list for SIT DOWN
      }
      if (result = "sprawl out") {
          msg ("You sprawl out.")
          msg ("{command:menume:DO IT AGAIN}")
      }
      if (result = "cancel") {
        msg ("Canceled.")
        msg ("{command:menume:DO IT AGAIN}")
      }
    }


this is filler to edit the post!


The trick is to set the initial list as an attribute of the game object, and then call a function. In the function call ShowMenu and then inside the case bits of your switch add or remove items from the list and then call the function again.


Would the initial list be a string list?


So I could do something like...

list remove (todo2, "old choice")
list add (todo, "new choice")

You sure can!

The Split thing is just a shortcut to keep from writing out list add for each choice.


Would the initial list be a string list?

A string list is what I'm using, but that's just because I find them the easiest to work with.


I think you could get even trickier with String Dictionaries, but I have no experience there.

http://docs.textadventures.co.uk/quest/using_dictionaries.html


Here's a link to tips for using String Lists.

http://docs.textadventures.co.uk/quest/using_lists.html


(filler for getting my edited post updated/posted)


you can take a look at my old, poor/bad, and with a few mistakes/inefficiencies 'explore and travel' code, as it handles removing items, so they're not done again, which is much more simple than the super/ultimate/monstrousity dynamic menu code design that I'm working on (seen a bit further below), lol:

http://textadventures.co.uk/forum/samples/topic/5138/explore-and-travel-code-sample-by-hk

look at the 'explore_function' first, which uses the 'events_stringlist' and 'events_scriptdictionary', which adds the place to the 'travel_list' (and removes the event item from the 'events_list', as I only got one-time events of discovering/adding new places to travel to, and it's only done for 'exploring the homeland', as it's just an example), which is used by the 'travel_function' for where you can travel to.


and here's my own guide on using lists and dictionaries:

http://textadventures.co.uk/forum/samples/topic/5137/list-and-dictionary-extensive-guide-by-hk


I need a break !!! (and time to think on how to continue/handle with what's left to do with it)... but if anyone wants to look at this 'work in progress' ultimate dynamic menu coding of mine for: ideas, studying it, and/or edit/finish it up and using it, feel free to do so !!!


<delegate name="dynamic_menu_delegate" parameters="name_of_object_dot_name_of_dictionary_attribute_parameter, menu_prompt_string_parameter, name_of_object_parameter, name_of_attribute_parameter, value_parameter">

<object name="npc_1_object">
  
</object>

<type name="dynamic_menu_type">

  <attr name="dynamic_menu_script_attribute" type="dynamic_menu_delegate">

    ClearScreen // as I don't like having/keeping scrolling long walls of text in my big text box during game play

    // creating a local List Variable (for beig able to remove the items from it after doing that action/item/topic, so not to be able do that action/item/topic again upon looping):

    stringlist_variable = NewStringList ()

    // adding the items (dictionary's string keys) to the local List Variable:
    // (just to be safe, doing 'deep copying' manually):

    foreach (dictionary_key_string_variable, name_of_object_dot_name_of_dictionary_attribute_parameter) {
      list add (stringlist_variable, dictionary_key_string_variable)
    }

    // manually generating the displayment of the menu (instead of using the built-in 'DisplayList' Function, as it enables you to customize your menu displayment, such as my liking of using a random selection menu option/choice, hehe):

    numbering_integer_variable = 0

    msg (menu_prompt_string_parameter)
    msg ("(Type in the number of your choice)")

    msg (numbering_integer_variable + ". random selection") // I like having a random selection menu option/choice

    foreach (menu_item_string_variable, stringlist_variable) {
      numbering_integer_variable = numbering_integer_variable + 1
      msg (numbering_integer_variable + ". " + menu_item_string_variable)
    }

    // handling selection (part 1), via a single number typed-in input (as I like it):

    get input {

      ClearScreen

      if (isInt (result)) {

        stringlist_item_string_variable = ""

        input_integer_variable = ToInt (result)
        list_count_integer_variable = ListCount (stringlist_variable)
        last_index_number_integer_variable = list_count_integer_variable - 1

        if (input_integer_variable = 0) {
          random_in_bounds_index_number_integer_variable = GetRandomInt (0, last_index_number_integer_variable)
          stringlist_item_string_variable = StringListItem (stringlist_variable, random_in_bounds_index_number_integer_variable)
        } else if (input_integer_variable > 0 and input_integer_variable < list_count_integer_variable) {
          stringlist_item_string_variable = StringListItem (stringlist_variable, random_in_bounds_index_number_integer_variable)
        } else { if input out-of-bounds
          do (this, dynamic_menu_script_attribute, name_of_object_dot_name_of_dictionary_attribute_parameter, menu_prompt_string_parameter, name_of_object_parameter, name_of_attribute_parameter, value_parameter)
        }

      } else { // if input not an integer
         do (this, dynamic_menu_script_attribute, name_of_object_dot_name_of_dictionary_attribute_parameter, menu_prompt_string_parameter, name_of_object_parameter, name_of_attribute_parameter, value_parameter)
      }
    } // end of 'get input'

    // handling selection (part 2):

    // -------------------------------------------------------------------------------------------------------------------------------------------------------------
    // have to split the Object from the Dictionary Attribute, as required by the needed use of using the 'TypeOf' Function:

    name_of_object_dot_name_of_dictionary_attribute_parameter_stringlist_variable = split (name_of_object_dot_name_of_dictionary_attribute_parameter, ".")

    name_of_object_that_is_parent_of_dictionary_attribute_string_variable = StringListItem (name_of_object_dot_name_of_dictionary_attribute_parameter, 0)

    name_of_object_that_is_parent_of_dictionary_attribute_object_variable = GetObject (name_of_object_that_is_parent_of_dictionary_attribute_string_variable)

    name_of_dictionary_attribute_string_variable = StringListItem (name_of_object_dot_name_of_dictionary_attribute_parameter, 1)
    // -------------------------------------------------------------------------------------------------------------------------------------------------------------------

    if (TypeOf (name_of_object_that_is_parent_of_dictionary_attribute_object_variable, name_of_dictionary_attribute_string_variable) = "scriptdictionary") {
      dictionary_item_variable => { ScriptDictionaryItem (name_of_object_dot_name_of_dictionary_attribute_parameter, stringlist_item_string_variable) }
    } else if (TypeOf (name_of_object_that_is_parent_of_dictionary_attribute_string_variable, name_of_dictionary_attribute_string_variable) = "stringdictionary") {
      dictionary_item_variable = StringDictionaryItem (name_of_object_dot_name_of_dictionary_attribute_parameter, stringlist_item_string_variable)
    } else {
      dictionary_item_variable = ObjectDictionaryItem (name_of_object_dot_name_of_dictionary_attribute_parameter, stringlist_item_string_variable)
    }

    // handling actions upon your selection:

    // (lots of handling I need to figure out: directly doing the dictionary item or passing it into the looping of this dynamic_menu_script_attribute, such as for doing nested dialogue topics)

    // removing the selected item from your list, so it's not done again, upon looping:

    list remove (stringlist_variable, stringlist_item_string_variable)

  </attr>

</type>

How about this?

FUNCTION:
todomenu

 ShowMenu ("What to do now?", game.todo, false) {
      if (result = "walk") {
        msg ("You walk.")
        game.todo = Split("walk|run|sit|handstand|cancel", "|")
        todomenu()
      }
      if (result = "stand") {
        msg ("You stand.")
        game.todo = Split("walk|run|sit|handstand|cancel", "|")
          todomenu()
        }
      if (result = "run") {
        msg ("You run around.")
        game.todo = Split("walk|run|sit|handstand|cancel", "|")
        todomenu()
      }
      if (result = "sit") {
          msg ("You sit down.")
          game.todo = Split("stand|sprawl out|cancel", "|")
          todomenu()
      }
      if (result = "sprawl out") {
          msg ("You sprawl out.")
          game.todo = Split("sit|stand|cancel", "|")
          todomenu()
      }if (result = "handstand") {
          msg ("You stand on your hands for a bit, then right yourself.")
          game.todo = Split("walk|run|sit|handstand|cancel", "|")
          todomenu()
      }
      if (result = "cancel") {
        msg ("Canceled.")
        msg ("{command:menume:DO IT AGAIN}")
      }
    }

START SCRIPT

game.todo = Split("walk|run|sit|handstand|cancel", "|")
      todomenu()

COMMAND (just to use for testing purposes)
Pattern: menume

todomenu()
CLICK HERE TO VIEW ENTIRE EXAMPLE GAME CODE ``` ```

Play this example game online:

http://textadventures.co.uk/games/view/hehrr_xpnuyiq2hdkztmfq/showmenu-changing-and-looping-the-altered-unaltered-menu-from-within-one-script


@ Richard:

just stream-lined/re-factored (made more efficient as can, without changing your design) up your code a bit:

ShowMenu ("What to do now?", game.todo, false) {

  if (result = "walk") {
    msg ("You walk.")
    game.todo = Split("walk|run|sit|handstand|cancel", "|")
  } else if (result = "stand") {
    msg ("You stand.")
    game.todo = Split("walk|run|sit|handstand|cancel", "|")
  } else if (result = "run") {
    msg ("You run around.")
    game.todo = Split("walk|run|sit|handstand|cancel", "|")
  } else if (result = "sit") {
    msg ("You sit down.")
    game.todo = Split("stand|sprawl out|cancel", "|")
  } else if (result = "sprawl out") {
    msg ("You sprawl out.")
    game.todo = Split("sit|stand|cancel", "|")
  } else if (result = "handstand") {
    msg ("You stand on your hands for a bit, then right yourself.")
    game.todo = Split("walk|run|sit|handstand|cancel", "|")
  }
      
  if (result = "cancel") {
    msg ("Canceled.")
    // msg ("{command:menume:DO IT AGAIN}")
  } else {
    todomenu ()
  }

}

a slightly better design:

<game name="example_game">
  <attr name="todo" type="simplestringlist">walk; ETC; ETC; ETC</attr> // too lazy to write in all of the items...
</game>

// 'todomenu' Function (I'd have to indent the scripting below to put it into an actual Function tag, so just doing this instead):

ShowMenu ("What to do now?", game.todo, false) {

  if (result = "walk") {
    msg ("You walk.")
  } else if (result = "stand") {
    msg ("You stand.")
  } else if (result = "run") {
    msg ("You run around.")
  } else if (result = "sit") {
    msg ("You sit down.")
  } else if (result = "sprawl out") {
    msg ("You sprawl out.")
  } else if (result = "handstand") {
    msg ("You stand on your hands for a bit, then right yourself.")
  }
      
  if (result = "cancel") {
    msg ("Canceled.")
    // msg ("{command:menume:DO IT AGAIN}")
  } else {
    list remove (game.todo, result)
    todomenu ()
  }

}

Dictionaries are actually extremely nice, and not as complicated as them seem to be:

literally think of a Dictionary as a 'input-output' Function/Equation in math, or as a 'conversion' Function:

String Dictionary:

string input: name_of_key
string output: string_value

Object Dictionary:

string input: name_of_key
Object reference/pointer output: name_of_object_value

Script Dictionary:

string input: name_of_key
script output: script_value

Dictionary (dynamic: quest parses what type of dictionary to use for you): http://docs.textadventures.co.uk/quest/types/dictionary.html

for example:

<object name="example_object">

  // Dictionary (dynamic: quest parses what type of Dictionary to use for you) : http://docs.textadventures.co.uk/quest/types/dictionary.html

  // String Dictionary ( http://docs.textadventures.co.uk/quest/types/stringdictionary.html ):

  // this quick form/format/style is nice for when your values are short (and you don't want a long vertical wall of items, lol):

  <attr name="example_stringdictionary_attribute" type="simplestringdictionary">princess = The princess has been kidnapped by the dragon; dragon = The dragon can only be killed by the dragon slayer sword; sword = The dragon slaying sword is held by the wizard; wizard = The wizard can be found in his tower</attr>

  // or another form/format/style (if you got paragraphs for your values):

  <attr name="example_stringdictionary_attribute" type="simplestringdictionary">
    <item>
      <key>princess</key>
      <value>The princess has been kidnapped by the dragon</value>
    </item>
    <item>
      <key>dragon</key>
      <value>The dragon can only be killed by the dragon slayer sword</value>
    </item>
    <item>
      <key>sword</key>
      <value>The dragon slaying sword is held by the wizard</value>
    </item>
    <item>
      <key>wizard</key>
      <value>The wizard can be found in his tower</value>
    </item>
  </attr>

  // Object Dictionary ( http://docs.textadventures.co.uk/quest/types/objectdictionary.html ):

  <attr name="example_objectdictionary_attribute" type="simpleobjectdictionary">princess = princess_object; dragon = dragon_object; sword = sword_object; wizard = wizard_object</attr>

  // Script Dictionary ( http://docs.textadventures.co.uk/quest/types/scriptdictionary.html ):

  <attr name="example_scriptdictionary_attribute" type="scriptdictionary">
    <item key="princess">
      msg ("The princess has been kidnapped by the dragon")
    </item>
    <item key="dragon">
      msg ("The dragon can only be killed by the dragon slayer sword")
    </item>
    <item key="sword">
      msg ("The dragon slaying sword is held by the wizard")
    </item>
    <item key="wizard">
      msg ("The wizard can be found in his tower")
    </item>
  </attr>

</object>

<object name="princess_object">
</object>

<object name="dragon_object">
</object>

<object name="sword_object">
</object>

<object name="wizard_object">
</object>

this 'input-output' or 'conversion' functionality of Dictionaries, let's you do some really cool stuff!

(you can use Lists with Dictionaries, to utilize their full power, just like with Attributes and the 'if' Script being used together)

for example, Pixie's opposite spells (damage/elemental types) functionality, quick/brief conceptually about it only:

<object name="global_data_object">
  <attr name="elemental_dict" type="simplestringdictionary">fire = water; water = fire</attr> //we need the 'water = fire' (the reverse) because remember its: input ----> output, so: fire -----> water, and: water -----> fire
</object>

<object name="water_dragon">
  <attr name="elemental_string" type="string">water</attr>
</object>

<object name="fireball_spell">
  <attr name="elemental_string" type="string">fire</attr>
  <attr name="cast" type="script">
    if (fireball_spell.elemental_string = water_dragon.elemental_string) { // if (fireball:fire = fire:fire_dragon/NOT:water_dragon) // this means that you got the same elements, and so either it does no damage ("immunity") or it does less damage ("strong") or it reflects the damage back onto you ("reflect"):
      water_dragon.current_life = water_dragon.current_life - (fireball_spell.damage / 2)
    if (fireball_spell.elemental_string = StringDictionaryItem (global_data_object.elemental_dict, water_dragon.elemental_string) { // if (fireball: fire = (water_dragon:water ----> dictionary conversion ----> fire)) // if (fireball:fire = fire: opposite element of water_dragon): this means that the elementals are opposite and thus more damage ("weak") is to be done:
      water_dragon.current_life = water_dragon.current_life - (fireball_spell.damage * 2)
    } else { // not opposite elements and not same elements, so normal damage is done:
      water_dragon.current_life = water_dragon.current_life - fireball_spell.damage
    }
  </attr>
</object>

and an example of using Lists with dictionaries:

<object name="king">

  <attr name="dialogue" type="script">

    // as one line (easy to mess it up: missing/extra parenthesis and/or in the wrong locations and/or etc mistakes, and also having to do these iterative operations over and over, is extra/un-needed operations, whereas by creating Variables as seen a bit further below, you'll actually be doing less operations):

    msg (StringDictionaryItem (this.topic_stringdictionary_attribute, StringListItem (this.topic_stringlist_attribute, GetRandomInt (0, ListCount (this.topic_stringlist_attribute) - 1))))

    // or, as multiple lines (better for getting it correct and working, and for doing more stuff as you got all those Variables for use):

    list_count_integer_variable = ListCount (this.topic_stringlist_attribute)
    last_index_number_integer_variable = list_count_integer_variable - 1
    random_in_bounds_index_number_integer_variable = GetRandomInt (0, last_index_number_integer_variable)
    random_list_item_string_variable = StringListItem (this.topic_stringlist_attribute, random_in_bounds_index_number_integer_variable)
    random_dictionary_item_string_variable = StringDictionaryItem (this.topic_stringdictionary_attribute, random_list_item_string_variable)

    msg (random_dictionary_item_string_variable)
   
  </attr>

  <attr name="topic_stringlist_attribute" type="simplestringlist">princess;dragon;sword;wizard"</attr>

  <attr name="topic_stringdictionary_attribute" type="simplestringdictionary">
    <item>
      <key>princess</key>
      <value>The princess has been kidnapped by the dragon</value>
    </item>
    <item>
      <key>dragon</key>
      <value>The dragon can only be killed by the dragon slayer sword</value>
    </item>
    <item>
      <key>sword</key>
      <value>The dragon slaying sword is held by the wizard</value>
    </item>
    <item>
      <key>wizard</key>
      <value>The wizard can be found in his tower</value>
    </item>
  </attr>

</object>

and by using lists with dictionaries, the lists are great to be used for adding/removing items from them, while leaving your dictionary alone / keeping it un-touched.


HK,

Whoa! That stream-lined code DOES look better! (Plus, it looks like it would save me from constantly searching for my missing/extra } after having written an IF... statement!!!)


Also, holy schnikeys!

<attr name="todo" type="simplestringlist">walk; waddle; saunter; sashay; jog; run; hop; skip; jump</attr>

I didn't know you could do it that way in Code View!

(Sweet!)


Log in to post a reply.

Support

Forums