Character Creation Issues

Hey there,

I'm starting to learn my way around Quest and I've been following http://docs.textadventures.co.uk/quest/character_creation.html . I've literally copy-and-pasted the code to have a look at it, see how it works, before starting to customise it; I wanted to start of with something known as working before breaking it as I try to customise it to my own needs. Unfortunately, copy and pasting it hasn't gotten me something working.

I encounter the following issues:

  1. When run, it skips the first question (name) and instead displays several messages all at once:
    "Let's generate a character...
    First, what is your name?
    Hi, me
    Your gender?" in the background.
  2. The error "Error running script: Only one menu can be shown at a time." is displayed in the background
  3. The menu to choose gender is displayed, but on clicking either option the error "Error running script: Function not found: 'CharacterCreationClassMale'" is displayed.

The code I've copied from the link above is:

<start type="script">
msg ("Let's generate a character...")
msg ("First, what is your name?")
get input  {
  player.alias = result
  CharacterCreationGender
}
msg ("Hi, " + player.alias)
show menu ("Your gender?", Split ("Male;Female", ";"), false) {
  player.gender = result
  if (result = "Female") {
    CharacterCreationClassFemale
  }
  else {
    CharacterCreationClassMale
  }
}
show menu ("Your character class?", Split ("Amazon;Witch;Priestess;Thief", ";"), false) {
  player.class = result
  switch (result) {
    case ("Amazon") {
      player.strength = 3
      player.agility = 1
      fur_bikini.parent = player
    }
    case ("Witch") {
      player.magic = 4
      black_robes.parent = player
    }
    case ("Priestess") {
      player.magic = 2
      player.agility = 2
      white_robes.parent = player
    }
    case ("Thief") {
      player.agility = 4
      black_catsuit.parent = player
    }
  }
  CharacterCreationBackground
}
show menu ("Your character class?", Split ("Barbarian;Wizard;Priest;Thief", ";"), false) {
  player.class = result
  switch (result) {
    case ("Barbarian") {
      player.strength = 4
      fur_thong.parent = player
    }
    case ("Wizard") {
      player.magic = 4
      black_robes.parent = player
    }
    case ("Priest") {
      player.magic = 2
      player.strength = 2
      brown_robes.parent = player
    }
    case ("Thief") {
      player.agility = 4
      black_catsuit.parent = player
    }
  }
  CharacterCreationBackground
}
 </start>

Can someone please point me in the right direction, as I'm a little stumped as to why literally copy-and-pasting the tutorial example isn't working.


Your problem involves what I call "simultaneous scriptflow". I.e., while Quest is waiting for a response from the player after get input or show menu, Quest will keep executing scripts that are on the same vertical "level" as the get input or show menu script.

So you need to restructure your code so that everything in that chunk of creation code that follows get input/show menu is nested within that same get input/show menu script (i.e., indented). Look at that link in your post again and see how Pixie does it -- see how his code is indented while yours is on the same level.

The following link is directly related to your issue. It will probably confuse you even more :P, but I offer it for completeness:

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


It's part of what I would refer to as bad programming in the Quest code...
In Basic, the program stops at a "Get Input" command, then continues after...
So, in Quest you need to nest the Get Input commands

get input {
get input {
get input {
get input {
CharacterCreationBackground
}
}
}
}
The main problem is keeping track of all the nests to get them to come out right.
You could also set it up as a series of rooms that the player goes through like this:
(Not real code)
(Room1)
msg ("What is your name?")
get input {
player.alias = result
move player, Room2
}
(Room2)
msg ("Hi, " + player.alias)
show menu ("Your gender?", Split ("Male;Female", ";"), false) {
player.gender = result
(extra code here)
move player, Room3
}
(Room3)
show menu ("Your character class?", Split ("Amazon;Witch;Priestess;Thief", ";"), false) {
player.class = result
(extra code)
move player, Room4
}
and so on...


I've literally copy-and-pasted the code to have a look at it

If you copy and pasted, why is your code not the same as the code in the tutorial?

Ah, you've taken the example code for all the different functions and put them in the same block of script.
You can't do that; if you're using functions you need to create the functions.


Okay, I want to make sure I understand this correctly.

The recommended way around this is to nest the code (resulting in it becoming increasingly difficult to track what belongs where), or to create individual rooms for each question?

I can relatively easily go through and nest the code, but want to make sure I'm not missing another way around this, and that I was misreading http://docs.textadventures.co.uk/quest/character_creation.html when it implied that the latter part of the page was a way of avoiding that.

