Removed advent.info and added to .gitignore
[open-adventure.git] / score.c
1 #include <stdlib.h>
2 #include "advent.h"
3 #include "database.h"
4 #include "newdb.h"
5
6 /*
7  * scoring and wrap-up
8  */
9
10 static long mxscor;     /* ugh..the price for having score() not exit. */
11
12 long score(enum termination mode)
13 /* mode is 'scoregame' if scoring, 'quitgame' if quitting, 'endgame' if died
14  * or won */
15 {
16     long score = 0;
17
18     /*  The present scoring algorithm is as follows:
19      *     Objective:          Points:        Present total possible:
20      *  Getting well into cave   25                    25
21      *  Each treasure < chest    12                    60
22      *  Treasure chest itself    14                    14
23      *  Each treasure > chest    16                   224
24      *  Surviving             (MAX-NUM)*10             30
25      *  Not quitting              4                     4
26      *  Reaching "game.closng"   25                    25
27      *  "Closed": Quit/Killed    10
28      *            Klutzed        25
29      *            Wrong way      30
30      *            Success        45                    45
31      *  Came to Witt's End        1                     1
32      *  Round out the total       2                     2
33      *                                       TOTAL:   430
34      *  Points can also be deducted for using hints or too many turns, or for
35      *  saving intermediate positions. */
36
37     /*  First tally up the treasures.  Must be in building and not broken.
38      *  Give the poor guy 2 points just for finding each treasure. */
39     mxscor = 0;
40     for (int i = 1; i <= NOBJECTS; i++) {
41         if (!objects[i].is_treasure)
42             continue;
43         if (objects[i].inventory != 0) {
44             long k = 12;
45             if (i == CHEST)k = 14;
46             if (i > CHEST)k = 16;
47             if (game.prop[i] >= 0)
48                 score += 2;
49             if (game.place[i] == LOC_BUILDING && game.prop[i] == 0)
50                 score += k - 2;
51             mxscor += k;
52         }
53     }
54
55     /*  Now look at how he finished and how far he got.  NDEATHS and
56      *  game.numdie tell us how well he survived.  game.dflag will tell us
57      *  if he ever got suitably deep into the cave.  game.closng still
58      *  indicates whether he reached the endgame.  And if he got as far as
59      *  "cave closed" (indicated by "game.closed"), then bonus is zero for
60      *  mundane exits or 133, 134, 135 if he blew it (so to speak). */
61     score += (NDEATHS - game.numdie) * 10;
62     mxscor += NDEATHS * 10;
63     if (mode == endgame)
64         score += 4;
65     mxscor += 4;
66     if (game.dflag != 0)score += 25;
67     mxscor += 25;
68     if (game.closng)score += 25;
69     mxscor += 25;
70     if (game.closed) {
71         if (game.bonus == 0)
72             score += 10;
73         if (game.bonus == SPLATTER_MESSAGE)
74             score += 25;
75         if (game.bonus == DEFEAT_MESSAGE)
76             score += 30;
77         if (game.bonus == VICTORY_MESSAGE)
78             score += 45;
79     }
80     mxscor += 45;
81
82     /* Did he come to Witt's End as he should? */
83     if (game.place[MAGAZINE] == LOC_WITTSEND)
84         score += 1;
85     mxscor += 1;
86
87     /* Round it off. */
88     score += 2;
89     mxscor += 2;
90
91     /* Deduct for hints/turns/saves. Hints < 4 are special; see database desc. */
92     for (long i = 0; i < NHINTS; i++) {
93         if (game.hinted[i])
94             score = score - hints[i].penalty;
95     }
96     if (game.novice)
97         score -= 5;
98     if (game.clshnt)
99         score -= 10;
100     score = score - game.trnluz - game.saved;
101
102     /* Return to score command if that's where we came from. */
103     if (mode == scoregame) {
104         rspeak(GARNERED_POINTS, score, mxscor, game.turns, game.turns);
105     }
106
107     return score;
108 }
109
110 void terminate(enum termination mode)
111 /* End of game.  Let's tell him all about it. */
112 {
113     long points = score(mode);
114
115     if (points + game.trnluz + 1 >= mxscor && game.trnluz != 0)
116         rspeak(TOOK_LONG);
117     if (points + game.saved + 1 >= mxscor && game.saved != 0)
118         rspeak(WITHOUT_SUSPENDS);
119     rspeak(TOTAL_SCORE, points, mxscor, game.turns, game.turns);
120     for (long i = 1; i <= (long)NCLASSES; i++) {
121         if (classes[i].threshold >= points) {
122             speak(classes[i].message);
123             i = classes[i].threshold + 1 - points;
124             rspeak(NEXT_HIGHER, i, i);
125             exit(0);
126         }
127     }
128     rspeak(OFF_SCALE);
129     rspeak(NO_HIGHER);
130     exit(0);
131 }
132
133 /* end */