swrip/bin/
swrip/doc/mudprogs/
swrip/gods/
swrip/player/d/
#include <stdio.h>
#include <stdlib.h>
#include "mud.h"
#include <string.h>

/*
 
Explanation of ship template language:
  Ship Template Language is a way to copy premade rooms into a specified layout. Each copied room
  MUST be from a different premade room.  IE: You cannot use premade room 14 in the same layout twice.
  You can reuse premade rooms in different layouts.  Whitespace is ignored.

  Use by example
  When multiple strings are accepted the more verbose methods will be listed first

  To create a 1 room fighter from premade room 8.
  "1] 8)" or "1] 8"
  The '1]' specifies that this is a single room layout.
  The '8' or '8)' both specify using premade room 8 with no exits.

  To create a 2 room fighter from premade rooms 8 and 9 with a 2-way exit going from room 8 north to room 9.  
  Example 1: "2] 9; 8)20:9"
  The '2]' specifies that this is a 2 room layout
  The '9' specifies that we use premade room 9
  The ';' specifies that we are no longer in room 9
  The '8)' specifies that we use premade room 8 and it will be followed by a list of exits
  The '20:9' specifies a northern 2-way exit between rooms 8 and 9, start at 8 and going to 9
  Example 2: "2] 8)20:9"
  This example does the same thing as Example 1 but uses an implicit creation of room 9.  Room 9 will
  still be created even though it was not explicitly listed as a room to create.

  To create a 3 room fighter from premade rooms 8, 9, and 10.
  8 links north to 9, 9 links north to 10.
  "3] 8; 10; 9)20:10,22:8"
  The ',' specifies that room 9 will have a second exit.
  Alternate method using implicit creation of rooms:
  "3] 9)20:10,22:8"
   
  Use of implicit creation of rooms is encouraged because it actually takes less processing time.  In fact, the
  shorter the string is the faster it will be processed.

  For further help talk to Kre.
*/

int lookupstrtype( int rtype ) // looks up the type of the ship template room - DV 3-20-03
{
  switch ( rtype )
  {
    case 1: return STRTYPE_PILOTSEAT;
    case 2: return STRTYPE_ENTRANCE;
    case 3: return STRTYPE_COSEAT;
    case 4: return STRTYPE_ENGINEROOM;
    case 5: return STRTYPE_NAVSEAT;
    case 6: return STRTYPE_GUNSEAT;
    case 7: return STRTYPE_HANGAR;
    case 8: return STRTYPE_COCKPIT;
    case 12: return STRTYPE_COCKPIT;
    case 61: return STRTYPE_ENTRANCE;
    default: return STRTYPE_DEFAULT; // Hallways, cabins, etc... anything that isn't set to the ship structure - DV 3-20-03
  }
  return STRTYPE_DEFAULT;
}

bool setroomtoship( SHIP_DATA *ship, ROOM_INDEX_DATA *room, int strtype )
{
  switch(strtype)
  {
    case STRTYPE_PILOTSEAT: ship->pilotseat = room->vnum; break;
    case STRTYPE_ENTRANCE: ship->entrance = room->vnum; break;
    case STRTYPE_COSEAT: ship->coseat = room->vnum; break;
    case STRTYPE_ENGINEROOM: ship->engineroom = room->vnum; break;
    case STRTYPE_NAVSEAT: ship->navseat = room->vnum; break;
    case STRTYPE_GUNSEAT: ship->gunseat = room->vnum; break;
    case STRTYPE_HANGAR: ship->hanger = room->vnum; break;
    case STRTYPE_COCKPIT: 
      ship->cockpit = room->vnum;
      ship->coseat = room->vnum;
      ship->navseat = room->vnum;
      ship->gunseat = room->vnum;
      ship->pilotseat = room->vnum;
    case STRTYPE_DEFAULT: break;
    default: return FALSE; break;
  }
  return TRUE;
}

/**********************************************************
Function: make_template_room - Kre
	  Creates a room and sets its attributes
Arguments:
	rtype - the room which will be copied as the original  
	ship  - the ship the room is being created for - DV 3-20-03
	roomnum - what number room this is in the template - Used to create unique vnums - DV 3-20-03
	
**********************************************************/

