the level to use the pathfinding routines for patrolling. The monsters still sometimes disappear when near the exit instead of on it, which needs to be fixed, but it's vastly closer to working properly.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@6186 c06c8d41-db1a-0410-9941-cceddc491573
SPWOUV6ZNHLBSAX455ACJDBEJYVFHGO4H76L4NPAE5DF6BEAK34QC XJBNF2N35THJC2KYGCMPLC3CDCJP25CEDKHUI3P55V6H5YWXBUKAC XBC6V43KX2PSRWHAW3FUCALPYEDP2FNQMR7UA4FHLXQ6JI42PP2AC U54JNIWKKB5QRZVEK4ZMBHAVVB6HLKVJVZENZHDOINKBCOAUDOGAC Q7MDQRE6DP7C6BYGJDFYHHAUZGYQUNZINQWU7GTLT4HNYAEXYUOQC SWQ3SMISYGEY5OFIR74O5XHGQXCBZE3ZVQDYC2SUA7V327VTE7KQC VT6WFXYCMVUYNQVKLVT3QZTICAYNKG4LTG2Q44LZCC6CM35KP2CAC J4LFL6BUKGETJOK3O54CPTCP6NNVXWUHYBQ4IEQMHI67VBS4LNBAC SKWBAGSAB625IIN4UP3NCPRX2H3KCPC2LULHS2A7JVRLO3EUBJDAC Y5YQ2AXS6XTWCHEQFDXRYU2IDQTBW7WXNJFES22GSKYQ2JGZ3U5AC BINKDWGFGUPTOA7IE5KK4ZIELGU5WC3X47MYXOWU4X43EGAC5DUAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC VNB7OLRPCC7ITTUKYLQ4SDV25QD2XZHXOYXDCIRJ2OTF2U4VZFWAC 25EX6COTFUVEIGQMCJ47FDSEKASVVO74LPJ4ZS66ZYUYXD5G3N3QC P5TRGRH7XMQSPCZKM5IEEO34TY6WMLGHHX7BU6Y453JFRXLUR2VQC VEVPRVWGRHRKBBUTO64ELK3NPZANUQI3ZZ7F23YXJQLKIORUW3HQC D7SLVLRNCYCBDYYRANHDG3JYEF25CFCSUY5FMF5KXVD5D4UZSDDAC 5CRNBCK3AH6UGZN4R5MZ47UCVYYA3CKFXYPKEPZWRTBJ5PIGDB6AC F4FAPEZ5P5CPHZIHUSRYULB3LY4LOJCUC7DZAYVL77LFFBUBCUNAC MPBVX6OOMRMXWV4AZG4MZ4B6BYMWHHF5OOLD5FUGQCHM6UKBCIEAC FXK7Y2F4YJE422WMQ6TYHONWVVDRWLWCU47BXHXCR53DHF6YC76AC IQVLEFABSOHRW24PGIX6XGDJQJG5NXYWLZTKE2V26ZS3OPMH2IZQC HDFQR3WVDBL62P3RTJ4LBIOTHHL2ZN4FHKUIBCERHLQYDRLHRTKQC EMOBSWJHHB4V6WVMZL7JCF2V3KZN454Z6NS346OKFPMBNO24EJDQC LH4OYDEWEON5QNUCM74R7MNBJDP7O4XRETY74ZMYSXUXYQV427PAC REOC4SN5SYUZ6IDLV6I6XZ4MPKE36VAJXLCZ2SXYYZB3RECLXSLQC BMZK7EPYNL2TBAQ7AWEJD466B4LI3RBPDXAIZCKBKJRIWOW7DCOAC IPCURZEWW7HBUKIBNAHSPTYD2HVABST6T5VRVLNIUPYGSFYJLPDAC S6NJIL6VIKUYD4VVXOT7V237J5WCKOIEBTNIMIF54CABA46KUETQC U56SICUKK36SJAG3QKV4WGDSAXOW5BELRPZGHTRAMZVUV56AESVAC FWLLPRIZDBJVQ336TPOLYAFT6WYGAFC52OFIOTRN2YQPFZ3PQVRQC JME76OR4ZNGHYVDVQ6ZT7FCB4UMG4V3RVMTQJQNQRRR66KARJHLQC FT2JKKQAUESFIMB2G5YGBI4FX7V7ARLOHWEKLP3M5MGV5ZCAAZMAC 6ZIZHBWWQC7HGUKAL5T2ADE3UXGFOEA7XNIIZOJO3DFPEW3TP7LAC F7U354ESXSJ4GWPN6CPJ2FZ2ASEO55WS6NHUPTOBPT3OCNFXTB7AC KVRDLMIRHKEMFKZ22JK5SZEDLDEXPEVOYWW535DN7EJVHL32IOMQC UIKSTCCPMCWUK6PVX5HTCPJOZHQWZXRQ2J3LTJPZDYVV2STFOQGAC 3RNRFLMD2X4RUFTDVITLXAP377YB6F6YMQLL3DAXSUZDZBTWSLRQC WQIEW3O4MANA2KKYRUWEZP44KHVJ4RRHEZTDXSF4EDELX66LO26QC 2YK255CF5YJ3LZTKOI633NJSVM63HFB3MAIYDV7ZJDCC5SWQIO6AC EJYK3CKIEMP4NMZUCMUYLHIBE7A3LPZOU7DUON5V7CPHY7QEKLEAC ZUV76RGZDBOY745YXVMGFUOWEH2B47J74BCT5MDKHIDHC4URGMKAC 3CY6KJWHQUZFZGO2C7VVCO32RRHUIMQQQJAE2MUXFF45F7ECRLJQC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC TFKOHHRA6CJ44OODVA2WL4ITYOLPE6VLKDS7XVBK5JH6BHVZDDFAC S2LIBA2CLTZ6ZU66AUZ2CCNLCDOBSGWQGTZ6HFAFP2XSWAALGLSQC IBCGW7GAP7MBB4EQ5Q6B6GAOUIYG3O7NLU2LCK37E7ZSDMTAAYZQC HIRKGUMNJPWKSVTR6TVBPD3MWNA63CEHCLCIPWEMGDFHVB3NPLDQC trap_type tt = trap_type_at_xy(x, y);if (tt == TRAP_SHAFT && _is_trap_safe(mon, x, y))e.push_back(level_exit(coord_def(x, y), MTRAV_TRAP, false));
if (trap_type_at_xy(x, y) == TRAP_SHAFT&& _is_trap_safe(mon, x, y)){e.push_back(level_exit(coord_def(x, y), false));}
case MTRAV_STAIR:
command_type dir = grid_stair_direction(grd[x][y]);simple_monster_message(mon,make_stringf(" %s the stairs.",dir == CMD_GO_UPSTAIRS ? "goes up" :dir == CMD_GO_DOWNSTAIRS ? "goes down": "takes").c_str());}else if (is_gate(grd[x][y]))simple_monster_message(mon, " passes through the gate.");// Shaft traps.else if (trap_type_at_xy(x, y) == TRAP_SHAFT)
if (is_travelable_stair(grd[x][y])){command_type dir = grid_stair_direction(grd[x][y]);simple_monster_message(mon,make_stringf(" %s the stairs.",dir == CMD_GO_UPSTAIRS ? "goes up" :dir == CMD_GO_DOWNSTAIRS ? "goes down": "takes").c_str());}else if (is_gate(grd[x][y]))simple_monster_message(mon, " passes through the gate.");break;
simple_monster_message(mon, " falls through a shaft!");grd[x][y] = trap_category(trap_type_at_xy(x, y));
trap_type tt = trap_type_at_xy(x, y);if (tt == TRAP_SHAFT){simple_monster_message(mon, " falls through a shaft!");grd[x][y] = trap_category(tt);}break;}case MTRAV_SUBMERSIBLE:
new_beh = BEH_LEAVE;break;
// If a pacified monster is far enough away from the// player, make it leave the level.if (grid_distance(mon->x, mon->y, you.x_pos, you.y_pos)>= LOS_RADIUS * LOS_RADIUS * 4){make_mons_leave_level(mon);return;}// If a pacified monster isn't travelling toward// someplace from which it can leave the level, make it// start doing so.if (mon->travel_target != MTRAV_PATROL&& mon->travel_target != MTRAV_UNREACHABLE){e_index = _mons_find_nearest_level_exit(mon, e);if (e_index != -1){mon->foe = MHITNOT;patrolling = true;mon->patrol_point = e[e_index].target;mon->target_x = e[e_index].target.x;mon->target_y = e[e_index].target.y;mon->travel_target = MTRAV_PATROL;mon->travel_path.clear();}}// If the level exit is unreachable, find a new one.if (mon->travel_target == MTRAV_UNREACHABLE){e[e_index].unreachable = true;mon->travel_target = MTRAV_NONE;}
// If the monster is far enough away from the player, make// it leave the level.if (grid_distance(mon->x, mon->y, you.x_pos, you.y_pos)>= LOS_RADIUS * LOS_RADIUS * 4){make_mons_leave_level(mon);return;}// If the monster isn't travelling toward someplace from// which it can leave the level, and it can move (or at// least teleport, as a mimic can), make it start doing so.if (mon->travel_target == MTRAV_NONE){e_index = _mons_find_nearest_level_exit(mon, e);if (e_index != -1){mon->foe = MHITNOT;mon->target_x = e[e_index].target.x;mon->target_y = e[e_index].target.y;mon->travel_target = e[e_index].target_type;if (travelling)mon->travel_path.clear();}}else if (mon->travel_target != MTRAV_UNREACHABLE|| one_chance_in(12)){#ifdef DEBUG_PATHFINDmprf("%s: Level exit out of reach! What now?",mon->name(DESC_PLAIN).c_str());#endif// If we're already on our way, do nothing.if (travelling){// Current target still valid?if (mon->x == mon->travel_path[0].x&& mon->y == mon->travel_path[0].y){// Get next waypoint.mon->travel_path.erase(mon->travel_path.begin() );if (!mon->travel_path.empty()){mon->target_x = mon->travel_path[0].x;mon->target_y = mon->travel_path[0].y;break;}}}}else{// Use pathfinding to find a (new) path to the level exit.const int dist = grid_distance(mon->x, mon->y,e[e_index].target.x,e[e_index].target.y);#ifdef DEBUG_PATHFINDmprf("Need to calculate a path... (dist = %d)", dist);#endifconst bool native = mons_is_native_in_branch(mon);int range = 0;switch (mons_intel(mon->type)){case I_PLANT:range = 2;break;case I_INSECT:range = 3;break;case I_ANIMAL:range = 4;break;case I_NORMAL:range = 8;break;default:// Highly intelligent monsters can find their way// anywhere. (range == 0 means no restriction.)break;}if (range && native)range += 3;if (range > 0 && dist > range){mon->travel_target = MTRAV_UNREACHABLE;#ifdef DEBUG_PATHFINDmprf("Distance too great, don't attempt pathfinding! (%s)",mon->name(DESC_PLAIN).c_str());#endif}else{#ifdef DEBUG_PATHFINDmprf("Need a path for %s from (%d, %d) to (%d, %d), ""max. dist = %d",mon->name(DESC_PLAIN).c_str(), mon->x, mon->y,e[e_index].target.x, e[e_index].target.y, range);#endifmonster_pathfind mp;if (range > 0)mp.set_range(range);if (mp.start_pathfind(mon, e[e_index].target)){mon->travel_path = mp.calc_waypoints();if (!mon->travel_path.empty()){// Okay then, we found a path. Let's use it!mon->target_x = mon->travel_path[0].x;mon->target_y = mon->travel_path[0].y;break;}else{#ifdef DEBUG_PATHFINDmpr("No path found!");#endifmon->travel_target = MTRAV_UNREACHABLE;// Pass information on to nearby monsters._mark_neighbours_target_unreachable(mon);}}else{#ifdef DEBUG_PATHFINDmpr("No path found!");#endifmon->travel_target = MTRAV_UNREACHABLE;// Pass information on to nearby monsters._mark_neighbours_target_unreachable(mon);}}}// If the level exit is unreachable, find a new one.if (mon->travel_target == MTRAV_UNREACHABLE){e[e_index].unreachable = true;mon->travel_target = MTRAV_NONE;}// If the monster is leaving the level via a stair or// submersion, and has reached its goal, handle it here.if ((mon->travel_target == MTRAV_STAIR|| mon->travel_target == MTRAV_SUBMERSIBLE)&& mon->x == e[e_index].target.x&& mon->y == e[e_index].target.y){make_mons_leave_level(mon);return;}
// Greatly lowered chances if the monster is fleeing or leaving the// level.if ((mons_is_fleeing(monster) || mons_is_leaving(monster))
// Greatly lowered chances if the monster is fleeing or pacified and// leaving the level.if ((mons_is_fleeing(monster) || mons_is_pacified(monster))
// If the monster is leaving the level via a trap, and is// about to reach its goal, handle it here.if (mons_is_leaving(monster)&& monster->travel_target == MTRAV_TRAP
// If a pacified monster is leaving the level via a trap,// and is about to reach its goal, handle it here.if (mons_is_pacified(monster)
MTRAV_UNREACHABLE, // Not travelling because target is unreachable.MTRAV_STAIR, // Travelling to reach a stair.MTRAV_TRAP, // Travelling to reach a trap.MTRAV_SUBMERSIBLE // Travelling to reach a submersible place.
MTRAV_UNREACHABLE // Not travelling because target is unreachable.