/
roa/
roa/lib/boards/
roa/lib/config/
roa/lib/edits/
roa/lib/help/
roa/lib/misc/
roa/lib/plrobjs/
roa/lib/quests/
roa/lib/socials/
roa/lib/www/
roa/lib/www/LEDSign/
roa/lib/www/LEDSign/fonts/
roa/lib/www/LEDSign/scripts/
roa/src/s_inc/
roa/src/sclient/
roa/src/sclient/binary/
roa/src/sclient/text/
roa/src/util/
/************************************************************************
Realms of Aurealis 		James Rhone aka Vall of RoA

assem.c				Code dealing with the assembly of various
				objects to form other objects.  Originally
				submitted by Freebie, extensive changes
				added by Vall.

				Edit list via texedit for now.
					- texedit assembly

		******** 100% Completely Original Code ********
		*** BE AWARE OF ALL RIGHTS AND RESERVATIONS ***
		******** 100% Completely Original Code ********
		        All rights reserved henceforth. 

    Please note that no guarantees are associated with any code from
Realms of Aurealis.  All code which has been released to the general
public has been done so with an 'as is' pretense.  RoA is based on both
Diku and CircleMUD and ALL licenses from both *MUST* be adhered to as well
as the RoA license.   *** Read, Learn, Understand, Improve ***

note: assembly_table component list changed to a 10 int array rather than
      using a linked list.  easier manipulation, reading, saving, editting
      displaying, etc etc etc... with not that much memory waste relative

      REWRITE: 
	jtrhone 1/20/97
*************************************************************************/
#include "conf.h"
#include "sysdep.h"

#include "structures.h"
#include "utils.h"
#include "comm.h"
#include "interpreter.h"
#include "acmd.h"
#include "handler.h"
#include "db.h"
#include "assem.h"
#include "quest.h"
#include "lists.h"
  
// Takes several objects and assembles another object out of them 
// Information is in the assembly_table 
ACMD(do_assemble) 
{
  int prio, num;
  obdata *components[NUM_COMPONENTS];
  int vnums[NUM_COMPONENTS];
  int vnum_copy[NUM_COMPONENTS];
  int depth = 0;
  int no_chance;
  char *rest;
  int i, j;
  obdata *ob;
  obdata *resobj;

  if (strlen(argument) > MAX_STRING_LENGTH - 1)
  {
    send_to_char("Argument string too long.  Please rephrase the assembly.\n\r",ch);
    return;
  }

  for(num = 0;num < NUM_COMPONENTS; num++) 
  {
    vnums[num] = vnum_copy[num] = 0;
    components[num] = NULL;
  }

  rest = one_argument(argument, arg);
  if(!*arg) 
  {
    send_to_char("Assemble from what?\r\n", ch);
    return;
  }

  while(*arg) 
  {
    if(!(ob = get_obj_in_list_vis(ch, arg, ch->carrying))) 
    {
      sprintf(buf, "You don't seem to carry %s.\r\n", arg);
      S2C();
      return;
    }

    vnums[depth] = vnum_copy[depth] = GET_OBJ_VNUM(ob);
    components[depth] = ob;
    depth++;
    rest = one_argument(rest, arg);
  }
      
  /* Check for duplicates! */
  for(i = 0; i < NUM_COMPONENTS; i++) 
    for(j = i + 1; j < NUM_COMPONENTS; j++) 
      if(components[i] && (components[i] == components[j])) 
      {
        send_to_char("Each component can only be used once in assembly!\r\n", ch);
        return;
      }

  // Now start going thru the assembly table. 
  // Objects with lower priority assignments are checked FIRST! 
  for(prio = 0; prio < MAX_PRIO; prio++) 
  {
    for(num = 0; ATABLE(num).vnum != 99999; num++) 
    {
      if(ATABLE(num).priority != prio) 
	continue;

      /* set up the initial conditions */
      depth = 0; no_chance = 0;

      /* Reload the vnum table */
      for(i = 0; i < NUM_COMPONENTS;i++)
        vnum_copy[i] = vnums[i];

      /* Start going thru the assembly table, trying to find the components */
      for (i = 0; i < NUM_COMPONENTS && !no_chance; i++)
      {
        depth = find_num_in_array(ATABLE_COMP(num, i), vnum_copy, NUM_COMPONENTS);
        if(depth != -1) 
          vnum_copy[depth] = -1;
        else 
          no_chance = TRUE;
      }

      if(no_chance) 
	continue;

      /* Check that ALL components were used up */
      for(i = 0; i < NUM_COMPONENTS && !no_chance; i++) 
        if(vnum_copy[i] > 0)
          no_chance = TRUE;

      if(no_chance) 
	continue;

      /* Otherwise, perform the assembly */
      /* Load the object in ch's inventory and return */  
      /* Also, remove the parts from char's inventory */
      for(i = 0; components[i] && i < NUM_COMPONENTS;i++) 
	{
          extract_obj(components[i]);
	  components[i] = NULL;
        }

      if (!(resobj = read_object(ATABLE(num).vnum, VIRTUAL)))
      {
	send_to_char("There was a problem in assembly, notify an immortal.\n\r",ch);
	return;
      }

      obj_to_char(resobj, ch);
      act("You assemble $p!", FALSE, ch, resobj, 0, TO_CHAR);
      act("$n assembles $p!", FALSE, ch, resobj, 0, TO_ROOM);
      
      // check for quest assemblies here... -roa
      qcheck_obj_get(ch, resobj);
      return;
    }
  }

  send_to_char("You fiddle with your inventory but fail to assemble anything useful.\r\n", ch);
  act("$n fiddles around with $s inventory but fails to assemble anything useful.", 
      FALSE, ch, 0, 0, TO_ROOM);
}

