Getting result (New Problem)

Deckrect
22 Nov 2016, 12:28

I was trying to follow the "character creation" tutorial in order to solve a problem about getting a result, however it is not working.

The premise here is a scrip to be run when the player clicks on an Object's verb. It should get an input from the player, what would be a number. The game compares the result to the player attribute named "player.Narrative" and if it is greater, it returns a massage to warn the number is invalid because the character has not that much of "player.Narrative".

If the result is smaller than player.Narrative attribute, then it sets player.task = result.

I believe it should be simple, but things are not happening as i supposed. After a test, i tried first creating a new attribute named player.invest just to store the result. But anyway, it is not working.

This is the last code i used:

player.invest = result
if (player.invest>player.Narrative) {
msg ("Ashley has not that points.")
}
else {
player.task = player.invest
}

I suppose the problem here is Quest is taking the answer as a string and not an Int. So, i suppose i need finding both a way of telling it should be an Int and that it should cancel or ignore the result in case of a string.


The Pixie
22 Nov 2016, 13:27

Use IsInt to test if a string can be concerted to an integer, and if it can, use ToInt to get the value.


Deckrect
22 Nov 2016, 13:50

Thank you, Pixie! now i am having a hard time trying to figure out how following this instructions! lol

This is the code i came up:

get input {
if (IsInt (result)) {
ToInt (result)
if (result>player.Narrative) {
msg ("You have not so many points!")
}
else {
player.task = result
}
}
else {
msg ("This is not a number!")
}
}

But any number i place, it is returning an error massage like this:

Error running script: Function not found: 'ToInt'

The good news is that it returns correctly if i do not type a number!


Deckrect
22 Nov 2016, 14:10

As you can see, on the second attempt i suppressed the player.invest from the script in order to reduce the number os attributes in the game. This time, i returned it to the scrip this way:

get input {
if (IsInt (result)) {
player.invest=ToInt (result)
if (player.invest>player.Narrative) {
msg ("You have not so many points!")
}
else {
player.task = player.invest
}
}
else {
msg ("This is not a number!")
}
}

It seems to be working fine. I will tell the game to print the result to check if it is working all good!
Thank you, Pixie! And thank you HK for another post where you approach the matter.


hegemonkhan
22 Nov 2016, 21:31

good job, you discovered the error!

When a Function returns a Value, it must be used: set/stored to a VARIABLE or used by another Function/Script, examples:

game.integer_attribute = GetRandomInt (1,10)

msg (game.integer_attribute)

// -----------------

game.stringlist_attribute = split ("red;blue;yellow", ";")
game.string_attribute = StringListItem (game.stringlist_attribute, GetRandomInt (0,2))

msg (game.string_attribute)

Deckrect
22 Nov 2016, 23:54

Thanks, Hk.


Deckrect
26 Nov 2016, 00:53

I am using a script to ask the player how many of the "Narrative Points" he/she wants investing on the task at hand. So it takes the result to later compare to the difficulty level and print the results of the attempt. I created a few details on the script to check if the character has so many points and even return if the player types a string instead of a number.

However, i am not finding a way to make Quest ask again if the player does not type a valid number (More points than possessed or strings instead of numbers) In the way the script is, the game just treats what was typed as if a zero and goes on. I need to make it try again if the Get Input gets something not valid. Here goes the script:

if (Got(Influence Trait)) {
player.task = player.task + 2
}
msg ("How many Narrative Points will Ashley invest on this task?")
get input {
if (IsInt (result)) {
player.invest = ToInt (result)
if (player.invest>player.Narrative) {
msg ("Ashley has not that many Narrative Points!")
}
else if (player.invest<0) {
msg ("You may not invest negative numbers.")
}
else {
player.task = player.task+player.invest
player.Narrative = player.Narrative - player.invest
}
}
else {
msg ("Why don't you try a number?")
}
}


Deckrect
26 Nov 2016, 01:01

By the way, i am making some experiments with Call Function. However, it is not solved yet and i am not sure if it is the best way.


Deckrect
26 Nov 2016, 01:08

This is the new code using Functions. But still not working:

