/***************************************************************************
* Mud20 1.0 by Todd H. Johnson (Kregor) a derivative of the Open Gaming *
* License by Wizards of the Coast. All comments referring to D20, OGL, *
* and SRD refer to the System Reference Document for the Open Gaming *
* system. Any inclusion of these derivatives must include credit to the *
* Mud20 system, the full and complete Open Gaming LIcense, and credit to *
* the respective authors. See ../doc/srd.txt for more information. *
* *
* Emud 2.2 by Igor van den Hoven, Michiel Lange, and Martin Bethlehem. *
* *
* MrMud 1.4 by David Bills, Dug Michael and Martin Gallwey *
* *
* Merc 2.1 Diku Mud improvments copyright (C) 1992, 1993 by Michael *
* Chastain, Michael Quan, and Mitchell Tse. *
* *
* Original Diku Mud copyright (C) 1990 1991 by Sebastian Hammer, *
* Michael Seifert, Hans Henrik St{rfeld, Tom Madsen, and Katje Nyboe. *
***************************************************************************/
/***************************************************************************
* pathfind.c: Pathfinding functions *
***************************************************************************/
#include "mud.h"
bool world_index[2000];
ROOM_INDEX_DATA * pfind_dest;
CHAR_DATA * pfind_char;
CHAR_DATA * pfind_mob;
AREA_DATA * pfind_area;
char * pfind_name;
bool pfind_cnt;
sh_int valid_exit;
sh_int pfind_dir;
bool valid_pfind_exit( EXIT_DATA *pExit )
{
if (room_index[pExit->to_room] == NULL)
{
return FALSE;
}
if (room_index[pExit->to_room]->area != pfind_area)
{
return FALSE;
}
return TRUE;
}
/*
Fast short distance node weighted algorithm, can be used to backtrack the
entire shortest path - Scandum
*/
void findpath_dest(ROOM_INDEX_DATA *room, bool cnt)
{
bool door;
world_index[room->vnum - room->area->low_r_vnum] = cnt;
if (room == pfind_dest)
{
pfind_cnt = cnt;
valid_exit = pfind_dir;
}
else if (cnt < pfind_cnt)
{
cnt++;
for (door = 0 ; door < 6 ; door++)
{
if (room->exit[door] && valid_pfind_exit(room->exit[door]))
{
if (world_index[room->exit[door]->to_room - room->area->low_r_vnum] > cnt)
{
findpath_dest(room_index[room->exit[door]->to_room], cnt);
}
}
}
}
}
void findpath_name(ROOM_INDEX_DATA *room, bool cnt)
{
CHAR_DATA *rch;
bool door;
world_index[room->vnum - room->area->low_r_vnum] = cnt;
if (pfind_cnt > cnt)
{
for (rch = room->first_person ; rch ; rch = rch->next_in_room)
{
if (is_name_short(pfind_name, rch->name) && can_see(pfind_char, rch) && can_hear(pfind_char, rch))
{
pfind_cnt = cnt;
pfind_mob = rch;
return;
}
}
cnt++;
for (door = 0 ; door < 6 ; door++)
{
if (room->exit[door] && valid_pfind_exit(room->exit[door]))
{
if (world_index[room->exit[door]->to_room - room->area->low_r_vnum] > cnt)
{
findpath_name(room_index[room->exit[door]->to_room], cnt);
}
}
}
}
}
int findpath_search_victim( CHAR_DATA *ch, CHAR_DATA *victim, int range )
{
int area_size;
push_call("findpath_search_victim(%p,%p,%p)",ch,victim,range);
if (ch->in_room == victim->in_room)
{
pop_call();
return -2;
}
if (ch->in_room->area != victim->in_room->area)
{
pop_call();
return -1;
}
if ((area_size = ch->in_room->area->hi_r_vnum - ch->in_room->area->low_r_vnum) >= 2000)
{
log_build_printf(ch->in_room->vnum, "findpath_search_victim: Area too big");
pop_call();
return -1;
}
pfind_area = ch->in_room->area;
pfind_mob = victim;
pfind_dest = victim->in_room;
pfind_cnt = range;
valid_exit = -1;
memset(world_index, 128, area_size);
world_index[ch->in_room->vnum - ch->in_room->area->low_r_vnum] = 0;
for (pfind_dir = 0 ; pfind_dir < 6 ; pfind_dir++)
{
if (ch->in_room->exit[pfind_dir] && valid_pfind_exit(ch->in_room->exit[pfind_dir]))
{
findpath_dest(room_index[ch->in_room->exit[pfind_dir]->to_room], 1);
}
}
pop_call();
return valid_exit;
}
int findpath_room( CHAR_DATA *ch, int vnum, int range )
{
int area_size;
ROOM_INDEX_DATA *room;
push_call("findpath_room(%p,%p,%p)",ch,vnum,range);
if ((room = get_room_index(vnum)) == NULL)
{
log_build_printf(ch->in_room->vnum, "findpath_room: invalid room vnum");
pop_call();
return -1;
}
if (ch->in_room == room)
{
pop_call();
return -2;
}
if (ch->in_room->area != room->area)
{
pop_call();
return -1;
}
if ((area_size = ch->in_room->area->hi_r_vnum - ch->in_room->area->low_r_vnum) >= 2000)
{
log_build_printf(ch->in_room->vnum, "findpath_room: Area too big");
pop_call();
return -1;
}
pfind_area = ch->in_room->area;
pfind_dest = room;
pfind_cnt = range;
valid_exit = -1;
memset(world_index, 128, area_size);
world_index[ch->in_room->vnum - ch->in_room->area->low_r_vnum] = 0;
for (pfind_dir = 0 ; pfind_dir < 6 ; pfind_dir++)
{
if (ch->in_room->exit[pfind_dir] && valid_pfind_exit(ch->in_room->exit[pfind_dir]))
{
findpath_dest(room_index[ch->in_room->exit[pfind_dir]->to_room], 1);
}
}
pop_call();
return valid_exit;
}
CHAR_DATA *findpath_search_name( CHAR_DATA *ch, char *name, int range )
{
CHAR_DATA *victim;
int area_size;
push_call("findpath_search_name(%p,%p,%p)",ch,name,range);
if ((victim = get_char_room(ch, name)) != NULL)
{
pop_call();
return victim;
}
if ((area_size = ch->in_room->area->hi_r_vnum - ch->in_room->area->low_r_vnum) >= 2000)
{
log_build_printf(ch->in_room->vnum, "findpath_search_name: Area too big");
pop_call();
return NULL;
}
pfind_area = ch->in_room->area;
pfind_name = name;
pfind_mob = NULL;
pfind_char = ch;
pfind_cnt = range;
memset(world_index, 128, area_size);
world_index[ch->in_room->vnum - ch->in_room->area->low_r_vnum] = 0;
for (pfind_dir = 0 ; pfind_dir < 6 ; pfind_dir++)
{
if (ch->in_room->exit[pfind_dir] && valid_pfind_exit(ch->in_room->exit[pfind_dir]))
{
findpath_name(room_index[ch->in_room->exit[pfind_dir]->to_room], 1);
}
}
pop_call();
return pfind_mob;
}