Scoring
The score.t implements a scoring system that is identical to that in the adv3 library (and uses exactly the same code). If your game doesn't use scoring, exclude the score.t module from your build.
The quick and dirty way to keep score is to use the addToScore(points, desc) function to add points to the player's total score along with a description of what you're awarding points for. A cleaner and more secure way (secure, for example, in that it makes it easier to ensure you don't keep awarding point for the same deed) is to use Achievement objects.
An Achievement is an object used to award points in the score. For most purposes, an achievement can be described simply by a string, but the Achievement object provides more flexibility in describing combined scores when a set of similar achievements are to be grouped.
There are two ways to use the scoring system.
- You can use a mix of string names and Achievement objects for scoring items; each time you award a scoring item, you call the function addToScore(points, desc) to specify the achievement (by name or by Achievement object) and the number of points to award. You can also call the method addToScoreOnce() on an Achievement object to award the scoring item, ensuring that the item is only awarded once in the entire game (saving you the trouble of checking to see if the event that triggered the scoring item has happened before already in the same game). If you do this, you MUST set the property gameMain.maxScore to reflect the maximum score possible in the game.
- You can use EXCLUSIVELY Achievement objects to represents scoring items, and give each Achievement object a 'points' property indicating the number of points it's worth. To award a scoring item, you call the method awardPoints() on an Achievement object. If you use this style of scoring, the library AUTOMATICALLY computes the gameMain.maxScore value, by adding up the 'points' values of all of the Achievement objects in the game. For this to work properly, you have to obey the following rules:
- use ONLY Achievement objects (never strings) to award points;
- set the 'points' property of each Achievement to its score;
- define Achievement objects statically only (never use 'new' to create an Achievement dynamically)
- if an Achievement can be awarded more than once, you must override its 'maxPoints' property to reflect the total number of points it will be worth when it is awarded the maximum number of times;
- always award an Achievement through its awardPoints() or awardPointsOnce() method;
- there exists at least one solution of the game in which every Achievement object is awarded
If there is more than one route through your game, it may be a bit tricky using the second of these approaches. One possible workaround is to use method 2 for the main route through your game (which you count as the 'main' route may, of course, be an arbitrary choice: you could choose the longest route, the shortest route, the most interesting route or anything else that makes sense to you). Then use Achievement objects for the other routes but call their addToScoreOnce(points) method instead of awardPoints() or awardPointsOnce() if they're not on the main route; and don't define their points property. That way the points from these additional off-the-main-route Achievements won't be included the calculation of the maximum available points.
Score Rank Table
Although it is less common with modern games, some games display a textual ranking (e.g. "This makes you a Master Adventurer") along with the numberical score. You can do this in your own game by defining a scoreRankTable on your gameMain object, for example:
gameMain: GameMainDef
/* Define the initial player character; this is compulsory */
initialPlayerChar = me
showIntro()
{
"Welcome to Extraodinary Adventure! In this game you collect as
many elves as possible and deposit them at the north pole
in time for Christmas!";
}
scoreRankTable = [
[0, 'a rank amateur'],
[50, 'a Novice Class adventurer'],
[100, 'a moderately competent trainee'],
[150, 'a seasoned trainee'],
[200, 'an experienced adventurer'],
[270, 'a valiant explorer'],
[275, 'a fully qualified adventurer']
]
;
The scoreRankTable provides a list of names for various score levels. If the game provides a non-nil list here, the SCORE and FULL SCORE commands will show the rank along with the score ("This makes you a Master Adventurer").
This table is a list of score entries. Each score entry is itself a list of two elements: the first element is the minimum score for the rank, and the second is a string describing the rank. The ranks should be given in ascending order, since we simply search the list for the first item whose minimum score is greater than our score, and use the preceding item. The first entry in the list would normally have a minimum of zero points, since it should give the initial, lowest rank.
If this is set to nil, which it is by default, we'll simply skip score ranks entirely.
modify libScore
showScoreRankMessage(msg)
{
"You may accordingly now consider yourself <<msg>>. ";
}
;
Or this:
CustomMessages
messages =
[
Msg(show score rank, 'You may accordingly now consider yourself {1} ')
]
;
