1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-24 03:47:18 +02:00

Merged changes from trunk.

This commit is contained in:
Michał W. Urbańczyk 2010-12-05 23:26:56 +00:00
commit f020562570
24 changed files with 651 additions and 574 deletions

View File

@ -100,11 +100,11 @@ void Priorities::fillFeatures(const CGeniusAI::HypotheticalGameState & hgs)
float Priorities::getCost(vector<int> &resourceCosts,const CGHeroInstance * moved,int distOutOfTheWay)
{
if(resourceCosts.size()==0)return -1;
if(!resourceCosts.size())return -1;
//TODO: replace with ann
float cost = resourceCosts[0]/4.0+resourceCosts[1]/2.0+resourceCosts[2]/4.0+resourceCosts[3]/2.0+resourceCosts[4]/2.0+resourceCosts[5]/2.0+resourceCosts[6]/3000.0;
if(moved!=NULL) //TODO: multiply by importance of hero
if(moved) //TODO: multiply by importance of hero
cost+=distOutOfTheWay/10000.0;
return cost;
}
@ -210,25 +210,24 @@ float Priorities::getValue(const CGeniusAI::AIObjective & obj)
//objectNetworks[53][hobj->object->subID].feedForward(stateFeatures);
case 113://TODO: replace with value of skill for the hero
return 0;
case 103:case 58://TODO: replace with value of seeing x number of new tiles
case 103: case 58://TODO: replace with value of seeing x number of new tiles
return 0;
default:
if(objectNetworks[hobj->object->ID].size()!=0)
if (objectNetworks[hobj->object->ID].size())
return objectNetworks[hobj->object->ID][0].feedForward(stateFeatures);
cout << "don't know the value of ";
tlog6 << "don't know the value of ";
switch(obj.type)
{
case CGeniusAI::AIObjective::visit:
cout << "visiting " << hobj->object->ID;
tlog6 << "visiting " << hobj->object->ID;
break;
case CGeniusAI::AIObjective::attack:
cout << "attacking " << hobj->object->ID;
tlog6 << "attacking " << hobj->object->ID;
break;
case CGeniusAI::AIObjective::finishTurn:
obj.print();
break;
}
cout << endl;
tlog6 << endl;
}
}
else //town objective
@ -240,9 +239,9 @@ float Priorities::getValue(const CGeniusAI::AIObjective & obj)
return buildingNetworks[tnObj->whichTown->t->subID][tnObj->which].feedForward(stateFeatures);
else
{
cout << "don't know the value of ";
tlog6 << "don't know the value of ";
obj.print();
cout << endl;
tlog6 << endl;
}
}

View File

@ -42,7 +42,7 @@ ui8 side; //who made this action: false - left, true - right player
/**
* Implementation of CBattleLogic class.
*/
CBattleLogic::CBattleLogic(ICallback *cb, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side) :
CBattleLogic::CBattleLogic(ICallback *cb, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) :
m_iCurrentTurn(-2),
m_bIsAttacker(!side),
m_cb(cb),

View File

@ -63,7 +63,7 @@ private:
int leftHitPoint_for_min; // scenario
};
public:
CBattleLogic(ICallback *cb, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side);
CBattleLogic(ICallback *cb, const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side);
~CBattleLogic();
void SetCurrentTurn(int turn);
@ -80,8 +80,8 @@ private:
const CCreatureSet *m_army1;
const CCreatureSet *m_army2;
int3 m_tile;
CGHeroInstance *m_hero1;
CGHeroInstance *m_hero2;
const CGHeroInstance *m_hero1;
const CGHeroInstance *m_hero2;
bool m_side;
// statistics

File diff suppressed because it is too large Load Diff

View File