obdata *find_vnum_inv_vis(int vnum, chdata *ch)
{
  obdata *ob;
  for(ob = ch->carrying; ob; ob = ob->next_content) 
    if((vnum == GET_OBJ_VNUM(ob)) && CAN_SEE_OBJ(ch, ob)) 
      return ob;
  return NULL;
} 

int find_num_in_array(int num, int *numbers, int size)
{
  int i;
  for(i = 0; i < size; i++) 
    if(num == *(numbers + i)) 
      return i;
  return -1;
}

// return the number of assemblies in the assembly table so far
int num_assemblies(void)
{
  int i, cnt;

  for (i = cnt = 0; ATABLE(i).vnum != 99999; i++, cnt++)
    ;

  return cnt; 
}

// wax the assembly table's values on load
void clear_assembly_table(void)
{
  int i,j;

  for (i=0; i < MAX_ASSEMBLES; i++)
  {
    ATABLE(i).vnum       = 99999;
    ATABLE(i).priority   = 0;
    for (j = 0; j < NUM_COMPONENTS; j++)
      ATABLE_COMP(i, j) = -1;
  }
}

// save the table now
void save_assembly_table(void)
{
  FILE *fp;
  int i, j;

  if(!(fp = fopen(ASSEMBLY_FILE, "w"))) {
    mudlog("SYSERR: Unable to save assembly table.", BRF, LEV_IMM, TRUE);
    return;
  }

  for (i = 0; i < MAX_ASSEMBLES; i++)
  {
    fprintf(fp, "%d", ATABLE(i).vnum);
    if (ATABLE(i).vnum == 99999)
    {
      fprintf(fp, " 99999\n");
      break; 
    }
    fprintf(fp, " %d", ATABLE(i).priority);
    for (j = 0; j < NUM_COMPONENTS; j++)
      fprintf(fp, " %d", ATABLE_COMP(i, j));
    fprintf(fp, "\n");
  }
  fclose(fp);
}

// load the assembly table from disk
void load_assembly_table(void)
{
  FILE *fp;
  int i, cnt = 0;

  clear_assembly_table();

  if(!(fp = fopen(ASSEMBLY_FILE, "r"))) {
    mudlog("SYSERR: Unable to load assembly table.", BRF, LEV_IMM, TRUE);
    return;
  }

  for (cnt = 0; cnt < MAX_ASSEMBLES; cnt++)
  {
    fscanf(fp, "%d %d", &ATABLE(cnt).vnum, &ATABLE(cnt).priority);
    if (ATABLE(cnt).vnum == 99999)
      break;

    for (i = 0; i < NUM_COMPONENTS; i++)
      fscanf(fp, " %d", &ATABLE_COMP(cnt, i));

    fscanf(fp, "\n");
  }

  fclose(fp);
  return;
}

ACMD(do_reload_table)
{
  if (IS_NPC(ch)) return;
  load_assembly_table();

  send_to_char("Ok.\n\r",ch);
  sprintf(buf, "Assembly table reloaded with %%B%%6%d%%0 entries.", num_assemblies());
  mudlog(buf, BUG, LEV_IMM, TRUE);
}

ACMD(do_show_assem_table) 
{
  int i, j;
  int rnum;
  
  strcpy(buf, "%B%5Object Assembly Table%0\n\r"
	      "---------------------\n\r");

  for (i = 0; i < MAX_ASSEMBLES && ATABLE(i).vnum != 99999; i++)
  {
    if ((rnum = real_object(ATABLE(i).vnum)) <= 0)
    {
      sprintf(buf+strlen(buf), "%%1%%BDNE%%0: vnum: %d, rnum %d.\n\r",
	      ATABLE(i).vnum, rnum);
      continue;
    }
    else
      sprintf(buf+strlen(buf), "%%6%%BFinal Product%%0: %s (#%d), priority: %d.\n\r", 
	      obj_proto[rnum].shdesc, ATABLE(i).vnum, ATABLE(i).priority);

    for(j = 0; j < NUM_COMPONENTS; j++) 
    {
      if (ATABLE_COMP(i, j) <= 0)
	break;
      if ((rnum = real_object(ATABLE_COMP(i, j))) <= 0)
      {
	sprintf(buf+strlen(buf), "   %%B%%1DNE%%0, vnum: %d, rnum: %d\n\r",
		ATABLE_COMP(i, j), rnum);
	continue;
      }
      else
        sprintf(buf+strlen(buf), "   %s (#%d)\n\r", obj_proto[rnum].shdesc, 
		ATABLE_COMP(i, j));
    }
  }
  sprintf(buf+strlen(buf), "\n\r%%6Total assemblies%%0: %d\n\r", num_assemblies());

  if (*buf)
    page_string(ch->desc, buf, TRUE);
  else
    send_to_char("Assembly table empty.\n\r",ch);
}