00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00043 #include <global.h>
00044 #include <loader.h>
00045
00047 #define TIME_ARCH_LOAD 0
00048
00049 static void add_arch(archetype *at);
00050
00051 static archetype *arch_table[ARCHTABLE];
00052 static int arch_cmp = 0;
00053 static int arch_search = 0;
00054 int arch_init;
00056 static void load_archetypes(void);
00057
00070 archetype *find_archetype_by_object_name(const char *name) {
00071 archetype *at;
00072 const char *tmp;
00073
00074 if (name == NULL)
00075 return (archetype *)NULL;
00076 tmp = add_string(name);
00077 for (at = first_archetype; at != NULL; at = at->next) {
00078 if (at->clone.name == tmp) {
00079 free_string(tmp);
00080 return at;
00081 }
00082 }
00083 free_string(tmp);
00084 return NULL;
00085 }
00086
00096 archetype *find_archetype_by_object_type_name(int type, const char *name) {
00097 archetype *at;
00098
00099 if (name == NULL)
00100 return NULL;
00101
00102 for (at = first_archetype; at != NULL; at = at->next) {
00103 if (at->clone.type == type && strcmp(at->clone.name, name) == 0)
00104 return at;
00105 }
00106
00107 return NULL;
00108 }
00109
00120 archetype *get_archetype_by_skill_name(const char *skill, int type) {
00121 archetype *at;
00122
00123 if (skill == NULL)
00124 return NULL;
00125
00126 for (at = first_archetype; at != NULL; at = at->next) {
00127 if (((type == -1) || (type == at->clone.type))
00128 && (at->clone.skill) && (!strcmp(at->clone.skill, skill)))
00129 return at;
00130 }
00131 return NULL;
00132 }
00133
00149 archetype *get_archetype_by_type_subtype(int type, int subtype) {
00150 archetype *at;
00151
00152 for (at = first_archetype; at != NULL; at = at->next) {
00153 if (((type == -1) || (type == at->clone.type))
00154 && (subtype == -1 || subtype == at->clone.subtype))
00155 return at;
00156 }
00157 return NULL;
00158 }
00159
00173 object *create_archetype_by_object_name(const char *name) {
00174 archetype *at;
00175 char tmpname[MAX_BUF];
00176 size_t i;
00177
00178 strncpy(tmpname, name, MAX_BUF-1);
00179 tmpname[MAX_BUF-1] = 0;
00180 for (i = strlen(tmpname); i > 0; i--) {
00181 tmpname[i] = 0;
00182 at = find_archetype_by_object_name(tmpname);
00183 if (at != NULL) {
00184 return arch_to_object(at);
00185 }
00186 }
00187 return create_singularity(name);
00188 }
00189
00195 void init_archetypes(void) {
00196 if (first_archetype != NULL)
00197 return;
00198 arch_init = 1;
00199 load_archetypes();
00200 arch_init = 0;
00201 empty_archetype = find_archetype("empty_archetype");
00202
00203 }
00204
00209 void arch_info(object *op) {
00210 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DEBUG,
00211 "%d searches and %d strcmp()'s",
00212 "%d searches and %d strcmp()'s",
00213 arch_search, arch_cmp);
00214 }
00215
00219 void clear_archetable(void) {
00220 memset((void *)arch_table, 0, ARCHTABLE*sizeof(archetype *));
00221 }
00222
00226 static void init_archetable(void) {
00227 archetype *at;
00228
00229 LOG(llevDebug, " Setting up archetable...\n");
00230 for (at = first_archetype; at != NULL; at = (at->more == NULL) ? at->next : at->more)
00231 add_arch(at);
00232 LOG(llevDebug, "done\n");
00233 }
00234
00243 void dump_arch(archetype *at, StringBuffer *sb) {
00244 dump_object(&at->clone, sb);
00245 }
00246
00252 void dump_all_archetypes(void) {
00253 archetype *at;
00254
00255 for (at = first_archetype; at != NULL; at = (at->more == NULL) ? at->next : at->more) {
00256 StringBuffer *sb;
00257 char *diff;
00258
00259 sb = stringbuffer_new();
00260 dump_arch(at, sb);
00261 diff = stringbuffer_finish(sb);
00262 LOG(llevDebug, "%s\n", diff);
00263 free(diff);
00264 }
00265 }
00266
00273 void free_arch(archetype *at) {
00274 if (at->name)
00275 free_string(at->name);
00276 if (at->clone.name)
00277 free_string(at->clone.name);
00278 if (at->clone.name_pl)
00279 free_string(at->clone.name_pl);
00280 if (at->clone.title)
00281 free_string(at->clone.title);
00282 if (at->clone.race)
00283 free_string(at->clone.race);
00284 if (at->clone.slaying)
00285 free_string(at->clone.slaying);
00286 if (at->clone.msg)
00287 free_string(at->clone.msg);
00288 if (at->clone.discrete_damage)
00289 free(at->clone.discrete_damage);
00290 free_key_values(&at->clone);
00291 free(at);
00292 }
00293
00298 void free_all_archs(void) {
00299 archetype *at, *next;
00300 int i = 0;
00301
00302 for (at = first_archetype; at != NULL; at = next) {
00303 if (at->more)
00304 next = at->more;
00305 else
00306 next = at->next;
00307 free_arch(at);
00308 i++;
00309 }
00310 first_archetype = NULL;
00311
00312 clear_archetable();
00313 LOG(llevDebug, "Freed %d archetypes\n", i);
00314 }
00315
00323 archetype *get_archetype_struct(void) {
00324 archetype *new;
00325
00326 new = (archetype *)CALLOC(1, sizeof(archetype));
00327 if (new == NULL)
00328 fatal(OUT_OF_MEMORY);
00329 new->next = NULL;
00330 new->name = NULL;
00331 new->clone.other_arch = NULL;
00332 new->clone.name = NULL;
00333 new->clone.name_pl = NULL;
00334 new->clone.title = NULL;
00335 new->clone.race = NULL;
00336 new->clone.slaying = NULL;
00337 new->clone.msg = NULL;
00338 clear_object(&new->clone);
00339 CLEAR_FLAG((&new->clone), FLAG_FREED);
00340 SET_FLAG((&new->clone), FLAG_REMOVED);
00341 new->head = NULL;
00342 new->more = NULL;
00343 new->clone.arch = new;
00344 return new;
00345 }
00346
00357 static void first_arch_pass(FILE *fp) {
00358 object *op;
00359 archetype *at, *head = NULL, *last_more = NULL;
00360 int i, first = 2;
00361
00362 op = get_object();
00363 op->arch = first_archetype = at = get_archetype_struct();
00364
00365 while ((i = load_object(fp, op, first, 0))) {
00366 first = 0;
00367 copy_object(op, &at->clone);
00368 at->clone.speed_left = (float)(-0.1);
00369
00370
00371
00372
00373
00374
00375 memcpy(&at->clone.body_used, &op->body_info, sizeof(op->body_info));
00376
00377 switch (i) {
00378 case LL_NORMAL:
00379 if (last_more != NULL)
00380 last_more->next = at;
00381 if (head != NULL)
00382 head->next = at;
00383 head = last_more = at;
00384 at->tail_x = 0;
00385 at->tail_y = 0;
00386 break;
00387
00388 case LL_MORE:
00389 at->head = head;
00390 at->clone.head = &head->clone;
00391 if (last_more != NULL) {
00392 last_more->more = at;
00393 last_more->clone.more = &at->clone;
00394 }
00395 last_more = at;
00396
00397
00398 if (QUERY_FLAG(&head->clone, FLAG_MONSTER)) {
00399 SET_FLAG(&at->clone, FLAG_MONSTER);
00400 }
00401
00402
00403
00404
00405
00406
00407 if (at->clone.face != head->clone.face) {
00408 head->tail_x = 0;
00409 head->tail_y = 0;
00410 } else {
00411 if (at->clone.x > head->tail_x)
00412 head->tail_x = at->clone.x;
00413 if (at->clone.y > head->tail_y)
00414 head->tail_y = at->clone.y;
00415 }
00416 break;
00417 }
00418
00419 at = get_archetype_struct();
00420 clear_object(op);
00421 op->arch = at;
00422 }
00423 free_object(op);
00424 op->arch = NULL;
00425 free(at);
00426 }
00427
00437 static void second_arch_pass(FILE *fp) {
00438 char buf[MAX_BUF], *variable = buf, *argument, *cp;
00439 archetype *at = NULL, *other;
00440 object *inv;
00441
00442 while (fgets(buf, MAX_BUF, fp) != NULL) {
00443 if (*buf == '#')
00444 continue;
00445 if ((argument = strchr(buf, ' ')) != NULL) {
00446 *argument = '\0', argument++;
00447 cp = argument+strlen(argument)-1;
00448 while (isspace(*cp)) {
00449 *cp = '\0';
00450 cp--;
00451 }
00452 }
00453 if (!strcmp("Object", variable)) {
00454 if ((at = find_archetype(argument)) == NULL)
00455 LOG(llevError, "Warning: failed to find arch %s\n", argument);
00456 } else if (!strcmp("other_arch", variable)) {
00457 if (at != NULL && at->clone.other_arch == NULL) {
00458 if ((other = find_archetype(argument)) == NULL)
00459 LOG(llevError, "Warning: failed to find other_arch %s\n", argument);
00460 else if (at != NULL)
00461 at->clone.other_arch = other;
00462 }
00463 } else if (!strcmp("randomitems", variable)) {
00464 if (at != NULL) {
00465 treasurelist *tl = find_treasurelist(argument);
00466 if (tl == NULL)
00467 LOG(llevError, "Failed to link treasure to arch (%s): %s\n", at->name, argument);
00468 else
00469 at->clone.randomitems = tl;
00470 }
00471 } else if (!strcmp("arch", variable)) {
00472 inv = create_archetype(argument);
00473 load_object(fp, inv, LO_LINEMODE, 0);
00474 if (at) {
00475 insert_ob_in_ob(inv, &at->clone);
00476
00477 } else {
00478 LOG(llevError, "Got an arch %s not inside an Object.\n", argument);
00479 free_object(inv);
00480 }
00481 }
00482 }
00483 }
00484
00485 #ifdef DEBUG
00486
00491 void check_generators(void) {
00492 archetype *at;
00493
00494 for (at = first_archetype; at != NULL; at = at->next)
00495 if (QUERY_FLAG(&at->clone, FLAG_GENERATOR) && at->clone.other_arch == NULL)
00496 LOG(llevError, "Warning: %s is generator but lacks other_arch.\n", at->name);
00497 }
00498 #endif
00499
00507 static void load_archetypes(void) {
00508 FILE *fp;
00509 char filename[MAX_BUF];
00510 int comp;
00511 #if TIME_ARCH_LOAD
00512 struct timeval tv1, tv2;
00513 #endif
00514
00515 snprintf(filename, sizeof(filename), "%s/%s", settings.datadir, settings.archetypes);
00516 LOG(llevDebug, "Reading archetypes from %s...\n", filename);
00517 if ((fp = open_and_uncompress(filename, 0, &comp)) == NULL) {
00518 LOG(llevError, " Can't open archetype file.\n");
00519 return;
00520 }
00521 clear_archetable();
00522 LOG(llevDebug, " arch-pass 1...\n");
00523 #if TIME_ARCH_LOAD
00524 GETTIMEOFDAY(&tv1);
00525 #endif
00526 first_arch_pass(fp);
00527 #if TIME_ARCH_LOAD
00528 {
00529 int sec, usec;
00530
00531 GETTIMEOFDAY(&tv2);
00532 sec = tv2.tv_sec-tv1.tv_sec;
00533 usec = tv2.tv_usec-tv1.tv_usec;
00534 if (usec < 0) {
00535 usec += 1000000;
00536 sec--;
00537 }
00538 LOG(llevDebug, "Load took %d.%06d seconds\n", sec, usec);
00539 }
00540 #endif
00541
00542 LOG(llevDebug, " done\n");
00543 init_archetable();
00544 warn_archetypes = 1;
00545
00546
00547
00548
00549 close_and_delete(fp, comp);
00550 fp = open_and_uncompress(filename, 0, &comp);
00551
00552 LOG(llevDebug, " loading treasure...\n");
00553 load_treasures();
00554 LOG(llevDebug, " done\n");
00555 LOG(llevDebug, "arch-pass 2...\n");
00556 second_arch_pass(fp);
00557 LOG(llevDebug, " done\n");
00558 #ifdef DEBUG
00559 check_generators();
00560 #endif
00561 close_and_delete(fp, comp);
00562 LOG(llevDebug, " done\n");
00563 }
00564
00576 object *arch_to_object(archetype *at) {
00577 object *op;
00578
00579 if (at == NULL) {
00580 if (warn_archetypes)
00581 LOG(llevError, "Couldn't find archetype.\n");
00582 return NULL;
00583 }
00584 op = get_object();
00585 copy_object_with_inv(&at->clone, op);
00586 op->arch = at;
00587 return op;
00588 }
00589
00603 object *create_singularity(const char *name) {
00604 object *op;
00605 char buf[MAX_BUF];
00606
00607 snprintf(buf, sizeof(buf), "%s (%s)", ARCH_SINGULARITY, name);
00608 op = get_object();
00609 op->name = add_string(buf);
00610 op->name_pl = add_string(buf);
00611 SET_FLAG(op, FLAG_NO_PICK);
00612 return op;
00613 }
00614
00625 object *create_archetype(const char *name) {
00626 archetype *at;
00627
00628 at = find_archetype(name);
00629 if (at == NULL)
00630 return create_singularity(name);
00631 return arch_to_object(at);
00632 }
00633
00643 static unsigned long
00644 hasharch(const char *str, int tablesize) {
00645 unsigned long hash = 0;
00646 int i = 0;
00647 const char *p;
00648
00649
00650
00651
00652
00653
00654 for (p = str; i < MAXSTRING && *p; p++, i++) {
00655 hash += *p;
00656 hash += hash<<10;
00657 hash ^= hash>>6;
00658 }
00659 hash += hash<<3;
00660 hash ^= hash>>11;
00661 hash += hash<<15;
00662 return hash%tablesize;
00663 }
00664
00671 archetype *try_find_archetype(const char *name) {
00672 archetype *at;
00673 unsigned long index;
00674
00675 if (name == NULL)
00676 return (archetype *)NULL;
00677
00678 index = hasharch(name, ARCHTABLE);
00679 arch_search++;
00680 for (;;) {
00681 at = arch_table[index];
00682 if (at == NULL) {
00683 return NULL;
00684 }
00685 arch_cmp++;
00686 if (!strcmp(at->name, name))
00687 return at;
00688 if (++index >= ARCHTABLE)
00689 index = 0;
00690 }
00691 }
00692
00700 archetype *find_archetype(const char *name) {
00701 archetype *at;
00702
00703 if (name == NULL)
00704 return (archetype *)NULL;
00705 at = try_find_archetype(name);
00706 if (at == NULL && warn_archetypes)
00707 LOG(llevError, "Couldn't find archetype %s\n", name);
00708 return at;
00709 }
00710
00715 static void add_arch(archetype *at) {
00716 unsigned long index = hasharch(at->name, ARCHTABLE), org_index = index;
00717
00718 for (;;) {
00719 if (arch_table[index] == NULL) {
00720 arch_table[index] = at;
00721 return;
00722 }
00723 if (++index == ARCHTABLE)
00724 index = 0;
00725 if (index == org_index)
00726 fatal(ARCHTABLE_TOO_SMALL);
00727 }
00728 }
00729
00741 object *object_create_arch(archetype *at) {
00742 object *op, *prev = NULL, *head = NULL;
00743
00744 while (at) {
00745 op = arch_to_object(at);
00746 op->x = at->clone.x;
00747 op->y = at->clone.y;
00748 if (head)
00749 op->head = head, prev->more = op;
00750 if (!head)
00751 head = op;
00752 prev = op;
00753 at = at->more;
00754 }
00755 return (head);
00756 }
00757
00758