/* read element to body */ bool AGG::File::Read(const std::string & key, std::vector<u8> & body) { const FAT & f = fat[key]; if(IS_DEBUG(DBG_ENGINE, DBG_TRACE)) f.Dump(key); if(f.size) { DEBUG(DBG_ENGINE , DBG_TRACE, "AGG::File::Read: " << key); body.resize(f.size); stream->seekg(f.offset, std::ios_base::beg); stream->read(reinterpret_cast<char*>(&body[0]), f.size); return true; } return false; }
bool Algorithm::PathFind(std::list<Route::Step> *result, const s32 from, const s32 to, const u16 limit, const Heroes *hero) { const u8 pathfinding = (hero ? hero->GetLevelSkill(Skill::Secondary::PATHFINDING) : Skill::Level::NONE); s32 cur = from; s32 alt = 0; s32 tmp = 0; std::map<s32, cell_t> list; std::map<s32, cell_t>::iterator it1 = list.begin(); std::map<s32, cell_t>::iterator it2 = list.end(); Direction::vector_t direct = Direction::CENTER; list[cur].cost_g = 0; list[cur].cost_t = 0; list[cur].parent = -1; list[cur].open = false; while(cur != to) { LocalEvent::Get().HandleEvents(false); for(direct = Direction::TOP_LEFT; direct != Direction::CENTER; ++direct) { if(Maps::isValidDirection(cur, direct)) { tmp = Maps::GetDirectionIndex(cur, direct); if(list[tmp].open) { // new if(-1 == list[tmp].parent) { const u16 costg = Maps::Ground::GetPenalty(tmp, direct, pathfinding); if(MAXU16 == costg) continue; if((list[cur].passbl & direct) || PassableFromToTile(hero, cur, tmp, direct, to)) { list[cur].passbl |= direct; cell_t & cell = list[tmp]; cell.cost_g = costg; cell.parent = cur; cell.open = true; cell.cost_t = cell.cost_g + list[cur].cost_t; cell.cost_d = 50 * Maps::GetApproximateDistance(tmp, to); } } // check alt else { alt = Maps::Ground::GetPenalty(cur, direct, pathfinding); if(list[tmp].cost_t > list[cur].cost_t + alt && ((list[cur].passbl & direct) || PassableFromToTile(hero, cur, tmp, direct, to))) { list[cur].passbl |= direct; list[tmp].parent = cur; list[tmp].cost_g = alt; list[tmp].cost_t = list[cur].cost_t + alt; } } } } } list[cur].open = false; it1 = list.begin(); alt = -1; tmp = MAXU16; DEBUG(DBG_OTHER, DBG_TRACE, "route, from: " << cur); // find minimal cost for(; it1 != it2; ++it1) if((*it1).second.open) { const cell_t & cell2 = (*it1).second; #ifdef WITH_DEBUG if(IS_DEBUG(DBG_OTHER, DBG_TRACE) && cell2.cost_g != MAXU16) { direct = Direction::Get(cur, (*it1).first); if(Direction::UNKNOWN != direct) { VERBOSE("\t\tdirect: " << Direction::String(direct) << ", index: " << (*it1).first << ", cost g: " << cell2.cost_g << ", cost t: " << cell2.cost_t << ", cost d: " << cell2.cost_d); } } #endif if(cell2.cost_t + cell2.cost_d < tmp) { tmp = cell2.cost_t + cell2.cost_d; alt = (*it1).first; } } // not found, and exception if(MAXU16 == tmp || -1 == alt || (limit && GetCurrentLength(list, cur) > limit)) break; #ifdef WITH_DEBUG else DEBUG(DBG_OTHER, DBG_TRACE, "select: " << alt); #endif cur = alt; } // save path if(cur == to) { while(cur != from) { if(-1 == list[cur].parent) break; alt = cur; cur = list[alt].parent; if(result) result->push_front(Route::Step(cur, Direction::Get(cur, alt), list[alt].cost_g)); } return true; } DEBUG(DBG_OTHER, DBG_TRACE, "not found" << ", from:" << from << ", to: " << to); list.clear(); return false; }
Battle::Result Battle::Loader(Army & army1, Army & army2, s32 mapsindex) { const Settings & conf = Settings::Get(); // pre battle army1 if(army1.GetCommander()) { if(CONTROL_AI & army1.GetControl()) AI::HeroesPreBattle(*army1.GetCommander()); else army1.GetCommander()->ActionPreBattle(); } // pre battle army2 if(army2.GetCommander()) { if(CONTROL_AI & army2.GetControl()) AI::HeroesPreBattle(*army2.GetCommander()); else army2.GetCommander()->ActionPreBattle(); } if(conf.ExtPocketLowMemory()) AGG::ICNRegistryEnable(true); AGG::ResetMixer(); bool local = (CONTROL_HUMAN & army1.GetControl()) || (CONTROL_HUMAN & army2.GetControl()) || IS_DEBUG(DBG_BATTLE, DBG_TRACE); Arena arena(army1, army2, mapsindex, local); DEBUG(DBG_BATTLE, DBG_INFO, "army1 " << army1.String()); DEBUG(DBG_BATTLE, DBG_INFO, "army2 " << army2.String()); while(arena.BattleValid()) arena.Turns(); const Result & result = arena.GetResult(); AGG::ResetMixer(); HeroBase* hero_wins = (result.army1 & RESULT_WINS ? army1.GetCommander() : (result.army2 & RESULT_WINS ? army2.GetCommander() : NULL)); HeroBase* hero_loss = (result.army1 & RESULT_LOSS ? army1.GetCommander() : (result.army2 & RESULT_LOSS ? army2.GetCommander() : NULL)); const u8 loss_result = result.army1 & RESULT_LOSS ? result.army1 : result.army2; if(local) { // fade arena arena.FadeArena(); // dialog summary arena.DialogBattleSummary(result); } // save count troop arena.GetForce1().SyncArmyCount(); arena.GetForce2().SyncArmyCount(); // after battle army1 if(army1.GetCommander()) { if(CONTROL_AI & army1.GetControl()) AI::HeroesAfterBattle(*army1.GetCommander()); else army1.GetCommander()->ActionAfterBattle(); } // after battle army2 if(army2.GetCommander()) { if(CONTROL_AI & army2.GetControl()) AI::HeroesAfterBattle(*army2.GetCommander()); else army2.GetCommander()->ActionAfterBattle(); } // pickup artifact if(hero_wins && hero_loss && !((RESULT_RETREAT | RESULT_SURRENDER) & loss_result) && Skill::Primary::HEROES == hero_wins->GetType() && Skill::Primary::HEROES == hero_loss->GetType()) PickupArtifactsAction(*hero_wins, *hero_loss, (CONTROL_HUMAN & hero_wins->GetControl())); // eagle eye capability if(hero_wins && hero_loss && hero_wins->GetLevelSkill(Skill::Secondary::EAGLEEYE) && Skill::Primary::HEROES == hero_loss->GetType()) EagleEyeSkillAction(*hero_wins, arena.GetUsageSpells(), (CONTROL_HUMAN & hero_wins->GetControl())); // necromancy capability if(hero_wins && hero_wins->GetLevelSkill(Skill::Secondary::NECROMANCY)) NecromancySkillAction(*hero_wins, result.killed, (CONTROL_HUMAN & hero_wins->GetControl())); DEBUG(DBG_BATTLE, DBG_INFO, "army1 " << army1.String()); DEBUG(DBG_BATTLE, DBG_INFO, "army2 " << army1.String()); // update army if(army1.GetCommander() && Skill::Primary::HEROES == army1.GetCommander()->GetType()) { // hard reset army if(!army1.isValid() || (result.army1 & RESULT_RETREAT)) army1.Reset(false); } // update army if(army2.GetCommander() && Skill::Primary::HEROES == army2.GetCommander()->GetType()) { // hard reset army if(!army2.isValid() || (result.army2 & RESULT_RETREAT)) army2.Reset(false); } if(conf.ExtPocketLowMemory()) { AGG::ICNRegistryEnable(false); AGG::ICNRegistryFreeObjects(); } DEBUG(DBG_BATTLE, DBG_INFO, "army1: " << (result.army1 & RESULT_WINS ? "wins" : "loss") << ", army2: " << (result.army2 & RESULT_WINS ? "wins" : "loss")); return result; }
Battle::Result Battle::Loader(Army & army1, Army & army2, s32 mapsindex) { // pre battle army1 if(army1.GetCommander()) { if(army1.GetCommander()->isCaptain()) army1.GetCommander()->ActionPreBattle(); else if(army1.isControlAI()) AI::HeroesPreBattle(*army1.GetCommander()); else army1.GetCommander()->ActionPreBattle(); } // pre battle army2 if(army2.GetCommander()) { if(army2.GetCommander()->isCaptain()) army2.GetCommander()->ActionPreBattle(); else if(army2.isControlAI()) AI::HeroesPreBattle(*army2.GetCommander()); else army2.GetCommander()->ActionPreBattle(); } AGG::ResetMixer(); bool local = army1.isControlHuman() || army2.isControlHuman(); #ifdef DEBUG if(IS_DEBUG(DBG_BATTLE, DBG_TRACE)) local = true; #endif Arena arena(army1, army2, mapsindex, local); DEBUG(DBG_BATTLE, DBG_INFO, "army1 " << army1.String()); DEBUG(DBG_BATTLE, DBG_INFO, "army2 " << army2.String()); while(arena.BattleValid()) arena.Turns(); const Result & result = arena.GetResult(); AGG::ResetMixer(); HeroBase* hero_wins = (result.army1 & RESULT_WINS ? army1.GetCommander() : (result.army2 & RESULT_WINS ? army2.GetCommander() : NULL)); HeroBase* hero_loss = (result.army1 & RESULT_LOSS ? army1.GetCommander() : (result.army2 & RESULT_LOSS ? army2.GetCommander() : NULL)); const u32 loss_result = result.army1 & RESULT_LOSS ? result.army1 : result.army2; if(local) { // fade arena arena.FadeArena(); // dialog summary arena.DialogBattleSummary(result); } // save count troop arena.GetForce1().SyncArmyCount(); arena.GetForce2().SyncArmyCount(); // after battle army1 if(army1.GetCommander()) { if(army1.isControlAI()) AI::HeroesAfterBattle(*army1.GetCommander()); else army1.GetCommander()->ActionAfterBattle(); } // after battle army2 if(army2.GetCommander()) { if(army2.isControlAI()) AI::HeroesAfterBattle(*army2.GetCommander()); else army2.GetCommander()->ActionAfterBattle(); } // pickup artifact if(hero_wins && hero_loss && !((RESULT_RETREAT | RESULT_SURRENDER) & loss_result) && hero_wins->isHeroes() && hero_loss->isHeroes()) PickupArtifactsAction(*hero_wins, *hero_loss, hero_wins->isControlHuman()); // eagle eye capability if(hero_wins && hero_loss && hero_wins->GetLevelSkill(Skill::Secondary::EAGLEEYE) && hero_loss->isHeroes()) EagleEyeSkillAction(*hero_wins, arena.GetUsageSpells(), hero_wins->isControlHuman()); // necromancy capability if(hero_wins && hero_wins->GetLevelSkill(Skill::Secondary::NECROMANCY)) NecromancySkillAction(*hero_wins, result.killed, hero_wins->isControlHuman()); DEBUG(DBG_BATTLE, DBG_INFO, "army1 " << army1.String()); DEBUG(DBG_BATTLE, DBG_INFO, "army2 " << army1.String()); // update army if(army1.GetCommander() && army1.GetCommander()->isHeroes()) { // hard reset army if(!army1.isValid() || (result.army1 & RESULT_RETREAT)) army1.Reset(false); } // update army if(army2.GetCommander() && army2.GetCommander()->isHeroes()) { // hard reset army if(!army2.isValid() || (result.army2 & RESULT_RETREAT)) army2.Reset(false); } DEBUG(DBG_BATTLE, DBG_INFO, "army1: " << (result.army1 & RESULT_WINS ? "wins" : "loss") << ", army2: " << (result.army2 & RESULT_WINS ? "wins" : "loss")); return result; }
bool Route::Path::Find(s32 to, int limit) { const int pathfinding = hero->GetLevelSkill(Skill::Secondary::PATHFINDING); const s32 from = hero->GetIndex(); s32 cur = from; s32 alt = 0; s32 tmp = 0; std::map<s32, cell_t> list; std::map<s32, cell_t>::iterator it1 = list.begin(); std::map<s32, cell_t>::iterator it2 = list.end(); list[cur].cost_g = 0; list[cur].cost_t = 0; list[cur].parent = -1; list[cur].open = 0; const Directions directions = Direction::All(); clear(); while(cur != to) { LocalEvent::Get().HandleEvents(false); for(Directions::const_iterator it = directions.begin(); it != directions.end(); ++it) { if(Maps::isValidDirection(cur, *it)) { tmp = Maps::GetDirectionIndex(cur, *it); if(list[tmp].open) { const u32 costg = GetPenaltyFromTo(cur, tmp, *it, pathfinding); // new if(-1 == list[tmp].parent) { if((list[cur].passbl & *it) || PassableFromToTile(*hero, cur, tmp, *it, to)) { list[cur].passbl |= *it; list[tmp].direct = *it; list[tmp].cost_g = costg; list[tmp].parent = cur; list[tmp].open = 1; list[tmp].cost_d = 50 * Maps::GetApproximateDistance(tmp, to); list[tmp].cost_t = list[cur].cost_t + costg; } } // check alt else { if(list[tmp].cost_t > list[cur].cost_t + costg && ((list[cur].passbl & *it) || PassableFromToTile(*hero, cur, tmp, *it, to))) { list[cur].passbl |= *it; list[tmp].direct = *it; list[tmp].parent = cur; list[tmp].cost_g = costg; list[tmp].cost_t = list[cur].cost_t + costg; } } } } } list[cur].open = 0; it1 = list.begin(); alt = -1; tmp = MAXU16; DEBUG(DBG_OTHER, DBG_TRACE, "route, from: " << cur); // find minimal cost for(; it1 != it2; ++it1) if((*it1).second.open) { const cell_t & cell2 = (*it1).second; #ifdef WITH_DEBUG if(IS_DEBUG(DBG_OTHER, DBG_TRACE) && cell2.cost_g != MAXU16) { int direct = Direction::Get(cur, (*it1).first); if(Direction::UNKNOWN != direct) { VERBOSE("\t\tdirect: " << Direction::String(direct) << ", index: " << (*it1).first << ", cost g: " << cell2.cost_g << ", cost t: " << cell2.cost_t << ", cost d: " << cell2.cost_d); } } #endif if(cell2.cost_t + cell2.cost_d < tmp) { tmp = cell2.cost_t + cell2.cost_d; alt = (*it1).first; } } // not found, and exception if(MAXU16 == tmp || -1 == alt) break; #ifdef WITH_DEBUG else DEBUG(DBG_OTHER, DBG_TRACE, "select: " << alt); #endif cur = alt; if(0 < limit && GetCurrentLength(list, cur) > limit) break; } // save path if(cur == to) { while(cur != from) { push_front(Route::Step(list[cur].parent, list[cur].direct, list[cur].cost_g)); cur = list[cur].parent; } } else { DEBUG(DBG_OTHER, DBG_TRACE, "not found" << ", from:" << from << ", to: " << to); } return !empty(); }