@ -28,11 +28,10 @@ class CGeniusAI : public CGlobalAI
{
private:
// TODO: cb... come back, croach busters!?
ICallback* m_cb;
ICallback* m_cb;
geniusai::BattleAI::CBattleLogic* m_battleLogic;
geniusai::GeneralAI::CGeneralAI m_generalAI;
geniusai::Priorities* m_priorities;
geniusai::Priorities* m_priorities;
CondSh<BattleState> m_state; //are we engaged into battle?
@ -71,7 +70,7 @@ private:
void update(CGeniusAI & ai);
CGeniusAI * AI;
std::vector<const CGHeroInstance *> AvailableHeroesToBuy;
std::vector<int> resourceAmounts;
std::vector<ui32> resourceAmounts;
std::vector<HeroModel> heroModels;
std::vector<TownModel> townModels;
std::set< AIObjectContainer > knownVisitableObjects;
@ -110,7 +109,7 @@ private:
public:
HypotheticalGameState hgs;
int3 pos;
const CGObjectInstance * object;
const CGObjectInstance * object; //interactive object
mutable std::vector<HypotheticalGameState::HeroModel*> whoCanAchieve;
//HeroObjective(){}
@ -202,14 +201,14 @@ public:
// battle
virtual void actionFinished(const BattleAction *action);//occurs AFTER every action taken by any stack or by the hero
virtual void actionStarted(const BattleAction *action);//occurs BEFORE every action taken by any stack or by the hero
virtual void battleAttack(BattleAttack *ba); //called when stack is performing attack
virtual void battleStacksAttacked(std::set<BattleStackAttacked> & bsa); //called when stack receives damage (after battleAttack())
virtual void battleEnd(BattleResult *br);
virtual void battleAttack(const BattleAttack *ba); //called when stack is performing attack
virtual void battleStacksAttacked(const std::set<BattleStackAttacked> & bsa); //called when stack receives damage (after battleAttack())
virtual void battleEnd(const BattleResult *br);
virtual void battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
virtual void battleStackMoved(int ID, int dest, int distance, bool end);
virtual void battleSpellCast(BattleSpellCast *sc);
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right
virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
virtual void battleSpellCast(const BattleSpellCast *sc);
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right
//virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
//
virtual void battleStackMoved(int ID, int dest, bool startMoving, bool endMoving);
virtual void battleStackAttacking(int ID, int dest);

View File

@ -45,11 +45,7 @@ template <typename ruleType, typename facts> template <typename cond> void Exper
++goalCounter;
}
}
matchedConditions = 0;
//modify set until something happens (hopefully!)
for (iF = factsToErase.begin(); iF != factsToErase.end(); iF++)
factList.erase(knowledge.find(*iF));
factsToErase.clear(); //TODO: what if fact is remembered by rule, yet already erased?
for (iF = factsToAdd.begin(); iF != factsToAdd.end(); iF++)
factList.insert(*iF);
if (factsToAdd.size())
@ -58,6 +54,9 @@ template <typename ruleType, typename facts> template <typename cond> void Exper
factWasAdded = true;
}
}
for (iF = factsToErase.begin(); iF != factsToErase.end(); iF++) //remove facts discarded in this run
factList.erase(knowledge.find(*iF));
factsToErase.clear(); //erase only after all rules had a chance to trigger
for (ir = rulesToErase.begin(); ir != rulesToErase.end(); ir++)
knowledge.erase(knowledge.find(*ir));
rulesToErase.clear();
@ -89,13 +88,13 @@ void BonusRule::fireRule()
case BonusCondition::duration:
if (!it->first.functor(it->second->object->duration, it->first.value)) return;
break;
case BonusCondition::source:
case BonusCondition::source: //likely to handle by selector
if (!it->first.functor(it->second->object->source, it->first.value)) return;
break;
case BonusCondition::id:
if (!it->first.functor(it->second->object->id, it->first.value)) return;
break;
case BonusCondition::valType:
case BonusCondition::valType: //ever needed?
if (!it->first.functor(it->second->object->valType, it->first.value)) return;
break;
case BonusCondition::additionalInfo:
@ -110,12 +109,18 @@ void BonusRule::fireRule()
}
//TODO: add new fact or modify existing one
}
//TODO: find out why it does not compile
//template <typename input, typename conType> void Rule<input, conType>::refreshRule(std::set<conType> &conditionSet)
//{
// cons.clear();
// for (std::set<conType>::iterator it = conditionSet.begin(); it != conditionSet.end(); it++)
// cons.insert(std::make_pair<conType,input*>(*it, NULL)); //pointer to condition and null fact
//}
//template <typename input, typename conType> void Rule<input, conType>::refreshRule()
//{
// for (std::set<std::pair<conType, input*>>::iterator it = cons.begin(); it != cons.end(); it++)
// *it->second = NULL;
//}
bool BonusCondition::matchesFact(Bonus &fact)
{
if (object(fact)) //Bonus(fact) matches local Selector(object)

View File

@ -53,7 +53,7 @@ public:
};
template <typename input> class condition
{//determines selected object parameter with value using functor
{//compares selected object parameter with value using functor. universal logic handler
public:
input object; //what the fact is, or what it's like (CSelector)
si32 value;
@ -74,9 +74,13 @@ public:
protected:
std::set<std::pair<conType, input*>> cons; //conditions and matching facts
input decision;
virtual void canBeFired(); //if this data makes any sense for rule
virtual void fireRule(std::set<input*> &feed);
virtual void canBeFired(); //if this data makes any sense for rule - type check
virtual bool checkCondition(); //if condition is true or false
virtual bool checkCondition(std::set<input*> &feed);
virtual void fireRule(); //use paired conditions and facts by default
virtual void fireRule(ExpertSystemShell<input, conType> &system);
virtual void fireRule(std::set<input*> &feed);
virtual void refreshRule();
virtual void refreshRule(std::set<conType> &conditionSet); //in case conditions were erased
public:
Rule(){fired = false; conditionCounter = 0; decision = NULL;};
@ -124,21 +128,56 @@ public:
};
bool matchesFact(Bonus &fact);
};
class BonusHolder : public AIholder<Bonus>
{
public:
BonusHolder(Bonus &bonus){object = &bonus; aiValue = bonus.val;}
BonusHolder(Bonus &bonus, si32 val){object = &bonus; aiValue = val;}
};
class BonusRule : public Rule <BonusHolder, BonusCondition>
{
protected:
void fireRule();
};
bool greaterThan (int prop, si32 val)
inline bool greaterThan (int prop, si32 val)
{
if ((si32)prop > val)
return true;
return false;
}
}
inline bool lessThan (int prop, si32 val)
{
if ((si32)prop < val)
return true;
return false;
}
inline bool eqal (int prop, si32 val)
{
if ((si32)prop == val)
return true;
return false;
}
inline bool unequal (int prop, si32 val)
{
if ((si32)prop != val)
return true;
return false;
}
inline bool present (int prop, si32 val=0)
//inline bool present (int prop) //TODO: can we use function with less arguments?
{
return(prop); //unfixable warning :(
}
class KnowledgeHandler///I'd opt for one omniscent knowledge manager, so no templates here
{
public:
std::list<BonusRule> knowledge; //permanent storage of rules
void parseKnowledge(std::string &filename){};
void addKnowledge(ExpertSystemShell<BRule,Bonus> &expert);
void addFacts(ExpertSystemShell<BRule,Bonus> &expert);
};

