#include "copyright.h" //#include <stdio.h> #include <stdlib.h> #include "db.h" #include "config.h" /* Compute shortest path to each room */ /* Locks cost extra */ #define INFINITY 2148575 /* MAXINT or thereabouts */ #define LOCK_COST 10000 /* extra cost for a lock */ /* This code blasts a lot of fields in the database, so */ /* you don't ever want to write it back out afterwards. */ /* Where things get stored: */ /* cost to get here gets put in pennies */ /* location is the previous room that gets you here */ /* next is the next room in the search queue */ /* key non-zero means already queued */ /* contents is previous exit that gets you here */ /* this should be a priority queue, but we're cheap */ dbref search_queue_head = NOTHING; dbref search_queue_tail = NOTHING; void queue_room (dbref room) { if (db[room].key) return; if (search_queue_tail == NOTHING) { search_queue_head = room; } else { db[search_queue_tail].next = room; } search_queue_tail = room; db[room].next = NOTHING; db[room].key = 1; } dbref dequeue_room (void) { dbref room; if ((room = search_queue_head) == NOTHING) return NOTHING; if ((search_queue_head = db[room].next) == NOTHING) { search_queue_tail = NOTHING; } db[room].next = NOTHING; db[room].key = 0; return room; } void find_paths (void) { dbref room; dbref exit; dbref mycost; /* dbref[room].pennies */ dbref cost; /* mycost + cost to use exit */ dbref dest; /* exit destination */ while ((room = dequeue_room ()) != NOTHING) { /* get first one */ /* check its exits */ mycost = db[room].pennies; DOLIST (exit, db[room].exits) { if ((dest = db[exit].location) < 0) continue; cost = mycost + 1; if (db[exit].key != NOTHING) { if (!(db[exit].flags & ANTILOCK) && Typeof (db[exit].key) != TYPE_THING) { continue; /* we can't get it */ } else { cost += LOCK_COST; } } if (cost < db[dest].pennies) { /* it's cheaper, set and queue it */ db[dest].pennies = cost; db[dest].location = room; db[dest].contents = exit; queue_room (dest); } } } } void compute_paths (dbref start) { dbref room; /* clear out all fields we use */ for (room = 0; room < db_top; room++) { if (Typeof (room) == TYPE_ROOM) { db[room].location = db[room].next = db[room].contents = NOTHING; db[room].pennies = INFINITY; db[room].key = 0; } } /* set up start */ db[start].pennies = 0; queue_room (start); find_paths (); } void print_path (dbref room) { dbref prev; dbref exit; dbref key; if ((prev = db[room].location) != NOTHING) { print_path (prev); exit = db[room].contents; if ((key = db[exit].key) != NOTHING) { printf ("LOCKED[%s(%d)] ", db[key].name, key); } printf ("%s => %s\n", db[exit].name, db[room].name); } } void print_paths (void) { dbref room; for (room = 0; room < db_top; room++) { if (Typeof (room) == TYPE_ROOM) { printf ("%s(%d)[%s]: ", db[room].name, room, db[db[room].owner].name); if (db[room].pennies == INFINITY) { puts ("UNREACHABLE"); } else { printf ("%d + %d locks\n", db[room].pennies % LOCK_COST, db[room].pennies / LOCK_COST); } print_path (room); putchar ('\n'); } } } int main (int argc, char **argv) { dbref start = 0; if (argc >= 2) { start = atol (argv[2]); } else { start = PLAYER_START; } if (db_read (stdin) < 0) { fprintf (stderr, "%s: bad input\n", argv[0]); exit (5); } compute_paths (start); print_paths (); return 0; }