Annotation of early-roguelike/rogue4/monsters.c, Revision 1.1.1.1
1.1 rubenllo 1: /*
2: * File with various monster functions in it
3: *
4: * @(#)monsters.c 4.24 (Berkeley) 4/6/82
5: *
6: * Rogue: Exploring the Dungeons of Doom
7: * Copyright (C) 1980, 1981, 1982 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 <ctype.h>
16: #include "rogue.h"
17:
18: int exp_add(THING *tp);
19:
20: /*
21: * List of monsters in rough order of vorpalness
22: *
23: * NOTE: This not initialized using strings so that xstr doesn't set up
24: * the string not to be saved. Otherwise genocide is lost through
25: * saving a game.
26: */
27: char lvl_mons[] = {
28: 'K', 'J', 'B', 'S', 'H', 'E', 'A', 'O', 'Z', 'G', 'L', 'C', 'R',
29: 'Q', 'N', 'Y', 'T', 'W', 'F', 'I', 'X', 'U', 'M', 'V', 'P', 'D',
30: '\0'
31: };
32:
33: char wand_mons[] = {
34: 'K', 'J', 'B', 'S', 'H', ' ', 'A', 'O', 'Z', 'G', ' ', 'C', 'R',
35: 'Q', ' ', 'Y', 'T', 'W', ' ', 'I', 'X', 'U', ' ', 'V', 'P', ' ',
36: '\0'
37: };
38:
39: /*
40: * randmonster:
41: * Pick a monster to show up. The lower the level,
42: * the meaner the monster.
43: */
44: char
45: randmonster(bool wander)
46: {
47: register int d;
48: register char *mons;
49:
50: mons = wander ? wand_mons : lvl_mons;
51: do
52: {
53: d = level + (rnd(10) - 5);
54: if (d < 1)
55: d = rnd(5) + 1;
56: if (d > 26)
57: d = rnd(5) + 22;
58: } while (mons[--d] == ' ');
59: return mons[d];
60: }
61:
62: /*
63: * new_monster:
64: * Pick a new monster and add it to the list
65: */
66: void
67: new_monster(THING *tp, char type, coord *cp)
68: {
69: register struct monster *mp;
70: register int lev_add;
71:
72: if ((lev_add = level - AMULETLEVEL) < 0)
73: lev_add = 0;
74: attach(mlist, tp);
75: tp->t_type = type;
76: tp->t_disguise = type;
77: tp->t_pos = *cp;
78: tp->t_oldch = mvinch(cp->y, cp->x);
79: tp->t_room = roomin(cp);
80: moat(cp->y, cp->x) = tp;
81: mp = &monsters[tp->t_type-'A'];
82: tp->t_stats.s_lvl = mp->m_stats.s_lvl + lev_add;
83: tp->t_stats.s_maxhp = tp->t_stats.s_hpt = roll(tp->t_stats.s_lvl, 8);
84: tp->t_stats.s_arm = mp->m_stats.s_arm - lev_add;
85: strncpy(tp->t_stats.s_dmg,mp->m_stats.s_dmg,16);
86: tp->t_stats.s_str = mp->m_stats.s_str;
87: tp->t_stats.s_exp = mp->m_stats.s_exp + lev_add * 10 + exp_add(tp);
88: tp->t_flags = mp->m_flags;
89: tp->t_turn = TRUE;
90: tp->t_pack = NULL;
91: if (ISWEARING(R_AGGR))
92: runto(cp, &hero);
93: if (type == 'M')
94: switch (rnd(level > 25 ? 9 : 8))
95: {
96: case 0: tp->t_disguise = GOLD;
97: when 1: tp->t_disguise = POTION;
98: when 2: tp->t_disguise = SCROLL;
99: when 3: tp->t_disguise = STAIRS;
100: when 4: tp->t_disguise = WEAPON;
101: when 5: tp->t_disguise = ARMOR;
102: when 6: tp->t_disguise = RING;
103: when 7: tp->t_disguise = STICK;
104: when 8: tp->t_disguise = AMULET;
105: }
106: }
107:
108: /*
109: * expadd:
110: * Experience to add for this monster's level/hit points
111: */
112: int
113: exp_add(THING *tp)
114: {
115: register int mod;
116:
117: if (tp->t_stats.s_lvl == 1)
118: mod = tp->t_stats.s_maxhp / 8;
119: else
120: mod = tp->t_stats.s_maxhp / 6;
121: if (tp->t_stats.s_lvl > 9)
122: mod *= 20;
123: else if (tp->t_stats.s_lvl > 6)
124: mod *= 4;
125: return mod;
126: }
127:
128: /*
129: * wanderer:
130: * Create a new wandering monster and aim it at the player
131: */
132: void
133: wanderer(void)
134: {
135: register int i;
136: register struct room *rp;
137: register THING *tp;
138: coord cp = {0,0};
139: register int cnt = 0;
140:
141: tp = new_item();
142: do
143: {
144: /* Avoid endless loop when all rooms are filled with monsters
145: * and the player room is not accessible to the monsters.
146: */
147: if (cnt++ >= 500)
148: {
149: discard(tp);
150: return;
151: }
152: i = rnd_room();
153: if ((rp = &rooms[i]) == proom)
154: continue;
155: rnd_pos(rp, &cp);
156: } until (rp != proom && step_ok(winat(cp.y, cp.x)));
157: new_monster(tp, randmonster(TRUE), &cp);
158: runto(&tp->t_pos, &hero);
159: #ifdef WIZARD
160: if (wizard)
161: msg("started a wandering %s", monsters[tp->t_type-'A'].m_name);
162: #endif
163: }
164:
165: /*
166: * wake_monster:
167: * What to do when the hero steps next to a monster
168: */
169: THING *
170: wake_monster(int y, int x)
171: {
172: register THING *tp;
173: register struct room *rp;
174: register char ch;
175:
176: #ifdef WIZARD
177: if ((tp = moat(y, x)) == NULL)
178: msg("can't find monster in wake_monster");
179: #else
180: tp = moat(y, x);
181: #endif
182: ch = tp->t_type;
183: /*
184: * Every time he sees mean monster, it might start chasing him
185: */
186: if (!on(*tp, ISRUN) && rnd(3) != 0 && on(*tp, ISMEAN) && !on(*tp, ISHELD)
187: && !ISWEARING(R_STEALTH))
188: {
189: tp->t_dest = &hero;
190: tp->t_flags |= ISRUN;
191: }
192: if (ch == 'U' && !on(player, ISBLIND) && !on(*tp, ISFOUND)
193: && !on(*tp, ISCANC) && on(*tp, ISRUN))
194: {
195: rp = proom;
196: if ((rp != NULL && !(rp->r_flags & ISDARK))
197: || DISTANCE(y, x, hero.y, hero.x) < LAMPDIST)
198: {
199: tp->t_flags |= ISFOUND;
200: if (!save(VS_MAGIC))
201: {
202: if (on(player, ISHUH))
203: lengthen(unconfuse, rnd(20) + HUHDURATION);
204: else
205: fuse(unconfuse, 0, rnd(20) + HUHDURATION, AFTER);
206: player.t_flags |= ISHUH;
207: msg("the umber hulk's gaze has confused you");
208: }
209: }
210: }
211: /*
212: * Let greedy ones guard gold
213: */
214: if (on(*tp, ISGREED) && !on(*tp, ISRUN))
215: {
216: tp->t_flags |= ISRUN;
217: if (proom->r_goldval)
218: tp->t_dest = &proom->r_gold;
219: else
220: tp->t_dest = &hero;
221: }
222: return tp;
223: }
224:
225: /*
226: * genocide:
227: * Wipe one monster out of existence (for now...)
228: */
229: void
230: genocide(void)
231: {
232: register THING *mp;
233: register char c;
234: register int i;
235: register THING *nmp;
236:
237: addmsg("which monster");
238: if (!terse)
239: addmsg(" do you wish to wipe out");
240: msg("? ");
241: while (!isalpha(c = readchar()))
242: if (c == ESCAPE)
243: return;
244: else
245: {
246: mpos = 0;
247: msg("please specifiy a letter between 'A' and 'Z'");
248: }
249: mpos = 0;
250: if (islower(c))
251: c = toupper(c);
252: for (mp = mlist; mp; mp = nmp)
253: {
254: nmp = next(mp);
255: if (mp->t_type == c)
256: remove_monster(&mp->t_pos, mp, FALSE);
257: }
258: for (i = 0; i < 26; i++)
259: if (lvl_mons[i] == c)
260: {
261: lvl_mons[i] = ' ';
262: wand_mons[i] = ' ';
263: break;
264: }
265: if (!terse)
266: addmsg("there will be ");
267: msg("no more %ss", monsters[c - 'A'].m_name);
268: }
269:
270: /*
271: * give_pack:
272: * Give a pack to a monster if it deserves one
273: */
274: void
275: give_pack(THING *tp)
276: {
277: if (rnd(100) < monsters[tp->t_type-'A'].m_carry)
278: attach(tp->t_pack, new_thing());
279: }
CVSweb