comparison arogue7/util.c @ 125:adfa37e67084

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