void StatusMonitor::diagnosticStatus(const ros::TimerEvent& time) { if ((double)ros::Time::now().toSec() - (double)last_status_.toSec() > TIMEOUT){ diag_error("CONTROLLER TIMEOUT"); } else if (status_ == 0){ diag_ok(info_); } else if (status_ == 1){ diag_warn(info_); } else if (status_ == 2){ diag_error(info_); } }
/* * 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. */ int chase(THING *tp, const coord *ee) { THING *obj; int x, y; int curdist, thisdist; const coord *er = &tp->t_pos; int ch; int plcnt = 1; coord tryp; /* * If the thing is confused, let it move randomly. Invisible * Stalkers are slightly confused all of the time, and bats are * quite confused all the time */ if ((on(*tp, ISHUH) && rnd(5) != 0) || (tp->t_type == 'P' && rnd(5) == 0) || (tp->t_type == 'B' && rnd(2) == 0)) { /* * get a valid random move */ ch_ret = rndmove(tp); curdist = dist_cp(&ch_ret, ee); /* * Small chance that it will become un-confused */ if (rnd(20) == 0) tp->t_flags &= ~ISHUH; } /* * Otherwise, find the empty spot next to the chaser that is * closest to the chasee. */ else { int ey, ex; /* * This will eventually hold where we move to get closer * If we can't find an empty spot, we stay where we are. */ curdist = dist_cp(er, ee); ch_ret = *er; ey = er->y + 1; if (ey >= NUMLINES - 1) ey = NUMLINES - 2; ex = er->x + 1; if (ex >= NUMCOLS) ex = NUMCOLS - 1; for (x = er->x - 1; x <= ex; x++) { if (x < 0) continue; tryp.x = x; for (y = er->y - 1; y <= ey; y++) { tryp.y = y; if (!diag_ok(er, &tryp)) continue; ch = winat(y, x); if (step_ok(ch)) { /* * If it is a scroll, it might be a scare monster scroll * so we need to look it up to see what type it is. */ if (ch == SCROLL) { for (obj = lvl_obj; obj != NULL; obj = next(obj)) { if (y == obj->o_pos.y && x == obj->o_pos.x) break; } if (obj != NULL && obj->o_which == S_SCARE) continue; } /* * It can also be a Xeroc, which we shouldn't step on */ if ((obj = moat(y, x)) != NULL && obj->t_type == 'X') continue; /* * If we didn't find any scrolls at this place or it * wasn't a scare scroll, then this place counts */ thisdist = dist(y, x, ee->y, ee->x); if (thisdist < curdist) { plcnt = 1; ch_ret = tryp; curdist = thisdist; } else if (thisdist == curdist && rnd(++plcnt) == 0) { ch_ret = tryp; curdist = thisdist; } } } } } return (curdist != 0 && !ce(ch_ret, hero)); }
int chase(struct thing *tp, coord *ee) { int x, y; int dist, thisdist; struct linked_list *item; struct object *obj; coord *er = &tp->t_pos; int ch; /* * If the thing is confused, let it move randomly. Invisible * Stalkers are slightly confused all of the time, and bats are * quite confused all the time */ if ((on(*tp, ISHUH) && rnd(10) < 8) || (tp->t_type == 'I' && rnd(100) < 20) || (tp->t_type == 'B' && rnd(100) < 50)) { /* * get a valid random move */ ch_ret = *rndmove(tp); dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x); /* * Small chance that it will become un-confused */ if (rnd(1000) < 50) tp->t_flags &= ~ISHUH; } /* * Otherwise, find the empty spot next to the chaser that is * closest to the chasee. */ else { int ey, ex; /* * This will eventually hold where we move to get closer * If we can't find an empty spot, we stay where we are. */ dist = DISTANCE(er->y, er->x, ee->y, ee->x); ch_ret = *er; ey = er->y + 1; ex = er->x + 1; for (x = er->x - 1; x <= ex; x++) for (y = er->y - 1; y <= ey; y++) { coord tryp; tryp.x = x; tryp.y = y; if (!diag_ok(er, &tryp)) continue; ch = winat(y, x); if (step_ok(ch)) { /* * If it is a scroll, it might be a scare monster scroll * so we need to look it up to see what type it is. */ if (ch == SCROLL) { 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 we didn't find any scrolls at this place or it * wasn't a scare scroll, then this place counts */ thisdist = DISTANCE(y, x, ee->y, ee->x); if (thisdist < dist) { ch_ret = tryp; dist = thisdist; } } } } return (dist != 0); }
int chase(struct thing *tp, coord *ee, int flee) { int x, y; int dist, thisdist, monst_dist = INT_MAX; struct linked_list *weapon; coord *er = &tp->t_pos; coord shoot; coord *shootit_dir = NULL; int ch; char mch; int next_player = FALSE; /* Take care of shooting directions */ if (on(*tp, CANBREATHE) || on(*tp, CANSHOOT) || on(*tp, CANCAST)) { if (good_monster(*tp)) { shootit_dir = find_shoot(tp, &shoot); /* find a mean monster */ if (wizard && shootit_dir) msg("Found monster to attack towards (%d,%d).", shootit_dir->x, shootit_dir->y); } else shootit_dir = can_shoot(er, ee, &shoot); /* shoot hero */ } /* * If the thing is confused, let it move randomly. Some monsters are * slightly confused all of the time. */ if ((on(*tp, ISHUH) && rnd(10) < 8) || ((on(*tp, ISINVIS) || on(*tp, ISSHADOW)) && rnd(100) < 20) || (on(player, ISINVIS) && off(*tp, CANSEE))) { /* Player is invisible */ /* get a valid random move */ tp->t_nxtpos = rndmove(tp); dist = DISTANCE(tp->t_nxtpos, *ee); if (on(*tp, ISHUH) && rnd(20) == 0) /* monster might lose confusion */ turn_off(*tp, ISHUH); /* * check to see if random move takes creature away from * player if it does then turn off ISHELD */ if (dist > 1 && on(*tp, DIDHOLD)) { turn_off(*tp, DIDHOLD); turn_on(*tp, CANHOLD); if (--hold_count == 0) turn_off(player, ISHELD); } } /* If we can breathe, we may do so */ else if (on(*tp, CANBREATHE) && (shootit_dir) && (rnd(100) < 67) && (off(player, ISDISGUISE) || (rnd(tp->t_stats.s_lvl) > 6)) && (DISTANCE(*er, *ee) < BOLT_LENGTH * BOLT_LENGTH)) { int chance; char *breath; /* Will it breathe at random */ if (on(*tp, CANBRANDOM)) { if (rnd(level / 20) == 0 && tp->t_index != nummonst + 1 && !(good_monster(*tp))) turn_off(*tp, CANBRANDOM); /* Select type of breath */ chance = rnd(100); if (chance < 11) breath = "acid"; else if (chance < 22) breath = "flame"; else if (chance < 33) breath = "lightning bolt"; else if (chance < 44) breath = "chlorine gas"; else if (chance < 55) breath = "ice"; else if (chance < 66) breath = "nerve gas"; else if (chance < 77) breath = "sleeping gas"; else if (chance < 88) breath = "slow gas"; else breath = "fear gas"; } /* Or can it breathe acid? */ else if (on(*tp, CANBACID)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBACID); breath = "acid"; } /* Or can it breathe fire */ else if (on(*tp, CANBFIRE)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBFIRE); breath = "flame"; } /* Or can it breathe electricity? */ else if (on(*tp, CANBBOLT)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBBOLT); breath = "lightning bolt"; } /* Or can it breathe gas? */ else if (on(*tp, CANBGAS)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBGAS); breath = "chlorine gas"; } /* Or can it breathe ice? */ else if (on(*tp, CANBICE)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBICE); breath = "ice"; } else if (on(*tp, CANBPGAS)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBPGAS); breath = "nerve gas"; } else if (on(*tp, CANBSGAS)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBSGAS); breath = "sleeping gas"; } else if (on(*tp, CANBSLGAS)) { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBSLGAS); breath = "slow gas"; } else { if (!good_monster(*tp) && rnd(level / 15) == 0) turn_off(*tp, CANBFGAS); breath = "fear gas"; } shoot_bolt(tp, *er, *shootit_dir, (tp == THINGPTR(fam_ptr)), tp->t_index, breath, roll(tp->t_stats.s_lvl, 6)); tp->t_nxtpos = *er; dist = DISTANCE(tp->t_nxtpos, *ee); if (!curr_mons) return (TRUE); } else if (shootit_dir && on(*tp, CANCAST) && (off(player, ISDISGUISE) || (rnd(tp->t_stats.s_lvl) > 6))) { /* If we can cast spells we might do so - even if adjacent fleeing monsters are restricted to certain spells */ incant(tp, *shootit_dir); tp->t_nxtpos = *er; dist = DISTANCE(tp->t_nxtpos, *ee); } else if (shootit_dir && on(*tp, CANSHOOT)) { weapon = get_hurl(tp); if (weapon && (off(*tp, ISFLEE) || rnd(DISTANCE(*er, *ee)) > 2) && (off(player, ISDISGUISE) || (rnd(tp->t_stats.s_lvl) > 6))) { /* Should we shoot or throw something? fleeing monsters may to shoot anyway if far enough away */ missile(shootit_dir->y, shootit_dir->x, weapon, tp); tp->t_nxtpos = *er; dist = DISTANCE(tp->t_nxtpos, *ee); } } else { /* Otherwise, find the empty spot next to the chaser that is closest to the chasee. */ int ey, ex; struct room *rer, *ree; int dist_to_old = INT_MIN; /* Dist from goal to old position */ /* Get rooms */ rer = roomin(*er); ree = roomin(*ee); /* * 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 : INT_MAX; tp->t_nxtpos = *er; /* Are we at our goal already? */ if (!flee && ce(tp->t_nxtpos, *ee)) return (FALSE); ey = er->y + 1; ex = er->x + 1; for (x = er->x - 1; x <= ex; x++) for (y = er->y - 1; y <= ey; y++) { coord tryp; /* test position */ /* Don't try off the screen */ if ((x < 0) || (x >= COLS) || (y < 1) || (y >= LINES - 2)) continue; /* * Don't try the player if not going after * the player or he's disguised and monster is dumb */ if (((off(*tp, ISFLEE) && !ce(hero, *ee)) || (on(player, ISDISGUISE) && (rnd(tp->t_stats.s_lvl) < 6)) || good_monster(*tp)) && x == hero.x && y == hero.y) continue; tryp.x = x; tryp.y = y; /* * Is there a monster on this spot closer to * our goal? Don't look in our spot or where * we were. */ if (!ce(tryp, *er) && !ce(tryp, tp->t_oldpos) && isalpha( (mch = CCHAR(mvwinch(mw, y, x))) ) ) { int test_dist; test_dist = DISTANCE(tryp,*ee); if (test_dist <= 25 && /* Let's be fairly close */ test_dist < monst_dist) { /* Could we really move there? */ mvwaddch(mw, y, x, ' '); /* Temp blank monst */ if (diag_ok(er, &tryp, tp)) monst_dist = test_dist; mvwaddch(mw, y, x, mch); /* Restore monster */ } } if (!diag_ok(er, &tryp, tp)) continue; ch = mvwinch(cw, y, x); /* Screen character */ /* * Stepping on player is NOT okay if we are * fleeing */ if (on(*tp, ISFLEE) && (ch == PLAYER)) next_player = TRUE; if (step_ok(y, x, NOMONST, tp) && (off(*tp, ISFLEE) || ch != PLAYER)) { /* * If it is a trap, an intelligent * monster may not step on it (unless * our hero is on top!) */ if (isatrap(ch)) { if (!(ch == RUSTTRAP) && !(ch == FIRETRAP && on(*tp, NOFIRE)) && rnd(10) < tp->t_stats.s_intel && (y != hero.y || x != hero.x)) continue; } /* * OK -- this place counts */ thisdist = DISTANCE(tryp, *ee); /* * Adjust distance if we are being * shot at to moving out of line of sight. */ if (tp->t_wasshot && tp->t_stats.s_intel > 5 && ce(hero, *ee)) { /* Move out of line of sight */ if (straight_shot(tryp.y, tryp.x, ee->y, ee->x, NULL)) { if (flee) thisdist -= SHOTPENALTY; else thisdist += SHOTPENALTY; } /* * But do we want to leave * the room? */ else if (rer && rer == ree && ch == DOOR) thisdist += DOORPENALTY; } /* * Don't move to the last position if * we can help it */ if (ce(tryp, tp->t_oldpos)) dist_to_old = thisdist; else if ((flee && (thisdist > dist)) || (!flee && (thisdist < dist))) { tp->t_nxtpos = tryp; dist = thisdist; } } } /* * If we are running from the player and he is in our way, go * ahead and slug him. */ if (next_player && DISTANCE(*er,*ee) < dist && step_ok(tp->t_chasee->t_pos.y, tp->t_chasee->t_pos.x, NOMONST, tp)) { tp->t_nxtpos = tp->t_chasee->t_pos; /* Okay to hit player */ return(FALSE); } /* * If we can't get closer to the player (if that's our goal) * because other monsters are in the way, just stay put */ if (!flee && ce(hero, *ee) && monst_dist < INT_MAX && DISTANCE(*er, hero) < dist) tp->t_nxtpos = *er; /* Do we want to go back to the last position? */ else if (dist_to_old != INT_MIN && /* It is possible to move back */ ((flee && dist == 0) || /* No other possible moves */ (!flee && dist == INT_MAX))) { /* Do we move back or just stay put (default)? */ dist = DISTANCE(*er,*ee); /* Current distance */ if (!flee || (flee && (dist_to_old > dist))) tp->t_nxtpos = tp->t_oldpos; } } /* Make sure we have the real distance now */ dist = DISTANCE(tp->t_nxtpos, *ee); /* Mark monsters in a wall */ switch(mvinch(tp->t_nxtpos.y, tp->t_nxtpos.x)) { case WALL: case '-': case '|': turn_on(*tp, ISINWALL); break; default: turn_off(*tp, ISINWALL); } if (off(*tp, ISFLEE) && !(!SAME_POS((tp->t_chasee->t_pos),hero) || off(player, ISINWALL) || on(*tp, CANINWALL))) return(dist != 0); else /* May actually hit here from a confused move */ return(!ce(tp->t_nxtpos, hero)); }
int can_blink(struct thing *tp) { int y, x, index = 9; coord tryp; /* To hold the coordinates for use in diag_ok */ int spots[9], found_one = FALSE; /* * First, can the monster even blink? And if so, there is only a 30% * chance that it will do so. And it won't blink if it is running. */ if (off(*tp, CANBLINK) || (on(*tp, ISHELD)) || on(*tp, ISFLEE) || (on(*tp, ISSLOW) && off(*tp, ISHASTE) && !(tp->t_turn)) || (rnd(10) < 9)) 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)) spots[index] = FALSE; else { /* * 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) { /* 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) ); if (cansee(y, x) && off(*tp, ISINWALL) && ((off(*tp, ISINVIS) && (off(*tp, ISSHADOW) || rnd(100) < 10)) || on(player, CANSEE)) && off(*tp, CANSURPRISE)) mvwaddch(cw, y, x, tp->t_type); mvwaddch(mw, tp->t_pos.y,tp->t_pos.x,' '); /*Clear old position */ mvwaddch(mw, y, x, tp->t_type); tp->t_pos.y = y; tp->t_pos.x = x; } return (found_one); }
/* * 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. */ int chase(struct thing *tp, coord *ee, int flee, int *mdead) { register int x, y; register int dist, thisdist, monst_dist = MAXINT; register struct linked_list *weapon; register coord *er = &tp->t_pos, *shoot_dir; register int ch, mch; register int next_player = FALSE; int deadflg; if (mdead != NULL) *mdead = 0; shoot_dir = can_shoot(er, ee); weapon = get_hurl(tp); /* * If the thing is confused, let it move randomly. Invisible * Stalkers are slightly confused all of the time. */ if ((on(*tp, ISHUH) && rnd(10) < 8) || ((on(*tp, ISINVIS) || on(*tp, ISSHADOW)) && rnd(100) < 20) || (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); if (on(*tp, ISHUH) && rnd(20) == 0) /* monster might lose confusion */ turn_off(*tp, ISHUH); /* * check to see if random move takes creature away from player * if it does then turn off ISHELD */ if (dist > 1 && on(*tp, DIDHOLD)) { turn_off(*tp, DIDHOLD); turn_on(*tp, CANHOLD); if (--hold_count <= 0) { hold_count = 0; turn_off(player, ISHELD); } } } /* If we can breathe, we may do so */ else if (on(*tp, CANBREATHE) && (shoot_dir) && (rnd(100) < 67) && (off(player, ISDISGUISE) || (rnd(tp->t_stats.s_lvl) > 6)) && (DISTANCE(er->y, er->x, ee->y, ee->x) < BOLT_LENGTH*BOLT_LENGTH)) { register int chance; register char *breath; /* Will it breathe at random */ if (on(*tp, CANBRANDOM)) { if (rnd(level/20) == 0 && tp->t_index != NUMMONST+1) turn_off(*tp, CANBRANDOM); /* Select type of breath */ chance = rnd(100); if (chance < 11) breath = "acid"; else if (chance < 22) breath = "flame"; else if (chance < 33) breath = "lightning bolt"; else if (chance < 44) breath = "chlorine gas"; else if (chance < 55) breath = "ice"; else if (chance < 66) breath = "nerve gas"; else if (chance < 77) breath = "sleeping gas"; else if (chance < 88) breath = "slow gas"; else breath = "fear gas"; } /* Or can it breathe acid? */ else if (on(*tp, CANBACID)) { if (rnd(level/20) == 0) turn_off(*tp, CANBACID); breath = "acid"; } /* Or can it breathe fire */ else if (on(*tp, CANBFIRE)) { if (rnd(level/20) == 0) turn_off(*tp, CANBFIRE); breath = "flame"; } /* Or can it breathe electricity? */ else if (on(*tp, CANBBOLT)) { if (rnd(level/20) == 0) turn_off(*tp, CANBBOLT); breath = "lightning bolt"; } /* Or can it breathe gas? */ else if (on(*tp, CANBGAS)) { if (rnd(level/20) == 0) turn_off(*tp, CANBGAS); breath = "chlorine gas"; } /* Or can it breathe ice? */ else if (on(*tp, CANBICE)) { if (rnd(level/20) == 0) turn_off(*tp, CANBICE); breath = "ice"; } else if (on(*tp, CANBPGAS)) { if (rnd(level/20) == 0) turn_off(*tp, CANBPGAS); breath = "nerve gas"; } else if (on(*tp, CANBSGAS)) { if (rnd(level/20) == 0) turn_off(*tp, CANBSGAS); breath = "sleeping gas"; } else if (on(*tp, CANBSLGAS)) { if (rnd(level/20) == 0) turn_off(*tp, CANBSLGAS); breath = "slow gas"; } else { if (rnd(level/20) == 0) turn_off(*tp, CANBFGAS); breath = "fear gas"; } /* Now breathe -- returns TRUE if kills itself */ deadflg = shoot_bolt(tp, *er, *shoot_dir, FALSE, tp->t_index, breath, (save(VS_BREATH) ? tp->t_stats.s_hpt/2 : tp->t_stats.s_hpt)); if (deadflg && mdead != NULL) *mdead = 1; ch_ret = *er; dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x); if (deadflg) return(TRUE); } /* * If we can shoot or throw something, we might do so * if we are running away, we may decide to shoot anyway if we are far * enough */ else if((off(*tp, ISFLEE) || rnd(DISTANCE(er->y,er->x,ee->y,ee->x)) > 2) && on(*tp, CANSHOOT) && (off(player, ISDISGUISE) || (rnd(tp->t_stats.s_lvl) > 6)) && (shoot_dir) && (weapon)) { missile(shoot_dir->y, shoot_dir->x, weapon, tp); ch_ret = *er; dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x); } /* * Otherwise, find the empty spot next to the chaser that is * closest to the chasee. */ else { register int ey, ex; register struct room *rer, *ree; register int dist_to_old = MININT; /* Dist from goal to old position */ /* Get rooms */ rer = roomin(er); ree = roomin(ee); /* * 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; ex = er->x + 1; for (x = er->x - 1; x <= ex; x++) for (y = er->y - 1; y <= ey; y++) { coord tryp; /* Don't try off the board */ if ((x < 0) || (x >= COLS) || (y < 1) || (y >= LINES - 2)) continue; /* Don't try the player if not going after the player */ /* or he's disguised */ if ( ((off(*tp, ISFLEE) && !ce(hero, *ee)) || (on(player, ISDISGUISE) && (rnd(tp->t_stats.s_lvl) < 6))) && x == hero.x && y == hero.y) continue; tryp.x = x; tryp.y = y; /* Is there a monster on this spot closer to our goal? * Don't look in our spot or where we were. */ if (!ce(tryp, *er) && !ce(tryp, tp->t_oldpos) && isalpha(mch = CCHAR( mvwinch(mw, y, x) ))) { register int test_dist; test_dist = DISTANCE(y, x, ee->y, ee->x); if (test_dist <= 25 && /* Let's be fairly close */ test_dist < monst_dist) { /* Could we really move there? */ mvwaddch(mw, y, x, ' '); /* Temporarily blank monst */ if (diag_ok(er, &tryp, tp)) monst_dist = test_dist; mvwaddch(mw, y, x, mch); /* Restore monster */ } } if (!diag_ok(er, &tryp, tp)) continue; ch = CCHAR( mvwinch(cw, y, x) ); /* Screen character */ if (on(*tp, ISFLEE) && (ch == PLAYER)) next_player = TRUE; /* Stepping on player is NOT okay if we are fleeing */ if (step_ok(y, x, NOMONST, tp) && (off(*tp, ISFLEE) || ch != PLAYER)) { /* * If it is a trap, an intelligent monster may not * step on it (unless our hero is on top!) */ if (isatrap(ch)) { if (!(ch == RUSTTRAP) && !(ch == FIRETRAP && on(*tp,NOFIRE)) && rnd(10) < tp->t_stats.s_intel && (y != hero.y || x != hero.x)) continue; } /* * OK -- this place counts */ thisdist = DISTANCE(y, x, ee->y, ee->x); /* Adjust distance if we are being shot at */ if (tp->t_wasshot && tp->t_stats.s_intel > 5 && ce(hero, *ee)) { /* Move out of line of sight */ if (straight_shot(tryp.y, tryp.x, ee->y, ee->x, NULL)) { if (flee) thisdist -= SHOTPENALTY; else thisdist += SHOTPENALTY; } /* But do we want to leave the room? */ else if (rer && rer == ree && ch == DOOR) thisdist += DOORPENALTY; } /* Don't move to the last position if we can help it */ if (ce(tryp, tp->t_oldpos)) dist_to_old = thisdist; else if ((flee && (thisdist > dist)) || (!flee && (thisdist < dist))) { ch_ret = tryp; dist = thisdist; } } } /* If we are running from the player and he is in our way, * go ahead and slug him. */ if (next_player && DISTANCE(er->y, er->x, ee->y, ee->x) < dist && step_ok(tp->t_dest->y, tp->t_dest->x, NOMONST, tp)) { ch_ret = *(tp->t_dest); /* Okay to hit player */ return FALSE; } /* If we can't get closer to the player (if that's our goal) * because other monsters are in the way, just stay put */ if (!flee && ce(hero, *ee) && monst_dist < MAXINT && DISTANCE(er->y, er->x, hero.y, hero.x) < dist) ch_ret = *er; /* Do we want to go back to the last position? */ else if (dist_to_old != MININT && /* It is possible to move back */ ((flee && dist == 0) || /* No other possible moves */ (!flee && dist == MAXINT))) { /* Do we move back or just stay put (default)? */ dist = DISTANCE(er->y, er->x, ee->y, ee->x); /* Current distance */ if (!flee || (flee && (dist_to_old > dist))) ch_ret = tp->t_oldpos; } } /* Make sure we have the real distance now */ dist = DISTANCE(ch_ret.y, ch_ret.x, ee->y, ee->x); /* Mark monsters in a wall */ if (isrock(CCHAR( mvinch(ch_ret.y, ch_ret.x) ))) turn_on(*tp, ISINWALL); else turn_off(*tp, ISINWALL); if (off(*tp, ISFLEE) && ((tp->t_dest != &hero) || off(player, ISINWALL) || on(*tp, CANINWALL))) return (dist != 0); /* May actually hit here from a confused move */ else return(!ce(ch_ret, hero)); }
coord solve(coord start, coord end) { this->end = end; coord co; co.x = start.x; co.y = start.y - 1; addToList(co.x, co.y, co, 1); co.x = start.x - 1; co.y = start.y; addToList(co.x, co.y, co, 1); co.x = start.x + 1; co.y = start.y; addToList(co.x, co.y, co, 1); co.x = start.x; co.y = start.y + 1; addToList(co.x, co.y, co, 1); co.x = start.x - 1; co.y = start.y - 1; if (diag_ok(&start, &co)) addToList(co.x, co.y, co, 1); co.x = start.x + 1; co.y = start.y - 1; if (diag_ok(&start, &co)) addToList(co.x, co.y, co, 1); co.x = start.x - 1; co.y = start.y + 1; if (diag_ok(&start, &co)) addToList(co.x, co.y, co, 1); co.x = start.x + 1; co.y = start.y + 1; if (diag_ok(&start, &co)) addToList(co.x, co.y, co, 1); while(open_list.size() > 0) { int pos = open_list.front(); open_list.pop_front(); int score = info[pos].base_score; coord origin = info[pos].origin; co.x = pos & 0xFFFF; co.y = pos >> 16; if (ce(co, end)) return origin; addToList(co.x, co.y - 1, origin, score + 1); addToList(co.x - 1, co.y, origin, score + 1); addToList(co.x + 1, co.y, origin, score + 1); addToList(co.x, co.y + 1, origin, score + 1); coord ct; ct.x = co.x - 1; ct.y = co.y - 1; if (diag_ok(&co, &ct)) addToList(ct.x, ct.y, origin, score + 1); ct.x = co.x + 1; ct.y = co.y - 1; if (diag_ok(&co, &ct)) addToList(ct.x, ct.y, origin, score + 1); ct.x = co.x - 1; ct.y = co.y + 1; if (diag_ok(&co, &ct)) addToList(ct.x, ct.y, origin, score + 1); ct.x = co.x + 1; ct.y = co.y + 1; if (diag_ok(&co, &ct)) addToList(ct.x, ct.y, origin, score + 1); } return start; }