If I've misread something, please do let me know, as whilst I've not used Quest before I do have at least some modicum of experience working with other people's code to make some simple changes in a few languages, not enough for me to code from scratch mind you, but at least enough to understand and change it (mostly) without breaking it once I understand the structure.


the latter part of the page was a way of avoiding that.

You don't need to make different rooms, or to nest everything.

You can do what it says on that page. It lists several blocks of code, each of which is a function. You seem to have taken all of that code and put it in one place.

My preferred method is to put it all in one function, making it easier if you want the player to be able to go back and change their mind. But using a function for each question like it says in the tutorial is probably easier to follow if you don't think in code.


you can also take a look at these links/guides/resources as well to help you with quest and its coding:

http://textadventures.co.uk/forum/general/topic/ljjm32av4e2t9ot49k478g/help#710be61e-eae1-4af1-8363-520cc718ba1c

and you can see my own struggle (starting with parts of the tutorial that I was having trouble with and then next onto the 'character creation' guide myself) back when I first found quest, knowing ZERO/NOTHING about coding and game making:

https://textadventures.co.uk/forum/quest/topic/3348/noobie-hks-help-me-thread

https://textadventures.co.uk/forum/quest/topic/3348/noobie-hks-help-me-thread#22036 (here's my first post on getting help on learning the 'character creation' guide/code)


ask if you need help with anything


Apologies for the delayed reply; things got kind of hectic at work in the run up to Christmas, and then Christmas itself hit.

RE: "You can do what it says on that page. It lists several blocks of code, each of which is a function. You seem to have taken all of that code and put it in one place."
Right, I was expecting to get some useful error messages when trying to run it which would point towards things that hadn't been defined and to work from there. As you can see, that didn't happen as the error messages weren't quite enough to point me towards where/how to define.

