SolvedCannot convert type 'String' to expression result of 'IScript'. Calling vs Invoking Functions and using variables.

So I had another off the wall idea about combat menus that then call scripts based off the result. But the regular script function doesn't do it, but then I saw the invoking one and tried it but got the above Error. I'm guessing something is off similar to with doing this with objects, but I can't find anything about turning a string to a function like with GetObject().

Also, I've been poking about Quest's core files to try and learn how they work and been wondering where GetObject() is.

In the end I'm using eval, and my errors were caused by trying to invoke things when I didn't need and it messed things up.


Quest 5 is written in C#, and some of the functions only exist there, rather than in the .aslx files, so that is where getObject() is.
http://docs.textadventures.co.uk/quest/functions/hardcoded.html

The error you have is also from C#, and means something at that level; not so much at the Quest level. More on that towards the end of this page:
http://docs.textadventures.co.uk/quest/problems.html

I am not sure quite what you want to do, but Eval may be the way forward.
http://docs.textadventures.co.uk/quest/functions/eval.html


Hello.

I've been poking about Quest's core files to try and learn how they work and been wondering where GetObject() is.

GetObject is not in a Quest library. It is a C# thing:

https://github.com/textadventures/quest/blob/28b466b83125efdaf9bcdec1013b81e207cbfe09/WorldModel/WorldModel/Fields.cs#L731


So I had another off the wall idea about combat menus that then call scripts based off the result. But the regular script function doesn't do it, but then I saw the invoking one and tried it but got the above Error.

then I saw the invoking one and tried it but got the above Error

Do you have any code to post, so we can see how we might help?

I'm assuming you're talking about using invoke.

https://docs.textadventures.co.uk/quest/scripts/invoke.html


If the script is an object attribute, I prefer using do, which is mostly the same, except the script being invoked can use this if the script is an object's attribute (this also applies to verbs).

https://docs.textadventures.co.uk/quest/scripts/do.html


Since you are dealing with combat menus, I assume you are attempting to invoke scripts which are an object's script attributes (or verbs), but I'm not certain.

This may or may not help (click "Details" to view example game):

<!--Saved by Quest 5.8.7753.35184-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="do the object's script attribute">
    <gameid>d0c51440-955c-479e-8fdb-e63b64422353</gameid>
    <version>1.0</version>
    <firstpublished>2021</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
    </object>
    <object name="frob">
      <inherit name="editor_object" />
      <test1 type="script">
        msg ("This is frob.test1.")
      </test1>
      <test2 type="script">
        msg ("This is frob.test2.")
      </test2>
      <look type="script">
        choices = NewStringList()
        list add (choices, "test1")
        list add (choices, "test2")
        game.tempObj = this
        ShowMenu ("Pick one.", choices, false) {
          result = LCase(Trim(result))
          do (game.tempObj, result)
          game.tempObj = null
        }
      </look>
    </object>
  </object>
</asl>

EDIT

Pixie posted while I was writing. Pixie knows more about Quest than I could ever learn. Heed the Pixie's advice.


Close, but no, I do have that somewhere else in the system, but I was wanting to just let players get a string list of actions they can take in combat, aka, skills and stuff, which are displayed in a menu easily. Then I wanted to take the result and just turn it to a function rather then have an if else train.

I also knew this was going to be a sideways thing and made a new game to test around with this idea.

<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Syntaxing">
    <gameid>1caf0f1c-ceee-49d4-b6d1-236bacb0a368</gameid>
    <version>1.0</version>
    <firstpublished>2021</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <description type="script">
      msg ("You are in " + this.name + ".")
    </description>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <look type="script">
        msg ("you are " + this.name + ".")
        this = GetScript (result)
      </look>
    </object>
    <object name="stick">
      <inherit name="editor_object" />
      <CombatActions type="stringlist">
        <value>Attack</value>
        <value>Defend</value>
        <value>Flee</value>
      </CombatActions>
      <look type="script">
        options = NewStringList()
        foreach (action, this.CombatActions) {
          list add (options, action)
        }
        ShowMenu ("do what", options, true) {
          invoke (result)
        }
      </look>
    </object>
  </object>
  <command name="Explore">
    <pattern>Look, seek, explore, check</pattern>
    <script>
      msg ("You look around")
    </script>
  </command>
  <verb />
  <type name="ggg" />
  <function name="Attack">
    msg ("You attacked")
  </function>
  <function name="Defend">
    msg ("you defended")
  </function>
  <function name="Flee">
    msg ("you ran away")
  </function>
