/*
   disambig.t version 1.00 (6 May 2001)
   Automatic scoring-based disambiguation for TADS 2.4 and up
   Dan Schmidt <dfan@dfan.org>
   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
;
