Selection menus

MaDbRiT
12 Jun 2009, 14:51
Hi

While considering the possibilities for a conversation system, I was reminded of a limitation I'd noticed in the past but (AFAIK) have never got around to requesting a fix for.

Selection menus have to be 'hard coded'. As authors we cannot embed variables in, or dynamically change the 'choice' messages, nor can we change/replace the scripts associated with them.

I can't imagine it would be too hard to allow us to use variables as info & choice options, that would make them much more useful, especially if the script could read the variable choice associated with it. We could then use the information for our own purposes.

define selection <selectionname>
info <#variable# | Text>
choice < #variable# |Text> (script)
.
end define


The script could then do whatever we required using a select case on the variable - so we'd have dynamically variable menus. I can see this being very useful for those who like the conversation tree approach to NPC interaction. By setting a choice variable to an empty string, it could be not diplayed so menu's could shrink if needed.

Better still if we could replace the choice text of a selection menu, and it's script by referring to it by an index number. So having coded

define selection <Fred_Talk>
info <Talking to Fred...>
choice < What do you know about Porsches?> msg <"Naff all mate.!">
choice <etc>... .
end define


Perhaps we could then amend the menu with something like;

Fred_Talk.info = "Talking to Boris..."
Fred_Talk.choice[1] = "Ask him about his tap dancing skills.>"
Fred_Talk.script[1] = do <run_before_he_beats_you_to_a_pulp_procedure>


I can see how it might have to only allow a procedure call or a simple message as 'script' here. I also see that this could be a LOT more work to implement than the former method.

Any comments?

Al (MaDbRiT)

paul_one
12 Jun 2009, 20:31
I think this is one of the first limitations that I noticed after finding Quest.
Completely agree.

Not sure about the solution though, and I can't quite get my mind round to this.. Maybe later..

MaDbRiT
12 Jun 2009, 21:48
paul_one wrote:Not sure about the solution though, and I can't quite get my mind round to this


Not sure of the best way to fix it either, just floated a couple of ideas :-) I daresay that the way Alex has implemented the selections will pretty much dictate the solution - assuming we get one!

Cheers

Al (MaDbRiT)

paul_one
13 Jun 2009, 10:49
Ok, just re-read your post and am a bit more tech-minded today.
Good to have you back BTW Al :) .

Riiight, the main downside with your approach would be a limit to the changes in the menu structure... For instance:
define menu <menu>
info <What do you say?>
choice <#one#> stuff..
choice <#two#> stuff..
choice <#three#> stuff..
end define


Of course you can change the menu contents (and possibly the "stuff" part too).. But what happens if you want to add 6 or 10 or 'x' number of choices?

With a text-based menu all you'd do is have an index variable, output the choices to one or two arrays and then when reading the input, match the index with the 'script' part of the array/s. (which I have *just* realized you do say anyway)
I see the tough part here being loads of variables etc. Plus removing stuff from the array isn't all that easy.

I think adding / removing actions would be far more suitable.
Having the menu as more of an (I daresay it) object!
This might allow you to do something similar to actions:
define object <menu>
description <what do you want to say?>
action <Oh no - not again!> stuff..
action <*pokie* *pokie* *pokie*> stuff..
end define


I was also thinking about somehow scripting a menu - but that would just be silly.
I'm thinking a proper data structure which you can change would be MUCH better.

Thoughts?

Overcat
13 Jun 2009, 13:17
[edited June 13th 12:31 pm eastern Canadian time]

I've always been a GUI minimalist with Quest. Don't like the panes, nor any kind of popup. Would love disambiguation control. But, as you (Al) said you are choosing Quest over other IF authoring options specifically because of the GUI, I could see where the functionality you've described would make a huge difference.

