diff arogue7/move.c @ 125:adfa37e67084

Import Advanced Rogue 7.7 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Fri, 08 May 2015 15:24:40 -0400
parents
children a0a57cf42810
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/arogue7/move.c	Fri May 08 15:24:40 2015 -0400
@@ -0,0 +1,1874 @@
+/*
+ * move.c  -  Hero movement commands
+ *
+ * Advanced Rogue
+ * Copyright (C) 1984, 1985, 1986 Michael Morgan, Ken Dalka and AT&T
+ * All rights reserved.
+ *
+ * Based on "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.
+ */
+
+/*
+ * Hero movement commands
+ *
+ */
+
+#include "curses.h"
+#include <ctype.h>
+#include "rogue.h"
+#ifdef PC7300
+#include "menu.h"
+#endif
+
+/*
+ * Used to hold the new hero position
+ */
+
+static coord nh;
+
+static char Moves[3][3] = {
+    { 'y', 'k', 'u' },
+    { 'h', '.', 'l' },
+    { 'b', 'j', 'n' }
+};
+
+/*
+ * be_trapped:
+ *	The guy stepped on a trap.... Make him pay.
+ */
+
+be_trapped(th, tc)
+register struct thing *th;
+register coord *tc;
+{
+    register struct trap *tp;
+    register char ch, *mname;
+    register bool is_player = (th == &player),
+	          can_see;
+    register struct linked_list *mitem;
+    register struct thing *mp;
+
+
+    /* Can the player see the creature? */
+    can_see = (cansee(tc->y, tc->x) && (is_player || !invisible(th)));
+
+    tp = trap_at(tc->y, tc->x);
+    /*
+     * if he's wearing boots of elvenkind, he won't set off the trap
+     * unless its a magic pool (they're not really traps)
+     */
+    if (is_player					&&
+	cur_misc[WEAR_BOOTS] != NULL			&&
+	cur_misc[WEAR_BOOTS]->o_which == MM_ELF_BOOTS	&&
+	tp->tr_type != POOL)
+	    return '\0';
+
+    /*
+     * if the creature is flying then it won't set off the trap
+     */
+     if (on(*th, ISFLY))
+	return '\0';
+
+    tp->tr_flags |= ISFOUND;
+
+    if (!is_player) {
+	mitem = find_mons(th->t_pos.y, th->t_pos.x);
+	mname = monster_name(th);
+    }
+    else {
+	count = running = FALSE;
+	mvwaddch(cw, tp->tr_pos.y, tp->tr_pos.x, tp->tr_type);
+    }
+    switch (ch = tp->tr_type) {
+	case TRAPDOOR:
+	    if (is_player) {
+		level++;
+		pstats.s_hpt -= roll(1, 10);
+		msg("You fell into a trap!");
+		if (pstats.s_hpt <= 0) death(D_FALL);
+		new_level(NORMLEV);
+	    }
+	    else {
+		if (can_see) msg("%s fell into a trap!", prname(mname, TRUE));
+
+		/* 
+		 * See if the fall killed the monster 
+		 * don't let a UNIQUE die since it might have an artifact
+		 * that we need
+		 */
+		if (off(*th,ISUNIQUE) && (th->t_stats.s_hpt-=roll(1,10)) <= 0){
+		    killed(mitem, FALSE, FALSE, FALSE);
+		}
+		else {	/* Just move monster to next level */
+		    check_residue(th);
+
+		    /* Erase the monster from the old position */
+		    if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
+			mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
+		    mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+
+		    /* let him summon on next lvl */
+		    if (on (*th, HASSUMMONED)) {
+			    turn_off(*th, HASSUMMONED); 
+			    turn_on(*th, CANSUMMON);
+		    }
+		    turn_on(*th,ISELSEWHERE);
+		    detach(mlist, mitem);
+		    attach(tlist, mitem);	/* remember him next level */
+
+		    /* Make sure that no one is still chasing us */
+		    for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
+			mp = THINGPTR(mitem);
+			if (mp->t_dest == &th->t_pos) {
+			    mp->t_dest = &hero;
+			    mp->t_wasshot = FALSE;
+			    turn_off(*mp, ISFLEE);	/* Don't run away! */
+			}
+		    }
+
+		    /* Make sure we were not chasing a monster here */
+		    th->t_dest = &hero;
+		    if (on(*th, ISFRIENDLY), turn_off(*th, ISFLEE));
+		}
+	    }
+	when BEARTRAP:
+	    if (is_stealth(th)) {
+		if (is_player) msg("You pass a bear trap.");
+		else if (can_see) msg("%s passes a bear trap.", 
+				      prname(mname, TRUE));
+	    }
+	    else {
+		th->t_no_move += movement(&player) * BEARTIME;
+		th->t_action = A_FREEZE;
+		if (is_player) msg("You are caught in a bear trap.");
+		else if (can_see) msg("%s is caught in a bear trap.",
+					prname(mname, TRUE));
+	    }
+	when SLEEPTRAP:
+	    if (is_player) {
+		msg("A strange white mist envelops you.");
+		if (!ISWEARING(R_ALERT)) {
+		    msg("You fall asleep.");
+		    player.t_no_move += movement(&player) * SLEEPTIME;
+		    player.t_action = A_FREEZE;
+		}
+	    }
+	    else {
+		if (can_see) 
+		    msg("A strange white mist envelops %s.",
+			prname(mname, FALSE));
+		if (on(*th, ISUNDEAD)) {
+		    if (can_see) 
+			msg("The mist doesn't seem to affect %s.",
+			   prname(mname, FALSE));
+		}
+		else {
+		    th->t_no_move += movement(th) * SLEEPTIME;
+		    th->t_action = A_FREEZE;
+		}
+	    }
+	when ARROWTRAP:
+	    if (swing(th->t_ctype, th->t_stats.s_lvl-1, th->t_stats.s_arm, 1))
+	    {
+		if (is_player) {
+		    msg("Oh no! An arrow shot you.");
+		    if ((pstats.s_hpt -= roll(1, 6)) <= 0) {
+			msg("The arrow killed you.");
+			death(D_ARROW);
+		    }
+		}
+		else {
+		    if (can_see) 
+			msg("An arrow shot %s.", prname(mname, FALSE));
+		    if ((th->t_stats.s_hpt -= roll(1, 6)) <= 0) {
+			if (can_see) 
+			    msg("The arrow killed %s.", prname(mname, FALSE));
+			killed(mitem, FALSE, FALSE, TRUE);
+		    }
+		}
+	    }
+	    else
+	    {
+		register struct linked_list *item;
+		register struct object *arrow;
+
+		if (is_player) msg("An arrow shoots past you.");
+		else if (can_see) 
+			  msg("An arrow shoots by %s.", prname(mname, FALSE));
+		item = new_item(sizeof *arrow);
+		arrow = OBJPTR(item);
+		arrow->o_type = WEAPON;
+		arrow->contents = NULL;
+		arrow->o_which = ARROW;
+		arrow->o_hplus = rnd(3) - 1;
+		arrow->o_dplus = rnd(3) - 1;
+		init_weapon(arrow, ARROW);
+		arrow->o_count = 1;
+		arrow->o_pos = *tc;
+		arrow->o_mark[0] = '\0';
+		fall(item, FALSE);
+	    }
+	when TELTRAP:
+	    if (is_player) teleport();
+	    else {
+		register int rm;
+	        struct room *old_room;	/* old room of monster */
+
+		/* 
+		 * Erase the monster from the old position 
+		 */
+		if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
+		    mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
+		mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+		/*
+		 * check to see if room should go dark
+		 */
+		if (on(*th, HASFIRE)) {
+		    old_room=roomin(&th->t_pos);
+		    if (old_room != NULL) {
+			register struct linked_list *fire_item;
+
+			for (fire_item = old_room->r_fires; fire_item != NULL;
+			     fire_item = next(fire_item)) {
+			    if (THINGPTR(fire_item) == th) {
+				detach(old_room->r_fires, fire_item);
+				destroy_item(fire_item);
+
+				if (old_room->r_fires == NULL) {
+				    old_room->r_flags &= ~HASFIRE;
+				    if (can_see) light(&hero);
+				}
+			    }
+			}
+		    }
+		}
+
+		/* Get a new position */
+		do {
+		    rm = rnd_room();
+		    rnd_pos(&rooms[rm], &th->t_pos);
+		} until(winat(th->t_pos.y, th->t_pos.x) == FLOOR);
+
+		/* Put it there */
+		mvwaddch(mw, th->t_pos.y, th->t_pos.x, th->t_type);
+		th->t_oldch = CCHAR( mvwinch(cw, th->t_pos.y, th->t_pos.x) );
+		/*
+		 * check to see if room that creature appears in should
+		 * light up
+		 */
+	        if (on(*th, HASFIRE)) {
+		    register struct linked_list *fire_item;
+
+		    fire_item = creat_item();
+		    ldata(fire_item) = (char *) th;
+		    attach(rooms[rm].r_fires, fire_item);
+
+		    rooms[rm].r_flags |= HASFIRE;
+		    if(cansee(th->t_pos.y, th->t_pos.x) && 
+		       next(rooms[rm].r_fires) == NULL)
+			light(&hero);
+		}
+		if (can_see) 
+		    msg("%s seems to have disappeared!", prname(mname, TRUE));
+	    }
+	when DARTTRAP:
+	    if (swing(th->t_ctype, th->t_stats.s_lvl+1, th->t_stats.s_arm, 1)) {
+		if (is_player) {
+		    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_DART);
+		    }
+
+		    /* Now the poison */
+		    if (!save(VS_POISON, &player, 0)) {
+			/* 75% chance it will do point damage - else strength */
+			if (rnd(100) < 75) {
+			    pstats.s_hpt /= 2;
+			    if (pstats.s_hpt == 0) death(D_POISON);
+			}
+			else if (!ISWEARING(R_SUSABILITY))
+				chg_str(-1);
+		    }
+		}
+		else {
+		    if (can_see)
+			msg("A small dart just hit %s in the shoulder.",
+				prname(mname, FALSE));
+		    if ((th->t_stats.s_hpt -= roll(1,4)) <= 0) {
+			if (can_see) 
+			    msg("The dart killed %s.", prname(mname, FALSE));
+			killed(mitem, FALSE, FALSE, TRUE);
+		    }
+		    if (!save(VS_POISON, th, 0)) {
+			th->t_stats.s_hpt /= 2;
+			if (th->t_stats.s_hpt <= 0) {
+			    if (can_see) 
+				msg("The dart killed %s.", prname(mname,FALSE));
+			    killed(mitem, FALSE, FALSE, TRUE);
+			}
+		    }
+		}
+	    }
+	    else {
+		if (is_player)
+		    msg("A small dart whizzes by your ear and vanishes.");
+		else if (can_see)
+		    msg("A small dart whizzes by %s's ear and vanishes.",
+			prname(mname, FALSE));
+	    }
+        when POOL: {
+	    register int i;
+
+	    i = rnd(100);
+	    if (is_player) {
+		if ((tp->tr_flags & ISGONE)) {
+		    if (i < 30) {
+			teleport();	   /* teleport away */
+			pool_teleport = TRUE;
+		    }
+		    else if((i < 45) && level > 2) {
+			level -= rnd(2) + 1;
+			cur_max = level;
+			new_level(NORMLEV);
+			pool_teleport = TRUE;
+			msg("You here a faint groan from below.");
+		    }
+		    else if(i < 70) {
+			level += rnd(4) + 1;
+			new_level(NORMLEV);
+			pool_teleport = TRUE;
+			msg("You find yourself in strange surroundings.");
+		    }
+		    else if(i > 95) {
+			msg("Oh no!!! You drown in the pool!!! --More--");
+			wait_for(' ');
+			death(D_DROWN);
+		    }
+		}
+	    }
+	    else {
+		if (i < 60) {
+		    if (can_see) {
+			/* Drowns */
+			if (i < 30) 
+			    msg("%s drowned in the pool!", prname(mname, TRUE));
+
+			/* Teleported to another level */
+			else msg("%s disappeared!", prname(mname, TRUE));
+		    }
+		    killed(mitem, FALSE, FALSE, TRUE);
+		}
+	    }
+	}
+    when MAZETRAP:
+	if (is_player) {
+	    pstats.s_hpt -= roll(1, 10);
+	    level++;
+	    msg("You fell through a trap door!");
+	    if (pstats.s_hpt <= 0) death(D_FALL);
+	    new_level(MAZELEV);
+	    msg("You are surrounded by twisty passages!");
+	}
+	else {
+	    if (can_see) msg("%s fell into a trap!", prname(mname, TRUE));
+
+	    if (on(*th, ISUNIQUE)) {
+		    check_residue(th);
+
+		    /* Erase the monster from the old position */
+		    if (isalpha(mvwinch(cw, th->t_pos.y, th->t_pos.x)))
+			mvwaddch(cw, th->t_pos.y, th->t_pos.x, th->t_oldch);
+		    mvwaddch(mw, th->t_pos.y, th->t_pos.x, ' ');
+
+		    /* let him summon on next lvl */
+		    if (on (*th, HASSUMMONED)) {
+			    turn_off(*th, HASSUMMONED); 
+			    turn_on(*th, CANSUMMON);
+		    }
+		    turn_on(*th,ISELSEWHERE);
+		    detach(mlist, mitem);
+		    attach(tlist, mitem);	/* remember him next level */
+
+		    /* Make sure that no one is still chasing us */
+		    for (mitem = mlist; mitem != NULL; mitem = next(mitem)) {
+			mp = THINGPTR(mitem);
+			if (mp->t_dest == &th->t_pos) {
+			    mp->t_dest = &hero;
+			    mp->t_wasshot = FALSE;
+			    turn_off(*mp, ISFLEE);	/* Don't run away! */
+			}
+		    }
+
+		    /* Make sure we were not chasing a monster here */
+		    th->t_dest = &hero;
+		    if (on(*th, ISFRIENDLY), turn_off(*th, ISFLEE));
+	    }
+	    else
+		    killed(mitem, FALSE, FALSE, FALSE);
+	}
+    }
+
+    /* Move the cursor back onto the hero */
+    wmove(cw, hero.y, hero.x);
+
+    md_flushinp();
+    return(ch);
+}
+
+/*
+ * blue_light:
+ *	magically light up a room (or level or make it dark)
+ */
+
+bool
+blue_light(blessed, cursed)
+bool blessed, cursed;
+{
+    register struct room *rp;
+    bool ret_val=FALSE;	/* Whether or not affect is known */
+
+    rp = roomin(&hero);	/* What room is hero in? */
+
+    /* Darken the room if the magic is cursed */
+    if (cursed) {
+	if ((rp == NULL) || !lit_room(rp)) msg(nothing);
+	else {
+	    rp->r_flags |= ISDARK;
+	    if (!lit_room(rp) && (levtype != OUTSIDE || !daytime))
+		msg("The %s suddenly goes dark.",
+			levtype == OUTSIDE ? "area" : "room");
+	    else msg(nothing);
+	    ret_val = TRUE;
+	}
+    }
+    else {
+	ret_val = TRUE;
+	if (rp && !lit_room(rp) &&
+	    (levtype != OUTSIDE || !daytime)) {
+	    addmsg("The %s is lit", levtype == OUTSIDE ? "area" : "room");
+	    if (!terse)
+		addmsg(" by a %s blue light.",
+		    blessed ? "bright" : "shimmering");
+	    endmsg();
+	}
+	else if (winat(hero.y, hero.x) == PASSAGE)
+	    msg("The corridor glows %sand then fades",
+		    blessed ? "brightly " : "");
+	else {
+	    ret_val = FALSE;
+	    msg(nothing);
+	}
+	if (blessed) {
+	    register int i;	/* Index through rooms */
+
+	    for (i=0; i<MAXROOMS; i++)
+		rooms[i].r_flags &= ~ISDARK;
+	}
+	else if (rp) rp->r_flags &= ~ISDARK;
+    }
+
+    /*
+     * Light the room and put the player back up
+     */
+    light(&hero);
+    mvwaddch(cw, hero.y, hero.x, PLAYER);
+    return(ret_val);
+}
+
+/*
+ * corr_move:
+ *	Check to see that a move is legal.  If so, return correct character.
+ * 	If not, if player came from a legal place, then try to turn him.
+ */
+
+corr_move(dy, dx)
+int dy, dx;
+{
+    int legal=0;		/* Number of legal alternatives */
+    register int y, x,		/* Indexes though possible positions */
+		 locy, locx;	/* Hold delta of chosen location */
+
+    /* New position */
+    nh.y = hero.y + dy;
+    nh.x = hero.x + dx;
+
+    /* If it is a legal move, just return */
+    if (nh.x >= 0 && nh.x < cols && nh.y > 0 && nh.y < lines - 2) {
+        
+	switch (winat(nh.y, nh.x)) {
+	    case WALL:
+	    case '|':
+	    case '-':
+		break;
+	    default:
+		if (diag_ok(&hero, &nh, &player))
+			return;
+	}
+    }
+
+    /* Check legal places surrounding the player -- ignore previous position */
+    for (y = hero.y - 1; y <= hero.y + 1; y++) {
+	if (y < 1 || y > lines - 3)
+	    continue;
+	for (x = hero.x - 1; x <= hero.x + 1; x++) {
+	    /* Ignore borders of the screen */
+	    if (x < 0 || x > cols - 1)
+		continue;
+	    
+	    /* 
+	     * Ignore where we came from, where we are, and where we couldn't go
+	     */
+	    if ((x == hero.x - dx && y == hero.y - dy) ||
+		(x == hero.x + dx && y == hero.y + dy) ||
+		(x == hero.x && y == hero.y))
+		continue;
+
+	    switch (winat(y, x)) {
+		case WALL:
+		case '|':
+		case '-':
+		    break;
+		default:
+		    nh.y = y;
+		    nh.x = x;
+		    if (diag_ok(&hero, &nh, &player)) {
+			legal++;
+			locy = y - (hero.y - 1);
+			locx = x - (hero.x - 1);
+		    }
+	    }
+	}
+    }
+
+    /* If we have 2 or more legal moves, make no change */
+    if (legal != 1) {
+	return;
+    }
+
+    runch = Moves[locy][locx];
+
+    /*
+     * For mazes, pretend like it is the beginning of a new run at each turn
+     * in order to get the lighting correct.
+     */
+    if (levtype == MAZELEV) firstmove = TRUE;
+    return;
+}
+
+/*
+ * dip_it:
+ *	Dip an object into a magic pool
+ */
+dip_it()
+{
+	reg struct linked_list *what;
+	reg struct object *ob;
+	reg struct trap *tp;
+	reg int wh, i;
+
+	tp = trap_at(hero.y,hero.x);
+	if (tp == NULL || tp->tr_type != POOL) {
+	    msg("I see no shimmering pool here");
+	    return;
+	}
+	if (tp->tr_flags & ISGONE) {
+	    msg("This shimmering pool appears to have been used once already.");
+	    return;
+	}
+
+	/* It takes 3 movement periods to dip something */
+	if (player.t_action != C_DIP) {
+	    if ((what = get_item(pack, "dip", ALL, FALSE, FALSE)) == NULL) {
+		msg("");
+		after = FALSE;
+		return;
+	    }
+
+	    ob = OBJPTR(what);
+	    if (ob == cur_armor		 || 
+		ob == cur_misc[WEAR_BOOTS]	 || ob == cur_misc[WEAR_JEWEL]	 ||
+		ob == cur_misc[WEAR_GAUNTLET] ||
+		ob == cur_misc[WEAR_CLOAK]	 ||
+		ob == cur_misc[WEAR_BRACERS] ||
+		ob == cur_misc[WEAR_NECKLACE]||
+		ob == cur_ring[LEFT_1]	 || ob == cur_ring[LEFT_2]	 ||
+		ob == cur_ring[LEFT_3]	 || ob == cur_ring[LEFT_4]	 ||
+		ob == cur_ring[RIGHT_1]	 || ob == cur_ring[RIGHT_2]	 ||
+		ob == cur_ring[RIGHT_3]	 || ob == cur_ring[RIGHT_4]) {
+		mpos = 0;
+		msg("You'll have to take it off first.");
+		return;
+	    }
+
+	    player.t_using = what;	/* Remember what it is */
+	    player.t_action = C_DIP;	/* We are dipping */
+	    player.t_no_move = 3 * movement(&player);
+	    return;
+	}
+
+	/* We have waited our time, let's dip it */
+	what = player.t_using;
+	player.t_using = NULL;
+	player.t_action = A_NIL;
+
+	ob = OBJPTR(what);
+
+	tp->tr_flags |= ISGONE;
+	if (ob != NULL) {
+	    wh = ob->o_which;
+	    ob->o_flags |= ISKNOW;
+	    i = rnd(100);
+	    switch(ob->o_type) {
+		case WEAPON:
+		    if(i < 50) {		/* enchant weapon here */
+			if ((ob->o_flags & ISCURSED) == 0) {
+				ob->o_hplus += 1;
+				ob->o_dplus += 1;
+			}
+			else {		/* weapon was prev cursed here */
+				ob->o_hplus = rnd(2);
+				ob->o_dplus = rnd(2);
+			}
+			ob->o_flags &= ~ISCURSED;
+		        msg("The %s glows blue for a moment.",weaps[wh].w_name);
+		    }
+		    else if(i < 70) {	/* curse weapon here */
+			if ((ob->o_flags & ISCURSED) == 0) {
+				ob->o_hplus = -(rnd(2)+1);
+				ob->o_dplus = -(rnd(2)+1);
+			}
+			else {			/* if already cursed */
+				ob->o_hplus--;
+				ob->o_dplus--;
+			}
+			ob->o_flags |= ISCURSED;
+		        msg("The %s glows red for a moment.",weaps[wh].w_name);
+		    }			
+		    else
+			msg(nothing);
+		when ARMOR:
+		    if (i < 50) {	/* enchant armor */
+			if((ob->o_flags & ISCURSED) == 0)
+			    ob->o_ac -= rnd(2) + 1;
+			else
+			    ob->o_ac = -rnd(3)+ armors[wh].a_class;
+			ob->o_flags &= ~ISCURSED;
+		        msg("The %s glows blue for a moment",armors[wh].a_name);
+		    }
+		    else if(i < 75){	/* curse armor */
+			if ((ob->o_flags & ISCURSED) == 0)
+			    ob->o_ac = rnd(3)+ armors[wh].a_class;