#if defined(macintosh) #include <types.h> #else #include <sys/types.h> #include <sys/time.h> #endif #include <ctype.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include "merc.h" #include "tables.h" #define PATH_MAX_VNUM 32768 #define PATH_MAX_DIR 6 // #define BITS_PER_INT (sizeof(int)*8) #define BITS_PER_INT 32 #define PATH_IS_FLAG(flag, bit) ((unsigned)flag[bit/BITS_PER_INT]>>bit%BITS_PER_INT&01) #define PATH_SET_FLAG(flag, bit) (flag[bit/BITS_PER_INT] |= 1 << bit%BITS_PER_INT) int find_path(ROOM_INDEX_DATA *from, ROOM_INDEX_DATA *to, int max_depth); extern char * const dir_name[]; void do_track(CHAR_DATA *ch, char *argument) { CHAR_DATA *victim; int i; int skill; char buf[MAX_STRING_LENGTH]; if (((skill = get_skill(ch,gsn_track)) == 0) || (IS_NPC(ch))) { send_to_char("You do not know how to track.\n\r",ch); return; } victim = get_char_world(ch, argument); if( victim == NULL ) { send_to_char("No one around by that name.\n\r", ch); return; } if(ch->in_room == victim->in_room) { act( "$N is here!", ch, NULL, victim, TO_CHAR ); return; } act("$n carefully sniffs the air.", ch, NULL, NULL, TO_ROOM); WAIT_STATE(ch, skill_table[gsn_track].beats); // What I do is use the player's track skill and level // to get the maximum length path track will find. // modify this however you want your track to work... skill /= 4; skill += ch->level/5; i = find_path(ch->in_room, victim->in_room, skill); //If you don't have chprintf, GET IT. Will save you about a billion buf[]'s. if (i == -1) act( "You couldn't find a path to $N from here.", ch, NULL, victim, TO_CHAR ); else { sprintf( buf, "$N is %s from here.", dir_name[i] ); act( buf, ch, NULL, victim, TO_CHAR ); } check_improve(ch, gsn_track, TRUE, 1); } int find_path(ROOM_INDEX_DATA *from, ROOM_INDEX_DATA *to, int max_depth) { int bitvector[PATH_MAX_VNUM/BITS_PER_INT]; ROOM_INDEX_DATA *rlist; ROOM_INDEX_DATA *track_room_list; int i, depth; bzero(bitvector, sizeof(bitvector)); PATH_SET_FLAG(bitvector, from->vnum); track_room_list = from; track_room_list->next_track = NULL; for (depth = 0; depth < max_depth; depth++) { rlist = track_room_list; track_room_list = NULL; for (; rlist; rlist = rlist->next_track) { for (i = 0; i < PATH_MAX_DIR; i++) { if (!rlist->exit[i] || !rlist->exit[i]->u1.to_room || PATH_IS_FLAG(bitvector, rlist->exit[i]->u1.to_room->vnum)) continue; PATH_SET_FLAG(bitvector, rlist->exit[i]->u1.to_room->vnum); rlist->exit[i]->u1.to_room->track_came_from = rlist; if (rlist->exit[i]->u1.to_room == to) { if (rlist == from) return i; // if you need access to the entire path, this is the place to get it. // basically it's back-tracking how it got to the destination. // Also a good place to hinder track based on sector, weather, etc. while (rlist->track_came_from != from) rlist = rlist->track_came_from; for (i = 0; i < PATH_MAX_DIR; i++) if (from->exit[i] && from->exit[i]->u1.to_room == rlist) return i; return -1; } else { rlist->exit[i]->u1.to_room->next_track = track_room_list; track_room_list = rlist->exit[i]->u1.to_room; } } } } return -1; }