diff options
author | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2006-09-14 11:11:30 +0000 |
---|---|---|
committer | dshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573> | 2006-09-14 11:11:30 +0000 |
commit | 00ebcacf6e5da3af116b42d9ed01a37a4c715a69 (patch) | |
tree | 1a5a6b9c003e5b62eadf3ef05d7b4b47af3d0a57 | |
parent | 09babcd3185429b363ea4fa079bc217a8c85de3f (diff) | |
download | crawl-ref-00ebcacf6e5da3af116b42d9ed01a37a4c715a69.tar.gz crawl-ref-00ebcacf6e5da3af116b42d9ed01a37a4c715a69.zip |
r98@xenon: dshaligram | 2006-09-14 16:42:08 +051800
* Rebalanced missile weapons (again!), should be close to their final form.
* Reworked mock-fight debugging code.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/branches/stone_soup@38 c06c8d41-db1a-0410-9941-cceddc491573
-rw-r--r-- | crawl-ref/source/acr.cc | 6 | ||||
-rw-r--r-- | crawl-ref/source/debug.cc | 225 | ||||
-rw-r--r-- | crawl-ref/source/debug.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 1 | ||||
-rw-r--r-- | crawl-ref/source/initfile.cc | 14 | ||||
-rw-r--r-- | crawl-ref/source/item_use.cc | 28 | ||||
-rw-r--r-- | crawl-ref/source/stuff.cc | 2 |
7 files changed, 206 insertions, 72 deletions
diff --git a/crawl-ref/source/acr.cc b/crawl-ref/source/acr.cc index b94e55a2c0..95618e83c0 100644 --- a/crawl-ref/source/acr.cc +++ b/crawl-ref/source/acr.cc @@ -580,8 +580,12 @@ static void handle_wizard_command( void ) tweak_object(); break; + case 'f': + debug_fight_statistics(false); + break; + case 'F': - debug_fight_statistics(); + debug_fight_statistics(true); break; case 'm': diff --git a/crawl-ref/source/debug.cc b/crawl-ref/source/debug.cc index ff70b482c1..eb29e8c9d9 100644 --- a/crawl-ref/source/debug.cc +++ b/crawl-ref/source/debug.cc @@ -19,6 +19,7 @@ #include <string.h> #include <stdio.h> #include <stdarg.h> +#include <time.h> #include <ctype.h> #ifdef DOS @@ -1728,7 +1729,7 @@ void error_message_to_player(void) #ifdef WIZARD -static int create_dfs_monster(int mtype, int hp) +static int create_fsim_monster(int mtype, int hp) { const int mi = create_monster( mtype, 0, BEH_HOSTILE, you.x_pos, you.y_pos, @@ -1742,7 +1743,7 @@ static int create_dfs_monster(int mtype, int hp) return (mi); } -static skill_type dfs_melee_skill(const item_def *item) +static skill_type fsim_melee_skill(const item_def *item) { skill_type sk = SK_UNARMED_COMBAT; if (item) @@ -1750,19 +1751,19 @@ static skill_type dfs_melee_skill(const item_def *item) return (sk); } -static void dfs_set_melee_skill(int skill, const item_def *item) +static void fsim_set_melee_skill(int skill, const item_def *item) { - you.skills[dfs_melee_skill(item)] = skill; + you.skills[fsim_melee_skill(item)] = skill; you.skills[SK_FIGHTING] = skill * 15 / 27; } -static void dfs_set_ranged_skill(int skill, const item_def *item) +static void fsim_set_ranged_skill(int skill, const item_def *item) { you.skills[range_skill(*item)] = skill; you.skills[SK_RANGED_COMBAT] = skill * 15 / 27; } -static void dfs_item(FILE *out, +static void fsim_item(FILE *out, bool melee, const item_def *weap, int wskill, unsigned long damage, @@ -1781,8 +1782,8 @@ static void dfs_item(FILE *out, time / iterations); } -static bool dfs_ranged_combat(FILE *out, int wskill, int mi, - const item_def *item) +static bool fsim_ranged_combat(FILE *out, int wskill, int mi, + const item_def *item, int missile_slot) { monsters &mon = menv[mi]; unsigned long cumulative_damage = 0L; @@ -1790,14 +1791,14 @@ static bool dfs_ranged_combat(FILE *out, int wskill, int mi, long hits = 0L; int maxdam = 0; - const int thrown = get_fire_item_index(); - if (thrown == ENDOFPACK) + const int thrown = missile_slot == -1? get_fire_item_index() : missile_slot; + if (thrown == ENDOFPACK || thrown == -1) { mprf("No suitable missiles for combat simulation."); return (false); } - dfs_set_ranged_skill(wskill, item); + fsim_set_ranged_skill(wskill, item); no_messages mx; const long iter_limit = Options.fsim_rounds; @@ -1817,13 +1818,13 @@ static bool dfs_ranged_combat(FILE *out, int wskill, int mi, if (damage > maxdam) maxdam = damage; } - dfs_item(out, false, item, wskill, cumulative_damage, + fsim_item(out, false, item, wskill, cumulative_damage, iter_limit, hits, maxdam, time_taken); return (true); } -static bool dfs_melee_combat(FILE *out, int wskill, int mi, +static bool fsim_melee_combat(FILE *out, int wskill, int mi, const item_def *item) { monsters &mon = menv[mi]; @@ -1832,7 +1833,7 @@ static bool dfs_melee_combat(FILE *out, int wskill, int mi, long hits = 0L; int maxdam = 0; - dfs_set_melee_skill(wskill, item); + fsim_set_melee_skill(wskill, item); no_messages mx; const long iter_limit = Options.fsim_rounds; @@ -1852,25 +1853,25 @@ static bool dfs_melee_combat(FILE *out, int wskill, int mi, if (damage > maxdam) maxdam = damage; } - dfs_item(out, true, item, wskill, cumulative_damage, iter_limit, hits, + fsim_item(out, true, item, wskill, cumulative_damage, iter_limit, hits, maxdam, time_taken); return (true); } -static bool debug_fight_simulate(FILE *out, int wskill, int mi) +static bool debug_fight_simulate(FILE *out, int wskill, int mi, int miss_slot) { int weapon = you.equip[EQ_WEAPON]; const item_def *iweap = weapon != -1? &you.inv[weapon] : NULL; if (iweap && iweap->base_type == OBJ_WEAPONS && is_range_weapon(*iweap)) - return dfs_ranged_combat(out, wskill, mi, iweap); + return fsim_ranged_combat(out, wskill, mi, iweap, miss_slot); else - return dfs_melee_combat(out, wskill, mi, iweap); + return fsim_melee_combat(out, wskill, mi, iweap); } -static const item_def *dfs_weap_item() +static const item_def *fsim_weap_item() { const int weap = you.equip[EQ_WEAPON]; if (weap == -1) @@ -1879,17 +1880,17 @@ static const item_def *dfs_weap_item() return &you.inv[weap]; } -static std::string dfs_wskill() +static std::string fsim_wskill() { - const item_def *iweap = dfs_weap_item(); + const item_def *iweap = fsim_weap_item(); return iweap && iweap->base_type == OBJ_WEAPONS && is_range_weapon(*iweap)? skill_name( range_skill(*iweap) ) : - iweap? skill_name( dfs_melee_skill(iweap) ) : + iweap? skill_name( fsim_melee_skill(iweap) ) : skill_name( SK_UNARMED_COMBAT ); } -static std::string dfs_weapon() +static std::string fsim_weapon(int missile_slot) { char item_buf[ITEMNAME_SIZE]; if (you.equip[EQ_WEAPON] != -1) @@ -1899,7 +1900,9 @@ static std::string dfs_weapon() if (is_range_weapon(weapon)) { - const int missile = get_fire_item_index(); + const int missile = + missile_slot == -1? get_fire_item_index() : + missile_slot; if (missile < ENDOFPACK) { std::string base = item_buf; @@ -1916,23 +1919,56 @@ static std::string dfs_weapon() return (item_buf); } -static void dfs_title(FILE *o, int mon) +static std::string fsim_time_string() +{ + time_t curr_time = time(NULL); + struct tm *ltime = localtime(&curr_time); + if (ltime) + { + char buf[100]; + snprintf(buf, sizeof buf, "%4d%02d%02d/%2d:%02d:%02d", + ltime->tm_year + 1900, + ltime->tm_mon + 1, + ltime->tm_mday, + ltime->tm_hour, + ltime->tm_min, + ltime->tm_sec); + return (buf); + } + return (""); +} + +static void fsim_mon_stats(FILE *o, const monsters &mon) +{ + char buf[ITEMNAME_SIZE]; + fprintf(o, "Monster : %s\n", + moname(mon.type, true, DESC_PLAIN, buf)); + fprintf(o, "HD : %d\n", mon.hit_dice); + fprintf(o, "AC : %d\n", mon.armour_class); + fprintf(o, "EV : %d\n", mon.evasion); +} + +static void fsim_title(FILE *o, int mon, int ms) { char buf[ITEMNAME_SIZE]; fprintf(o, "Dungeon Crawl Stone Soup version " VERSION "\n\n"); - fprintf(o, "Combat simulation: %s %s vs. %s (%ld turns)\n", + fprintf(o, "Combat simulation: %s %s vs. %s (%ld rounds) (%s)\n", species_name(you.species, you.experience_level), you.class_name, moname(menv[mon].type, true, DESC_PLAIN, buf), - Options.fsim_rounds); + Options.fsim_rounds, + fsim_time_string().c_str()); fprintf(o, "Experience: %d\n", you.experience_level); fprintf(o, "Strength : %d\n", you.strength); fprintf(o, "Intel. : %d\n", you.intel); - fprintf(o, "Dexterity : %d\n\n", you.dex); - fprintf(o, "Weapon : %s\n", dfs_weapon().c_str()); - fprintf(o, "Skill : %s\n", dfs_wskill().c_str()); + fprintf(o, "Dexterity : %d\n", you.dex); fprintf(o, "Base speed: %d\n", player_speed()); fprintf(o, "\n"); + fsim_mon_stats(o, menv[mon]); + fprintf(o, "\n"); + fprintf(o, "Weapon : %s\n", fsim_weapon(ms).c_str()); + fprintf(o, "Skill : %s\n", fsim_wskill().c_str()); + fprintf(o, "\n"); fprintf(o, "Skill | Accuracy | Av.Dam | Av.HitDam | Eff.Dam | Max.Dam | Av.Time\n"); } @@ -1943,37 +1979,25 @@ static int fsim_stat(int stat) stat); } -// Writes statistics about a fight to fight.stat in the current directory. -// For fight purposes, a punching bag is summoned and given lots of hp, and the -// average damage the player does to the p. bag over 10000 hits is noted, -// advancing the weapon skill from 0 to 27, and keeping fighting skill to 2/5 -// of current weapon skill. -void debug_fight_statistics() +static bool debug_fight_sim(int mindex, int missile_slot) { - int punching_bag = get_monnum(Options.fsim_mons.c_str()); - if (punching_bag == -1) - punching_bag = MONS_WORM; - - int mindex = create_dfs_monster(punching_bag, 500); - if (mindex == -1) - { - mprf("Failed to create punching bag"); - return; - } - FILE *ostat = fopen("fight.stat", "a"); if (!ostat) { mprf("Can't write fight.stat: %s", strerror(errno)); - return; + return (false); } + bool success = true; FixedVector<unsigned char, 50> skill_backup = you.skills; int ystr = you.strength, yint = you.intel, ydex = you.dex; int yxp = you.experience_level; + for (int i = SK_FIGHTING; i < NUM_SKILLS; ++i) + you.skills[i] = 0; + you.experience_level = Options.fsim_xl; if (you.experience_level < 1) you.experience_level = 1; @@ -1984,13 +2008,13 @@ void debug_fight_statistics() you.intel = fsim_stat(Options.fsim_int); you.dex = fsim_stat(Options.fsim_dex); - dfs_title(ostat, mindex); + fsim_title(ostat, mindex, missile_slot); for (int wskill = 0; wskill <= 27; ++wskill) { mesclr(); mprf("Calculating average damage for %s at skill %d", - dfs_weapon().c_str(), wskill); - if (!debug_fight_simulate(ostat, wskill, mindex)) + fsim_weapon(missile_slot).c_str(), wskill); + if (!debug_fight_simulate(ostat, wskill, mindex, missile_slot)) goto done_combat_sim; fflush(ostat); @@ -1998,6 +2022,7 @@ void debug_fight_statistics() // for the user, but slow down the sim with all the calls to kbhit(). if (kbhit() && getch() == 27) { + success = false; mprf("Canceling simulation\n"); goto done_combat_sim; } @@ -2008,12 +2033,104 @@ void debug_fight_statistics() you.dex = ydex; you.experience_level = yxp; - mprf("Done fight simulation with %s", dfs_weapon().c_str()); + mprf("Done fight simulation with %s", fsim_weapon(missile_slot).c_str()); done_combat_sim: fprintf(ostat, "-----------------------------------\n\n"); - fclose(ostat); - monster_die(&menv[mindex], KILL_DISMISSED, 0); + + return (success); +} + +int fsim_kit_equip(const std::string &kit) +{ + int missile_slot = -1; + char item_buf[ITEMNAME_SIZE]; + + std::string::size_type ammo_div = kit.find("/"); + std::string weapon = kit; + std::string missile; + if (ammo_div != std::string::npos) + { + weapon = kit.substr(0, ammo_div); + missile = kit.substr(ammo_div + 1); + trim_string(weapon); + trim_string(missile); + } + + for (int i = 0; i < ENDOFPACK; ++i) + { + if (!is_valid_item(you.inv[i])) + continue; + + in_name(i, DESC_PLAIN, item_buf, true); + if (std::string(item_buf).find(weapon) != std::string::npos) + { + if (i != you.equip[EQ_WEAPON]) + { + wield_weapon(true, i, false); + if (i != you.equip[EQ_WEAPON]) + return -100; + } + break; + } + } + + if (!missile.empty()) + { + for (int i = 0; i < ENDOFPACK; ++i) + { + if (!is_valid_item(you.inv[i])) + continue; + + in_name(i, DESC_PLAIN, item_buf, true); + if (std::string(item_buf).find(missile) != std::string::npos) + { + missile_slot = i; + break; + } + } + } + + return (missile_slot); +} + +// Writes statistics about a fight to fight.stat in the current directory. +// For fight purposes, a punching bag is summoned and given lots of hp, and the +// average damage the player does to the p. bag over 10000 hits is noted, +// advancing the weapon skill from 0 to 27, and keeping fighting skill to 2/5 +// of current weapon skill. +void debug_fight_statistics(bool use_defaults) +{ + int punching_bag = get_monnum(Options.fsim_mons.c_str()); + if (punching_bag == -1) + punching_bag = MONS_WORM; + + int mindex = create_fsim_monster(punching_bag, 500); + if (mindex == -1) + { + mprf("Failed to create punching bag"); + return; + } + + if (!use_defaults) + { + debug_fight_sim(mindex, -1); + goto fsim_mcleanup; + } + + for (int i = 0, size = Options.fsim_kit.size(); i < size; ++i) + { + int missile = fsim_kit_equip(Options.fsim_kit[i]); + if (missile == -100) + { + mprf("Aborting sim on %s", Options.fsim_kit[i].c_str()); + goto fsim_mcleanup; + } + if (!debug_fight_sim(mindex, missile)) + break; + } +fsim_mcleanup: + monster_die(&menv[mindex], KILL_DISMISSED, 0); } #endif diff --git a/crawl-ref/source/debug.h b/crawl-ref/source/debug.h index 8675ef9de3..3df332441d 100644 --- a/crawl-ref/source/debug.h +++ b/crawl-ref/source/debug.h @@ -143,6 +143,6 @@ void stethoscope(int mwh); void debug_item_scan( void ); void debug_get_religion( void ); void debug_change_species( void ); -void debug_fight_statistics( void ); +void debug_fight_statistics( bool use_init_defaults ); #endif diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h index aab1dd2d87..525ec77614 100644 --- a/crawl-ref/source/externs.h +++ b/crawl-ref/source/externs.h @@ -781,6 +781,7 @@ struct game_options int fsim_str, fsim_int, fsim_dex; int fsim_xl; std::string fsim_mons; + std::vector<std::string> fsim_kit; typedef std::map<std::string, std::string> opt_map; opt_map named_options; // All options not caught above are diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index e7e62adc1f..02d7be3ad1 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -437,6 +437,7 @@ void reset_options(bool clear_name) Options.fsim_mons = "worm"; Options.fsim_str = Options.fsim_int = Options.fsim_dex = 15; Options.fsim_xl = 10; + Options.fsim_kit.clear(); // These are only used internally, and only from the commandline: // XXX: These need a better place. @@ -1286,6 +1287,10 @@ void parse_option_line(const std::string &str, bool runscript) { Options.show_waypoints = read_bool(field, Options.show_waypoints); } + else if (key == "fsim_kit") + { + append_vector(Options.fsim_kit, split_string(",", field)); + } else if (key == "fsim_rounds") { Options.fsim_rounds = atol(field.c_str()); @@ -1354,15 +1359,18 @@ void parse_option_line(const std::string &str, bool runscript) else if (key == "stop_travel") { std::vector<std::string> fragments = split_string(",", field); - for (int i = 0, count = fragments.size(); i < count; ++i) { + for (int i = 0, count = fragments.size(); i < count; ++i) + { if (fragments[i].length() == 0) continue; std::string::size_type pos = fragments[i].find(":"); - if (pos && pos != std::string::npos) { + if (pos && pos != std::string::npos) + { std::string prefix = fragments[i].substr(0, pos); int channel = str_to_channel( prefix ); - if (channel != -1 || prefix == "any") { + if (channel != -1 || prefix == "any") + { std::string s = fragments[i].substr( pos + 1 ); trim_string( s ); Options.stop_travel.push_back( diff --git a/crawl-ref/source/item_use.cc b/crawl-ref/source/item_use.cc index f9c69b9fd8..1be7114d8d 100644 --- a/crawl-ref/source/item_use.cc +++ b/crawl-ref/source/item_use.cc @@ -1335,7 +1335,11 @@ bool throw_it(struct bolt &pbolt, int throw_2, monsters *dummy_target) int speed = 100; baseHit = property( launcher, PWPN_HIT ); - baseDam = item_base_dam + lnch_base_dam; + baseDam = lnch_base_dam + random2(1 + item_base_dam); + + // Slings are terribly weakened otherwise + if (lnch_base_dam == 0) + baseDam = item_base_dam; if (launcher_skill == SK_BOWS) speed_min = 40; @@ -1415,11 +1419,11 @@ bool throw_it(struct bolt &pbolt, int throw_2, monsters *dummy_target) // - Add on launcher and missile pluses to extra damage. // [dshaligram] This can get large... - exDamBonus = lnchDamBonus + ammoDamBonus; - exDamBonus = exDamBonus > 0? random2avg(exDamBonus + 1, 2) - : exDamBonus; - exHitBonus = lnchHitBonus > 0? random2avg(lnchHitBonus + 1, 2) - : lnchHitBonus; + exDamBonus = lnchDamBonus + random2(1 + ammoDamBonus); + exDamBonus = exDamBonus > 0? random2(exDamBonus + 1) + : -random2(-exDamBonus + 1); + exHitBonus = lnchHitBonus > 0? random2(lnchHitBonus + 1) + : -random2(-lnchHitBonus + 1); // removed 2 random2(2)s from each of the learning curves, but // left slings because they're hard enough to develop without @@ -1444,7 +1448,7 @@ bool throw_it(struct bolt &pbolt, int throw_2, monsters *dummy_target) exDamBonus += strbonus; // add skill for slings.. helps to find those vulnerable spots - dice_mult = dice_mult * (15 + random2(1 + effSkill)) / 15; + dice_mult = dice_mult * (14 + random2(1 + effSkill)) / 14; // now kill the launcher damage bonus if (lnchDamBonus > 0) @@ -1488,7 +1492,7 @@ bool throw_it(struct bolt &pbolt, int throw_2, monsters *dummy_target) // add in skill for bows.. help you to find those vulnerable spots. // exDamBonus += effSkill; - dice_mult = dice_mult * (25 + random2(1 + effSkill)) / 25; + dice_mult = dice_mult * (17 + random2(1 + effSkill)) / 17; // now kill the launcher damage bonus if (lnchDamBonus > 0) @@ -1503,12 +1507,12 @@ bool throw_it(struct bolt &pbolt, int throw_2, monsters *dummy_target) exHitBonus += (3 * effSkill) / 2 + 6; // exDamBonus += effSkill * 2 / 3 + 4; - dice_mult = dice_mult * (33 + random2(1 + effSkill)) / 33; + dice_mult = dice_mult * (22 + random2(1 + effSkill)) / 22; if (lnchType == WPN_HAND_CROSSBOW) { exHitBonus -= 2; - dice_mult = dice_mult * 28 / 30; + dice_mult = dice_mult * 26 / 30; } break; @@ -1521,8 +1525,8 @@ bool throw_it(struct bolt &pbolt, int throw_2, monsters *dummy_target) if (coinflip()) exercise(SK_RANGED_COMBAT, 1); - // all launched weapons get a tohit boost from throwing skill. - exHitBonus += (3 * you.skills[SK_RANGED_COMBAT]) / 4; + // all launched weapons get a minor tohit boost from throwing skill. + exHitBonus += you.skills[SK_RANGED_COMBAT] / 5; if (bow_brand == SPWPN_VORPAL) { diff --git a/crawl-ref/source/stuff.cc b/crawl-ref/source/stuff.cc index 01b5b8a030..1b241bb807 100644 --- a/crawl-ref/source/stuff.cc +++ b/crawl-ref/source/stuff.cc @@ -366,7 +366,7 @@ void scale_dice( dice_def &dice, int threshold ) dice.num *= 2; // If it's an odd number, lose one; this is more than // compensated by the increase in number of dice. - dice.size = dice.size / 2; + dice.size /= 2; } } |