// disambig.t version 0.11
// Automatic scoring-based disambiguation for TADS 2.4 and up
// Dan Schmidt <dfan@alum.mit.edu>
// improvements by 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! 
// 
// 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
    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) {
            // 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
;