View File

@ -42,6 +42,7 @@
#define CONSOLE_YELLOW FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
#define CONSOLE_WHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
#define CONSOLE_GRAY FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
#define CONSOLE_TEAL FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
#endif
TColor defColor;
@ -168,6 +169,9 @@ void CConsoleHandler::setColor(int level)
case 5:
color = CONSOLE_GRAY;
break;
case -2:
color = CONSOLE_TEAL;
break;
default:
color = defColor;
break;

View File

@ -111,17 +111,17 @@ public:
virtual void actionFinished(const BattleAction *action){};//occurs AFTER every action taken by any stack or by the hero
virtual void actionStarted(const BattleAction *action){};//occurs BEFORE every action taken by any stack or by the hero
virtual BattleAction activeStack(int stackID)=0; //called when it's turn of that stack
virtual void battleAttack(BattleAttack *ba){}; //called when stack is performing attack
virtual void battleStacksAttacked(std::vector<BattleStackAttacked> & bsa){}; //called when stack receives damage (after battleAttack())
virtual void battleEnd(BattleResult *br){};
virtual void battleAttack(const BattleAttack *ba){}; //called when stack is performing attack
virtual void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa){}; //called when stack receives damage (after battleAttack())
virtual void battleEnd(const BattleResult *br){};
virtual void battleResultsApplied(){}; //called when all effects of last battle are applied
virtual void battleNewRoundFirst(int round){}; //called at the beginning of each turn before changes are applied;
virtual void battleNewRound(int round){}; //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
virtual void battleStackMoved(int ID, int dest, int distance, bool end){};
virtual void battleSpellCast(BattleSpellCast *sc){};
virtual void battleStacksEffectsSet(SetStackEffect & sse){};//called when a specific effect is set to stacks
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning
virtual void battleSpellCast(const BattleSpellCast *sc){};
virtual void battleStacksEffectsSet(const SetStackEffect & sse){};//called when a specific effect is set to stacks
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
//virtual void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles){}; //called when battlefield is prepared, prior the battle beginning
virtual void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, si32 lifeDrainFrom){}; //called when stacks are healed / resurrected first element of pair - stack id, second - healed hp
virtual void battleNewStackAppeared(int stackID){}; //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
virtual void battleObstaclesRemoved(const std::set<si32> & removedObstacles){}; //called when a certain set of obstacles is removed from batlefield; IDs of them are given