</asl>

Close, but no?

I was very close, considering I hadn't seen your code.

... especially considering I just modified your code using my method to make stuff actually work. :)

Also, I didn't use any if statements, nor did I advise that anyone use any if statements (yet).

Try this modified version of the example you just posted:

<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Syntaxing">
    <gameid>1caf0f1c-ceee-49d4-b6d1-236bacb0a368</gameid>
    <version>1.0</version>
    <firstpublished>2021</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <description type="script">
      msg ("You are in " + this.name + ".")
    </description>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <look type="script">
        msg ("you are " + this.name + ".")
        this = GetScript (result)
      </look>
    </object>
    <object name="stick">
      <inherit name="editor_object" />
      <Attack type="script">Attack</Attack>
      <Defend type="script">Defend</Defend>
      <Flee type="script">Flee</Flee>
      <CombatActions type="stringlist">
        <value>Attack</value>
        <value>Defend</value>
        <value>Flee</value>
      </CombatActions>
      <look type="script">
        options = NewStringList()
        game.tempObject = this
        foreach (action, this.CombatActions) {
          list add (options, action)
        }
        ShowMenu ("do what", options, true) {

          do (game.tempObject, result)
          game.tempObject = null
        }
      </look>
    </object>
  </object>
  <command name="Explore">
    <pattern>Look, seek, explore, check</pattern>
    <script>
      msg ("You look around")
    </script>
  </command>
  <verb />
  <type name="ggg" />
  <function name="Attack">
    msg ("You attacked")
  </function>
  <function name="Defend">
    msg ("you defended")
  </function>
  <function name="Flee">
    msg ("you ran away")
  </function>
</asl>

You could also do it without the standalone functions, like this:

<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Syntaxing">
    <gameid>1caf0f1c-ceee-49d4-b6d1-236bacb0a368</gameid>
    <version>1.0</version>
    <firstpublished>2021</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <description type="script">
      msg ("You are in " + this.name + ".")
    </description>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <look type="script">
        msg ("you are " + this.name + ".")
        this = GetScript (result)
      </look>
    </object>
    <object name="stick">
      <inherit name="editor_object" />
      <Attack type="script">
        msg ("You attacked")
      </Attack>
      <Defend type="script">
        msg ("you defended")
      </Defend>
      <Flee type="script">
        msg ("you ran away")
      </Flee>
      <CombatActions type="stringlist">
        <value>Attack</value>
        <value>Defend</value>
        <value>Flee</value>
      </CombatActions>
      <look type="script">
        options = NewStringList()
        game.tempObject = this
        foreach (action, this.CombatActions) {
          list add (options, action)
        }
        ShowMenu ("do what", options, true) {

          do (game.tempObject, result)
          game.tempObject = null
        }
      </look>
    </object>
  </object>
  <command name="Explore">
    <pattern>Look, seek, explore, check</pattern>
    <script>
      msg ("You look around")
    </script>
  </command>
  <verb />
  <type name="ggg" />
</asl>

You could also do it several other ways.


I wanted to take the result and just turn it to a function rather then have an if else train.

You can't directly refer to a function in this way, because a Quest variable can't hold a function (and there is no way to get any kind of reference to a function into a variable).

You can do it with scripts, but not functions. Two common ways to do something like this would be…

1. Using an object
If you have an object, you can use do or invoke to activate its script attributes.
From the error message in the topic, I guess that you're passing a string to invoke.