msg ("How many Narrative Points will Ashley invest on this task?")
get input {
if (IsInt (result)) {
player.invest = ToInt (result)
if (player.invest>player.Narrative) {
msg ("Ashley has not that many Narrative Points!")
Resolution
}
else if (player.invest<0) {
msg ("You may not invest negative numbers.")
Resolution
}
else {
player.task = player.invest
player.Narrative = player.Narrative - player.invest
}
}
else {
msg ("Why don't you try a number?")
}
msg ("End of test")
}


hegemonkhan
26 Nov 2016, 02:43

the trick is you got to loop ('looping') (do/run/use/activate/exevute/call/invoke/etc again) your scripting, which can be done a few ways:

(you do NOT want an endless/infinite loop... as while the looping is endless/inifinte, quest's/computer's resources to handle the looping are not endless/infinite, and so quest crashes)

  1. using a Function for your scripting, and calling (doing/running/activating/executing/using) the Function again

(Functions also allow for Parameter/Argument/input_values and return-value capabilities)

in code:

<game name="example_game">
  <attr name="start" type="script">
    example_function
  </attr>
</game>

<function name="example_function">
  ask ("loop this function?") {
    if (result) { // if yes/true
      example_function
    } else { // if no/false
      msg ("You decided not to loop this function")
    }
  }
</function>

for the GUI/Editor scripting path, for using/doing/calling your Function:

(create/add your Function and its scripting, of course, so your Function exists, so you can then use/call/do it, lol)

run as script -> add new script -> 'output(I think)' section/category -> 'call function' Script -> (see below)

Function Name (small/skinny rectangle text box): type in the name of your function you want to do/use
optionally click the 'add parameters' button, to add in your arguments (input values) for your parameters, which are to be used by the Function's scripting), and to loop, simply add in another 'call function' Script where you want it within/for your Function's scripting.


  1. using a Script Attribute for your scripting:

(A script Attribute by itself can't use Parameters nor have a return value, however you can also create/add Delegates, which will allow the capability of Parameters and a return value to your use of using a Script Attribute, so it's the same as a Function)

<game name="example_game">
  <attr name="start" type="script">
    do (game, "example_script_attribute") // 'do' is more powerful/useful, as it allows you to use/do concatenation/nested Functions for your Object's and/or Attirbute's name inputs)
    // or:
    // invoke (game.example_script_attribute) // but for running a simple Script Attribute, 'invoke' is fine
  </attr>
  <attr name="example_script_attribute" type="script">
    ask ("loop this script attribute?") {
      if (result) { // if yes/true
        do (game, "example_script_attribute") // 'do' is more powerful/useful, as it allows you to use/do concatenation/nested Functions for your Object's and/or Attirbute's name inputs)
        // or:
        // invoke (game.example_script_attribute) // but for running a simple Script Attribute, 'invoke' is fine
      } else { // if no/false
        msg ("You decided not to loop this script attribute")
      }
    }
  </attr>
</game>

as for how to do this in the GUI/Editor, taking some guesses:

there should be a scripting option to do a Script Attribute, but if not, you should be able to use the 'call function' Script, and type in 'do' or 'invoke' as these are Functions, but you'll have to add in their needed parameter arguments: name of object, name of script attribute. Let me know if you need help on how/what to do with this stuff.


there's also the 'while' Function too, and you can also use the 'for' or 'foreach' Functions as well.


if you can understand code, here's a lot of examples of looping Functions:

(you can try copying my code, and pasting it into a new game's game code --- delete it's default code of course, and maybe you can 'play/see/try/test/study' my character creation code in action)

