Crossfire Server, Branch 1.12  R12190
bwp.c
Go to the documentation of this file.
00001 /*
00002  * bwp - build wiki pages
00003  *
00004  * This program will sort out all monster archetypes and print wiki pages
00005  * for them, named 'a' through 'z'.  It uses some *_template subroutines taken
00006  * from Ryo's mapper.c.  It should compile if installed in server/trunk/utils.
00007  * Please direct all suggestions or corrections to aaron@baugher.biz (or
00008  * Mhoram on #crossfire).
00009  *
00010  * Compile command: gcc -g -O0 bwp.c -I../include ../common/libcross.a ../socket/libsocket.a -o bwp -lz -lcrypt -lm
00011  */
00012 
00013 /*
00014  * CrossFire, A Multiplayer game for X-windows
00015  *
00016  * Copyright (C) 2002-2006 Mark Wedel & Crossfire Development Team
00017  * Copyright (C) 1992 Frank Tore Johansen
00018  *
00019  * This program is free software; you can redistribute it and/or modify
00020  * it under the terms of the GNU General Public License as published by
00021  * the Free Software Foundation; either version 2 of the License, or
00022  * (at your option) any later version.
00023  *
00024  * This program is distributed in the hope that it will be useful,
00025  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00026  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00027  * GNU General Public License for more details.
00028  *
00029  * You should have received a copy of the GNU General Public License
00030  * along with this program; if not, write to the Free Software
00031  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00032  *
00033  * The authors can be reached via e-mail at crossfire-devel@real-time.com
00034  */
00035 
00036 #define LO_NEWFILE 2
00037 #define MAX_SIZE 64
00038 #define NA "n/a"
00039 
00040 #include <time.h>
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 #include <global.h>
00044 
00045 char *monster_page_head;       /* Head of wiki page of monsters  */
00046 char *monster_page_foot;       /* Foot of wiki page of monsters  */
00047 char *monster_entry;           /* A single monster entry         */
00048 char *monster_canuse_row;      /* Can_use table row              */
00049 char *monster_protected_row;   /* Protected table row            */
00050 char *monster_vulnerable_row;  /* Vulnerable table row           */
00051 char *monster_special_row;     /* Special table row              */
00052 char *monster_attack_row;      /* Attack types table row         */
00053 char *monster_lore_row;        /* Lore table row                 */
00054 
00055 typedef struct string_array {
00056     sint16 count;
00057     char **item;
00058 } String_Array;
00059 
00069 const char *const flag_names[NUM_FLAGS+1] = {
00070     "alive", "wiz", NULL, NULL, "was_wiz", "applied", "unpaid",
00071     "can_use_shield", "no_pick", "client_anim_sync", "client_anim_random", /* 10 */
00072     "is_animated", NULL /* slow_move */,
00073     NULL /* flying */, "monster", "friendly", "generator",
00074     "is_thrown", "auto_apply", "treasure", "player sold",   /* 20 */
00075     "see_invisible", "can_roll", "overlay_floor",
00076     "is_turnable", NULL /* walk_off */, NULL /* fly_on */,
00077     NULL /*fly_off*/, "is_used_up", "identified", "reflecting", /* 30 */
00078     "changing", "splitting", "hitback", "startequip",
00079     "blocksview", "undead", "scared", "unaggressive",
00080     "reflect_missile", "reflect_spell",                             /* 40 */
00081     "no_magic", "no_fix_player", "is_lightable", "tear_down",
00082     "run_away", NULL /*pass_thru */, NULL /*can_pass_thru*/,
00083     "pick_up", "unique", "no_drop",                                     /* 50 */
00084     NULL /* wizcast*/, "can_cast_spell", "can_use_scroll", "can_use_range",
00085     "can_use_bow",  "can_use_armour", "can_use_weapon",
00086     "can_use_ring", "has_ready_range", "has_ready_bow",             /* 60 */
00087     "xrays", NULL, "is_floor", "lifesave", "no_strength", "sleep",
00088     "stand_still", "random_movement", "only_attack", "confused",        /* 70 */
00089     "stealth", NULL, NULL, "cursed", "damned",
00090     "see_anywhere", "known_magical", "known_cursed",
00091     "can_use_skill", "been_applied",                                /* 80 */
00092     "has_ready_scroll", "can_use_rod", NULL,
00093     "can_use_horn", "make_invisible",  "inv_locked", "is_wooded",
00094     "is_hilly", "has_ready_skill", "has_ready_weapon",              /* 90 */
00095     "no_skill_ident", "is_blind", "can_see_in_dark", "is_cauldron",
00096     "is_dust", "no_steal", "one_hit", NULL, "berserk", "neutral",       /* 100 */
00097     "no_attack", "no_damage", NULL, NULL, "activate_on_push",
00098     "activate_on_release", "is_water", "use_content_on_gen", NULL, "is_buildable", /* 110 */
00099     NULL, "blessed", "known_blessed"
00100 };
00101 
00112 static char *cat_template(char *source, char *add) {
00113     if (!source)
00114         return add;
00115     source = realloc(source, strlen(source)+strlen(add)+1);
00116     strcat(source, add);
00117     free(add);
00118     return source;
00119 }
00120 
00131 static int read_template(const char *name, char **buffer) {
00132     FILE *file;
00133     size_t size;
00134     struct stat info;
00135 
00136     if (stat(name, &info)) {
00137         printf("Couldn't stat template %s!\n", name);
00138         return 1;
00139     }
00140 
00141     (*buffer) = calloc(1, info.st_size+1);
00142     if (!(*buffer)) {
00143         printf("Template %s calloc failed!\n", name);
00144         return 1;
00145     }
00146 
00147     if (info.st_size == 0) {
00148         (*buffer)[0] = '\0';
00149         return 0;
00150     }
00151 
00152     file = fopen(name, "rb");
00153     if (!file) {
00154         printf("Couldn't open template %s!\n", name);
00155         free(*buffer);
00156         return 1;
00157     }
00158     if (fread(*buffer, info.st_size, 1, file) != 1) {
00159         printf("Couldn't read template %s!\n", name);
00160         free(*buffer);
00161         fclose(file);
00162         return 1;
00163     }
00164     fclose(file);
00165     return 0;
00166 }
00167 
00185 static char *do_template(const char *template, const char **vars, const char **values) {
00186     int count = 0;
00187     const char *sharp = template;
00188     int maxlen = 0;
00189     int var = 0;
00190     char *result;
00191     char *current_result;
00192     const char *end;
00193 
00194     while ((sharp = strchr(sharp, '#')) != NULL) {
00195         sharp++;
00196         count++;
00197     }
00198     if (!count)
00199         return strdup(template);
00200     if (count%2) {
00201         printf("Malformed template, mismatched #!\n");
00202         return strdup(template);
00203     }
00204 
00205     while (vars[var] != NULL) {
00206         if (strlen(values[var]) > maxlen)
00207             maxlen = strlen(values[var]);
00208         var++;
00209     }
00210     result = calloc(1, strlen(template)+maxlen*(count/2)+1);
00211     if (!result)
00212         return NULL;
00213     current_result = result;
00214 
00215     sharp = template;
00216     while ((sharp = strchr(sharp, '#')) != NULL) {
00217         end = strchr(sharp+1, '#');
00218         strncpy(current_result, template, sharp-template);
00219         if (end == sharp+1) {
00220             strcat(current_result, "#");
00221         } else {
00222             current_result = current_result+strlen(current_result);
00223             var = 0;
00224             while (vars[var] != 0 && strncmp(vars[var], sharp+1, end-sharp-1))
00225                 var++;
00226             if (vars[var] == 0)
00227                 printf("Wrong tag: %s\n", sharp);
00228             else
00229                 strcpy(current_result, values[var]);
00230         }
00231         current_result = current_result+strlen(current_result);
00232         sharp = end+1;
00233         template = sharp;
00234     }
00235     strcat(current_result, template);
00236     return result;
00237 }
00238 
00239 /****  Mhoram's code starts here *****/
00240 
00253 static void free_if_used(char *p) {
00254     if (p && strlen(p) > 0) {
00255         free(p);
00256     }
00257 }
00258 
00271 static int sortbyname(const void *a, const void *b) {
00272     return (strcasecmp(*(const char **)a, *(const char **)b));
00273 }
00274 
00288 static int sort_archetypes(const void *a, const void *b) {
00289     archetype *aa;
00290     archetype *bb;
00291 
00292     aa = *(archetype **)a;
00293     bb = *(archetype **)b;
00294 
00295     return (strcasecmp(aa->clone.name, bb->clone.name));
00296 }
00297 
00310 void push(String_Array *array, const char *string) {
00311     sint16 i = array->count;
00312 
00313     array->item[i] = strdup_local(string);
00314     array->count++;
00315 }
00316 
00325 void free_data(String_Array *array) {
00326     int item;
00327 
00328     for (item = 0; item < array->count; item++)
00329         free(array->item[item]);
00330     free(array->item);
00331     array->item = NULL;
00332 }
00333 
00344 const char *join_with_comma(String_Array *array) {
00345     char *newtext;
00346     int i;
00347 
00348     newtext = calloc(1, 1);
00349     qsort(array->item, array->count, sizeof(char *), sortbyname);
00350     for (i = 0; i < array->count; i++) {
00351         if (i) {
00352             newtext = realloc(newtext, strlen(newtext)+strlen(", ")+1);
00353             newtext = strncat(newtext, ", ", 2);
00354         }
00355         newtext = realloc(newtext, strlen(newtext)+strlen(array->item[i])+1);
00356         newtext = strncat(newtext, array->item[i], strlen(array->item[i]));
00357     }
00358     return newtext;
00359 }
00360 
00361 int main(int argc, char *argv[]) {
00362 
00363     archetype *at;
00364     int archnum = 0;
00365     archetype *monster[4000];
00366     int i;
00367     char letter;
00368     char last_letter;
00369     char *wiki_page = NULL;
00370     char *monster_entries = NULL;
00371 
00372     FILE *fp = NULL;
00373     FILE *image_list;
00374     char image_list_path[128];
00375     char wikifile[128];
00376     char *template;
00377 
00378     const char *wikidir = "/tmp";  /* Should change this to come from command line? */
00379 
00380     init_globals();
00381     init_library();
00382     init_archetypes();
00383     init_artifacts();
00384     init_formulae();
00385     init_readable();
00386 
00387     init_gods();
00388 
00389         /* Initialize templates */
00390     if (read_template("templates/wiki/monster_page_head", &monster_page_head))
00391         return;
00392     if (read_template("templates/wiki/monster_page_foot", &monster_page_foot))
00393         return;
00394     if (read_template("templates/wiki/monster_entry", &monster_entry))
00395         return;
00396     if (read_template("templates/wiki/monster_canuse_row", &monster_canuse_row))
00397         return;
00398     if (read_template("templates/wiki/monster_protected_row", &monster_protected_row))
00399         return;
00400     if (read_template("templates/wiki/monster_vulnerable_row", &monster_vulnerable_row))
00401         return;
00402     if (read_template("templates/wiki/monster_special_row", &monster_special_row))
00403         return;
00404     if (read_template("templates/wiki/monster_attack_row", &monster_attack_row))
00405         return;
00406     if (read_template("templates/wiki/monster_lore_row", &monster_lore_row))
00407         return;
00408     sprintf(image_list_path, "%s/image_list", wikidir);
00409     image_list = fopen(image_list_path, "w");
00410     if (!image_list) {
00411         LOG(llevError, "Unable to open image list file!\n");
00412         exit(1);
00413     }
00414 
00415         /* Pick out the monster archetypes and sort them into an array */
00416     for (at = first_archetype; at != NULL; at = at->next) {
00417         if (QUERY_FLAG(&at->clone, FLAG_MONSTER)
00418         && QUERY_FLAG(&at->clone, FLAG_ALIVE)) {
00419             monster[archnum++] = at;
00420         }
00421     }
00422     printf("Sorting...");
00423     /* Calling qsort on monster, which is archetype**     */
00424     qsort(&monster[0], archnum, sizeof(archetype *), sort_archetypes);
00425     printf("done.  %i items found\n", archnum);
00426 
00427     last_letter = '\0';
00428 
00429     for (i = 0; i < archnum; i++) {
00430         at = monster[i];
00431         if (at) {
00432             const char *key[16] = { NULL, };
00433             const char *val[16] = { NULL, };
00434             char buf[16][MAX_BUF];
00435             int keycount = 0;
00436             int res;
00437 
00438             letter = tolower(at->clone.name[0]);
00439 
00440             LOG(llevInfo, "Doing archetype %s\n", at->name);
00441 
00442             if (letter != last_letter) {  /* New letter, new file */
00443                 if (fp) {
00444                     keycount = 0;
00445                     key[keycount] = NULL;
00446                     template = do_template(monster_page_foot, key, val);
00447                     res = fprintf(fp, "%s", template);
00448                     free(template);
00449                     template = NULL;
00450                     if (res < 0) {
00451                         LOG(llevError, "Unable to write to file!\n");
00452                     }
00453                     fclose(fp);
00454                 }
00455 
00456                 snprintf(wikifile, sizeof(wikifile), "%s/%c", wikidir, letter);
00457                 fp = fopen(wikifile, "w");
00458                 if (!fp) {
00459                     fprintf(stderr, "Unable to write to wiki file!\n");
00460                     exit(1);
00461                 }
00462 
00463                 char letterindex[256] = "";
00464                 char letterindexnext[7];
00465                 char li;
00466                 letterindexnext[0] = '\0';
00467                 for (li = 'a'; li <= 'z'; li++) {
00468                     if (li == letter) {
00469                         sprintf(letterindexnext, "%c ", toupper(li));
00470                     } else {
00471                         sprintf(letterindexnext, "[[%c]] ", toupper(li));
00472                     }
00473                     strncat(letterindex, letterindexnext, 256);
00474                 }
00475 
00476                 keycount = 0;
00477                 key[keycount] = "LETTER";
00478                 sprintf(buf[keycount], "%c", toupper(letter));
00479                 val[keycount++] = buf[keycount];
00480                 key[keycount] = "LETTERINDEX";
00481                 val[keycount++] = letterindex;
00482                 key[keycount] = NULL;
00483                 template = do_template(monster_page_head, key, val);
00484                 res = fprintf(fp, template);
00485                 free(template);
00486                 if (res < 0) {
00487                     LOG(llevError, "Unable to write to file!");
00488                 }
00489                 last_letter = letter;
00490             }
00491 
00492             /* add a monster entry */
00493             char *canuse_row;
00494             char *protected_row;
00495             char *vulnerable_row;
00496             char *special_row;
00497             char *attack_row;
00498             char *lore_row;
00499             const int CANUSE_LENGTH = 16;
00500             String_Array canuse;
00501             String_Array resist;
00502             String_Array vulner;
00503             String_Array attack;
00504             String_Array special;
00505             /* Some flags that seemed useful; may need to add to this list.
00506              * *special_names[] is used because some of the names in
00507              * define.h are a bit awkward.  Last one is negative to mark end.
00508                  */
00509             const sint8 special_flags[] = { 21, 93, 52, 38, 13, 32, 61, -1 };
00510             const char *special_names[] = {
00511                 "see invisible",
00512                 "see in dark",
00513                 "spellcaster",
00514                 "unaggressive",
00515                 "flying",
00516                 "splitting",
00517                 "x-ray vision"
00518             };
00519             int j;
00520 
00521             canuse.item = calloc(1, sizeof(const char *)*(CANUSE_LENGTH+1));
00522             resist.item = calloc(1, sizeof(const char *)*(NROFATTACKS+1));
00523             vulner.item = calloc(1, sizeof(const char *)*(NROFATTACKS+1));
00524             attack.item = calloc(1, sizeof(const char *)*(NROFATTACKS+1));
00525             special.item = calloc(1, sizeof(const char *)*(NROFATTACKS+1));
00526 
00527                 /* Do lore row */
00528             if (at->clone.lore) {
00529                 key[keycount] = "LORE";
00530                 key[keycount+1] = NULL;
00531                 val[keycount] = at->clone.lore;
00532                 keycount++;
00533                 lore_row = do_template(monster_lore_row, key, val);
00534             } else
00535                 lore_row = strdup("");
00536 
00537                 /* Do canuse row */
00538             canuse.count = 0;
00539             keycount = 0;
00540             for (j = 1; j <= NUM_FLAGS; j++) {
00541                 if (QUERY_FLAG(&at->clone, j)
00542                 && flag_names[j]
00543                 && !strncmp(flag_names[j], "can_use_", 8)) {
00544                     push(&canuse, flag_names[j]+8);
00545                 }
00546             }
00547             if (canuse.count) {
00548                 key[keycount] = "CANUSE";
00549                 key[keycount+1] = NULL;
00550                 val[keycount] = join_with_comma(&canuse);
00551                 canuse_row = do_template(monster_canuse_row, key, val);
00552                 free(val[keycount]);
00553             } else
00554                 canuse_row = strdup("");
00555 
00556                 /* Do protected/vulnerable rows */
00557             resist.count = 0;
00558             vulner.count = 0;
00559             for (j = 0; j <= NROFATTACKS; j++) {
00560                 if (at->clone.resist[j] && attacktype_desc[j]) {
00561                     char rowtext[32];
00562 
00563                     if (at->clone.resist[j] < 0) {
00564                         sprintf(rowtext, "%s %i", attacktype_desc[j], at->clone.resist[j]);
00565                         push(&vulner, rowtext);
00566                     } else {
00567                         sprintf(rowtext, "%s +%i", attacktype_desc[j], at->clone.resist[j]);
00568                         push(&resist, rowtext);
00569                     }
00570                 }
00571             }
00572             keycount = 0;
00573             if (resist.count) {
00574                 key[keycount] = "PROTECTED";
00575                 key[keycount+1] = NULL;
00576                 val[keycount] = join_with_comma(&resist);
00577                 protected_row = do_template(monster_protected_row, key, val);
00578                 free(val[keycount]);
00579             } else
00580                 protected_row = strdup("");
00581 
00582             keycount = 0;
00583             if (vulner.count) {
00584                 key[keycount] = "VULNERABLE";
00585                 key[keycount+1] = NULL;
00586                 val[keycount] = join_with_comma(&vulner);
00587                 vulnerable_row = do_template(monster_vulnerable_row, key, val);
00588                 free(val[keycount]);
00589             } else
00590                 vulnerable_row = strdup("");
00591 
00592                 /* Do attacktype row */
00593             attack.count = 0;
00594             keycount = 0;
00595             val[keycount] = NULL;
00596             for (j = 0; j <= NROFATTACKS; j++) {
00597                 if (at->clone.attacktype&(1U<<j)) {
00598                     push(&attack, attacktype_desc[j]);
00599                 }
00600             }
00601             if (attack.count) {
00602                 key[keycount] = "ATTACKS";
00603                 key[keycount+1] = NULL;
00604                 val[keycount] = join_with_comma(&attack);
00605                 attack_row = do_template(monster_attack_row, key, val);
00606                 free(val[keycount]);
00607             } else
00608                 attack_row = strdup("");
00609 
00610                 /* Do special row */
00611             special.count = 0;
00612             keycount = 0;
00613             val[keycount] = NULL;
00614             for (j = 0; special_flags[j] >= 0; j++) {
00615                 if (QUERY_FLAG(&at->clone, special_flags[j])) {
00616                     push(&special, special_names[j]);
00617                 }
00618             }
00619             if (special.count) {
00620                 key[keycount] = "SPECIAL";
00621                 key[keycount+1] = NULL;
00622                 val[keycount] = join_with_comma(&special);
00623                 special_row = do_template(monster_special_row, key, val);
00624                 free(val[keycount]);
00625             } else
00626                 special_row = strdup("");
00627 
00628             keycount = 0;
00629             key[keycount] = "CANUSEROW";
00630             val[keycount++] = canuse_row;
00631             key[keycount] = "PROTECTEDROW";
00632             val[keycount++] = protected_row;
00633             key[keycount] = "VULNERABLEROW";
00634             val[keycount++] = vulnerable_row;
00635             key[keycount] = "SPECIALROW";
00636             val[keycount++] = attack_row;
00637             key[keycount] = "ATTACKROW";
00638             val[keycount++] = special_row;
00639             key[keycount] = "LOREROW";
00640             val[keycount++] = lore_row;
00641             key[keycount] = "XP";
00642             sprintf(buf[keycount], "%li", at->clone.stats.exp);
00643             val[keycount++] = buf[keycount];
00644             key[keycount] = "HP";
00645             sprintf(buf[keycount], "%i", at->clone.stats.hp);
00646             val[keycount++] = buf[keycount];
00647             key[keycount] = "AC";
00648             sprintf(buf[keycount], "%i", at->clone.stats.ac);
00649             val[keycount++] = buf[keycount];
00650             key[keycount] = "NAME";
00651             val[keycount++] = at->clone.name;
00652             key[keycount] = "RACE";
00653             if (at->clone.race) {
00654                 val[keycount++] = at->clone.race;
00655             } else {
00656                 val[keycount++] = NA;
00657             }
00658             if (at->clone.face->name) {
00659                 key[keycount] = "FACE";
00660                 sprintf(buf[keycount], "{{http://aaron.baugher.biz/images/cf/%s.png}}", at->clone.face->name);
00661                 val[keycount++] = buf[keycount];
00662                 sprintf(buf[keycount], "%s.png\n", at->clone.face->name);
00663                 fprintf(image_list, buf[keycount]);
00664             }
00665 /*  Plan to add generator face too, when I decide how    */
00666             key[keycount] = "GENFACE";
00667             val[keycount++] = "";
00668             key[keycount] = NULL;
00669 
00670             template = do_template(monster_entry, key, val);
00671             fprintf(fp, template);
00672             free(template);
00673             template = NULL;
00674 
00675             free_data(&canuse);
00676             free_data(&resist);
00677             free_data(&vulner);
00678             free_data(&attack);
00679             free_data(&special);
00680             free(canuse_row);
00681             free(protected_row);
00682             free(vulnerable_row);
00683             free(attack_row);
00684             free(special_row);
00685             free(lore_row);
00686         } else {
00687             LOG(llevError, "Something is very wrong.\n");
00688         }
00689     }
00690     fclose(image_list);
00691 }
00692 
00693 void set_map_timeout(void) {
00694     /* doesn't need to do anything */
00695 }
00696 
00697 #include <global.h>
00698 
00699 /* some plagarized code from apply.c--I needed just these two functions
00700    without all the rest of the junk, so.... */
00701 int auto_apply(object *op) {
00702     object *tmp = NULL;
00703     int i;
00704 
00705     switch (op->type) {
00706     case SHOP_FLOOR:
00707         if (!HAS_RANDOM_ITEMS(op))
00708             return 0;
00709         do {
00710             i = 10; /* let's give it 10 tries */
00711             while ((tmp = generate_treasure(op->randomitems, op->stats.exp ? op->stats.exp : 5)) == NULL && --i)
00712                 ;
00713             if (tmp == NULL)
00714                 return 0;
00715             if (QUERY_FLAG(tmp, FLAG_CURSED) || QUERY_FLAG(tmp, FLAG_DAMNED)) {
00716                 free_object(tmp);
00717                 tmp = NULL;
00718             }
00719         } while (!tmp);
00720 
00721         tmp->x = op->x,
00722         tmp->y = op->y;
00723         SET_FLAG(tmp, FLAG_UNPAID);
00724         insert_ob_in_map(tmp, op->map, NULL, 0);
00725         CLEAR_FLAG(op, FLAG_AUTO_APPLY);
00726         identify(tmp);
00727         break;
00728 
00729     case TREASURE:
00730         if (HAS_RANDOM_ITEMS(op))
00731             while ((op->stats.hp--) > 0)
00732                 create_treasure(op->randomitems, op, GT_ENVIRONMENT, op->stats.exp ? op->stats.exp : op->map == NULL ? 14 : op->map->difficulty, 0);
00733         remove_ob(op);
00734         free_object(op);
00735         break;
00736     }
00737 
00738     return tmp ? 1 : 0;
00739 }
00740 
00741 /* fix_auto_apply goes through the entire map (only the first time
00742  * when an original map is loaded) and performs special actions for
00743  * certain objects (most initialization of chests and creation of
00744  * treasures and stuff).  Calls auto_apply if appropriate.
00745  */
00746 void fix_auto_apply(mapstruct *m) {
00747     object *tmp, *above = NULL;
00748     int x, y;
00749 
00750     for (x = 0; x < MAP_WIDTH(m); x++)
00751         for (y = 0; y < MAP_HEIGHT(m); y++)
00752             for (tmp = GET_MAP_OB(m, x, y); tmp != NULL; tmp = above) {
00753                 above = tmp->above;
00754 
00755                 if (QUERY_FLAG(tmp, FLAG_AUTO_APPLY))
00756                     auto_apply(tmp);
00757                 else if (tmp->type == TREASURE) {
00758                     if (HAS_RANDOM_ITEMS(tmp))
00759                         while ((tmp->stats.hp--) > 0)
00760                             create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
00761                 }
00762                 if (tmp
00763                 && tmp->arch
00764                 && tmp->type != PLAYER
00765                 && tmp->type != TREASURE
00766                 && tmp->randomitems) {
00767                     if (tmp->type == CONTAINER) {
00768                         if (HAS_RANDOM_ITEMS(tmp))
00769                             while ((tmp->stats.hp--) > 0)
00770                                 create_treasure(tmp->randomitems, tmp, 0, m->difficulty, 0);
00771                     } else if (HAS_RANDOM_ITEMS(tmp))
00772                         create_treasure(tmp->randomitems, tmp, GT_APPLY, m->difficulty, 0);
00773                 }
00774             }
00775     for (x = 0; x < MAP_WIDTH(m); x++)
00776         for (y = 0; y < MAP_HEIGHT(m); y++)
00777             for (tmp = GET_MAP_OB(m, x, y); tmp != NULL; tmp = tmp->above)
00778                 if (tmp->above
00779                 && (tmp->type == TRIGGER_BUTTON || tmp->type == TRIGGER_PEDESTAL))
00780                     check_trigger(tmp, tmp->above);
00781 }
00782 
00783 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00784 
00790 void draw_ext_info(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *txt, const char *txt2) {
00791     fprintf(logfile, "%s\n", txt);
00792 }
00793 
00794 void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format, ...) {
00795     va_list ap;
00796     va_start(ap, old_format);
00797     vfprintf(logfile, old_format, ap);
00798     va_end(ap);
00799 }
00800 
00801 void ext_info_map(int color, const mapstruct *map, uint8 type, uint8 subtype, const char *str1, const char *str2) {
00802     fprintf(logfile, "ext_info_map: %s\n", str2);
00803 }
00804 
00805 void move_firewall(object *ob) {
00806 }
00807 
00808 void emergency_save(int x) {
00809 }
00810 
00811 void clean_tmp_files(void) {
00812 }
00813 
00814 void esrv_send_item(object *ob, object *obx) {
00815 }
00816 
00817 void dragon_ability_gain(object *ob, int x, int y) {
00818 }
00819 
00820 void set_darkness_map(mapstruct *m) {
00821 }
00822 
00823 object *find_skill_by_number(object *who, int skillno) {
00824     return NULL;
00825 }
00826 
00827 void esrv_del_item(player *pl, int tag) {
00828 }
00829 
00830 void esrv_update_spells(player *pl) {
00831 }
00832 
00833 void monster_check_apply(object *ob, object *obt) {
00834 }
00835 
00836 void trap_adjust(object *ob, int x) {
00837 }
00838 
00839 int execute_event(object *op, int eventcode, object *activator, object *third, const char *message, int fix) {
00840     return 0;
00841 }
00842 
00843 int execute_global_event(int eventcode, ...) {
00844     return 0;
00845 }
00846 #endif /* dummy DOXYGEN_SHOULD_SKIP_THIS */