Mercurial > hg > early-roguelike
view arogue5/chase.c @ 159:44a0fce4b168
arogue7, xrogue: fix configure's wizardmode and limitscore options.
WIZARD and LIMITSCORE, when set by options to './configure', are no
longer overridden in mach_dep.h.
| author | John "Elwin" Edwards |
|---|---|
| date | Fri, 05 Jun 2015 13:57:38 -0400 |
| parents | 0ed67132cf10 |
| children | 56e748983fa8 |
line wrap: on
line source
/* * Code for one object to chase another * * 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 <ctype.h> #include <limits.h> #include "curses.h" #include "rogue.h" #define MAXINT INT_MAX #define MININT INT_MIN coord ch_ret; /* Where chasing takes you */ /* * Canblink checks if the monster can teleport (blink). If so, it will * try to blink the monster next to the player. */ bool can_blink(tp) register struct thing *tp; { register int y, x, index=9; coord tryp; /* To hold the coordinates for use in diag_ok */ bool spots[9], found_one=FALSE; /* * First, can the monster even blink? And if so, there is only a 50% * chance that it will do so. And it won't blink if it is running or * held. */ if (off(*tp, CANBLINK) || (on(*tp, ISHELD)) || on(*tp, ISFLEE) || (on(*tp, ISSLOW) && off(*tp, ISHASTE) && !(tp->t_turn)) || tp->t_no_move || (rnd(12) < 6)) return(FALSE); /* Initialize the spots as illegal */ do { spots[--index] = FALSE; } while (index > 0); /* Find a suitable spot next to the player */ for (y=hero.y-1; y<hero.y+2; y++) for (x=hero.x-1; x<hero.x+2; x++, index++) { /* Make sure x coordinate is in range and that we are * not at the player's position */ if (x<0 || x >= COLS || index == 4) continue; /* Is it OK to move there? */ if (step_ok(y, x, NOMONST, tp) && (!isatrap(mvwinch(cw, y, x)) || rnd(10) >= tp->t_stats.s_intel || on(*tp, ISFLY))) { /* OK, we can go here. But don't go there if * monster can't get at player from there */ tryp.y = y; tryp.x = x; if (diag_ok(&tryp, &hero, tp)) { spots[index] = TRUE; found_one = TRUE; } } } /* If we found one, go to it */ if (found_one) { char rch; /* What's really where the creatures moves to */ /* Find a legal spot */ while (spots[index=rnd(9)] == FALSE) continue; /* Get the coordinates */ y = hero.y + (index/3) - 1; x = hero.x + (index % 3) - 1; /* Move the monster from the old space */ mvwaddch(cw, tp->t_pos.y, tp->t_pos.x, tp->t_oldch); /* Move it to the new space */ tp->t_oldch = CCHAR( mvwinch(cw, y, x) ); /* Display the creature if our hero can see it */ if (cansee(y, x) && off(*tp, ISINWALL) && !invisible(tp)) mvwaddch(cw, y, x, tp->t_type); /* Fix the monster window */ mvwaddch(mw, tp->t_pos.y, tp->t_pos.x, ' '); /* Clear old position */ mvwaddch(mw, y, x, tp->t_type); /* Record the new position */ tp->t_pos.y = y; tp->t_pos.x = x; /* If the monster is on a trap, trap it */ rch = CCHAR( mvinch(y, x) ); if (isatrap(rch)) { if (cansee(y, x)) tp->t_oldch = rch; be_trapped(tp, &(tp->t_pos)); } } return(found_one); } /* * Can_shoot determines if the monster (er) has a direct line of shot * at the player (ee). If so, it returns the direction in which to shoot. */ coord * can_shoot(er, ee) register coord *er, *ee; { static coord shoot_dir; /* Make sure we are chasing the player */ if (!ce((*ee), hero)) return(NULL); /* * They must be in the same room or very close (at door) */ if (roomin(er) != roomin(&hero) && DISTANCE(er->y,er->x,ee->y,ee->x) > 1) return(NULL); /* Do we have a straight shot? */ if (!straight_shot(er->y, er->x, ee->y, ee->x, &shoot_dir)) return(NULL); else return(&shoot_dir); } /* * chase: * Find the spot for the chaser(er) to move closer to the * chasee(ee). Returns TRUE if we want to keep on chasing later * FALSE if we reach the goal. */ chase(tp, ee, flee, mdead) register struct thing *tp; register coord *ee; bool flee; /* True if destination (ee) is player and monster is running away * or the player is in a wall and the monster can't get to it */ bool *mdead; { int damage, dist, thisdist, monst_dist = MAXINT; struct linked_list *weapon; register coord *er = &tp->t_pos; coord *shoot_dir; char ch, mch; bool next_player = FALSE; if (mdead != NULL) *mdead = 0; /* * set the distance from the chas(er) to the chas(ee) here and then * we won't have to reset it unless the chas(er) moves (instead of shoots) */ dist = DISTANCE(er->y, er->x, ee->y, ee->x); /* * If the thing is confused or it can't see the player, * let it move randomly. */ if ((on(*tp, ISHUH) && rnd(10) < 8) || (on(player, ISINVIS) && off(*tp, CANSEE))) { /* Player is invisible */ /* * get a valid random move */ ch_ret = *rndmove(tp); dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x); /* * check to see if random move takes creature away from player * if it does then turn off ISHELD */ if (dist > 2) { if (on(*tp, DIDHOLD)) { turn_off(*tp, DIDHOLD); turn_on(*tp, CANHOLD); if (--hold_count == 0) turn_off(player, ISHELD); } /* If monster was suffocating, stop it */ if (on(*tp, DIDSUFFOCATE)) { turn_off(*tp, DIDSUFFOCATE); turn_on(*tp, CANSUFFOCATE); extinguish(suffocate); } } } /* If we can breathe, we may do so */ else if (on(*tp, CANBREATHE) && (dist < BOLT_LENGTH*BOLT_LENGTH) && (shoot_dir = can_shoot(er, ee)) && !on(player, ISINWALL) && (rnd(100) < 75)) { register char *breath = NULL; damage = tp->t_stats.s_hpt; /* Will it breathe at random */ if (on(*tp, CANBRANDOM)) { /* Turn off random breath */ turn_off(*tp, CANBRANDOM); /* Select type of breath */ switch (rnd(10)) { case 0: breath = "acid"; turn_on(*tp, NOACID); when 1: breath = "flame"; turn_on(*tp, NOFIRE); when 2: breath = "lightning bolt"; turn_on(*tp, NOBOLT); when 3: breath = "chlorine gas"; turn_on(*tp, NOGAS); when 4: breath = "ice"; turn_on(*tp, NOCOLD); when 5: breath = "nerve gas"; turn_on(*tp, NOPARALYZE); when 6: breath = "sleeping gas"; turn_on(*tp, NOSLEEP); when 7: breath = "slow gas"; turn_on(*tp, NOSLOW); when 8: breath = "confusion gas"; turn_on(*tp, ISCLEAR); when 9: breath = "fear gas"; turn_on(*tp, NOFEAR); } } /* Or can it breathe acid? */ else if (on(*tp, CANBACID)) { turn_off(*tp, CANBACID); breath = "acid"; } /* Or can it breathe fire */ else if (on(*tp, CANBFIRE)) { turn_off(*tp, CANBFIRE); breath = "flame"; } /* Or can it breathe electricity? */ else if (on(*tp, CANBBOLT)) { turn_off(*tp, CANBBOLT); breath = "lightning bolt"; } /* Or can it breathe gas? */ else if (on(*tp, CANBGAS)) { turn_off(*tp, CANBGAS); breath = "chlorine gas"; } /* Or can it breathe ice? */ else if (on(*tp, CANBICE)) { turn_off(*tp, CANBICE); breath = "ice"; } else if (on(*tp, CANBPGAS)) { turn_off(*tp, CANBPGAS); breath = "nerve gas"; } /* can it breathe sleeping gas */ else if (on(*tp, CANBSGAS)) { turn_off(*tp, CANBSGAS); breath = "sleeping gas"; } /* can it breathe slow gas */ else if (on(*tp, CANBSLGAS)) { turn_off(*tp, CANBSLGAS); breath = "slow gas"; } /* can it breathe confusion gas */ else if (on(*tp, CANBCGAS)) { turn_off(*tp, CANBCGAS); breath = "confusion gas"; } /* can it breathe fear gas */ else { turn_off(*tp, CANBFGAS); breath = "fear gas"; } /* Now breathe -- sets "monst_dead" if it kills someone */ *mdead = shoot_bolt( tp, *er, *shoot_dir, FALSE, tp->t_index, breath, damage); ch_ret = *er; running = FALSE; if (*mdead) return(TRUE); } /* We may shoot missiles if we can */ else if (on(*tp, CANMISSILE) && (shoot_dir = can_shoot(er, ee)) && !on(player, ISINWALL) && (rnd(100) < 75)) { static struct object missile = { MISSILE, {0, 0}, "", 0, "", "0d4 " , NULL, 0, WS_MISSILE, 100, 1 }; sprintf(missile.o_hurldmg, "%dd4", tp->t_stats.s_lvl); do_motion(&missile, shoot_dir->y, shoot_dir->x, tp); hit_monster(unc(missile.o_pos), &missile, tp); turn_off(*tp, CANMISSILE); ch_ret = *er; running = FALSE; } /* We may use a sonic blast if we can */ else if (on(*tp, CANSONIC) && (dist < BOLT_LENGTH*2) && (shoot_dir = can_shoot(er, ee)) && !on(player, ISINWALL) && (rnd(100) < 50)) { static struct object blast = { MISSILE, {0, 0}, "", 0, "", "150" , NULL, 0, 0, 0, 0 }; turn_off(*tp, CANSONIC); do_motion(&blast, shoot_dir->y, shoot_dir->x, tp); damage = 150; if (save(VS_BREATH, &player, -3)) damage /= 2; msg ("The %s's sonic blast hits you", monsters[tp->t_index].m_name); if ((pstats.s_hpt -= damage) <= 0) death(tp->t_index); ch_ret = *er; running = FALSE; } /* * If we have a special magic item, we might use it. We will restrict * this options to uniques with relics for now. */ else if (on(*tp, ISUNIQUE) && m_use_item(tp, er, ee)) { ch_ret = *er; running = FALSE; } /* * If we can shoot or throw something, we might do so. * If next to player, then 80% prob will fight. */ else if(on(*tp, CANSHOOT) && (shoot_dir = can_shoot(er, ee)) && !on(player, ISINWALL) && (dist > 3 || (rnd(100) > 80)) && (weapon = get_hurl(tp))) { missile(shoot_dir->y, shoot_dir->x, weapon, tp); ch_ret = *er; } /* * Otherwise, find the empty spot next to the chaser that is * closest to the chasee. */ else { register int ey, ex, x, y; register struct room *rer, *ree; int dist_to_old = MININT; /* Dist from goal to old position */ /* Get rooms */ rer = roomin(er); /* Room the chasER (monster) is in */ ree = roomin(ee); /* Room the chasEE is in */ /* * This will eventually hold where we move to get closer * If we can't find an empty spot, we stay where we are. */ dist = flee ? 0 : MAXINT; ch_ret = *er; /* Are we at our goal already? */ if (!flee && ce(ch_ret, *ee)) return(FALSE); ey = er->y + 1;
