/****************************************************************************** Snippet: Wilderness system (v1.0). Author: Richard Woolcock (aka KaVir). Date: 2nd September 1998. ****************************************************************************** File: wild_move.c Purpose: Deals with wilderness movement. ****************************************************************************** This code is copyright (C) 1998 by Richard Woolcock. It may be used and distributed freely, as long as you do not remove this copyright notice. ******************************************************************************/ /****************************************************************************** Required libraries ******************************************************************************/ #include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "merc.h" #include "wild.h" /****************************************************************************** Global variables ******************************************************************************/ CHAR_DATA * first_wilderness = NULL; CHAR_DATA * last_wilderness = NULL; static int highest_room_vnum; /****************************************************************************** Local operation prototypes ******************************************************************************/ AREA_DATA * wilderness_vnum args( ( void ) ); ROOM_INDEX_DATA * new_room_index args( ( void ) ); EXIT_DATA * make_new_exit args( ( void ) ); void char_to_wilderness args( ( CHAR_DATA *ch ) ); void generate_mob args( ( int vnum, \ RID_T *pRoom ) ); /****************************************************************************** Global operations ******************************************************************************/ /* Move a character from the wilderness. */ void char_from_wilderness( CHAR_DATA *ch ) { if ( ch->prev_wilderness != NULL && ch->next_wilderness != NULL ) { ch->prev_wilderness->next_wilderness = ch->next_wilderness; ch->next_wilderness->prev_wilderness = ch->prev_wilderness; } else if ( ch->prev_wilderness != NULL ) { ch->prev_wilderness->next_wilderness = NULL; last_wilderness = ch->prev_wilderness; } else if ( ch->next_wilderness != NULL ) { ch->next_wilderness->prev_wilderness = NULL; first_wilderness = ch->next_wilderness; } else { first_wilderness = NULL; last_wilderness = NULL; } ch->prev_wilderness = NULL; ch->next_wilderness = NULL; return; } ROOM_INDEX_DATA *wilderness_room( CHAR_DATA *ch, ROOM_INDEX_DATA *room ) { AREA_DATA *pArea; ROOM_INDEX_DATA *pRoomIndex = room; extern AREA_DATA *area_first; if ( ch->x >= 0 && ch->y >= 0 && map_data(ch->x,ch->y) == WILD_AREA_LINK ) { for ( pArea = area_first; pArea != NULL; pArea = pArea->next ) { if ( pArea->x == ch->x && pArea->y == ch->y ) { if ( ( pRoomIndex = get_room_index( pArea->start ) ) == NULL ) { bug( "Wilderness_room: null arealink room.", 0 ); pRoomIndex = get_room_index( ROOM_VNUM_ALTAR ); } } } } else { if ( ( pRoomIndex = next_room( ch->x, ch->y, ch->room ) ) == NULL ) { pRoomIndex = room; } } ch->x = pRoomIndex->x; ch->y = pRoomIndex->y; ch->room = pRoomIndex->room; char_to_wilderness( ch ); return ( pRoomIndex ); } /* Used for wilderness */ ROOM_INDEX_DATA *next_room( int x, int y, int room ) { CHAR_DATA *wch; CHAR_DATA *wch_next; OBJ_DATA *obj; OBJ_DATA *obj_next; AREA_DATA *pArea; ROOM_INDEX_DATA *pRoom = NULL; EXIT_DATA *pExit; int iHash; int value; int door, rev_door; int sector_type = 0; int dice = number_range(1,30); extern ROOM_INDEX_DATA * room_index_hash [MAX_KEY_HASH]; extern const sh_int rev_dir []; if ( x < 0 || x >= WILDERNESS_SIZE ) { x = 0; } if ( y < 0 || y >= WILDERNESS_SIZE ) { y = 0; } if ( ( pArea = wilderness_vnum( ) ) == NULL ) { return ( NULL ); } /* * If someone else is at the same coordinate position as you, move * you there. */ if (first_wilderness != NULL) for ( wch = first_wilderness; wch != NULL; wch = wch_next ) { wch_next = wch->next_wilderness; if (wch->x < 0 || wch->y < 0) continue; if (wch->x > 999 || wch->y > 999) continue; if (wch->x != x || wch->y != y) continue; if (wch->room != room) continue; if (wch->in_room != NULL) { return ( wch->in_room ); } } for ( value = WILDERNESS_LOW_VNUM; value < WILDERNESS_HIGH_VNUM+1; value++ ) { /* * Look for an existing blank room to use. */ if ( ( pRoom = get_room_index( value ) ) != NULL ) { if ( pRoom->people == NULL ) { pRoom->x = x; pRoom->y = y; pRoom->room = room; pRoom->ground = 0; pRoom->build = 0; pRoom->wood = 0; pRoom->room_flags = 0; if ( pRoom->contents != NULL ) { for ( obj = pRoom->contents; obj != NULL; obj = obj_next ) { obj_next = obj->next_content; if (obj->item_type == ITEM_CORPSE_PC) { obj_from_room(obj); obj_to_room(obj,get_room_index(ROOM_VNUM_ALTAR)); } else extract_obj( obj ); } } switch ( map_data(x,y) ) { default: pRoom->sector_type = SECT_INSIDE; break; case WILD_HUT: case WILD_HUT_OWNED: case WILD_HUT_LOCKED: case WILD_CABIN: case WILD_CABIN_OWNED: case WILD_CABIN_LOCKED: case WILD_COTTAGE: case WILD_COTTAGE_OWNED: case WILD_COTTAGE_LOCKED: case WILD_HOUSE: case WILD_HOUSE_OWNED: case WILD_HOUSE_LOCKED: case WILD_MINE_STRUCTURE_STONE: case WILD_MINE_STRUCTURE_IRON: case WILD_MINE_STRUCTURE_GOLD: case WILD_MINE_STRUCTURE_OIL: case WILD_MINE_STRUCTURE_EMPTY: case WILD_MINE_STONE_1: case WILD_MINE_STONE_2: case WILD_MINE_IRON_1: case WILD_MINE_IRON_2: case WILD_MINE_GOLD_1: case WILD_MINE_GOLD_2: case WILD_MINE_OIL_1: case WILD_MINE_OIL_2: case WILD_MINE_EMPTY: pRoom->sector_type = SECT_INSIDE; SET_BIT(pRoom->room_flags, ROOM_INDOORS); break; case WILD_WATER_DEEP_1: case WILD_WATER_DEEP_2: switch (dice) { default: break; case 1: case 2: generate_mob(MOB_VNUM_SHARK,pRoom); break; } pRoom->sector_type = SECT_WATER_NOSWIM; break; case WILD_FOREST_1: case WILD_FOREST_2: case WILD_FOREST_3: case WILD_FOREST_4: pRoom->sector_type = SECT_FOREST; switch (dice) { default: break; case 1: case 2: generate_mob(MOB_VNUM_WOLF,pRoom); break; case 3: case 4: generate_mob(MOB_VNUM_BEAR,pRoom); break; } break; case WILD_MOUNTAINS_NONE: case WILD_MOUNTAINS_STONE: case WILD_MOUNTAINS_IRON: case WILD_MOUNTAINS_GOLD: case WILD_MOUNTAINS_OIL: pRoom->sector_type = SECT_MOUNTAIN; switch (dice) { default: break; case 1: case 2: case 3: generate_mob(MOB_VNUM_BEAR,pRoom); case 4: generate_mob(MOB_VNUM_BEAR,pRoom); break; } break; case WILD_PLAINS: case WILD_FIELD_HOED: case WILD_FIELD_SEEDED: case WILD_FIELD_WHEAT: pRoom->sector_type = SECT_FIELD; switch (dice) { default: break; case 1: case 2: case 3: generate_mob(MOB_VNUM_WOLF,pRoom); case 4: generate_mob(MOB_VNUM_WOLF,pRoom); break; } break; case WILD_WATER_1: case WILD_WATER_2: pRoom->sector_type = SECT_WATER_SWIM; switch (dice) { default: break; case 1: generate_mob(1,pRoom); break; } break; } return ( pRoom ); } continue; } /* * Generate a new blank room to use. */ pRoom = new_room_index(); pRoom->area = pArea; pRoom->vnum = value; pRoom->x = x; pRoom->y = y; pRoom->room = room; pRoom->ground = 0; pRoom->build = 0; pRoom->wood = 0; pRoom->room_flags = 0; if ( value > highest_room_vnum ) highest_room_vnum = value; iHash = value % MAX_KEY_HASH; pRoom->next = room_index_hash[iHash]; room_index_hash[iHash] = pRoom; for ( door = 0; door <= 5; door++ ) { pRoom->exit[door] = make_new_exit(); pRoom->exit[door]->to_room = pRoom; pRoom->exit[door]->vnum = value; rev_door = rev_dir[door]; pExit = make_new_exit(); pExit->to_room = pRoom; pExit->vnum = pRoom->vnum; pRoom->exit[door] = pExit; } switch ( map_data(x,y) ) { default: sector_type = SECT_INSIDE; break; case WILD_HUT: case WILD_HUT_LOCKED: case WILD_CABIN: case WILD_CABIN_LOCKED: case WILD_COTTAGE: case WILD_COTTAGE_LOCKED: case WILD_HOUSE: case WILD_HOUSE_LOCKED: case WILD_MINE_STRUCTURE_STONE: case WILD_MINE_STRUCTURE_IRON: case WILD_MINE_STRUCTURE_GOLD: case WILD_MINE_STRUCTURE_OIL: case WILD_MINE_STRUCTURE_EMPTY: case WILD_MINE_STONE_1: case WILD_MINE_STONE_2: case WILD_MINE_IRON_1: case WILD_MINE_IRON_2: case WILD_MINE_GOLD_1: case WILD_MINE_GOLD_2: case WILD_MINE_OIL_1: case WILD_MINE_OIL_2: case WILD_MINE_EMPTY: pRoom->sector_type = SECT_INSIDE; SET_BIT(pRoom->room_flags, ROOM_INDOORS); break; case WILD_WATER_DEEP_1: case WILD_WATER_DEEP_2: sector_type = SECT_WATER_NOSWIM; switch (dice) { default: break; case 1: case 2: generate_mob(MOB_VNUM_SHARK,pRoom); break; } break; case WILD_FOREST_1: case WILD_FOREST_2: case WILD_FOREST_3: case WILD_FOREST_4: sector_type = SECT_FOREST; switch (dice) { default: break; case 1: generate_mob(MOB_VNUM_WOLF,pRoom); break; case 2: generate_mob(MOB_VNUM_BEAR,pRoom); break; } break; case WILD_MOUNTAINS_NONE: case WILD_MOUNTAINS_STONE: case WILD_MOUNTAINS_IRON: case WILD_MOUNTAINS_GOLD: case WILD_MOUNTAINS_OIL: sector_type = SECT_MOUNTAIN; switch (dice) { default: break; case 1: case 2: generate_mob(MOB_VNUM_WOLF,pRoom); break; case 3: generate_mob(MOB_VNUM_BEAR,pRoom); break; } break; case WILD_PLAINS: case WILD_FIELD_HOED: case WILD_FIELD_SEEDED: case WILD_FIELD_WHEAT: sector_type = SECT_FIELD; switch (dice) { default: break; case 1: generate_mob(MOB_VNUM_BEAR,pRoom); case 2: generate_mob(MOB_VNUM_BEAR,pRoom); break; } break; case WILD_WATER_1: case WILD_WATER_2: sector_type = SECT_WATER_SWIM; switch (dice) { default: break; case 1: generate_mob(MOB_VNUM_SHARK,pRoom); break; } break; } pRoom->sector_type = sector_type; return ( pRoom ); } return ( NULL ); } int next_home ( CHAR_DATA *ch, int door ) { int chroom = -1; int xx = ch->x; int yy = ch->y; if (xx < 0 || xx >= 1000 || yy < 0 || yy >= 1000) { return ( chroom ); } switch ( map_data(xx,yy) ) { default: break; case WILD_MINE_STRUCTURE_EMPTY: case WILD_MINE_STRUCTURE_STONE: case WILD_MINE_STRUCTURE_IRON: case WILD_MINE_STRUCTURE_GOLD: case WILD_MINE_STRUCTURE_OIL: switch (ch->room) { default: break; case 0: switch (door) { default: break; case DIR_NORTH: chroom = 1; break; } break; case 1: switch (door) { default: break; case DIR_SOUTH: chroom = 0; break; } break; } break; case WILD_MINE_STONE_1: case WILD_MINE_STONE_2: case WILD_MINE_IRON_1: case WILD_MINE_IRON_2: case WILD_MINE_GOLD_1: case WILD_MINE_GOLD_2: case WILD_MINE_OIL_1: case WILD_MINE_OIL_2: case WILD_MINE_EMPTY: switch (ch->room) { default: break; case 0: switch (door) { default: break; case DIR_NORTH: chroom = 1; break; } break; case 1: switch (door) { default: break; case DIR_SOUTH: chroom = 0; break; case DIR_DOWN: chroom = 2; break; } break; case 2: switch (door) { default: break; case DIR_NORTH: chroom = 3; break; case DIR_SOUTH: chroom = 6; break; case DIR_EAST: chroom = 5; break; case DIR_WEST: chroom = 4; break; case DIR_UP: chroom = 1; break; } break; case 3: switch (door) { default: break; case DIR_SOUTH: chroom = 2; break; } break; case 4: switch (door) { default: break; case DIR_EAST: chroom = 2; break; } break; case 5: switch (door) { default: break; case DIR_WEST: chroom = 2; break; } break; case 6: switch (door) { default: break; case DIR_NORTH: chroom = 2; break; } break; } break; case WILD_HUT: case WILD_HUT_OWNED: case WILD_HUT_LOCKED: switch (ch->room) { default: break; case 0: switch (door) { default: break; case DIR_NORTH: chroom = 1; break; } break; case 1: switch (door) { default: break; case DIR_SOUTH: chroom = 0; break; } break; } break; case WILD_CABIN: case WILD_CABIN_OWNED: case WILD_CABIN_LOCKED: switch (ch->room) { default: break; case 0: switch (door) { default: break; case DIR_NORTH: chroom = 1; break; } break; case 1: switch (door) { default: break; case DIR_NORTH: chroom = 2; break; case DIR_SOUTH: chroom = 0; break; } break; case 2: switch (door) { default: break; case DIR_SOUTH: chroom = 1; break; } break; } break; case WILD_COTTAGE: case WILD_COTTAGE_OWNED: case WILD_COTTAGE_LOCKED: switch (ch->room) { default: break; case 0: switch (door) { default: break; case DIR_NORTH: chroom = 1; break; } break; case 1: switch (door) { default: break; case DIR_NORTH: chroom = 4; break; case DIR_SOUTH: chroom = 0; break; case DIR_EAST: chroom = 3; break; case DIR_WEST: chroom = 2; break; } break; case 2: switch (door) { default: break; case DIR_EAST: chroom = 1; break; } break; case 3: switch (door) { default: break; case DIR_WEST: chroom = 1; break; } break; case 4: switch (door) { default: break; case DIR_NORTH: chroom = 7; break; case DIR_SOUTH: chroom = 1; break; case DIR_EAST: chroom = 6; break; case DIR_WEST: chroom = 5; break; } break; case 5: switch (door) { default: break; case DIR_EAST: chroom = 4; break; } break; case 6: switch (door) { default: break; case DIR_WEST: chroom = 4; break; } break; case 7: switch (door) { default: break; case DIR_SOUTH: chroom = 4; break; } break; } break; case WILD_HOUSE: case WILD_HOUSE_OWNED: case WILD_HOUSE_LOCKED: switch (ch->room) { default: break; case 0: switch (door) { default: break; case DIR_NORTH: chroom = 2; break; } break; case 1: switch (door) { default: break; case DIR_NORTH: chroom = 4; break; case DIR_EAST: chroom = 2; break; } break; case 2: switch (door) { default: break; case DIR_NORTH: chroom = 5; break; case DIR_SOUTH: chroom = 0; break; case DIR_EAST: chroom = 3; break; case DIR_WEST: chroom = 1; break; } break; case 3: switch (door) { default: break; case DIR_WEST: chroom = 2; break; } break; case 4: switch (door) { default: break; case DIR_NORTH: chroom = 7; break; case DIR_SOUTH: chroom = 1; break; case DIR_EAST: chroom = 5; break; } break; case 5: switch (door) { default: break; case DIR_NORTH: chroom = 8; break; case DIR_SOUTH: chroom = 2; break; case DIR_EAST: chroom = 6; break; case DIR_WEST: chroom = 4; break; } break; case 6: switch (door) { default: break; case DIR_WEST: chroom = 5; break; case DIR_UP: chroom = 12; break; } break; case 7: switch (door) { default: break; case DIR_SOUTH: chroom = 4; break; case DIR_EAST: chroom = 8; break; } break; case 8: switch (door) { default: break; case DIR_SOUTH: chroom = 5; break; case DIR_WEST: chroom = 7; break; } break; case 9: switch (door) { default: break; case DIR_SOUTH: chroom = 11; break; } break; case 10: switch (door) { default: break; case DIR_EAST: chroom = 11; break; } break; case 11: switch (door) { default: break; case DIR_NORTH: chroom = 9; break; case DIR_SOUTH: chroom = 14; break; case DIR_EAST: chroom = 12; break; case DIR_WEST: chroom = 10; break; } break; case 12: switch (door) { default: break; case DIR_WEST: chroom = 11; break; case DIR_DOWN: chroom = 6; break; } break; case 13: switch (door) { default: break; case DIR_EAST: chroom = 14; break; } break; case 14: switch (door) { default: break; case DIR_NORTH: chroom = 11; break; case DIR_SOUTH: chroom = 16; break; case DIR_EAST: chroom = 15; break; case DIR_WEST: chroom = 13; break; } break; case 15: switch (door) { default: break; case DIR_WEST: chroom = 14; break; } break; case 16: switch (door) { default: break; case DIR_NORTH: chroom = 14; break; } break; } break; } return ( chroom ); } void put_area_vnum( int vnum ) { if ( vnum > highest_room_vnum ) { highest_room_vnum = vnum; } return; } /****************************************************************************** Local operations ******************************************************************************/ AREA_DATA *wilderness_vnum( void ) { AREA_DATA *pArea; extern AREA_DATA *area_first; for ( pArea = area_first; pArea != NULL; pArea = pArea->next ) { if ( WILDERNESS_LOW_VNUM == pArea->start ) { return ( pArea ); } } return ( NULL ); } ROOM_INDEX_DATA *new_room_index( void ) { ROOM_INDEX_DATA *pRoom; int door; extern int top_room; extern char str_empty[1]; pRoom = alloc_perm( sizeof(*pRoom) ); top_room++; pRoom->next = NULL; pRoom->people = NULL; pRoom->contents = NULL; pRoom->extra_descr = NULL; pRoom->area = NULL; for ( door = 0; door < 6; door++ ) { pRoom->exit[door] = NULL; } pRoom->name = &str_empty[0]; pRoom->description = &str_empty[0]; pRoom->vnum = 0; pRoom->room_flags = 0; pRoom->light = 0; pRoom->sector_type = 0; pRoom->x = 0; pRoom->y = 0; pRoom->room = 0; pRoom->wood = 0; pRoom->build = 0; pRoom->ground = 0; return ( pRoom ); } EXIT_DATA *make_new_exit( void ) { EXIT_DATA *pExit; extern int top_exit; pExit = alloc_perm( sizeof(*pExit) ); top_exit++; pExit->to_room = NULL; pExit->vnum = 0; pExit->exit_info = 0; pExit->key = 0; pExit->keyword = str_dup(""); pExit->description = str_dup(""); return ( pExit ); } /* Move a character into the wilderness. */ void char_to_wilderness( CHAR_DATA *ch ) { if ( last_wilderness == ch || ch->prev_wilderness != NULL ) { return; } if ( first_wilderness == NULL ) { first_wilderness = ch; } if ( last_wilderness != NULL ) { last_wilderness->next_wilderness = ch; ch->prev_wilderness = last_wilderness; } last_wilderness = ch; return; } /* Creates a wild animal. */ void generate_mob( int vnum, ROOM_INDEX_DATA *pRoom ) { MOB_INDEX_DATA *pMobIndex; CHAR_DATA *victim; if ( ( pMobIndex = get_mob_index( vnum ) ) == NULL ) { return; } if ( pRoom == NULL ) { return; } victim = create_mobile( pMobIndex ); victim->x = pRoom->x; victim->y = pRoom->y; victim->room = pRoom->room; char_to_room( victim, pRoom ); return; }