ROOM_INDEX_DATA *make_template_room(int rtype, SHIP_DATA *ship, int roomnum) 
{
    ROOM_INDEX_DATA *room, *templateroom;
    int strtype, strvnum, roomvnum;
    
    // STR_AREAVNUM is set in mud.h.  This is the first room of the area in which the template rooms reside - DV 3-20-03    
    strvnum = STR_AREAVNUM+rtype; 
    
    //strtype is the type of room it is... engineroom, etc - DV 4-15-03
    strtype = lookupstrtype( rtype );

    // Hopefully this produces a unique vnum for every virtual room.. if not, we may have to play with it some more - DV 3-20-03    
    // Alright, so that formula didn't work... so I'm going for a straight sequencial system.
    roomvnum    = (ship->shipID*100) + roomnum;
    
    room = make_room( roomvnum );
    
    templateroom = get_room_index( strvnum );
    
    if ( !templateroom )
    {
      bug( "make_template_room: no template room exists.\n\r", 0 );
      return NULL;
    }
    
    
    room->area    	= templateroom->area;
    room->sector_type 	= templateroom->sector_type;
    room->room_flags  	= templateroom->room_flags;
    room->name 		= STRALLOC( templateroom->name );
    room->description 	= STRALLOC( templateroom->description );
    room->tunnel 	= templateroom->tunnel;
    if ( !setroomtoship( ship, room, strtype ) )
    {
      bug( "make_template_room: setroomtoship failed.\n\r", 0 );
      return NULL;
    }

    return room;
}

int create_exit( int location, int evnum, int edir )
{
  EXIT_DATA *xit = NULL;
  EXIT_DATA *texit;
  ROOM_INDEX_DATA *tmp;
  
    if ( edir < 0 )
      return 1;
      
//  if ( (xit = get_exit_num(get_room_index(location), edir)) != NULL )
//    edir = xit->vdir;

	if ( (tmp = get_room_index( evnum )) == NULL )
	{

	    return 1;
	}
	if ( !xit )
	{
	    if ( xit && get_exit_to(get_room_index(location), edir, tmp->vnum) )
	    {
		return 1;
	    }
	    xit = make_exit( get_room_index(location), tmp, edir );
	    xit->keyword		= STRALLOC( "" );
	    xit->description		= STRALLOC( "" );
	    xit->key			= -1;
	    xit->exit_info		= 0;
	}
	if ( xit->to_room != tmp )
	{
	    xit->to_room = tmp;
	    xit->vnum = evnum;
	    texit = get_exit_to( xit->to_room, rev_dir[edir], get_room_index(location)->vnum );
	    if ( texit )
	    {
		texit->rexit = xit;
		xit->rexit = texit;
	    }
	}
	return 0;
}

int reversedir( int dir )
{
  switch( dir )
  {
    case DIR_NORTH: return DIR_SOUTH;
    case DIR_EAST: return DIR_WEST;
    case DIR_SOUTH: return DIR_NORTH;
    case DIR_WEST: return DIR_EAST;
    case DIR_UP: return DIR_DOWN;
    case DIR_DOWN: return DIR_UP;
    case DIR_NORTHEAST: return DIR_SOUTHWEST;
    case DIR_NORTHWEST: return DIR_SOUTHEAST;
    case DIR_SOUTHEAST: return DIR_NORTHWEST;
    case DIR_SOUTHWEST: return DIR_NORTHEAST;
    default: return -1;
  }
  return -1;
}

int join_template_rooms(int room1, ROOM_INDEX_DATA *room2, int exitType)
{
    int success = 0, dir;
    bool twoway;
//  char buf[MAX_INPUT_LENGTH];
    
    twoway = FALSE;
    
    switch(exitType)
    {
	case 10: dir = DIR_NORTH; 	twoway = FALSE; break; // 1-way north
	case 11: dir = DIR_EAST; 	twoway = FALSE; break; //1-way east 
	case 12: dir = DIR_SOUTH; 	twoway = FALSE; break; //1-way south
	case 13: dir = DIR_WEST; 	twoway = FALSE; break; //1-way west
	case 14: dir = DIR_NORTHEAST; 	twoway = FALSE; break; //1-way northeast
	case 15: dir = DIR_NORTHWEST; 	twoway = FALSE; break; //1-way northwest
	case 16: dir = DIR_SOUTHEAST; 	twoway = FALSE; break; //1-way southeast
	case 17: dir = DIR_SOUTHWEST; 	twoway = FALSE; break; //1-way southwest
	case 18: dir = DIR_UP; 		twoway = FALSE; break; //1-way up 
	case 19: dir = DIR_DOWN; 	twoway = FALSE; break; //1-way down 
	case 20: dir = DIR_NORTH; 	twoway = TRUE; break; //2-way north 
	case 21: dir = DIR_EAST; 	twoway = TRUE; break; //2-way east 
	case 22: dir = DIR_SOUTH; 	twoway = TRUE; break; //2-way south 
	case 23: dir = DIR_WEST; 	twoway = TRUE; break; //2-way west 
	case 24: dir = DIR_NORTHEAST; 	twoway = TRUE; break; //2-way northeast 
	case 25: dir = DIR_NORTHWEST; 	twoway = TRUE; break; //2-way northwest 
	case 26: dir = DIR_SOUTHEAST; 	twoway = TRUE; break; //2-way southeast 
	case 27: dir = DIR_SOUTHWEST; 	twoway = TRUE; break; //2-way southwest 
	case 28: dir = DIR_UP; 		twoway = TRUE; break; //2-way up 
	case 29: dir = DIR_DOWN; 	twoway = TRUE; break; //2-way down 
	default: return 1;
    }
    
//sprintf( buf, "Room1: %d Room2: %d exitType: %d\n\r", room1, room2->vnum, exitType );
//bug ( buf, 0 );
    
    if( twoway )
    {
      success += create_exit( room1, (room2->vnum), dir );
      success += create_exit( (room2->vnum), room1, reversedir(dir) );
    }
    else
      success += create_exit( room1, (room2->vnum), dir );
    
    if ( success > 0 )
      return 1;
      
    return 0;
}