When searching for functions in the tutorial all I could find was the functions build in to Quest (http://docs.textadventures.co.uk/quest/functions/) which, whilst I'm sure I'll find that useful, I don't believe is quite what I was looking for.

Is there a good link out there for defining functions as are being discussed here?


here's pixie's post helping me understand the code, with the code being a single scripting (within the built-in special 'start' Script Attribute of the special 'game' game-wide settings and publishing info Object), but its within an example full game code:

taken from here: https://textadventures.co.uk/forum/quest/topic/3348/noobie-hks-help-me-thread#22036
and here: https://textadventures.co.uk/forum/quest/topic/3348/noobie-hks-help-me-thread#22041

<asl version="550">

  <include ref="English.aslx" />
  <include ref="Core.aslx" />

  <game name="NAME_OF_GAME">

    <attr name="gameid" type="string">SOME_RANDOM_GENERATED_HASH_STRING_AS_THE_ID_FOR_PUBLISHING_GAMES_ON_QUEST_SERVER</attr>

    <attr name="author" type="string">NAME_OF_AUTHOR</attr>

    <attr name="version" type="string">YOUR_VERSION_AS_DECIMAL_NUMBER_HISTORY_IN_CREATING_YOUR_GAME</attr>

    <attr name="firstpublished" type="string">THE_4_DIGIT_YEAR</attr>

    <!--
    etc Attributes
    -->

    <gender_list type="stringlist">

      <value>male</value>
      <value>female</value>

    </gender_list>

    <class_list type="stringlist">

      <value>warrior</value>
      <value>thief</value>
      <value>cleric</value>
      <value>wizard</value>

    </class_list>

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

      msg ("Let's generate a character...")
      msg ("First, what is your name?")
      get input  {
        player.alias = result
        msg ("Hi, " + player.alias)
        show menu ("Your gender?", game.gender_list, false) {
          player.gender = result
          show menu ("Your skill set?", game.class_list, false) {
            player.class = result
            msg (" ")
            msg (player.alias + " was a " + LCase (player.gender) + " " + LCase (player.class) + ".")
            msg (" ")
            msg ("Now press a key to begin...")
            wait {
              ClearScreen
            }
          }
        }
      }

    </attr>

  </game>

  <object name="room">

    <inherit name="editor_room" />

  </object>

  <object name="player">

    <inherit name="editor_object" />
    <inherit name="editor_player" />

    <attr name="parent" type="object">room</attr>

  </object>

</asl>

here is it, put within a single Function:

<asl version="550">

  <include ref="English.aslx" />
  <include ref="Core.aslx" />

  <game name="NAME_OF_GAME">

    <attr name="gameid" type="string">SOME_RANDOM_GENERATED_HASH_STRING_AS_THE_ID_FOR_PUBLISHING_GAMES_ON_QUEST_SERVER</attr>

    <attr name="author" type="string">NAME_OF_AUTHOR</attr>

    <attr name="version" type="string">YOUR_VERSION_AS_DECIMAL_NUMBER_HISTORY_IN_CREATING_YOUR_GAME</attr>

    <attr name="firstpublished" type="string">THE_4_DIGIT_YEAR</attr>

    <!--
    etc Attributes
    -->

    <gender_list type="stringlist">

      <value>male</value>
      <value>female</value>

    </gender_list>

    <class_list type="stringlist">

      <value>warrior</value>
      <value>thief</value>
      <value>cleric</value>
      <value>wizard</value>

    </class_list>

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

      character_creation_function

    </attr>

  </game>

  <object name="room">

    <inherit name="editor_room" />

  </object>

  <object name="player">

    <inherit name="editor_object" />
    <inherit name="editor_player" />

    <attr name="parent" type="object">room</attr>

  </object>

  <function name="character_creation_function">

    msg ("Let's generate a character...")
    msg ("First, what is your name?")
    get input  {
      player.alias = result
      msg ("Hi, " + player.alias)
      show menu ("Your gender?", game.gender_list, false) {
        player.gender = result
        show menu ("Your skill set?", game.class_list, false) {
          player.class = result
          msg (" ")
          msg (player.alias + " was a " + LCase (player.gender) + " " + LCase (player.class) + ".")
          msg (" ")
          msg ("Now press a key to begin...")
          wait {
            ClearScreen
          }
        }
      }
    }

  </function>

</asl>

and here's pixie's explanation of every code line:

     // Here "msg" is a script command, what string is sent to it will appear on the screen
     msg ("Let's generate a character...")
     // And again
     msg ("First, what is your name?")
     // Another script command, "get input". Waits for the player to type something,
     // puts that text into a variable called "result",
     // then runs its 'block'. The block is enclosed in curly braces.
     get input  {
       // The "player" object has an attribute "alias" that is
       // now set to the text in the "result" variable.
       player.alias = result
       // Now use "msg" to print to the screen, but this time the text is constructed
       // by adding together two parts, using the plus sign.
       msg ("Hi, " + player.alias)
       // I have broken one line into two for simplicity
       // The "Split" function breaks up a string of text into set of smaller strings,
       // called a 'string list'.
       // Here it will break up "Male;Female", and it will break the string wherever it
       // find a semi-colon, as the second paramter is ";".
       // The variable "options" will contain the output of the function.
       options = Split ("Male;Female", ";")
       // The "show menu" scrpt command will display a menu for the player.
       // The "Your gender?" part will be the prompt or title.
       // Then it will use the variable "options", which we just set. So the player will
       // have the choice of "Male" or "Female".
       // Finally we have "false", which tells Quest not to let the player cancel the menu
       // choice.
       // As with "get input", when the player makes a choice, the text goes into "result"
       // and the block is run.
       show menu ("Your gender?", options, false) {
         // The "gender" attribute of "player" is now set to "Male" or "Female",
         // as the player chose
         player.gender = result
         // Another menu, just like before, but here the two lines are combined
         // You have the prompt, the string list with the option from the "Split"
         // function, and "false" again.
         show menu ("Your character class?", Split ("Warrior;Wizard;Priest;Thief", ";"), false) {
           // The "class" attribute of "player" is now set.
           player.class = result
           // Print an empty line.
           msg (" ")
           // Print a summary to screen
           msg (player.alias + " was a " + LCase (player.gender) + " " + LCase (player.class) + ".")
           // Print an empty line.
           msg (" ")
           // Print instructions.
           msg ("Now press a key to begin...")
           // The "wait" script command is kind of like "get input", but instead of the player
           // typing a sentence, the player presses a single key. Once that happens,
           // the code in that box runs
           wait {
             // This function clears the screen, as you probably guessed
             ClearScreen
           // This is the end of the "wait" block.
           }
         // This is the end of the second "show menu" block.
         }
       // This is the end of the first "show menu" block.
       }
     // This is the end of the "get input" block.
     }

here's some good reference links:

http://docs.textadventures.co.uk/quest/ (doc main page)

http://docs.textadventures.co.uk/quest/tutorial/ (the tutorial)

http://docs.textadventures.co.uk/quest/elements/ ('Elements' are the "physical things" in quest)

http://docs.textadventures.co.uk/quest/types/ (These are the Attribute Types in quest)

http://docs.textadventures.co.uk/quest/elements/object.html (here's all of the built-in Attributes for Objects)

http://docs.textadventures.co.uk/quest/scripts/ (the built-in Scripts/Functions)

http://docs.textadventures.co.uk/quest/functions/ (the built-in functions: categorical order)
http://docs.textadventures.co.uk/quest/functions/index_allfunctions.html (the built-in functions: alphabetical order)

http://docs.textadventures.co.uk/quest/using_lists.html (using lists: list attributes)

http://docs.textadventures.co.uk/quest/using_dictionaries.html (using dictionaries: dictionary attributes)

http://docs.textadventures.co.uk/quest/display_verbs.html (using the built-in 'displayverbs/inventoryverbs' Stringlist Attributes)


Functions are just a way of organizing parts/segments of code (and they allow you to loop, aka do/run again, those organized segments/parts of code, which is very useful):

conceptual comparison examples below


as a single scripting block within our built-in special 'start' Script Attribute of the special 'game' Game-wide Settings and publishing info Object

aka, within the 'game.start' Script Attribute:

prompt (Name?) script(s)
get/set name script(s)
prompt (Sex?) script(s)
prompt a menu list of choices/options (male/female) script(s)
set sex script(s)
prompt (Class?) script(s)
prompt a menu list of choices/options (warrior/thief/cleric/wizard) script(s)
set class script(s)


or, we can organize (break it up), such as via using Functions

within the 'game.start' Script Attribute:

Name Function (goto/jump-to/do/run/call the Name Function)
Sex Function (goto/jump-to/do/run/call the Sex Function)
Class Function (goto/jump-to/do/run/call the ClassFunction)

Name Function:

prompt (Name?) script(s)
get/set name script(s)

Sex Function:

prompt (Sex?) script(s)
prompt a menu list of choices/options (male/female) script(s)
set sex script(s)

Class Function:

prompt (Sex?) script(s)
prompt a menu list of choices/options (warrior/thief/cleric/wizard) script(s)
set class script(s)


(filler for getting my edited post, updated/posted)
(again, filler for getting my edited post, updated/posted)


here's full game code comparison examples:

re-doing the entire character creation over again if any user (person playing the game) inputs are/were incorrect (which is generally bad, as why re-do the whole thing and not just the specific inputs that are/were wrong? Also, the person playing the game, doesn't want to re-do the entire character creation process either if he/she makes an input mistake, they just want to re-do that specific input/part/segment of code of the character creation, they don't want to have to re-do the entire character creation process)

<asl version="550">

  <include ref="English.aslx" />
  <include ref="Core.aslx" />

  <game name="NAME_OF_GAME">

    <attr name="gameid" type="string">SOME_RANDOM_GENERATED_HASH_STRING_AS_THE_ID_FOR_PUBLISHING_GAMES_ON_QUEST_SERVER</attr>

    <attr name="author" type="string">NAME_OF_AUTHOR</attr>

    <attr name="version" type="string">YOUR_VERSION_AS_DECIMAL_NUMBER_HISTORY_IN_CREATING_YOUR_GAME</attr>

    <attr name="firstpublished" type="string">THE_4_DIGIT_YEAR</attr>

    <!--
    etc Attributes
    -->

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

      character_creation_function

    </attr>

  </game>

  <object name="room">

    <inherit name="editor_room" />

  </object>

  <object name="player">

    <inherit name="editor_object" />
    <inherit name="editor_player" />

    <attr name="parent" type="object">room</attr>

  </object>

  <object name="character_creation_object">

    <inherit name="editor_object" />

    <attr name="name_maximum_length" type="int">8</attr>
    <attr name="name_minimum_length" type="int">3</attr>

    <sex_list type="stringlist">

      <value>male</value>
      <value>female</value>

    </sex_list>

    <class_list type="stringlist">

      <value>warrior</value>
      <value>thief</value>
      <value>cleric</value>
      <value>wizard</value>

    </class_list>

  </object>

  <function name="character_creation_function">

    <![CDATA[

      msg ("Name?")
      get input {
        if (IsNumeric (result)) {
          msg ("Your name must be a string, try again")
          wait {
            ClearScreen
            character_creation_function
          }
        } else if (LengthOf (result) >= character_creation_object.name_minimum_length and LengthOf (result) <= character_creation_object.name_maximum_length) {
          player.alias = result
          msg ("Player Name: " + player.alias)
          ask ("Is this the name you want?") {
            if (result) {
              show menu ("Sex?", character_creation_object.sex_list, false) {
                player.sex = result
                msg ("Player Sex: " + player.sex)
                ask ("Is this the sex you want?") {
                  if (result) {
                    show menu ("Class?", character_creation_object.class_list, false) {
                      player.class = result
                      msg ("Player Class: " + player.class)
                      ask ("Is this the class you want?") {
                        if (not result) {
                          msg ("try again")
                          wait {
                            ClearScreen
                            character_creation_function
                          }
                        }
                      }
                    }
                  } else {
                    msg ("try again")
                    wait {
                      ClearScreen
                      character_creation_function
                    }
                  }
                }
              }
            } else {
              msg ("try again")
              wait {
                ClearScreen
                character_creation_function
              }
            }
          }
        } else {
          msg ("Your name must between: " + character_creation_object.name_minimum_length + " and " + character_creation_object.name_maximum_length + ", try again")
          wait {
            ClearScreen
            character_creation_function
          }
        }
      }

    ]]>

  </function>

</asl>

or organized (broken up) into multiple functions (and thus the ability to only repeat the input/parts/segments that need to be repeated, and not the entire character creation code):

<asl version="550">

  <include ref="English.aslx" />
  <include ref="Core.aslx" />

  <game name="NAME_OF_GAME">

    <attr name="gameid" type="string">SOME_RANDOM_GENERATED_HASH_STRING_AS_THE_ID_FOR_PUBLISHING_GAMES_ON_QUEST_SERVER</attr>

    <attr name="author" type="string">NAME_OF_AUTHOR</attr>

    <attr name="version" type="string">YOUR_VERSION_AS_DECIMAL_NUMBER_HISTORY_IN_CREATING_YOUR_GAME</attr>

    <attr name="firstpublished" type="string">THE_4_DIGIT_YEAR</attr>

    <!--
    etc Attributes
    -->

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

      character_creation_function

    </attr>

  </game>

  <object name="room">

    <inherit name="editor_room" />

  </object>

  <object name="player">

    <inherit name="editor_object" />
    <inherit name="editor_player" />

    <attr name="parent" type="object">room</attr>

  </object>

  <object name="character_creation_object">

    <inherit name="editor_object" />

    <attr name="name_maximum_length" type="int">8</attr>
    <attr name="name_minimum_length" type="int">3</attr>

    <sex_list type="stringlist">

      <value>male</value>
      <value>female</value>

    </sex_list>

    <class_list type="stringlist">

      <value>warrior</value>
      <value>thief</value>
      <value>cleric</value>
      <value>wizard</value>

    </class_list>

  </object>

  <function name="character_creation_function">

    name_function
    on ready {
      sex_function
      on ready {
        class_function
      }
    }

  </function>

  <function name="name_function">

    <![CDATA[

      msg ("Name?")
      get input {
        if (IsNumeric (result)) {
          msg ("Your name must be a string, try again")
          wait {
            ClearScreen
            name_function
          }
        } else if (LengthOf (result) >= character_creation_object.name_minimum_length and LengthOf (result) <= character_creation_object.name_maximum_length) {
          player.alias = result
          msg ("Player Name: " + player.alias)
          ask ("Is this the name you want?") {
            if (not result) {
              msg ("try again")
              wait {
                ClearScreen
                name_function
              }
            }
          }
        } else {
          msg ("Your name must between: " + character_creation_object.name_minimum_length + " and " + character_creation_object.name_maximum_length + ", try again")
          wait {
            ClearScreen
            name_function
          }
        }
      }

    ]]>

  </function>

  <function name="sex_function">

    show menu ("Sex?", character_creation_object.sex_list, false) {
      player.sex = result
      msg ("Player Sex: " + player.sex)
      ask ("Is this the sex you want?") {
        if (not result) {
          msg ("try again")
          wait {
            ClearScreen
            sex_function
          }
        }
      }
    }

  </function>

  <function name="class_function">

    show menu ("Class?", character_creation_object.class_list, false) {
      player.class = result
      msg ("Player Class: " + player.class)
      ask ("Is this the class you want?") {
        if (not result) {
          msg ("try again")
          wait {
            ClearScreen
            class_function
          }
        }
      }
    }

  </function>

</asl>

google


Log in to post a reply.

Support

Forums