Mercurial > hg > early-roguelike
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;