Mercurial > hg > early-roguelike
view xrogue/move.c @ 265:7fcb2f9f57e6
Mention UltraRogue in the top-level README.
author | John "Elwin" Edwards |
---|---|
date | Sun, 19 Feb 2017 19:54:17 -0500 |
parents | f54901b9c39b |
children | e52a8a7ad4c5 |
line wrap: on
line source
/* move.c - Hero movement commands XRogue: Expeditions into the Dungeons of Doom Copyright (C) 1991 Robert Pietkivitch All rights reserved. Based on "Advanced Rogue" Copyright (C) 1984, 1985 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. */ #include <curses.h> #include <ctype.h> #include <string.h> #include "rogue.h" /* * Used to hold the new hero position */ coord move_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. */ char be_trapped(struct thing *th, coord *tc) { register struct trap *tp; register char ch, *mname = NULL; register bool is_player = (th == &player), can_see; register struct linked_list *mitem = NULL; register struct thing *mp; /* Can the player see the creature? */ can_see = cansee(tc->y, tc->x); can_see &= (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); if (pstats.s_hpt < 1) { pstats.s_hpt = -1; death(D_FALL); } wclear(cw); wclear(mw); new_level(NORMLEV); msg("You fell through a trap! "); } 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); } } /* worm hole trap to OUTSIDE */ when WORMHOLE: if (is_player) { prev_max = 1000; /* flag used in n_level.c */ level++; pstats.s_hpt -= roll(1, 10); if (pstats.s_hpt < 1) { pstats.s_hpt = -1; death(D_FALL); } new_level(OUTSIDE); msg("You suddenly find yourself in strange surroundings! "); return(ch); } else { if (can_see) msg("%s fell into the worm hole! ", 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) { if (!ISWEARING(R_ALERT)) { msg("A strange white mist envelops you. You fall asleep. "); player.t_no_move += movement(&player) * SLEEPTIME; player.t_action = A_FREEZE; } else { msg("The white mist invigorates you. "); } } 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, 8)) < 1) { pstats.s_hpt = -1; msg("The arrow killed you. --More--"); wait_for(' '); death(D_ARROW); } } else { if (can_see) msg("An arrow shot %s.", prname(mname, FALSE)); if ((th->t_stats.s_hpt -= roll(1, 8)) < 1) { 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(7) - 1; arrow->o_dplus = rnd(7) - 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 = 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. "); if ((pstats.s_hpt -= roll(1, 8)) < 1) { pstats.s_hpt = -1; msg("The dart killed you."); wait_for(' '); 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 < 1) { pstats.s_hpt = -1; death(D_POISON); } } else if (!ISWEARING(R_SUSABILITY)) chg_str(-1); } } else { if (can_see) msg("A small dart stabs the %s. ", prname(mname, FALSE)); if ((th->t_stats.s_hpt -= roll(1,8)) < 1) { 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 + level; if (th->t_stats.s_hpt < 1) { 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 < 56) { teleport(); /* teleport away */ pool_teleport = TRUE; } else if((i < 72) && level > 4) { level -= rnd(4) + 1; cur_max = level; new_level(NORMLEV); pool_teleport = TRUE; msg("You here a faint groan from below."); } else if(i < 85) { level += rnd(4) + 1; new_level(NORMLEV); pool_teleport = TRUE; msg("You find yourself in strange surroundings."); } else if(i > 96) { msg("Oh no!!! You drown in the pool!!! --More--"); wait_for(' '); pstats.s_hpt = -1; death(D_DROWN); } else { new_level(NORMLEV); pool_teleport = TRUE; msg("You are whisked away to another region."); } } } else { if (i < 60) { if (can_see) { /* Drowns */ if (i < 50) 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++; if (pstats.s_hpt < 1) { pstats.s_hpt = -1; death(D_FALL); } wclear(cw); wclear(mw); new_level(MAZELEV); msg("You are surrounded by twisty passages! "); } else { if (can_see) msg("%s fell into a maze 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); flushinp(); return(ch); } /* * blue_light: * magically light up a room (or level or make it dark) */ bool blue_light(bool blessed, bool 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) && !ISWEARING(R_LIGHT)) 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"); 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. */ void corr_move(int dy, int dx) { int legal=0; /* Number of legal alternatives */ register int y, x, /* Indexes though possible positions */ locy = 0, locx = 0; /* Hold delta of chosen location */ /* New position */ move_nh.y = hero.y + dy; move_nh.x = hero.x + dx; /* If it is a legal move, just return */ if (move_nh.x >= 0 && move_nh.x < cols && move_nh.y > 0 && move_nh.y < lines - 2) { switch (winat(move_nh.y, move_nh.x)) { case WALL: case VERTWALL: case HORZWALL: break; default: if (diag_ok(&hero, &move_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 VERTWALL: case HORZWALL: break; default: move_nh.y = y; move_nh.x = x; if (diag_ok(&hero, &move_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 */ void dip_it(void) { 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); if (ob->o_group != 0) ob->o_group = newgrp(); /* change the group */ switch(ob->o_type) { case WEAPON: if(i < 60) { /* 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 < 75) { /* 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 < 60) { /* 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; else ob->o_ac += rnd(2) + 1; ob->o_flags |= ISCURSED; msg("The %s glows red for a moment.",armors[wh].a_name); } else msg(nothing); when STICK: { int j; j = rnd(14) + 1; if(i < 60) { /* add charges */ ob->o_charges += j;