Crossfire Server, Branch 1.12
R12190
|
00001 /* 00002 * static char *rcsid_arch_c = 00003 * "$Id: arch.c 11578 2009-02-23 22:02:27Z lalo $"; 00004 */ 00005 00006 /* 00007 CrossFire, A Multiplayer game for X-windows 00008 00009 Copyright (C) 2002-2006 Mark Wedel & Crossfire Development Team 00010 Copyright (C) 1992 Frank Tore Johansen 00011 00012 This program is free software; you can redistribute it and/or modify 00013 it under the terms of the GNU General Public License as published by 00014 the Free Software Foundation; either version 2 of the License, or 00015 (at your option) any later version. 00016 00017 This program is distributed in the hope that it will be useful, 00018 but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 GNU General Public License for more details. 00021 00022 You should have received a copy of the GNU General Public License 00023 along with this program; if not, write to the Free Software 00024 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00025 00026 The authors can be reached via e-mail at crossfire-devel@real-time.com 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) /* Only do this once */ 00197 return; 00198 arch_init = 1; 00199 load_archetypes(); 00200 arch_init = 0; 00201 empty_archetype = find_archetype("empty_archetype"); 00202 /* init_blocksview();*/ 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 /* Reset the hashtable */ 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); /* to initial state other also */ 00339 CLEAR_FLAG((&new->clone), FLAG_FREED); /* This shouldn't matter, since copy_object() */ 00340 SET_FLAG((&new->clone), FLAG_REMOVED); /* doesn't copy these flags... */ 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 /* copy the body_info to the body_used - this is only really 00370 * need for monsters, but doesn't hurt to do it for everything. 00371 * by doing so, when a monster is created, it has good starting 00372 * values for the body_used info, so when items are created 00373 * for it, they can be properly equipped. 00374 */ 00375 memcpy(&at->clone.body_used, &op->body_info, sizeof(op->body_info)); 00376 00377 switch (i) { 00378 case LL_NORMAL: /* A new archetype, just link it with the previous */ 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: /* Another part of the previous archetype, link it correctly */ 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 /* Set FLAG_MONSTER throughout parts if head has it */ 00398 if (QUERY_FLAG(&head->clone, FLAG_MONSTER)) { 00399 SET_FLAG(&at->clone, FLAG_MONSTER); 00400 } 00401 00402 /* If this multipart image is still composed of individual small 00403 * images, don't set the tail_.. values. We can't use them anyways, 00404 * and setting these to zero makes the map sending to the client much 00405 * easier as just looking at the head, we know what to do. 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; /* arch is checked for temporary archetypes if not 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 /*LOG(llevDebug, "Put %s in %s\n", inv->name, at->clone.name);*/ 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 /* do a close and reopen instead of a rewind - necessary in case the 00547 * file has been compressed. 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 /* use the one-at-a-time hash function, which supposedly is 00650 * better than the djb2-like one used by perl5.005, but 00651 * certainly is better then the bug used here before. 00652 * see http://burtleburtle.net/bob/hash/doobs.html 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 /*** end of arch.c ***/