Concerning the Disambiguator
K.V.
07 May 2021, 00:04> GET FROB
Which do you mean?
- the scenery frob
- the red herring frob
- the big blue frob
In Inform 7, we could put:
Does the player mean the big blue frob: it is very likely.
What if we used an optional attribute with a specific name which targets an object in Quest?
In ZIL, they used the generic
tag.
So, if we put a "generic" attribute on the scenery frob and the red herring frob, each targeting the big blue frob object, the disambiguation script could say, "hey! I have 3 candidates! 2 of them have generic
, and both of those target the 3rd candidate. That's it, then. Case closed. Going with with candidate 3!"
Thoughts? Suggestions?
mrangel
07 May 2021, 08:24I think I can see how that works. But it might be simpler just to put "frob" in the alt
attribute for the big blue one. That way it's a complete match and overrides partial ones.
K.V.
28 May 2021, 17:28it might be simpler just to put "frob" in the alt attribute for the big blue one. That way it's a complete match and overrides partial ones.
That would probably handle things most of the time, but I've got the game I was messing with set up so that the alt
attribute is the only thing checked to find the object from the player's input. All the frobs have "frob" in the alt
somewhere.
Also, I figured out that I can just set the generic
attribute on the target object, with generic
set to the object itself.
This is not the game I was messing with. It's just a working example game. This example does not require the alt
attributes, although I've added the "alternate" names anyway. (It's a habit.)
<!--Saved by Quest 5.8.7753.35184-->
<asl version="580">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="generic">
<gameid>fa0a429f-a214-4559-bcbc-b419e81c6c5b</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="old frob">
<inherit name="editor_object" />
<take type="boolean">false</take>
<takemsg>It's too old and fragile to move.</takemsg>
<alt type="stringlist">
<value>frob</value>
<value>old frob</value>
</alt>
</object>
<object name="tiny frob">
<inherit name="editor_object" />
<takemsg>It's too small to get hold of.</takemsg>
<alt type="stringlist">
<value>frob</value>
<value>tiny frob</value>
</alt>
</object>
<object name="blue frob">
<inherit name="editor_object" />
<take />
<generic type="object">blue frob</generic>
<alt type="stringlist">
<value>frob</value>
<value>blue frob</value>
</alt>
</object>
</object>
<function name="ResolveNameFromList" parameters="variable, value, objtype, scope, secondaryscope" type="object"><![CDATA[
value = Trim(LCase(value))
fullmatches = NewObjectList()
partialmatches = NewObjectList()
foreach (obj, scope) {
name = LCase(GetDisplayAlias(obj))
CompareNames (name, value, obj, fullmatches, partialmatches)
if (obj.alt <> null) {
foreach (altname, obj.alt) {
CompareNames (LCase(altname), value, obj, fullmatches, partialmatches)
}
}
}
// allow referring to objects from the previous command by gender or article
if (objtype = "object" and game.lastobjects <> null) {
foreach (obj, game.lastobjects) {
CompareNames (LCase(obj.article), value, obj, fullmatches, partialmatches)
CompareNames (LCase(obj.gender), value, obj, fullmatches, partialmatches)
}
}
// Also check the secondary scope, but only if we have not found anything yet
if (ListCount(fullmatches) = 0 and ListCount(partialmatches) = 0 and not secondaryscope = null) {
foreach (obj, secondaryscope) {
name = LCase(GetDisplayAlias(obj))
CompareNames (name, value, obj, fullmatches, partialmatches)
if (obj.alt <> null) {
foreach (altname, obj.alt) {
CompareNames (LCase(altname), value, obj, fullmatches, partialmatches)
}
}
}
}
if (ListCount(fullmatches) = 1) {
return (ListItem(fullmatches, 0))
}
else if (ListCount(fullmatches) = 0 and ListCount(partialmatches) = 1) {
return (ListItem(partialmatches, 0))
}
else if (ListCount(fullmatches) + ListCount(partialmatches) = 0) {
return (null)
}
else {
game.disambiguating = true
candidates = ListCompact(ListCombine(fullmatches, partialmatches))
generic = false
// msg(candidates)
foreach (o, candidates) {
if (HasAttribute(o,"generic")) {
if (ListContains(ScopeVisible(),o.generic)) {
generic = true
generic_object = o.generic
}
}
}
// Added this line to resolve issue with new FinishTurn setup in 580
// game.disambiguating = true
if (LengthOf(variable) > 0) {
// single object command, so after showing the menu, add the object to game.pov.currentcommandresolvedelements
if (generic) {
return (generic_object)
}
else {
game.disambiguating = true
game.pov.currentcommandpendingvariable = variable
ShowMenu (DynamicTemplate("DisambiguateMenu", value), candidates, true) {
varname = game.pov.currentcommandpendingvariable
game.pov.currentcommandpendingvariable = null
if (result <> null) {
AddToResolvedNames (varname, GetObject(result))
}
}
}
}
else {
// multi-object command, so after showing the menu, add the object to the list
game.pov.currentcommandmultiobjectpending = true
if (generic) {
list add (game.pov.currentcommandpendingobjectlist, generic_object)
ResolveNextNameListItem
}
else {
game.disambiguating = true
ShowMenu (DynamicTemplate("DisambiguateMenu", value), candidates, true) {
if (result <> null) {
list add (game.pov.currentcommandpendingobjectlist, GetObject(result))
ResolveNextNameListItem
}
}
}
}
return (null)
}
]]></function>
</asl>