comparison xrogue/util.c @ 133:e6179860cb76

Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 21 Apr 2015 08:55:20 -0400
parents
children ce0cf824c192
comparison
equal deleted inserted replaced
124:d10fc4a065ac 133:e6179860cb76
1 /*
2 util.c - all sorts of miscellaneous routines
3
4 XRogue: Expeditions into the Dungeons of Doom
5 Copyright (C) 1991 Robert Pietkivitch
6 All rights reserved.
7
8 Based on "Advanced Rogue"
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
10 All rights reserved.
11
12 Based on "Rogue: Exploring the Dungeons of Doom"
13 Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
14 All rights reserved.
15
16 See the file LICENSE.TXT for full copyright and licensing information.
17 */
18
19 #include <curses.h>
20 #include <ctype.h>
21 #include "rogue.h"
22
23 /*
24 * this routine computes the players current AC without dex bonus's
25 */
26
27 int
28 ac_compute(ignoremetal)
29 bool ignoremetal;
30 {
31 register int ac;
32
33 ac = pstats.s_arm; /* base armor of "skin" */
34 if (cur_armor) {
35 if (!ignoremetal ||
36 (cur_armor->o_which != LEATHER &&
37 cur_armor->o_which != STUDDED_LEATHER &&
38 cur_armor->o_which != PADDED_ARMOR))
39 ac -= (10 - cur_armor->o_ac);
40 }
41 if (player.t_ctype == C_MONK)
42 ac -= pstats.s_lvl * 3 / 5;
43 ac -= ring_value(R_PROTECT);
44 if (cur_misc[WEAR_BRACERS] != NULL)
45 ac -= cur_misc[WEAR_BRACERS]->o_ac;
46 if (cur_misc[WEAR_CLOAK] != NULL)
47 ac -= cur_misc[WEAR_CLOAK]->o_ac;
48
49 /* If player has the cloak, must be wearing it */
50 if (cur_relic[EMORI_CLOAK]) ac -= 15;
51
52 if (ac > 25)
53 ac = 25;
54 return(ac);
55 }
56
57 /*
58 * aggravate:
59 * aggravate all the monsters on this level
60 */
61
62 aggravate(do_uniques, do_good)
63 bool do_uniques, do_good;
64 {
65 register struct linked_list *mi;
66 register struct thing *thingptr;
67
68 for (mi = mlist; mi != NULL; mi = next(mi)) {
69 thingptr = THINGPTR(mi);
70 if (do_good == FALSE && off(*thingptr, ISMEAN)) continue;
71 if (do_uniques || off(*thingptr, ISUNIQUE)) runto(thingptr, &hero);
72 }
73 }
74
75 /*
76 * cansee:
77 * returns true if the hero can see a certain coordinate.
78 */
79
80 cansee(y, x)
81 register int y, x;
82 {
83 register struct room *rer;
84 register int radius;
85 coord tp;
86
87 if (on(player, ISBLIND))
88 return FALSE;
89
90 tp.y = y;
91 tp.x = x;
92 rer = roomin(&tp);
93
94 /* How far can we see? */
95 if (levtype == OUTSIDE) {
96 if (daytime) radius = 36;
97 else if (lit_room(rer)) radius = 9;
98 else radius = 3;
99 }
100 else radius = 3;
101
102 /*
103 * We can only see if the hero in the same room as
104 * the coordinate and the room is lit or if it is close.
105 */
106 return ((rer != NULL &&
107 levtype != OUTSIDE &&
108 (levtype != MAZELEV || /* Maze level needs direct line */
109 maze_view(tp.y, tp.x)) &&
110 rer == roomin(&hero) &&
111 lit_room(rer)) ||
112 DISTANCE(y, x, hero.y, hero.x) < radius);
113 }
114
115 /*
116 * check_level:
117 * Check to see if the guy has gone up a level.
118 *
119 * Return points needed to obtain next level.
120 *
121 * These are certain beginning experience levels for all players.
122 * All further experience levels are computed by muliplying by 2
123 * up through MAXDOUBLE. Then the cap is added in to compute
124 * further levels
125 */
126
127 long
128 check_level()
129 {
130 register int i, j, add = 0;
131 register unsigned long exp;
132 long retval; /* Return value */
133 int nsides;
134
135 pstats.s_lvl -= pstats.s_lvladj; /* correct for level adjustment */
136 /* See if we are past the doubling stage */
137 exp = char_class[player.t_ctype].cap;
138 if (pstats.s_exp >= exp) {
139 i = pstats.s_exp/exp; /* First get amount above doubling area */
140 retval = exp + i * exp; /* Compute next higher boundary */
141 i += MAXDOUBLE; /* Add in the previous doubled levels */
142 }
143 else {
144 i = 0;
145 exp = char_class[player.t_ctype].start_exp;
146 while (exp <= pstats.s_exp) {
147 i++;
148 exp <<= 1;
149 }
150 retval = exp;
151 }
152 if (++i > pstats.s_lvl) {
153 nsides = char_class[player.t_ctype].hit_pts;
154 for (j=0; j<(i-pstats.s_lvl); j++) /* Take care of multi-level jumps */
155 add += max(1, roll(1,nsides) + const_bonus());
156 max_stats.s_hpt += add;
157 if ((pstats.s_hpt += add) > max_stats.s_hpt)
158 pstats.s_hpt = max_stats.s_hpt;
159 msg("Welcome, %s, to level %d",
160 cnames[player.t_ctype][min(i-1, NUM_CNAMES-1)], i);
161 }
162 pstats.s_lvl = i;
163 pstats.s_lvl += pstats.s_lvladj; /* correct for level adjustment */
164 return(retval);
165 }
166
167 /*
168 * Used to modify the players strength
169 * it keeps track of the highest it has been, just in case
170 */
171
172 chg_str(amt)
173 register int amt;
174 {
175 register int ring_str; /* ring strengths */
176 register struct stats *ptr; /* for speed */
177
178 ptr = &pstats;
179 ring_str = ring_value(R_ADDSTR);
180 ptr->s_str -= ring_str;
181 ptr->s_str += amt;
182 if (ptr->s_str > MAXATT) ptr->s_str = MAXATT;
183 if (ptr->s_str > max_stats.s_str)
184 max_stats.s_str = ptr->s_str;
185 ptr->s_str += ring_str;
186 if (ptr->s_str <= 0) {
187 pstats.s_hpt = -1;
188 death(D_STRENGTH);
189 }
190 updpack(TRUE, &player);
191 }
192
193 /*
194 * let's confuse the player
195 */
196
197 confus_player()
198 {
199 if (off(player, ISCLEAR))
200 {
201 msg("Wait, what's going on here! Huh? What? Who?");
202 if (find_slot(unconfuse))
203 lengthen(unconfuse, HUHDURATION);
204 else
205 fuse(unconfuse, (VOID *)NULL, HUHDURATION, AFTER);
206 turn_on(player, ISHUH);
207 }
208 else msg("You feel dizzy for a moment, but it quickly passes.");
209 }
210
211 /*
212 * this routine computes the players current dexterity
213 */
214
215 dex_compute()
216 {
217 if (cur_misc[WEAR_GAUNTLET] != NULL &&
218 cur_misc[WEAR_GAUNTLET]->o_which == MM_G_DEXTERITY) {
219 if (cur_misc[WEAR_GAUNTLET]->o_flags & ISCURSED)
220 return (3);
221 else
222 return (21);
223 }
224 else
225 return (pstats.s_dext);
226 }
227
228 /*
229 * diag_ok:
230 * Check to see if the move is legal if it is diagonal
231 */
232
233 diag_ok(sp, ep, flgptr)
234 register coord *sp, *ep;
235 struct thing *flgptr;
236 {
237 register int numpaths = 0;
238
239 /* Horizontal and vertical moves are always ok */
240 if (ep->x == sp->x || ep->y == sp->y)
241 return TRUE;
242
243 /* Diagonal moves are not allowed if there is a horizontal or
244 * vertical path to the destination
245 */
246 if (step_ok(ep->y, sp->x, MONSTOK, flgptr)) numpaths++;
247 if (step_ok(sp->y, ep->x, MONSTOK, flgptr)) numpaths++;
248 return(numpaths != 1);
249 }
250
251 /*
252 * pick a random position around the give (y, x) coordinates
253 */
254
255 coord *
256 fallpos(pos, be_clear, range)
257 register coord *pos;
258 bool be_clear;
259 int range;
260 {
261 register int tried, i, j;
262 register char ch;
263 static coord ret;
264 static short masks[] = {
265 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x100 };
266
267 /*
268 * Pick a spot at random centered on the position given by 'pos' and
269 * up to 'range' squares away from 'pos'
270 *
271 * If 'be_clear' is TRUE, the spot must be either FLOOR or PASSAGE
272 * inorder to be considered valid
273 *
274 * Generate a number from 0 to 8, representing the position to pick.
275 * Note that this DOES include the positon 'pos' itself
276 *
277 * If this position is not valid, mark it as 'tried', and pick another.
278 * Whenever a position is picked that has been tried before,
279 * sequentially find the next untried position. This eliminates costly
280 * random number generation
281 */
282
283 tried = 0;
284 while( tried != 0x1ff ) {
285 i = rnd(9);
286 while( tried & masks[i] )
287 i = (i + 1) % 9;
288
289 tried |= masks[i];
290
291 for( j = 1; j <= range; j++ ) {
292 ret.x = pos->x + j*grid[i].x;
293 ret.y = pos->y + j*grid[i].y;
294
295 if (ret.x == hero.x && ret.y == hero.y)
296 continue; /* skip the hero */
297
298 if (ret.x < 0 || ret.x > cols - 1 ||
299 ret.y < 1 || ret.y > lines - 3)
300 continue; /* off the screen? */
301
302 ch = winat(ret.y, ret.x);
303
304 /*
305 * Check to make certain the spot is valid
306 */
307 switch( ch ) {
308 case FLOOR:
309 case PASSAGE:
310 return( &ret );
311 case GOLD:
312 case SCROLL:
313 case POTION:
314 case STICK:
315 case RING:
316 case WEAPON:
317 case ARMOR:
318 case MM:
319 case FOOD:
320 if(!be_clear && levtype != POSTLEV)
321 return( &ret );
322 default:
323 break;
324 }
325 }
326 }
327 return( NULL );
328 }
329
330 /*
331 * findmindex:
332 * Find the index into the monster table of a monster given its name.
333 */
334
335 findmindex(name)
336 char *name;
337 {
338 int which;
339
340 for (which=1; which<NUMMONST; which++) {
341 if (strcmp(name, monsters[which].m_name) == 0)
342 break;
343 }
344 if (which >= NUMMONST) {
345 debug("couldn't find monster index");
346 which = 1;
347 }
348 return(which);
349 }
350
351 /*
352 * find_mons:
353 * Find the monster from his coordinates
354 */
355
356 struct linked_list *
357 find_mons(y, x)
358 register int y;
359 register int x;
360 {
361 register struct linked_list *item;
362 register struct thing *th;
363
364 for (item = mlist; item != NULL; item = next(item))
365 {
366 th = THINGPTR(item);
367 if (th->t_pos.y == y && th->t_pos.x == x)
368 return item;
369 }
370 return NULL;
371 }
372
373 /*