rogue

Ken Arnold's Rogue
git clone https://git.woozle.org/neale/rogue.git

Neale Pickett  ·  2011-10-13

rexec.c

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