/* * Find the default paths to all of our important sub-directories. * * The purpose of each sub-directory is described in "variable.c". * * All of the sub-directories should, by default, be located inside * the main "lib" directory, whose location is very system dependant. * * This function takes a writable buffer, initially containing the * "path" to the "lib" directory, for example, "/pkg/lib/angband/", * or a system dependant string, for example, ":lib:". The buffer * must be large enough to contain at least 32 more characters. * * Various command line options may allow some of the important * directories to be changed to user-specified directories, most * importantly, the "info" and "user" and "save" directories, * but this is done after this function, see "main.c". * * In general, the initial path should end in the appropriate "PATH_SEP" * string. All of the "sub-directory" paths (created below or supplied * by the user) will NOT end in the "PATH_SEP" string, see the special * "path_build()" function in "util.c" for more information. * * Mega-Hack -- support fat raw files under NEXTSTEP, using special * "suffixed" directories for the "ANGBAND_DIR_DATA" directory, but * requiring the directories to be created by hand by the user. * * Hack -- first we free all the strings, since this is known * to succeed even if the strings have not been allocated yet, * as long as the variables start out as "NULL". This allows * this function to be called multiple times, for example, to * try several base "path" values until a good one is found. */ void init_file_paths(char *path) { char *tail; #ifdef SET_UID char buf[1024]; #endif /* SET_UID */ /*** Free everything ***/ /* Free the main path */ string_free(ANGBAND_DIR); /* Free the sub-paths */ string_free(ANGBAND_DIR_APEX); string_free(ANGBAND_DIR_BONE); string_free(ANGBAND_DIR_DATA); string_free(ANGBAND_DIR_EDIT); string_free(ANGBAND_DIR_FILE); string_free(ANGBAND_DIR_HELP); string_free(ANGBAND_DIR_INFO); string_free(ANGBAND_DIR_SAVE); string_free(ANGBAND_DIR_PREF); string_free(ANGBAND_DIR_USER); string_free(ANGBAND_DIR_XTRA); /*** Prepare the "path" ***/ /* Hack -- save the main directory */ ANGBAND_DIR = string_make(path); /* Prepare to append to the Base Path */ tail = path + strlen(path); #ifdef VM /*** Use "flat" paths with VM/ESA ***/ /* Use "blank" path names */ ANGBAND_DIR_APEX = string_make(""); ANGBAND_DIR_BONE = string_make(""); ANGBAND_DIR_DATA = string_make(""); ANGBAND_DIR_EDIT = string_make(""); ANGBAND_DIR_FILE = string_make(""); ANGBAND_DIR_HELP = string_make(""); ANGBAND_DIR_INFO = string_make(""); ANGBAND_DIR_SAVE = string_make(""); ANGBAND_DIR_PREF = string_make(""); ANGBAND_DIR_USER = string_make(""); ANGBAND_DIR_XTRA = string_make(""); #else /* VM */ /*** Build the sub-directory names ***/ /* Build a path name */ strcpy(tail, "apex"); ANGBAND_DIR_APEX = string_make(path); /* Build a path name */ strcpy(tail, "bone"); ANGBAND_DIR_BONE = string_make(path); /* Build a path name */ strcpy(tail, "data"); ANGBAND_DIR_DATA = string_make(path); /* Build a path name */ strcpy(tail, "edit"); ANGBAND_DIR_EDIT = string_make(path); /* Build a path name */ strcpy(tail, "file"); ANGBAND_DIR_FILE = string_make(path); /* Build a path name */ strcpy(tail, "help"); ANGBAND_DIR_HELP = string_make(path); /* Build a path name */ strcpy(tail, "info"); ANGBAND_DIR_INFO = string_make(path); /* Build a path name */ strcpy(tail, "save"); ANGBAND_DIR_SAVE = string_make(path); /* Build a path name */ strcpy(tail, "pref"); ANGBAND_DIR_PREF = string_make(path); #ifdef PRIVATE_USER_PATH /* Build the path to the user specific directory */ path_build(buf, 1024, PRIVATE_USER_PATH, VERSION_NAME); /* Build a relative path name */ ANGBAND_DIR_USER = string_make(buf); #else /* PRIVATE_USER_PATH */ /* Build a path name */ strcpy(tail, "user"); ANGBAND_DIR_USER = string_make(path); #endif /* PRIVATE_USER_PATH */ /* Build a path name */ strcpy(tail, "xtra"); ANGBAND_DIR_XTRA = string_make(path); #endif /* VM */ #ifdef NeXT /* Allow "fat binary" usage with NeXT */ if (TRUE) { cptr next = NULL; # if defined(m68k) next = "m68k"; # endif # if defined(i386) next = "i386"; # endif # if defined(sparc) next = "sparc"; # endif # if defined(hppa) next = "hppa"; # endif /* Use special directory */ if (next) { /* Forget the old path name */ string_free(ANGBAND_DIR_DATA); /* Build a new path name */ sprintf(tail, "data-%s", next); ANGBAND_DIR_DATA = string_make(path); } } #endif /* NeXT */ }
/** * This is the function called from wiz-debug.c. */ void stats_collect(void) { static int simtype; static bool auto_flag; char buf[1024]; /* Prompt the user for sim params */ simtype = stats_prompt(); /* Make sure the results are good! */ if (!((simtype == 1) || (simtype == 2))) return; /* Are we in diving or clearing mode */ if (simtype == 2) clearing = TRUE; else clearing = FALSE; /* Open log file */ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "stats.log"); stats_log = file_open(buf, MODE_WRITE, FTYPE_TEXT); /* Logging didn't work */ if (!stats_log) { msg("Error - can't open stats.log for writing."); exit(1); } /* Turn on auto-more. This will clear prompts for items * that drop under the player, or that can't fit on the * floor due to too many items. This is a very small amount * of items, even on deeper levels, so it's not worth worrying * too much about. */ auto_flag = FALSE; if (!OPT(auto_more)) { /* Remember that we turned off auto_more */ auto_flag = TRUE; /* Turn on auto-more */ option_set(option_name(OPT_auto_more),TRUE); } /* Print heading for the file */ print_heading(); /* Make sure all stats are 0 */ init_stat_vals(); /* Select diving option */ if (!clearing) diving_stats(); /* Select clearing option */ if (clearing) clearing_stats(); /* Turn auto-more back off */ if (auto_flag) option_set(option_name(OPT_auto_more), FALSE); /* Close log file */ if (!file_close(stats_log)) { msg("Error - can't close randart.log file."); exit(1); } }
/* * Save a simple text screendump. */ static void do_cmd_save_screen_text(void) { int y, x; byte a = 0; char c = ' '; ang_file *fff; char buf[1024]; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt"); fff = file_open(buf, MODE_WRITE, FTYPE_TEXT); if (!fff) return; /* Save screen */ screen_save(); /* Dump the screen */ for (y = 0; y < 24; y++) { /* Dump each row */ for (x = 0; x < 79; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Dump it */ buf[x] = c; } /* Terminate */ buf[x] = '\0'; /* End the row */ file_putf(fff, "%s\n", buf); } /* Skip a line */ file_putf(fff, "\n"); /* Dump the screen */ for (y = 0; y < 24; y++) { /* Dump each row */ for (x = 0; x < 79; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Dump it */ buf[x] = hack[a & 0x0F]; } /* Terminate */ buf[x] = '\0'; /* End the row */ file_putf(fff, "%s\n", buf); } /* Skip a line */ file_putf(fff, "\n"); /* Close it */ file_close(fff); /* Message */ msg("Screen dump saved."); message_flush(); /* Load screen */ screen_load(); }
/* * Create a spoiler file for monsters */ static void spoil_mon_desc(const char *fname) { int i, n = 0; char buf[1024]; char nam[80]; char lev[80]; char rar[80]; char spd[80]; char ac[80]; char hp[80]; char exp[80]; u16b *who; /* We use either ascii or system-specific encoding */ int encoding = (OPT(xchars_to_file)) ? SYSTEM_SPECIFIC : ASCII; /* Build the filename */ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); fh = file_open(buf, MODE_WRITE, FTYPE_TEXT); /* Oops */ if (!fh) { msg("Cannot create spoiler file."); return; } /* Dump the header */ x_file_putf(fh, encoding, "Monster Spoilers for %s\n", buildid); x_file_putf(fh, encoding, "------------------------------------------\n\n"); /* Dump the header */ x_file_putf(fh, encoding, "%-40.40s%4s%4s%6s%8s%4s %11.11s\n", "Name", "Lev", "Rar", "Spd", "Hp", "Ac", "Visual Info"); x_file_putf(fh, encoding, "%-40.40s%4s%4s%6s%8s%4s %11.11s\n", "----", "---", "---", "---", "--", "--", "-----------"); /* Allocate the "who" array */ who = C_ZNEW(z_info->r_max, u16b); /* Scan the monsters (except the ghost) */ for (i = 1; i < z_info->r_max - 1; i++) { monster_race *r_ptr = &r_info[i]; /* Use that monster */ if (r_ptr->name) who[n++] = (u16b)i; } /* Sort the array by dungeon depth of monsters */ sort(who, n, sizeof(*who), cmp_monsters); /* Scan again */ for (i = 0; i < n; i++) { monster_race *r_ptr = &r_info[who[i]]; const char *name = r_ptr->name; /* Get the "name" */ if (rf_has(r_ptr->flags, RF_QUESTOR)) { strnfmt(nam, sizeof(nam), "[Q] %s", name); } else if (rf_has(r_ptr->flags, RF_UNIQUE)) { strnfmt(nam, sizeof(nam), "[U] %s", name); } else { strnfmt(nam, sizeof(nam), "The %s", name); } /* Level */ strnfmt(lev, sizeof(lev), "%d", r_ptr->level); /* Rarity */ strnfmt(rar, sizeof(rar), "%d", r_ptr->rarity); /* Speed */ if (r_ptr->speed >= 110) strnfmt(spd, sizeof(spd), "+%d", (r_ptr->speed - 110)); else strnfmt(spd, sizeof(spd), "-%d", (110 - r_ptr->speed)); /* Armor Class */ strnfmt(ac, sizeof(ac), "%d", r_ptr->ac); /* Hitpoints */ strnfmt(hp, sizeof(hp), "%d", r_ptr->avg_hp); /* Experience */ strnfmt(exp, sizeof(exp), "%ld", (long)(r_ptr->mexp)); /* Hack -- use visual instead */ strnfmt(exp, sizeof(exp), "%s '%c'", attr_to_text(r_ptr->d_attr), r_ptr->d_char); /* Dump the info */ x_file_putf(fh, encoding, "%-40.40s%4s%4s%6s%8s%4s %11.11s\n", nam, lev, rar, spd, hp, ac, exp); } /* End it */ file_putf(fh, "\n"); /* Free the "who" array */ FREE(who); /* Check for errors */ if (!file_close(fh)) { msg("Cannot close spoiler file."); return; } /* Worked */ msg("Successfully created a spoiler file."); }
void timestamp( char *target, time_t *time ) { PATHNAME f1, f2; BINDING binding, *b = &binding; string buf[1]; # ifdef DOWNSHIFT_PATHS string path; char *p; string_copy( &path, target ); p = path.value; do *p = tolower( *p ); while( *p++ ); target = path.value; # endif string_new( buf ); if( !bindhash ) bindhash = hashinit( sizeof( BINDING ), "bindings" ); /* Quick path - is it there? */ b->name = target; b->time = b->flags = 0; b->progress = BIND_INIT; if( hashenter( bindhash, (HASHDATA **)&b ) ) b->name = newstr( target ); /* never freed */ if( b->progress != BIND_INIT ) goto afterscanning; b->progress = BIND_NOENTRY; /* Not found - have to scan for it */ path_parse( target, &f1 ); /* Scan directory if not already done so */ { BINDING binding, *b = &binding; f2 = f1; f2.f_grist.len = 0; path_parent( &f2 ); path_build( &f2, buf, 0 ); b->name = buf->value; b->time = b->flags = 0; b->progress = BIND_INIT; if( hashenter( bindhash, (HASHDATA **)&b ) ) b->name = newstr( buf->value ); /* never freed */ if( !( b->flags & BIND_SCANNED ) ) { file_dirscan( buf->value, time_enter, bindhash ); b->flags |= BIND_SCANNED; } } /* Scan archive if not already done so */ if( f1.f_member.len ) { BINDING binding, *b = &binding; f2 = f1; f2.f_grist.len = 0; f2.f_member.len = 0; string_truncate( buf, 0 ); path_build( &f2, buf, 0 ); b->name = buf->value; b->time = b->flags = 0; b->progress = BIND_INIT; if( hashenter( bindhash, (HASHDATA **)&b ) ) b->name = newstr( buf->value ); /* never freed */ if( !( b->flags & BIND_SCANNED ) ) { file_archscan( buf->value, time_enter, bindhash ); b->flags |= BIND_SCANNED; } } afterscanning: if( b->progress == BIND_SPOTTED ) { if( file_time( b->name, &b->time ) < 0 ) b->progress = BIND_MISSING; else b->progress = BIND_FOUND; } *time = b->progress == BIND_FOUND ? b->time : 0; string_free( buf ); # ifdef DOWNSHIFT_PATHS string_free( &path ); #endif }
/*! * @brief 現在のオプション設定をダンプ出力する / * Hack -- Dump option bits usage * @return なし */ static void do_cmd_dump_options(void) { int i, j; FILE *fff; char buf[1024]; int **exist; /* Build the filename */ path_build(buf, sizeof buf, ANGBAND_DIR_USER, "opt_info.txt"); /* File type is "TEXT" */ FILE_TYPE(FILE_TYPE_TEXT); /* Open the file */ fff = my_fopen(buf, "a"); /* Oops */ if (!fff) { msg_format(_("ファイル %s を開けませんでした。", "Failed to open file %s."), buf); msg_print(NULL); return; } /* Allocate the "exist" array (2-dimension) */ C_MAKE(exist, NUM_O_SET, int *); C_MAKE(*exist, NUM_O_BIT * NUM_O_SET, int); for (i = 1; i < NUM_O_SET; i++) exist[i] = *exist + i * NUM_O_BIT; /* Check for exist option bits */ for (i = 0; option_info[i].o_desc; i++) { const option_type *ot_ptr = &option_info[i]; if (ot_ptr->o_var) exist[ot_ptr->o_set][ot_ptr->o_bit] = i + 1; } fprintf(fff, "[Option bits usage on Hengband %d.%d.%d]\n\n", FAKE_VER_MAJOR - 10, FAKE_VER_MINOR, FAKE_VER_PATCH); fputs("Set - Bit (Page) Option Name\n", fff); fputs("------------------------------------------------\n", fff); /* Dump option bits usage */ for (i = 0; i < NUM_O_SET; i++) { for (j = 0; j < NUM_O_BIT; j++) { if (exist[i][j]) { const option_type *ot_ptr = &option_info[exist[i][j] - 1]; fprintf(fff, " %d - %02d (%4d) %s\n", i, j, ot_ptr->o_page, ot_ptr->o_text); } else { fprintf(fff, " %d - %02d\n", i, j); } } fputc('\n', fff); } /* Free the "exist" array (2-dimension) */ C_KILL(*exist, NUM_O_BIT * NUM_O_SET, int); C_KILL(exist, NUM_O_SET, int *); /* Close it */ my_fclose(fff); msg_format(_("オプションbit使用状況をファイル %s に書き出しました。", "Option bits usage dump saved to file %s."), buf); }
/* * Create a spoiler file for items */ static void spoil_obj_desc(const char *fname) { int i, k, s, t, n = 0; u16b who[200]; char buf[1024]; char wgt[80]; char dam[80]; const char *format = "%-51s %7s%6s%4s%9s\n"; /* We use either ascii or system-specific encoding */ int encoding = (OPT(xchars_to_file)) ? SYSTEM_SPECIFIC : ASCII; /* Open the file */ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); fh = file_open(buf, MODE_WRITE, FTYPE_TEXT); /* Oops */ if (!fh) { msg("Cannot create spoiler file."); return; } /* Header */ file_putf(fh, "Spoiler File -- Basic Items (%s)\n\n\n", buildid); /* More Header */ file_putf(fh, format, "Description", "Dam/AC", "Wgt", "Lev", "Cost"); file_putf(fh, format, "----------------------------------------", "------", "---", "---", "----"); /* List the groups */ for (i = 0; TRUE; i++) { /* Write out the group title */ if (group_item[i].name) { /* Hack -- bubble-sort by cost and then level */ for (s = 0; s < n - 1; s++) { for (t = 0; t < n - 1; t++) { int i1 = t; int i2 = t + 1; int e1; int e2; s32b t1; s32b t2; kind_info(NULL, 0, NULL, 0, NULL, 0, &e1, &t1, who[i1]); kind_info(NULL, 0, NULL, 0, NULL, 0, &e2, &t2, who[i2]); if ((t1 > t2) || ((t1 == t2) && (e1 > e2))) { int tmp = who[i1]; who[i1] = who[i2]; who[i2] = tmp; } } } /* Spoil each item */ for (s = 0; s < n; s++) { int e; s32b v; /* Describe the kind */ kind_info(buf, sizeof(buf), dam, sizeof(dam), wgt, sizeof(wgt), &e, &v, who[s]); /* Dump it */ x_file_putf(fh, encoding, " %-51s%7s%6s%4d%9ld\n", buf, dam, wgt, e, (long)(v)); } /* Start a new set */ n = 0; /* Notice the end */ if (!group_item[i].tval) break; /* Start a new set */ x_file_putf(fh, encoding, "\n\n%s\n\n", group_item[i].name); } /* Get legal item types */ for (k = 1; k < z_info->k_max; k++) { object_kind *k_ptr = &k_info[k]; /* Skip wrong tval's */ if (k_ptr->tval != group_item[i].tval) continue; /* Hack -- Skip instant-artifacts */ if (of_has(k_ptr->flags, OF_INSTA_ART)) continue; /* Save the index */ who[n++] = k; } } /* Check for errors */ if (!file_close(fh)) { msg("Cannot close spoiler file."); return; } /* Message */ msg("Successfully created a spoiler file."); }
/*used to check the power of artifacts. Currently unused*/ void dump_artifact_power(void) { int i; char buf[1024]; int fd; FILE *fff = NULL; artifact_type *a_ptr; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_EDIT, "power.txt"); /* Check for existing file */ fd = fd_open(buf, O_RDONLY); /* Existing file */ if (fd >= 0) { char out_val[160]; /* Close the file */ fd_close(fd); /* Build query */ sprintf(out_val, "Replace existing file %s? ", buf); /* Ask */ if (get_check(out_val)) fd = -1; } /* Open the non-existing file */ if (fd < 0) fff = my_fopen(buf, "w"); /* No output file - fail */ if (!fff) return; /* Write a note */ fprintf(fff, "# File: artifact_power.txt (autogenerated)\n\n"); /* Read and print out all the objects */ for (i = 1; i < z_info->art_norm_max; i++) { s32b power; char o_name[80]; object_type *i_ptr; object_type object_type_body; /* Get local object */ i_ptr = &object_type_body; /* Get the object */ a_ptr = &a_info[i]; /* Ignore unused objects */ if (!strlen(a_ptr->name)) { fprintf(fff, "## empty space (available for artifact) ##\n\n"); continue; } /* Write the complete name of the artifact*/ make_fake_artifact(i_ptr, i); /* Identify it */ object_aware(i_ptr); object_known(i_ptr); i_ptr->ident |= (IDENT_MENTAL); /* Get a description to dump */ object_desc(o_name, sizeof(o_name), i_ptr, TRUE, 0); power = artifact_power(i); /*dump the information*/ fprintf(fff, "%9d is the power of %55s, tval is %6d \n", power, o_name, a_ptr->tval); } /* Done */ fclose(fff); }
/* * Use the monster racial information to a format easily parsed by a spreadsheet. * * Original function by -EB- (probably), revisions by -LM- & JG. */ void write_mon_power(void) { int i; char buf[1024]; int fd; FILE *fff = NULL; monster_race *r_ptr; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_EDIT, "mon_power_output.txt"); /* Check for existing file */ fd = fd_open(buf, O_RDONLY); /* Existing file */ if (fd >= 0) { char out_val[160]; /* Close the file */ fd_close(fd); /* Build query */ sprintf(out_val, "Replace existing file %s? ", buf); /* Ask */ if (get_check(out_val)) fd = -1; } /* Open the non-existing file */ if (fd < 0) fff = my_fopen(buf, "w"); /* No output file - fail */ if (!fff) return; /* Write a note */ fprintf(fff, "# File: mon_power_output.txt (autogenerated)\n\n"); /* Write a note */ fprintf(fff, "##### The Player #####\n\n"); /* Read and print out all the monsters */ for (i = 0; i < z_info->r_max; i++) { /* Get the monster */ r_ptr = &r_info[i]; /* Ignore empty monsters */ if (!strlen(r_name + r_ptr->name)) { fprintf(fff, "## empty space (available for monsters) ##\n\n"); continue; } /* Write New/Number/Name */ fprintf(fff, "%3d:lvl: %3d power:%9d hp:%9d dam:%9d name: %s\n", i, r_ptr->level, r_ptr->mon_power, r_ptr->mon_eval_hp, r_ptr->mon_eval_dam,(r_name + r_ptr->name)); } /*a few blank lines*/ fprintf(fff, "\n\n"); /*first clear the tables*/ for (i = 0; i < MAX_DEPTH; i++) { /* Write New/Number/Name */ fprintf(fff, "lvl: %3d unique_ave_power:%9d creature_ave_power:%9d \n", i, mon_power_ave[i][CREATURE_UNIQUE], mon_power_ave[i][CREATURE_NON_UNIQUE]); } /* Done */ fclose(fff); }
/** * Create a spoiler file for artifacts */ static void spoil_artifact(const char *fname) { int i, j; char buf[1024]; /* Build the filename */ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); fh = file_open(buf, MODE_WRITE, FTYPE_TEXT); /* Oops */ if (!fh) { msg("Cannot create spoiler file."); return; } /* Dump to the spoiler file */ text_out_hook = text_out_to_file; text_out_file = fh; /* Dump the header */ spoiler_underline(format("Artifact Spoilers for %s", buildid), '='); text_out("\n Randart seed is %u\n", seed_randart); /* List the artifacts by tval */ for (i = 0; group_artifact[i].tval; i++) { /* Write out the group title */ if (group_artifact[i].name) { spoiler_blanklines(2); spoiler_underline(group_artifact[i].name, '='); spoiler_blanklines(1); } /* Now search through all of the artifacts */ for (j = 1; j < z_info->a_max; ++j) { struct artifact *art = &a_info[j]; char buf2[80]; char *temp; struct object *obj, *known_obj; /* We only want objects in the current group */ if (art->tval != group_artifact[i].tval) continue; /* Get local object */ obj = object_new(); known_obj = object_new(); /* Attempt to "forge" the artifact */ if (!make_fake_artifact(obj, art)) { object_delete(&known_obj); object_delete(&obj); continue; } /* Grab artifact name */ object_copy(known_obj, obj); obj->known = known_obj; object_desc(buf2, sizeof(buf2), obj, ODESC_PREFIX | ODESC_COMBAT | ODESC_EXTRA | ODESC_SPOIL); /* Print name and underline */ spoiler_underline(buf2, '-'); /* Temporarily blank the artifact flavour text - spoilers spoil the mechanics, not the atmosphere. */ temp = obj->artifact->text; obj->artifact->text = NULL; /* Write out the artifact description to the spoiler file */ object_info_spoil(fh, obj, 80); /* Put back the flavour */ obj->artifact->text = temp; /* * Determine the minimum and maximum depths an * artifact can appear, its rarity, its weight, and * its power rating. */ text_out("\nMin Level %u, Max Level %u, Generation chance %u, Power %d, %d.%d lbs\n", art->alloc_min, art->alloc_max, art->alloc_prob, object_power(obj, false, NULL), (art->weight / 10), (art->weight % 10)); if (OPT(birth_randarts)) text_out("%s.\n", art->text); /* Terminate the entry */ spoiler_blanklines(2); object_delete(&known_obj); object_delete(&obj); } } /* Check for errors */ if (!file_close(fh)) { msg("Cannot close spoiler file."); return; } /* Message */ msg("Successfully created a spoiler file."); }
/** * Create a spoiler file for monsters (-SHAWN-) */ static void spoil_mon_info(const char *fname) { char buf[1024]; int i, n; u16b *who; int count = 0; textblock *tb = NULL; /* Open the file */ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); fh = file_open(buf, MODE_WRITE, FTYPE_TEXT); if (!fh) { msg("Cannot create spoiler file."); return; } /* Dump the header */ tb = textblock_new(); textblock_append(tb, "Monster Spoilers for %s\n", buildid); textblock_append(tb, "------------------------------------------\n\n"); textblock_to_file(tb, fh, 0, 75); textblock_free(tb); tb = NULL; /* Allocate the "who" array */ who = mem_zalloc(z_info->r_max * sizeof(u16b)); /* Scan the monsters */ for (i = 1; i < z_info->r_max; i++) { struct monster_race *race = &r_info[i]; /* Use that monster */ if (race->name) who[count++] = (u16b)i; } sort(who, count, sizeof(*who), cmp_monsters); /* List all monsters in order. */ for (n = 0; n < count; n++) { int r_idx = who[n]; const struct monster_race *race = &r_info[r_idx]; const struct monster_lore *lore = &l_list[r_idx]; tb = textblock_new(); /* Line 1: prefix, name, color, and symbol */ if (rf_has(race->flags, RF_QUESTOR)) textblock_append(tb, "[Q] "); else if (rf_has(race->flags, RF_UNIQUE)) textblock_append(tb, "[U] "); else textblock_append(tb, "The "); /* As of 3.5, race->name and race->text are stored as UTF-8 strings; * there is no conversion from the source edit files. */ textblock_append_utf8(tb, race->name); textblock_append(tb, " ("); /* ---)--- */ textblock_append(tb, attr_to_text(race->d_attr)); textblock_append(tb, " '%c')\n", race->d_char); /* Line 2: number, level, rarity, speed, HP, AC, exp */ textblock_append(tb, "=== "); textblock_append(tb, "Num:%d ", r_idx); textblock_append(tb, "Lev:%d ", race->level); textblock_append(tb, "Rar:%d ", race->rarity); if (race->speed >= 110) textblock_append(tb, "Spd:+%d ", (race->speed - 110)); else textblock_append(tb, "Spd:-%d ", (110 - race->speed)); textblock_append(tb, "Hp:%d ", race->avg_hp); textblock_append(tb, "Ac:%d ", race->ac); textblock_append(tb, "Exp:%ld\n", (long)(race->mexp)); /* Normal description (with automatic line breaks) */ lore_description(tb, race, lore, true); textblock_append(tb, "\n"); textblock_to_file(tb, fh, 0, 75); textblock_free(tb); tb = NULL; } /* Free the "who" array */ mem_free(who); /* Check for errors */ if (!file_close(fh)) { msg("Cannot close spoiler file."); return; } msg("Successfully created a spoiler file."); }
/* * Initialization function for an "X11" module to Angband */ errr init_x11(int argc, char **argv) { int i; cptr dpy_name = ""; int num_term = 1; #ifdef USE_GRAPHICS cptr bitmap_file = ""; char filename[1024]; int pict_wid = 0; int pict_hgt = 0; char *TmpData; #endif /* USE_GRAPHICS */ /* Parse args */ for (i = 1; i < argc; i++) { if (prefix(argv[i], "-d")) { dpy_name = &argv[i][2]; continue; } #ifdef USE_GRAPHICS if (prefix(argv[i], "-s")) { smoothRescaling = FALSE; continue; } if (prefix(argv[i], "-o")) { arg_graphics = GRAPHICS_ORIGINAL; continue; } if (prefix(argv[i], "-a")) { arg_graphics = GRAPHICS_ADAM_BOLT; continue; } if (prefix(argv[i], "-g")) { smoothRescaling = FALSE; arg_graphics = GRAPHICS_DAVID_GERVAIS; continue; } if (prefix(argv[i], "-b")) { use_bigtile = TRUE; continue; } #endif /* USE_GRAPHICS */ if (prefix(argv[i], "-n")) { num_term = atoi(&argv[i][2]); if (num_term > MAX_TERM_DATA) num_term = MAX_TERM_DATA; else if (num_term < 1) num_term = 1; continue; } plog_fmt("Ignoring option: %s", argv[i]); } /* Init the Metadpy if possible */ if (Metadpy_init_name(dpy_name)) return (-1); /* Prepare cursor color */ MAKE(xor, infoclr); Infoclr_set(xor); Infoclr_init_ppn(Metadpy->fg, Metadpy->bg, "xor", 0); /* Prepare normal colors */ for (i = 0; i < 256; ++i) { Pixell pixel; MAKE(clr[i], infoclr); Infoclr_set(clr[i]); /* Acquire Angband colors */ color_table[i][0] = angband_color_table[i][0]; color_table[i][1] = angband_color_table[i][1]; color_table[i][2] = angband_color_table[i][2]; color_table[i][3] = angband_color_table[i][3]; /* Default to monochrome */ pixel = ((i == 0) ? Metadpy->bg : Metadpy->fg); /* Handle color */ if (Metadpy->color) { /* Create pixel */ pixel = create_pixel(Metadpy->dpy, color_table[i][1], color_table[i][2], color_table[i][3]); } /* Initialize the color */ Infoclr_init_ppn(pixel, Metadpy->bg, "cpy", 0); } /* Initialize the windows */ for (i = 0; i < num_term; i++) { term_data *td = &data[i]; /* Initialize the term_data */ term_data_init(td, i); /* Save global entry */ angband_term[i] = Term; } /* Raise the "Angband" window */ Infowin_set(data[0].win); Infowin_raise(); /* Activate the "Angband" window screen */ Term_activate(&data[0].t); #ifdef USE_GRAPHICS /* Try graphics */ switch (arg_graphics) { case GRAPHICS_ADAM_BOLT: /* Use tile graphics of Adam Bolt */ bitmap_file = "16x16.bmp"; /* Try the "16x16.bmp" file */ path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, format("graf/%s", bitmap_file)); /* Use the "16x16.bmp" file if it exists */ if (0 == fd_close(fd_open(filename, O_RDONLY))) { /* Use graphics */ use_graphics = TRUE; use_transparency = TRUE; pict_wid = pict_hgt = 16; ANGBAND_GRAF = "new"; break; } /* Fall through */ case GRAPHICS_ORIGINAL: /* Use original tile graphics */ bitmap_file = "8x8.bmp"; /* Try the "8x8.bmp" file */ path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, format("graf/%s", bitmap_file)); /* Use the "8x8.bmp" file if it exists */ if (0 == fd_close(fd_open(filename, O_RDONLY))) { /* Use graphics */ use_graphics = TRUE; pict_wid = pict_hgt = 8; ANGBAND_GRAF = "old"; break; } break; case GRAPHICS_DAVID_GERVAIS: /* Use tile graphics of David Gervais */ bitmap_file = "32x32.bmp"; /* Use graphics */ use_graphics = TRUE; use_transparency = TRUE; pict_wid = pict_hgt = 32; ANGBAND_GRAF = "david"; break; } /* Load graphics */ if (use_graphics) { Display *dpy = Metadpy->dpy; XImage *tiles_raw; /* Initialize */ for (i = 0; i < num_term; i++) { term_data *td = &data[i]; td->tiles = NULL; } path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, format("graf/%s", bitmap_file)); /* Load the graphical tiles */ tiles_raw = ReadBMP(dpy, filename); if (tiles_raw) { /* Initialize the windows */ for (i = 0; i < num_term; i++) { int j; bool same = FALSE; term_data *td = &data[i]; term_data *o_td = NULL; term *t = &td->t; /* Graphics hook */ t->pict_hook = Term_pict_x11; /* Use graphics sometimes */ t->higher_pict = TRUE; /* Look for another term with same font size */ for (j = 0; j < i; j++) { o_td = &data[j]; if ((td->fnt->twid == o_td->fnt->twid) && (td->fnt->hgt == o_td->fnt->hgt)) { same = TRUE; break; } } if (!same) { /* Resize tiles */ td->tiles = ResizeImage(dpy, tiles_raw, pict_wid, pict_hgt, td->fnt->twid, td->fnt->hgt); } else { /* Use same graphics */ td->tiles = o_td->tiles; } } /* Free tiles_raw */ FREE(tiles_raw); } /* Initialize the transparency masks */ for (i = 0; i < num_term; i++) { term_data *td = &data[i]; int ii, jj; int depth = DefaultDepth(dpy, DefaultScreen(dpy)); Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy)); int total; /* Determine total bytes needed for image */ ii = 1; jj = (depth - 1) >> 2; while (jj >>= 1) ii <<= 1; total = td->fnt->twid * td->fnt->hgt * ii; TmpData = (char *)malloc(total); td->TmpImage = XCreateImage(dpy,visual,depth, ZPixmap, 0, TmpData, td->fnt->twid, td->fnt->hgt, 32, 0); } } #endif /* USE_GRAPHICS */ /* Success */ return (0); }
/* * Actually place an entry into the high score file * Return the location (0 is best) or -1 on "failure" */ static void highscore_write(const high_score scores[], size_t sz) { size_t n; ang_file *lok; ang_file *scorefile; char old_name[1024]; char cur_name[1024]; char new_name[1024]; char lok_name[1024]; path_build(old_name, sizeof(old_name), ANGBAND_DIR_APEX, "scores.old"); path_build(cur_name, sizeof(cur_name), ANGBAND_DIR_APEX, "scores.raw"); path_build(new_name, sizeof(new_name), ANGBAND_DIR_APEX, "scores.new"); path_build(lok_name, sizeof(lok_name), ANGBAND_DIR_APEX, "scores.lok"); /* Read in and add new score */ n = highscore_count(scores, sz); /*** Lock scores ***/ if (file_exists(lok_name)) { msg("Lock file in place for scorefile; not writing."); return; } safe_setuid_grab(); lok = file_open(lok_name, MODE_WRITE, FTYPE_RAW); file_lock(lok); safe_setuid_drop(); if (!lok) { msg("Failed to create lock for scorefile; not writing."); return; } /*** Open the new file for writing ***/ safe_setuid_grab(); scorefile = file_open(new_name, MODE_WRITE, FTYPE_RAW); safe_setuid_drop(); if (!scorefile) { msg("Failed to open new scorefile for writing."); file_close(lok); file_delete(lok_name); return; } file_write(scorefile, (const char *)scores, sizeof(high_score)*n); file_close(scorefile); /*** Now move things around ***/ safe_setuid_grab(); if (file_exists(old_name) && !file_delete(old_name)) msg("Couldn't delete old scorefile"); if (file_exists(cur_name) && !file_move(cur_name, old_name)) msg("Couldn't move old scores.raw out of the way"); if (!file_move(new_name, cur_name)) msg("Couldn't rename new scorefile to scores.raw"); /* Remove the lock */ file_close(lok); file_delete(lok_name); safe_setuid_drop(); }
/* * Initialization function for an X Athena Widget module to Angband * * We should accept "-d<dpy>" requests in the "argv" array. XXX XXX XXX */ errr init_xaw(int argc, char **argv) { int i; Widget topLevel; Display *dpy; cptr dpy_name = ""; #ifdef USE_GRAPHICS cptr bitmap_file = ""; char filename[1024]; int pict_wid = 0; int pict_hgt = 0; char *TmpData; #endif /* USE_GRAPHICS */ /* Parse args */ for (i = 1; i < argc; i++) { if (prefix(argv[i], "-d")) { dpy_name = &argv[i][2]; continue; } #ifdef USE_GRAPHICS if (prefix(argv[i], "-s")) { smoothRescaling = FALSE; continue; } if (prefix(argv[i], "-o")) { arg_graphics = GRAPHICS_ORIGINAL; continue; } if (prefix(argv[i], "-a")) { arg_graphics = GRAPHICS_ADAM_BOLT; continue; } if (prefix(argv[i], "-g")) { smoothRescaling = FALSE; arg_graphics = GRAPHICS_DAVID_GERVAIS; continue; } if (prefix(argv[i], "-b")) { use_bigtile = TRUE; continue; } #endif /* USE_GRAPHICS */ if (prefix(argv[i], "-n")) { num_term = atoi(&argv[i][2]); if (num_term > MAX_TERM_DATA) num_term = MAX_TERM_DATA; else if (num_term < 1) num_term = 1; continue; } plog_fmt("Ignoring option: %s", argv[i]); } /* Attempt to open the local display */ dpy = XOpenDisplay(dpy_name); /* Failure -- assume no X11 available */ if (!dpy) return (-1); /* Close the local display */ XCloseDisplay(dpy); #ifdef USE_XAW_LANG /* Support locale processing */ XtSetLanguageProc(NULL, NULL, NULL); #endif /* USE_XAW_LANG */ /* Initialize the toolkit */ topLevel = XtAppInitialize(&appcon, "Angband", NULL, 0, &argc, argv, fallback, NULL, 0); /* Initialize the windows */ for (i = 0; i < num_term; i++) { term_data *td = &data[i]; term_data_init(td, topLevel, 1024, termNames[i], (i == 0) ? specialArgs : defaultArgs, TERM_FALLBACKS, i); angband_term[i] = Term; } /* Activate the "Angband" window screen */ Term_activate(&data[0].t); /* Raise the "Angband" window */ term_raise(&data[0]); #ifdef USE_GRAPHICS /* Try graphics */ switch (arg_graphics) { case GRAPHICS_ADAM_BOLT: /* Use tile graphics of Adam Bolt */ bitmap_file = "16x16.bmp"; /* Try the "16x16.bmp" file */ path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, format("graf/%s", bitmap_file)); /* Use the "16x16.bmp" file if it exists */ if (0 == fd_close(fd_open(filename, O_RDONLY))) { /* Use graphics */ use_graphics = GRAPHICS_ADAM_BOLT; use_transparency = TRUE; pict_wid = pict_hgt = 16; ANGBAND_GRAF = "new"; break; } /* Fall through */ case GRAPHICS_ORIGINAL: /* Use original tile graphics */ bitmap_file = "8x8.bmp"; /* Try the "8x8.bmp" file */ path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, format("graf/%s", bitmap_file)); /* Use the "8x8.bmp" file if it exists */ if (0 == fd_close(fd_open(filename, O_RDONLY))) { /* Use graphics */ use_graphics = GRAPHICS_ORIGINAL; pict_wid = pict_hgt = 8; ANGBAND_GRAF = "old"; break; } break; case GRAPHICS_DAVID_GERVAIS: /* Use tile graphics of David Gervais */ bitmap_file = "32x32.bmp"; /* Use graphics */ use_graphics = GRAPHICS_DAVID_GERVAIS; use_transparency = TRUE; pict_wid = pict_hgt = 32; ANGBAND_GRAF = "david"; break; } /* Load graphics */ if (use_graphics) { /* Hack -- Get the Display */ term_data *td = &data[0]; Widget widget = (Widget)(td->widget); Display *dpy = XtDisplay(widget); XImage *tiles_raw; for (i = 0; i < num_term; i++) { term_data *td = &data[i]; td->widget->angband.tiles = NULL; } path_build(filename, sizeof(filename), ANGBAND_DIR_XTRA, format("graf/%s", bitmap_file)); /* Load the graphical tiles */ tiles_raw = ReadBMP(dpy, filename); if (tiles_raw) { /* Initialize the windows */ for (i = 0; i < num_term; i++) { int j; bool same = FALSE; term_data *td = &data[i]; term_data *o_td = NULL; term *t = &td->t; t->pict_hook = Term_pict_xaw; t->higher_pict = TRUE; /* Look for another term with same font size */ for (j = 0; j < i; j++) { o_td = &data[j]; if ((td->widget->angband.tilewidth == o_td->widget->angband.tilewidth) && (td->widget->angband.fontheight == o_td->widget->angband.fontheight)) { same = TRUE; break; } } if (!same) { /* Resize tiles */ td->widget->angband.tiles = ResizeImage(dpy, tiles_raw, pict_wid, pict_hgt, td->widget->angband.tilewidth, td->widget->angband.fontheight); } else { /* Use same graphics */ td->widget->angband.tiles = o_td->widget->angband.tiles; } } /* Free tiles_raw */ FREE(tiles_raw); } /* Initialize the transparency temp storage */ for (i = 0; i < num_term; i++) { term_data *td = &data[i]; int ii, jj; int depth = DefaultDepth(dpy, DefaultScreen(dpy)); Visual *visual = DefaultVisual(dpy, DefaultScreen(dpy)); int total; /* Determine total bytes needed for image */ ii = 1; jj = (depth - 1) >> 2; while (jj >>= 1) ii <<= 1; total = td->widget->angband.tilewidth * td->widget->angband.fontheight * ii; TmpData = (char *)malloc(total); td->widget->angband.TmpImage = XCreateImage(dpy, visual,depth, ZPixmap, 0, TmpData, td->widget->angband.tilewidth, td->widget->angband.fontheight, 8, 0); } } #endif /* USE_GRAPHICS */ /* Success */ return (0); }
OBJECT * search( OBJECT * target, time_t *time, OBJECT * * another_target, int file ) { PATHNAME f[1]; LIST * varlist; string buf[1]; int found = 0; /* Will be set to 1 if target location is specified via LOCATE. */ int explicitly_located = 0; OBJECT * boundname = 0; if ( another_target ) *another_target = 0; if (! explicit_bindings ) explicit_bindings = hashinit( sizeof(BINDING), "explicitly specified locations"); string_new( buf ); /* Parse the filename */ path_parse( object_str( target ), f ); f->f_grist.ptr = 0; f->f_grist.len = 0; varlist = var_get( root_module(), constant_LOCATE ); if ( !list_empty( varlist ) ) { OBJECT * key; f->f_root.ptr = object_str( list_front( varlist ) ); f->f_root.len = strlen( object_str( list_front( varlist ) ) ); path_build( f, buf, 1 ); if ( DEBUG_SEARCH ) printf( "locate %s: %s\n", object_str( target ), buf->value ); explicitly_located = 1; key = object_new( buf->value ); timestamp( key, time ); object_free( key ); found = 1; } else if ( varlist = var_get( root_module(), constant_SEARCH ), !list_empty( varlist ) ) { LISTITER iter = list_begin( varlist ), end = list_end( varlist ); for ( ; iter != end; iter = list_next( iter ) ) { BINDING * ba; file_info_t *ff; OBJECT * key; OBJECT * test_path; f->f_root.ptr = object_str( list_item( iter ) ); f->f_root.len = strlen( object_str( list_item( iter ) ) ); string_truncate( buf, 0 ); path_build( f, buf, 1 ); if ( DEBUG_SEARCH ) printf( "search %s: %s\n", object_str( target ), buf->value ); test_path = object_new( buf->value ); key = path_as_key( test_path ); object_free( test_path ); ff = file_query( key ); timestamp( key, time ); if ( ( ba = (BINDING *)hash_find( explicit_bindings, key ) ) ) { if ( DEBUG_SEARCH ) printf(" search %s: found explicitly located target %s\n", object_str( target ), object_str( ba->target ) ); if ( another_target ) *another_target = ba->target; found = 1; object_free( key ); break; } else if ( ff && ff->time ) { if ( !file || ff->is_file ) { found = 1; object_free( key ); break; } } object_free( key ); } } if ( !found ) { /* Look for the obvious */ /* This is a questionable move. Should we look in the */ /* obvious place if SEARCH is set? */ OBJECT * key; f->f_root.ptr = 0; f->f_root.len = 0; string_truncate( buf, 0 ); path_build( f, buf, 1 ); if ( DEBUG_SEARCH ) printf( "search %s: %s\n", object_str( target ), buf->value ); key = object_new( buf->value ); timestamp( key, time ); object_free( key ); } boundname = object_new( buf->value ); string_free( buf ); if ( explicitly_located ) { int found; BINDING * ba; OBJECT * key = path_as_key( boundname ); /* CONSIDER: we probably should issue a warning is another file is explicitly bound to the same location. This might break compatibility, though. */ ba = (BINDING *)hash_insert( explicit_bindings, key, &found ); if ( !found ) { ba->binding = key; ba->target = target; } else { object_free( key ); } } /* prepare a call to BINDRULE if the variable is set */ call_bind_rule( target, boundname ); return boundname; }
/* * Dump the object information a format easily parsed by a spreadsheet. * * Original function by -EB- (probably), revisions by -LM- & JG. */ void write_o_info_txt(void) { int i, j, bc; int dlen; char buf[1024]; int fd; FILE *fff = NULL; cptr desc; object_kind *k_ptr; /* We allow 75 characters on the line (plus 2) */ u16b line_length = 75; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_EDIT, "o_output.txt"); /* Check for existing file */ fd = fd_open(buf, O_RDONLY); /* Existing file */ if (fd >= 0) { char out_val[160]; /* Close the file */ fd_close(fd); /* Build query */ sprintf(out_val, "Replace existing file %s? ", buf); /* Ask */ if (get_check(out_val)) fd = -1; } /* Open the non-existing file */ if (fd < 0) fff = my_fopen(buf, "w"); /* No output file - fail */ if (!fff) return; /* Write a note */ fprintf(fff, "# File: o_info.txt (autogenerated)\n\n"); /* Read and print out all the objects */ for (i = 0; i < z_info->k_max; i++) { int counter = 1; cptr color_name; /* Get the object */ k_ptr = &k_info[i]; /* Ignore unused objects */ if (!strlen((k_name + k_ptr->name))) { fprintf(fff, "## empty space (available for object) ##\n\n"); continue; } /* Perform any translations */ /* Write New/Number/Name */ fprintf(fff, "N:%d:%s\n", i, k_name + k_ptr->name); /*get the color name*/ color_name = get_ext_color_name(k_ptr->d_attr); /* Write G: line */ fprintf(fff, "G:%d:%c:%s\n", i, k_ptr->d_char, color_name); /*don't do the rest for the pile symbol*/ if (i == 0) { /* Write G: line */ fprintf(fff, "\n\n\n"); continue; } /* Write I: line */ fprintf(fff, "I:%d:%d:%d:%d\n", i, k_ptr->tval, k_ptr->sval, k_ptr->pval); /* Write W: line */ fprintf(fff, "W:%d:%d:%d:%d\n", i, k_ptr->k_level, k_ptr->weight, k_ptr->cost); /* Write P: line */ fprintf(fff, "P:%d:%d:%d:d:%d:%d:%d:%d\n", i, k_ptr->ac, k_ptr->dd, k_ptr->ds, k_ptr->to_h, k_ptr->to_d, k_ptr->to_a); /* Write this A line */ fprintf(fff, "A:%d:%d:%d:%d:%d:%d:%d\n", i, k_ptr->locale[0], k_ptr->chance[0], k_ptr->locale[1], k_ptr->chance[1], k_ptr->locale[2], k_ptr->chance[2]); /* Get the flags, store flag text in a format easily parsed by a * database, but pretty much illegible to a person. */ dump_flags(fff, k_ptr->k_flags1, 1, i); dump_flags(fff, k_ptr->k_flags2, 2, i); dump_flags(fff, k_ptr->k_flags3, 3, i); dump_flags(fff, k_ptr->k_native, 4, i); /* Acquire the description */ desc = k_text + k_ptr->text; dlen = strlen(desc); if (dlen < 1) { /* Space between entries */ fprintf(fff, "\n\n\n"); continue; } /* Write Description */ for (j = 0; j < dlen;) { char buf[160], *t; /* Initialize */ t = buf; bc = 0; /* Build this line */ while (TRUE) { /* Insert this character, count it */ *t++ = desc[j++]; /* Oops. Line is too long. */ if (bc++ >= line_length) { /* Parse backwards until we find a space */ while (!my_isspace(desc[j-1]) && (bc-- > 40)) { j--; t--; } /* Time to end this line */ *t++ = '\0'; break; } /* All done */ if (j >= dlen) { /* Time to end this line */ *t++ = '\0'; break; } } /* Done with this line; write it */ fprintf(fff, "D-%d:%d:%s\n", counter, i, buf); counter++; } /* * Print out empty lines, so all objects have * an equal number of lines * makes parsing and combining the description easier */ for (; counter <+ 9; counter++) { fprintf(fff, "D-%d:%d\n", counter, i); } /* Space between entries */ fprintf(fff, "\n\n\n"); } /* Done */ fclose(fff); }
/* * Recursive file perusal. * * Return FALSE on "?", otherwise TRUE. * * This function could be made much more efficient with the use of "seek" * functionality, especially when moving backwards through a file, or * forwards through a file by less than a page at a time. XXX XXX XXX */ bool show_file(const char *name, const char *what, int line, int mode) { int i, k, n; struct keypress ch; /* Number of "real" lines passed by */ int next = 0; /* Number of "real" lines in the file */ int size; /* Backup value for "line" */ int back = 0; /* This screen has sub-screens */ bool menu = FALSE; /* Case sensitive search */ bool case_sensitive = FALSE; /* Current help file */ ang_file *fff = NULL; /* Find this string (if any) */ char *find = NULL; /* Jump to this tag */ const char *tag = NULL; /* Hold a string to find */ char finder[80] = ""; /* Hold a string to show */ char shower[80] = ""; /* Filename */ char filename[1024]; /* Describe this thing */ char caption[128] = ""; /* Path buffer */ char path[1024]; /* General buffer */ char buf[1024]; /* Lower case version of the buffer, for searching */ char lc_buf[1024]; /* Sub-menu information */ char hook[26][32]; int wid, hgt; /* TRUE if we are inside a RST block that should be skipped */ bool skip_lines = FALSE; /* Wipe the hooks */ for (i = 0; i < 26; i++) hook[i][0] = '\0'; /* Get size */ Term_get_size(&wid, &hgt); /* Copy the filename */ my_strcpy(filename, name, sizeof(filename)); n = strlen(filename); /* Extract the tag from the filename */ for (i = 0; i < n; i++) { if (filename[i] == '#') { filename[i] = '\0'; tag = filename + i + 1; break; } } /* Redirect the name */ name = filename; /* Hack XXX XXX XXX */ if (what) { my_strcpy(caption, what, sizeof(caption)); my_strcpy(path, name, sizeof(path)); fff = file_open(path, MODE_READ, FTYPE_TEXT); } /* Look in "help" */ if (!fff) { strnfmt(caption, sizeof(caption), "Help file '%s'", name); path_build(path, sizeof(path), ANGBAND_DIR_HELP, name); fff = file_open(path, MODE_READ, FTYPE_TEXT); } /* Look in "info" */ if (!fff) { strnfmt(caption, sizeof(caption), "Info file '%s'", name); path_build(path, sizeof(path), ANGBAND_DIR_INFO, name); fff = file_open(path, MODE_READ, FTYPE_TEXT); } /* Oops */ if (!fff) { /* Message */ msg("Cannot open '%s'.", name); event_signal(EVENT_MESSAGE_FLUSH); /* Oops */ return (TRUE); } /* Pre-Parse the file */ while (TRUE) { /* Read a line or stop */ if (!file_getl(fff, buf, sizeof(buf))) break; /* Skip lines if we are inside a RST directive*/ if(skip_lines){ if(contains_only_spaces(buf)) skip_lines=FALSE; continue; } /* Parse a very small subset of RST */ /* TODO: should be more flexible */ if (prefix(buf, ".. ")) { /* parse ".. menu:: [x] filename.txt" (with exact spacing)*/ if(prefix(buf+strlen(".. "), "menu:: [") && buf[strlen(".. menu:: [x")]==']') { /* This is a menu file */ menu = TRUE; /* Extract the menu item */ k = A2I(buf[strlen(".. menu:: [")]); /* Store the menu item (if valid) */ if ((k >= 0) && (k < 26)) my_strcpy(hook[k], buf + strlen(".. menu:: [x] "), sizeof(hook[0])); } /* parse ".. _some_hyperlink_target:" */ else if (buf[strlen(".. ")] == '_') { if (tag) { /* Remove the closing '>' of the tag */ buf[strlen(buf) - 1] = '\0'; /* Compare with the requested tag */ if (streq(buf + strlen(".. _"), tag)) { /* Remember the tagged line */ line = next; } } } /* Skip this and enter skip mode*/ skip_lines = TRUE; continue; } /* Count the "real" lines */ next++; } /* Save the number of "real" lines */ size = next; /* Display the file */ while (TRUE) { /* Clear screen */ Term_clear(); /* Restrict the visible range */ if (line > (size - (hgt - 4))) line = size - (hgt - 4); if (line < 0) line = 0; skip_lines = FALSE; /* Re-open the file if needed */ if (next > line) { /* Close it */ file_close(fff); /* Hack -- Re-Open the file */ fff = file_open(path, MODE_READ, FTYPE_TEXT); if (!fff) return (TRUE); /* File has been restarted */ next = 0; } /* Goto the selected line */ while (next < line) { /* Get a line */ if (!file_getl(fff, buf, sizeof(buf))) break; /* Skip lines if we are inside a RST directive*/ if(skip_lines){ if(contains_only_spaces(buf)) skip_lines=FALSE; continue; } /* Skip RST directives */ if (prefix(buf, ".. ")) { skip_lines=TRUE; continue; } /* Count the lines */ next++; } /* Dump the next lines of the file */ for (i = 0; i < hgt - 4; ) { /* Hack -- track the "first" line */ if (!i) line = next; /* Get a line of the file or stop */ if (!file_getl(fff, buf, sizeof(buf))) break; /* Skip lines if we are inside a RST directive*/ if(skip_lines){ if(contains_only_spaces(buf)) skip_lines=FALSE; continue; } /* Skip RST directives */ if (prefix(buf, ".. ")) { skip_lines=TRUE; continue; } /* skip | characters */ strskip(buf,'|'); /* escape backslashes */ strescape(buf,'\\'); /* Count the "real" lines */ next++; /* Make a copy of the current line for searching */ my_strcpy(lc_buf, buf, sizeof(lc_buf)); /* Make the line lower case */ if (!case_sensitive) string_lower(lc_buf); /* Hack -- keep searching */ if (find && !i && !strstr(lc_buf, find)) continue; /* Hack -- stop searching */ find = NULL; /* Dump the line */ Term_putstr(0, i+2, -1, COLOUR_WHITE, buf); /* Highlight "shower" */ if (shower[0]) { const char *str = lc_buf; /* Display matches */ while ((str = strstr(str, shower)) != NULL) { int len = strlen(shower); /* Display the match */ Term_putstr(str-lc_buf, i+2, len, COLOUR_YELLOW, &buf[str-lc_buf]); /* Advance */ str += len; } } /* Count the printed lines */ i++; } /* Hack -- failed search */ if (find) { bell("Search string not found!"); line = back; find = NULL; continue; } /* Show a general "title" */ prt(format("[%s, %s, Line %d-%d/%d]", buildid, caption, line, line + hgt - 4, size), 0, 0); /* Prompt -- menu screen */ if (menu) { /* Wait for it */ prt("[Press a Letter, or ESC to exit.]", hgt - 1, 0); } /* Prompt -- small files */ else if (size <= hgt - 4) { /* Wait for it */ prt("[Press ESC to exit.]", hgt - 1, 0); } /* Prompt -- large files */ else { /* Wait for it */ prt("[Press Space to advance, or ESC to exit.]", hgt - 1, 0); } /* Get a keypress */ ch = inkey(); /* Exit the help */ if (ch.code == '?') break; /* Toggle case sensitive on/off */ if (ch.code == '!') { case_sensitive = !case_sensitive; } /* Try showing */ if (ch.code == '&') { /* Get "shower" */ prt("Show: ", hgt - 1, 0); (void)askfor_aux(shower, sizeof(shower), NULL); /* Make the "shower" lowercase */ if (!case_sensitive) string_lower(shower); } /* Try finding */ if (ch.code == '/') { /* Get "finder" */ prt("Find: ", hgt - 1, 0); if (askfor_aux(finder, sizeof(finder), NULL)) { /* Find it */ find = finder; back = line; line = line + 1; /* Make the "finder" lowercase */ if (!case_sensitive) string_lower(finder); /* Show it */ my_strcpy(shower, finder, sizeof(shower)); } } /* Go to a specific line */ if (ch.code == '#') { char tmp[80] = "0"; prt("Goto Line: ", hgt - 1, 0); if (askfor_aux(tmp, sizeof(tmp), NULL)) line = atoi(tmp); } /* Go to a specific file */ if (ch.code == '%') { char ftmp[80] = "help.hlp"; prt("Goto File: ", hgt - 1, 0); if (askfor_aux(ftmp, sizeof(ftmp), NULL)) { if (!show_file(ftmp, NULL, 0, mode)) ch.code = ESCAPE; } } switch (ch.code) { /* up a line */ case ARROW_UP: case '8': line--; break; /* up a page */ case KC_PGUP: case '9': case '-': line -= (hgt - 4); break; /* home */ case KC_HOME: case '7': line = 0; break; /* down a line */ case ARROW_DOWN: case '2': case KC_ENTER: line++; break; /* down a page */ case KC_PGDOWN: case '3': case ' ': line += hgt - 4; break; /* end */ case KC_END: case '1': line = size; break; } /* Recurse on letters */ if (menu && isalpha((unsigned char)ch.code)) { /* Extract the requested menu item */ k = A2I(ch.code); /* Verify the menu item */ if ((k >= 0) && (k <= 25) && hook[k][0]) { /* Recurse on that file */ if (!show_file(hook[k], NULL, 0, mode)) ch.code = ESCAPE; } } /* Exit on escape */ if (ch.code == ESCAPE) break; } /* Close the file */ file_close(fff); /* Done */ return (ch.code != '?'); }
/* * Dump the ego-item information in a format easily parsed by a spreadsheet. * * Original function by -EB- (probably), revisions by -LM- & JG. */ void write_e_info_txt(void) { int i, j, bc; int dlen; char buf[1024]; int fd; FILE *fff = NULL; cptr desc; ego_item_type *e_ptr; /* We allow 75 characters on the line (plus 2) */ u16b line_length = 75; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_EDIT, "e_output.txt"); /* Check for existing file */ fd = fd_open(buf, O_RDONLY); /* Existing file */ if (fd >= 0) { char out_val[160]; /* Close the file */ fd_close(fd); /* Build query */ sprintf(out_val, "Replace existing file %s? ", buf); /* Ask */ if (get_check(out_val)) fd = -1; } /* Open the non-existing file */ if (fd < 0) fff = my_fopen(buf, "w"); /* No output file - fail */ if (!fff) return; /* Write a note */ fprintf(fff, "# File: e_info.txt (autogenerated)\n\n"); /* Read and print out all the objects */ for (i = 0; i < z_info->e_max; i++) { int counter = 1; /* Get the ego-item */ e_ptr = &e_info[i]; /* Ignore empty monsters */ if (!strlen((e_name + e_ptr->name))) { fprintf(fff, "## empty space (available for ego-item) ##\n\n"); continue; } /* Perform any translations */ /* Write New/Number/Name */ fprintf(fff, "N:%d:%s\n", i, e_name + e_ptr->name); /* Write X: line */ fprintf(fff, "X:%d:%d:%d\n", i, e_ptr->rating, e_ptr->xtra); /* Write C: line */ fprintf(fff, "C:%d:%d:%d:%d:%d\n", i, e_ptr->max_to_h, e_ptr->max_to_d, e_ptr->max_to_a, e_ptr->max_pval); /* Write W: line */ fprintf(fff, "W:%d:%d:%d:0:%d\n", i, e_ptr->level, e_ptr->rarity, e_ptr->cost); /* Write the T lines */ fprintf(fff, "T:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d\n", i, e_ptr->tval[0], e_ptr->min_sval[0], e_ptr->max_sval[0], e_ptr->tval[1], e_ptr->min_sval[1], e_ptr->max_sval[1], e_ptr->tval[2], e_ptr->min_sval[2], e_ptr->max_sval[2]); /* Get the flags, store flag text in a format easily parsed by a * database, but pretty much illegible to a person. */ dump_flags(fff, e_ptr->flags1, 1, i); dump_flags(fff, e_ptr->flags2, 2, i); dump_flags(fff, e_ptr->flags3, 3, i); dump_flags(fff, e_ptr->e_native, 4, i); /* Acquire the description */ desc = e_text + e_ptr->text; dlen = strlen(desc); if (dlen < 1) { /* Space between entries */ fprintf(fff, "\n\n\n"); continue; } /* Write Description */ for (j = 0; j < dlen;) { char buf[160], *t; /* Initialize */ t = buf; bc = 0; /* Build this line */ while (TRUE) { /* Insert this character, count it */ *t++ = desc[j++]; /* Oops. Line is too long. */ if (bc++ >= line_length) { /* Parse backwards until we find a space */ while (!my_isspace(desc[j-1]) && (bc-- > 40)) { j--; t--; } /* Time to end this line */ *t++ = '\0'; break; } /* All done */ if (j >= dlen) { /* Time to end this line */ *t++ = '\0'; break; } } /* Done with this line; write it */ fprintf(fff, "D-%d:%d:%s\n", counter, i, buf); counter++; } /* * Print out empty lines, so all objects have * an equal number of lines * makes parsing and combining the description easier */ for (; counter <+ 6; counter++) { fprintf(fff, "D-%d:%d\n", counter, i); } /* Space between entries */ fprintf(fff, "\n\n\n"); } /* Done */ fclose(fff); }
/* * Save a "bones" file for a dead character * * Should probably attempt some form of locking... */ void make_bones(void) { #if 0 /* DGDGDGDG */ FILE *fp; int i; char str[1024]; /* Ignore wizards and borgs */ if (!(noscore & 0x00FF)) { /* Ignore people who die in town */ if (dun_level) { int level; char tmp[128]; /* Slightly more tenacious saving routine. */ for (i = 0; i < 5; i++) { /* Ghost hovers near level of death. */ if (i == 0) level = dun_level; else level = dun_level + 5 - damroll(2, 4); if (level < 1) level = randint(4); /* XXX XXX XXX "Bones" name */ sprintf(tmp, "bone%03d.%03d", dungeon_type, level); /* Build the filename */ path_build(str, 1024, ANGBAND_DIR_BONE, tmp); /* Grab permission */ safe_setuid_grab(); /* Attempt to open the bones file */ fp = my_fopen(str, "r"); /* Drop permission */ safe_setuid_drop(); /* Close it right away */ if (fp) my_fclose(fp); /* Do not over-write a previous ghost */ if (fp) continue; /* If no file by that name exists, we can make a new one. */ if (!(fp)) break; } /* File type is "TEXT" */ FILE_TYPE(FILE_TYPE_TEXT); /* Grab permission */ safe_setuid_grab(); /* Try to write a new "Bones File" */ fp = my_fopen(str, "w"); /* Drop permission */ safe_setuid_drop(); /* Not allowed to write it? Weird. */ if (!fp) return; /* Save the info */ fprintf(fp, "%s\n", player_name); fprintf(fp, "%d\n", p_ptr->mhp); fprintf(fp, "%d\n", p_ptr->prace); fprintf(fp, "%d\n", p_ptr->pclass); /* Close and save the Bones file */ my_fclose(fp); } } #endif }
/* * Use the monster racial information to a format easily parsed by a spreadsheet. * * Original function by -EB- (probably), revisions by -LM- & JG. */ void write_r_info_txt(void) { int i, j, bc; int dlen; char buf[1024]; int fd; FILE *fff = NULL; cptr desc; monster_race *r_ptr; /* We allow 75 characters on the line (plus 2) */ u16b line_length = 75; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_EDIT, "r_output.txt"); /* Check for existing file */ fd = fd_open(buf, O_RDONLY); /* Existing file */ if (fd >= 0) { char out_val[160]; /* Close the file */ fd_close(fd); /* Build query */ sprintf(out_val, "Replace existing file %s? ", buf); /* Ask */ if (get_check(out_val)) fd = -1; } /* Open the non-existing file */ if (fd < 0) fff = my_fopen(buf, "w"); /* No output file - fail */ if (!fff) return; /* Write a note */ fprintf(fff, "# File: r_info.txt (autogenerated)\n\n"); /* Write a note */ fprintf(fff, "##### The Player #####\n\n"); /* Read and print out all the monsters */ for (i = 0; i < z_info->r_max; i++) { char what_char; cptr color_name; int counter = 1; /* Get the monster */ r_ptr = &r_info[i]; /* Ignore empty monsters */ if (!strlen(r_name + r_ptr->name)) { fprintf(fff, "## empty space (available for monsters) ##\n\n"); continue; } /* Ignore useless monsters */ if (i && !r_ptr->speed) { fprintf(fff, "## empty space (available for monsters) ##\n\n"); continue; } /* Perform any translations */ /* Write New/Number/Name */ fprintf(fff, "N:%d:%d:%s\n", i, i, r_name + r_ptr->name); /*get the color name*/ color_name = get_ext_color_name(r_ptr->d_attr); /* Write G: line */ if (r_ptr->rarity) fprintf(fff, "G:%d:%c:%s \n", i, r_ptr->d_char, color_name); /*don't do rest for player*/ if (i == 0) { /* Write a note */ fprintf(fff, "\n\n ##### The Monsters #####\n\n"); continue; } /* Write I: line */ fprintf(fff, "I:%d:%d:%dd%d:%d:%d:%d\n", i, r_ptr->speed, r_ptr->hdice, r_ptr->hside, r_ptr->aaf, r_ptr->ac, r_ptr->sleep); /* Write W: line */ fprintf(fff, "W:%d:%d::%d:%d:%ld\n", i, r_ptr->level, r_ptr->rarity, r_ptr->mana, r_ptr->mexp); /* Write blows */ for(j = 0; j < 4; j++) { /* Write this blow */ fprintf(fff, format("B-%d:%d:%d:%d:%dd%d\n", j, i, r_ptr->blow[j].method, r_ptr->blow[j].effect, r_ptr->blow[j].d_dice, r_ptr->blow[j].d_side)); } what_char = 'F'; /* Get the flags, store flag text in a format easily parsed by a * database, but pretty much illegible to a person. */ dump_flags(fff, r_ptr->flags1, 1, i); dump_flags(fff, r_ptr->flags2, 2, i); dump_flags(fff, r_ptr->flags3, 3, i); dump_flags(fff, r_ptr->flags4, 4, i); dump_flags(fff, r_ptr->flags5, 5, i); dump_flags(fff, r_ptr->flags6, 6, i); /* Write the terrain native flag. */ what_char = 'T'; dump_flags(fff, r_ptr->r_native, 8, i); fprintf(fff, "S:%d:%d:%d\n", i, r_ptr->freq_ranged, r_ptr->spell_power); /*now the summon flag*/ what_char = 'S'; dump_flags(fff, r_ptr->flags7, 7, i); /* Acquire the description */ desc = r_text + r_ptr->text; dlen = strlen(desc); /* Write Description */ for (j = 0; j < dlen;) { char buf[160], *t; /* Initialize */ t = buf; bc = 0; /* Build this line */ while (TRUE) { /* Insert this character, count it */ *t++ = desc[j++]; /* Oops. Line is too long. */ if (bc++ >= line_length) { /* Parse backwards until we find a space */ while (!my_isspace(desc[j-1]) && (bc-- > 40)) { j--; t--; } /* Time to end this line */ *t++ = '\0'; break; } /* All done */ if (j >= dlen) { /* Time to end this line */ *t++ = '\0'; break; } } /* Done with this line; write it */ fprintf(fff, "D-%d:%d:%s\n", counter, i, buf); counter++; } /* * Print out empty lines, so all monsters have * an equal number of lines * makes parsing and combining the description easier */ for (; counter <+ 12; counter++) { fprintf(fff, "D-%d:%d\n", counter, i); } /* Space between entries */ fprintf(fff, "\n\n\n"); } /* Done */ fclose(fff); }
/* * Create a spoiler file for artifacts */ static void spoil_artifact(const char *fname) { int i, j; object_type *i_ptr; object_type object_type_body; char buf[1024]; /* Build the filename */ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); fh = file_open(buf, MODE_WRITE, FTYPE_TEXT); /* Oops */ if (!fh) { msg("Cannot create spoiler file."); return; } /* Dump to the spoiler file */ text_out_hook = text_out_to_file; text_out_file = fh; /* Dump the header */ spoiler_underline(format("Artifact Spoilers for %s", buildid), '='); /* List the artifacts by tval */ for (i = 0; group_artifact[i].tval; i++) { /* Write out the group title */ if (group_artifact[i].name) { spoiler_blanklines(2); spoiler_underline(group_artifact[i].name, '='); spoiler_blanklines(1); } /* Now search through all of the artifacts */ for (j = 1; j < z_info->a_max; ++j) { artifact_type *a_ptr = &a_info[j]; char buf[80]; /* We only want objects in the current group */ if (a_ptr->tval != group_artifact[i].tval) continue; /* Get local object */ i_ptr = &object_type_body; /* Wipe the object */ object_wipe(i_ptr); /* Attempt to "forge" the artifact */ if (!make_fake_artifact(i_ptr, a_ptr)) continue; /* Grab artifact name */ object_desc(buf, sizeof(buf), i_ptr, ODESC_PREFIX | ODESC_COMBAT | ODESC_EXTRA | ODESC_SPOIL); /* Print name and underline */ spoiler_underline(buf, '-'); /* Write out the artifact description to the spoiler file */ object_info_spoil(fh, i_ptr, 80); /* * Determine the minimum and maximum depths an * artifact can appear, its rarity, its weight, and * its power rating. */ text_out("\nMin Level %u, Max Level %u, Generation chance %u, Power %d, %d.%d lbs\n", a_ptr->alloc_min, a_ptr->alloc_max, a_ptr->alloc_prob, object_power(i_ptr, FALSE, NULL, TRUE), (a_ptr->weight / 10), (a_ptr->weight % 10)); /* Terminate the entry */ spoiler_blanklines(2); } } /* Check for errors */ if (!file_close(fh)) { msg("Cannot close spoiler file."); return; } /* Message */ msg("Successfully created a spoiler file."); }
/* * Use the monster racial information to a format easily parsed by a spreadsheet. * * Original function by -EB- (probably), revisions by -LM- & JG. * Note: This function needs some updating as it is missing some fields. */ void write_f_info_txt(void) { int i, j, bc, x; int dlen; char buf[1024]; int fd; FILE *fff = NULL; cptr desc; feature_type *f_ptr; /* We allow 75 characters on the line (plus 2) */ u16b line_length = 75; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_EDIT, "f_output.txt"); /* Check for existing file */ fd = fd_open(buf, O_RDONLY); /* Existing file */ if (fd >= 0) { char out_val[160]; /* Close the file */ fd_close(fd); /* Build query */ sprintf(out_val, "Replace existing file %s? ", buf); /* Ask */ if (get_check(out_val)) fd = -1; } /* Open the non-existing file */ if (fd < 0) fff = my_fopen(buf, "w"); /* No output file - fail */ if (!fff) return; /* Write a note */ fprintf(fff, "# File: f_info.txt (autogenerated)\n\n"); /* Read and print out all the features */ for (i = 0; i < z_info->f_max; i++) { cptr color_name; int counter = 1; desc = NULL; /* Get the monster */ f_ptr = &f_info[i]; /* Ignore empty monsters */ if (!strlen(f_name + f_ptr->name)) { fprintf(fff, "## empty space (available for terrain) ##\n\n"); continue; } /* Perform any translations */ /* Write New/Number/Name */ fprintf(fff, "N:%d:%d:%s\n", i, i, f_name + f_ptr->name); /* Write Mimic */ if (f_ptr->f_mimic > 0) { /*hack, switch to a new f_ptr- t outpit out the name*/ f_ptr = &f_info[f_info[i].f_mimic]; fprintf(fff, "M:%d:%s\n", i, f_name + f_ptr->name); /* Switch Back*/ f_ptr = &f_info[i]; } /* Write Edge */ if (f_ptr->f_edge > 0) { /*hack, switch to a new f_ptr- t outpit out the name*/ f_ptr = &f_info[f_info[i].f_edge]; fprintf(fff, "E:%d:%s\n", i, f_name + f_ptr->name); /* Switch Back*/ f_ptr = &f_info[i]; } /*get the color name*/ color_name = get_ext_color_name(f_ptr->d_attr); /* Write G: line */ fprintf(fff, "G:%d:%c:%s\n",i, f_ptr->d_char, color_name); if (f_ptr->f_edge > 0) { /*hack, switch to a new f_ptr- t outpit out the name*/ f_ptr = &f_info[f_info[i].f_edge]; desc = (f_name + f_ptr->name); /* Switch Back*/ f_ptr = &f_info[i]; } else desc = NULL; /* Write W: line */ fprintf(fff, "W:%d:%d:%d:%d:%d:\n", i, f_ptr->f_level, f_ptr->f_rarity, f_ptr->priority, f_ptr->f_power); /* Write C: line */ fprintf(fff, "C:%d:%d:%d:%d:%d:%d:%d:\n", i, f_ptr->dam_non_native, f_ptr->native_energy_move, f_ptr->non_native_energy_move, f_ptr->native_to_hit_adj, f_ptr->non_native_to_hit_adj, f_ptr->f_stealth_adj); /* Write X: line */ fprintf(fff, "X:%d:%d:%d:%d:%d:%d:%d:%d:\n", i, f_ptr->f_level, f_ptr->f_rarity, f_ptr->f_power, f_ptr->x_damage, f_ptr->x_gf_type, f_ptr->x_timeout_set, f_ptr->x_timeout_rand); /* Get the flags, store flag text in a format easily parsed by a * database, but pretty much illegible to a person. */ dump_flags(fff, f_ptr->f_flags1, 1, i); dump_flags(fff, f_ptr->f_flags2, 2, i); dump_flags(fff, f_ptr->f_flags3, 3, i); /*Drop the default*/ fprintf(fff, "DEFAULT:%d:%d\n", i, f_ptr->defaults); /* Find the next empty state slot (if any) */ for (x = 0; x < MAX_FEAT_STATES; x++) { if (f_ptr->state[x].fs_action != FS_FLAGS_END) { char action_desc[80]; get_feature_name(action_desc, sizeof(action_desc), f_ptr->state[x].fs_action); if (f_ptr->state[x].fs_result > 0) { /*Get the name of terrain switching to*/ f_ptr = &f_info[f_ptr->state[x].fs_result]; desc = (f_name + f_ptr->name); /* Switch Back*/ f_ptr = &f_info[i]; } else desc = NULL; /*drop the "K" line*/ fprintf(fff, "K%d:%d:%s:%s:%d\n", i, x, action_desc, desc, f_ptr->state[x].fs_power); } } /* Acquire the description */ desc = f_text + f_ptr->f_text; dlen = strlen(desc); /* Write Description */ for (j = 0; j < dlen;) { char buf[160], *t; /* Initialize */ t = buf; bc = 0; /* Build this line */ while (TRUE) { /* Insert this character, count it */ *t++ = desc[j++]; /* Oops. Line is too long. */ if (bc++ >= line_length) { /* Parse backwards until we find a space */ while (!my_isspace(desc[j-1]) && (bc-- > 40)) { j--; t--; } /* Time to end this line */ *t++ = '\0'; break; } /* All done */ if (j >= dlen) { /* Time to end this line */ *t++ = '\0'; break; } } /* Done with this line; write it */ fprintf(fff, "D-%d:%d:%s\n", counter, i, buf); counter++; } /* * Print out empty lines, so all monsters have * an equal number of lines * makes parsing and combining the description easier */ for (; counter <+ 3; counter++) { fprintf(fff, "D-%d:%d\n", counter, i); } /* Space between entries */ fprintf(fff, "\n\n\n"); } /* Done */ fclose(fff); }
/* * Create a spoiler file for monsters (-SHAWN-) */ static void spoil_mon_info(const char *fname) { char buf[1024]; int i, n; u16b *who; int count = 0; /* Open the file */ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, fname); fh = file_open(buf, MODE_WRITE, FTYPE_TEXT); /* Oops */ if (!fh) { msg("Cannot create spoiler file."); return; } /* Dump to the spoiler file */ text_out_hook = text_out_to_file; text_out_file = fh; /* Dump the header */ text_out("Monster Spoilers for %s\n", buildid); text_out("------------------------------------------\n\n"); /* Allocate the "who" array */ who = C_ZNEW(z_info->r_max, u16b); /* Scan the monsters */ for (i = 1; i < z_info->r_max; i++) { monster_race *r_ptr = &r_info[i]; /* Use that monster */ if (r_ptr->name) who[count++] = (u16b)i; } sort(who, count, sizeof(*who), cmp_monsters); /* * List all monsters in order (except the ghost). */ for (n = 0; n < count; n++) { int r_idx = who[n]; monster_race *r_ptr = &r_info[r_idx]; /* Prefix */ if (rf_has(r_ptr->flags, RF_QUESTOR)) { text_out("[Q] "); } else if (rf_has(r_ptr->flags, RF_UNIQUE)) { text_out("[U] "); } else { text_out("The "); } /* Name */ text_out("%s (", r_ptr->name); /* ---)--- */ /* Color */ text_out(attr_to_text(r_ptr->d_attr)); /* Symbol --(-- */ text_out(" '%c')\n", r_ptr->d_char); /* Indent */ text_out("=== "); /* Number */ text_out("Num:%d ", r_idx); /* Level */ text_out("Lev:%d ", r_ptr->level); /* Rarity */ text_out("Rar:%d ", r_ptr->rarity); /* Speed */ if (r_ptr->speed >= 110) { text_out("Spd:+%d ", (r_ptr->speed - 110)); } else { text_out("Spd:-%d ", (110 - r_ptr->speed)); } /* Hitpoints */ text_out("Hp:%d ", r_ptr->avg_hp); /* Armor Class */ text_out("Ac:%d ", r_ptr->ac); /* Experience */ text_out("Exp:%ld\n", (long)(r_ptr->mexp)); /* Describe */ describe_monster(r_idx, TRUE); /* Terminate the entry */ text_out("\n"); } /* Free the "who" array */ FREE(who); /* Check for errors */ if (!file_close(fh)) { msg("Cannot close spoiler file."); return; } msg("Successfully created a spoiler file."); }
/* * Dump the object information a format easily parsed by a spreadsheet. * * Original function by -EB- (probably), revisions by -LM- & JG. */ void write_a_info_txt(void) { int i, j, bc; int dlen; char buf[1024]; int fd; FILE *fff = NULL; cptr desc; artifact_type *a_ptr; /* We allow 75 characters on the line (plus 2) */ u16b line_length = 75; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_EDIT, "a_output.txt"); /* Check for existing file */ fd = fd_open(buf, O_RDONLY); /* Existing file */ if (fd >= 0) { char out_val[160]; /* Close the file */ fd_close(fd); /* Build query */ sprintf(out_val, "Replace existing file %s? ", buf); /* Ask */ if (get_check(out_val)) fd = -1; } /* Open the non-existing file */ if (fd < 0) fff = my_fopen(buf, "w"); /* No output file - fail */ if (!fff) return; /* Write a note */ fprintf(fff, "# File: a_info.txt (autogenerated)\n\n"); /* Read and print out all the objects */ for (i = 0; i < z_info->art_norm_max; i++) { int counter = 1; char o_name[80]; object_type *i_ptr; object_type object_type_body; /* Get local object */ i_ptr = &object_type_body; /* Get the object */ a_ptr = &a_info[i]; /* Ignore unused objects */ if (!strlen(a_ptr->name)) { fprintf(fff, "## empty space (available for artifact) ##\n\n"); continue; } /* Perform any translations */ /* Write New/Number/Name */ fprintf(fff, "N:%d:%s\n", i, a_ptr->name); /* Write the complete name of the artifact*/ make_fake_artifact(i_ptr, i); /*identify it*/ /* Identify it */ object_aware(i_ptr); object_known(i_ptr); i_ptr->ident |= (IDENT_MENTAL); /* Get a description to dump */ object_desc(o_name, sizeof(o_name), i_ptr, TRUE, 0); /*dump the long name*/ fprintf(fff, "desc:%d: # %s\n", i, o_name); /* Write I: line */ fprintf(fff, "I:%d:%d:%d:%d\n", i, a_ptr->tval, a_ptr->sval, a_ptr->pval); /* Write W: line */ fprintf(fff, "W:%d:%d:%d:%d:%d\n", i, a_ptr->a_level, a_ptr->a_rarity, a_ptr->weight, a_ptr->cost); /* Write P: line */ fprintf(fff, "P:%d:%d:%d:d:%d:%d:%d:%d\n", i, a_ptr->ac, a_ptr->dd, a_ptr->ds, a_ptr->to_h, a_ptr->to_d, a_ptr->to_a); /* Get the flags, store flag text in a format easily parsed by a * database, but pretty much illegible to a person. */ dump_flags(fff, a_ptr->a_flags1, 1, i); dump_flags(fff, a_ptr->a_flags2, 2, i); dump_flags(fff, a_ptr->a_flags3, 3, i); dump_flags(fff, a_ptr->a_native, 4, i); /* Write the A line */ fprintf(fff, "A:%d:%d:%d:%d\n", i, a_ptr->activation, a_ptr->time, a_ptr->randtime); /* Acquire the description */ desc = a_text + a_ptr->text; dlen = strlen(desc); if (dlen < 1) { /* Space between entries */ fprintf(fff, "\n\n\n"); continue; } /* Write Description */ for (j = 0; j < dlen;) { char buf[160], *t; /* Initialize */ t = buf; bc = 0; /* Build this line */ while (TRUE) { /* Insert this character, count it */ *t++ = desc[j++]; /* Oops. Line is too long. */ if (bc++ >= line_length) { /* Parse backwards until we find a space */ while (!my_isspace(desc[j-1]) && (bc-- > 40)) { j--; t--; } /* Time to end this line */ *t++ = '\0'; break; } /* All done */ if (j >= dlen) { /* Time to end this line */ *t++ = '\0'; break; } } /* Done with this line; write it */ fprintf(fff, "D-%d:%d:%s\n", counter, i, buf); counter++; } /* * Print out empty lines, so all objects have * an equal number of lines * makes parsing and combining the description easier */ for (; counter <+ 12; counter++) { fprintf(fff, "D-%d:%d\n", counter, i); } /* Space between entries */ fprintf(fff, "\n\n\n"); } /* Done */ fclose(fff); }
void file_dirscan( char * dir, scanback func, void * closure ) { PROFILE_ENTER( FILE_DIRSCAN ); file_info_t * d = 0; d = file_query( dir ); if ( !d || !d->is_dir ) { PROFILE_EXIT( FILE_DIRSCAN ); return; } if ( ! d->files ) { LIST* files = L0; PATHNAME f; DIR *dd; STRUCT_DIRENT *dirent; string filename[1]; /* First enter directory itself */ memset( (char *)&f, '\0', sizeof( f ) ); f.f_dir.ptr = dir; f.f_dir.len = strlen(dir); dir = *dir ? dir : "."; /* Now enter contents of directory. */ if ( !( dd = opendir( dir ) ) ) { PROFILE_EXIT( FILE_DIRSCAN ); return; } if ( DEBUG_BINDSCAN ) printf( "scan directory %s\n", dir ); string_new( filename ); while ( ( dirent = readdir( dd ) ) ) { # ifdef old_sinix /* Broken structure definition on sinix. */ f.f_base.ptr = dirent->d_name - 2; # else f.f_base.ptr = dirent->d_name; # endif f.f_base.len = strlen( f.f_base.ptr ); string_truncate( filename, 0 ); path_build( &f, filename, 0 ); files = list_new( files, newstr(filename->value) ); file_query( filename->value ); } string_free( filename ); closedir( dd ); d->files = files; } /* Special case / : enter it */ { unsigned long len = strlen(d->name); if ( ( len == 1 ) && ( d->name[0] == '/' ) ) (*func)( closure, d->name, 1 /* stat()'ed */, d->time ); } /* Now enter contents of directory */ if ( d->files ) { LIST * files = d->files; while ( files ) { file_info_t * ff = file_info( files->string ); (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time ); files = list_next( files ); } } PROFILE_EXIT( FILE_DIRSCAN ); }
/** * Evaluate the whole monster list and write a new one. power and scaled_power * are always adjusted, level, rarity and mexp only if requested. */ errr eval_monster_power(struct monster_race *racelist) { int i, j, iteration; byte lvl; monster_race *r_ptr = NULL; ang_file *mon_fp; char buf[1024]; bool dump = FALSE; /* Allocate arrays */ power = mem_zalloc(z_info->r_max * sizeof(long)); scaled_power = mem_zalloc(z_info->r_max * sizeof(long)); final_hp = mem_zalloc(z_info->r_max * sizeof(long)); final_melee_dam = mem_zalloc(z_info->r_max * sizeof(long)); final_spell_dam = mem_zalloc(z_info->r_max * sizeof(long)); highest_threat = mem_zalloc(z_info->r_max * sizeof(int)); for (iteration = 0; iteration < 3; iteration ++) { long hp, av_hp, dam, av_dam; long *tot_hp = mem_zalloc(z_info->max_depth * sizeof(long)); long *tot_dam = mem_zalloc(z_info->max_depth * sizeof(long)); long *mon_count = mem_zalloc(z_info->max_depth * sizeof(long)); /* Reset the sum of all monster power values */ tot_mon_power = 0; /* Go through r_info and evaluate power ratings & flows. */ for (i = 0; i < z_info->r_max; i++) { /* Point at the "info" */ r_ptr = &racelist[i]; /* Set the current level */ lvl = r_ptr->level; /* Maximum damage this monster can do in 10 game turns */ dam = eval_max_dam(r_ptr, i); /* Adjust hit points based on resistances */ hp = eval_hp_adjust(r_ptr); /* Hack -- set exp */ if (lvl == 0) r_ptr->mexp = 0L; else { /* Compute depths of non-unique monsters */ if (!rf_has(r_ptr->flags, RF_UNIQUE)) { long mexp = (hp * dam) / 25; long threat = highest_threat[i]; /* Compute level algorithmically */ for (j = 1; (mexp > j + 4) || (threat > j + 5); mexp -= j * j, threat -= (j + 4), j++); /* Set level */ lvl = MIN(( j > 250 ? 90 + (j - 250) / 20 : /* Level 90+ */ (j > 130 ? 70 + (j - 130) / 6 : /* Level 70+ */ (j > 40 ? 40 + (j - 40) / 3 : /* Level 40+ */ j))), 99); /* Set level */ if (arg_rebalance) r_ptr->level = lvl; } if (arg_rebalance) { /* Hack -- for Ungoliant */ if (hp > 10000) r_ptr->mexp = (hp / 25) * (dam / lvl); else r_ptr->mexp = (hp * dam) / (lvl * 25); /* Round to 2 significant figures */ if (r_ptr->mexp > 100) { if (r_ptr->mexp < 1000) { r_ptr->mexp = (r_ptr->mexp + 5) / 10; r_ptr->mexp *= 10; } else if (r_ptr->mexp < 10000) { r_ptr->mexp = (r_ptr->mexp + 50) / 100; r_ptr->mexp *= 100; } else if (r_ptr->mexp < 100000) { r_ptr->mexp = (r_ptr->mexp + 500) / 1000; r_ptr->mexp *= 1000; } else if (r_ptr->mexp < 1000000) { r_ptr->mexp = (r_ptr->mexp + 5000) / 10000; r_ptr->mexp *= 10000; } else if (r_ptr->mexp < 10000000) { r_ptr->mexp = (r_ptr->mexp + 50000) / 100000; r_ptr->mexp *= 100000; } } } } /* If we're rebalancing, this is a nop, if not, we restore the * orig value */ lvl = r_ptr->level; if ((lvl) && (r_ptr->mexp < 1L)) r_ptr->mexp = 1L; /* * Hack - We have to use an adjustment factor to prevent overflow. * Try to scale evenly across all levels instead of scaling by level */ hp /= 2; if(hp < 1) hp = 1; final_hp[i] = hp; /* Define the power rating */ power[i] = hp * dam; /* Adjust for group monsters, using somewhat arbitrary * multipliers for now */ if (!rf_has(r_ptr->flags, RF_UNIQUE)) { if (r_ptr->friends) power[i] *= 3; } /* Adjust for escorts */ if (r_ptr->friends_base) power[i] *= 2; /* Adjust for multiplying monsters. This is modified by the speed, * as fast multipliers are much worse than slow ones. We also * adjust for ability to bypass walls or doors. */ if (rf_has(r_ptr->flags, RF_MULTIPLY)) { int adj_power; if (flags_test(r_ptr->flags, RF_SIZE, RF_KILL_WALL, RF_PASS_WALL, FLAG_END)) adj_power = power[i] * adj_energy(r_ptr); else if (flags_test(r_ptr->flags, RF_SIZE, RF_OPEN_DOOR, RF_BASH_DOOR, FLAG_END)) adj_power = power[i] * adj_energy(r_ptr) * 3 / 2; else adj_power = power[i] * adj_energy(r_ptr) / 2; power[i] = MAX(power[i], adj_power); } /* Update the running totals - these will be used as divisors later * Total HP / dam / count for everything up to the current level */ for (j = lvl; j < (lvl == 0 ? lvl + 1: z_info->max_depth); j++) { int count = 10; /* Uniques don't count towards monster power on the level. */ if (rf_has(r_ptr->flags, RF_UNIQUE)) continue; /* Specifically placed monsters don't count towards monster * power on the level. */ if (!(r_ptr->rarity)) continue; /* Hack -- provide adjustment factor to prevent overflow */ if ((j == 90) && (r_ptr->level < 90)) { hp /= 10; dam /= 10; } if ((j == 65) && (r_ptr->level < 65)) { hp /= 10; dam /= 10; } if ((j == 40) && (r_ptr->level < 40)) { hp /= 10; dam /= 10; } /* Hack - if it's a group monster or multiplying monster, add * several to the count so the averages don't get thrown off */ if (r_ptr->friends || r_ptr->friends_base) count = 15; if (rf_has(r_ptr->flags, RF_MULTIPLY)) { int adj_energy_amt; if (flags_test(r_ptr->flags, RF_SIZE, RF_KILL_WALL, RF_PASS_WALL, FLAG_END)) adj_energy_amt = adj_energy(r_ptr); else if (flags_test(r_ptr->flags, RF_SIZE, RF_OPEN_DOOR, RF_BASH_DOOR, FLAG_END)) adj_energy_amt = adj_energy(r_ptr) * 3 / 2; else adj_energy_amt = adj_energy(r_ptr) / 2; count = MAX(1, adj_energy_amt) * count; } /* Very rare monsters count less towards total monster power * on the level. */ if (r_ptr->rarity > count) { hp = hp * count / r_ptr->rarity; dam = dam * count / r_ptr->rarity; count = r_ptr->rarity; } tot_hp[j] += hp; tot_dam[j] += dam; mon_count[j] += count / r_ptr->rarity; } } /* Apply divisors now */ for (i = 0; i < z_info->r_max; i++) { int new_power; /* Point at the "info" */ r_ptr = &racelist[i]; /* Extract level */ lvl = r_ptr->level; /* Paranoia */ if (tot_hp[lvl] != 0 && tot_dam[lvl] != 0) { scaled_power[i] = power[i]; /* Divide by av HP and av damage for all in-level monsters */ /* Note we have factored in the above 'adjustment factor' */ av_hp = tot_hp[lvl] * 10 / mon_count[lvl]; av_dam = tot_dam[lvl] * 10 / mon_count[lvl]; /* Justifiable paranoia - avoid divide by zero errors */ if (av_hp > 0) scaled_power[i] = scaled_power[i] / av_hp; if (av_dam > 0) scaled_power[i] = scaled_power[i] / av_dam; /* Never less than 1 */ if (power[i] < 1) power[i] = 1; /* Set powers */ if (arg_rebalance) { r_ptr->power = power[i]; r_ptr->scaled_power = scaled_power[i]; } /* Get power */ new_power = power[i]; /* Compute rarity algorithmically */ for (j = 1; new_power > j; new_power -= j * j, j++); /* Set rarity */ if (arg_rebalance) r_ptr->rarity = j; } } mem_free(mon_count); mem_free(tot_dam); mem_free(tot_hp); } /* Determine total monster power */ for (i = 0; i < z_info->r_max; i++) tot_mon_power += r_info[i].scaled_power; if (dump) { /* Dump the power details */ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "mon_power.txt"); mon_fp = file_open(buf, MODE_WRITE, FTYPE_TEXT); file_putf(mon_fp, "ridx|level|rarity|d_char|name|pwr|scaled|melee|spell|hp\n"); for (i = 0; i < z_info->r_max; i++) { char mbstr[MB_LEN_MAX + 1] = { 0 }; r_ptr = &r_info[i]; /* Don't print anything for nonexistent monsters */ if (!r_ptr->name) continue; wctomb(mbstr, r_ptr->d_char); file_putf(mon_fp, "%d|%d|%d|%s|%s|%d|%d|%d|%d|%d\n", r_ptr->ridx, r_ptr->level, r_ptr->rarity, mbstr, r_ptr->name, power[i], scaled_power[i], final_melee_dam[i], final_spell_dam[i], final_hp[i]); } file_close(mon_fp); } /* Write to the user directory */ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "new_monster.txt"); if (text_lines_to_file(buf, write_monster_entries)) { msg("Failed to create file %s.new", buf); return -1; } /* Free power arrays */ mem_free(highest_threat); mem_free(final_spell_dam); mem_free(final_melee_dam); mem_free(final_hp); mem_free(scaled_power); mem_free(power); /* Success */ return 0; }
/* * Hack -- load a screen dump from a file * * ToDo: Add support for loading/saving screen-dumps with graphics * and pseudo-graphics. Allow the player to specify the filename * of the dump. */ void do_cmd_load_screen(void) { int i, y, x; byte a = 0; char c = ' '; bool okay = TRUE; ang_file *fp; char buf[1024]; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt"); fp = file_open(buf, MODE_READ, -1); if (!fp) return; /* Save screen */ screen_save(); /* Clear the screen */ Term_clear(); /* Load the screen */ for (y = 0; okay && (y < 24); y++) { /* Get a line of data */ if (!file_getl(fp, buf, sizeof(buf))) okay = FALSE; /* Show each row */ for (x = 0; x < 79; x++) { /* Put the attr/char */ Term_draw(x, y, TERM_WHITE, buf[x]); } } /* Get the blank line */ if (!file_getl(fp, buf, sizeof(buf))) okay = FALSE; /* Dump the screen */ for (y = 0; okay && (y < 24); y++) { /* Get a line of data */ if (!file_getl(fp, buf, sizeof(buf))) okay = FALSE; /* Dump each row */ for (x = 0; x < 79; x++) { /* Get the attr/char */ (void)(Term_what(x, y, &a, &c)); /* Look up the attr */ for (i = 0; i < BASIC_COLORS; i++) { /* Use attr matches */ if (hack[i] == buf[x]) a = i; } /* Put the attr/char */ Term_draw(x, y, a, c); } } /* Close it */ file_close(fp); /* Message */ msg("Screen dump loaded."); message_flush(); /* Load screen */ screen_load(); }
static void describe_monster_desc(const monster_race *r_ptr) { char buf[2048]; char *s, *t; int match = (r_ptr->flags1 & (RF1_FEMALE)) ? 2 : 1; int state = 0; #ifdef DELAY_LOAD_R_TEXT int fd; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_DATA, "monster.raw"); /* Open the "raw" file */ fd = fd_open(buf, O_RDONLY); /* Use file */ if (fd >= 0) { long pos; /* Starting position */ pos = r_ptr->text; /* Additional offsets */ pos += r_head->head_size; pos += r_head->info_size; pos += r_head->name_size; #if 0 /* Maximal length */ len = r_head->text_size - r_ptr->text; /* Actual length */ for (i = r_idx+1; i < z_info->r_max; i++) { /* Actual length */ if (r_info[i].text > r_ptr->text) { /* Extract length */ len = r_info[i].text - r_ptr->text; /* Done */ break; } } /* Maximal length */ if (len > 2048) len = 2048; #endif /* Seek */ fd_seek(fd, pos); /* Read a chunk of data */ fd_read(fd, buf, sizeof(buf)); /* Close it */ fd_close(fd); } #else /* Simple method */ my_strcpy(buf, r_text + r_ptr->text, sizeof(buf)); #endif /* Remove gender sensitivity */ for (t = s = buf; *s; s++) { if (*s == '|') { state++; if (state == 3) state = 0; } else if (!state || (state == match)) { *t++ = *s; } } /* Terminate buffer */ *t = '\0'; /* Dump it */ text_out(buf); if (strlen(buf)) text_out(" "); }
TARGET* search_for_target ( char * name, LIST* search_path ) { PATHNAME f[1]; string buf[1]; LOCATED_TARGET lt, *lta = < time_t time; int found = 0; TARGET* result; string_new( buf ); path_parse( name, f ); f->f_grist.ptr = 0; f->f_grist.len = 0; while( search_path ) { f->f_root.ptr = search_path->string; f->f_root.len = strlen( search_path->string ); string_truncate( buf, 0 ); path_build( f, buf, 1 ); lt.file_name = buf->value ; if (! located_targets ) located_targets = hashinit( sizeof(LOCATED_TARGET), "located targets" ); if ( hashcheck( located_targets, (HASHDATA **)<a ) ) { return lta->target; } timestamp( buf->value, &time ); if (time) { found = 1; break; } search_path = list_next( search_path ); } if ( ! found ) { f->f_root.ptr = 0; f->f_root.len = 0; string_truncate( buf, 0 ); path_build( f, buf, 1 ); timestamp( buf->value, &time ); } result = bindtarget( name ); result->boundname = newstr( buf->value ); result->time = time; result->binding = time ? T_BIND_EXISTS : T_BIND_MISSING; call_bind_rule( result->name, result->boundname ); string_free( buf ); return result; }
/* * Race Legends * -KMW- */ void race_score(int race_num) { register int i = 0, j, m = 0; int pr, clev, lastlev; high_score the_score; char buf[1024], out_val[256], tmp_str[80]; lastlev = 0; /* rr9: TODO - pluralize the race */ sprintf(tmp_str,"The Greatest of all the %s", get_race_t_aux(race_num, 0)->name); prt(tmp_str, 5, 15); /* Build the filename */ path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); highscore_fd = fd_open(buf, O_RDONLY); if (highscore_fd < 0) { msg_print("Score file unavailable."); msg_print(NULL); return; } if (highscore_seek(0)) return; for (i = 0; i < MAX_HISCORES; i++) { if (highscore_read(&the_score)) break; } m = 0; j = 0; while ((m < 10) || (j < MAX_HISCORES)) { if (highscore_seek(j)) break; if (highscore_read(&the_score)) break; pr = atoi(the_score.p_r); clev = atoi(the_score.cur_lev); if (pr == race_num) { sprintf(out_val, "%3d) %s the %s (Level %3d)", (m + 1), the_score.who, get_race_t_aux(pr, 0)->name, clev); prt(out_val, (m + 7), 0); m++; lastlev = clev; } j++; } /* add player if qualified */ if ((p_ptr->prace == race_num) && (p_ptr->lev >= lastlev)) { sprintf(out_val, "You) %s the %s (Level %3d)", player_name, get_race_t_aux(p_ptr->prace, p_ptr->psubrace)->name, p_ptr->lev); prt(out_val, (m + 8), 0); } (void)fd_close(highscore_fd); highscore_fd = -1; }