diff rogue3/move.c @ 0:527e2150eaf0

Import Rogue 3.6 from the Roguelike Restoration Project (r1490)
author edwarj4
date Tue, 13 Oct 2009 13:33:34 +0000
parents
children d9e44e18eeec
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rogue3/move.c	Tue Oct 13 13:33:34 2009 +0000
@@ -0,0 +1,384 @@
+/*
+ * Hero movement commands
+ *
+ * @(#)move.c	3.26 (Berkeley) 6/15/81
+ *
+ * Rogue: Exploring the Dungeons of Doom
+ * Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman
+ * All rights reserved.
+ *
+ * See the file LICENSE.TXT for full copyright and licensing information.
+ */
+
+#include "curses.h"
+#include <ctype.h>
+#include "rogue.h"
+
+/*
+ * Used to hold the new hero position
+ */
+
+coord nh;
+
+/*
+ * do_run:
+ *	Start the hero running
+ */
+
+void
+do_run(int ch)
+{
+    running = TRUE;
+    after = FALSE;
+    runch = ch;
+}
+
+/*
+ * do_move:
+ *	Check to see that a move is legal.  If it is handle the
+ * consequences (fighting, picking up, etc.)
+ */
+
+void
+do_move(int dy, int dx)
+{
+    int ch;
+
+    firstmove = FALSE;
+    if (no_move)
+    {
+	no_move--;
+	msg("You are still stuck in the bear trap");
+	return;
+    }
+    /*
+     * Do a confused move (maybe)
+     */
+    if (rnd(100) < 80 && on(player, ISHUH))
+	nh = *rndmove(&player);
+    else
+    {
+	nh.y = hero.y + dy;
+	nh.x = hero.x + dx;
+    }
+
+    /*
+     * Check if he tried to move off the screen or make an illegal
+     * diagonal move, and stop him if he did.
+     */
+    if (nh.x < 0 || nh.x > COLS-1 || nh.y < 0 || nh.y > LINES - 1
+	|| !diag_ok(&hero, &nh))
+    {
+	after = FALSE;
+	running = FALSE;
+	return;
+    }
+    if (running && ce(hero, nh))
+	after = running = FALSE;
+    ch = winat(nh.y, nh.x);
+    if (on(player, ISHELD) && ch != 'F')
+    {
+	msg("You are being held");
+	return;
+    }
+    switch(ch)
+    {
+	case ' ':
+	case '|':
+	case '-':
+	case SECRETDOOR:
+	    after = running = FALSE;
+	    return;
+	case TRAP:
+	    ch = be_trapped(&nh);
+	    if (ch == TRAPDOOR || ch == TELTRAP)
+		return;
+	    goto move_stuff;
+	case GOLD:
+	case POTION:
+	case SCROLL:
+	case FOOD:
+	case WEAPON:
+	case ARMOR:
+	case RING:
+	case AMULET:
+	case STICK:
+	    running = FALSE;
+	    take = ch;
+	default:
+move_stuff:
+	    if (ch == PASSAGE && winat(hero.y, hero.x) == DOOR)
+		light(&hero);
+	    else if (ch == DOOR)
+	    {
+		running = FALSE;
+		if (winat(hero.y, hero.x) == PASSAGE)
+		    light(&nh);
+	    }
+	    else if (ch == STAIRS)
+		running = FALSE;
+	    else if (isupper(ch))
+	    {
+		running = FALSE;
+		fight(&nh, ch, cur_weapon, FALSE);
+		return;
+	    }
+	    ch = winat(hero.y, hero.x);
+	    wmove(cw, unc(hero));
+	    waddch(cw, ch);
+	    hero = nh;
+	    wmove(cw, unc(hero));
+	    waddch(cw, PLAYER);
+    }
+}
+
+/*
+ * Called to illuminate a room.
+ * If it is dark, remove anything that might move.
+ */
+
+void
+light(coord *cp)
+{
+    struct room *rp;
+    int j, k;
+    int ch;
+    int rch;
+    struct linked_list *item;
+
+    if ((rp = roomin(cp)) != NULL && !on(player, ISBLIND))
+    {
+	for (j = 0; j < rp->r_max.y; j++)
+	{
+	    for (k = 0; k < rp->r_max.x; k++)
+	    {
+		ch = show(rp->r_pos.y + j, rp->r_pos.x + k);
+		wmove(cw, rp->r_pos.y + j, rp->r_pos.x + k);
+		/*
+		 * Figure out how to display a secret door
+		 */
+		if (ch == SECRETDOOR)
+		{
+		    if (j == 0 || j == rp->r_max.y - 1)
+			ch = '-';
+		    else
+			ch = '|';
+		}
+		/*
+		 * If the room is a dark room, we might want to remove
+		 * monsters and the like from it (since they might
+		 * move)
+		 */
+		if (isupper(ch))
+		{
+		    item = wake_monster(rp->r_pos.y+j, rp->r_pos.x+k);
+		    if (((struct thing *) ldata(item))->t_oldch == ' ')
+			if (!(rp->r_flags & ISDARK))
+			    ((struct thing *) ldata(item))->t_oldch =
+				mvwinch(stdscr, rp->r_pos.y+j, rp->r_pos.x+k);
+		}
+		if (rp->r_flags & ISDARK)
+		{
+		    rch = mvwinch(cw, rp->r_pos.y+j, rp->r_pos.x+k);
+		    switch (rch)
+		    {
+			case DOOR:
+			case STAIRS:
+			case TRAP:
+			case '|':
+			case '-':
+			case ' ':
+			    ch = rch;
+			when FLOOR:
+			    ch = (on(player, ISBLIND) ? FLOOR : ' ');
+			otherwise:
+			    ch = ' ';
+		    }
+		}
+		mvwaddch(cw, rp->r_pos.y+j, rp->r_pos.x+k, ch);
+	    }
+	}
+    }
+}
+
+/*
+ * show:
+ *	returns what a certain thing will display as to the un-initiated
+ */
+
+int
+show(int y, int x)
+{
+    int ch = winat(y, x);
+    struct linked_list *it;
+    struct thing *tp;
+
+    if (ch == TRAP)
+	return (trap_at(y, x)->tr_flags & ISFOUND) ? TRAP : FLOOR;
+    else if (ch == 'M' || ch == 'I')
+    {
+	if ((it = find_mons(y, x)) == NULL)
+	    fatal("Can't find monster in show");
+	tp = (struct thing *) ldata(it);
+	if (ch == 'M')
+	    ch = tp->t_disguise;
+	/*
+	 * Hide invisible monsters
+	 */
+	else if (off(player, CANSEE))
+	    ch = mvwinch(stdscr, y, x);
+    }
+    return ch;
+}
+
+/*
+ * be_trapped:
+ *	The guy stepped on a trap.... Make him pay.
+ */
+
+int
+be_trapped(coord *tc)
+{
+    struct trap *tp;
+    int ch;
+
+    tp = trap_at(tc->y, tc->x);
+    count = running = FALSE;
+    mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, TRAP);
+    tp->tr_flags |= ISFOUND;
+    switch (ch = tp->tr_type)
+    {
+	case TRAPDOOR:
+	    level++;
+	    new_level();
+	    msg("You fell into a trap!");
+	when BEARTRAP:
+	    no_move += BEARTIME;
+	    msg("You are caught in a bear trap");
+	when SLEEPTRAP:
+	    no_command += SLEEPTIME;
+	    msg("A strange white mist envelops you and you fall asleep");
+	when ARROWTRAP:
+	    if (swing(pstats.s_lvl-1, pstats.s_arm, 1))
+	    {
+		msg("Oh no! An arrow shot you");
+		if ((pstats.s_hpt -= roll(1, 6)) <= 0)
+		{
+		    msg("The arrow killed you.");
+		    death('a');
+		}
+	    }
+	    else
+	    {
+		struct linked_list *item;
+		struct object *arrow;
+
+		msg("An arrow shoots past you.");
+		item = new_item(sizeof *arrow);
+		arrow = (struct object *) ldata(item);
+		arrow->o_type = WEAPON;
+		arrow->o_which = ARROW;
+		init_weapon(arrow, ARROW);
+		arrow->o_count = 1;
+		arrow->o_pos = hero;
+		arrow->o_hplus = arrow->o_dplus = 0; /* "arrow bug" FIX */
+		fall(item, FALSE);
+	    }
+	when TELTRAP:
+	    teleport();
+	when DARTTRAP:
+	    if (swing(pstats.s_lvl+1, pstats.s_arm, 1))
+	    {
+		msg("A small dart just hit you in the shoulder");
+		if ((pstats.s_hpt -= roll(1, 4)) <= 0)
+		{
+		    msg("The dart killed you.");
+		    death('d');
+		}
+		if (!ISWEARING(R_SUSTSTR))
+		    chg_str(-1);
+	    }
+	    else
+		msg("A small dart whizzes by your ear and vanishes.");
+    }
+    flush_type();	/* flush typeahead */
+    return(ch);
+}
+
+/*
+ * trap_at:
+ *	find the trap at (y,x) on screen.
+ */
+
+struct trap *
+trap_at(int y, int x)
+{
+    struct trap *tp, *ep;
+
+    ep = &traps[ntraps];
+    for (tp = traps; tp < ep; tp++)
+	if (tp->tr_pos.y == y && tp->tr_pos.x == x)
+	    break;
+    if (tp == ep)
+    {
+	sprintf(prbuf, "Trap at %d,%d not in array", y, x);
+	fatal(prbuf);
+    }
+    return tp;
+}
+
+/*
+ * rndmove:
+ *	move in a random direction if the monster/person is confused
+ */
+
+coord *
+rndmove(struct thing *who)
+{
+    int x, y;
+    int ch;
+    int ex, ey, nopen = 0;
+    struct linked_list *item;
+    struct object *obj;
+    static coord ret;  /* what we will be returning */
+    static coord dest;
+
+    ret = who->t_pos;
+    /*
+     * Now go through the spaces surrounding the player and
+     * set that place in the array to true if the space can be
+     * moved into
+     */
+    ey = ret.y + 1;
+    ex = ret.x + 1;
+    for (y = who->t_pos.y - 1; y <= ey; y++)
+	if (y >= 0 && y < LINES)
+	    for (x = who->t_pos.x - 1; x <= ex; x++)
+	    {
+		if (x < 0 || x >= COLS)
+		    continue;
+		ch = winat(y, x);
+		if (step_ok(ch))
+		{
+		    dest.y = y;
+		    dest.x = x;
+		    if (!diag_ok(&who->t_pos, &dest))
+			continue;
+		    if (ch == SCROLL)
+		    {
+			item = NULL;
+			for (item = lvl_obj; item != NULL; item = next(item))
+			{
+			    obj = (struct object *) ldata(item);
+			    if (y == obj->o_pos.y && x == obj->o_pos.x)
+				break;
+			}
+			if (item != NULL && obj->o_which == S_SCARE)
+			    continue;
+		    }
+		    if (rnd(++nopen) == 0)
+			ret = dest;
+		}
+	    }
+    return &ret;
+}