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