Place1TBS mandatory braces.
[open-adventure.git] / score.c
1 /*
2  * Scoring and wrap-up.
3  *
4  * SPDX-FileCopyrightText: (C) 1977, 2005 by Will Crowther and Don Woods
5  * SPDX-License-Identifier: BSD-2-Clause
6  */
7 #include <stdlib.h>
8 #include "advent.h"
9 #include "dungeon.h"
10
11 static int mxscor;      /* ugh..the price for having score() not exit. */
12
13 int score(enum termination mode) {
14 /* mode is 'scoregame' if scoring, 'quitgame' if quitting, 'endgame' if died
15  * or won */
16     int 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         }
44         if (objects[i].inventory != 0) {
45             int k = 12;
46             if (i == CHEST) {
47                 k = 14;
48             }
49             if (i > CHEST) {
50                 k = 16;
51             }
52             if (!PROP_IS_STASHED(i) && !PROP_IS_NOTFOUND(i)) {
53                 score += 2;
54             }
55             if (game.objects[i].place == LOC_BUILDING && PROP_IS_FOUND(i)) {
56                 score += k - 2;
57             }
58             mxscor += k;
59         }
60     }
61
62     /*  Now look at how he finished and how far he got.  NDEATHS and
63      *  game.numdie tell us how well he survived.  game.dflag will tell us
64      *  if he ever got suitably deep into the cave.  game.closng still
65      *  indicates whether he reached the endgame.  And if he got as far as
66      *  "cave closed" (indicated by "game.closed"), then bonus is zero for
67      *  mundane exits or 133, 134, 135 if he blew it (so to speak). */
68     score += (NDEATHS - game.numdie) * 10;
69     mxscor += NDEATHS * 10;
70     if (mode == endgame) {
71         score += 4;
72     }
73     mxscor += 4;
74     if (game.dflag != 0) {
75         score += 25;
76     }
77     mxscor += 25;
78     if (game.closng) {
79         score += 25;
80     }
81     mxscor += 25;
82     if (game.closed) {
83         if (game.bonus == none) {
84               score += 10;
85         }
86         if (game.bonus == splatter) {
87               score += 25;
88         }
89         if (game.bonus == defeat) {
90               score += 30;
91         }
92         if (game.bonus == victory) {
93               score += 45;
94         }
95     }
96     mxscor += 45;
97
98     /* Did he come to Witt's End as he should? */
99     if (game.objects[MAGAZINE].place == LOC_WITTSEND) {
100         score += 1;
101     }
102     mxscor += 1;
103
104     /* Round it off. */
105     score += 2;
106     mxscor += 2;
107
108     /* Deduct for hints/turns/saves. Hints < 4 are special; see database desc. */
109     for (int i = 0; i < NHINTS; i++) {
110         if (game.hints[i].used) {
111               score = score - hints[i].penalty;
112         }
113     }
114     if (game.novice) {
115         score -= 5;
116     }
117     if (game.clshnt) {
118         score -= 10;
119     }
120     score = score - game.trnluz - game.saved;
121
122     /* Return to score command if that's where we came from. */
123     if (mode == scoregame) {
124         rspeak(GARNERED_POINTS, score, mxscor, game.turns, game.turns);
125     }
126
127     return score;
128 }
129
130 void terminate(enum termination mode) {
131 /* End of game.  Let's tell him all about it. */
132     int points = score(mode);
133 #if defined ADVENT_AUTOSAVE
134     autosave();
135 #endif
136
137     if (points + game.trnluz + 1 >= mxscor && game.trnluz != 0) {
138         rspeak(TOOK_LONG);
139     }
140     if (points + game.saved + 1 >= mxscor && game.saved != 0) {
141         rspeak(WITHOUT_SUSPENDS);
142     }
143     rspeak(TOTAL_SCORE, points, mxscor, game.turns, game.turns);
144     for (int i = 1; i <= (int)NCLASSES; i++) {
145         if (classes[i].threshold >= points) {
146             speak(classes[i].message);
147             if (i < (int)NCLASSES) {
148                 int nxt = classes[i].threshold + 1 - points;
149                 rspeak(NEXT_HIGHER, nxt, nxt);
150             } else {
151                 rspeak(NO_HIGHER);
152             }
153             exit(EXIT_SUCCESS);
154         }
155     }
156     rspeak(OFF_SCALE);
157     exit(EXIT_SUCCESS);
158 }
159
160 /* end */