rogue

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

Neale Pickett  ·  2011-10-13

master.c

  1/*
  2 * Hero movement commands
  3 *
  4 * @(#)master.c	4.49 (Berkeley) 02/05/99
  5 */
  6
  7#include <curses.h>
  8#include <ctype.h>
  9#include "netprot.h"
 10
 11/*
 12 * Used to hold the new Hero position
 13 */
 14
 15coord nh;
 16
 17/*
 18 * do_run:
 19 *	Start the hero running
 20 */
 21void
 22do_run(char ch)
 23{
 24    Running = TRUE;
 25    After = FALSE;
 26    Runch = ch;
 27}
 28
 29/*
 30 * do_move:
 31 *	Check to see that a move is legal.  If it is handle the
 32 * consequences (fighting, picking up, etc.)
 33 */
 34void
 35do_move(int dy, int dx)
 36{
 37    char ch, fl;
 38
 39    Firstmove = FALSE;
 40    if (No_move)
 41    {
 42	No_move--;
 43	msg("you are still stuck in the bear trap");
 44	return;
 45    }
 46    /*
 47     * Do a confused move (maybe)
 48     */
 49    if (on(Player, ISHUH) && rnd(5) != 0)
 50    {
 51	nh = *rndmove(&Player);
 52	if (ce(nh, Hero))
 53	{
 54	    After = FALSE;
 55	    Running = FALSE;
 56	    To_death = FALSE;
 57	    return;
 58	}
 59    }
 60    else
 61    {
 62over:
 63	nh.y = Hero.y + dy;
 64	nh.x = Hero.x + dx;
 65    }
 66
 67    /*
 68     * Check if he tried to move off the screen or make an illegal
 69     * diagonal move, and stop him if he did.
 70     */
 71    if (nh.x < 0 || nh.x >= NUMCOLS || nh.y <= 0 || nh.y >= NUMLINES - 1)
 72	goto hit_bound;
 73    if (!diag_ok(&Hero, &nh))
 74    {
 75	After = FALSE;
 76	Running = FALSE;
 77	return;
 78    }
 79    if (Running && ce(Hero, nh))
 80	After = Running = FALSE;
 81    fl = flat(nh.y, nh.x);
 82    ch = winat(nh.y, nh.x);
 83    if (!(fl & F_REAL) && ch == FLOOR)
 84    {
 85	if (!on(Player, ISLEVIT))
 86	{
 87	    chat(nh.y, nh.x) = ch = TRAP;
 88	    flat(nh.y, nh.x) |= F_REAL;
 89	}
 90    }
 91    else if (on(Player, ISHELD) && ch != 'F')
 92    {
 93	msg("you are being held");
 94	return;
 95    }
 96    switch (ch)
 97    {
 98	case ' ':
 99	case '|':
100	case '-':
101hit_bound:
102	    if (Passgo && Running && (Proom->r_flags & ISGONE)
103		&& !on(Player, ISBLIND))
104	    {
105		bool	b1, b2;
106
107		switch (Runch)
108		{
109		    case 'h':
110		    case 'l':
111			b1 = (Hero.y != 1 && turn_ok(Hero.y - 1, Hero.x));
112			b2 = (Hero.y != NUMLINES - 2 && turn_ok(Hero.y + 1, Hero.x));
113			if (!(b1 ^ b2))
114			    break;
115			if (b1)
116			{
117			    Runch = 'k';
118			    dy = -1;
119			}
120			else
121			{
122			    Runch = 'j';
123			    dy = 1;
124			}
125			dx = 0;
126			turnref();
127			goto over;
128		    case 'j':
129		    case 'k':
130			b1 = (Hero.x != 0 && turn_ok(Hero.y, Hero.x - 1));
131			b2 = (Hero.x != NUMCOLS - 1 && turn_ok(Hero.y, Hero.x + 1));
132			if (!(b1 ^ b2))
133			    break;
134			if (b1)
135			{
136			    Runch = 'h';
137			    dx = -1;
138			}
139			else
140			{
141			    Runch = 'l';
142			    dx = 1;
143			}
144			dy = 0;
145			turnref();
146			goto over;
147		}
148	    }
149	    Running = FALSE;
150	    After = FALSE;
151	    break;
152	case DOOR:
153	    Running = FALSE;
154	    if (flat(Hero.y, Hero.x) & F_PASS)
155		enter_room(&nh);
156	    goto move_stuff;
157	case TRAP:
158	    ch = be_trapped(&nh);
159	    if (ch == T_DOOR || ch == T_TELEP)
160		return;
161	    goto move_stuff;
162	case PASSAGE:
163	    /*
164	     * when you're in a corridor, you don't know if you're in
165	     * a maze room or not, and there ain't no way to find out
166	     * if you're leaving a maze room, so it is necessary to
167	     * always recalculate Proom.
168	     */
169	    Proom = roomin(&Hero);
170	    goto move_stuff;
171	case FLOOR:
172	    if (!(fl & F_REAL))
173		be_trapped(&Hero);
174	    goto move_stuff;
175	case STAIRS:
176	    Seenstairs = TRUE;
177	    /* FALLTHROUGH */
178	default:
179	    Running = FALSE;
180	    if (isupper(ch) || moat(nh.y, nh.x))
181		fight(&nh, Cur_weapon, FALSE);
182	    else
183	    {
184		if (ch != STAIRS)
185		    Take = ch;
186move_stuff:
187		mvaddch(Hero.y, Hero.x, floor_at());
188		if ((fl & F_PASS) && chat(Oldpos.y, Oldpos.x) == DOOR)
189		    leave_room(&nh);
190		Hero = nh;
191	    }
192    }
193}
194
195/*
196 * turn_ok:
197 *	Decide whether it is legal to turn onto the given space
198 */
199bool
200turn_ok(int y, int x)
201{
202    PLACE *pp;
203
204    pp = INDEX(y, x);
205    return (pp->p_ch == DOOR
206	|| (pp->p_flags & (F_REAL|F_PASS)) == (F_REAL|F_PASS));
207}
208
209/*
210 * turnref:
211 *	Decide whether to refresh at a passage turning or not
212 */
213void
214turnref(void)
215{
216    PLACE *pp;
217
218    pp = INDEX(Hero.y, Hero.x);
219    if (!(pp->p_flags & F_SEEN))
220    {
221	if (Jump)
222	{
223	    leaveok(stdscr, TRUE);
224	    refresh();
225	    leaveok(stdscr, FALSE);
226	}
227	pp->p_flags |= F_SEEN;
228    }
229}
230
231/*
232 * door_open:
233 *	Called to illuminate a room.  If it is dark, remove anything
234 *	that might move.
235 */
236void
237door_open(struct room *rp)
238{
239    THING *mp;
240    int y, x;
241
242    if (!(rp->r_flags & ISGONE))
243	for (y = rp->r_pos.y; y < rp->r_pos.y + rp->r_max.y; y++)
244	    for (x = rp->r_pos.x; x < rp->r_pos.x + rp->r_max.x; x++)
245		if (isupper(winat(y, x)))
246		    wake_monster(y, x);
247}
248
249/*
250 * be_trapped:
251 *	The guy stepped on a trap.... Make him pay.
252 */
253char
254be_trapped(coord *tc)
255{
256    PLACE *pp;
257    THING *arrow;
258    char tr;
259
260    if (on(Player, ISLEVIT))
261	return T_RUST;	/* anything that's not a door or teleport */
262    Running = FALSE;
263    Count = FALSE;
264    pp = INDEX(tc->y, tc->x);
265    pp->p_ch = TRAP;
266    tr = pp->p_flags & F_TMASK;
267    pp->p_flags |= F_SEEN;
268    switch (tr)
269    {
270	when T_DOOR:
271	    Level++;
272	    new_level();
273	    msg("you fell into a trap!");
274	when T_BEAR:
275	    No_move += BEARTIME;
276	    msg("you are caught in a bear trap");
277	when T_SLEEP:
278	    No_command += SLEEPTIME;
279	    Player.t_flags &= ~ISRUN;
280	    msg("a strange white mist envelops you and you fall asleep");
281	when T_ARROW:
282	    if (swing(Pstats.s_lvl - 1, Pstats.s_arm, 1))
283	    {
284		Pstats.s_hpt -= roll(1, 6);
285		if (Pstats.s_hpt <= 0)
286		{
287		    msg("an arrow killed you");
288		    death('a');
289		}
290		else
291		    msg("oh no! An arrow shot you");
292	    }
293	    else
294	    {
295		arrow = new_item();
296		init_weapon(arrow, ARROW);
297		arrow->o_count = 1;
298		arrow->o_pos = Hero;
299		fall(arrow, FALSE);
300		msg("an arrow shoots past you");
301	    }
302	when T_TELEP:
303	    /*
304	     * since the hero's leaving, look() won't put a TRAP
305	     * down for us, so we have to do it ourself
306	     */
307	    teleport();
308	    mvaddch(tc->y, tc->x, TRAP);
309	when T_DART:
310	    if (!swing(Pstats.s_lvl+1, Pstats.s_arm, 1))
311		msg("a small dart whizzes by your ear and vanishes");
312	    else
313	    {
314		Pstats.s_hpt -= roll(1, 4);
315		if (Pstats.s_hpt <= 0)
316		{
317		    msg("a poisoned dart killed you");
318		    death('d');
319		}
320		if (!ISWEARING(R_SUSTSTR) && !save(VS_POISON))
321		    chg_str(-1);
322		msg("a small dart just hit you in the shoulder");
323	    }
324	when T_RUST:
325	    msg("a gush of water hits you on the head");
326	    rust_armor(Cur_armor);
327    }
328    flush_type();
329    return tr;
330}
331
332/*
333 * rndmove:
334 *	Move in a random direction if the monster/person is confused
335 */
336coord *
337rndmove(THING *who)
338{
339    THING *obj;
340    int x, y;
341    char ch;
342    coord ret;  /* what we will be returning */
343
344    y = ret.y = who->t_pos.y + rnd(3) - 1;
345    x = ret.x = who->t_pos.x + rnd(3) - 1;
346    /*
347     * Now check to see if that's a legal move.  If not, don't move.
348     * (I.e., bump into the wall or whatever)
349     */
350    if (y == who->t_pos.y && x == who->t_pos.x)
351	return &ret;
352    if (!diag_ok(&who->t_pos, &ret))
353	goto bad;
354    else
355    {
356	ch = winat(y, x);
357	if (!step_ok(ch))
358	    goto bad;
359	if (ch == SCROLL)
360	{
361	    for (obj = Lvl_obj; obj != NULL; obj = next(obj))
362		if (y == obj->o_pos.y && x == obj->o_pos.x)
363		    break;
364	    if (obj != NULL && obj->o_which == S_SCARE)
365		goto bad;
366	}
367    }
368    return &ret;
369
370bad:
371    ret = who->t_pos;
372    return &ret;
373}
374
375/*
376 * rust_armor:
377 *	Rust the given armor, if it is a legal kind to rust, and we
378 *	aren't wearing a magic ring.
379 */
380void
381rust_armor(THING *arm)
382{
383    if (arm == NULL || arm->o_type != ARMOR || arm->o_which == LEATHER ||
384	arm->o_arm >= 9)
385	    return;
386
387    if ((arm->o_flags & ISPROT) || ISWEARING(R_SUSTARM))
388    {
389	if (!To_death)
390	    msg("the rust vanishes instantly");
391    }
392    else
393    {
394	arm->o_arm++;
395	if (!Terse)
396	    msg("your armor appears to be weaker now. Oh my!");
397	else
398	    msg("your armor weakens");
399    }
400}