2012-09-14 02:42:11 +03:00
# pragma once
# include "../../lib/BattleHex.h"
2013-06-21 23:59:32 +03:00
# include "../../lib/HeroBonus.h"
# include "../../lib/CBattleCallback.h"
2012-09-14 02:42:11 +03:00
2012-09-24 02:10:56 +03:00
class CSpell ;
2013-06-21 23:59:32 +03:00
class StackWithBonuses : public IBonusBearer
{
public :
const CStack * stack ;
mutable std : : vector < Bonus > bonusesToAdd ;
2013-06-26 14:18:27 +03:00
virtual const TBonusListPtr getAllBonuses ( const CSelector & selector , const CSelector & limit , const CBonusSystemNode * root = nullptr , const std : : string & cachingStr = " " ) const override ;
2013-06-21 23:59:32 +03:00
} ;
struct EnemyInfo
{
const CStack * s ;
int adi , adr ;
std : : vector < BattleHex > attackFrom ; //for melee fight
EnemyInfo ( const CStack * _s ) : s ( _s )
{ }
void calcDmg ( const CStack * ourStack ) ;
bool operator = = ( const EnemyInfo & ei ) const
{
return s = = ei . s ;
}
} ;
//FIXME: unused function
/*
static bool willSecondHexBlockMoreEnemyShooters ( const BattleHex & h1 , const BattleHex & h2 )
{
int shooters [ 2 ] = { 0 } ; //count of shooters on hexes
for ( int i = 0 ; i < 2 ; i + + )
BOOST_FOREACH ( BattleHex neighbour , ( i ? h2 : h1 ) . neighbouringTiles ( ) )
if ( const CStack * s = cbc - > battleGetStackByPos ( neighbour ) )
if ( s - > getCreature ( ) - > isShooting ( ) )
shooters [ i ] + + ;
return shooters [ 0 ] < shooters [ 1 ] ;
}
*/
struct ThreatMap
{
std : : array < std : : vector < BattleAttackInfo > , GameConstants : : BFIELD_SIZE > threatMap ; // [hexNr] -> enemies able to strike
const CStack * endangered ;
std : : array < int , GameConstants : : BFIELD_SIZE > sufferedDamage ;
ThreatMap ( const CStack * Endangered ) ;
} ;
struct HypotheticChangesToBattleState
{
std : : map < const CStack * , const IBonusBearer * > bonusesOfStacks ;
std : : map < const CStack * , int > counterAttacksLeft ;
} ;
struct AttackPossibility
{
const CStack * enemy ; //redundant (to attack.defender) but looks nice
BattleHex tile ; //tile from which we attack
BattleAttackInfo attack ;
int damageDealt ;
int damageReceived ; //usually by counter-attack
int tacticImpact ;
int damageDiff ( ) const ;
int attackValue ( ) const ;
static AttackPossibility evaluate ( const BattleAttackInfo & AttackInfo , const HypotheticChangesToBattleState & state , BattleHex hex ) ;
} ;
template < typename Key , typename Val , typename Val2 >
2013-06-23 22:35:54 +03:00
const Val getValOr ( const std : : map < Key , Val > & Map , const Key & key , const Val2 defaultValue )
2013-06-21 23:59:32 +03:00
{
2013-06-23 22:35:54 +03:00
//returning references here won't work: defaultValue must be converted into Val, creating temporary
2013-06-21 23:59:32 +03:00
auto i = Map . find ( key ) ;
if ( i ! = Map . end ( ) )
return i - > second ;
else
return defaultValue ;
}
struct PotentialTargets
{
std : : vector < AttackPossibility > possibleAttacks ;
std : : vector < const CStack * > unreachableEnemies ;
//std::function<AttackPossibility(bool,BattleHex)> GenerateAttackInfo; //args: shooting, destHex
PotentialTargets ( ) { } ;
PotentialTargets ( const CStack * attacker , const HypotheticChangesToBattleState & state = HypotheticChangesToBattleState ( ) ) ;
AttackPossibility bestAction ( ) const ;
int bestActionValue ( ) const ;
} ;
2012-09-14 02:42:11 +03:00
class CBattleAI : public CBattleGameInterface
{
int side ;
2015-12-29 04:43:33 +02:00
std : : shared_ptr < CBattleCallback > cb ;
2012-09-29 17:44:06 +03:00
//Previous setting of cb
bool wasWaitingForRealize , wasUnlockingGs ;
2012-09-14 02:42:11 +03:00
void print ( const std : : string & text ) const ;
public :
CBattleAI ( void ) ;
~ CBattleAI ( void ) ;
2015-12-29 04:43:33 +02:00
void init ( std : : shared_ptr < CBattleCallback > CB ) override ;
2013-06-26 14:18:27 +03:00
void actionFinished ( const BattleAction & action ) override ; //occurs AFTER every action taken by any stack or by the hero
void actionStarted ( const BattleAction & action ) override ; //occurs BEFORE every action taken by any stack or by the hero
BattleAction activeStack ( const CStack * stack ) override ; //called when it's turn of that stack
void battleAttack ( const BattleAttack * ba ) override ; //called when stack is performing attack
void battleStacksAttacked ( const std : : vector < BattleStackAttacked > & bsa ) override ; //called when stack receives damage (after battleAttack())
void battleEnd ( const BattleResult * br ) override ;
//void battleResultsApplied() override; //called when all effects of last battle are applied
void battleNewRoundFirst ( int round ) override ; //called at the beginning of each turn before changes are applied;
2014-03-23 15:59:03 +03:00
void battleNewRound ( int round ) override ; //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
2013-06-26 14:18:27 +03:00
void battleStackMoved ( const CStack * stack , std : : vector < BattleHex > dest , int distance ) override ;
void battleSpellCast ( const BattleSpellCast * sc ) override ;
void battleStacksEffectsSet ( const SetStackEffect & sse ) override ; //called when a specific effect is set to stacks
//void battleTriggerEffect(const BattleTriggerEffect & bte) override;
void battleStart ( const CCreatureSet * army1 , const CCreatureSet * army2 , int3 tile , const CGHeroInstance * hero1 , const CGHeroInstance * hero2 , bool side ) override ; //called by engine when battle starts; side=0 - left, side=1 - right
void battleStacksHealedRes ( const std : : vector < std : : pair < ui32 , ui32 > > & healedStacks , bool lifeDrain , bool tentHeal , si32 lifeDrainFrom ) override ; //called when stacks are healed / resurrected first element of pair - stack id, second - healed hp
void battleNewStackAppeared ( const CStack * stack ) override ; //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
void battleObstaclesRemoved ( const std : : set < si32 > & removedObstacles ) override ; //called when a certain set of obstacles is removed from batlefield; IDs of them are given
void battleCatapultAttacked ( const CatapultAttack & ca ) override ; //called when catapult makes an attack
void battleStacksRemoved ( const BattleStacksRemoved & bsr ) override ; //called when certain stack is completely removed from battlefield
2012-09-14 02:42:11 +03:00
BattleAction goTowards ( const CStack * stack , BattleHex hex ) ;
2012-09-20 19:55:21 +03:00
BattleAction useCatapult ( const CStack * stack ) ;
2013-06-17 18:45:55 +03:00
boost : : optional < BattleAction > considerFleeingOrSurrendering ( ) ;
2012-09-20 19:55:21 +03:00
void attemptCastingSpell ( ) ;
2012-09-24 02:10:56 +03:00
std : : vector < BattleHex > getTargetsToConsider ( const CSpell * spell ) const ;
2012-09-14 02:42:11 +03:00
} ;