(though, this is very badly done old code, as I was having issues for an unknown reason, so that's why I have so many Functions, instead of creating a single Function to do all of those Functions)

http://textadventures.co.uk/forum/samples/topic/4988/character-creation-crude-code-and-sample-game

on/for character creation


TinFoilMkIV
26 Nov 2016, 02:49

What you'll want to do is turn that entire script into a function, This will allow you to repeatedly run the function in a normal script. When you reach either of the error states you call the function again to make it repeat till a valid input is given.

example
event script of whatever is happening

//stuff happens, player is performing a task
InvestPoints()
player.task = player.invest

InvestPoints function

msg ("How many Narrative Points will Ashley invest on this task?")
get input {
if (IsInt (result)) {
player.invest = ToInt (result)
if (player.invest>player.Narrative) {
msg ("Ashley has not that many Narrative Points!")
Resolution
}
else if (player.invest<0) {
msg ("You may not invest negative numbers.")
InvestPoints()
}
else {
player.task = player.invest
player.Narrative = player.Narrative - player.invest
}
}
else {
msg ("Why don't you try a number?")
InvestPoints()
}
msg ("End of test")
}


hegemonkhan
26 Nov 2016, 02:57

P.S.

if you're coding in directly (non-GU/IEditor), and you use the greater than ( > ) or lesser than ( < ) symbols... you need your scripting to be encased within these tags:

<![CDATA[ your scripting ]]>

for example:

<function name="example_function">
  if (player.strength_integer_attribute > 66) {
    player.strength_string_attribute = "strong"
  } else if (player.strength_integer_attribute > 33) {
    player.strength_string_attribute = "average"
  } else {
    player.strength_string_attribute = "weak"
  }
</function>

// ERROR!!! quest is incorrectly reading your '>' and '<' symbols in your/mine/whatever/lol 'if/else if' Scripts as aslx/xml/html creation tags ( like this such creation tag: <function name="example_function">content</function> ), and not correctly as 'greater than' and 'lesser than' math-value-comparison operations/symbols. This is what the 'CDATA' tag does.

// --------

<function name="example_function"><![CDATA[
  if (player.strength_integer_attribute > 66) {
    player.strength_string_attribute = "strong"
  } else if (player.strength_integer_attribute > 33) {
    player.strength_string_attribute = "average"
  } else {
    player.strength_string_attribute = "weak"
  }
]]></function>

// NO error

// or if you like this format better (you can see the nesting/containment/indenting/relationship layers/levels clearly):

<function name="example_function">
  <![CDATA[
    if (player.strength_integer_attribute > 66) {
      player.strength_string_attribute = "strong"
    } else if (player.strength_integer_attribute > 33) {
      player.strength_string_attribute = "average"
    } else {
      player.strength_string_attribute = "weak"
    }
  ]]>
</function>

// NO error

Deckrect
26 Nov 2016, 11:19

Oh, people! This is a lot yo study! Again! lol

Yesterday, i barely made it work. I can make it works when i get the desired result running if all conditions are ok. However, it leaves me with a weird problem. If making a Function, i need it would be called every single time the game needs solving a "Task Test". However, the "what to do if everything is fine" (i.e. How perform is player entered a number under or equal to player.Narrative) must be stored in the place where the script was called. So, everything ruins.

I am not sure if i can see the advantages of storing the script as an attribute instead of a Function, however i also do not understand a lot of stuff. I still clueless about the Function parameters, and perhaps it may be important for this script.

So, all i may do for now is to sit and study our posts and try to figure out how to solve the matter. Perhaps i should hire HK to solve this code for me.


Deckrect
26 Nov 2016, 11:47

TinFoilMkIV, your suggestion is also not working. It is doing the basic same error. If the player types an undesired result (not a number, negative number or excessive value) if flows to the "End Test" print.

I need a Function to be called and only allow the Object's script continue running if it gets a valid result from player, basically. I made it work once, but working only giving one result. I need this script to be an ace, to be called every time i need taking an input from the player to solve a task.

Now i will study in detail HK's suggestions.


hegemonkhan
26 Nov 2016, 14:27

let's look at some very simple Functions, to help you understand how Parameters/Arguments (inputs) work (and if need be, returned values too):

<function name="adder_function" parameters="number_1_parameter,number_2_parameter" type="int">
  return (number_1_parameter + number_2_parameter)
</function>

<function name="subtracter_function" parameters="number_1_parameter,number_2_parameter" type="int">
  return (number_1_parameter - number_2_parameter)
</function>

<function name="multiplier_function" parameters="number_1_parameter,number_2_parameter" type="int">
  return (number_1_parameter * number_2_parameter)
</function>

<function name="divider_function" parameters="number_1_parameter,number_2_parameter" type="int">
  return (number_1_parameter / number_2_parameter)
</function>

<function name="display_function">
  msg (game.integer_attribute)
</function>

<function name="test_function">
    display_function
    game.integer_attribute = adder_function (10,5)
    display_function
    game.integer_attribute = subtracter_function (10,5)
    display_function
    game.integer_attribute = multiplier_function (10,5)
    display_function
    game.integer_attribute = divider_function (10,5)
    display_function
    game.integer_attribute = adder_function (5,5)
    display_function
    game.integer_attribute = subtracter_function (5,5)
    display_function
    game.integer_attribute = multiplier_function (5,5)
    display_function
    game.integer_attribute = divider_function (5,5)
    display_function
    game.integer_attribute = adder_function (50,5)
    display_function
    game.integer_attribute = subtracter_function (50,5)
    display_function
    game.integer_attribute = multiplier_function (50,5)
    display_function
    game.integer_attribute = divider_function (50,5)
</function>

<game name="example_game">
  <attr name="integer_attribute" type="int">0</attr>
  <attr name="start" type="script">
    test_function
  </attr>
</game>

// -------------------------

// game.integer_attribute = 0
// game.start
// -> test_function
// ->-> display_function
// ->->-> 0
// ->-> adder_function (10,5)
// ->->-> game.integer_attribute = 15
// ->-> display_function
// ->->-> 15
// ->-> subtracter_function (10,5)
// ->->-> game.integer_attribute = 5
// ->-> display_function
// ->->-> 5
// ->-> multiplier_function (10,5)
// ->->-> game.integer_attribute = 50
// ->-> display_function
// ->->-> 50
// ->-> divider_function (10,5)
// ->->-> game.integer_attribute = 2
// ->-> display_function
// ->->-> 2
// ->-> adder_function (5,5)
// ->->-> game.integer_attribute = 10
// ->-> display_function
// ->->-> 10
// ->-> subtracter_function (5,5)
// ->->-> game.integer_attribute = 0
// ->-> display_function
// ->->-> 0
// ->-> multiplier_function (5,5)
// ->->-> game.integer_attribute = 25
// ->-> display_function
// ->->-> 25
// ->-> divider_function (5,5)
// ->->-> game.integer_attribute = 1
// ->-> display_function
// ->->-> 1
// ->-> adder_function (50,5)
// ->->-> game.integer_attribute = 55
// ->-> display_function
// ->->-> 55
// ->-> subtracter_function (50,5)
// ->->-> game.integer_attribute = 45
// ->-> display_function
// ->->-> 45
// ->-> multiplier_function (50,5)
// ->->-> game.integer_attribute = 250
// ->-> display_function
// ->->-> 250
// ->-> divider_function (50,5)
// ->->-> game.integer_attribute = 10
// ->-> display_function
// ->->-> 10

// -------------------

how Parameters/Arguments work:

game.attribute_1 = "one"
game.attribute_2 = "two"

<function name="example_function" parameter="parameter_1,parameter_2">
// <function name="example_function" parameter="(position 1) parameter_1, (position 2) parameter_2">
  msg (parameter_1)
  msg (Parameter_1)
</function>

// ---

example_function (game.attribute_1,game.attribute_2)
// Argument Values/VARIABLES: (position 1 / argument 1) game.attribute_1, (position 2 / argument 2) game.attribute_2
// example_function (argument 1: game.attribute_1 = "one", argument 2: game.attribute_2 = "two")

// quest does this stuff automatically (hidden from you) for you:
//
// Argument position 1 matches up with Parameter position 1:
// parameter_1 = (argument_1) game.attribute_1 = "one"
// parameter_1 = "one"
//
// Argument position 2 matches up with Parameter position 2:
// parameter_2 = (argument 2) game.attribute_2 = "two"
// parameter_2 = "two"

// msg (parameter_1)
// output: one
//
// msg (parameter_2)
// output: two

the GUI/Editor works the same way: NAME_OF_FUNCTION and optionally 'add in your: arguments when calling function / parameters when creating-adding function' and optionally setting it to have a return value and what type of value (int, string, double, object, boolean, etc) you'll must (else an error) return, so hopefully you can figure it out from comparing it to my function coding


does this help, or is it confusing to you?


Deckrect
26 Nov 2016, 15:06

Never mind, people. I found an alternative solution, not using Functions, but changing the logic of where scripts are placed and what happens next.


hegemonkhan
26 Nov 2016, 15:15

think of scripting as a phone call, you can communicate via your voice, but once the phone call is over, what was communicated is lost/erased/gone-forever/destroyed (ignore real life tele-companies recording/saving your conversations without your permission for cops to use against you, lol). You can't use that communication elsewhere as it no longer exists.

This type of non-preserved/saved/stored/recorded communication is the use of:

Variable VARIABLES (NAME_OF_VARIABLE = VALUE_OR_EXPRESSION), examples:

x = 5
handled = false
right_hand = sword // 'sword' must be an actual existing or still existing Object, of course
my_string = "hi, my name is HK, what is your name?"

<game name="blah_game">
  <attr name="start" type="script">
    blah_function // NO error occurs, as it creates its local 'x' Variable along with it's (initial) value of 5
    // 'blah_function' has ended, so its local 'x' Variable is destroyed, and thus now there's no existing 'x' Variable
    blah_2_function // this function fails as it uses an 'x' Variable, but none exists for it to use
    // let's just pretend that the error in 'blah_2_function' doesn't prevent from doing 'blah_3_function', so we can continue...
    blah_3_function // NO error occurs, as it creates its local 'x' Variable along with it's (initial) value of 8
    // 'blah_3_function' has ended, so its local 'x' Variable is destroyed, and thus now there's no existing 'x' Variable
  </attr>
</game>

<function name="blah_function">
  x = 5
  msg (x)
  // outputs: 5
  // NO error here
</function>

<function name="blah_2_function">
  msg (x)
  // ERROR: there is no 'x' Variable created/existing
</function>

<function name="blah_3_function">
  x = 8
  msg (x)
  // outputs: 8
  // no error here
</function>

this is why Attribute VARIABLES are used most of the time in quest, as these DO save/store/record (as long as the Attribute's Object exists or still exists), so you can use them anywhere and as much as you want:

NAME_OF_OBJECT.NAME_OF_ATTRIBUTE = VALUE_OR_EXPRESSION

the Object is the Object containing/holding the Attribute (think of the Object as a basket, which can hold Attributes and/or other Objects, as its 'eggs' inside of it), this is done in the GUI/Editor via: 'whatever' Object -> 'Attributes' Tab -> Attributes -> Add -> (set up your attribute), or through the GUI/Editor's scripting options: 'set a variable or attribute' Script.

examples:

game.state = 0
player.sex = "male"
orc.right_hand = club
bird.flying = true

<game name="blah_game">
  <attr name="state" type="int">123</attr>
  <attr name="start" type="script">
    msg (game.state) // outputs: 123
    blah_function // outputs: 123
    msg (game.state) // outputs: 123
    // NO errors at all
  </attr>
</game>

<function name="blah_function">
  msg (game.state)
</function>

hegemonkhan
26 Nov 2016, 15:30

correct indenting/nesting/containment/parent-child-heirarchy (or in the GUI/Editor, clicking on the 7^&% correct 'add new script' circle button, ARGH! - doing scripts in the gUI/Editor is so so so frustrating --- especially when you accidentally delete a massive scriping block... GROWLES) is vital, as it is the 'order of operations / placement-containment' of scripting.

Scripting is/works-as practically/almost/nearly the exact same as an outline:

I. get input
  A. if (result = 1)
    1.  if (game.state = 0)
       a. player.strength = result
     2. else if (game.state = 10)
      b. player.strength = result * 100
  B. if (result = 2)
II. if (player.strength = 100
 A. if (result = 1)
   1. msg ("strong")

Deckrect
26 Nov 2016, 19:16

lol Nice, HK! I still not knowing why the Function was not working. However i found a way to make the game work and that i can understand what is happening, even if needs repeating the code every time i need it, what is not elegant.