As an alternative, (and I see Paul is thinking exactly along the same lines) I think you may be able to structure your own dynamic conversation nodes (that work similarly to how you've described selection menus working) using objects. These wouldn't have a GUI popup, but you could control color, formatting, and all the rest.

I am thinking of something like the following:

!library
!asl-version <400>

define type <ConversationNode>

info = UNDEFINED
choice_1 = NULL

lastChoice = NULL

'hook for gatekeeping OnChoosing, may be overwritten
action <BeforeChoosing> {

doaction <$thisobject$; OnChoosing>
}

'internal functionality, should not be overwritten
action <OnChoosing> {

set string <this; $thisobject$>
msg <#(this):info#>
msg <>

set numeric <i; 1>
set string <strChoice; $objectproperty(#this#; choice_%i%)$>
repeat until (#strChoice# = NULL) or (#strChoice# = !) {

msg < %i%. #strChoice#>
inc <i>
if property <#this#; choice_%i%> then {

set <strChoice; $objectproperty(#this#; choice_%i%)$>
}
else {
set <strChoice; NULL>
}
}

msg <>
dec <i>

set string <playerChoice; >
set numeric <n; 0>
repeat until (%n% >= 1) and (%n% <= %i%) {

enter <playerChoice>
set <n; #playerChoice#>

'if (%n% < 1) or (%n% > %i%) then msg < Invalid choice. Choose again.>
}

property <#this#; lastChoice = %n%>

if action <#this#; choice_%n%> then {

doaction <#this#; choice_%n%>
}
else {
if property <#this#; choiceMsg_%n%> then {

msg <$objectproperty(#this#; choiceMsg_%n%)$>
}
else {
debug <Conversation Node "#this#" has no message or state change for choice %n%, which is set to "$objectproperty(#this#; choice_%n%)$".>
}
}

doaction <#this#; AfterChoosing>
}

'hook for additional consequence logic for having made a choice,
'may be overwritten
action <AfterChoosing> {
}

'called when the node is first encountered, add property flag
'"node_initialized" to ensure this only fires once, may be
'overwritten
action <initialize_node> {
}

end define


Then the main file with an object:

!include <convNode.lib>

define options

debug on
panes disabled

end define

define game <ConversationNodeTypeTest>

asl-version <400>
foreground <white>
background <black>
default fontname <Courier>
default fontsize <12>

startscript {

for each object in game {

if action <#quest.thing#; initialize_node> then doaction <#quest.thing#; initialize_node>
}
}

start room <StartRoom>

command <do conv #cmd1#> {

if real <convNode_#cmd1#> then {

doaction <convNode_#cmd1#; BeforeChoosing>
}
else {

msg <No such conversation node exists.>
}
}

command <jump> {

msg <You jump.>
property <game; jumped>
}

end define

define room <StartRoom>

alias <Start>
look <A very boring location, indeed.>

define object <convNode_1>

type <ConversationNode>
properties <info = Which do |byou|xb like best:>
properties <choice_1 = |crred|cb; choice_2 = |clblue|cb; choice_3 = |cggreen|cb>

action <choice_1> {

set string <this; $thisobject$>
msg <You chose #(this):choice_1#.>
}

properties <choiceMsg_2 = You chose blue.>

action <BeforeChoosing> {

if not property <game; jumped> then {
msg <You must jump first.>
}
else {
doaction <$thisobject$; OnChoosing>
}
}

action <AfterChoosing> {

set string <this; $thisobject$>
msg <Your last choice was #(this):lastChoice#.>
}

action <initialize_node> {

property <game; not jumped>
debug <node $thisobject$ initialized>
}

end define
end define


As Paul mentioned, since you can add and remove properties/types at run-time, each conversation node can be dynamic to plot progression. To see how the above works, run the main file and type the command 'do conv 1'. It'll say 'You need to jump first.'. So do that, and then retype the command. For the third choice in the example menu I 'accidentally' forgot to code a reaction - a suitable debug message prints in this case.



Having the menu as more of an (I daresay it) object!



I knew you'd see the light! :lol:

paul_one
14 Jun 2009, 19:06
That all seems a bit TOO messy, plus you only have 1 selection there, where I would actually imagine a tree-structure.

I suppose you could combine several nodes to achieve that, but I would prefer to keep a whole tree in a single 'object' myself.