dotd-2.3.7/area/
dotd-2.3.7/clans/
dotd-2.3.7/classes/
dotd-2.3.7/councils/
dotd-2.3.7/deity/
dotd-2.3.7/dict/
dotd-2.3.7/doc/mudprogs/
dotd-2.3.7/player/a/
dotd-2.3.7/player/g/
#include <stdio.h>

#include "mud.h"

extern ROOM_INDEX_DATA *room_index_hash[MAX_KEY_HASH];

struct visited
{
    struct visited *next;
    void *data;
    void *data2;
};

struct visited *vlist = NULL;

bool is_visited(void *data)
{
    struct visited *v;

    for (v = vlist; v; v = v->next)
	if (v->data == data)
	    return TRUE;
    return FALSE;
}

bool is_visited_pair(void *data, void *data2)
{
    struct visited *v;

    for (v = vlist; v; v = v->next)
	if ((v->data == data &&
	     v->data2 == data2) ||
	    (v->data == data2 &&
	     v->data2 == data))
	    return TRUE;
    return FALSE;
}

void add_visited(void *data)
{
    struct visited *v;

    CREATE(v, struct visited, 1);
    v->data = data;

    v->next = vlist;
    vlist = v;
}

void add_visited_pair(void *data, void *data2)
{
    struct visited *v;

    CREATE(v, struct visited, 1);
    v->data = data;
    v->data2 = data2;

    v->next = vlist;
    vlist = v;
}

void free_visited(void)
{
    struct visited *v;

    while (vlist)
    {
        v = vlist;
        vlist = vlist->next;
        DISPOSE(v);
    }
}

static void graph_recurse( FILE *fp, ROOM_INDEX_DATA *room, int recurse_level )
{
    EXIT_DATA *xit;

    if (recurse_level++ > 15)
        return;

    if (!room->first_exit || IS_ROOM_FLAG(room, ROOM_ORPHANED))
	return;

    fprintf(fp, "    \"%s (%d)\" -- ", room->name, room->vnum);

    if (room->first_exit != room->last_exit)
	fprintf(fp, "{ ");

    for ( xit = room->first_exit; xit; xit = xit->next )
    {
	if ( IS_EXIT_FLAG(xit, EX_PORTAL) )
	    continue;

	fprintf(fp, "\"%s (%d)\" ", xit->to_room->name, xit->vnum);
    }
    if (room->first_exit != room->last_exit)
	fprintf(fp, "}");
    fprintf(fp, ";\n");

    for ( xit = room->first_exit; xit; xit = xit->next )
    {
	if ( IS_EXIT_FLAG(xit, EX_PORTAL) )
	    continue;

	if (is_visited(xit->to_room))
	    continue;
	add_visited(xit->to_room);

        graph_recurse(fp, xit->to_room, recurse_level);
    }
}

static void graph_area(ROOM_INDEX_DATA *first_room)
{
    FILE *fp;
    char filename[MAX_INPUT_LENGTH];

    sprintf(filename, "%s.dot", first_room->area->filename);

    if (!(fp = fopen(filename, "w")))
        return;

    fprintf(fp, "graph G {\n");

    vlist = NULL;
    add_visited(first_room);

    graph_recurse(fp, first_room, 0);

    free_visited();

    fprintf(fp, "}\n");

    fclose(fp);
}

static void graph_mud(void)
{
    FILE *fp;
    ROOM_INDEX_DATA *pRoomIndex;
    EXIT_DATA *pexit;
    char filename[16];
    int hash;

    sprintf(filename, "mud.dot");

    if (!(fp = fopen(filename, "w")))
        return;

    fprintf(fp, "graph G {\n");

    for ( hash = 0; hash < MAX_KEY_HASH; hash++ )
	for ( pRoomIndex = room_index_hash[hash]; pRoomIndex; pRoomIndex = pRoomIndex->next )
	{
	    for ( pexit = pRoomIndex->first_exit; pexit; pexit = pexit->next )
	    {
		if (IS_ROOM_FLAG(pexit->to_room, ROOM_ORPHANED) ||
		    IS_ROOM_FLAG(pRoomIndex, ROOM_ORPHANED))
		    continue;

		if (is_visited_pair(pRoomIndex->area, pexit->to_room->area))
		    continue;

		if (pexit->to_room->area != pRoomIndex->area )
		{
		    add_visited_pair(pexit->to_room->area, pRoomIndex->area);
		    fprintf(fp, "    \"%s\" -- \"%s\"\n",
			    pexit->to_room->area->name,
                            pRoomIndex->area->name);
		}
	    }
	    if (pRoomIndex->tele_vnum)
	    {
		ROOM_INDEX_DATA *to_room = get_room_index(pRoomIndex->tele_vnum);

		if (!to_room)
		    continue;

		if (IS_ROOM_FLAG(to_room, ROOM_ORPHANED) ||
		    IS_ROOM_FLAG(pRoomIndex, ROOM_ORPHANED))
		    continue;

		if (is_visited_pair(pRoomIndex->area, to_room->area))
		    continue;

		if (to_room->area != pRoomIndex->area )
		{
		    add_visited_pair(to_room->area, pRoomIndex->area);
		    fprintf(fp, "    \"%s\" -- \"%s\"\n",
			    to_room->area->name,
			    pRoomIndex->area->name);
		}

	    }
	}
    fprintf(fp, "}\n");

    fclose(fp);

    free_visited();
}

void do_graphviz(CHAR_DATA *ch, char *argument)
{
    if (!argument || !*argument)
    {
	graph_area( ch->in_room );

	send_to_char( "Done.\n\r", ch );
        return;
    }

    graph_mud();
    send_to_char("Done.\n\r", ch);
}