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