/*
  disambig.t version 1.00 (6 May 2001)
  Automatic scoring-based disambiguation for TADS 2.4 and up
  Dan Schmidt <[email protected]>
  with guest star Stephen Granade

Before you go any further: you need TADS 2.4 or later to use this code!

disambig.t allows you to use a scoring system to do automatic disambiguation
of objects.  Perhaps your game currently acts like this:

 You see a red apple and a green apple here.

 >GET RED APPLE
 Taken.

 >EAT APPLE
 Which apple do you mean, the red apple, or the green apple?

That's kind of silly; you'd like to have EAT prefer the objects that
you're holding.  disambig.t makes it easy to do object scoring, so
that EAT can give high scores to objects in your inventory and low
scores to objects outside of it.

Here's how you would do that:

 modify eatVerb
     disambigDobjScore (obj) = { return obj.isIn (Me) ? 10 : 0; }
 ;

This gives items in your inventory a score of 10, and other items
a score of 0.  TADS will now automatically pick the object with the
highest score (and then ask the player to choose, if it still has to).

Here's the new transcript:

 You see a red apple and a green apple here.

 >GET RED APPLE
 Taken.

 >EAT APPLE
 (the red apple)
 That was delicious!

(The extra message '(the red apple)' will appear if and only if the verb
has a verbose_disambiguation property of true.)

There are two ways you can modify scores.

1) the disambigDobjScore(obj) method in a verb.  See the example above.
  This is called once for each object that the player might be
  referring to.  (There's also a disambigIobjScore method, for
  disambiguating indirect objects.) The default implementation
  of disambigDobjScore simply looks at the object's own default
  score, which you can change by modifying:

2) Any object or class's baseDisambigScore property.  Objects have
  a baseDisambigScore of 100 by default.  Here's how to automatically
  make fixeditems be ignored in favor of other items:

  modify fixeditem
      baseDisambigScore = 50

Note that if you write your own verb disambigDobjScore method, it will not
pay attention to the objects' baseDisambigScore properties unless you
make it do so.

CAVEATS:

- disambig.t takes over the disambigDobj and disambigIobj properties
  of deepverb.  If you need to mess with those properties, you'll
  have to hack this file so it doesn't step on your code's toes.

- disambig.t ignores some of the more sophisticated information that's
  passed to it.  It's possible that it could provide inappropriate
  results under weird circumstances.  Let me know if it does.
*/

#pragma C+

#define MINSCORE -999

modify deepverb
 verbose_disambiguation = nil

 disambigGen (objlist, prop) = {
   local i;                   // index
   local score;               // score of current object
   local maxscore = MINSCORE; // best score yet
   local disambiglist = [];   // objects we still need to choose between

   // Find the maxscore and remember some stuff
   for (i = 1; i <= length(objlist); ++i) {
     score = self.(prop) (objlist[i]);
     if (score > maxscore) {
       maxscore = score;
       disambiglist = [ (objlist[i]) ];
     } else if (score == maxscore)
         disambiglist += objlist[i];
   }

   if (length(disambiglist) == 1 && self.verbose_disambiguation) {
     // Print out what we chose
     "(<<disambiglist[1].thedesc >>)\n";
   }

   return disambiglist;
 }

 disambigDobj (actor, prep, iobj, verprop, wordlist, objlist,
               flaglist, numberWanted, isAmbiguous, silent) = {
   if (!isAmbiguous) return DISAMBIG_CONTINUE;
   return self.disambigGen (objlist, &disambigDobjScore);
 }

 disambigIobj (actor, prep, dobj, verprop, wordlist, objlist,
               flaglist, numberWanted, isAmbiguous, silent) = {
   if (!isAmbiguous) return DISAMBIG_CONTINUE;
   return self.disambigGen (objlist, &disambigIobjScore);
 }

 disambigDobjScore (obj) = {
   return obj.baseDisambigScore;
 }

 disambigIobjScore (obj) = {
   return obj.baseDisambigScore;
 }
;

modify thing
 baseDisambigScore = 100
;