summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2006-09-14 11:11:30 +0000
committerdshaligram <dshaligram@c06c8d41-db1a-0410-9941-cceddc491573>2006-09-14 11:11:30 +0000
commit00ebcacf6e5da3af116b42d9ed01a37a4c715a69 (patch)
tree1a5a6b9c003e5b62eadf3ef05d7b4b47af3d0a57
parent09babcd3185429b363ea4fa079bc217a8c85de3f (diff)
downloadcrawl-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.cc6
-rw-r--r--crawl-ref/source/debug.cc225
-rw-r--r--crawl-ref/source/debug.h2
-rw-r--r--crawl-ref/source/externs.h1
-rw-r--r--crawl-ref/source/initfile.cc14
-rw-r--r--crawl-ref/source/item_use.cc28
-rw-r--r--crawl-ref/source/stuff.cc2
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;
}
}