/** information for paths.c ************************************** * * * A lot of effort and time has been put into this code and * * text. Permission to use it is granted provided that you * * keep the headers intact. * * I would like VERY much any comments/suggestions you might * * have. If you use this code, I would appreciate very much a * * mail just saying you did! :) * * * * Jorge Ribeiro Pereira, <evren_ash@hotmail.com> 20/12/1998 * * * ******************************************************************/ ************************************************************* INDEX: ************************************************************* SECTION 0 - Introduction - IMPORTANT SECTION 1 - Why would you want to use this code? SECTION 2 - Changes needed for this code to work SECTION 3 - Replacing the older track/hunt code SECTION 4 - The functions and example commands in this code ( important ) ************************************************************* SECTION 0: ************************************************************* I've tested this with Envy, but it should work on Merc based muds. It can be easily altered to most other code bases though. Some instructions might not be very accurate, since I've recoded my Envy base nearly beyond recognition(kidding!), so if something is completly non-understandable, please mail me so I can fix this document. :) For those who don't want to read this whole document, or aren't really interested in new functions, the bottom line is that the get_direction() function in paths.c is a replacement for the find_path() function that ships with the code in track.c(or hunt.c) files (think from SillyMud). Also, if that's the only function you're planning to use, you just need to perform step 1, 2 and 4 of section 2 (note for programmers) I initially had included in this file versions of these functions that didn't do the path length checking, that is, returned not the best path, but only the first they could find. You can easily change the existing functions to have that behavior (by just adding a "break" after a path is found in the loop), though I doubt you'd want to. Anyway, if you're by any means interested in that, or other variations of this code, just mail me. ************************************************************* SECTION 1: ************************************************************* 1) I believe this code to be a LOT faster then the code used in any of the tracking codes I've seen so far. The trick is in the "visited" field we add to room_index_data (see below) which avoids the need for building a whole data structure to keep track of the path's we've discarded(or other algorithm, exclusion or whatever). 2) The get_direction function gets the BEST (shortest) path between two rooms, which avoids that problem of beeing told to go north, then beeing told to go south, then beeing told to go north... (loop), because it's always following the same path, and not just following the one that appears first in memory (think this is fixed in some versions of the track code, but not sure on which). 3) If you take a close look, you'll soon notice that the those functions returning directions never even need to allocate any memory, and that also adds a lot of performance increase, since mallocing is a s l o w operation. Also, there's a nifty function, get_dir_somewhere(), that given a predicate function will look for the path to a room that matches the predicate, and return the direction. get_path_somewhere() does the same but returns a path, like get_path does. A predicate function is a function that given a room pointer and an argument returns TRUE or FALSE. This is looked into with more detail in section 4, and is more simple then I it probably looks, just check out the code. I also provide functions that will return the full path ( not only a direction) towards a room. ************************************************************* SECTION 2 - Changes needed for this code to work ************************************************************* You can get this to work with these steps: 1) You need to add an extra field to the room_index_data structure in merc.h. Add the line marked with ++: -- merc.h ------------------------------------------------ struct room_index_data { ROOM_INDEX_DATA * next; CHAR_DATA * people; OBJ_DATA * contents; EXTRA_DESCR_DATA * extra_descr; AREA_DATA * area; EXIT_DATA * exit [MAX_DIR]; ++ bool visited; /* paths.c */ ----------------------------------------------------------- 2) You need to declare the functions somewhere in merc.h so they can be used anywhere. You could declare them all in merc.h, together with the PATH_DATA type, but you can keep them all in paths.c if you'e not planning to use any other functions. Add to your merc.h file: -- merc.h ------------------------------------------------ ++ int get_direction ( ROOM_INDEX_DATA *pOrig, ++ ROOM_INDEX_DATA *pDest, bool pass_doors ); --------------------------------------------------------- 3) If you wish to test the example commands(see below), add the command declarations to your merc.h: -- merc.h -------------------------------------------------- ++ DECLARE_DO_FUN( do_path ); ++ DECLARE_DO_FUN( do_direction ); ++ DECLARE_DO_FUN( do_whereto ); ------------------------------------------------------------ 4) Now all you need to do is adding the file to the Makefile Add paths.o to the O_FILES variable in your Makefile, and type "make" (this is the Envy procedure, not sure about others) ************************************************************* SECTION 3 - Replacing the older track/hunt code. ************************************************************* 1) You need to replace the find_path() function with the get_direction() function, wherever it shows up ( either track.c or hunt.c ). If you have none of these, I suggest you get the track code from, eg: ftp.games.org, and then get back to this. hint: if you have no idea, on the command line type: grep -i "find_path" *.c *.h 1.1) in the do_track / skill_track function replace: -- direction = find_path( ch->in_room->vnum, -- victim->in_room->vnum, -- ch, -40000, fArea ); with: ++ direction = get_direction( ch->in_room, ++ victim->in_room, TRUE ); 1.2) in the hunt_victim function replace: -- dir = find_path( ch->in_room->vnum, -- ch->hunting->who->in_room->vnum, -- ch, -40000, TRUE ); with: ++ dir = get_direction( ch->in_room, ++ ch->hunting->who->in_room, TRUE ); ************************************************************* SECTION 4 - The functions and example commands in this code ************************************************************* Main functions in paths.c get_direction : returns a direction for the shortest path towards a room. This can be used to replace the find_path function that ships with the track/hunt code. get_path : builds a list of the rooms that make the shortest path between two rooms get_dir_somewhere : given a function that takes a room and an argument and returns TRUE or FALSE, returns the shortest path to a room to which that function evaluates TRUE. get_path_somewhere : same as the above, but returns the path, like get_path does. ( check the examples for these functions in do_whereto() ) ( the above functions take a boolean value as last argument that when set to TRUE, will make the functions search paths through doors. The first argument for them is a pointer to the origin room, and the last argument a pointer to the destination room ) do_direction : a simple command that given a room vnum will return the direction you have to follow to get there. It's an example of how to use get_direction() do_path : a simple command that given a room vnum will return the full list of direction you have to take to get there. follow to get to it. It's an example of how to use get_path() is_room_name : function that given a room pointer and a string checks if the room has the string in its name. Used as an argument to get_dir_somewhere, to build the do_whereto command(below) do_whereto : an example command of how to use get_dir_somewhere(). Given a string argument returns the shortest path to a room with that string as name. // auxiliar functions - Some of the functions above provide the entry point to recursive functions. These have the same name with "_" as suffix. (example: get_path() and get_path_() ) path_string : given a path, returns a string with the directions (uses a static buffer). free_path : frees the memory allocated for a path. add_to_path : adds a room(from a direction) to a path. new_path_data : creates an empty path data. It's the same as using add_to_path on a NULL list. WARNING: When using get_path and get_path_somewhere, don't forget to free the memory for the path it returns by using free_path. Check the do_path command for an example. NOTE: You could well change the "malloc" in new_path_data and append_path to use some other mem allocation code, like alloc_mem. THE END ----------------------------------------------------------------------- - Evren ( Jorge Pereira <evren_ash@hotmail.com> ) Braga - Portugal, 20/12/1998