/******************************************************************************
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;
}