Annotation of early-roguelike/rogue5/monsters.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: * File with various monster functions in it
3: *
4: * @(#)monsters.c 4.46 (Berkeley) 02/05/99
5: *
6: * Rogue: Exploring the Dungeons of Doom
7: * Copyright (C) 1980-1983, 1985, 1999 Michael Toy, Ken Arnold and Glenn Wichman
8: * All rights reserved.
9: *
10: * See the file LICENSE.TXT for full copyright and licensing information.
11: */
12:
13: #include <curses.h>
14: #include <string.h>
15: #include "rogue.h"
16: #include <ctype.h>
17:
18: /*
19: * List of monsters in rough order of vorpalness
20: */
21: static const int lvl_mons[] = {
22: 'K', 'E', 'B', 'S', 'H', 'I', 'R', 'O', 'Z', 'L', 'C', 'Q', 'A',
23: 'N', 'Y', 'F', 'T', 'W', 'P', 'X', 'U', 'M', 'V', 'G', 'J', 'D'
24: };
25:
26: static const int wand_mons[] = {
27: 'K', 'E', 'B', 'S', 'H', 0, 'R', 'O', 'Z', 0, 'C', 'Q', 'A',
28: 0, 'Y', 0, 'T', 'W', 'P', 0, 'U', 'M', 'V', 'G', 'J', 0
29: };
30:
31: /*
32: * randmonster:
33: * Pick a monster to show up. The lower the level,
34: * the meaner the monster.
35: */
36: int
37: randmonster(int wander)
38: {
39: int d;
40: const int *mons;
41:
42: mons = (wander ? wand_mons : lvl_mons);
43: do
44: {
45: d = level + (rnd(10) - 6);
46: if (d < 0)
47: d = rnd(5);
48: if (d > 25)
49: d = rnd(5) + 21;
50: } while (mons[d] == 0);
51: return mons[d];
52: }
53:
54: /*
55: * new_monster:
56: * Pick a new monster and add it to the list
57: */
58:
59: void
60: new_monster(THING *tp, int type, const coord *cp)
61: {
62: struct monster *mp;
63: int lev_add;
64:
65: if ((lev_add = level - AMULETLEVEL) < 0)
66: lev_add = 0;
67: attach(mlist, tp);
68: tp->t_type = type;
69: tp->t_disguise = type;
70: tp->t_pos = *cp;
71: move(cp->y, cp->x);
72: tp->t_oldch = CCHAR( inch() );
73: tp->t_room = roomin(cp);
74: moat(cp->y, cp->x) = tp;
75: mp = &monsters[tp->t_type-'A'];
76: tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add;
77: tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8);
78: tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add;
79: strcpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg);
80: tp->t_stats.s_str = mp->m_stats.s_str;
81: tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp);
82: tp->t_flags = mp->m_flags;
83: if (level > 29)
84: tp->t_flags |= ISHASTE;
85: tp->t_turn = TRUE;
86: tp->t_pack = NULL;
87: if (ISWEARING(R_AGGR))
88: runto(cp);
89: if (type == 'X')
90: tp->t_disguise = rnd_thing();
91: }
92:
93: /*
94: * expadd:
95: * Experience to add for this monster's level/hit points
96: */
97: int
98: exp_add(const THING *tp)
99: {
100: int mod;
101:
102: if (tp->t_stats.s_lvl == 1)
103: mod = tp->t_stats.s_maxhp / 8;
104: else
105: mod = tp->t_stats.s_maxhp / 6;
106: if (tp->t_stats.s_lvl > 9)
107: mod *= 20;
108: else if (tp->t_stats.s_lvl > 6)
109: mod *= 4;
110: return mod;
111: }
112:
113: /*
114: * wanderer:
115: * Create a new wandering monster and aim it at the player
116: */
117:
118: void
119: wanderer(void)
120: {
121: THING *tp;
122: coord cp;
123: int cnt = 0;
124:
125: tp = new_item();
126: do
127: {
128: /* Avoid endless loop when all rooms are filled with monsters
129: * and the player room is not accessible to the monsters.
130: */
131: if (cnt++ >= 500)
132: {
133: discard(tp);
134: return;
135: }
136: find_floor(NULL, &cp, FALSE, TRUE);
137: } while (roomin(&cp) == proom && moat(cp.y, cp.x) == NULL);
138: new_monster(tp, randmonster(TRUE), &cp);
139: if (on(player, SEEMONST))
140: {
141: standout();
142: if (!on(player, ISHALU))
143: addch(tp->t_type);
144: else
145: addch(rnd(26) + 'A');
146: standend();
147: }
148: runto(&tp->t_pos);
149: #ifdef MASTER
150: if (wizard)
151: msg("started a wandering %s", monsters[tp->t_type-'A'].m_name);
152: #endif
153: }
154:
155: /*
156: * wake_monster:
157: * What to do when the hero steps next to a monster
158: */
159: const THING *
160: wake_monster(int y, int x)
161: {
162: THING *tp;
163: struct room *rp;
164: int ch;
165: const char *mname;
166:
167: if ((tp = moat(y, x)) == NULL) {
168: #ifdef MASTER
169: msg("can't find monster in wake_monster");
170: #endif
171: return NULL;
172: }
173:
174: ch = tp->t_type;
175: /*
176: * Every time he sees mean monster, it might start chasing him
177: */
178: if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD)
179: && !ISWEARING(R_STEALTH) && !on(player, ISLEVIT))
180: {
181: tp->t_dest = &hero;
182: tp->t_flags |= ISRUN;
183: }
184: if (ch == 'M' && !on(player, ISBLIND) && !on(player, ISHALU)
185: && !on(*tp, ISFOUND) && !on(*tp, ISCANC) && on(*tp, ISRUN))
186: {
187: rp = proom;
188: if ((rp != NULL && !(rp->r_flags & ISDARK))
189: || dist(y, x, hero.y, hero.x) < LAMPDIST)
190: {
191: tp->t_flags |= ISFOUND;
192: if (!save(VS_MAGIC))
193: {
194: if (on(player, ISHUH))
195: lengthen(unconfuse, spread(HUHDURATION));
196: else
197: fuse(unconfuse, 0, spread(HUHDURATION), AFTER);
198: player.t_flags |= ISHUH;
199: mname = set_mname(tp);
200: addmsg("%s", mname);
201: if (strcmp(mname, "it") != 0)
202: addmsg("'");
203: msg("s gaze has confused you");
204: }
205: }
206: }
207: /*
208: * Let greedy ones guard gold
209: */
210: if (on(*tp, ISGREED) && !on(*tp, ISRUN))
211: {
212: tp->t_flags |= ISRUN;
213: if (proom->r_goldval)
214: tp->t_dest = &proom->r_gold;
215: else
216: tp->t_dest = &hero;
217: }
218: return tp;
219: }
220:
221: /*
222: * give_pack:
223: * Give a pack to a monster if it deserves one
224: */
225:
226: void
227: give_pack(THING *tp)
228: {
229: if (level >= max_level && rnd(100) < monsters[tp->t_type-'A'].m_carry)
230: attach(tp->t_pack, new_thing());
231: }
232:
233: /*
234: * save_throw:
235: * See if a creature save against something
236: */
237: int
238: save_throw(int which, const THING *tp)
239: {
240: int need;
241:
242: need = 14 + which - tp->t_stats.s_lvl / 2;
243: return (roll(1, 20) >= need);
244: }
245:
246: /*
247: * save:
248: * See if he saves against various nasty things
249: */
250: int
251: save(int which)
252: {
253: if (which == VS_MAGIC)
254: {
255: if (ISRING(LEFT, R_PROTECT))
256: which -= cur_ring[LEFT]->o_arm;
257: if (ISRING(RIGHT, R_PROTECT))
258: which -= cur_ring[RIGHT]->o_arm;
259: }
260: return save_throw(which, &player);
261: }
CVSweb