int destroy_vnums(ROOM_INDEX_DATA *rooms[], int size)
{
    int i;
    for(i = 0; i < size; i++) 
    {
    	if ( rooms[i] )
	delete_room( rooms[i] );
	free(rooms[i]);
    }
    return 1;
}
int parse_ship_template(char *string, SHIP_DATA *ship)
{
    #define PST_BUF_SIZE 15
    char buf[PST_BUF_SIZE];
//  char debug[MAX_STRING_LENGTH];
//  char buf2[PST_BUF_SIZE];
    int masterIndex;
    int index;
    int bindex;
    int roomCount;
    int *roomArray;
    ROOM_INDEX_DATA *vnumArray[100];
    int i, j;
    short start;
    int room;
    int room2;
    
//  sprintf( buf, "Parser activated: String: %s, Ship: %s", string, ship->personalname );
//  bug( buf, 0 );
    
    masterIndex=0;
    //Parse out the number of rooms
    bindex=0;
    while(string[masterIndex] != ']' && masterIndex < (int) strlen(string) && bindex < PST_BUF_SIZE)
    {
	buf[bindex] = string[masterIndex];
	masterIndex++;
	bindex++;
    }
    buf[bindex] = '\0';
    if (masterIndex == (int) strlen(string) || bindex == PST_BUF_SIZE) {
	return 1;
    }
    masterIndex++;
    roomCount = atoi(buf);
    roomArray = (int*)calloc(roomCount,sizeof(int));
//    vnumArray = (ROOM_INDEX_DATA*)calloc(roomCount,sizeof(ROOM_INDEX_DATA));

    //Find all the room numbers
    index = masterIndex-1;
    i = 0;
    start = 1;
    bindex = 0;
    while(i < roomCount && index < (int) strlen(string)) {
	index++;
	if (string[index] == ':') {
	    start = 1;
	    continue;
	}
	if ((string[index] == ',' || string[index] == '\0' || string[index] == ')' || string[index] == ';') && start) {
	    buf[bindex]='\0';
	    roomArray[i] = atoi(buf);
	    //Check for duplicates
	    for(j = 0; j < i; j++) {
		if (roomArray[j] == roomArray[i]) {
		    break;
		}
	    }
	    start = 0;
	    bindex = 0;
	    if (j >= i) {
		i++;          //Only increment if we want to keep this number
	    }
	    if (string[index] == ';') {
		start = 1;
	    }
	    continue;
	}
        if (string[index] < '0' && string[index] > '9')
	    continue;  //haven't hit a number yet
	if (start == 1) {
	    buf[bindex] = string[index];
	    bindex++;
	}
    }
    if (i != roomCount) {
	free(roomArray);
//	clearrooms(vnumArray);
	return 2;
    }
    for(i = 0; i < roomCount; i++) {
	vnumArray[i] = make_template_room(roomArray[i], ship, i);

        if( !(vnumArray[i]) )
          continue;


        if( i == 0 )
        {
          ship->entrance      = ((vnumArray[i])->vnum);
          ship->pilotseat     = ((vnumArray[i])->vnum);
          ship->coseat        = ((vnumArray[i])->vnum);
          ship->cockpit       = ((vnumArray[i])->vnum);
          ship->engineroom    = ((vnumArray[i])->vnum);
          ship->navseat       = ((vnumArray[i])->vnum);
          ship->gunseat       = ((vnumArray[i])->vnum);
          ship->lastroom      = roomCount;
//        ship->cockpitroom   = get_room_index((vnumArray[i])->vnum);
        }

//	printf("Make room type: %d, Vnum: %d\n",roomArray[i],vnumArray[i]->vnum);
    }

  ship->firstroom = ship->shipID*100;
  ship->lastroom += ship->firstroom-1;

/*  for( i = 0; i < roomCount; i++ )
    {
    	sprintf(debug, "Rooms: Tmp#: %d Vnum: %d\n\r", roomArray[i], vnumArray[i]->vnum );
    	bug( debug, 0 );
    }
*/

    //Create Exits
    index = masterIndex-1;
    i = 0;
    start = 0;
    bindex = 0;
    room = -1;
    while(/*i < roomCount && */index < (int) strlen(string)) {
	index++;
	if (string[index] == ')' && !start) {
	    room = atoi(buf);
	    for(j = 0; j < roomCount; j++) {
		if ( ( roomArray[j] == room ) && vnumArray[j] ) 
		{
//		    sprintf( debug, "Tmp#: %d Vnum: %d\n\r", room, vnumArray[j]->vnum );
//		    bug( debug, 0 );
		    room = vnumArray[j]->vnum;
		    bindex = 0;
		    break;
		}
	    }
	    if (j == roomCount) {
	    	bug( "No room found for exit.\n\r", 0 );
		destroy_vnums(vnumArray,roomCount);
//		free(vnumArray);
		free(roomArray);
		return 5;
	    } 
	}
	
	//If a ',' or ')' appears in the string, start capturing the exitType - DV 4-20-03
	if ((string[index] == ',' || string[index] == ')') && start == 0 && room > -1) {
	    start = 1;
	    continue;
	}
	//Once start = 1, it is capturing the exitType... when next a separate appears,
	//capture the room template number.
	if (start && ((string[index] == ',' || string[index] == '\0') || string[index] == ';')) 
	{
	    buf[bindex]='\0';
	    
	    //Brings buf to capture the room template number DV- 4-20-03
	    j = 0;
	    while(buf[j]!=':') {
		if (j >= bindex) {
		    //Some error- really have no idea what :) DV - 4-20-03
		    destroy_vnums(vnumArray,roomCount);
//		    free(vnumArray);
		    free(roomArray);
		    return 3;
		}
		j++;
	    }
	    buf[j] = '\0';
	    room2 = atoi((char*)buf+j+1);
//	    sprintf( debug, "Buf: %s Room2: %d\n\r", buf, room2 );
//	    bug( debug, 0 );
	    for(j = 0; j < roomCount; j++) {
		if (roomArray[j] == room2) {
		    if (join_template_rooms(room,vnumArray[j],atoi(buf))) {
			destroy_vnums(vnumArray,roomCount);
//			free(vnumArray);
			free(roomArray);
			return 6;
		    }
		    break;
		}
	    }
	    if (j == roomCount)
	    {
		printf("searching for: %d\n",room2);
		destroy_vnums(vnumArray,roomCount);
//		free(vnumArray);
		free(roomArray);
		return 4;
	    }
	    start = 0;	    
	    bindex = 0;
	    i++;  
	    if (string[index] == ',')
	    	index--;
	    continue;
	}
	if (string[index] == ';') {
	    room = -1;
	    start = 0;
	}
        if (string[index] < '0' && string[index] > '9' && string[index] != ':')
	    continue;  //haven't hit a number yet
	buf[bindex] = string[index];
	bindex++;
	buf[bindex] = '\0';
    }
//  free(vnumArray);
    free(roomArray);
    return 0;
}


/*

int main()
{

    printf("Exit Types\n");
    printf("1-Way\n");
    printf("10=north\n11=east\n12=south\n13=west\n14=northeast\n15=southeast\n16=southwest\n17=northwest\n18=up\n19=down\n");
    printf("2-Way\n");
    printf("20=north\n21=east\n22=south\n23=west\n24=northeast\n25=southeast\n26=southwest\n27=northwest\n28=up\n29=down\n");

    printf("------\nShip 1\n");
    printf("Return: %d\n------\n",parse_ship_template("4] 100)12:101,13:102;102)10:103"));
    printf("------\nShip 2\n");
    printf("Return: %d\n------\n",parse_ship_template("1] 100"));
    printf("------\nShip 3\n");
    printf("Return: %d\n------\n",parse_ship_template("10] 8)20:100,22:13;201)20:3,21:13,22:15,23:12;115)21:3,23:110;1)20:15")); 
  return 0;
}

*/