/********************************************************************** zoneact.c Realms of Aurealis zone activities and spec/procs But, then I started adding room procs OLCable and activity.c got too long, so I have split up that file into two called mobact.c and roomact.c...note: sooner or later there will be zoneact.c as well to perform zone procs such as zone specific weather and what not... 3/13/97 - zoneact.c has been added -roa Author: jtrhone aka Vall of RoA **********************************************************************/ #include "conf.h" #include "sysdep.h" #include "structures.h" #include "utils.h" #include "db.h" #include "comm.h" #include "interpreter.h" #include "acmd.h" #include "handler.h" #include "magic.h" #include "bard.h" #include "lists.h" #include "fight.h" #define MARK(room) (SET_BIT(world[room].room_flags, BFS_MARK)) #define UNMARK(room) (REMOVE_BIT(world[room].room_flags, BFS_MARK)) #define IS_MARKED(room) (ROOM_FLAGGED((room), BFS_MARK)) /* external vars */ extern int rev_dir[]; // external functions extern void do_zone_storm(int zone); extern void do_zone_blizzard(int zone); extern void send_soundfile_to_client(dsdata *d, char *sname); void check_zone_music(void) { dsdata *d; for (d = descriptor_list; d;d=d->next) if (D_CHECK(d) && HAS_CLIENT(d) && d->zone_stimer > -1) { d->zone_stimer--; if (d->zone_stimer == 0) { int tozone; if (INVALID_ROOM(d->character->in_room)) continue; tozone = world[d->character->in_room].zone; // if not in the original zone, or the sound file is gone... if (!zone_table[tozone].sound_file || tozone != d->music_zone) { d->zone_stimer = -1; d->music_zone = -1; continue; } // else send it and set the numbers... send_soundfile_to_client(d, zone_table[tozone].sound_file); d->zone_stimer = zone_table[tozone].music_timer; d->music_zone = tozone; } } } /* control various zone aspects */ void zone_activity(void) { int i; check_zone_music(); for (i=0; i < NUM_ZONES; i++) if (REAL_ZONE(i) && !ZONE_FLAGGED(i, Z_FREED)) { if (ZONE_FLAGGED(i, Z_TSTORM)) { if (zone_table[i].current_gtemp > 32) { if (number(0,1)) do_zone_storm(i); } else { REMOVE_BIT(ZONE_FLAGS(i), Z_TSTORM); SET_BIT(ZONE_FLAGS(i), Z_BLIZZARD); } } if (ZONE_FLAGGED(i, Z_BLIZZARD)) { if (zone_table[i].current_gtemp <= 32) { if (number(0,1)) do_zone_blizzard(i); } else { REMOVE_BIT(ZONE_FLAGS(i), Z_BLIZZARD); SET_BIT(ZONE_FLAGS(i), Z_TSTORM); } } } } // use source rooms to dictate descs for every other room in zone // except other sources and NOGEN rooms int generate_descrips(int zone, int *room_stack, int room_top) { int source_stack[100], source_top = 0, spick, i; extern exdescdata *free_extra_descrips(exdescdata *head); extern exdescdata *dupe_exdesc_over(exdescdata *head); // stick all source rooms into a source stack for fast pickins -roa for (i = 0; i < room_top; i++) if (ROOM_FLAGGED2(room_stack[i], SOURCE_ROOM)) source_stack[source_top++] = room_stack[i]; if (!source_top) { sprintf(buf, "SYSERR: No SOURCE rooms in DESCGEN zone %d.",zone); mudlog(buf, BRF, LEV_IMM, TRUE); return FALSE; } // no go thru rooms, each one that isnt SOURCE or NOGEN, // assign it a descript from source_stack for (i = 0; i < room_top; i++) if (!ROOM_FLAGGED2(room_stack[i], SOURCE_ROOM) && !ROOM_FLAGGED2(room_stack[i], NOGEN_ROOM)) { FREENULL(world[room_stack[i]].name); FREENULL(world[room_stack[i]].description); world[room_stack[i]].exdesc = free_extra_descrips(world[room_stack[i]].exdesc); // now pick one from sources, and dupe it over spick = number(0, source_top -1); world[room_stack[i]].name = STR_DUP(world[source_stack[spick]].name); world[room_stack[i]].description = STR_DUP(world[source_stack[spick]].description); world[room_stack[i]].exdesc = dupe_exdesc_over(world[source_stack[spick]].exdesc); } sprintf(buf, "SYSUPD: Zone %d: AutoDescGen with %d source rooms.",zone, source_top-1); mudlog(buf, BUG, LEV_IMM, TRUE); return TRUE; } // given zone, two room rnums, and the stack (unused at this point) // try to "rconnect" them with an unused direction int hookup_rooms(int zone, int cur, int pick, int *room_stack, int room_top) { int dir, rdir, num = 0; rmdata *otherroom, *thisroom; do { dir = number(0, NUM_OF_DIRS - 1); if (num++ > 50) // check umpteen times { // log("Gave up."); return FALSE; // couldn't find one :( } // if lateral zone, don't go up or down -roa } while (DIR(cur, dir) || DIR(pick, rev_dir[dir]) || (ZONE_FLAGGED(zone, Z_EXITGENLAT) && (dir == 4 || dir == 5))); rdir = rev_dir[dir]; thisroom = &world[cur]; otherroom = &world[pick]; // create dir to new room CREATE(thisroom->dir_option[dir], rmdirdata, 1); thisroom->dir_option[dir]->keyword = NULL; thisroom->dir_option[dir]->exit_descr = NULL; // Exit messages. 03/24/98 -callahan thisroom->dir_option[dir]->enter = NULL; thisroom->dir_option[dir]->oenter = NULL; thisroom->dir_option[dir]->drop = NULL; thisroom->dir_option[dir]->odrop = NULL; thisroom->dir_option[dir]->to_room_virtual = otherroom->number; thisroom->dir_option[dir]->to_room = pick; // create dir from new room to thisroom CREATE(otherroom->dir_option[rdir], rmdirdata, 1); otherroom->dir_option[rdir]->keyword = NULL; otherroom->dir_option[rdir]->exit_descr = NULL; // Exit messages. 03/24/98 -callahan otherroom->dir_option[rdir]->enter = NULL; otherroom->dir_option[rdir]->oenter = NULL; otherroom->dir_option[rdir]->drop = NULL; otherroom->dir_option[rdir]->odrop = NULL; otherroom->dir_option[rdir]->to_room_virtual = thisroom->number; otherroom->dir_option[rdir]->to_room = real_room(thisroom->number); return TRUE; } // only call if EXITGENALL or EXITGENLAT zone int wax_dirs(int zone, int *stk, int top) { int i = 0, dir; if (!ZONE_FLAGGED(zone, Z_EXITGENALL) && !ZONE_FLAGGED(zone, Z_EXITGENLAT)) return FALSE; for ( ; i < top; i++) for (dir = 0; dir < NUM_OF_DIRS; dir++) { // if it leads to another zone, dont kill it if (DIR(stk[i], dir) && !EXIT_FLAGGED(DIR(stk[i], dir), EX_NOGEN) && (INVALID_ROOM(DIR(stk[i], dir)->to_room) || world[DIR(stk[i], dir)->to_room].zone == zone)) { // wax the puppy FREENULL(DIR(stk[i], dir)->keyword); FREENULL(DIR(stk[i], dir)->exit_descr); // Nuke exit messages. 03/24/98 -callahan FREENULL(DIR(stk[i], dir)->enter); FREENULL(DIR(stk[i], dir)->oenter); FREENULL(DIR(stk[i], dir)->drop); FREENULL(DIR(stk[i], dir)->odrop); FREENULL(DIR(stk[i], dir)); } } return TRUE; } // there is an unmarked room in said stack of rnums int has_unmarked(int *stk, int top) { int i; for (i = 0; i < top; i++) if (!IS_MARKED(stk[i])) return TRUE; return FALSE; } // generate a random zone for auto generate zones int generate_zone(int zone) { int cur, pick; int rnum, vnum, last; int room_stack[100], picked_stack[100]; int room_top = 0, picked_top = 0; last = zone*100+99; for (vnum=zone*100; vnum <= last; vnum++) if ((rnum = real_room(vnum)) > 0) { UNMARK(rnum); room_stack[room_top++] = rnum; } if (!room_top) // no rooms in zone? { sprintf(buf, "SYSERR: No rooms in autogen zone %d.",zone); mudlog(buf, BRF, LEV_IMM, TRUE); return FALSE; } // ok, we have our stack of rooms from this zone // now send it over to generate_descripts if (ZONE_FLAGGED(zone, Z_DESCGEN)) generate_descrips(zone, room_stack, room_top); // ok we done with descrips for now, if no exit to be done, go home if (!ZONE_FLAGGED(zone, Z_EXITGENALL) && !ZONE_FLAGGED(zone, Z_EXITGENLAT)) return TRUE; // ok, assume descrips are generated, now do dirs... wax_dirs(zone, room_stack, room_top); // the actual dir generation algorithm cur = room_stack[number(0, room_top - 1)]; MARK(cur); while (has_unmarked(room_stack, room_top)) // this could take forever! { pick = room_stack[number(0, room_top - 1)]; if (IS_MARKED(pick) && picked_top > 0) { cur = picked_stack[--picked_top]; } else { if (!IS_MARKED(pick)) if (hookup_rooms(zone, cur, pick, room_stack, room_top)) MARK(pick); picked_stack[picked_top++] = cur; cur = pick; } } sprintf(buf, "SYSUPD: Zone %d: AutoExit Generation.", zone); mudlog(buf, BUG, LEV_IMM, TRUE); return TRUE; }