mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
[programming challenge] Improved spell handling.
This commit is contained in:
parent
67571d5823
commit
2a18d2efcc
@ -8,6 +8,8 @@
|
||||
#include <algorithm>
|
||||
//#include <boost/thread.hpp>
|
||||
#include "../../lib/CHeroHandler.h"
|
||||
#include "../../lib/VCMI_Lib.h"
|
||||
#include "../../lib/CSpellHandler.h"
|
||||
|
||||
CBattleCallback * cbc;
|
||||
|
||||
@ -98,6 +100,8 @@ static bool willSecondHexBlockMoreEnemyShooters(const THex &h1, const THex &h2)
|
||||
return shooters[0] < shooters[1];
|
||||
}
|
||||
|
||||
|
||||
|
||||
BattleAction CStupidAI::activeStack( const CStack * stack )
|
||||
{
|
||||
//boost::this_thread::sleep(boost::posix_time::seconds(2));
|
||||
@ -106,6 +110,14 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
|
||||
std::vector<int> dists = cb->battleGetDistances(stack);
|
||||
std::vector<EnemyInfo> enemiesShootable, enemiesReachable, enemiesUnreachable;
|
||||
|
||||
// const CStack *firstEnemy = cb->battleGetStacks(CBattleCallback::ONLY_ENEMY).front();
|
||||
// if(cb->battleCanCastThisSpell(VLC->spellh->spells[Spells::FORGETFULNESS]) == SpellCasting::OK)
|
||||
// castSpell(Spells::FORGETFULNESS, firstEnemy->position);
|
||||
const CStack *firstEnemy = cb->battleGetStacks(CBattleCallback::ONLY_MINE).front();
|
||||
if(cb->battleCanCastThisSpell(VLC->spellh->spells[Spells::AIR_SHIELD]) == SpellCasting::OK)
|
||||
castSpell(Spells::AIR_SHIELD, firstEnemy->position);
|
||||
|
||||
|
||||
BOOST_FOREACH(const CStack *s, cb->battleGetStacks(CBattleCallback::ONLY_ENEMY))
|
||||
{
|
||||
if(cb->battleCanShoot(stack, s->position))
|
||||
@ -295,3 +307,29 @@ void CStupidAI::printOpeningReport()
|
||||
% (i+1) % s->count % s->getCreature()->namePl % s->Attack() % s->Defense() % s->MaxHealth() % s->getMinDamage() % s->getMaxDamage();
|
||||
}
|
||||
}
|
||||
|
||||
void CStupidAI::castSpell(int spellID, int destinationTile, bool safe/* = true*/)
|
||||
{
|
||||
const CGHeroInstance *h = cb->battleGetFightingHero(side);
|
||||
if(!h)
|
||||
{
|
||||
tlog1 << "A hero is required for casting spells!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
SpellCasting::ESpellCastProblem canCast = safe ? cb->battleCanCastThisSpell(VLC->spellh->spells[spellID]) : SpellCasting::OK;
|
||||
if(canCast != SpellCasting::OK)
|
||||
{
|
||||
tlog1 << "Spell cannot be cast (problem=" << canCast << ")!\n";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
BattleAction ba;
|
||||
ba.actionType = BattleAction::HERO_SPELL;
|
||||
ba.destinationTile = destinationTile;
|
||||
ba.side = side;
|
||||
ba.stackNumber = -(side+1); //-1 dla lewego bohatera, -2 dla prawego
|
||||
ba.additionalInfo = spellID;
|
||||
cb->battleMakeAction(&ba);
|
||||
}
|
@ -33,5 +33,6 @@ public:
|
||||
void battleStacksRemoved(const BattleStacksRemoved & bsr) OVERRIDE; //called when certain stack is completely removed from battlefield
|
||||
|
||||
BattleAction goTowards(const CStack * stack, THex hex );
|
||||
void castSpell(int spellID, int destinationTile, bool safe = true);
|
||||
};
|
||||
|
||||
|
@ -58,9 +58,10 @@ struct CheckTime
|
||||
|
||||
//all ms
|
||||
const int PROCESS_INFO_TIME = 5;
|
||||
const int MAKE_DECIDION_TIME = 125;
|
||||
const int MEASURE_MARGIN = 1;
|
||||
const int HANGUP_TIME = 50;
|
||||
const int MAKE_DECIDION_TIME = 150;
|
||||
const int MEASURE_MARGIN = 3;
|
||||
const int HANGUP_TIME = 250;
|
||||
const int CONSTRUCT_TIME = 50;
|
||||
const int STARTUP_TIME = 100;
|
||||
|
||||
void postInfoCall(int timeUsed);
|
||||
@ -68,6 +69,7 @@ void postDecisionCall(int timeUsed, const std::string &text = "AI was thinking o
|
||||
|
||||
struct Bomb
|
||||
{
|
||||
std::string txt;
|
||||
int armed;
|
||||
|
||||
void run(int time)
|
||||
@ -76,13 +78,15 @@ struct Bomb
|
||||
if(armed)
|
||||
{
|
||||
tlog1 << "BOOOM! The bomb exploded! AI was thinking for too long!\n";
|
||||
if(txt.size())
|
||||
tlog1 << "Bomb description: " << txt << std::endl;;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
Bomb(int timer)
|
||||
Bomb(int timer, const std::string &TXT = "") : txt(TXT)
|
||||
{
|
||||
boost::thread t(&Bomb::run, this, timer);
|
||||
t.detach();
|
||||
|
@ -105,7 +105,8 @@ void CClient::requestMoveFromAIWorker(const CStack *s)
|
||||
|
||||
try
|
||||
{
|
||||
Bomb *b = new Bomb(MAKE_DECIDION_TIME + HANGUP_TIME);
|
||||
boost::shared_lock<boost::shared_mutex> shl(*gs->mx);
|
||||
Bomb *b = new Bomb(MAKE_DECIDION_TIME + HANGUP_TIME, "activeStack timer");
|
||||
CheckTime timer;
|
||||
ba = ai->activeStack(s);
|
||||
postDecisionCall(timer.timeSinceStart());
|
||||
|
@ -36,13 +36,13 @@ void postDecisionCall(int timeUsed, const std::string &text/* = "AI was thinking
|
||||
//awaiting variadic templates...
|
||||
//
|
||||
|
||||
#define BATTLE_INTERFACE_CALL_IF_PRESENT_WITH_TIME_LIMIT(TIME_LIMIT, function, ...) \
|
||||
#define BATTLE_INTERFACE_CALL_IF_PRESENT_WITH_TIME_LIMIT(TIME_LIMIT, txt, function, ...) \
|
||||
do \
|
||||
{ \
|
||||
int timeUsed = 0; \
|
||||
if(cl->ai) \
|
||||
{ \
|
||||
Bomb *b = new Bomb(TIME_LIMIT + HANGUP_TIME); \
|
||||
Bomb *b = new Bomb(TIME_LIMIT + HANGUP_TIME,txt);\
|
||||
CheckTime pr; \
|
||||
cl->ai->function(__VA_ARGS__); \
|
||||
postInfoCall(pr.timeSinceStart(), TIME_LIMIT); \
|
||||
@ -51,7 +51,7 @@ void postDecisionCall(int timeUsed, const std::string &text/* = "AI was thinking
|
||||
} while(0)
|
||||
|
||||
#define BATTLE_INTERFACE_CALL_IF_PRESENT(function,...) \
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_WITH_TIME_LIMIT(PROCESS_INFO_TIME, function, __VA_ARGS__)
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_WITH_TIME_LIMIT(PROCESS_INFO_TIME, "process info timer", function, __VA_ARGS__)
|
||||
|
||||
#define UNEXPECTED_PACK assert(0)
|
||||
|
||||
@ -282,7 +282,7 @@ void GarrisonDialog::applyCl(CClient *cl)
|
||||
|
||||
void BattleStart::applyCl( CClient *cl )
|
||||
{
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_WITH_TIME_LIMIT(STARTUP_TIME, battleStart, info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], cl->color);
|
||||
BATTLE_INTERFACE_CALL_IF_PRESENT_WITH_TIME_LIMIT(STARTUP_TIME, "battleStart timer", battleStart, info->belligerents[0], info->belligerents[1], info->tile, info->heroes[0], info->heroes[1], cl->color);
|
||||
}
|
||||
|
||||
void BattleNextRound::applyFirstCl(CClient *cl)
|
||||
|
@ -89,7 +89,7 @@ int main(int argc, char** argv)
|
||||
tlog0 << "Cbc created\n";
|
||||
if(battleAIName.size())
|
||||
{
|
||||
Bomb *b = new Bomb(55 + HANGUP_TIME);
|
||||
Bomb *b = new Bomb(CONSTRUCT_TIME + 5 + HANGUP_TIME, "startup timer");
|
||||
CheckTime timer;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
cl.ai = CDynLibHandler::getNewBattleAI(battleAIName);
|
||||
|
@ -976,6 +976,17 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
|
||||
for(int i = 0; i < ss.heroPrimSkills.size(); i++)
|
||||
h->pushPrimSkill(i, ss.heroPrimSkills[i]);
|
||||
|
||||
if(ss.spells.size())
|
||||
{
|
||||
h->putArtifact(Arts::SPELLBOOK, CArtifactInstance::createNewArtifactInstance(0));
|
||||
BOOST_FOREACH(si32 spell, ss.spells)
|
||||
h->spells.insert(spell);
|
||||
}
|
||||
|
||||
typedef const std::pair<si32, si8> &TSecSKill;
|
||||
BOOST_FOREACH(TSecSKill secSkill, ss.heroSecSkills)
|
||||
h->setSecSkillLevel((CGHeroInstance::SecondarySkill)secSkill.first, secSkill.second, 1);
|
||||
|
||||
h->initHero(h->subID);
|
||||
obj->initObj();
|
||||
}
|
||||
@ -2832,6 +2843,14 @@ DuelParameters DuelParameters::fromJSON(const std::string &fname)
|
||||
BOOST_FOREACH(const JsonNode &n, n["heroPrimSkills"].Vector())
|
||||
ss.heroPrimSkills.push_back(n.Float());
|
||||
|
||||
BOOST_FOREACH(const JsonNode &skillNode, n["heroSecSkills"].Vector())
|
||||
{
|
||||
std::pair<si32, si8> secSkill;
|
||||
secSkill.first = skillNode.Vector()[0].Float();
|
||||
secSkill.second = skillNode.Vector()[1].Float();
|
||||
ss.heroSecSkills.push_back(secSkill);
|
||||
}
|
||||
|
||||
assert(ss.heroPrimSkills.empty() || ss.heroPrimSkills.size() == PRIMARY_SKILLS);
|
||||
|
||||
if(ss.heroId != -1)
|
||||
|
@ -298,6 +298,7 @@ struct DLL_EXPORT DuelParameters
|
||||
|
||||
si32 heroId; //-1 if none
|
||||
std::vector<si32> heroPrimSkills; //may be empty
|
||||
std::vector<std::pair<si32, si8> > heroSecSkills; //may be empty; pairs <id, level>, level [0-3]
|
||||
std::set<si32> spells;
|
||||
|
||||
SideSettings();
|
||||
|
@ -53,7 +53,27 @@ public:
|
||||
|
||||
namespace Spells
|
||||
{
|
||||
enum {SUMMON_BOAT=0, SCUTTLE_BOAT, VISIONS, VIEW_EARTH, DISGUISE, VIEW_AIR, FLY, WATER_WALK, DIMENSION_DOOR, TOWN_PORTAL};
|
||||
enum {SUMMON_BOAT=0, SCUTTLE_BOAT, VISIONS, VIEW_EARTH, DISGUISE, VIEW_AIR, FLY, WATER_WALK, DIMENSION_DOOR, TOWN_PORTAL,
|
||||
|
||||
|
||||
QUICKSAND=10, LAND_MINE=11, FORCE_FIELD=12, FIRE_WALL=13, EARTHQUAKE=14,
|
||||
MAGIC_ARROW=15, ICE_BOLT=16, LIGHTNING_BOLT=17, IMPLOSION=18,
|
||||
CHAIN_LIGHTNING=19, FROST_RING=20, FIREBALL=21, INFERNO=22,
|
||||
METEOR_SHOWER=23, DEATH_RIPPLE=24, DESTROY_UNDEAD=25, ARMAGEDDON=26,
|
||||
SHIELD=27, AIR_SHIELD=28, FIRE_SHIELD=29, PROTECTION_FROM_AIR=30,
|
||||
PROTECTION_FROM_FIRE=31, PROTECTION_FROM_WATER=32,
|
||||
PROTECTION_FROM_EARTH=33, ANTI_MAGIC=34, DISPEL=35, MAGIC_MIRROR=36,
|
||||
CURE=37, RESURRECTION=38, ANIMATE_DEAD=39, SACRIFICE=40, BLESS=41,
|
||||
CURSE=42, BLOODLUST=43, PRECISION=44, WEAKNESS=45, STONE_SKIN=46,
|
||||
DISRUPTING_RAY=47, PRAYER=48, MIRTH=49, SORROW=50, FORTUNE=51,
|
||||
MISFORTUNE=52, HASTE=53, SLOW=54, SLAYER=55, FRENZY=56,
|
||||
TITANS_LIGHTNING_BOLT=57, COUNTERSTRIKE=58, BERSERK=59, HYPNOTIZE=60,
|
||||
FORGETFULNESS=61, BLIND=62, TELEPORT=63, REMOVE_OBSTACLE=64, CLONE=65,
|
||||
SUMMON_FIRE_ELEMENTAL=66, SUMMON_EARTH_ELEMENTAL=67, SUMMON_WATER_ELEMENTAL=68, SUMMON_AIR_ELEMENTAL=69,
|
||||
|
||||
STONE_GAZE=70, POISON=71, BIND=72, DISEASE=73, PARALYZE=74, AGE=75, DEATH_CLOUD=76, THUNDERBOLT=77,
|
||||
DISPEL_HELPFUL_SPELLS=78, DEATH_STARE=79, ACID_BREATH_DEFENSE=80, ACID_BREATH_DAMAGE=81
|
||||
};
|
||||
}
|
||||
|
||||
bool DLL_EXPORT isInScreenRange(const int3 ¢er, const int3 &pos); //for spells like Dimension Door
|
||||
|
Loading…
Reference in New Issue
Block a user