Branch data Line data Source code
1 : : /* omega copyright (C) by Laurence Raphael Brothers, 1987,1988,1989 */
2 : : /* aux1.c */
3 : : /* auxiliary functions for those in com.c, also see aux2.c and aux3.c */
4 : :
5 : : #include "glob.h"
6 : :
7 : :
8 : :
9 : : /* check to see if too much tunneling has been done in this level */
10 : 0 : void tunnelcheck(void)
11 : : {
12 [ # # ][ # # ]: 0 : if ((Level->depth == 0 && Current_Environment != E_DLAIR) ||
[ # # ]
13 : 0 : Current_Environment == E_ASTRAL)
14 : 0 : return;
15 : 0 : Level->tunnelled++;
16 [ # # ]: 0 : if ((Level->tunnelled) > (Level->level_length)/4)
17 : 0 : mprint("Dust and stone fragments fall on you from overhead.");
18 [ # # ]: 0 : if ((Level->tunnelled) >(Level->level_length)/2)
19 : 0 : mprint("You hear groaning and creaking noises.");
20 [ # # ]: 0 : if ((Level->tunnelled) > (3*(Level->level_length))/4)
21 : 0 : mprint("The floor trembles and you hear a loud grinding screech.");
22 [ # # ]: 0 : if ((Level->tunnelled) > Level->level_length) {
23 : 0 : mprint("With a scream of tortured stone, the entire dungeon caves in!!!");
24 : 0 : gain_experience(5000);
25 [ # # ]: 0 : if (Player.status[SHADOWFORM]) {
26 : 0 : change_environment(E_COUNTRYSIDE);
27 [ # # # # : 0 : switch (Country[Player.x][Player.y].base_terrain_type)
# ]
28 : : {
29 : : case CASTLE:
30 : : case STARPEAK:
31 : : case CAVES:
32 : : case VOLCANO:
33 : 0 : Country[Player.x][Player.y].current_terrain_type = MOUNTAINS;
34 : 0 : break;
35 : : case DRAGONLAIR:
36 : 0 : Country[Player.x][Player.y].current_terrain_type = DESERT;
37 : 0 : break;
38 : : case MAGIC_ISLE:
39 : 0 : Country[Player.x][Player.y].current_terrain_type = CHAOS_SEA;
40 : 0 : break;
41 : : case PALACE:
42 : 0 : Country[Player.x][Player.y].current_terrain_type = JUNGLE;
43 : 0 : break;
44 : : }
45 : 0 : Country[Player.x][Player.y].base_terrain_type =
46 : 0 : Country[Player.x][Player.y].current_terrain_type;
47 : 0 : c_set(Player.x, Player.y, CHANGED);
48 : 0 : print1("In your shadowy state, you float back up to the surface.");
49 : 0 : return;
50 : : }
51 : 0 : mprint("You are flattened into an unpleasant jellylike substance.");
52 : 0 : p_death("dungeon cave-in");
53 : : }
54 : : }
55 : :
56 : : /* displays a room's name */
57 : 5 : void showroom(int i)
58 : : {
59 : 5 : strcpy(Str1,"");
60 : 5 : strcpy(Str2,"");
61 [ - - - + : 5 : switch(Current_Environment) {
- + - - -
- - - - ]
62 : : case E_MANSION:
63 : 0 : strcpy(Str2,"A luxurious mansion: ");
64 : 0 : break;
65 : : case E_HOUSE:
66 : 0 : strcpy(Str2,"A house: ");
67 : 0 : break;
68 : : case E_HOVEL:
69 : 0 : strcpy(Str2,"A hovel: ");
70 : 0 : break;
71 : : case E_CITY:
72 : 2 : strcpy(Str2,"The City of Rampart");
73 : 2 : break;
74 : : case E_VILLAGE:
75 [ # # # # : 0 : switch(Villagenum) {
# # # ]
76 : 0 : case 1: strcpy(Str2,"The Village of Star View"); break;
77 : 0 : case 2: strcpy(Str2,"The Village of Woodmere"); break;
78 : 0 : case 3: strcpy(Str2,"The Village of Stormwatch"); break;
79 : 0 : case 4: strcpy(Str2,"The Village of Thaumaris"); break;
80 : 0 : case 5: strcpy(Str2,"The Village of Skorch"); break;
81 : 0 : case 6: strcpy(Str2,"The Village of Whorfen"); break;
82 : : }
83 : 0 : break;
84 : : case E_CAVES:
85 : 3 : strcpy(Str2,"The Goblin Caves: ");
86 : 3 : break;
87 : : case E_CASTLE:
88 : 0 : strcpy(Str2,"The Archmage's Castle: ");
89 : 0 : break;
90 : : case E_ASTRAL:
91 : 0 : strcpy(Str2,"The Astral Plane: ");
92 : 0 : break;
93 : : case E_VOLCANO:
94 : 0 : strcpy(Str2,"The Volcano: ");
95 : 0 : break;
96 : : case E_PALACE:
97 : 0 : strcpy(Str2,"The Palace Dungeons: ");
98 : 0 : break;
99 : : case E_SEWERS:
100 : 0 : strcpy(Str2,"The Sewers: ");
101 : 0 : break;
102 : : case E_TACTICAL_MAP:
103 : 0 : strcpy(Str2,"The Tactical Map ");
104 : 0 : break;
105 : : default:
106 : 0 : strcpy(Str2,"");
107 : 0 : break;
108 : : }
109 [ + + ]: 5 : if (Current_Environment == Current_Dungeon) {
110 : 3 : strcpy(Str1,"Level ");
111 [ + - ]: 3 : if (Level->depth < 10) {
112 : 3 : Str1[6] = Level->depth + '0';
113 : 3 : Str1[7] = 0;
114 : : }
115 : : else {
116 : 0 : Str1[6] = (Level->depth / 10) + '0';
117 : 0 : Str1[7] = (Level->depth % 10) + '0';
118 : 0 : Str1[8] = 0;
119 : : }
120 : 3 : strcat(Str1," (");
121 : 3 : strcat(Str1,roomname(i));
122 : 3 : strcat(Str1,")");
123 : : }
124 [ + - ][ + - ]: 2 : else if (strlen(Str2) == 0 || Current_Environment == E_MANSION ||
[ + - ]
125 [ - + ]: 2 : Current_Environment == E_HOUSE || Current_Environment == E_HOVEL)
126 : 0 : strcpy(Str1,roomname(i));
127 : 5 : strcat(Str2,Str1);
128 : 5 : locprint(Str2);
129 : 5 : }
130 : :
131 : :
132 : 58 : int player_on_sanctuary(void)
133 : : {
134 [ - + ][ # # ]: 58 : if ((Player.x==Player.sx) &&
135 : 0 : (Player.y==Player.sy))
136 : 0 : return(TRUE);
137 : : else {
138 [ - + ]: 58 : if (Player.patron) {
139 [ # # ][ # # ]: 0 : if ((Level->site[Player.x][Player.y].locchar == ALTAR) &&
140 : 0 : (Level->site[Player.x][Player.y].aux == Player.patron))
141 : 0 : return(TRUE);
142 : 0 : else return(FALSE);
143 : : }
144 : 58 : else return(FALSE);
145 : : }
146 : : }
147 : :
148 : :
149 : : /* check a move attempt, maybe attack something, return TRUE if ok to move. */
150 : : /* x y is the proposed place to move to */
151 : 19 : int p_moveable(int x, int y)
152 : : {
153 : 19 : setgamestatus(SKIP_MONSTERS);
154 [ - + ]: 19 : if (! inbounds(x,y)) return (FALSE);
155 [ - + ]: 19 : else if (Player.status[SHADOWFORM]) {
156 [ # # ]: 0 : switch(Level->site[x][y].p_locf) {
157 : : case L_CHAOS: case L_ABYSS: case L_VOID:
158 : 0 : return cinema_confirm("That looks dangerous.") == 'y';
159 : : default:
160 : 0 : resetgamestatus(SKIP_MONSTERS);
161 : 0 : return(TRUE);
162 : : }
163 : : }
164 [ - + ]: 19 : else if (loc_statusp(x,y,SECRET)) {
165 [ # # ]: 0 : if (!gamestatusp(FAST_MOVE)) print3("Ouch!");
166 : 0 : return(FALSE);
167 : : }
168 [ + + ]: 19 : else if (Level->site[x][y].creature != NULL) {
169 [ + - ]: 14 : if (! gamestatusp(FAST_MOVE)) {
170 : 14 : fight_monster(Level->site[x][y].creature);
171 : 14 : resetgamestatus(SKIP_MONSTERS);
172 : 14 : return(FALSE);
173 : : }
174 : 0 : else return(FALSE);
175 : : }
176 [ + - ][ + - ]: 5 : else if ((Level->site[x][y].locchar == WALL) ||
177 [ + - ]: 5 : (Level->site[x][y].locchar == STATUE) ||
178 [ + - ]: 5 : (Level->site[x][y].locchar == PORTCULLIS) ||
179 [ - + ]: 5 : (Level->site[x][y].locchar == CLOSED_DOOR) ||
180 [ # # ]: 0 : (gamestatusp(FAST_MOVE) &&
181 [ # # ]: 0 : ((Level->site[x][y].locchar == HEDGE) ||
182 [ # # ]: 0 : (Level->site[x][y].locchar == LAVA) ||
183 [ # # ]: 0 : (Level->site[x][y].locchar == ABYSS) ||
184 [ # # ]: 0 : (Level->site[x][y].locchar == VOID_CHAR) ||
185 [ # # ]: 0 : (Level->site[x][y].locchar == FIRE) ||
186 [ # # ]: 0 : (Level->site[x][y].locchar == WHIRLWIND) ||
187 [ # # ]: 0 : (Level->site[x][y].locchar == WATER) ||
188 [ # # ]: 0 : (Level->site[x][y].locchar == LIFT) ||
189 : 0 : (Level->site[x][y].locchar == TRAP)))) {
190 [ # # ]: 0 : if (! gamestatusp(FAST_MOVE)) print3("Ouch!");
191 : 0 : return(FALSE);
192 : : }
193 [ + - ]: 5 : else if (optionp(CONFIRM)) {
194 [ + - ][ + - ]: 5 : if ((Level->site[x][y].locchar == HEDGE) ||
195 [ + - ]: 5 : (Level->site[x][y].locchar == LAVA) ||
196 [ + - ]: 5 : (Level->site[x][y].locchar == FIRE) ||
197 [ + - ]: 5 : (Level->site[x][y].locchar == WHIRLWIND) ||
198 [ + - ]: 5 : (Level->site[x][y].locchar == ABYSS) ||
199 [ + - ]: 5 : (Level->site[x][y].locchar == VOID_CHAR) ||
200 [ + - ]: 5 : (Level->site[x][y].locchar == WATER) ||
201 [ + - ]: 5 : (Level->site[x][y].locchar == RUBBLE) ||
202 [ - + ]: 5 : (Level->site[x][y].locchar == LIFT) ||
203 : 5 : (Level->site[x][y].locchar == TRAP)) {
204 : : /* horses WILL go into water... */
205 [ # # ]: 0 : if (gamestatusp(MOUNTED)) {
206 [ # # ][ # # ]: 0 : if (Level->site[x][y].locchar != WATER ||
207 : 0 : Level->site[x][y].p_locf != L_WATER) {
208 : 0 : print1("You can't convince your steed to continue.");
209 : 0 : setgamestatus(SKIP_MONSTERS);
210 : 0 : return(FALSE);
211 : : }
212 : 0 : else return(TRUE);
213 : : }
214 [ # # ]: 0 : else if (cinema_confirm("Look where you're about to step!") == 'y') resetgamestatus(SKIP_MONSTERS);
215 : 0 : else setgamestatus(SKIP_MONSTERS);
216 : 0 : return(!gamestatusp(SKIP_MONSTERS));
217 : : }
218 : : else {
219 : 5 : resetgamestatus(SKIP_MONSTERS);
220 : 5 : return(TRUE);
221 : : }
222 : : }
223 : : else {
224 : 0 : resetgamestatus(SKIP_MONSTERS);
225 : 0 : return(TRUE);
226 : : }
227 : : }
228 : :
229 : :
230 : :
231 : : /* check a move attempt in the countryside */
232 : 3 : int p_country_moveable(int x, int y)
233 : : {
234 [ - + ]: 3 : if (! inbounds(x,y)) return (FALSE);
235 [ + - ]: 3 : else if (optionp(CONFIRM)) {
236 [ + - ][ + + ]: 3 : if ((Country[x][y].current_terrain_type == CHAOS_SEA) ||
237 : 3 : (Country[x][y].current_terrain_type == MOUNTAINS))
238 : 1 : return(cinema_confirm("That's dangerous terrain, and slow going.")=='y');
239 : 2 : else return(TRUE);
240 : : }
241 : 0 : else return(TRUE);
242 : : }
243 : :
244 : :
245 : :
246 : :
247 : :
248 : : /* search once particular spot */
249 : 0 : void searchat(int x, int y)
250 : : {
251 : : int i;
252 [ # # ][ # # ]: 0 : if (inbounds(x,y) && (random_range(3) || Player.status[ALERT])) {
[ # # ]
253 [ # # ]: 0 : if (loc_statusp(x,y,SECRET)) {
254 : 0 : lreset(x,y,SECRET);
255 : 0 : lset(x, y, CHANGED);
256 [ # # ][ # # ]: 0 : if ((Level->site[x][y].locchar==OPEN_DOOR) ||
257 : 0 : (Level->site[x][y].locchar==CLOSED_DOOR)) {
258 : 0 : mprint("You find a secret door!");
259 [ # # ]: 0 : for(i=0;i<=8;i++) { /* FIXED! 12/25/98 */
260 : 0 : lset(x+Dirs[0][i],y+Dirs[1][i],STOPS);
261 : 0 : lset(x+Dirs[0][i], y+Dirs[1][i], CHANGED);
262 : : }
263 : : }
264 : 0 : else mprint("You find a secret passage!");
265 : 0 : drawvision(Player.x,Player.y);
266 : : }
267 [ # # ][ # # ]: 0 : if ((Level->site[x][y].p_locf >= TRAP_BASE) &&
268 [ # # ]: 0 : (Level->site[x][y].locchar != TRAP) &&
269 : 0 : (Level->site[x][y].p_locf <= TRAP_BASE+NUMTRAPS)) {
270 : 0 : Level->site[x][y].locchar = TRAP;
271 : 0 : lset(x, y, CHANGED);
272 : 0 : mprint("You find a trap!");
273 : 0 : drawvision(Player.x,Player.y);
274 : 0 : resetgamestatus(FAST_MOVE);
275 : : }
276 : : }
277 : 0 : }
278 : :
279 : :
280 : :
281 : : /* This is to be called whenever anything might change player performance in
282 : : melee, such as changing weapon, statistics, etc. */
283 : 20 : void calc_melee(void)
284 : : {
285 : 20 : calc_weight();
286 : :
287 : 20 : Player.maxweight = (Player.str * Player.agi * 10);
288 : 20 : Player.absorption = Player.status[PROTECTION];
289 : 20 : Player.defense = 2 * statmod(Player.agi)+(Player.level/2);
290 : 20 : Player.hit = Player.level + statmod(Player.dex)+1;
291 : 20 : Player.dmg = statmod(Player.str)+3;
292 [ + - ]: 20 : Player.speed = 5 - min(4,(statmod(Player.agi)/2));
293 [ - + ]: 20 : if (Player.status[HASTED] > 0) Player.speed = Player.speed / 2;
294 [ - + ]: 20 : if (Player.status[SLOWED] > 0) Player.speed = Player.speed * 2;
295 [ + - ]: 20 : if (Player.itemweight > 0)
296 [ - - - + : 20 : switch(Player.maxweight / Player.itemweight) {
+ ]
297 : 0 : case 0: Player.speed+=6; break;
298 : 0 : case 1: Player.speed+=3; break;
299 : 0 : case 2: Player.speed+=2; break;
300 : 6 : case 3: Player.speed+=1; break;
301 : : }
302 : :
303 [ - + ]: 20 : if (Player.status[ACCURATE]) Player.hit+=20;
304 [ - + ]: 20 : if (Player.status[HERO]) Player.hit+=Player.dex;
305 [ - + ]: 20 : if (Player.status[HERO]) Player.dmg+=Player.str;
306 [ - + ]: 20 : if (Player.status[HERO]) Player.defense+=Player.agi;
307 [ - + ]: 20 : if (Player.status[HERO]) Player.speed=Player.speed / 2;
308 : :
309 [ + - ]: 20 : Player.speed = max(1,min(25,Player.speed));
310 : :
311 [ + + ]: 20 : if (gamestatusp(MOUNTED)) {
312 : 15 : Player.speed = 3;
313 : 15 : Player.hit += 10;
314 : 15 : Player.dmg += 10;
315 : : }
316 : : #ifdef INCLUDE_MONKS
317 [ - + ]: 5 : else if (Player.rank[MONKS] > 0)
318 : : {
319 : : /* monks are faster when not in armor or on horseback */
320 [ # # ]: 0 : if (Player.possessions[O_ARMOR] == NULL) {
321 : 0 : Player.speed += (min(0,(Player.rank[MONKS] -1)));
322 : : }
323 : : }
324 : : #endif
325 : : /* weapon */
326 : : /* have to check for used since it could be a 2h weapon just carried
327 : : in one hand */
328 [ + - ]: 20 : if (Player.possessions[O_WEAPON_HAND] != NULL)
329 [ + + ][ - + ]: 20 : if (Player.possessions[O_WEAPON_HAND]->used &&
330 [ # # ]: 0 : ((Player.possessions[O_WEAPON_HAND]->objchar==WEAPON)||
331 : 0 : (Player.possessions[O_WEAPON_HAND]->objchar==MISSILEWEAPON))) {
332 : 38 : Player.hit +=
333 : 38 : Player.possessions[O_WEAPON_HAND]->hit +
334 : 19 : Player.possessions[O_WEAPON_HAND]->plus;
335 : 19 : Player.dmg +=
336 : 38 : Player.possessions[O_WEAPON_HAND]->dmg +
337 : 19 : Player.possessions[O_WEAPON_HAND]->plus;
338 : : }
339 : :
340 : : #ifdef INCLUDE_MONKS
341 [ - + ]: 20 : if (Player.rank[MONKS] > 0)
342 : : {
343 : : /* monks */
344 : : /* aren't monks just obscene? PGM */
345 [ # # ]: 0 : if (Player.possessions[O_WEAPON_HAND] == NULL) /*barehanded*/
346 : : {
347 : : /* all monks get a bonus in unarmed combat */
348 : 0 : Player.hit += ( Player.rank[MONKS] * Player.level );
349 : 0 : Player.dmg += ( Player.rank[MONKS] * Player.level );
350 : 0 : Player.defense += ( Player.rank[MONKS] * Player.level );
351 : :
352 [ # # ]: 0 : if (Player.rank[MONKS] == MONK_GRANDMASTER)
353 : : {
354 : : /* Grandmaster does 3x damage in unarmed combat. */
355 : 0 : Player.dmg *= 3;
356 : : }
357 : : }
358 : : }
359 : : #endif
360 : :
361 : : /* shield or defensive weapon */
362 [ - + ]: 20 : if (Player.possessions[O_SHIELD] != NULL) {
363 : 0 : Player.defense +=
364 : 0 : Player.possessions[O_SHIELD]->aux +
365 : 0 : Player.possessions[O_SHIELD]->plus;
366 : : }
367 : :
368 : : /* armor */
369 [ + - ]: 20 : if (Player.possessions[O_ARMOR] != NULL) {
370 : 20 : Player.absorption += Player.possessions[O_ARMOR]->dmg;
371 : 20 : Player.defense +=
372 : 40 : Player.possessions[O_ARMOR]->plus -
373 : 20 : Player.possessions[O_ARMOR]->aux;
374 : : }
375 : :
376 [ - + ]: 20 : if (strlen(Player.meleestr) > 2*maneuvers())
377 : 0 : default_maneuvers();
378 : 20 : comwinprint();
379 : 20 : showflags();
380 : 20 : dataprint();
381 : 20 : }
382 : :
383 : :
384 : : /* player attacks monster m */
385 : 14 : void fight_monster(struct monster *m)
386 : : {
387 : 14 : int hitmod = 0;
388 : 14 : int reallyfight = TRUE;
389 : :
390 [ - + ]: 14 : if (Player.status[AFRAID]) {
391 : 0 : print3("You are much too afraid to fight!");
392 : 0 : reallyfight = FALSE;
393 : : }
394 [ - + ]: 14 : else if (player_on_sanctuary()) {
395 : 0 : print3("You restrain yourself from desecrating this holy place.");
396 : 0 : reallyfight = FALSE;
397 : : }
398 [ - + ]: 14 : else if (Player.status[SHADOWFORM]) {
399 : 0 : print3("Your attack has no effect in your shadowy state.");
400 : 0 : reallyfight = FALSE;
401 : : }
402 [ + - ][ - + ]: 14 : else if ((Player.status[BERSERK]<1) && (! m_statusp(m,HOSTILE))) {
403 [ # # ]: 0 : if (optionp(BELLICOSE)) reallyfight = TRUE;
404 : 0 : else reallyfight = 'y'==cinema_confirm("You're attacking without provokation.");
405 : : }
406 : 14 : else reallyfight = TRUE;
407 : :
408 [ + - ]: 14 : if (reallyfight) {
409 : :
410 [ - + ]: 14 : if (Lunarity == 1) hitmod += Player.level;
411 [ - + ]: 14 : else if (Lunarity == -1) hitmod -= (Player.level / 2);
412 : :
413 [ - + ]: 14 : if (! m->attacked) Player.alignment -= 2; /* chaotic action */
414 : 14 : m_status_set(m,AWAKE);
415 : 14 : m_status_set(m,HOSTILE);
416 : 14 : m->attacked = TRUE;
417 : 14 : Player.hit += hitmod;
418 : 14 : tacplayer(m);
419 : 14 : Player.hit -= hitmod;
420 : : }
421 : 14 : }
422 : :
423 : :
424 : :
425 : :
426 : : /* Attempt to break an object o */
427 : 0 : int damage_item(pob o)
428 : : {
429 : : /* special case -- break star gem */
430 [ # # ]: 0 : if (o->id == OB_STARGEM) {
431 : 0 : print1("The Star Gem shatters into a million glistening shards....");
432 [ # # ]: 0 : if (Current_Environment == E_STARPEAK) {
433 [ # # ]: 0 : if (! gamestatusp(KILLED_LAWBRINGER))
434 : 0 : print2("You hear an agonizing scream of anguish and despair.");
435 : 0 : morewait();
436 : 0 : print1("A raging torrent of energy escapes in an explosion of magic!");
437 : 0 : print2("The energy flows to the apex of Star Peak where there is");
438 : 0 : morewait();
439 : 0 : clearmsg();
440 : 0 : print1("an enormous explosion!");
441 : 0 : morewait();
442 : 0 : annihilate(1);
443 : 0 : print3("You seem to gain strength in the chaotic glare of magic!");
444 : 0 : Player.str = max(Player.str, Player.maxstr + 5); /* FIXED! 12/25/98 */
445 : 0 : Player.pow = max(Player.pow, Player.maxpow + 5); /* ditto */
446 : 0 : Player.alignment -= 200;
447 : 0 : dispose_lost_objects(1,o);
448 : : }
449 : : else {
450 : 0 : morewait();
451 : 0 : print1("The shards coalesce back together again, and vanish");
452 : 0 : print2("with a muted giggle.");
453 : 0 : dispose_lost_objects(1,o);
454 : 0 : Objects[o->id].uniqueness = UNIQUE_UNMADE; /* FIXED! 12/30/98 */
455 : : }
456 : 0 : return 1;
457 : : }
458 : : else {
459 [ # # ]: 0 : if (o->fragility < random_range(30)) {
460 [ # # ][ # # ]: 0 : if (o->objchar == STICK && o->charge > 0) {
461 : 0 : strcpy(Str1,"Your ");
462 [ # # ]: 0 : strcat(Str1,(o->blessing >= 0 ? o->truename : o->cursestr));
463 : 0 : strcat(Str1," explodes!");
464 : 0 : print1(Str1);
465 : 0 : morewait();
466 : 0 : nprint1(" Ka-Blamm!!!");
467 : : /* general case. Some sticks will eventually do special things */
468 : 0 : morewait();
469 : 0 : manastorm(Player.x, Player.y, o->charge*o->level*10);
470 : 0 : dispose_lost_objects(1,o);
471 : 0 : return 1;
472 : : }
473 [ # # ][ # # ]: 0 : else if ((o->blessing > 0) && (o->level > random_range(10))) {
474 : 0 : strcpy(Str1,"Your ");
475 : 0 : strcat(Str1,itemid(o));
476 : 0 : strcat(Str1," glows strongly.");
477 : 0 : print1(Str1);
478 : 0 : return 0;
479 : : }
480 [ # # ][ # # ]: 0 : else if ((o->blessing < -1) && (o->level > random_range(10))) {
481 : 0 : strcpy(Str1,"You hear an evil giggle from your ");
482 : 0 : strcat(Str1,itemid(o));
483 : 0 : print1(Str1);
484 : 0 : return 0;
485 : : }
486 [ # # ]: 0 : else if (o->plus > 0) {
487 : 0 : strcpy(Str1,"Your ");
488 : 0 : strcat(Str1,itemid(o));
489 : 0 : strcat(Str1," glows and then fades.");
490 : 0 : print1(Str1);
491 : 0 : o->plus--;
492 : 0 : return 0;
493 : : }
494 : : else {
495 [ # # ]: 0 : if (o->blessing > 0) print1("You hear a faint despairing cry!");
496 [ # # ]: 0 : else if (o->blessing < 0) print1("You hear an agonized scream!");
497 : 0 : strcpy(Str1,"Your ");
498 : 0 : strcat(Str1,itemid(o));
499 : 0 : strcat(Str1," shatters in a thousand lost fragments!");
500 : 0 : print2(Str1);
501 : 0 : morewait();
502 : 0 : dispose_lost_objects(1,o);
503 : 0 : return 1;
504 : : }
505 : : }
506 : 0 : return 0;
507 : : }
508 : : }
509 : :
510 : : /* do dmg points of damage of type dtype, from source fromstring */
511 : 13 : void p_damage(int dmg, int dtype, char *fromstring)
512 : : {
513 [ - + ]: 13 : if (gamestatusp(FAST_MOVE)) {
514 : 0 : drawvision(Player.x,Player.y);
515 : 0 : resetgamestatus(FAST_MOVE);
516 : : }
517 [ + - ]: 13 : if (! p_immune(dtype)) {
518 [ + - ]: 13 : if (dtype == NORMAL_DAMAGE) Player.hp -= max(1,(dmg-Player.absorption));
519 : 0 : else Player.hp -= dmg;
520 [ + + ]: 13 : if (Player.hp < 1) p_death(fromstring);
521 : : }
522 : 0 : else mprint("You resist the effects!");
523 : 12 : dataprint();
524 : 12 : }
525 : :
526 : : /* game over, you lose! */
527 : 1 : void p_death(char *fromstring)
528 : : {
529 : 1 : Player.hp = -1;
530 : 1 : print3("You died!");
531 : 1 : morewait();
532 : 1 : display_death(fromstring);
533 : 1 : player_dump();
534 : : #ifdef SAVE_LEVELS
535 : : kill_all_levels();
536 : : #endif
537 : 1 : endgraf();
538 : 1 : exit(0);
539 : : }
540 : :
541 : :
542 : : /* move the cursor around, like for firing a wand, sets x and y to target */
543 : 3 : void setspot(int *x, int *y)
544 : : {
545 : 3 : char c = ' ';
546 : 3 : mprint("Targeting.... ? for help");
547 : 3 : omshowcursor(*x,*y);
548 [ + + ][ + - ]: 16 : while ((c != '.') && (c != ESCAPE)) {
549 : 13 : c = lgetc();
550 [ - + - + : 13 : switch(c) {
- + + + -
+ ]
551 : 0 : case 'h':case '4': movecursor(x,y,-1,0); break;
552 : 4 : case 'j':case '2': movecursor(x,y,0,1); break;
553 : 0 : case 'k':case '8': movecursor(x,y,0,-1); break;
554 : 2 : case 'l':case '6': movecursor(x,y,1,0); break;
555 : 0 : case 'b':case '1': movecursor(x,y,-1,1); break;
556 : 2 : case 'n':case '3': movecursor(x,y,1,1); break;
557 : 1 : case 'y':case '7': movecursor(x,y,-1,-1); break;
558 : 1 : case 'u':case '9': movecursor(x,y,1,-1); break;
559 : : case '?':
560 : 0 : clearmsg();
561 : 0 : mprint("Use vi keys or numeric keypad to move cursor to target.");
562 : 0 : mprint("Hit the '.' key when done, or ESCAPE to abort.");
563 : 0 : break;
564 : : }
565 : : }
566 [ - + ]: 3 : if (c==ESCAPE) *x = *y= ABORT;
567 : 3 : screencheck(Player.x,Player.y);
568 : 3 : }
569 : :
570 : :
571 : : /* get a direction: return index into Dirs array corresponding to direction */
572 : 0 : int getdir(void)
573 : : {
574 : : while (1) {
575 : 0 : mprint("Select direction [hjklyubn, ESCAPE to quit]: ");
576 [ # # # # : 0 : switch (mgetc()) {
# # # # #
# ]
577 : : case '4':
578 : : case 'h':
579 : 0 : case 'H': return(5);
580 : : case '2':
581 : : case 'j':
582 : 0 : case 'J': return(6);
583 : : case '8':
584 : : case 'k':
585 : 0 : case 'K': return(7);
586 : : case '6':
587 : : case 'l':
588 : 0 : case 'L': return(4);
589 : : case '7':
590 : : case 'y':
591 : 0 : case 'Y': return(3);
592 : : case '9':
593 : : case 'u':
594 : 0 : case 'U': return(1);
595 : : case '1':
596 : : case 'b':
597 : 0 : case 'B': return(2);
598 : : case '3':
599 : : case 'n':
600 : 0 : case 'N': return(0);
601 : 0 : case ESCAPE: return(ABORT);
602 : 0 : default: print3("That's not a direction! ");
603 : : }
604 : 0 : }
605 : : }
606 : :
607 : :
608 : :
609 : : /* functions describes monster m's state for examine function */
610 : 2 : char *mstatus_string(struct monster *m)
611 : : {
612 [ - + ][ # # ]: 2 : if (m_statusp(m, M_INVISIBLE) && !Player.status[TRUESIGHT])
613 : 0 : strcpy(Str2, "Some invisible creature");
614 [ + - ]: 2 : else if (m->uniqueness == COMMON) {
615 [ - + ]: 2 : if (m->hp < Monsters[m->id].hp / 3)
616 : 0 : strcpy(Str2,"a grievously injured ");
617 [ - + ]: 2 : else if (m->hp < Monsters[m->id].hp / 2)
618 : 0 : strcpy(Str2,"a severely injured ");
619 [ - + ]: 2 : else if (m->hp < Monsters[m->id].hp)
620 : 0 : strcpy(Str2,"an injured ");
621 : 2 : else strcpy(Str2,getarticle(m->monstring));
622 [ - + ]: 2 : if (m->level > Monsters[m->id].level) {
623 : 0 : strcat(Str2," (level ");
624 : 0 : strcat(Str2,wordnum(m->level+1-Monsters[m->id].level));
625 : 0 : strcat(Str2,") ");
626 : : }
627 : 2 : strcat(Str2,m->monstring);
628 : : }
629 : : else {
630 : 0 : strcpy(Str2,m->monstring);
631 [ # # ]: 0 : if (m->hp < Monsters[m->id].hp / 3)
632 : 0 : strcat(Str2," who is grievously injured ");
633 [ # # ]: 0 : else if (m->hp < Monsters[m->id].hp / 2)
634 : 0 : strcat(Str2," who is severely injured ");
635 [ # # ]: 0 : else if (m->hp < Monsters[m->id].hp)
636 : 0 : strcat(Str2," who is injured ");
637 : : }
638 : 2 : return(Str2);
639 : : }
640 : :
641 : :
642 : :
643 : :
644 : : /* for the examine function */
645 : 0 : void describe_player(void)
646 : : {
647 [ # # ]: 0 : if (Player.hp < (Player.maxhp /5))
648 : 0 : print1("A grievously injured ");
649 [ # # ]: 0 : else if (Player.hp < (Player.maxhp /2))
650 : 0 : print1("A seriously wounded ");
651 [ # # ]: 0 : else if (Player.hp < Player.maxhp)
652 : 0 : print1("A somewhat bruised ");
653 : 0 : else print1("A fit ");
654 : :
655 [ # # ]: 0 : if (Player.status[SHADOWFORM])
656 : 0 : nprint1("shadow");
657 : : else
658 : 0 : nprint1(levelname(Player.level));
659 : 0 : nprint1(" named ");
660 : 0 : nprint1(Player.name);
661 [ # # ]: 0 : if (gamestatusp(MOUNTED))
662 : 0 : nprint1(" (riding a horse.)");
663 : 0 : }
664 : :
665 : :
666 : : /* access to player experience... */
667 : : /* share out experience among guild memberships */
668 : 2 : void gain_experience(int amount)
669 : : {
670 : 2 : int i,count=0,share;
671 : 2 : Player.xp += (long) amount;
672 : 2 : gain_level(); /* actually, check to see if should gain level */
673 [ + + ]: 22 : for(i=0;i<NUMRANKS;i++)
674 [ + + ]: 20 : if (Player.guildxp[i] > 0) count++;
675 : 2 : share = amount/(max(count,1));
676 [ + + ]: 22 : for(i=0;i<NUMRANKS;i++)
677 [ + + ]: 20 : if (Player.guildxp[i] > 0) Player.guildxp[i]+=share;
678 : 2 : }
679 : :
680 : : /* try to hit a monster in an adjacent space. If there are none
681 : : return FALSE. Note if you're berserk you get to attack ALL
682 : : adjacent monsters! */
683 : 0 : int goberserk(void)
684 : : {
685 : 0 : int wentberserk=FALSE,i;
686 : : char meleestr[80];
687 : 0 : strcpy(meleestr,Player.meleestr);
688 : 0 : strcpy(Player.meleestr,"lLlClH");
689 [ # # ]: 0 : for(i=0;i<8;i++)
690 [ # # ]: 0 : if (Level->site[Player.x+Dirs[0][i]][Player.y+Dirs[1][i]].creature
691 : : != NULL) {
692 : 0 : wentberserk=TRUE;
693 : 0 : fight_monster(Level->site[Player.x+Dirs[0][i]][Player.y+Dirs[1][i]].creature);
694 : 0 : morewait();
695 : : }
696 : 0 : strcpy(Player.meleestr,meleestr);
697 : 0 : return(wentberserk);
698 : : }
699 : :
700 : : /* identifies a trap for examine() by its aux value */
701 : 0 : char *trapid(int trapno)
702 : : {
703 [ # # # # : 0 : switch (trapno) {
# # # # #
# # # #
# ]
704 : 0 : case L_TRAP_SIREN:return("A siren trap");
705 : 0 : case L_TRAP_DART:return("A dart trap");
706 : 0 : case L_TRAP_PIT:return("A pit");
707 : 0 : case L_TRAP_SNARE:return("A snare");
708 : 0 : case L_TRAP_BLADE:return("A blade trap");
709 : 0 : case L_TRAP_FIRE:return("A fire trap");
710 : 0 : case L_TRAP_TELEPORT:return("A teleport trap");
711 : 0 : case L_TRAP_DISINTEGRATE:return("A disintegration trap");
712 : 0 : case L_TRAP_DOOR:return("A trap door");
713 : 0 : case L_TRAP_MANADRAIN:return("A manadrain trap");
714 : 0 : case L_TRAP_ACID:return("An acid shower trap");
715 : 0 : case L_TRAP_SLEEP_GAS:return("A sleep gas trap");
716 : 0 : case L_TRAP_ABYSS:return("A concealed entrance to the abyss");
717 : 0 : default: return("A completely inoperative trap.");
718 : : }
719 : : }
720 : :
721 : :
722 : : /* checks current food status of player, every hour, and when food is eaten */
723 : 10 : void foodcheck(void)
724 : : {
725 [ - + ]: 10 : if (Player.food > 48) {
726 : 0 : print3("You vomit up your huge meal.");
727 : 0 : Player.food = 12;
728 : : }
729 [ + + ]: 10 : else if (Player.food == 30)
730 : 1 : print3("Time for a smackerel of something.");
731 [ - + ]: 9 : else if (Player.food == 20)
732 : 0 : print3("You feel hungry.");
733 [ - + ]: 9 : else if (Player.food == 12)
734 : 0 : print3("You are ravenously hungry.");
735 [ - + ]: 9 : else if (Player.food == 3) {
736 : 0 : print3("You feel weak.");
737 [ # # ]: 0 : if (gamestatusp(FAST_MOVE)) {
738 : 0 : drawvision(Player.x,Player.y);
739 : 0 : resetgamestatus(FAST_MOVE);
740 : : }
741 : : }
742 [ - + ]: 9 : else if (Player.food < 0) {
743 [ # # ]: 0 : if (gamestatusp(FAST_MOVE)) {
744 : 0 : drawvision(Player.x,Player.y);
745 : 0 : resetgamestatus(FAST_MOVE);
746 : : }
747 : 0 : print3("You're starving!");
748 : 0 : p_damage(-5*Player.food,UNSTOPPABLE,"starvation");
749 : : }
750 : 10 : showflags();
751 : 10 : }
752 : :
753 : :
754 : :
755 : :
756 : : /* see whether room should be illuminated */
757 : 30 : void roomcheck(void)
758 : : {
759 : : static int oldroomno = -1;
760 : : #ifdef MSDOS_SUPPORTED_ANTIQUE
761 : : static int oldlevel = -1;
762 : : #else
763 : : static plv oldlevel = NULL;
764 : : #endif
765 : 30 : int roomno = Level->site[Player.x][Player.y].roomnumber;
766 : :
767 [ + + ][ + - ]: 30 : if ((roomno == RS_CAVERN) ||
768 [ + - ]: 4 : (roomno == RS_SEWER_DUCT) ||
769 [ + - ]: 4 : (roomno == RS_KITCHEN) ||
770 [ + - ]: 4 : (roomno == RS_BATHROOM) ||
771 [ + - ]: 4 : (roomno == RS_BEDROOM) ||
772 [ + - ]: 4 : (roomno == RS_DININGROOM) ||
773 [ - + ]: 4 : (roomno == RS_CLOSET) ||
774 : : (roomno > ROOMBASE))
775 [ + + ][ + - ]: 26 : if ((! loc_statusp(Player.x,Player.y,LIT)) &&
776 [ + - ]: 1 : (! Player.status[BLINDED]) &&
777 [ + - ]: 1 : (Player.status[ILLUMINATION] || (difficulty() < 6))) {
778 : 1 : showroom(Level->site[Player.x][Player.y].roomnumber);
779 : 1 : spreadroomlight(Player.x,Player.y,roomno);
780 : 1 : levelrefresh();
781 : : }
782 [ + + ][ - + ]: 30 : if ((oldroomno != roomno) ||
783 : : #ifdef MSDOS_SUPPORTED_ANTIQUE
784 : : (oldlevel != Level->depth)) {
785 : : #else
786 : 28 : (oldlevel != Level)) {
787 : : #endif
788 : 2 : showroom(roomno);
789 : 2 : oldroomno = roomno;
790 : : #ifdef MSDOS_SUPPORTED_ANTIQUE
791 : : oldlevel = Level->depth;
792 : : #else
793 : 2 : oldlevel = Level;
794 : : #endif
795 : : }
796 : 30 : }
797 : :
798 : :
799 : : /* ask for mercy */
800 : 0 : void surrender(struct monster *m)
801 : : {
802 : : int i;
803 : : long bestitem,bestvalue;
804 : :
805 [ # # # # : 0 : switch(random_range(4)) {
# ]
806 : 0 : case 0: print1("You grovel at the monster's feet..."); break;
807 : 0 : case 1: print1("You cry 'uncle'!"); break;
808 : 0 : case 2: print1("You beg for mercy."); break;
809 : 0 : case 3: print1("You yield to the monster."); break;
810 : : }
811 [ # # ]: 0 : if (m->id == GUARD) {
812 [ # # ]: 0 : if (m_statusp(m,HOSTILE))
813 : 0 : monster_talk(m);
814 : : else {
815 : 0 : print2("The guard (bored): Have you broken a law? [yn] ");
816 [ # # ]: 0 : if (ynq2() == 'y') {
817 : 0 : print2("The guard grabs you, and drags you to court.");
818 : 0 : morewait();
819 : 0 : send_to_jail();
820 : : }
821 : 0 : else print2("Then don't bother me. Scat!");
822 : : }
823 : : }
824 [ # # ][ # # ]: 0 : else if ((m->talkf==M_NO_OP) ||
825 : 0 : (m->talkf==M_TALK_STUPID))
826 : 0 : print3("Your plea is ignored.");
827 : : else {
828 : 0 : morewait();
829 : 0 : print1("Your surrender is accepted.");
830 [ # # ]: 0 : if (Player.cash > 0) nprint1(" All your gold is taken....");
831 : 0 : Player.cash = 0;
832 : 0 : bestvalue = 0;
833 : 0 : bestitem = ABORT;
834 [ # # ]: 0 : for (i=1;i<MAXITEMS;i++)
835 [ # # ]: 0 : if (Player.possessions[i] != NULL)
836 [ # # ]: 0 : if (bestvalue < true_item_value(Player.possessions[i])) {
837 : 0 : bestitem = i;
838 : 0 : bestvalue = true_item_value(Player.possessions[i]);
839 : : }
840 [ # # ]: 0 : if (bestitem != ABORT) {
841 : 0 : print2("You also give away your best item... ");
842 : 0 : nprint2(itemid(Player.possessions[bestitem]));
843 : 0 : nprint2(".");
844 : 0 : morewait();
845 : 0 : givemonster(m,Player.possessions[bestitem]);
846 : 0 : morewait(); /* msgs come from givemonster */
847 : 0 : conform_unused_object(Player.possessions[bestitem]);
848 : 0 : Player.possessions[bestitem] = NULL;
849 : : }
850 : 0 : print2("You feel less experienced... ");
851 : 0 : Player.xp = max(0,Player.xp - m->xpv);
852 : 0 : nprint2("The monster seems more experienced!");
853 : 0 : m->level = (min(10,m->level+1));
854 : 0 : m->hp += m->level*20;
855 : 0 : m->hit += m->level;
856 : 0 : m->dmg += m->level;
857 : 0 : m->ac += m->level;
858 : 0 : m->xpv += m->level*10;
859 : 0 : morewait();
860 : 0 : clearmsg();
861 [ # # ][ # # ]: 0 : if ((m->talkf == M_TALK_EVIL) && random_range(10)) {
862 : 0 : print1("It continues to attack you, laughing evilly!");
863 : 0 : m_status_set(m,HOSTILE);
864 : 0 : m_status_reset(m,GREEDY);
865 : : }
866 [ # # ][ # # ]: 0 : else if (m->id == HORNET || m->id == GUARD)
867 : 0 : print1("It continues to attack you. ");
868 : : else {
869 : 0 : print1("The monster leaves, chuckling to itself....");
870 : 0 : m_teleport(m);
871 : : }
872 : : }
873 : 0 : dataprint();
874 : 0 : }
875 : :
876 : :
877 : : /* threaten a monster */
878 : 0 : void threaten(struct monster *m)
879 : : {
880 : : char response;
881 [ # # # # : 0 : switch(random_range(4)) {
# ]
882 : 0 : case 0:mprint("You demand that your opponent surrender!"); break;
883 : 0 : case 1:mprint("You threaten to do bodily harm to it."); break;
884 : 0 : case 2:mprint("You attempt to bluster it into submission."); break;
885 : 0 : case 3:mprint("You try to cow it with your awesome presence."); break;
886 : : }
887 : 0 : morewait(); /* FIXED! 12/25/98 */
888 [ # # ]: 0 : if (! m_statusp(m,HOSTILE)) {
889 : 0 : print3("You only annoy it with your futile demand.");
890 : 0 : m_status_set(m,HOSTILE);
891 : : }
892 [ # # ][ # # ]: 0 : else if (((m->level*2 > Player.level) && (m->hp > Player.dmg)) ||
[ # # ]
893 : 0 : (m->uniqueness != COMMON))
894 : 0 : print1("It sneers contemptuously at you.");
895 [ # # ][ # # ]: 0 : else if ((m->talkf != M_TALK_GREEDY) &&
896 [ # # ]: 0 : (m->talkf != M_TALK_HUNGRY) &&
897 [ # # ]: 0 : (m->talkf != M_TALK_EVIL) &&
898 [ # # ]: 0 : (m->talkf != M_TALK_MAN) &&
899 [ # # ]: 0 : (m->talkf != M_TALK_BEG) &&
900 [ # # ]: 0 : (m->talkf != M_TALK_THIEF) &&
901 [ # # ]: 0 : (m->talkf != M_TALK_MERCHANT) &&
902 : 0 : (m->talkf != M_TALK_IM))
903 : 0 : print1("Your demand is ignored");
904 : : else {
905 : 0 : print1("It yields to your mercy.");
906 : 0 : Player.alignment+=3;
907 : 0 : print2("Kill it, rob it, or free it? [krf] ");
908 : 0 : do response = (char) mcigetc();
909 [ # # ][ # # ]: 0 : while ((response != 'k')&&(response != 'r')&&(response !='f'));
[ # # ]
910 [ # # ]: 0 : if (response == 'k') {
911 : 0 : m_death(m);
912 : 0 : print2("You treacherous rogue!");
913 : 0 : Player.alignment -= 13;
914 : : }
915 [ # # ]: 0 : else if (response == 'r') {
916 : 0 : Player.alignment-=2;
917 : 0 : print2("It drops its treasure and flees.");
918 : 0 : m_dropstuff(m);
919 : 0 : m_remove( m );
920 : : }
921 : : else {
922 : 0 : Player.alignment+=2;
923 : 0 : print2("'If you love something set it free ... '");
924 [ # # ]: 0 : if (random_range(100)==13) {
925 : 0 : morewait();
926 : 0 : print2("'...If it doesn't come back, hunt it down and kill it.'");
927 : : }
928 : 0 : print3("It departs with a renewed sense of its own mortality.");
929 : 0 : m_remove( m );
930 : : }
931 : : }
932 : 0 : }
933 : :
934 : : /* name of the player's experience level */
935 : 18 : char *levelname(int level)
936 : : {
937 [ - + + - : 18 : switch(level) {
- - - - -
- + - - -
- - - - -
- - - -
- ]
938 : 0 : case 0:strcpy(Str3,"neophyte");break;
939 : 1 : case 1:strcpy(Str3,"beginner");break;
940 : 1 : case 2:strcpy(Str3,"tourist");break;
941 : 0 : case 3:strcpy(Str3,"traveller");break;
942 : 0 : case 4:strcpy(Str3,"wayfarer");break;
943 : 0 : case 5:strcpy(Str3,"peregrinator");break;
944 : 0 : case 6:strcpy(Str3,"wanderer");break;
945 : 0 : case 7:strcpy(Str3,"hunter");break;
946 : 0 : case 8:strcpy(Str3,"scout");break;
947 : 0 : case 9:strcpy(Str3,"trailblazer");break;
948 : 16 : case 10:strcpy(Str3,"discoverer");break;
949 : 0 : case 11:strcpy(Str3,"explorer");break;
950 : 0 : case 12:strcpy(Str3,"senior explorer");break;
951 : 0 : case 13:strcpy(Str3,"ranger");break;
952 : 0 : case 14:strcpy(Str3,"ranger captain");break;
953 : 0 : case 15:strcpy(Str3,"ranger knight");break;
954 : 0 : case 16:strcpy(Str3,"adventurer");break;
955 : 0 : case 17:strcpy(Str3,"experienced adventurer");break;
956 : 0 : case 18:strcpy(Str3,"skilled adventurer");break;
957 : 0 : case 19:strcpy(Str3,"master adventurer");break;
958 : 0 : case 20:strcpy(Str3,"hero");break;
959 : 0 : case 21:strcpy(Str3,"superhero");break;
960 : 0 : case 22:strcpy(Str3,"demigod");break;
961 : : default:
962 [ # # ]: 0 : if (level < 100) {
963 : 0 : strcpy(Str3,"Order ");
964 : 0 : Str3[6] = ((level/10)-2) + '0';
965 : 0 : Str3[7] = 0;
966 : 0 : strcat(Str3," Master of Omega");
967 : : }
968 : 0 : else strcpy(Str3,"Ultimate Master of Omega");
969 : 0 : break;
970 : : }
971 : 18 : return(Str3);
972 : : }
|