comparison arogue5/util.c @ 63:0ed67132cf10

Import Advanced Rogue 5.8 from the Roguelike Restoration Project (r1490)
author elwin
date Thu, 09 Aug 2012 22:58:48 +0000
parents
children c49f7927b0fa
comparison
equal deleted inserted replaced
62:0ef99244acb8 63:0ed67132cf10
1 /*
2 * all sorts of miscellaneous routines
3 *
4 * Advanced Rogue
5 * Copyright (C) 1984, 1985 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
19 /*
20 * aggravate:
21 * aggravate all the monsters on this level
22 */
23
24 aggravate()
25 {
26 register struct linked_list *mi;
27
28 for (mi = mlist; mi != NULL; mi = next(mi))
29 runto(THINGPTR(mi), &hero);
30 }
31
32 /*
33 * cansee:
34 * returns true if the hero can see a certain coordinate.
35 */
36
37 cansee(y, x)
38 register int y, x;
39 {
40 register struct room *rer;
41 register int radius;
42 coord tp;
43
44 if (on(player, ISBLIND))
45 return FALSE;
46
47 tp.y = y;
48 tp.x = x;
49 rer = roomin(&tp);
50
51 /* How far can we see? */
52 if (levtype == OUTSIDE) {
53 if (daytime) radius = 36;
54 else if (lit_room(rer)) radius = 9;
55 else radius = 3;
56 }
57 else radius = 3;
58
59 /*
60 * We can only see if the hero in the same room as
61 * the coordinate and the room is lit or if it is close.
62 */
63 return ((rer != NULL &&
64 levtype != OUTSIDE &&
65 (levtype != MAZELEV || /* Maze level needs direct line */
66 maze_view(tp.y, tp.x)) &&
67 rer == roomin(&hero) &&
68 lit_room(rer)) ||
69 DISTANCE(y, x, hero.y, hero.x) < radius);
70 }
71
72 /*
73 * check_level:
74 * Check to see if the guy has gone up a level.
75 *
76 * Return points needed to obtain next level.
77 *
78 * These are the beginning experience levels for all players.
79 * All further experience levels are computed by muliplying by 2
80 * up through MAXDOUBLE.
81 */
82 #define MAXDOUBLE 14 /* Maximum number of times score is doubled */
83 static struct {
84 long base; /* What it starts out at for doubling */
85 long cap; /* The maximum before doubling stops */
86 } e_levels[4] = {
87 /* You must change MAXDOUBLE if you change the cap figure */
88 { 90L, 1474560L }, /* Fighter */
89 { 130L, 2129920L }, /* Magician */
90 { 110L, 1802240L }, /* cleric */
91 { 75L, 1228800L } /* Thief */
92 };
93
94 long
95 check_level(get_spells)
96 bool get_spells;
97 {
98 register int i, j, add = 0;
99 register unsigned long exp;
100 long retval; /* Return value */
101 int nsides = 0;
102
103 /* See if we are past the doubling stage */
104 exp = e_levels[player.t_ctype].cap;
105 if (pstats.s_exp >= exp) {
106 i = pstats.s_exp/exp; /* First get amount above doubling area */
107 retval = exp + i * exp; /* Compute next higher boundary */
108 i += MAXDOUBLE; /* Add in the previous doubled levels */
109 }
110 else {
111 i = 0;
112 exp = e_levels[player.t_ctype].base;
113 while (exp <= pstats.s_exp) {
114 i++;
115 exp <<= 1;
116 }
117 retval = exp;
118 }
119 if (++i > pstats.s_lvl) {
120 switch (player.t_ctype) {
121 case C_FIGHTER: nsides = 10;
122 when C_MAGICIAN: nsides = 4;
123 when C_CLERIC: nsides = 8;
124 when C_THIEF: nsides = 6;
125 }
126
127 /* Take care of multi-level jumps */
128 for (j=0; j < (i-pstats.s_lvl); j++)
129 add += max(1, roll(1,nsides) + const_bonus());
130 max_stats.s_hpt += add;
131 if ((pstats.s_hpt += add) > max_stats.s_hpt)
132 pstats.s_hpt = max_stats.s_hpt;
133 sprintf(outstring,"Welcome, %s, to level %d",
134 cnames[player.t_ctype][min(i-1, 10)], i);
135 msg(outstring);
136 if (get_spells) {
137 pray_time = 0; /* A new round of prayers */
138 spell_power = 0; /* A new round of spells */
139 }
140 }
141 pstats.s_lvl = i;
142 return(retval);
143 }
144
145 /*
146 * Used to modify the playes strength
147 * it keeps track of the highest it has been, just in case
148 */
149
150 chg_str(amt)
151 register int amt;
152 {
153 register int ring_str; /* ring strengths */
154 register struct stats *ptr; /* for speed */
155
156 ptr = &pstats;
157 ring_str = ring_value(R_ADDSTR);
158 ptr->s_str -= ring_str;
159 ptr->s_str += amt;
160 if (ptr->s_str > 25)
161 ptr->s_str = 25;
162 if (ptr->s_str > max_stats.s_str)
163 max_stats.s_str = ptr->s_str;
164 ptr->s_str += ring_str;
165 if (ptr->s_str <= 0)
166 death(D_STRENGTH);
167 updpack(TRUE);
168 }
169
170 /*
171 * this routine computes the players current AC without dex bonus's
172 */
173 int
174 ac_compute()
175 {
176 register int ac;
177
178 ac = cur_armor != NULL ? cur_armor->o_ac : pstats.s_arm;
179 ac -= ring_value(R_PROTECT);
180 if (cur_misc[WEAR_BRACERS] != NULL)
181 ac -= cur_misc[WEAR_BRACERS]->o_ac;
182 if (cur_misc[WEAR_CLOAK] != NULL)
183 ac -= cur_misc[WEAR_CLOAK]->o_ac;
184
185 /* If player has the cloak, must be wearing it */
186 if (cur_relic[EMORI_CLOAK]) ac -= 5;
187
188 if (ac > 10)
189 ac = 10;
190 return(ac);
191 }
192
193 /*
194 * this routine computes the players current strength
195 */
196 str_compute()
197 {
198 if (cur_misc[WEAR_GAUNTLET] != NULL &&
199 cur_misc[WEAR_GAUNTLET]->o_which == MM_G_OGRE) {
200 if (cur_misc[WEAR_GAUNTLET]->o_flags & ISCURSED)
201 return (3);
202 else
203 return (18);
204 }
205 else
206 return (pstats.s_str);
207 }
208
209 /*
210 * this routine computes the players current dexterity
211 */
212 dex_compute()
213 {
214 if (cur_misc[WEAR_GAUNTLET] != NULL &&
215 cur_misc[WEAR_GAUNTLET]->o_which == MM_G_DEXTERITY) {
216 if (cur_misc[WEAR_GAUNTLET]->o_flags & ISCURSED)
217 return (3);
218 else
219 return (18);
220 }
221 else
222 return (pstats.s_dext);
223 }
224
225
226 /*
227 * diag_ok:
228 * Check to see if the move is legal if it is diagonal
229 */
230
231 diag_ok(sp, ep, flgptr)
232 register coord *sp, *ep;
233 struct thing *flgptr;
234 {
235 register int numpaths = 0;
236
237 /* Horizontal and vertical moves are always ok */
238 if (ep->x == sp->x || ep->y == sp->y)
239 return TRUE;
240
241 /* Diagonal moves are not allowed if there is a horizontal or
242 * vertical path to the destination
243 */
244 if (step_ok(ep->y, sp->x, MONSTOK, flgptr)) numpaths++;
245 if (step_ok(sp->y, ep->x, MONSTOK, flgptr)) numpaths++;
246 return(numpaths != 1);
247 }
248
249 /*
250 * eat:
251 * He wants to eat something, so let him try
252 */
253
254 eat()
255 {
256 register struct linked_list *item;
257
258 if ((item = get_item(pack, "eat", FOOD)) == NULL)
259 return;
260 if ((OBJPTR(item))->o_which == 1)
261 msg("My, that was a yummy %s", fruit);
262 else {
263 if (rnd(100) > 70) {
264 msg("Yuk, this food tastes awful");
265
266 /* Do a check for overflow before increasing experience */
267 if (pstats.s_exp + 1L > pstats.s_exp) pstats.s_exp++;
268 check_level(TRUE);
269 }
270 else
271 msg("Yum, that tasted good");
272 }
273 if ((food_left += HUNGERTIME + rnd(400) - 200) > STOMACHSIZE)
274 food_left = STOMACHSIZE;
275 del_pack(item);
276 hungry_state = F_OKAY;
277 updpack(TRUE);
278 }
279
280 /*
281 * pick a random position around the give (y, x) coordinates
282 */
283 coord *
284 fallpos(pos, be_clear, range)
285 register coord *pos;
286 bool be_clear;
287 int range;
288 {
289 register int tried, i, j;
290 register char ch;
291 static coord ret;
292 static short masks[] = {
293 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x100 };
294
295 /*
296 * Pick a spot at random centered on the position given by 'pos' and
297 * up to 'range' squares away from 'pos'
298 *
299 * If 'be_clear' is TRUE, the spot must be either FLOOR or PASSAGE
300 * inorder to be considered valid
301 *
302 *
303 * Generate a number from 0 to 8, representing the position to pick.
304 * Note that this DOES include the positon 'pos' itself
305 *
306 * If this position is not valid, mark it as 'tried', and pick another.
307 * Whenever a position is picked that has been tried before,
308 * sequentially find the next untried position. This eliminates costly
309 * random number generation
310 */
311
312 tried = 0;
313 while( tried != 0x1ff ) {
314 i = rnd(9);
315 while( tried & masks[i] )
316 i = (i + 1) % 9;
317
318 tried |= masks[i];
319
320 for( j = 1; j <= range; j++ ) {
321 ret.x = pos->x + j*grid[i].x;
322 ret.y = pos->y + j*grid[i].y;
323
324 if (ret.x == hero.x && ret.y == hero.y)
325 continue; /* skip the hero */
326
327 if (ret.x < 0 || ret.x > COLS - 1 ||
328 ret.y < 1 || ret.y > LINES - 3)
329 continue; /* off the screen? */
330
331 ch = CCHAR( winat(ret.y, ret.x) );
332
333 /*
334 * Check to make certain the spot is valid
335 */
336 switch( ch ) {
337 case FLOOR:
338 case PASSAGE:
339 return( &ret );
340 case GOLD:
341 case SCROLL:
342 case POTION:
343 case STICK:
344 case RING:
345 case WEAPON:
346 case ARMOR:
347 case MM:
348 case FOOD:
349 if(!be_clear && levtype != POSTLEV)
350 return( &ret );
351 default:
352 break;
353 }
354 }
355 }
356 return( NULL );
357 }
358
359
360 /*
361 * find_mons:
362 * Find the monster from his corrdinates
363 */
364
365 struct linked_list *
366 find_mons(y, x)
367 register int y;
368 register int x;
369 {
370 register struct linked_list *item;
371 register struct thing *th;
372
373 for (item = mlist; item != NULL; item = next(item))
374 {
375 th = THINGPTR(item);
376 if (th->t_pos.y == y && th->t_pos.x == x)
377 return item;
378 }
379 return NULL;
380 }
381
382 /*
383