/** @file /ai/Strategizer/attacks.cpp @brief Zdrojovy kod modulu utoku AI hrace. Zdrojovy kod modulu utoku AI hrace. @author PZ @version 0.1 */ #include "ai/Strategizer/attacks.h" using namespace World; namespace ai_ns { namespace strategizer_ns { // CStrategyAttackEngine class implementation CStrategyAttackEngine::CStrategyAttackEngine(TPacket_AI_LetsGo* WorldPointers,CStrategySerialization* SS) { SIP=WorldPointers; this->SS=SS; loadAttackCoefs(); } CStrategyAttackEngine::~CStrategyAttackEngine() { } void CStrategyAttackEngine::setPlayer(int passed_player_ID) { playerID=passed_player_ID; } void CStrategyAttackEngine::loadAttackCoefs() { ai_ns::CAIScriptCaller* sc=new ai_ns::CAIScriptCaller(); ai_ns::CTCLAIVar* varsout=sc->countScript(ID_SCRIPT_STRATEGY_COEFS,0); AttackingGroupStrengthRatio=varsout->getReal("ATTACKING_GROUP_STRENGTH_RATIO"); MinimalAttackPower=varsout->getInt("MINIMAL_ATTACK_POWER"); delete varsout; delete sc; } int CStrategyAttackEngine::identifyWorstEnemy(std::list* excluded_players) { int rv; TPacket_Diplomacy_FindWorstEnemy pdfwe; pdfwe.diplomat_world_id=playerID; pdfwe.excluded_diplomats=excluded_players; int* mrv=(int*) KSendGlobalMessage(MSG_DIPLOMACY_FIND_WORST_ENEMY,MOD_STRATEGY,MOD_DIPLOMACY,&pdfwe); if (!mrv) return (-1); rv=*mrv; KMemFree(mrv); return rv; } void CStrategyAttackEngine::processAttack(TAIAttackInfo* attack_info) { CPlan* attack_plan=new CPlan(playerID); if (attack_info->attack_target_type==ATUnit) { attack_info->attack_state=Charging; bool target_unit_not_found=true; int i; GLOBALLOGID(PRIORITY_AI_ALLOC, "for ln 74 attacks"); for(i=0;((target_unit_not_found) && (i<(SIP->map->width()*SIP->map->height())));i++) { if ((SIP->map->insideBorders(i)) && (VISIBILITY_FOR_PLAYER_ON_HEXID(SIP->visibility_maps,playerID,i)!=VI_NEVER_SEEN)) { if (UNIT_ID_ON_HEXID(SIP->map,i)==attack_info->target_unit_id) { attack_info->target_point=i; if (attack_info->attack_state==Done) attack_info->attack_state=Charging; target_unit_not_found=false; } } } if (target_unit_not_found) { attack_info->target_point=-1; } } switch (attack_info->attack_state) { case CannotBeSynchronized: { // test, zdali jsou jiz vsechny sloty obsazene a utok jiz muze prejit do Charging bool attack_units_produced=true; std::ATTACK_SLOTS_CONTAINER::iterator asIt; for(asIt=(attack_info->units_for_attack).begin();((attack_units_produced) && (asIt!=(attack_info->units_for_attack).end()));asIt++) { attack_units_produced=asIt->assigned; } if (attack_units_produced) attack_info->attack_state=Charging; } break; case Synchronizating: { std::ATTACK_SLOTS_CONTAINER::iterator asIt; for(asIt=(attack_info->units_for_attack).begin();asIt!=(attack_info->units_for_attack).end();asIt++) { if (asIt->assigned) { // jednotka stoji primo na synchronizacnim bode if (UNIT_ID_ON_HEXID(SIP->map,attack_info->synchronization_point)==asIt->assigned_unit_id) { asIt->synchronized=true; } else // s jednotkou se pokusim hejbnout { CUnitPlanAction_Go* dia=new CUnitPlanAction_Go(asIt->assigned_unit_id); dia->path_target=attack_info->synchronization_point; dia->transparency=ai_ns::pathfind_ns::PFT_IgnoreTargetUnit; attack_plan->addActionToBack(dia,PERFORM_IMMEDIATELY); attack_plan->deleteAllDoneActions(); // posilam jeste jednou s jinou transparenci - to je pokud by cesta neexistovala pres me jednotky CUnitPlanAction_Go* dia2=new CUnitPlanAction_Go(asIt->assigned_unit_id); dia2->path_target=attack_info->synchronization_point; dia2->transparency=ai_ns::pathfind_ns::PFT_IgnoreMyUnitsAndTargetUnit; attack_plan->addActionToBack(dia2,PERFORM_IMMEDIATELY); attack_plan->deleteAllDoneActions(); if (IS_UNIT_ON_HEXID(SIP->map,asIt->unit_position)) { if (UNIT_ID_ON_HEXID(SIP->map,asIt->unit_position)==asIt->assigned_unit_id) { // jednotka nemuze jit dal - je synchronizovana asIt->synchronized=true; } } else // jednotka nekam odesla - musim updatovat pozici { int i; for(i=0;(i<(SIP->map->width()*SIP->map->height()));i++) { if ((SIP->map->insideBorders(i)) && (VISIBILITY_FOR_PLAYER_ON_HEXID(SIP->visibility_maps,playerID,i)!=VI_NEVER_SEEN)) { if (IS_UNIT_ON_HEXID(SIP->map,i)) { if (UNIT_ID_ON_HEXID(SIP->map,i)==asIt->assigned_unit_id) { asIt->unit_position=i; } } } } } } } } // test, zdali je utok jiz synchronizovan a muze prejit do Charging - tzn. jsou vsechny jednotky vyrobene a nemohou se hnout oproti predchozimu kolu k synchronizacnimu bodu bool attack_synchronized=true; for(asIt=(attack_info->units_for_attack).begin();((attack_synchronized) && (asIt!=(attack_info->units_for_attack).end()));asIt++) { attack_synchronized=(asIt->assigned) && (asIt->synchronized); } if (attack_synchronized) attack_info->attack_state=Charging; } break; case Charging: { bool all_killed=true; std::ATTACK_SLOTS_CONTAINER::iterator dchIt; for(dchIt=(attack_info->units_for_attack).begin();((all_killed) && (dchIt!=(attack_info->units_for_attack).end()));dchIt++) all_killed=(!(dchIt->assigned)); if (all_killed) attack_info->attack_state=Done; else { switch (attack_info->attack_target_type) { case ATCity: { TPacket_MapAnalyzer_FindCityByPosition pfcbp; pfcbp.position=attack_info->target_point; TOWN* str_city=(TOWN*) KSendGlobalMessage(MSG_MAPANALYZER_FIND_CITY_BY_POSITION,MOD_STRATEGY,MOD_MAPANALYZER,&pfcbp); if (str_city->owner==playerID) { attack_info->attack_state=Done; } else { TPacket_Diplomacy_GetRelation grp; grp.source_diplomat_world_id=playerID; grp.target_diplomat_world_id=str_city->owner; ai_ns::diplomacy_ns::TRelationship* msg_result=(ai_ns::diplomacy_ns::TRelationship*) KSendGlobalMessage(MSG_DIPLOMACY_GET_RELATION,MOD_STRATEGY,MOD_DIPLOMACY,&grp); if ((*msg_result)>ai_ns::diplomacy_ns::RELATIONSHIP_WAR) attack_info->attack_state=Done; KMemFree(msg_result); } if (attack_info->attack_state!=Done) { if (IS_UNIT_ON_HEXID(SIP->map,attack_info->target_point)) { if ((str_city->owner!=playerID) && (UNIT_ON_HEXID(SIP->map,SIP->living_units,attack_info->target_point).player==playerID)) // nekde ve meste je jeste nepritel { int cpIt; bool enemy_unit_in_city_not_found=true; for(cpIt=0;((enemy_unit_in_city_not_found) && (cpItcitysize));cpIt++) { if (IS_UNIT_ON_HEXID(SIP->map,(str_city->position)[cpIt])) { if (UNIT_ON_HEXID(SIP->map,SIP->living_units,(str_city->position)[cpIt]).player!=playerID) { attack_info->target_point=(str_city->position)[cpIt]; enemy_unit_in_city_not_found=false; } } } } } std::ATTACK_SLOTS_CONTAINER::iterator asIt; for(asIt=(attack_info->units_for_attack).begin();asIt!=(attack_info->units_for_attack).end();asIt++) { if (asIt->assigned) { int bp=findBestAttackPosition(asIt->assigned_unit_id,attack_info->target_point); if ((bp==-1) || (!(IS_UNIT_ON_HEXID(SIP->map,attack_info->target_point)))) { CUnitPlanAction_Go* dia=new CUnitPlanAction_Go(asIt->assigned_unit_id); dia->path_target=attack_info->target_point; dia->transparency=ai_ns::pathfind_ns::PFT_IgnoreTargetUnit; attack_plan->addActionToBack(dia,PERFORM_IMMEDIATELY); attack_plan->deleteAllDoneActions(); // neni treba utocit, protoze nejde odkud } else { CUnitPlanAction_Go* dia=new CUnitPlanAction_Go(asIt->assigned_unit_id); dia->path_target=bp; dia->transparency=ai_ns::pathfind_ns::PFT_UnitsNotTransparent; // jdu najisto attack_plan->addActionToBack(dia,PERFORM_IMMEDIATELY); attack_plan->deleteAllDoneActions(); CUnitPlanAction_Attack* diaa=new CUnitPlanAction_Attack(asIt->assigned_unit_id); diaa->attack_target=attack_info->target_point; attack_plan->addActionToBack(diaa,PERFORM_IMMEDIATELY); attack_plan->deleteAllDoneActions(); } } } } } break; case ATBuilding: { if (BUILDING_ON_HEXID(SIP->map,SIP->living_buildings,attack_info->target_point).player==playerID) { attack_info->attack_state=Done; } else { TPacket_Diplomacy_GetRelation grp; grp.source_diplomat_world_id=playerID; grp.target_diplomat_world_id=BUILDING_ON_HEXID(SIP->map,SIP->living_buildings,attack_info->target_point).player; ai_ns::diplomacy_ns::TRelationship* msg_result=(ai_ns::diplomacy_ns::TRelationship*) KSendGlobalMessage(MSG_DIPLOMACY_GET_RELATION,MOD_STRATEGY,MOD_DIPLOMACY,&grp); if ((*msg_result)>ai_ns::diplomacy_ns::RELATIONSHIP_ENEMY) attack_info->attack_state=Done; KMemFree(msg_result); } if (attack_info->attack_state!=Done) { std::ATTACK_SLOTS_CONTAINER::iterator asIt; for(asIt=(attack_info->units_for_attack).begin();asIt!=(attack_info->units_for_attack).end();asIt++) { if (asIt->assigned) { int bp=findBestAttackPosition(asIt->assigned_unit_id,attack_info->target_point); if ((bp==-1) || (!(IS_UNIT_ON_HEXID(SIP->map,attack_info->target_point)))) { CUnitPlanAction_Go* dia=new CUnitPlanAction_Go(asIt->assigned_unit_id); dia->path_target=attack_info->target_point; dia->transparency=ai_ns::pathfind_ns::PFT_IgnoreTargetUnit; attack_plan->addActionToBack(dia,PERFORM_IMMEDIATELY); attack_plan->deleteAllDoneActions(); // neni treba utocit, protoze nejde odkud } else { CUnitPlanAction_Go* dia=new CUnitPlanAction_Go(asIt->assigned_unit_id); dia->path_target=bp; dia->transparency=ai_ns::pathfind_ns::PFT_UnitsNotTransparent; // jdu najisto attack_plan->addActionToBack(dia,PERFORM_IMMEDIATELY); attack_plan->deleteAllDoneActions(); CUnitPlanAction_Attack* diaa=new CUnitPlanAction_Attack(asIt->assigned_unit_id); diaa->attack_target=attack_info->target_point; attack_plan->addActionToBack(diaa,PERFORM_IMMEDIATELY); attack_plan->deleteAllDoneActions(); } } } } } break; case ATUnit: { if (attack_info->target_point==-1) attack_info->attack_state=Done; else { std::ATTACK_SLOTS_CONTAINER::iterator asIt; for(asIt=(attack_info->units_for_attack).begin();asIt!=(attack_info->units_for_attack).end();asIt++) { CUnitPlanAction_Go* dia=new CUnitPlanAction_Go(asIt->assigned_unit_id); dia->path_target=findBestAttackPosition(asIt->assigned_unit_id,attack_info->target_point); dia->transparency=ai_ns::pathfind_ns::PFT_IgnoreTargetUnit; // transparence pouze vuci target jednotce attack_plan->addActionToBack(dia,PERFORM_IMMEDIATELY); attack_plan->deleteAllDoneActions(); CUnitPlanAction_Attack* diaa=new CUnitPlanAction_Attack(asIt->assigned_unit_id); diaa->attack_target=attack_info->target_point; attack_plan->addActionToBack(diaa,PERFORM_IMMEDIATELY); attack_plan->deleteAllDoneActions(); } } } break; default:; } } } break; case Done: { srand((unsigned) time(NULL)); std::ATTACK_SLOTS_CONTAINER::iterator asIt; for(asIt=(attack_info->units_for_attack).begin();asIt!=(attack_info->units_for_attack).end();asIt++) { TAIUnitInfo* ui=SS->findUnitInfoByWorldID(asIt->assigned_unit_id); if (ui) { if (attack_info->attack_target_type==ATUnit) ui->global_desire=Attack_Unassigned; else { if (asIt==(attack_info->units_for_attack).begin()) { ui->global_desire=Defence; } else { if ((rand())%2) ui->global_desire=Defence; else ui->global_desire=Attack_Unassigned; } } } } } break; default:; } attack_plan->processPlan(); delete attack_plan; } int CStrategyAttackEngine::findBestAttackPosition(int attacker_id,int target_hex) { int rv=-1; PACKET_GET_INVERSE_ATTACK_RANGE pgiar; pgiar.type=MSG_GET_INVERSE_ATTACK_RANGE; pgiar.player_id=playerID; pgiar.attacker=attacker_id; pgiar.target=target_hex; TPacket_RET_INVERSE_ATTACK_RANGE* aph_result=(TPacket_RET_INVERSE_ATTACK_RANGE*) KSendGlobalMessage(MSG_WORLD_AI,MOD_STRATEGY, MOD_WORLD_SERVER, &pgiar); if (aph_result->attack_range.empty()) { delete aph_result; return rv; } ai_ns::pathfind_ns::PF_MARKMAP AllocatedMarkMap=(bool*) KMemAlloc((SIP->map->width()*SIP->map->height())*sizeof(bool)); GLOBALLOGID(PRIORITY_AI_ALLOC, "AllocatedMarkMap ln 392 attacks"); int i; GLOBALLOGID(PRIORITY_AI_ALLOC, "for ln 396 attacks"); for(i=0;(i<(SIP->map->width()*SIP->map->height()));i++) { if ((SIP->map->insideBorders(i)) && (VISIBILITY_FOR_PLAYER_ON_HEXID(SIP->visibility_maps,playerID,i)!=VI_NEVER_SEEN)) { AllocatedMarkMap[i]=true; } else { AllocatedMarkMap[i]=false; } } ai_ns::pathfind_ns::FLOOD_MASK AllocatedFloodMask=(int*) KMemAlloc((SIP->map->width()*SIP->map->height())*sizeof(int)); GLOBALLOGID(PRIORITY_AI_ALLOC, "AllocatedFloodMask ln 407 attacks"); PACKET_FLOODFILL_REQUEST pfr; pfr.unit_id=attacker_id; TPacket_MapAnalyzer_FindUnitPosition pmafup; pmafup.unit_world_id=attacker_id; int* uprv=(int*) KSendGlobalMessage(MSG_MAPANALYZER_FIND_UNIT_POSITION,MOD_STRATEGY,MOD_MAPANALYZER,&pmafup); int fup=*uprv; KMemFree(uprv); pfr.start_hex.x=fup%SIP->map->width(); pfr.start_hex.y=fup/SIP->map->width(); pfr.mark_map=AllocatedMarkMap; pfr.flood_mask=AllocatedFloodMask; pfr.flooding_transparency=ai_ns::pathfind_ns::PFT_UnitsNotTransparent; KSendGlobalMessage(MSG_FLOODFILL_REQUEST,MOD_STRATEGY,MOD_PATHFIND,&pfr); KMemFree(AllocatedMarkMap); int bv=-1; std::vector::iterator iIt; for (iIt=aph_result->attack_range.begin();iIt!=aph_result->attack_range.end();iIt++) { if (AllocatedFloodMask[(*iIt)]!=FLOOD_MASK_VALUE_NOT_ACCESSIBLE) { if ((bv<0) || (bv>AllocatedFloodMask[(*iIt)])) { rv=(*iIt); bv=AllocatedFloodMask[(*iIt)]; } } } KMemFree(AllocatedFloodMask); delete aph_result; return rv; } int CStrategyAttackEngine::findBestAttackTarget(TAttackTargetFilter attack_filter) { // primarne zkusim obsadit neutralni mesta int i; GLOBALLOGID(PRIORITY_AI_ALLOC, "for ln 452 attacks"); for(i=0;(i<(SIP->map->width()*SIP->map->height()));i++) { if ((SIP->map->insideBorders(i)) && (VISIBILITY_FOR_PLAYER_ON_HEXID(SIP->visibility_maps,playerID,i)!=VI_NEVER_SEEN)) { if ((SIP->map->getHexById(i)->data()).terrain==TT_TOWN) { TPacket_MapAnalyzer_FindCityByPosition pfcbp; pfcbp.position=i; TOWN* str_city=(TOWN*) KSendGlobalMessage(MSG_MAPANALYZER_FIND_CITY_BY_POSITION,MOD_STRATEGY,MOD_MAPANALYZER,&pfcbp); if (str_city->owner==0) return i; } } } // pak zkusim obsadit neutralni budovy (krom mostu) GLOBALLOGID(PRIORITY_AI_ALLOC, "for ln 469 attacks"); for(i=0;(i<(SIP->map->width()*SIP->map->height()));i++) { if ((SIP->map->insideBorders(i)) && (VISIBILITY_FOR_PLAYER_ON_HEXID(SIP->visibility_maps,playerID,i)!=VI_NEVER_SEEN)) { if (IS_BUILDING_ON_HEXID(SIP->map,i)) { if ((BUILDING_ON_HEXID(SIP->map,SIP->living_buildings,i).player==0) && (BUILDING_TO_CONQUER(BUILDING_ON_HEXID(SIP->map,SIP->living_buildings,i).type))) { return i; } } } } std::list excluded_players; excluded_players.clear(); int PlayerEmpireCenter; TPacket_MapAnalyzer_FindPlayerEmpireCenter pmafpec; pmafpec.player_id=playerID; int* pec_result=(int*) KSendGlobalMessage(MSG_MAPANALYZER_FIND_PLAYER_EMPIRE_CENTER,MOD_STRATEGY,MOD_MAPANALYZER,&pmafpec); PlayerEmpireCenter=*pec_result; KMemFree(pec_result); int bt=-1; int btd=INT_MAX; bool suitable_target_not_found=true; while (suitable_target_not_found) { int we=identifyWorstEnemy(&(excluded_players)); if (we==-1) { excluded_players.clear(); return we; } else { if (excluded_players.empty()) { // prvnimu nejhorsimu nepriteli nadeklaruji hned valku TPacket_Diplomacy_AIWarDeclaration pdAIwd; pdAIwd.ai_diplomat_world_id=playerID; pdAIwd.enemy_diplomat_of_ai_world_id=we; KSendGlobalMessage(MSG_DIPLOMACY_AI_WAR_DECLARATION,MOD_STRATEGY,MOD_DIPLOMACY,&pdAIwd); } else { // na kazdeho dalsiho nepritele se ptam, jestli to neni spojenec TPacket_Diplomacy_GetRelation grp; grp.source_diplomat_world_id=playerID; grp.target_diplomat_world_id=we; ai_ns::diplomacy_ns::TRelationship* msg_result=(ai_ns::diplomacy_ns::TRelationship*) KSendGlobalMessage(MSG_DIPLOMACY_GET_RELATION,MOD_STRATEGY,MOD_DIPLOMACY,&grp); switch (*msg_result) { case ai_ns::diplomacy_ns::RELATIONSHIP_ALLY: case ai_ns::diplomacy_ns::RELATIONSHIP_TRUCE: { // na nejhorsiho nepritele nelze utocit a dalsi na rade je prilis "pratelsky" KMemFree(msg_result); excluded_players.clear(); return (-1); } default:; } KMemFree(msg_result); } excluded_players.push_back(we); // hledam mesta nejhorsiho nepritele, na ktere se da zautocit GLOBALLOGID(PRIORITY_AI_ALLOC, "for ln 541 attacks"); if ((attack_filter==ATF_Any_Static) || (attack_filter==ATF_City_Only)) { // was missing ... it was confusing for(i=0;(i<(SIP->map->width()*SIP->map->height()));i++) { if ((SIP->map->insideBorders(i)) && (VISIBILITY_FOR_PLAYER_ON_HEXID(SIP->visibility_maps,playerID,i)!=VI_NEVER_SEEN)) { if ((SIP->map->getHexById(i)->data()).terrain==TT_TOWN) { TPacket_MapAnalyzer_FindCityByPosition pfcbp; pfcbp.position=i; TOWN* str_city=(TOWN*) KSendGlobalMessage(MSG_MAPANALYZER_FIND_CITY_BY_POSITION,MOD_STRATEGY,MOD_MAPANALYZER,&pfcbp); if (str_city->owner==we) { // jeste musim zkontrolovat, zdali jiz neni mezi vybranymi pro utok bool tnfiai=true; std::ATTACKS_AI_INFO_CONTAINER::iterator aiIt; for(aiIt=SS->AttacksInfo.begin();((tnfiai) && (aiIt!=SS->AttacksInfo.end()));aiIt++) { if (aiIt->attack_target_type==ATCity) { int cpc; for(cpc=0;cpccitysize;cpc++) { if (i==str_city->position[cpc]) tnfiai=false; } } } if (tnfiai) // na mesto s hexem i jeste neutocim { TPacket_MapAnalyzer_GetHexDistance pmaghd; pmaghd.hexid1=PlayerEmpireCenter; pmaghd.hexid2=i; int* dist=(int*) KSendGlobalMessage(MSG_MAPANALYZER_GET_HEX_DISTANCE,MOD_STRATEGY,MOD_MAPANALYZER,&pmaghd); if ((bt==-1) || (*distmap->width()*SIP->map->height()));i++) { if ((SIP->map->insideBorders(i)) && (VISIBILITY_FOR_PLAYER_ON_HEXID(SIP->visibility_maps,playerID,i)!=VI_NEVER_SEEN)) { if (IS_BUILDING_ON_HEXID(SIP->map,i)) { if ((BUILDING_ON_HEXID(SIP->map,SIP->living_buildings,i).player==we) && (BUILDING_TO_CONQUER(BUILDING_ON_HEXID(SIP->map,SIP->living_buildings,i).type))) { // jeste musim zkontrolovat, zdali jiz neni mezi vybranymi pro utok bool tnfiai=true; std::ATTACKS_AI_INFO_CONTAINER::iterator aiIt; for(aiIt=SS->AttacksInfo.begin();((tnfiai) && (aiIt!=SS->AttacksInfo.end()));aiIt++) { if (aiIt->attack_target_type==ATBuilding) { if (aiIt->target_point==i) tnfiai=false; } } if (tnfiai) // na budovu na hexu i jeste neutocim { TPacket_MapAnalyzer_GetHexDistance pmaghd; pmaghd.hexid1=PlayerEmpireCenter; pmaghd.hexid2=i; int* dist=(int*) KSendGlobalMessage(MSG_MAPANALYZER_GET_HEX_DISTANCE,MOD_STRATEGY,MOD_MAPANALYZER,&pmaghd); if ((bt==-1) || (*dist StList; StList.clear(); int i; // nastrkam budovy do kontajneru GLOBALLOGID(PRIORITY_AI_ALLOC, "for ln 644 attacks"); for(i=0;(i<(SIP->map->width()*SIP->map->height()));i++) { if ((SIP->map->insideBorders(i)) && (VISIBILITY_FOR_PLAYER_ON_HEXID(SIP->visibility_maps,playerID,i)!=World::VI_NEVER_SEEN)) { if (IS_BUILDING_ON_HEXID(SIP->map,i)) { if (BUILDING_ON_HEXID(SIP->map,SIP->living_buildings,i).player==playerID) // moje budova { StList.push_back(i); } } } } TTownsIterator citIt; // nastrkam mesta do kontajneru for(citIt=SIP->towns->begin();citIt!=SIP->towns->end();citIt++) { bool found_visible_piece=false; int cpc; for(cpc=0;((!found_visible_piece) && (cpc<(TOWN_FROM_ITERATOR(citIt)).citysize));cpc++) { if (VISIBILITY_FOR_PLAYER_ON_HEXID(SIP->visibility_maps,playerID,TOWN_FROM_ITERATOR(citIt).position[cpc])!=World::VI_NEVER_SEEN) { if (!found_visible_piece) { found_visible_piece=true; if (TOWN_FROM_ITERATOR(citIt).owner==playerID) // moje mesto { StList.push_back(TOWN_FROM_ITERATOR(citIt).position[cpc]); } } } } } int bv=-1; int bvd=INT_MAX; if (StList.empty()) // nemam staticke entity, misto nejblizsi urcim stred kralovstvi (urcen z jednotek) { return (-1); } else { std::list::iterator slIt; for(slIt=StList.begin();slIt!=StList.end();slIt++) { TPacket_MapAnalyzer_GetHexDistance pmaghd; pmaghd.hexid1=*slIt; pmaghd.hexid2=attack_target; int* dist=(int*) KSendGlobalMessage(MSG_MAPANALYZER_GET_HEX_DISTANCE,MOD_STRATEGY,MOD_MAPANALYZER,&pmaghd); if ((bv==-1) || (*distmap->width()*SIP->map->height())));i++) { if ((SIP->map->insideBorders(i)) && (VISIBILITY_FOR_PLAYER_ON_HEXID(SIP->visibility_maps,playerID,i)!=World::VI_NEVER_SEEN)) { if (IS_UNIT_ON_HEXID(SIP->map,i)) { if ((UNIT_ON_HEXID(SIP->map,SIP->living_units,i).player==playerID) && (UNIT_SUITABLE_FOR_PATHFIND_TESTING(UNIT_ON_HEXID(SIP->map,SIP->living_units,i).type))) { pf_unit_id=UNIT_ID_ON_HEXID(SIP->map,i); } } } } if (pf_unit_id==-1) return (-1); COORDS tmpcoords; PACKET_PATHFIND_REQUEST pathfr; pathfr.unit_id=pf_unit_id; tmpcoords.x=bv%SIP->map->width(); tmpcoords.y=bv/SIP->map->width(); pathfr.from=tmpcoords; tmpcoords.x=attack_target%SIP->map->width(); tmpcoords.y=attack_target/SIP->map->width(); pathfr.to=tmpcoords; pathfr.pathfind_transparency=ai_ns::pathfind_ns::PFT_IgnoreAllUnits; pathfr.points_of_movement=0; TPATH* dispPath=(TPATH*) KSendGlobalMessage(MSG_PATHFIND_REQUEST,MOD_STRATEGY,MOD_PATHFIND,&pathfr); if (!dispPath) { return bv; } else { TPATH_ITERATOR dispPathIt=dispPath->begin(); int path_pos=((int) (dispPath->size()))/2; int ppi; for(ppi=0;ppimap->width())+(*dispPathIt).x; delete dispPath; return rv; } } TAttackTargetType CStrategyAttackEngine::getTargetType(int attack_target) { if (SIP->map->getHexById(attack_target)->data().terrain==World::TT_TOWN) return ATCity; if (IS_BUILDING_ON_HEXID(SIP->map,attack_target)) return ATBuilding; return ATUnit; } int CStrategyAttackEngine::getAttackTargetStrenght(int attack_target) throw(E_8K_AI_Strategy_InvalidAttackTarget) { int rv=-1; switch(getTargetType(attack_target)) { case ATCity: { // spocitam silu vsech (cizich) jednotek ve meste TPacket_MapAnalyzer_FindCityByPosition pfcbp; pfcbp.position=attack_target; TOWN* str_city=(TOWN*) KSendGlobalMessage(MSG_MAPANALYZER_FIND_CITY_BY_POSITION,MOD_STRATEGY,MOD_MAPANALYZER,&pfcbp); if (str_city->owner==playerID) { THROW(E_8K_AI_Strategy_InvalidAttackTarget,"Cilove mesto pro utok nalezi utocicimu hracovi."); } else { rv=0; int cpc; for(cpc=0;cpccitysize;cpc++) { if (IS_UNIT_ON_HEXID(SIP->map,str_city->position[cpc])) { if (UNIT_ON_HEXID(SIP->map,SIP->living_units,str_city->position[cpc]).player!=playerID) { int unit_type=UNIT_ON_HEXID(SIP->map,SIP->living_units,str_city->position[cpc]).type; if ((((SIP->rules->unit_types)[unit_type])->data()).attack_range==0) return 0; ai_ns::CAIScriptCaller* sc=new ai_ns::CAIScriptCaller(); ai_ns::CTCLAIVar* varsin=new ai_ns::CTCLAIVar(); varsin->addInt("UNIT_ATTACK",(((SIP->rules->unit_types)[unit_type])->data()).attack); varsin->addInt("UNIT_DEFENCE",(((SIP->rules->unit_types)[unit_type])->data()).defense); varsin->addInt("IS_FIRING_UNIT",((((SIP->rules->unit_types)[unit_type])->data()).attack_range>1)?1:0); varsin->addInt("UNIT_ACTUAL_MEN_COUNT",UNIT_ON_HEXID(SIP->map,SIP->living_units,str_city->position[cpc]).lives); varsin->addInt("UNIT_MAX_MEN_NUMBER",(((SIP->rules->unit_types)[unit_type])->data()).max_lives); ai_ns::CTCLAIVar* varsout=sc->countScript(ID_SCRIPT_UNIT_POWERS,varsin); rv+=varsout->getInt("OVERALL_UNIT_POWER"); delete varsin; delete varsout; delete sc; } } } } } break; case ATBuilding: { if (IS_UNIT_ON_HEXID(SIP->map,attack_target)) { if (UNIT_ON_HEXID(SIP->map,SIP->living_units,attack_target).player==playerID) { THROW(E_8K_AI_Strategy_InvalidAttackTarget,"Na cilovem hexu budovy pro utok je hracova jednotka - budova je jeho."); } else { int unit_type=UNIT_ON_HEXID(SIP->map,SIP->living_units,attack_target).type; if ((((SIP->rules->unit_types)[unit_type])->data()).attack_range==0) return 0; ai_ns::CAIScriptCaller* sc=new ai_ns::CAIScriptCaller(); ai_ns::CTCLAIVar* varsin=new ai_ns::CTCLAIVar(); varsin->addInt("UNIT_ATTACK",(((SIP->rules->unit_types)[unit_type])->data()).attack); varsin->addInt("UNIT_DEFENCE",(((SIP->rules->unit_types)[unit_type])->data()).defense); varsin->addInt("IS_FIRING_UNIT",((((SIP->rules->unit_types)[unit_type])->data()).attack_range>1)?1:0); varsin->addInt("UNIT_ACTUAL_MEN_COUNT",UNIT_ON_HEXID(SIP->map,SIP->living_units,attack_target).lives); varsin->addInt("UNIT_MAX_MEN_NUMBER",(((SIP->rules->unit_types)[unit_type])->data()).max_lives); ai_ns::CTCLAIVar* varsout=sc->countScript(ID_SCRIPT_UNIT_POWERS,varsin); rv=varsout->getInt("OVERALL_UNIT_POWER"); delete varsin; delete varsout; delete sc; } } else { rv=0; } } break; case ATUnit: { if (IS_UNIT_ON_HEXID(SIP->map,attack_target)) { if (UNIT_ON_HEXID(SIP->map,SIP->living_units,attack_target).player==playerID) { THROW(E_8K_AI_Strategy_InvalidAttackTarget,"Na cilovem hexu pro utok je hracova jednotka."); } else { int unit_type=UNIT_ON_HEXID(SIP->map,SIP->living_units,attack_target).type; if ((((SIP->rules->unit_types)[unit_type])->data()).attack_range==0) return 0; ai_ns::CAIScriptCaller* sc=new ai_ns::CAIScriptCaller(); ai_ns::CTCLAIVar* varsin=new ai_ns::CTCLAIVar(); varsin->addInt("UNIT_ATTACK",(((SIP->rules->unit_types)[unit_type])->data()).attack); varsin->addInt("UNIT_DEFENCE",(((SIP->rules->unit_types)[unit_type])->data()).defense); varsin->addInt("IS_FIRING_UNIT",((((SIP->rules->unit_types)[unit_type])->data()).attack_range>1)?1:0); varsin->addInt("UNIT_ACTUAL_MEN_COUNT",UNIT_ON_HEXID(SIP->map,SIP->living_units,attack_target).lives); varsin->addInt("UNIT_MAX_MEN_NUMBER",(((SIP->rules->unit_types)[unit_type])->data()).max_lives); ai_ns::CTCLAIVar* varsout=sc->countScript(ID_SCRIPT_UNIT_POWERS,varsin); rv=varsout->getInt("OVERALL_UNIT_POWER"); delete varsin; delete varsout; delete sc; } } else { THROW(E_8K_AI_Strategy_InvalidAttackTarget,"Na cilovem hexu utoku neni jednotka."); } } break; default:; } return rv; } int CStrategyAttackEngine::getNewUnitStrength(int unit_type) { if ((((SIP->rules->unit_types)[unit_type])->data()).attack_range==0) return 0; ai_ns::CAIScriptCaller* sc=new ai_ns::CAIScriptCaller(); ai_ns::CTCLAIVar* varsin=new ai_ns::CTCLAIVar(); varsin->addInt("UNIT_ATTACK",(((SIP->rules->unit_types)[unit_type])->data()).attack); varsin->addInt("UNIT_DEFENCE",(((SIP->rules->unit_types)[unit_type])->data()).defense); varsin->addInt("IS_FIRING_UNIT",((((SIP->rules->unit_types)[unit_type])->data()).attack_range>1)?1:0); varsin->addInt("UNIT_ACTUAL_MEN_COUNT",(((SIP->rules->unit_types)[unit_type])->data()).max_lives); // nastaven na maximalni varsin->addInt("UNIT_MAX_MEN_NUMBER",(((SIP->rules->unit_types)[unit_type])->data()).max_lives); ai_ns::CTCLAIVar* varsout=sc->countScript(ID_SCRIPT_UNIT_POWERS,varsin); int rv=varsout->getInt("OVERALL_UNIT_POWER"); delete varsin; delete varsout; delete sc; return rv; } int CStrategyAttackEngine::selectToProduceRandomPossibleUnitForAttack() throw(E_8K_AI_Strategy_CantFindUnitForAttack) { std::list possible_producing; possible_producing.clear(); int i; GLOBALLOGID(PRIORITY_AI_ALLOC, "for ln 920 attacks"); for(i=0;(i<(SIP->map->width()*SIP->map->height()));i++) { if ((SIP->map->insideBorders(i)) && (VISIBILITY_FOR_PLAYER_ON_HEXID(SIP->visibility_maps,playerID,i)!=World::VI_NEVER_SEEN)) { if (IS_BUILDING_ON_HEXID(SIP->map,i)) { if ((BUILDING_ON_HEXID(SIP->map,SIP->living_buildings,i).player==playerID) && (BUILDING_ON_HEXID(SIP->map,SIP->living_buildings,i).construction_duration==0)) { TUnitsIterator uIt; for(uIt=SIP->rules->unit_types.begin();uIt!=SIP->rules->unit_types.end();uIt++) { TPacket_MapAnalyzer_UnitTrainableInBuilding pmautib; pmautib.building_placement=i; pmautib.unit_type=uIt->first; bool* ut_msg_res=(bool*) KSendGlobalMessage(MSG_MAPANALYZER_UNIT_TRAINABLE_IN_BUILDING,MOD_STRATEGY,MOD_MAPANALYZER,&pmautib); bool upttib=*ut_msg_res; KMemFree(ut_msg_res); if ((upttib) && (((SIP->rules->unit_types)[uIt->first])->data().attack_range>=1)) { possible_producing.push_back(uIt->first); } } } } } } // nemam zadne budovy - kounu se na prvni produkcni, kterou chci if (possible_producing.empty()) { World::BUILDING b=((SIP->rules->building_types)[FIRST_PRODUCTION_BUILDING_ID])->data(); int bpIt; for(bpIt=0;(bpItrules->unit_types)[(b.unit_recruitment.data)[bpIt]])->data().default_occurrence==1) && (((SIP->rules->unit_types)[(b.unit_recruitment.data)[bpIt]])->data().attack_range>=1)) { possible_producing.push_back((b.unit_recruitment.data)[bpIt]); } } } if (possible_producing.empty()) THROW(E_8K_AI_Strategy_CantFindUnitForAttack,"Nelze nalezt jednotku k produkci pro planovany utok"); srand((unsigned) time(NULL)); int prod_choices_rand_pos=((rand())%((int) (possible_producing.size()))); std::list::iterator ppIt=possible_producing.begin(); int pccntr; for(pccntr=0;pccntrmap->width()*SIP->map->height()));i++) { if ((SIP->map->insideBorders(i)) && (VISIBILITY_FOR_PLAYER_ON_HEXID(SIP->visibility_maps,playerID,i)!=World::VI_NEVER_SEEN)) { if (IS_UNIT_ON_HEXID(SIP->map,i)) { if ((UNIT_ON_HEXID(SIP->map,SIP->living_units,i).player==playerID) && (UNIT_ON_HEXID_CAN_ATTACK(SIP->map,SIP->rules,SIP->living_units,i))) { int unit_type=UNIT_ON_HEXID(SIP->map,SIP->living_units,i).type; if ((((SIP->rules->unit_types)[unit_type])->data()).attack_range>=1) { TPacket_MapAnalyzer_GetActionRadius pmagar; pmagar.position=i; pmagar.radius_size=(((SIP->rules->unit_types)[unit_type])->data()).attack_range; TPacket_MapAnalyzer_ActionRadiusResponse* ar=(TPacket_MapAnalyzer_ActionRadiusResponse*) KSendGlobalMessage(MSG_MAPANALYZER_GET_ACTION_RADIUS,MOD_STRATEGY,MOD_MAPANALYZER,&pmagar); std::list::iterator hIt; bool atnf=true; for(hIt=(ar->radius_hexes).begin();((atnf) && (hIt!=(ar->radius_hexes).end()));hIt++) { if (IS_UNIT_ON_HEXID(SIP->map,*hIt)) { if (UNIT_ON_HEXID(SIP->map,SIP->living_units,*hIt).player!=playerID) { TPacket_Diplomacy_GetRelation grp; grp.source_diplomat_world_id=playerID; grp.target_diplomat_world_id=UNIT_ON_HEXID(SIP->map,SIP->living_units,*hIt).player; ai_ns::diplomacy_ns::TRelationship* msg_result=(ai_ns::diplomacy_ns::TRelationship*) KSendGlobalMessage(MSG_DIPLOMACY_GET_RELATION,MOD_STRATEGY,MOD_DIPLOMACY,&grp); if ((*msg_result)<=ai_ns::diplomacy_ns::RELATIONSHIP_ENEMY) { atnf=true; CPlan* attack_in_radius_plan=new CPlan(playerID); CUnitPlanAction_Attack* diaa=new CUnitPlanAction_Attack(UNIT_ID_ON_HEXID(SIP->map,i)); diaa->attack_target=*hIt; attack_in_radius_plan->addActionToBack(diaa,PERFORM_IMMEDIATELY); attack_in_radius_plan->deleteAllDoneActions(); delete attack_in_radius_plan; } KMemFree(msg_result); } } } delete ar; } } } } } } void CStrategyAttackEngine::processExploringWithUnassignedAttackers() { std::UNIT_AI_INFO_CONTAINER::iterator uiIt; for(uiIt=SS->UnitsInfo.begin();uiIt!=SS->UnitsInfo.end();uiIt++) { if (uiIt->global_desire==Attack_Unassigned) { TPacket_MapAnalyzer_GetRandomInvisibleHex pmagrih; pmagrih.player_id=playerID; int* ar=(int*) KSendGlobalMessage(MSG_MAPANALYZER_GET_RANDOM_INVISIBLE_HEX,MOD_STRATEGY,MOD_MAPANALYZER,&pmagrih); int rih=*ar; KMemFree(ar); if (rih!=-1) { // zkusim jit k nejblizsimu neprozkoumanemu hexu CPlan* temp_plan=new CPlan(playerID); CUnitPlanAction_Go* dia=new CUnitPlanAction_Go(uiIt->world_id); dia->path_target=rih; dia->transparency=ai_ns::pathfind_ns::PFT_IgnoreTargetUnit; temp_plan->addActionToBack(dia,PERFORM_IMMEDIATELY); temp_plan->deleteAllDoneActions(); // posilam jeste jednou s jinou transparenci - to je pokud by cesta neexistovala pres me jednotky CUnitPlanAction_Go* dia2=new CUnitPlanAction_Go(uiIt->world_id); dia2->path_target=rih; dia2->transparency=ai_ns::pathfind_ns::PFT_IgnoreMyUnitsAndTargetUnit; temp_plan->addActionToBack(dia2,PERFORM_IMMEDIATELY); temp_plan->deleteAllDoneActions(); delete temp_plan; } } } } void CStrategyAttackEngine::updateAttacks() { // odmazu hotove utoky bool delete_done; std::ATTACKS_AI_INFO_CONTAINER::iterator aiIt; for(aiIt=SS->AttacksInfo.begin();aiIt!=SS->AttacksInfo.end();) { delete_done=(aiIt->attack_state==Done); if (delete_done) aiIt=SS->AttacksInfo.erase(aiIt); else aiIt++; } for(aiIt=SS->AttacksInfo.begin();aiIt!=SS->AttacksInfo.end();aiIt++) { // hledam neobsazene sloty u CannotBeSynchronized a Synchronizating utoku if ((aiIt->attack_state==CannotBeSynchronized) || (aiIt->attack_state==Synchronizating)) { std::ATTACK_SLOTS_CONTAINER::iterator asIt; for(asIt=(aiIt->units_for_attack).begin();asIt!=(aiIt->units_for_attack).end();asIt++) { if (!(asIt->assigned)) { std::UNIT_AI_INFO_CONTAINER::iterator uiIt; for(uiIt=SS->UnitsInfo.begin();((!(asIt->assigned)) && (uiIt!=SS->UnitsInfo.end()));uiIt++) { if ((uiIt->global_desire==Attack_Unassigned) && (uiIt->unit_type==asIt->needed_unit_type)) { uiIt->global_desire=Attack_Assigned; asIt->assigned=true; asIt->assigned_unit_id=uiIt->world_id; asIt->synchronized=false; TPacket_MapAnalyzer_FindUnitPosition pmafup; pmafup.unit_world_id=uiIt->world_id; int* uprv=(int*) KSendGlobalMessage(MSG_MAPANALYZER_FIND_UNIT_POSITION,MOD_STRATEGY,MOD_MAPANALYZER,&pmafup); asIt->unit_position=*uprv; KMemFree(uprv); } } } } } } bool can_add_new_attack=true; for(aiIt=SS->AttacksInfo.begin();aiIt!=SS->AttacksInfo.end();aiIt++) { // hledam neobsazene sloty u Synchronizating nebo CannotBeSynchronized utoku - budu je plnit jednotkami, pokud mam penize a je budova, jenz je muze aktualne vytvorit if ((aiIt->attack_state==Synchronizating) || (aiIt->attack_state==CannotBeSynchronized)) { std::ATTACK_SLOTS_CONTAINER::iterator asIt; for(asIt=(aiIt->units_for_attack).begin();asIt!=(aiIt->units_for_attack).end();asIt++) { if ((!(asIt->assigned)) && (((SIP->rules->unit_types)[asIt->needed_unit_type])->data().costMoneyAttack)) { TPacket_MapAnalyzer_NearestFreeProductionBuildingForUnitTrain pmanfpbfut; pmanfpbfut.player_id=playerID; pmanfpbfut.start_hex=(aiIt->attack_state==Synchronizating)?(aiIt->synchronization_point):0; pmanfpbfut.unit_type=asIt->needed_unit_type; int* bbp=(int*) KSendGlobalMessage(MSG_MAPANALYZER_GET_NEAREST_FREE_PRODUCTION_BUILDING_FOR_UNIT_TRAIN,MOD_STRATEGY,MOD_MAPANALYZER,&pmanfpbfut); if (*bbp!=-1) { CPlan* build_unit_plan=new CPlan(playerID); CBuildingPlanAction_TrainUnit* bua=new CBuildingPlanAction_TrainUnit(BUILDING_ID_ON_HEXID(SIP->map,*bbp)); bua->trained_unit_type=asIt->needed_unit_type; build_unit_plan->addActionToBack(bua,PERFORM_IMMEDIATELY); build_unit_plan->processPlan(); delete build_unit_plan; // test, zdali se jednotka opravdu vytvorila if (IS_UNIT_ON_HEXID(SIP->map,*bbp)) { if (UNIT_ON_HEXID(SIP->map,SIP->living_units,*bbp).type==asIt->needed_unit_type) { // jednotka se skutecne vytvorila -> zaradim ji do struktur a odectu penize SS->MoneyAttack-=((SIP->rules->unit_types)[asIt->needed_unit_type])->data().cost; TAIUnitInfo new_ui; new_ui.global_desire=Attack_Assigned; new_ui.unit_type=asIt->needed_unit_type; new_ui.world_id=UNIT_ID_ON_HEXID(SIP->map,*bbp); SS->UnitsInfo.push_back(new_ui); asIt->assigned=true; asIt->assigned_unit_id=UNIT_ID_ON_HEXID(SIP->map,*bbp); asIt->synchronized=false; asIt->unit_position=*bbp; } } } KMemFree(bbp); } // pokud nemam penize na doplneni stavajicich, nemohu vytvaret dalsi nove utoky if ((!(asIt->assigned)) && (!(((SIP->rules->unit_types)[asIt->needed_unit_type])->data().costMoneyAttack))) can_add_new_attack=false; } } } if (can_add_new_attack) { int bat=findBestAttackTarget(ATF_Any_Static); if (bat==-1) { // nic neni v dohledu - utocim na jednotky int i; GLOBALLOGID(PRIORITY_AI_ALLOC, "for ln 1170 attacks"); for(i=0;(i<(SIP->map->width()*SIP->map->height()));i++) { if ((SIP->map->insideBorders(i)) && (VISIBILITY_FOR_PLAYER_ON_HEXID(SIP->visibility_maps,playerID,i)!=VI_NEVER_SEEN)) { if (IS_UNIT_ON_HEXID(SIP->map,i)) { if (UNIT_ON_HEXID(SIP->map,SIP->living_units,i).player!=playerID) { TPacket_Diplomacy_GetRelation grp; grp.source_diplomat_world_id=playerID; grp.target_diplomat_world_id=UNIT_ON_HEXID(SIP->map,SIP->living_units,i).player; ai_ns::diplomacy_ns::TRelationship* msg_result=(ai_ns::diplomacy_ns::TRelationship*) KSendGlobalMessage(MSG_DIPLOMACY_GET_RELATION,MOD_STRATEGY,MOD_DIPLOMACY,&grp); if ((*msg_result)<=ai_ns::diplomacy_ns::RELATIONSHIP_ENEMY) { bool aunf=true; std::ATTACKS_AI_INFO_CONTAINER::iterator aiIt; for(aiIt=SS->AttacksInfo.begin();((aunf) && (aiIt!=SS->AttacksInfo.end()));aiIt++) { if ((aiIt->attack_target_type==ATUnit) && (aiIt->target_unit_id==UNIT_ID_ON_HEXID(SIP->map,i))) aunf=false; } if (aunf) // na tuto jednotku jeste neutocim { int some_unit_type=selectToProduceRandomPossibleUnitForAttack(); TPacket_MapAnalyzer_NearestFreeProductionBuildingForUnitTrain pmanfpbfut; pmanfpbfut.player_id=playerID; pmanfpbfut.start_hex=i; pmanfpbfut.unit_type=some_unit_type; int* bbp=(int*) KSendGlobalMessage(MSG_MAPANALYZER_GET_NEAREST_FREE_PRODUCTION_BUILDING_FOR_UNIT_TRAIN,MOD_STRATEGY,MOD_MAPANALYZER,&pmanfpbfut); if ((*bbp!=-1) && (((SIP->rules->unit_types)[some_unit_type])->data().costMoneyAttack)) { CPlan* build_unit_plan=new CPlan(playerID); CBuildingPlanAction_TrainUnit* bua=new CBuildingPlanAction_TrainUnit(BUILDING_ID_ON_HEXID(SIP->map,*bbp)); bua->trained_unit_type=some_unit_type; build_unit_plan->addActionToBack(bua,PERFORM_IMMEDIATELY); build_unit_plan->processPlan(); delete build_unit_plan; // test, zdali se jednotka opravdu vytvorila if (IS_UNIT_ON_HEXID(SIP->map,*bbp)) { if (UNIT_ON_HEXID(SIP->map,SIP->living_units,*bbp).type==some_unit_type) { // jednotka se skutecne vytvorila -> zaradim ji do struktur a odectu penize SS->MoneyAttack-=((SIP->rules->unit_types)[some_unit_type])->data().cost; TAIUnitInfo new_ui; new_ui.global_desire=Attack_Assigned; new_ui.unit_type=some_unit_type; new_ui.world_id=UNIT_ID_ON_HEXID(SIP->map,*bbp); SS->UnitsInfo.push_back(new_ui); TAIAttackInfo new_ai; new_ai.attack_state=Charging; // rovnou zautocim, nastaveni na CannotBeSynchronized by jenom zbytecne zdrzovalo new_ai.attack_target_type=ATUnit; new_ai.synchronization_point=-1; new_ai.target_point=i; new_ai.target_unit_id=UNIT_ID_ON_HEXID(SIP->map,i); new_ai.units_for_attack.clear(); TAttackingUnitSlot new_aus; new_aus.assigned=true; new_aus.assigned_unit_id=UNIT_ID_ON_HEXID(SIP->map,*bbp); new_aus.needed_unit_type=some_unit_type; new_aus.synchronized=true; new_aus.unit_position=*bbp; new_ai.units_for_attack.push_back(new_aus); SS->AttacksInfo.push_back(new_ai); } } } KMemFree(bbp); } } KMemFree(msg_result); } } } } } else { // v bat mam nejlepsi staticky attack target int ats=MAX(MinimalAttackPower,(int) (AttackingGroupStrengthRatio*getAttackTargetStrenght(bat))); int sp=setSynchronizationPoint(bat); TAIAttackInfo new_ai; new_ai.attack_state=((sp==-1)?CannotBeSynchronized:Synchronizating); new_ai.attack_target_type=getTargetType(bat); new_ai.synchronization_point=sp; new_ai.target_point=bat; new_ai.target_unit_id=-1; new_ai.units_for_attack.clear(); int nap=0; while (napAttacksInfo.push_back(new_ai); } } // CannotBeSynchronized utoky mohou prejit na Charging Utoky, pokud jsou vsechny jednotky vyrobene for(aiIt=SS->AttacksInfo.begin();aiIt!=SS->AttacksInfo.end();aiIt++) { if (aiIt->attack_state==CannotBeSynchronized) { bool asfull=true; std::ATTACK_SLOTS_CONTAINER::iterator asIt; for(asIt=(aiIt->units_for_attack).begin();((asfull) && (asIt!=(aiIt->units_for_attack).end()));asIt++) asfull=(asIt->assigned); if (asfull) // pokud jsou vsechny jednotky obsazene, vyrazim rovnou na ztec aiIt->attack_state=Charging; } } // vykonam utoky for(aiIt=SS->AttacksInfo.begin();aiIt!=SS->AttacksInfo.end();aiIt++) processAttack(&(*aiIt)); } } }