You would need to make the actual script a script attribute of some object, and then either use the result selected by the player to choose the object, or the attribute. For example:

<object name="CombatActions">
  <attack type="script">
    msg ("You attacked")
  </attack>
  <defend type="script">
    msg ("you defended")
  </defend>
  <flee type="script">
    msg ("you ran away")
  </flee>
</object>

and then your script would look like:

  options = NewStringList()
  foreach (action, this.CombatActions) {
    if (HasScript (CombatActions, action)) {
      list add (options, LCase (action))
    }
  }
  ShowMenu ("do what", options, true) {
    do (CombatActions, result)
  }

2. Using a scriptdictionary
You can also create a scriptdictionary; which is a dictionary whose elements are scripts. You can then use ScriptDictionaryItem to extract the script that matches your string.

Or there is a third option:
3. Using eval
eval treats a string as a Quest expression, so it will kind of work.

This is the only method that works with functions rather than scripts – but I think one of the oddities of Quest is that void functions aren't valid in expressions. In other words, you need to give all of your functions a type, and make them return something, even if you don't want to use the return value.

So you could do something like:

ShowMenu ("Do what?", options, true) {
  somevariable = eval (result + "()")
}

PS

Your Explore command's pattern is all messed up, unless you want the player to have to actually enter this:

> look, seek, explore, check
You look around


I would change the pattern to seek;explore;check.

I excluded the word "look", because that would override the default look command, which would make most adventurers immediately dislike the game.

Anyway, if you change the pattern to seek;explore;check, it works like this:

> seek
You look around

> explore
You look around

> check
You look around

> look
You are in a room.
You can see a stick.
You are in room.


https://docs.textadventures.co.uk/quest/tutorial/custom_commands.html#alternative-command-patterns


PPS

I see mrangel was writing a post at the same time I was writing mine.

I always defer to mrangel, and everyone else should do the same.

:o)


mrangle has helped me several times already with my inquiries.

And eval seems to be what I want, but I have no idea what I'm doing and I'm getting the same error in int32 verson and a new one Error running script: Error evaluating expression 'eval (result + "()")': Error evaluating expression 'Attack()': Value type of 'QuestList`1' is not assignable to required type of 'QuestList`1' Which is a bunch of words, yes.

<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Syntaxing">
    <gameid>1caf0f1c-ceee-49d4-b6d1-236bacb0a368</gameid>
    <version>1.0</version>
    <firstpublished>2021</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <description type="script">
      msg ("You are in " + this.name + ".")
    </description>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <look type="script">
        msg ("you are " + this.name + ".")
        this = GetScript (result)
      </look>
    </object>
    <object name="stick">
      <inherit name="editor_object" />
      <CombatActions type="stringlist">
        <value>Attack</value>
        <value>Defend</value>
        <value>Flee</value>
      </CombatActions>
      <look type="script">
        options = NewStringList()
        foreach (action, this.CombatActions) {
          list add (options, action)
        }
        ShowMenu ("do what", options, true) {
          dothis = eval (result + "()") //this is eval thing
          invoke (dothis, work)
        }
      </look>
    </object>
  </object>
  <command name="Explore">
    <pattern>Look, seek, explore, check</pattern>
    <script>
      msg ("You look around")
    </script>
  </command>
  <verb />
  <type name="ggg" />
  <function name="Attack" type="list"> //changing this thing's type makes new errors...
    msg ("You attacked")
    work = NewStringList()
    return (work)
  </function>
  <function name="Defend">
    msg ("you defended")
  </function>
  <function name="Flee">
    msg ("you ran away")
  </function>
</asl>

Your Attack function's type is "list" when it should be "stringlist".

You didn't have Defend and Flee coded the same way as Attack, either, but I'm guessing this is because you were just testing Attack to get it working first.

Also, you don't need the invoke (dothis, work) line of code at all.

I made those changes, and it works for me.