View File

@ -2671,7 +2671,7 @@ void CBattleInterface::displayBattleFinished()
GH.pushInt(resWindow);
}
void CBattleInterface::spellCast(BattleSpellCast * sc)
void CBattleInterface::spellCast( const BattleSpellCast * sc )
{
const CSpell &spell = CGI->spellh->spells[sc->id];
@ -2820,7 +2820,7 @@ void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse)
void CBattleInterface::castThisSpell(int spellID)
{
BattleAction * ba = new BattleAction;
ba->actionType = 1;
ba->actionType = BattleAction::HERO_SPELL;
ba->additionalInfo = spellID; //spell number
ba->destinationTile = -1;
ba->stackNumber = (attackingHeroInstance->tempOwner == curInt->playerID) ? -1 : -2;
@ -3010,7 +3010,7 @@ void CBattleInterface::showAliveStack(const CStack *stack, SDL_Surface * to)
if(stack->count > 0 //don't print if stack is not alive
&& (!curInt->curAction
|| (curInt->curAction->stackNumber != ID //don't print if stack is currently taking an action
&& (curInt->curAction->actionType != 6 || stack->position != curInt->curAction->additionalInfo) //nor if it's an object of attack
&& (curInt->curAction->actionType != BattleAction::WALK_AND_ATTACK || stack->position != curInt->curAction->additionalInfo) //nor if it's an object of attack
&& (curInt->curAction->destinationTile != stack->position) //nor if it's on destination tile for current action
)
)
@ -3230,18 +3230,18 @@ void CBattleInterface::endAction(const BattleAction* action)
// {
// activate();
// }
if(action->actionType == 1)
if(action->actionType == BattleAction::HERO_SPELL)
{
if(action->side)
defendingHero->setPhase(0);
else
attackingHero->setPhase(0);
}
if(action->actionType == 2 && creAnims[action->stackNumber]->getType() != 2) //walk or walk & attack
if(action->actionType == BattleAction::WALK && creAnims[action->stackNumber]->getType() != 2) //walk or walk & attack
{
pendingAnims.push_back(std::make_pair(new CBattleMoveEnd(this, action->stackNumber, action->destinationTile), false));
}
if(action->actionType == 9) //catapult
if(action->actionType == BattleAction::CATAPULT) //catapult
{
}
queue->update();
@ -3283,11 +3283,11 @@ void CBattleInterface::startAction(const BattleAction* action)
}
else
{
assert(action->actionType == 1); //only cast spell is valid action without acting stack number
assert(action->actionType == BattleAction::HERO_SPELL); //only cast spell is valid action without acting stack number
}
if(action->actionType == 2
|| (action->actionType == 6 && action->destinationTile != stack->position))
if(action->actionType == BattleAction::WALK
|| (action->actionType == BattleAction::WALK_AND_ATTACK && action->destinationTile != stack->position))
{
moveStarted = true;
if(creAnims[action->stackNumber]->framesInGroup(20))
@ -3301,7 +3301,7 @@ void CBattleInterface::startAction(const BattleAction* action)
char txt[400];
if(action->actionType == 1) //when hero casts spell
if(action->actionType == BattleAction::HERO_SPELL) //when hero casts spell
{
if(action->side)
defendingHero->setPhase(4);
@ -3342,7 +3342,7 @@ void CBattleInterface::startAction(const BattleAction* action)
}
//displaying heal animation
if (action->actionType == 12)
if (action->actionType == BattleAction::STACK_HEAL)
{
displayEffect(50, action->destinationTile);
}

View File

@ -506,7 +506,7 @@ public:
void battleFinished(const BattleResult& br); //called when battle is finished - battleresult window should be printed
const BattleResult * bresult; //result of a battle; if non-zero then display when all animations end
void displayBattleFinished(); //displays battle result
void spellCast(BattleSpellCast * sc); //called when a hero casts a spell
void spellCast(const BattleSpellCast * sc); //called when a hero casts a spell
void battleStacksEffectsSet(const SetStackEffect & sse); //called when a specific effect is set to stacks
void castThisSpell(int spellID); //called when player has chosen a spell from spellbook
void displayEffect(ui32 effect, int destTile); //displays effect of a spell on the battlefield; affected: true - attacker. false - defender

View File

@ -75,7 +75,6 @@ Point screenLT = Point(0, 0); //position of top left corner of the screen
Point screenLTmax = Point(0, 0); //,maximal values for screenLT coordinates
static boost::thread *mainGUIThread;
SystemOptions GDefaultOptions;
VCMIDirs GVCMIDirs;
std::queue<SDL_Event*> events;
@ -428,6 +427,11 @@ void processCommand(const std::string &message)
{
gOnlyAI = true;
}
else if (cn == "ai")
{
VLC->IS_AI_ENABLED = !VLC->IS_AI_ENABLED;
tlog4 << "Current AI status: " << (VLC->IS_AI_ENABLED ? "enabled" : "disabled") << std::endl;
}
else if(cn == "mp" && adventureInt)
{
if(const CGHeroInstance *h = dynamic_cast<const CGHeroInstance *>(adventureInt->selection))

View File

@ -538,7 +538,7 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID,
}
}
void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side)
void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side)
{
if(LOCPLINT != this)
{ //another local interface should do this
@ -553,9 +553,6 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
GH.pushInt(battleInt);
}
void CPlayerInterface::battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles) //called when battlefield is prepared, prior the battle beginning
{
}
void CPlayerInterface::battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, si32 lifeDrainFrom)
{
@ -719,7 +716,7 @@ BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn
return ret;
}
void CPlayerInterface::battleEnd(BattleResult *br)
void CPlayerInterface::battleEnd(const BattleResult *br)
{
if(LOCPLINT != this)
{ //another local interface should do this
@ -740,7 +737,7 @@ void CPlayerInterface::battleStackMoved(int ID, int dest, int distance, bool end
boost::unique_lock<boost::recursive_mutex> un(*pim);
battleInt->stackMoved(ID, dest, end, distance);
}
void CPlayerInterface::battleSpellCast(BattleSpellCast *sc)
void CPlayerInterface::battleSpellCast( const BattleSpellCast *sc )
{
if(LOCPLINT != this)
{ //another local interface should do this
@ -750,7 +747,7 @@ void CPlayerInterface::battleSpellCast(BattleSpellCast *sc)
boost::unique_lock<boost::recursive_mutex> un(*pim);
battleInt->spellCast(sc);
}
void CPlayerInterface::battleStacksEffectsSet(SetStackEffect & sse)
void CPlayerInterface::battleStacksEffectsSet( const SetStackEffect & sse )
{
if(LOCPLINT != this)
{ //another local interface should do this
@ -760,7 +757,7 @@ void CPlayerInterface::battleStacksEffectsSet(SetStackEffect & sse)
boost::unique_lock<boost::recursive_mutex> un(*pim);
battleInt->battleStacksEffectsSet(sse);
}
void CPlayerInterface::battleStacksAttacked(std::vector<BattleStackAttacked> & bsa)
void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa)
{
if(LOCPLINT != this)
{ //another local interface should do this
@ -773,7 +770,7 @@ void CPlayerInterface::battleStacksAttacked(std::vector<BattleStackAttacked> & b
std::vector<SStackAttackedInfo> arg;
for(std::vector<BattleStackAttacked>::iterator i = bsa.begin(); i != bsa.end(); i++)
for(std::vector<BattleStackAttacked>::const_iterator i = bsa.begin(); i != bsa.end(); i++)
{
if(i->isEffect() && i->effect != 12) //and not armageddon
{
@ -793,7 +790,7 @@ void CPlayerInterface::battleStacksAttacked(std::vector<BattleStackAttacked> & b
battleInt->stacksAreAttacked(arg);
}
void CPlayerInterface::battleAttack(BattleAttack *ba)
void CPlayerInterface::battleAttack(const BattleAttack *ba)
{
if(LOCPLINT != this)
{ //another local interface should do this
@ -816,7 +813,7 @@ void CPlayerInterface::battleAttack(BattleAttack *ba)
if(ba->shot())
{
for(std::vector<BattleStackAttacked>::iterator i = ba->bsa.begin(); i != ba->bsa.end(); i++)
for(std::vector<BattleStackAttacked>::const_iterator i = ba->bsa.begin(); i != ba->bsa.end(); i++)
battleInt->stackIsShooting(ba->stackAttacking,cb->battleGetPos(i->stackAttacked), i->stackAttacked);
}
else

View File

@ -203,17 +203,16 @@ public:
void actionFinished(const BattleAction* action);//occurs AFTER action taken by active stack or by the hero
void actionStarted(const BattleAction* action);//occurs BEFORE action taken by active stack or by the hero
BattleAction activeStack(int stackID); //called when it's turn of that stack
void battleAttack(BattleAttack *ba); //stack performs attack
void battleEnd(BattleResult *br); //end of battle
void battleAttack(const BattleAttack *ba); //stack performs attack
void battleEnd(const BattleResult *br); //end of battle
//void battleResultQuited();
void battleNewRoundFirst(int round); //called at the beginning of each turn before changes are applied; used for HP regen handling
void battleNewRound(int round); //called at the beggining of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn
void battleStackMoved(int ID, int dest, int distance, bool end);
void battleSpellCast(BattleSpellCast *sc);
void battleStacksEffectsSet(SetStackEffect & sse); //called when a specific effect is set to stacks
void battleStacksAttacked(std::vector<BattleStackAttacked> & bsa);
void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, CGHeroInstance *hero1, CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right
void battlefieldPrepared(int battlefieldType, std::vector<CObstacle*> obstacles); //called when battlefield is prepared, prior the battle beginning
void battleSpellCast(const BattleSpellCast *sc);
void battleStacksEffectsSet(const SetStackEffect & sse); //called when a specific effect is set to stacks
void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa);
void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side); //called by engine when battle starts; side=0 - left, side=1 - right
void battleStacksHealedRes(const std::vector<std::pair<ui32, ui32> > & healedStacks, bool lifeDrain, si32 lifeDrainFrom); //called when stacks are healed / resurrected
void battleNewStackAppeared(int stackID); //not called at the beginning of a battle or by resurrection; called eg. when elemental is summoned
void battleObstaclesRemoved(const std::set<si32> & removedObstacles); //called when a certain set of obstacles is removed from batlefield; IDs of them are given

View File

@ -1676,7 +1676,7 @@ void CRecruitmentWindow::Buy()
int crid = creatures[which].ID,
dstslot = dst-> getSlotFor(crid);
if(dstslot < 0) //no available slot
if(dstslot < 0 && !vstd::contains(CGI->arth->bigArtifacts,CGI->arth->convertMachineID(crid, true))) //no available slot
{
std::string txt;
if(dst->ID == HEROI_TYPE)

View File

@ -358,6 +358,7 @@ extern DLL_EXPORT CLogger tlog2; //magenta - major warnings
extern DLL_EXPORT CLogger tlog3; //yellow - minor warnings
extern DLL_EXPORT CLogger tlog4; //white - detailed log info
extern DLL_EXPORT CLogger tlog5; //gray - minor log info
extern DLL_EXPORT CLogger tlog6; //teal - AI info
//XXX pls dont - 'debug macros' are usually more trouble than it's worth
#define HANDLE_EXCEPTION \

View File

@ -15,6 +15,10 @@ struct BattleAction
{
ui8 side; //who made this action: false - left, true - right player
ui32 stackNumber;//stack ID, -1 left hero, -2 right hero,
enum ActionType
{
NO_ACTION = 0, HERO_SPELL, WALK, DEFEND, RETREAT, SURRENDER, WALK_AND_ATTACK, SHOOT, WAIT, CATAPULT, MONSTER_SPELL, BAD_MORALE, STACK_HEAL
};
ui8 actionType; // 0 = No action; 1 = Hero cast a spell 2 = Walk 3 = Defend 4 = Retreat from the battle
//5 = Surrender 6 = Walk and Attack 7 = Shoot 8 = Wait 9 = Catapult
//10 = Monster casts a spell (i.e. Faerie Dragons) 11 - Bad morale freeze 12 - stacks heals another stack

View File

@ -365,7 +365,7 @@ bool CCreatureSet::hasStackAtSlot(TSlot slot) const
CCreatureSet & CCreatureSet::operator=(const CCreatureSet&cs)
{
assert(0);
return cs;
return *this;
}
CStackInstance::CStackInstance()

View File

@ -1177,19 +1177,19 @@ struct BattleAttack : public CPackForClient//3006
ui32 stackAttacking;
ui8 flags;
bool shot()//distance attack - decrease number of shots
bool shot() const//distance attack - decrease number of shots
{
return flags & 1;
}
bool counter()//is it counterattack?
bool counter() const//is it counterattack?
{
return flags & 2;
}
bool lucky()
bool lucky() const
{
return flags & 4;
}
bool unlucky()
bool unlucky() const
{
//TODO: support?
return flags & 8;

View File

@ -972,18 +972,20 @@ DLL_EXPORT void StartAction::applyGs( CGameState *gs )
{
CStack *st = gs->curB->getStack(ba.stackNumber);
if(ba.actionType != 1) //don't check for stack if it's custom action by hero
if(ba.actionType != BattleAction::HERO_SPELL) //don't check for stack if it's custom action by hero
assert(st);
switch(ba.actionType)
{
case 3:
case BattleAction::DEFEND:
st->state.insert(DEFENDING);
break;
case 8:
case BattleAction::WAIT:
st->state.insert(WAITING);
return;
case 0: case 2: case 6: case 7: case 9: case 10: case 11: case 12:
case BattleAction::NO_ACTION: case BattleAction::WALK: case BattleAction::WALK_AND_ATTACK:
case BattleAction::SHOOT: case BattleAction::CATAPULT: case BattleAction::MONSTER_SPELL:
case BattleAction::BAD_MORALE: case BattleAction::STACK_HEAL:
st->state.insert(MOVED);
break;
}

View File

@ -34,6 +34,7 @@ DLL_EXPORT CLogger tlog2(2);
DLL_EXPORT CLogger tlog3(3);
DLL_EXPORT CLogger tlog4(4);
DLL_EXPORT CLogger tlog5(5);
DLL_EXPORT CLogger tlog6(-2);
DLL_EXPORT CConsoleHandler *console = NULL;
DLL_EXPORT std::ostream *logfile = NULL
@ -205,6 +206,8 @@ void LibClasses::init()
spellh = new CSpellHandler;
spellh->loadSpells();
tlog0<<"\tSpell handler: "<<pomtime.getDif()<<std::endl;
IS_AI_ENABLED = true;
}
void LibClasses::clear()

View File

@ -26,6 +26,7 @@ class CGeneralTextHandler;
class DLL_EXPORT LibClasses
{
public:
bool IS_AI_ENABLED; //VLC is teh only object visible from both CMT and GeniusAI
CArtHandler * arth;
CHeroHandler * heroh;
CCreatureHandler * creh;
@ -45,7 +46,7 @@ public:
void callWhenDeserializing(); //should be called only by serialize !!!
template <typename Handler> void serialize(Handler &h, const int version)
{
h & heroh & arth & creh & townh & objh & dobjinfo & buildh & spellh;
h & heroh & arth & creh & townh & objh & dobjinfo & buildh & spellh & IS_AI_ENABLED;;
if(!h.saving)
{
callWhenDeserializing();

View File

@ -346,16 +346,15 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
setupBattle(curB, tile, army1, army2, hero1, hero2, creatureBank, town); //initializes stacks, places creatures on battlefield, blocks and informs player interfaces
}
NEW_ROUND;
//TODO: pre-tactic stuff, call scripts etc.
//tactic round
{
NEW_ROUND;
if( (hero1 && hero1->getSecSkillLevel(19)>0) ||
( hero2 && hero2->getSecSkillLevel(19)>0) )//someone has tactics
{
//TODO: tactic round (round -1)
NEW_ROUND;
}
}
@ -401,7 +400,7 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
{
//unit loses its turn - empty freeze action
BattleAction ba;
ba.actionType = 11;
ba.actionType = BattleAction::BAD_MORALE;
ba.additionalInfo = 1;
ba.side = !next->attackerOwned;
ba.stackNumber = next->ID;
@ -418,7 +417,7 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
if(attackInfo.first != NULL)
{
BattleAction attack;
attack.actionType = 6;
attack.actionType = BattleAction::WALK_AND_ATTACK;
attack.side = !next->attackerOwned;
attack.stackNumber = next->ID;
@ -429,6 +428,10 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
checkForBattleEnd(stacks);
}
else
{
makeStackDoNothing(next);
}
continue;
}
@ -438,7 +441,7 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
|| (next->getCreature()->idNumber == 146 && (!curOwner || curOwner->getSecSkillLevel(20) == 0))) //ballista, hero has no artillery
{
BattleAction attack;
attack.actionType = 7;
attack.actionType = BattleAction::SHOOT;
attack.side = !next->attackerOwned;
attack.stackNumber = next->ID;
@ -463,7 +466,7 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
static const int wallHexes[] = {50, 183, 182, 130, 62, 29, 12, 95};
attack.destinationTile = wallHexes[ rand()%ARRAY_COUNT(wallHexes) ];
attack.actionType = 9;
attack.actionType = BattleAction::CATAPULT;
attack.additionalInfo = 0;
attack.side = !next->attackerOwned;
attack.stackNumber = next->ID;
@ -489,21 +492,15 @@ void CGameHandler::startBattle(const CArmedInstance *army1, const CArmedInstance
if(possibleStacks.size() == 0)
{
//nothing to heal
BattleAction doNothing;
doNothing.actionType = 0;
doNothing.additionalInfo = 0;
doNothing.destinationTile = -1;
doNothing.side = !next->attackerOwned;
doNothing.stackNumber = next->ID;
sendAndApply(&StartAction(doNothing));
sendAndApply(&EndAction());
makeStackDoNothing(next);
continue;
}
else
{
//heal random creature
const CStack * toBeHealed = possibleStacks[ rand()%possibleStacks.size() ];
heal.actionType = 12;
heal.actionType = BattleAction::STACK_HEAL;
heal.additionalInfo = 0;
heal.destinationTile = toBeHealed->position;
heal.side = !next->attackerOwned;
@ -5225,6 +5222,18 @@ bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * h
return true;
}
void CGameHandler::makeStackDoNothing(const CStack * next)
{
BattleAction doNothing;
doNothing.actionType = 0;
doNothing.additionalInfo = 0;
doNothing.destinationTile = -1;
doNothing.side = !next->attackerOwned;
doNothing.stackNumber = next->ID;
sendAndApply(&StartAction(doNothing));
sendAndApply(&EndAction());
}
bool CGameHandler::insertNewStack(const StackLocation &sl, const CCreature *c, TQuantity count)
{
if(sl.army->hasStackAtSlot(sl.slot))

View File

@ -76,6 +76,8 @@ public:
class CGameHandler : public IGameCallback
{
private:
void makeStackDoNothing(const CStack * next);
public:
CVCMIServer *s;
std::map<int,CConnection*> connections; //player color -> connection to client with interface of that player
@ -237,3 +239,5 @@ public:
};
#endif // __CGAMEHANDLER_H__
void makeStackDoNothing();