/* SillyMUD Distribution V1.1b (c) 1993 SillyMUD Developement See license.doc for distribution terms. SillyMUD is based on DIKUMUD With an attempt by Rip to convert to merc 2.1 */ #include <stdio.h> #include "merc.h" #include "hash.h" struct hunting_data { char *name; struct char_data **victim; }; struct room_q { int room_nr; struct room_q *next_q; }; struct nodes { int visited; int ancestor; }; int exit_ok( EXIT_DATA *pexit ) { ROOM_INDEX_DATA *to_room; if ( ( pexit == NULL ) || ( to_room = pexit->to_room ) == NULL ) return (0); return (1); } void donothing() { return; } #define IS_DIR (get_room_index(q_head->room_nr)->exit[i]) #define GO_OK (!IS_SET( IS_DIR->exit_info, EX_CLOSED ) \ || IS_AFFECTED( ch, AFF_PASS_DOOR ) ) /* #define GO_OK_SMARTER ( !IS_SET( IS_DIR->exit_info, EX_LOCKED ) \ || IS_AFFECTED( ch, AFF_PASS_DOOR ) ) */ #define GO_OK_SMARTER 1 int find_path(int in_room_vnum, int out_room_vnum, CHAR_DATA *ch, int depth, int in_zone) { struct room_q *tmp_q, *q_head, *q_tail; #if 1 struct hash_header x_room; /* static struct hash_header x_room; */ #else struct nodes x_room[MAX_ROOMS]; #endif int i, tmp_room, count=0, thru_doors; ROOM_INDEX_DATA *herep, *therep; ROOM_INDEX_DATA *startp; EXIT_DATA *exitp; #if 0 if (top_of_world > MAX_ROOMS) { log("TRACK Is disabled, too many rooms.\n\rContact Loki soon.\n\r"); return -1; } #endif if (depth<0) { thru_doors = TRUE; depth = - depth; } else { thru_doors = FALSE; } startp = get_room_index(in_room_vnum); init_hash_table(&x_room, sizeof(int), 2048); hash_enter(&x_room, in_room_vnum, (void*)-1); /* initialize queue */ q_head = (struct room_q *) malloc(sizeof(struct room_q)); q_tail = q_head; q_tail->room_nr = in_room_vnum; q_tail->next_q = 0; while(q_head) { herep = get_room_index(q_head->room_nr); /* for each room test all directions */ if (herep->area == startp->area || !in_zone) { /* only look in this zone.. saves cpu time. makes world safer for players */ for(i = 0; i <= 5; i++) { exitp = herep->exit[i]; if (exit_ok(exitp) && (thru_doors ? GO_OK_SMARTER : GO_OK)) { /* next room */ tmp_room = herep->exit[i]->to_room->vnum; if (tmp_room != out_room_vnum) { /* shall we add room to queue ? */ /* count determines total breadth and depth */ if(!hash_find(&x_room,tmp_room) && (count < depth) ) /* && !IS_SET(RM_FLAGS(tmp_room),DEATH)) */ { count++; /* mark room as visted and put on queue */ tmp_q = (struct room_q *) malloc(sizeof(struct room_q)); tmp_q->room_nr = tmp_room; tmp_q->next_q = 0; q_tail->next_q = tmp_q; q_tail = tmp_q; /* ancestor for first layer is the direction */ hash_enter(&x_room, tmp_room, ((int)hash_find(&x_room,q_head->room_nr) == -1) ? (void*)(i+1) : hash_find(&x_room,q_head->room_nr)); } } else { /* have reached our goal so free queue */ tmp_room = q_head->room_nr; for(;q_head;q_head = tmp_q) { tmp_q = q_head->next_q; free(q_head); } /* return direction if first layer */ if ((int)hash_find(&x_room,tmp_room)==-1) { if (x_room.buckets) { /* junk left over from a previous track */ destroy_hash_table(&x_room, donothing); } return(i); } else { /* else return the ancestor */ int i; i = (int)hash_find(&x_room,tmp_room); if (x_room.buckets) { /* junk left over from a previous track */ destroy_hash_table(&x_room, donothing); } return( -1+i); } } } } } /* free queue head and point to next entry */ tmp_q = q_head->next_q; free(q_head); q_head = tmp_q; } /* couldn't find path */ if (x_room.buckets) { /* junk left over from a previous track */ destroy_hash_table(&x_room, donothing); } return(-1); } void do_whichway( CHAR_DATA *ch, char *argument ) { char buf[MAX_STRING_LENGTH]; char arg[MAX_STRING_LENGTH]; CHAR_DATA *victim; int direction; one_argument( argument, arg ); if (arg[0] == '\0') { send_to_char("Which way to WHAT?\n\r", ch ); return; } if ( (victim = get_char_world( ch, arg ) ) == NULL ) { send_to_char("No such victim!\n\r", ch ); return; } direction = find_path( ch->in_room->vnum, victim->in_room->vnum, ch, -40000, FALSE ); switch (direction) { case DIR_NORTH: send_to_char("Your quarry is to the north.\n\r", ch ); break; case DIR_SOUTH: send_to_char("Your quarry is to the south.\n\r", ch ); break; case DIR_EAST: send_to_char("Your quarry is to the east.\n\r", ch ); break; case DIR_WEST: send_to_char("Your quarry is to the west.\n\r", ch ); break; case DIR_UP: send_to_char("Your quarry is up.\n\r", ch ); break; case DIR_DOWN: send_to_char("Your quarry is down.\n\r", ch ); break; } return; } void do_sic_mob( CHAR_DATA *ch, char *argument ) { CHAR_DATA *victim; CHAR_DATA *mob; OBJ_DATA *obj; char arg[MAX_STRING_LENGTH]; one_argument( argument, arg ); if (arg[0] == '\0') { send_to_char("Sic em on who?\n\r", ch ); return; } if ( ( victim = get_char_world( ch, arg ) ) == NULL ) { send_to_char("They aren't here.\n\r", ch ); return; } if ( victim->desc == NULL) { send_to_char("Not a player.\n\r", ch ); return; } mob = create_mobile( get_mob_index( 10 ) ); mob->hunting = victim; obj = create_object( get_obj_index(50), 0 ); obj_to_char( obj, mob ); equip_char( mob, obj, WEAR_WIELD ); obj = create_object( get_obj_index(3620), 0 ); obj_to_char( obj, mob ); equip_char( mob, obj, WEAR_SHIELD ); char_to_room( mob, get_room_index(ROOM_VNUM_TEMPLE) ); return; }