Inform: No Score

Say you want to write a game with no "score" command. (I might have done this, once or twice.) It's a bit trickier than you think.

Wrong Technique 1

The "scored X out of a possible Y" message, like all library messages, can be overridden with a LibraryMessages object. So you try it:

  
! Wrong !
Object LibraryMessages "lib_messages"
  with
    before [;
      Score: 
        print "There is no score in this game";
        rtrue;
    ];

And this almost works...

   >score
There is no score in this game.

>lose
You drink fuming nitric acid.

   *** You have died ***

There is no score in this game.

The "score" command produces the proper message. But when you die, the library calls ScoreSub() to print your final score, and the messages appears again. In fact...

   >win
You find the Crown Jewels.

   *** You have won ***

There is no score in this game.

This is almost anticlimactic, and not what you want. (If it is, stop reading; you're done.)

Wrong Technique 2

So, obviously, you have to add a test to not print anything if the game is over. You know when the game is over because deadflag is nonzero:

  
! Wrong !
Object LibraryMessages "lib_messages"
  with
    before [;
      Score: 
        if (deadflag == 0)
          print "There is no score in this game";
        rtrue;
    ];

And this would be perfect...

   >score
There is no score in this game.

>lose
You drink fuming nitric acid.

   *** You have died ***

.

...except for that lone period at the end.

What's going on? Well, the way the library is set up, the default Score library message doesn't end with a period. (And therefore, when you override it, you shouldn't print a period either. Note that the above code doesn't.)

The period (and following linebreak) is actually printed by the PrintRank() routine, which is always called right after the Score library message. PrintRank() is what you provide to print "giving you the rank of Doofus", or whatever nonsense is appropriate. If you don't define one, the default PrintRank() just prints the period.

(What? You can't find the default PrintRank() routine in the library? That's because it's at the bottom of Grammar.h. Don't ask me.)

Solution

So you have to provide a blank PrintRank(). And, of course, put the period into the Score message. And a newline too.

  
Object LibraryMessages "lib_messages"
  with
    before [;
      Score: 
        if (deadflag == 0)
          print "There is no score in this game.^";
        rtrue;
    ];

[ PrintRank;
];

   >score
There is no score in this game.

>win
You find the Crown Jewels.

   *** You have won ***

Easier Solution

But actually, both the Score library message and PrintRank() routine are called from ScoreSub(). So a simpler tack is to replace that.

  
Replace ScoreSub;

[ ScoreSub;
  if (deadflag == 0)
    "There is no score in this game.";
];

(As usual for Replaced library routines, you should put the Replace statement before the "Parser" and "Verblib" library files are included, and the new ScoreSub() definition afterward.)

Prevention

After you squash the score message, test both the "score" and "full score" commands. And then test dying and winning, and make sure there's no score message there either. Watch out for the lone period.


More Inform Tricks