On Sun, 2006-04-02 at 14:52 +0200, Jérémy Rosen wrote:
> (note : this is code I don't know well)
>
> all this sound nice and good, I have seen your patch on savannah, at it
> looks promising...
>
>
> Xan, rusty, do you want to merge it or shall I ?
I'd prefer to go through in detail and merge it myself. The current
attack_prediction API was a first guess: but looking at the way it's
used I might decide to modify it.
BTW, Xan rewrote healing as part of this stuff (my changes clashed with
his), and it a little broken at the moment WRT allied healing and cure
vs. heal poisoning. I'll fix this first.
(Not criticising Xan: over 2000 lines of new code in 44 files is going
to have bugs!)
Thanks!
Rusty.
>
> I don't know the code well enough to comment much more than "work for
> me" so I think it would be better if one of you took care of that patch
>
>
> Laurent Birtz wrote:
> >
>
>
> Hello,
> >
> > some time ago I've worked on improving the "Damage Calculations" dialog
> > that is
> > shown when the user is considering to attack an enemy unit. I've also
> > tweaked
> > the code to improve the selection of the defense weapon when a unit is
> > attacked.
> > Unfortunatly, I had to stop development for a while since I've been kept
> > busy
> > with other projects (my apologies to Rusty for disappearing). Now that
> > I've got
> > some time, here's a resume of the modifications:
> >
> >
> > --------------------------------------------------
> > Damage Calculations dialog:
> >
> > The new dialog shows the damage computations and the hit points
> > distribution of
> > the units after the battle. Here's a sketch:
> >
> > Damage Calculations
> >
> > Attacker Defender
> > Base damage 10 Base damage 4
> > Morning +25% Morning
> > -25%
> > Attacker resistance vs blade *
> > 0.5
> > Damage per strike 12
> > Summary 12-3 (40%) Damage per strike 2
> > Chance of being unscathed 9.0% Summary
> > 2-2 (70%)
> > Chance of being unscathed
> > 21.6%
> >
> >
> > Expected Battle Result (hp) Expected Battle Result (hp)
> > -------------------------------------
> > --------------------------------------
> > | 51|== | 9.0%| | 39|====
> > |21.6%|
> > | 49|=========== |42.0%| | 27|=========
> > |43.2%|
> > | 47|============ |49.0%| | 15|======
> > |28.8%|
> > ------------------------------------- | 3|=
> > | 6.4%|
> >
> > --------------------------------------
> >
> >
> > --------------------------------------------------
> > Battle simulator:
> >
> > Rusty made a great battle simulator that can predict all the possible
> > outcomes
> > of a battle. The simulator handles drain, slow, first strike, berserk and
> > swarm. I use this simulator to obtain the hit points distribution of the
> > units
> > after the battle. However, the simulator can also be used by the AI to
> > accuratly predict the outcome of a battle (rather than relying on 50 dry
> > runs
> > like it is done currently). Remarkably, Rusty's simulator can "chain" many
> > attacks against a defender unit. Example: pikeman attacks wolfrider, then
> > shaman attacks wolfrider. After the first battle, the wolfrider will have
> > different possible HP values (e.g. 24, 10, 0 [bogus values]). The simulator
> > takes those values (and slow state) into account when it computes the
> > possible
> > states after the second battle. The final HP values of the wolfrider could
> > thus be (24, 15, 10, 5, 0). Since the simulator computes the probability
> > that
> > each unit remain unscathed (not touched by any blow), it is possible to get
> > the probability of a unit getting poisoned/slowed by an attack.
> >
> > Rusty spent much time optimizing his simulator. I *believe* that using the
> > simulator is faster than performing 50 dry runs, but I've conducted no
> > benchmarks. Rusty is the guy who would know.
> >
> > Possible caveat: due to the necessity of handling "slow + drain" properly,
> > Rusty had to use a slower implementation that involves a two-dimensions
> > matrix. The length and width of this matrix is determined by the maximum
> > HP of
> > the units that fight. So, while the computations are fast for units that
> > have
> > ~75 HP (?), they will get much slower as the health of the units increase
> > [O(n^2)]. Hence, if Wesnoth is to allow units that have lots of HP, the
> > simulator will probably be too slow for heavy usage by the AI (perhaps the
> > current approximation code can be used in those cases). Also, the
> > simulator is
> > slower to simulate battles involving 'berserk'.
> >
> >
> > --------------------------------------------------
> > "battle_context" object:
> >
> > To create the new dialog, I had to get the HP distributions and present the
> > different factors influencing the damage computations. In Wesnoth SVN
> > code (not
> > my code), evaluate_battle_stats() is used to get the strings explaining
> > those
> > factors and get the XX/XX/XX probability outcome string. However, I had
> > a number
> > of issues with evaluate_battle_stats() and its associated "battle_stats"
> > object:
> >
> > Firstly, before I designed the new dialog, I wanted to improve the
> > heuristic
> > used to select the weapon used on defense. evaluate_battle_stats() does
> > not make
> > this easy since some information such as the amount of damage dealt by the
> > attacker / defender are computed after the defense weapon has been chosen.
> >
> > Secondly, the information contained in "battle_stats" is derived from the
> > current tactical situation (in other words, evaluate_battle_stats()
> > looks at the
> > map and sees that it is day, that a leadership bonus applies to the
> > attacker,
> > etc). However, I considered using Rusty's simulator eventually to
> > compute the
> > outcome of many attacks on a single defender (when the AI is planning).
> > For the
> > second and subsequent attacks, the tactical situation is not the same as
> > the
> > "former" tactical situation (perhaps a unit will have leveled and provide
> > leadership, etc). Thus, I wanted to be able to manually set some factors
> > like
> > the leadership bonus and the time of day both for the attacker and the
> > defender.
> > Currently, evaluate_battle_stats() provides support for overriding the
> > terrain
> > used for the attacker (attacker_terrain_override) but it is not possible to
> > override other factors.
> >
> > Finally, I wasn't fond of the way evaluate_battle_stats() mixes GUI
> > stuff with
> > the battle computations. If 'strings' isn't NULL,
> > evaluate_battle_stats() fills
> > it out with strings describing the computations. Of course, this
> > approach may
> > avoid code duplication. However I feel it would be cleaner if there was
> > a clear
> > separation between the GUI and the actual computations.
> >
> > For these reasons, at the time I started writing the new dialog code, I
> > used
> > the "battle_context" object I had made to fix the (perceived) issues
> > mentionned
> > above. "battle_context" is designed to replace "battle_stats"
> > altogether. Here's
> > a quick rundown of the API:
> >
> > The "battle_context" object has some fields that are mandatory and some
> > fields
> > that are optional. Initially, the user sets the mandatory field with
> >
> > void init(const gamemap& map, std::vector<team>& teams,
> > std::map<gamemap::location,unit>& units,
> > const gamestatus& status, const gamemap::location& attacker_loc,
> > const gamemap::location& defender_loc,
> > const attack_type& attacker_weapon);
> >
> > The arguments are equivalent to the arguments used with
> > evaluate_battle_stats().
> >
> > Then, the user may optionally specify the
> > leadership/slowed/poisoned/time of
> > day/backstab state of the attacker and the defender, by setting those
> > fields
> > directly in the "battle_context" object.
> >
> > Afterward, the user calls compute_battle_stats() to compute the battle
> > statistics. This method first looks at the optional fields and obtains
> > the value
> > of any unitialized field by observing the current situation on the
> > battlefield,
> > like evaluate_battle_stats() does. Then, the method determines which
> > weapon will
> > be used on defense, if any. To do this, the method generates a
> > "battle_context"
> > object for each defense weapon that matches the attacker weapon's range.
> > Each of
> > those "battle_context" objects computes the stats of the attacker and
> > defender
> > weapons used (damage dealt, number of strikes, drain amount, etc).
> >
> > Then, an heuristic function is used to determine which is the best defense
> > weapon. The heuristic compares the current "best" defense weapon with
> > the next
> > available defense weapon and specifies which is the best weapon. At the
> > end of
> > the process, the original "battle_context" object contains the complete
> > stats of
> > the battle with the best defense weapon. Since the heuristic function
> > has access
> > to the complete battle stats when it compares two defense weapons, it
> > can make
> > an enlightened choice. For instance, the heuristic function could elicit
> > not to
> > use a low-damage poisoning attack if the attacker is already poisoned or is
> > undead. I know that some developers do not want a clever heuristic
> > though :)
> > For now, the heuristic of "battle_context" is compatible with the
> > heuristic used
> > in evaluate_battle_stats().
> >
> > Obviously the "battle_context" object is slower than
> > evaluate_battle_stats() due
> > to the extra work to select the defender's weapon. However, in most
> > cases, only
> > one defense weapon is available. I expect "battle_context" to be perhaps
> > 2 times
> > slower than evaluate_battle_stats() (just guessing, I didn't benchmark).
> > "battle_context" doesn't fill out 'strings' with the strings describing the
> > compution it makes. However, all the necessary information can be
> > obtained by
> > looking at the fields of "battle_context".
> >
> > Last minute note: "battle_context" no longer exactly matches the actual
> > computations done by evaluate_battle_stats() since Xan has been
> > modifying the
> > code extensively today. I've updated my code so that it compiles with
> > the new
> > interfaces. However, some of Xan's stuff is a work in progress and is
> > likely to
> > change in the next few days. Because of this I didn't update my code to
> > reflect
> > Xan's changes on backstab, charge, swarm and steadfast.
> >
> >
> > --------------------------------------------------
> > "battle_prediction_preview_pane" object:
> >
> > I modified attack_enemy() to compute the battle stats with
> > "attack_context", in
> > addition to the usual evaluate_battle_stats(). The logic doesn't change
> > much:
> >
> > // If set to 1, the new dialog is shown, otherwise the old dialog is shown.
> > #if 1
> > attack_prediction_displayer ap_displayer(gui_, bc_vector);
> > std::vector<gui::dialog_button> buttons;
> > buttons.push_back(gui::dialog_button(&ap_displayer, _("Damage
> > Calculations")));
> > #else
> > attack_calculations_displayer calc_displayer(gui_,stats);
> > std::vector<gui::dialog_button> buttons;
> > buttons.push_back(gui::dialog_button(&calc_displayer,_("Damage
> > Calculations")));
> > #endif
> >
> > "battle_prediction_preview_pane" is the object used to show the dialog. It
> > generates the graphics, obtains the strings describing the computations and
> > displays the dialog (straightforward code).
> >
> > Some notes about the graphics. HP values >= initial HP are shown in
> > green, 0 HP
> > is shown red, otherwise it's yellow. At most 10 lines are displayed in the
> > graphs. The lines with the highest probability values are retained when the
> > limit is exceeded. Thus, when two scuttlefishes or berseckers fight, it's
> > possible that some values with a low probability are not shown.
> >
> >
> > --------------------------------------------------
> > Code modifications:
> >
> > Rusty made a file called "attack_prediction.cpp" that contains his
> > simulator.
> > I've modified the file to extract the header "attack_prediction.hpp"
> > from it.
> > "Makefile.am" was modified to add "attack_prediction.cpp". The file
> > "playturn.cpp" was modified to contain the dialog code as described
> > above. The
> > files "actions.{cpp|hpp}" were modified to add the "battle_context"
> > code. The
> > file "font.hpp" was modified to add a prototype for the function
> > draw_text_line() (I needed this to draw text in a SDL surface directly).
> >
> >
> > --------------------------------------------------
> > Summary:
> >
> > The damage computations dialog code shouldn't cause problems. My
> > "battle_context" code probably will, since it aims at replacing existing
> > code.
> > The question is wheter you guys are happy with evaluate_battle_stats()
> > or if
> > you'd prefer "battle_context". In the former case, some work would have
> > to be
> > spent on reworking the dialog so that it uses evaluate_battle_stats() (I
> > guess
> > it would be possible to add "battle_context" just for the dialog but
> > that would
> > be a maintenance nightmare). Otherwise, evaluate_battle_stats() would
> > have to be
> > progressively phased out. The functions attack() and
> > attack_analysis::analyze()
> > use it and would need to be updated. In the process, analyze() could
> > make use of
> > Rusty's simulator to get rid of the dry runs and enhance the accuracy of
> > the
> > predictions (for instance, the current dry runs do not currently take
> > 'berserk'
> > into account as far as I can see).
> >
> > Last minute note: I spoke with Xan regarding my "battle_context" code
> > and it
> > seems there is hope that it might be integrated. Therefore I've posted
> > my patch
> > on Gna since Xan is updating evaluate_battle_stats() and I'm updating my
> > patch
> > in response to those changes. I'll try to keep my code compiling as the
> > various
> > interfaces are updated. However, the sooner my patch is accepted (or
> > rejected),
> > the less time I'll spend maintaining :) Hence here is the code. It doesn't
> > replace "battle_stats" in the AI and attack() yet, but if the developers
> > give
> > me the authorisation, I'll perform the conversion to battle_context
> > thoroughly
> > in the code.
> >
> >
> > I await your comments, thanks for your time!
> > Laurent Birtz
> >
> >
> > _______________________________________________
> > Wesnoth-dev mailing list
> > [email protected]
> > https://mail.gna.org/listinfo/wesnoth-dev
>
>
> _______________________________________________
> Wesnoth-dev mailing list
> [email protected]
> https://mail.gna.org/listinfo/wesnoth-dev
--
ccontrol: http://ozlabs.org/~rusty/ccontrol
_______________________________________________
Wesnoth-dev mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-dev