Example:

<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Syntaxing">
    <gameid>1caf0f1c-ceee-49d4-b6d1-236bacb0a368</gameid>
    <version>1.0</version>
    <firstpublished>2021</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <description type="script">
      msg ("You are in " + this.name + ".")
    </description>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <look type="script">
        msg ("you are " + this.name + ".")
        this = GetScript (result)
      </look>
    </object>
    <object name="stick">
      <inherit name="editor_object" />
      <CombatActions type="stringlist">
        <value>Attack</value>
        <value>Defend</value>
        <value>Flee</value>
      </CombatActions>
      <look type="script">
        options = NewStringList()
        foreach (action, this.CombatActions) {
          list add (options, action)
        }
        ShowMenu ("do what", options, true) {
          dothis = eval (result + "()") //this is eval thing
        }
      </look>
    </object>
  </object>
  <command name="Explore">
    <pattern>Look, seek, explore, check</pattern>
    <script>
      msg ("You look around")
    </script>
  </command>
  <verb />
  <type name="ggg" />
  <function name="Attack" type="stringlist"> //changing this thing's type makes new errors...
    msg ("You attacked")
    work = NewStringList()
    return (work)
  </function>
  <function name="Defend" type="stringlist">
    msg ("you defended")
    work = NewStringList()
    return (work)
  </function>
  <function name="Flee" type="stringlist">
    msg ("you ran away")
    work = NewStringList()
    return (work)
  </function>
</asl>

PS

If you change it like the following example, your functions will know which object they are dealing with.

<!--Saved by Quest 5.8.6836.13983-->
<asl version="580">
  <include ref="English.aslx" />
  <include ref="Core.aslx" />
  <game name="Syntaxing">
    <gameid>1caf0f1c-ceee-49d4-b6d1-236bacb0a368</gameid>
    <version>1.1</version>
    <firstpublished>2021</firstpublished>
  </game>
  <object name="room">
    <inherit name="editor_room" />
    <isroom />
    <description type="script">
      msg ("You are in " + this.name + ".")
    </description>
    <object name="player">
      <inherit name="editor_object" />
      <inherit name="editor_player" />
      <look type="script">
        msg ("you are " + this.name + ".")
        this = GetScript (result)
      </look>
    </object>
    <object name="stick">
      <inherit name="editor_object" />
      <CombatActions type="stringlist">
        <value>Attack</value>
        <value>Defend</value>
        <value>Flee</value>
      </CombatActions>
      <look type="script">
        options = NewStringList()
        foreach (action, this.CombatActions) {
          list add (options, action)
        }
        game.tempObj = this.name
        ShowMenu ("do what", options, true) {
          dothis = eval (result + "("+ game.tempObj + ")") //this is eval thing
          game.tempObj = null
        }
      </look>
    </object>
  </object>
  <command name="Explore">
    <pattern>Look, seek, explore, check</pattern>
    <script>
      msg ("You look around")
    </script>
  </command>
  <verb />
  <type name="ggg" />
  <function name="Attack" parameters="obj" type="stringlist"> //changing this thing's type makes new errors...
    msg ("You attacked " + GetDefiniteName(obj) + ".")
    work = NewStringList()
    return (work)
  </function>
  <function name="Defend" parameters="obj" type="stringlist">
    msg ("You defended yourself from " + GetDefiniteName(obj) + ".")
    work = NewStringList()
    return (work)
  </function>
  <function name="Flee" parameters="obj" type="stringlist">
    msg ("You ran away from " + GetDefiniteName(obj) + ".")
    work = NewStringList()
    return (work)
  </function>
</asl>

KV beat me to it :)

Though I have no idea why stringlist and list aren't assignable. As far as I remember, a stringlist is internally a QuestList<String>, in which case testing if it's a QuestList should work.

(when doing stuff like this, I normally make the type boolean; so I can just do return (true) without needing to create a temporary variable)


Log in to post a reply.

Support

Forums