/* Copyright (C) 2006 Bradley Arsenault This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "AIEcho.h" #include "Building.h" #include #include #include #include #include "BuildingsTypes.h" #include "IntBuildingType.h" #include "Game.h" #include "GlobalContainer.h" #include "Order.h" #include #include "Utilities.h" #include "Brush.h" using namespace AIEcho; using namespace AIEcho::Gradients; using namespace AIEcho::Construction; using namespace AIEcho::Management; using namespace AIEcho::Conditions; using namespace AIEcho::SearchTools; using namespace boost::logic; using namespace boost; void AIEcho::signature_write(GAGCore::OutputStream *stream) { stream->write("EchoSig", 7, "signature"); } void AIEcho::signature_check(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { char signature[7]; stream->read(signature, 7, "signature"); if (memcmp(signature,"EchoSig", 7)!=0) { std::cerr<<"Signature match failed. Expected \"EchoSig\", recieved \""<readEnterSection("Entity"); EntityType type = static_cast(stream->readUint32("type")); Entity* entity = NULL; switch(type) { case Entities::EBuilding: entity = new Entities::Building; entity->load(stream, player, versionMinor); break; case Entities::EAnyTeamBuilding: entity = new Entities::AnyTeamBuilding; entity->load(stream, player, versionMinor); break; case Entities::EAnyBuilding: entity = new Entities::AnyBuilding; entity->load(stream, player, versionMinor); break; case Entities::ERessource: entity = new Entities::Ressource; entity->load(stream, player, versionMinor); break; case Entities::EAnyRessource: entity = new Entities::AnyRessource; entity->load(stream, player, versionMinor); break; case Entities::EWater: entity = new Entities::Water; entity->load(stream, player, versionMinor); break; case Entities::EPosition: entity = new Entities::Position; entity->load(stream, player, versionMinor); break; case Entities::ESand: entity = new Entities::Sand; entity->load(stream, player, versionMinor); break; }; stream->readLeaveSection(); return entity; } void Entities::Entity::save_entity(Entity* entity, GAGCore::OutputStream *stream) { stream->writeEnterSection("Entity"); stream->writeUint32(entity->get_type(), "type"); entity->save(stream); stream->writeLeaveSection(); } Entities::Building::Building(int building_type, int team, bool under_construction) : building_type(building_type), team(team), under_construction(under_construction) { } bool Entities::Building::is_entity(Map* map, int posx, int posy) { int building_id=map->getBuilding(posx, posy); if(building_id!=NOGBID) { int team_id=::Building::GIDtoTeam(building_id); if(team_id==team && map->game->teams[team_id]->myBuildings[::Building::GIDtoID(building_id)]->typeNum==building_type && (map->game->teams[team_id]->myBuildings[::Building::GIDtoID(building_id)]->constructionResultState==::Building::NO_CONSTRUCTION || under_construction) ) { return true; } } return false; } bool Entities::Building::operator==(const Entity& rhs) { if(typeid(rhs)==typeid(Entities::Building) && static_cast(rhs).building_type==building_type && static_cast(rhs).team==team && static_cast(rhs).under_construction==under_construction ) return true; return false; } bool Entities::Building::can_change() { return true; } Entities::EntityType Entities::Building::get_type() { return Entities::EBuilding; } bool Entities::Building::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("Building"); building_type = stream->readSint32("building_type"); team = stream->readSint32("team"); under_construction = stream->readUint8("under_construction"); stream->readLeaveSection(); return true; } void Entities::Building::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("Building"); stream->writeSint32(building_type, "building_type"); stream->writeSint32(team, "team"); stream->writeUint8(under_construction, "under_construction"); stream->writeLeaveSection(); } Entities::AnyTeamBuilding::AnyTeamBuilding(int team, bool under_construction) : team(team), under_construction(under_construction) { } bool Entities::AnyTeamBuilding::is_entity(Map* map, int posx, int posy) { int building_id=map->getBuilding(posx, posy); if(building_id!=NOGBID) { int team_id=::Building::GIDtoTeam(building_id); if(team_id==team && (map->game->teams[team_id]->myBuildings[::Building::GIDtoID(building_id)]->constructionResultState==::Building::NO_CONSTRUCTION || under_construction) ) { return true; } } return false; } bool Entities::AnyTeamBuilding::operator==(const Entity& rhs) { if(typeid(rhs)==typeid(Entities::AnyTeamBuilding) && static_cast(rhs).team==team && static_cast(rhs).under_construction==under_construction ) return true; return false; } bool Entities::AnyTeamBuilding::can_change() { return true; } Entities::EntityType Entities::AnyTeamBuilding::get_type() { return Entities::EAnyTeamBuilding; } bool Entities::AnyTeamBuilding::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("AnyTeamBuilding"); team = stream->readSint32("team"); under_construction = stream->readUint8("under_construction"); stream->readLeaveSection(); return true; } void Entities::AnyTeamBuilding::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("AnyTeamBuilding"); stream->writeSint32(team, "team"); stream->writeUint8(under_construction, "under_construction"); stream->writeLeaveSection(); } Entities::AnyBuilding::AnyBuilding(bool under_construction) : under_construction(under_construction) { } bool Entities::AnyBuilding::is_entity(Map* map, int posx, int posy) { int building_id=map->getBuilding(posx, posy); if(building_id!=NOGBID) { int team_id=::Building::GIDtoTeam(building_id); if(map->game->teams[team_id]->myBuildings[::Building::GIDtoID(building_id)]->constructionResultState==::Building::NO_CONSTRUCTION || under_construction) return true; } return false; } bool Entities::AnyBuilding::operator==(const Entity& rhs) { if(typeid(rhs)==typeid(Entities::AnyBuilding) && static_cast(rhs).under_construction==under_construction ) return true; return false; } bool Entities::AnyBuilding::can_change() { return true; } Entities::EntityType Entities::AnyBuilding::get_type() { return Entities::EAnyBuilding; } bool Entities::AnyBuilding::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("AnyBuilding"); under_construction = stream->readUint8("under_construction"); stream->readLeaveSection(); return true; } void Entities::AnyBuilding::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("AnyBuilding"); stream->writeUint8(under_construction, "under_construction"); stream->writeLeaveSection(); } Entities::Ressource::Ressource(int ressource_type) : ressource_type(ressource_type) { } bool Entities::Ressource::is_entity(Map* map, int posx, int posy) { if(map->isRessourceTakeable(posx, posy, ressource_type)) { return true; } return false; } bool Entities::Ressource::operator==(const Entity& rhs) { if(typeid(rhs)==typeid(Entities::Ressource) && static_cast(rhs).ressource_type==ressource_type ) return true; return false; } bool Entities::Ressource::can_change() { if(ressource_type==WOOD || ressource_type==CORN || ressource_type==ALGA) return true; return false; } Entities::EntityType Entities::Ressource::get_type() { return Entities::ERessource; } bool Entities::Ressource::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("Ressource"); ressource_type = stream->readSint32("ressource_type"); stream->readLeaveSection(); return true; } void Entities::Ressource::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("Ressource"); stream->writeSint32(ressource_type, "ressource_type"); stream->writeLeaveSection(); } Entities::AnyRessource:: AnyRessource() { } bool Entities::AnyRessource:: is_entity(Map* map, int posx, int posy) { if(map->isRessource(posx, posy)) { return true; } return false; } bool Entities::AnyRessource::operator==(const Entity& rhs) { if(typeid(rhs)==typeid(Entities::AnyRessource)) return true; return false; } bool Entities::AnyRessource::can_change() { return true; } Entities::EntityType Entities::AnyRessource::get_type() { return Entities::EAnyRessource; } bool Entities::AnyRessource::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("AnyRessource"); stream->readLeaveSection(); return true; } void Entities::AnyRessource::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("AnyRessource"); stream->writeLeaveSection(); } Entities::Water::Water() { } bool Entities::Water::is_entity(Map* map, int posx, int posy) { if(map->isWater(posx, posy)) { return true; } return false; } bool Entities::Water::operator==(const Entity& rhs) { if(typeid(rhs)==typeid(Entities::Water)) return true; return false; } bool Entities::Water::can_change() { return false; } Entities::EntityType Entities::Water::get_type() { return Entities::EWater; } bool Entities::Water::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("Water"); stream->readLeaveSection(); return true; } void Entities::Water::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("Water"); stream->writeLeaveSection(); } Entities::Position::Position(int x, int y) : x(x), y(y) { } bool Entities::Position::is_entity(Map* map, int posx, int posy) { if(x==posx && y==posy) { return true; } return false; } bool Entities::Position::operator==(const Entity& rhs) { if(typeid(rhs)==typeid(Entities::Position) && static_cast(rhs).x==x && static_cast(rhs).y==y) return true; return false; } bool Entities::Position::can_change() { return false; } Entities::EntityType Entities::Position::get_type() { return Entities::EPosition; } bool Entities::Position::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("Position"); x=stream->readSint32("posX"); y=stream->readSint32("posY"); stream->readLeaveSection(); return false; } void Entities::Position::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("Position"); stream->writeSint32(x, "posX"); stream->writeSint32(y, "posy"); stream->writeLeaveSection(); } Entities::Sand::Sand() { } bool Entities::Sand::is_entity(Map* map, int posx, int posy) { if(map->hasSand(posx, posy)) { return true; } return false; } bool Entities::Sand::operator==(const Entity& rhs) { if(typeid(rhs)==typeid(Entities::Sand)) return true; return false; } bool Entities::Sand::can_change() { return false; } Entities::EntityType Entities::Sand::get_type() { return Entities::ESand; } bool Entities::Sand::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("Sand"); stream->readLeaveSection(); return true; } void Entities::Sand::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("Sand"); stream->writeLeaveSection(); } GradientInfo::GradientInfo() { needs_updated=indeterminate; } GradientInfo::~GradientInfo() { } void GradientInfo::add_source(Entities::Entity* source) { sources.push_back(boost::shared_ptr(source)); } void GradientInfo::add_obstacle(Entities::Entity* obstacle) { obstacles.push_back(boost::shared_ptr(obstacle)); } bool GradientInfo::match_source(Map* map, int posx, int posy) { for(unsigned int x=0; xis_entity(map, posx, posy)) return true; return false; } bool GradientInfo::match_obstacle(Map* map, int posx, int posy) { for(unsigned int x=0; xis_entity(map, posx, posy)) return true; return false; } bool GradientInfo::operator==(const GradientInfo& rhs) const { if(sources.size()!=rhs.sources.size() || obstacles.size() != rhs.obstacles.size()) return false; for(unsigned int i=0; ican_change()) { needs_updated=true; return true; } } for(unsigned int i=0; ican_change()) { needs_updated=true; return true; } } } return false; } bool GradientInfo::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("GradientInfo"); stream->readEnterSection("sources"); int size=stream->readUint32("size"); sources.resize(size); for(int n=0; nreadEnterSection(n); sources[n]=boost::shared_ptr(Entities::Entity::load_entity(stream, player, versionMinor)); stream->readLeaveSection(); } stream->readLeaveSection(); stream->readEnterSection("obstacles"); size=stream->readUint32("size"); obstacles.resize(size); for(int n=0; nreadEnterSection(n); obstacles[n]=boost::shared_ptr(Entities::Entity::load_entity(stream, player, versionMinor)); stream->readLeaveSection(); } stream->readLeaveSection(); stream->readLeaveSection(); return true; } void GradientInfo::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("GradientInfo"); stream->writeEnterSection("sources"); stream->writeUint32(sources.size(), "size"); for(unsigned n=0; nwriteEnterSection(n); Entities::Entity::save_entity(sources[n].get(), stream); stream->writeLeaveSection(); } stream->writeLeaveSection(); stream->writeEnterSection("obstacles"); stream->writeUint32(obstacles.size(), "size"); for(unsigned n=0; nwriteEnterSection(n); Entities::Entity::save_entity(obstacles[n].get(), stream); stream->writeLeaveSection(); } stream->writeLeaveSection(); stream->writeLeaveSection(); } GradientInfo make_gradient_info(Entities::Entity* source) { GradientInfo gi; gi.add_source(source); return gi; } GradientInfo make_gradient_info_obstacle(Entities::Entity* source, Entities::Entity* obstacle) { GradientInfo gi; gi.add_source(source); gi.add_obstacle(obstacle); return gi; } GradientInfo make_gradient_info(Entities::Entity* source1, Entities::Entity* source2) { GradientInfo gi; gi.add_source(source1); gi.add_source(source2); return gi; } GradientInfo make_gradient_info_obstacle(Entities::Entity* source1, Entities::Entity* source2, Entities::Entity* obstacle) { GradientInfo gi; gi.add_source(source1); gi.add_source(source2); gi.add_obstacle(obstacle); return gi; } Gradient::Gradient(const GradientInfo& gi) { gradient_info=gi; width=0; } void Gradient::recalculate(Map* map) { width=map->getW(); // if(gradient==NULL) // gradient=new Sint16[map->getW()*map->getH()]; // std::fill(gradient, gradient+(map->getW()*map->getH()),0); gradient.resize(map->getW()*map->getH()); std::fill(gradient.begin(), gradient.end(),0); std::queue positions; for(int x=0; xgetW(); ++x) { for(int y=0; ygetH(); ++y) { if(gradient_info.match_source(map, x, y)) { gradient[get_pos(x, y)]=2; positions.push(position(x, y)); } else if(gradient_info.match_obstacle(map, x, y)) gradient[get_pos(x, y)]=1; } } while(!positions.empty()) { position p=positions.front(); positions.pop(); int left=p.x-1; if(left<0) left+=map->getW(); int right=p.x+1; if(right>=map->getW()) right-=map->getW(); int up=p.y-1; if(up<0) up+=map->getH(); int down=p.y+1; if(down>=map->getH()) down-=map->getH(); int center_h=p.x; int center_y=p.y; int n=gradient[get_pos(center_h, center_y)]; if(gradient[get_pos(left, up)]==0) { gradient[get_pos(left, up)]=n+1; positions.push(position(left, up)); } if(gradient[get_pos(center_h, up)]==0) { gradient[get_pos(center_h, up)]=n+1; positions.push(position(center_h, up)); } if(gradient[get_pos(right, up)]==0) { gradient[get_pos(right, up)]=n+1; positions.push(position(right, up)); } if(gradient[get_pos(left, center_y)]==0) { gradient[get_pos(left, center_y)]=n+1; positions.push(position(left, center_y)); } if(gradient[get_pos(right, center_y)]==0) { gradient[get_pos(right, center_y)]=n+1; positions.push(position(right, center_y)); } if(gradient[get_pos(left, down)]==0) { gradient[get_pos(left, down)]=n+1; positions.push(position(left, down)); } if(gradient[get_pos(center_h, down)]==0) { gradient[get_pos(center_h, down)]=n+1; positions.push(position(center_h, down)); } if(gradient[get_pos(right, down)]==0) { gradient[get_pos(right, down)]=n+1; positions.push(position(right, down)); } } } int Gradient::get_height(int posx, int posy) const { return gradient[get_pos(posx, posy)]-2; } GradientManager::GradientManager(Map* map) : map(map), cur_update(0), timer(0) { } Gradient& GradientManager::get_gradient(const GradientInfo& gi) { for(std::vector >::iterator i=gradients.begin(); i!=gradients.end(); ++i) { if((*i)->get_gradient_info() == gi) { if(ticks_since_update[i-gradients.begin()]>150) { ticks_since_update[i-gradients.begin()]=0; (*i)->recalculate(map); } return **i; } } //Did not find a matching gradient gradients.push_back(boost::shared_ptr(new Gradient(gi))); (*(gradients.end()-1))->recalculate(map); ticks_since_update.push_back(0); return **(gradients.end()-1); } void GradientManager::queue_gradient(const GradientInfo& gi) { for(unsigned i=0; iget_gradient_info() == gi) { if(gi.needs_updating()) { queuedGradients.push(i); } return; } } //Did not find a matching gradient gradients.push_back(boost::shared_ptr(new Gradient(gi))); ticks_since_update.push_back(200); queuedGradients.push(gradients.size()-1); } bool GradientManager::is_updated(const GradientInfo& gi) { for(std::vector >::iterator i=gradients.begin(); i!=gradients.end(); ++i) { if((*i)->get_gradient_info() == gi) { if(ticks_since_update[i-gradients.begin()]>150 && (*i)->get_gradient_info().needs_updating()) { return false; } return true; } } //If the gradient hasn't been queued to be updated, consider it updated, //and it will be calculated on request return true; } void GradientManager::update() { timer++; std::transform(ticks_since_update.begin(), ticks_since_update.end(), ticks_since_update.begin(), increment); if((timer%1)==0 && !queuedGradients.empty()) { int g=queuedGradients.front(); if(ticks_since_update[g]>50) { gradients[g]->recalculate(map); ticks_since_update[g]=0; } queuedGradients.pop(); return; } } Constraint* Constraint::load_constraint(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("Constraint"); ConstraintType type=static_cast(stream->readUint32("type")); Constraint* constraint=NULL; switch(type) { case CTMinimumDistance: constraint=new MinimumDistance; constraint->load(stream, player, versionMinor); break; case CTMaximumDistance: constraint=new MaximumDistance; constraint->load(stream, player, versionMinor); break; case CTMinimizedDistance: constraint=new MinimizedDistance; constraint->load(stream, player, versionMinor); break; case CTMaximizedDistance: constraint=new MaximizedDistance; constraint->load(stream, player, versionMinor); break; case CTCenterOfBuilding: constraint=new CenterOfBuilding; constraint->load(stream, player, versionMinor); break; case CTSinglePosition: constraint=new SinglePosition; constraint->load(stream, player, versionMinor); break; } stream->readLeaveSection(); return constraint; } void Constraint::save_constraint(Constraint* constraint, GAGCore::OutputStream *stream) { stream->writeEnterSection("Constraint"); stream->writeUint32(constraint->get_type(), "type"); constraint->save(stream); stream->writeLeaveSection(); } MinimumDistance::MinimumDistance(const Gradients::GradientInfo& gi, int distance) : gi(gi), gradient_cache(NULL), distance(distance) { } int MinimumDistance::calculate_constraint(Echo& echo, int x, int y) { return 0; } bool MinimumDistance::passes_constraint(Echo& echo, int x, int y) { if(gradient_cache==NULL) gradient_cache=&echo.get_gradient_manager().get_gradient(gi); int height=gradient_cache->get_height(x, y); if(height==-2) return false; if(height>=distance) return true; return false; } ConstraintType MinimumDistance::get_type() { return CTMinimumDistance; } bool MinimumDistance::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("MinimumDistance"); distance = stream->readSint32("distance"); gi.load(stream, player, versionMinor); stream->readLeaveSection(); return true; } void MinimumDistance::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("MinimumDistance"); stream->writeSint32(distance, "distance"); gi.save(stream); stream->writeLeaveSection(); } MaximumDistance::MaximumDistance(const Gradients::GradientInfo& gi, int distance) : gi(gi), gradient_cache(NULL), distance(distance) { } int MaximumDistance::calculate_constraint(Echo& echo, int x, int y) { return 0; } bool MaximumDistance::passes_constraint(Echo& echo, int x, int y) { if(gradient_cache==NULL) gradient_cache=&echo.get_gradient_manager().get_gradient(gi); int height=gradient_cache->get_height(x, y); if(height==-2) return false; if(height<=distance) return true; return false; } ConstraintType MaximumDistance::get_type() { return CTMaximumDistance; } bool MaximumDistance::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("MaximumDistance"); distance = stream->readSint32("distance"); gi.load(stream, player, versionMinor); stream->readLeaveSection(); return true; } void MaximumDistance::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("MaximumDistance"); stream->writeSint32(distance, "distance"); gi.save(stream); stream->writeLeaveSection(); } MinimizedDistance::MinimizedDistance(const Gradients::GradientInfo& gi, int weight) : gi(gi), gradient_cache(NULL), weight(weight) { } int MinimizedDistance::calculate_constraint(Echo& echo, int x, int y) { if(gradient_cache==NULL) gradient_cache=&echo.get_gradient_manager().get_gradient(gi); return -(gradient_cache->get_height(x, y) * weight); } bool MinimizedDistance::passes_constraint(Echo& echo, int x, int y) { if(gradient_cache==NULL) gradient_cache=&echo.get_gradient_manager().get_gradient(gi); return gradient_cache->get_height(x, y)!=-2; } ConstraintType MinimizedDistance::get_type() { return CTMinimizedDistance; } bool MinimizedDistance::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("MinimizedDistance"); weight = stream->readSint32("weight"); gi.load(stream, player, versionMinor); stream->readLeaveSection(); return true; } void MinimizedDistance::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("MinimizedDistance"); stream->writeSint32(weight, "weight"); gi.save(stream); stream->writeLeaveSection(); } MaximizedDistance::MaximizedDistance(const Gradients::GradientInfo& gi, int weight) : gi(gi), gradient_cache(NULL), weight(weight) { } int MaximizedDistance::calculate_constraint(Echo& echo, int x, int y) { if(gradient_cache==NULL) gradient_cache=&echo.get_gradient_manager().get_gradient(gi); return gradient_cache->get_height(x, y) * weight; } bool MaximizedDistance::passes_constraint(Echo& echo, int x, int y) { if(gradient_cache==NULL) gradient_cache=&echo.get_gradient_manager().get_gradient(gi); return gradient_cache->get_height(x, y)!=-2; } ConstraintType MaximizedDistance::get_type() { return CTMaximizedDistance; } bool MaximizedDistance::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("MaximizedDistance"); weight = stream->readSint32("weight"); gi.load(stream, player, versionMinor); stream->readLeaveSection(); return true; } void MaximizedDistance::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("MaximizedDistance"); stream->writeSint32(weight, "weight"); gi.save(stream); stream->writeLeaveSection(); } CenterOfBuilding::CenterOfBuilding(int gbid) : gbid(gbid) { } int CenterOfBuilding::calculate_constraint(Echo& echo, int x, int y) { return 0; } bool CenterOfBuilding::passes_constraint(Echo& echo, int x, int y) { Building* b=echo.player->game->teams[Building::GIDtoTeam(gbid)]->myBuildings[Building::GIDtoID(gbid)]; if(b) { if((b->posX+b->type->width/2)==x && (b->posY+b->type->height/2)==y) { return true; } } return false; } ConstraintType CenterOfBuilding::get_type() { return CTCenterOfBuilding; } bool CenterOfBuilding::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("CenterOfBuilding"); gbid = stream->readSint32("gbid"); stream->readLeaveSection(); return true; } void CenterOfBuilding::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("CenterOfBuilding"); stream->writeSint32(gbid, "gbid"); stream->writeLeaveSection(); } SinglePosition::SinglePosition(int posx, int posy) : posx(posx), posy(posy) { } int SinglePosition::calculate_constraint(Echo& echo, int x, int y) { return 0; } bool SinglePosition::passes_constraint(Echo& echo, int x, int y) { if(posx==x && posy==y) return true; return false; } ConstraintType SinglePosition::get_type() { return CTSinglePosition; } bool SinglePosition::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("SinglePosition"); posx = stream->readSint32("posx"); posy = stream->readSint32("posy"); stream->readLeaveSection(); return true; } void SinglePosition::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("SinglePosition"); stream->writeSint32(posx, "posx"); stream->writeSint32(posy, "posy"); stream->writeLeaveSection(); } BuildingOrder::BuildingOrder(int building_type, int number_of_workers) : building_type(building_type), number_of_workers(number_of_workers) { } bool BuildingOrder::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("BuildingOrder"); building_type=stream->readUint32("building_type"); number_of_workers=stream->readUint32("number_of_workers"); stream->readEnterSection("constraints"); Uint32 size = stream->readUint32("size"); constraints.resize(size); for(unsigned x=0; xreadEnterSection(x); constraints[x] = boost::shared_ptr(Constraint::load_constraint(stream, player, versionMinor)); stream->readLeaveSection(); } stream->readLeaveSection(); stream->readEnterSection("conditions"); size = stream->readUint32("size"); conditions.resize(size); for(unsigned x=0; xreadEnterSection(x); conditions[x] = boost::shared_ptr(Condition::load_condition(stream, player, versionMinor)); stream->readLeaveSection(); } stream->readLeaveSection(); stream->readLeaveSection(); return true; } void BuildingOrder::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("BuildingOrder"); stream->writeUint32(building_type, "building_type"); stream->writeUint32(number_of_workers, "number_of_workers"); stream->writeEnterSection("constraints"); stream->writeUint32(constraints.size(), "size"); for(unsigned x=0; xwriteEnterSection(x); Constraint::save_constraint(constraints[x].get(), stream); stream->writeLeaveSection(); } stream->writeLeaveSection(); stream->writeEnterSection("conditions"); stream->writeUint32(conditions.size(), "size"); for(unsigned x=0; xwriteEnterSection(x); Condition::save_condition(conditions[x].get(), stream); stream->writeLeaveSection(); } stream->writeLeaveSection(); stream->writeLeaveSection(); } void BuildingOrder::add_constraint(Constraint* constraint) { constraints.push_back(boost::shared_ptr(constraint)); } void BuildingOrder::add_condition(Condition* condition) { conditions.push_back(boost::shared_ptr(condition)); } position BuildingOrder::find_location(Echo& echo, Map* map, GradientManager& manager) { position best(0,0); Player* player=echo.player; int best_score=std::numeric_limits::min(); BuildingType* type=globalContainer->buildingsTypes.getByType(IntBuildingType::typeFromShortNumber(building_type), 0, true); bool check_flag=false; //If theres no type for a construction zone, then this is a flag if(type==NULL) { type=globalContainer->buildingsTypes.getByType(IntBuildingType::typeFromShortNumber(building_type), 0, false); check_flag=true; } for(int x=0; xgetW(); ++x) { for(int y=0; ygetH(); ++y) { if(!check_flag && !map->isHardSpaceForBuilding(x, y, type->width, type->height)) continue; if(check_flag && echo.get_flag_map().get_flag(x, y)!=NOGBID) continue; int score=0; bool passes=true; for(std::vector >::iterator i=constraints.begin(); i!=constraints.end(); ++i) { for(int x2=0; x2width && passes; ++x2) for(int y2=0; y2height && passes; ++y2) if((x2==0 || y2==0 || x2==type->width-1 || y2==type->height-1)) { if(!(*i)->passes_constraint(echo, map->normalizeX(x+x2), map->normalizeY(y+y2))) { passes=false; } } if(!passes) { break; } if(!check_flag && (!map->isMapDiscovered(x, y, player->team->allies) || !map->isMapDiscovered(x+type->width-1, y+type->height-1, player->team->allies)) ) { passes=false; break; } score+=(*i)->calculate_constraint(echo, map->normalizeX(x), map->normalizeY(y)); score+=(*i)->calculate_constraint(echo, map->normalizeX(x+type->width-1), map->normalizeY(y+type->height-1)); score+=(*i)->calculate_constraint(echo, map->normalizeX(x), map->normalizeY(y+type->height-1)); score+=(*i)->calculate_constraint(echo, map->normalizeX(x+type->width-1), map->normalizeY(y)); } if(!passes) continue; if(score>best_score) { best=position(x, y); best_score=score; } } } return best; } boost::logic::tribool BuildingOrder::passes_conditions(Echo& echo) { for(unsigned int i=0; ipasses(echo); if(passes) continue; else if(!passes) return false; else return indeterminate; } for(unsigned n=0; nget_gradient_info()) { bool is_updated=echo.get_gradient_manager().is_updated(*constraints[n]->get_gradient_info()); if(!is_updated) return false; } } return true; } void BuildingOrder::queue_gradients(Gradients::GradientManager& manager) { for(unsigned n=0; nget_gradient_info()) { manager.queue_gradient(*constraints[n]->get_gradient_info()); } } } FlagMap::FlagMap(Echo& echo) : flagmap(echo.player->map->getW()*echo.player->map->getH(), NOGBID), width(echo.player->map->getW()), echo(echo) { } int FlagMap::get_flag(int x, int y) { return flagmap[y*width+x]; } void FlagMap::set_flag(int x, int y, int gid) { flagmap[y*width+x]=gid; } bool FlagMap::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("FlagMap"); stream->readEnterSection("flagmap"); Uint32 size=stream->readUint32("size"); flagmap.resize(size); for (Uint32 flagmap_index = 0; flagmap_index < size; flagmap_index++) { stream->readEnterSection(flagmap_index); flagmap[flagmap_index]=stream->readUint32("gid"); stream->readLeaveSection(); } stream->readLeaveSection(); width=stream->readUint32("width"); stream->readLeaveSection(); return true; } void FlagMap::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("FlagMap"); stream->writeEnterSection("flagmap"); stream->writeUint32(flagmap.size(), "size"); for (Uint32 flagmap_index = 0; flagmap_index < flagmap.size(); flagmap_index++) { stream->writeEnterSection(flagmap_index); stream->writeUint32(flagmap[flagmap_index], "gid"); stream->writeLeaveSection(); } stream->writeLeaveSection(); stream->writeUint32(width, "width"); stream->writeLeaveSection(); } BuildingRegister::BuildingRegister(Player* player, Echo& echo) : building_id(0), player(player), echo(echo) { } void BuildingRegister::initiate() { for(unsigned int i=0; i<1024; ++i) { Building* b=player->team->myBuildings[i]; if(b!=NULL) { found_buildings[building_id++]=boost::make_tuple(b->posX, b->posY, b->type->shortTypeNum, b->gid, false); } } } unsigned int BuildingRegister::register_building() { pending_buildings[building_id]=boost::make_tuple(-1, -1, -1, -1); return building_id++; } void BuildingRegister::issue_order(int id, int x, int y, int building_type) { pending_buildings[id]=boost::make_tuple(x, y, building_type, 0); } void BuildingRegister::remove_building(int id) { pending_buildings.erase(id); } bool BuildingRegister::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("BuildingRegister"); stream->readEnterSection("pending_buildings"); Uint32 pending_size=stream->readUint32("size"); for(Uint32 pending_index=0; pending_indexreadEnterSection(pending_index); Uint32 id=stream->readSint32("echo_building_id"); Uint32 x=stream->readSint32("xpos"); Uint32 y=stream->readSint32("ypos"); Uint32 type=stream->readSint32("building_type"); Uint32 ticks=stream->readSint32("ticks_since_registered"); pending_buildings[id]=boost::make_tuple(x, y, type, ticks); stream->readLeaveSection(); } stream->readLeaveSection(); stream->readEnterSection("found_buildings"); Uint32 found_size=stream->readUint32("size"); for(Uint32 found_index=0; found_indexreadEnterSection(found_index); Uint32 id=stream->readUint32("echo_building_id"); Uint32 xpos=stream->readUint32("xpos"); Uint32 ypos=stream->readUint32("ypos"); Uint32 building_type=stream->readUint32("building_type"); Uint32 gid=stream->readUint32("gid"); Uint8 upgrade_status=stream->readUint8("upgrade_status"); boost::logic::tribool t; if(upgrade_status==0) t=false; else if(upgrade_status==1) t=true; else t=indeterminate; found_buildings[id]=boost::make_tuple(xpos, ypos, building_type, gid, t); stream->readLeaveSection(); } stream->readLeaveSection(); building_id=stream->readUint32("building_id"); stream->readLeaveSection(); return true; } void BuildingRegister::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("BuildingRegister"); stream->writeEnterSection("pending_buildings"); unsigned int pending_size=0; stream->writeUint32(pending_buildings.size(), "size"); for(pending_iterator i=pending_buildings.begin(); i!=pending_buildings.end(); ++i) { stream->writeEnterSection(pending_size); stream->writeSint32(i->first, "echo_building_id"); stream->writeSint32(i->second.get<0>(), "xpos"); stream->writeSint32(i->second.get<1>(), "ypos"); stream->writeSint32(i->second.get<2>(), "building_type"); stream->writeSint32(i->second.get<3>(), "ticks_since_registered"); stream->writeLeaveSection(); pending_size++; } stream->writeLeaveSection(); stream->writeEnterSection("found_buildings"); unsigned int found_size=0; stream->writeUint32(found_buildings.size(), "size"); for(found_iterator i=found_buildings.begin(); i!=found_buildings.end(); ++i) { stream->writeEnterSection(found_size); stream->writeUint32(i->first, "echo_building_id"); stream->writeUint32(i->second.get<0>(), "xpos"); stream->writeUint32(i->second.get<1>(), "ypos"); stream->writeUint32(i->second.get<2>(), "building_type"); stream->writeUint32(i->second.get<3>(), "gid"); if(i->second.get<4>()) stream->writeUint8(1, "upgrade_status"); else if(!i->second.get<4>()) stream->writeUint8(0, "upgrade_status"); else stream->writeUint8(2, "upgrade_status"); stream->writeLeaveSection(); found_size++; } stream->writeLeaveSection(); stream->writeUint32(building_id, "building_id"); stream->writeLeaveSection(); } void BuildingRegister::set_upgrading(unsigned int id) { found_buildings[id].get<4>()=indeterminate; } void BuildingRegister::tick() { for(pending_iterator i=pending_buildings.begin(); i!=pending_buildings.end();) { //When get<3>() is -1, it means that the building order hasen't been sent to the glob2 engine yet. //This is used when the building is registered, but awaiting conditions to be satisfied. if(i->second.get<3>()!=-1) { i->second.get<3>()++; if(i->second.get<3>() > 300) { pending_iterator current=i; ++i; pending_buildings.erase(current); continue; } int gbid=NOGBID; if(i->second.get<2>() > IntBuildingType::DEFENSE_BUILDING && i->second.get<2>() < IntBuildingType::STONE_WALL) { gbid=is_flag(echo, i->second.get<0>(), i->second.get<1>()); } else { gbid=player->map->getBuilding(i->second.get<0>(), i->second.get<1>()); } if(gbid!=NOGBID) { if(i->second.get<2>() > IntBuildingType::DEFENSE_BUILDING && i->second.get<2>() < IntBuildingType::STONE_WALL) { echo.get_flag_map().set_flag(i->second.get<0>(), i->second.get<1>(), gbid); } found_buildings[i->first]=boost::make_tuple(i->second.get<0>(), i->second.get<1>(), i->second.get<2>(), gbid, false); pending_iterator current=i; ++i; pending_buildings.erase(current); continue; } } ++i; } for(found_iterator i = found_buildings.begin(); i!=found_buildings.end();) { if(i->second.get<2>() > IntBuildingType::DEFENSE_BUILDING && i->second.get<2>() < IntBuildingType::STONE_WALL) { if(echo.get_flag_map().get_flag(i->second.get<0>(), i->second.get<1>())==NOGBID) { found_iterator current=i; ++i; found_buildings.erase(current); continue; } if(player->team->myBuildings[::Building::GIDtoID(i->second.get<3>())]==NULL) { echo.get_flag_map().set_flag(i->second.get<0>(), i->second.get<1>(), NOGBID); found_iterator current=i; ++i; found_buildings.erase(current); continue; } } else { const int gbid=player->map->getBuilding(i->second.get<0>(), i->second.get<1>()); if(gbid==NOGBID || gbid != i->second.get<3>()) { found_iterator current=i; ++i; found_buildings.erase(current); continue; } Building* b=player->team->myBuildings[::Building::GIDtoID(gbid)]; if(b==NULL) { found_iterator current=i; ++i; found_buildings.erase(current); continue; } //True if(i->second.get<4>()) { i->second.get<0>()=b->posX; i->second.get<1>()=b->posY; if(b->constructionResultState==::Building::NO_CONSTRUCTION) { i->second.get<4>()=false; } } //False else if(!i->second.get<4>()) { } //Indeterminate else { if(b->constructionResultState!=::Building::NO_CONSTRUCTION) { i->second.get<4>()=true; } } } ++i; } } bool BuildingRegister::is_building_pending(unsigned int id) { return pending_buildings.find(id)!=pending_buildings.end(); } bool BuildingRegister::is_building_found(unsigned int id) { return found_buildings.find(id)!=found_buildings.end(); } bool BuildingRegister::is_building_upgrading(unsigned int id) { tribool v=found_buildings[id].get<4>(); if(v) return true; else if(!v) return false; return true; } Building* BuildingRegister::get_building(unsigned int id) { return player->team->myBuildings[::Building::GIDtoID(found_buildings[id].get<3>())]; } BuildingType* BuildingRegister::get_building_type(unsigned int id) { return player->team->myBuildings[::Building::GIDtoID(found_buildings[id].get<3>())]->type; } int BuildingRegister::get_type(unsigned int id) { return found_buildings[id].get<2>(); } int BuildingRegister::get_level(unsigned int id) { return get_building(id)->type->level+1; } int BuildingRegister::get_assigned(unsigned int id) { return get_building(id)->maxUnitWorking; } Condition* Condition::load_condition(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("Condition"); ConditionType type=static_cast(stream->readUint32("type")); Condition* condition=NULL; switch(type) { case CParticularBuilding: condition=new ParticularBuilding; condition->load(stream, player, versionMinor); break; case CBuildingDestroyed: condition=new BuildingDestroyed; condition->load(stream, player, versionMinor); break; case CEnemyBuildingDestroyed: condition=new EnemyBuildingDestroyed; condition->load(stream, player, versionMinor); break; case CEitherCondition: condition=new EitherCondition; condition->load(stream, player, versionMinor); break; case CAllConditions: condition=new AllConditions; condition->load(stream, player, versionMinor); break; case CPopulation: condition=new Population; condition->load(stream, player, versionMinor); break; } stream->readLeaveSection(); return condition; } void Condition::save_condition(Condition* condition, GAGCore::OutputStream *stream) { stream->writeEnterSection("Condition"); stream->writeUint32(condition->get_type(), "type"); condition->save(stream); stream->writeLeaveSection(); } ParticularBuilding::ParticularBuilding() : condition(NULL), id(-1) { } ParticularBuilding::ParticularBuilding(BuildingCondition* condition, int id) : condition(condition), id(id) { } ParticularBuilding::~ParticularBuilding() { if(condition) delete condition; } boost::logic::tribool ParticularBuilding::passes(Echo& echo) { if(!echo.get_building_register().is_building_found(id) && !echo.get_building_register().is_building_pending(id)) { return indeterminate; } if(echo.get_building_register().is_building_found(id)) { bool passes=condition->passes(echo, id); return passes; } return false; } ConditionType ParticularBuilding::get_type() { return CParticularBuilding; } bool ParticularBuilding::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("ParticularBuilding"); id=stream->readSint32("id"); condition=BuildingCondition::load_condition(stream, player, versionMinor); stream->readLeaveSection(); return true; } void ParticularBuilding::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("ParticularBuilding"); stream->writeSint32(id, "id"); BuildingCondition::save_condition(condition, stream); stream->writeLeaveSection(); } BuildingDestroyed::BuildingDestroyed(int id) : id(id) { } boost::logic::tribool BuildingDestroyed::passes(Echo& echo) { if(!echo.get_building_register().is_building_found(id) && !echo.get_building_register().is_building_pending(id)) { return true; } return false; } ConditionType BuildingDestroyed::get_type() { return CBuildingDestroyed; } bool BuildingDestroyed::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("BuildingDestroyed"); id=stream->readSint32("id"); stream->readLeaveSection(); return true; } void BuildingDestroyed::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("BuildingDestroyed"); stream->writeSint32(id, "id"); stream->writeLeaveSection(); } EnemyBuildingDestroyed::EnemyBuildingDestroyed(Echo& echo, int gbid) : gbid(gbid) { Building* b=echo.player->game->teams[Building::GIDtoTeam(gbid)]->myBuildings[Building::GIDtoID(gbid)]; type=b->type->shortTypeNum; level=b->type->level; location=position(b->posX, b->posY); } boost::logic::tribool EnemyBuildingDestroyed::passes(Echo& echo) { Building* b=echo.player->game->teams[Building::GIDtoTeam(gbid)]->myBuildings[Building::GIDtoID(gbid)]; if(b==NULL) { return true; } if(b->posX != location.x || b->posY != location.y) { return true; } if(b->type->shortTypeNum != type) { return true; } return false; } bool EnemyBuildingDestroyed::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("EnemyBuildingDestroyed"); gbid=stream->readUint32("gbid"); type=stream->readUint32("type"); level=stream->readUint32("level"); int posx=stream->readUint32("posx"); int posy=stream->readUint32("posy"); location=position(posx, posy); stream->readLeaveSection(); return true; } void EnemyBuildingDestroyed::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("EnemyBuildingDestroyed"); stream->writeUint32(gbid, "gbid"); stream->writeUint32(type, "type"); stream->writeUint32(level, "level"); stream->writeUint32(location.x, "posx"); stream->writeUint32(location.y, "posy"); stream->writeLeaveSection(); } EitherCondition::EitherCondition(Condition* condition1, Condition* condition2) : condition1(condition1), condition2(condition2) { } EitherCondition::~EitherCondition() { delete condition1; delete condition2; } boost::logic::tribool EitherCondition::passes(Echo& echo) { tribool p1=condition1->passes(echo); tribool p2=condition2->passes(echo); if(p1 || p2) return true; else if(!p1 || !p2) return false; else return indeterminate; } ConditionType EitherCondition::get_type() { return CEitherCondition; } bool EitherCondition::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("EitherCondition"); condition1=Condition::load_condition(stream, player, versionMinor); condition2=Condition::load_condition(stream, player, versionMinor); stream->readLeaveSection(); return true; } void EitherCondition::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("EitherCondition"); Condition::save_condition(condition1, stream); Condition::save_condition(condition2, stream); stream->writeLeaveSection(); } EitherCondition::EitherCondition() { } AllConditions::AllConditions(Condition* a, Condition* b, Condition* c, Condition* d) : a(a), b(b), c(c), d(d) { } AllConditions::~AllConditions() { if(a) delete a; if(b) delete b; if(c) delete c; if(d) delete d; } boost::logic::tribool AllConditions::passes(Echo& echo) { tribool a2=true; tribool b2=true; tribool c2=true; tribool d2=true; if(a) a2=a->passes(echo); if(b) b2=b->passes(echo); if(c) c2=c->passes(echo); if(d) d2=d->passes(echo); if(a2 && b2 && c2 && d2) return true; if(a2==indeterminate) return indeterminate; if(b2==indeterminate) return indeterminate; if(c2==indeterminate) return indeterminate; if(d2==indeterminate) return indeterminate; return false; } ConditionType AllConditions::get_type() { return CAllConditions; } bool AllConditions::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("EitherCondition"); bool condition_is_null=stream->readUint8("condition_is_null"); if(condition_is_null) a=NULL; else a=Condition::load_condition(stream, player, versionMinor); condition_is_null=stream->readUint8("condition_is_null"); if(condition_is_null) b=NULL; else b=Condition::load_condition(stream, player, versionMinor); condition_is_null=stream->readUint8("condition_is_null"); if(condition_is_null) c=NULL; else c=Condition::load_condition(stream, player, versionMinor); condition_is_null=stream->readUint8("condition_is_null"); if(condition_is_null) d=NULL; else d=Condition::load_condition(stream, player, versionMinor); stream->readLeaveSection(); return true; } void AllConditions::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("AllConditions"); if(a) { stream->writeUint8(false, "condition_is_null"); Condition::save_condition(a, stream); } else stream->writeUint8(true, "condition_is_null"); if(b) { stream->writeUint8(false, "condition_is_null"); Condition::save_condition(b, stream); } else stream->writeUint8(true, "condition_is_null"); if(c) { stream->writeUint8(false, "condition_is_null"); Condition::save_condition(c, stream); } else stream->writeUint8(true, "condition_is_null"); if(d) { stream->writeUint8(false, "condition_is_null"); Condition::save_condition(d, stream); } else stream->writeUint8(true, "condition_is_null"); stream->writeLeaveSection(); } AllConditions::AllConditions() { } Population::Population(bool workers, bool explorers, bool warriors, int num, PopulationMethod method) : workers(workers), explorers(explorers), warriors(warriors), num(num), method(method) { } Population::~Population() { } boost::logic::tribool Population::passes(Echo& echo) { int amount=0; if(workers) amount+=echo.player->team->stats.getLatestStat()->numberUnitPerType[WORKER]; if(explorers) amount+=echo.player->team->stats.getLatestStat()->numberUnitPerType[EXPLORER]; if(warriors) amount+=echo.player->team->stats.getLatestStat()->numberUnitPerType[WARRIOR]; if(method==Greater) { return (amount >= num); } else if(method==Lesser) { return (amount <= num); } return false; } ConditionType Population::get_type() { return CPopulation; } bool Population::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("Population"); workers=stream->readUint8("workers"); explorers=stream->readUint8("explorers"); warriors=stream->readUint8("warriors"); num=stream->readSint32("num"); method=static_cast(stream->readUint32("method")); stream->readLeaveSection(); return true; } void Population::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("Population"); stream->writeUint8(workers, "workers"); stream->writeUint8(explorers, "explorers"); stream->writeUint8(warriors, "warriors"); stream->writeSint32(num, "num"); stream->writeUint32(static_cast(method), "method"); stream->writeLeaveSection(); } Population::Population() { } BuildingCondition* BuildingCondition::load_condition(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("BuildingCondition"); BuildingConditionType type=static_cast(stream->readUint32("type")); BuildingCondition* condition=NULL; switch(type) { case CNotUnderConstruction: condition=new NotUnderConstruction; condition->load(stream, player, versionMinor); break; case CUnderConstruction: condition=new UnderConstruction; condition->load(stream, player, versionMinor); break; case CBeingUpgraded: condition=new BeingUpgraded; condition->load(stream, player, versionMinor); break; case CBeingUpgradedTo: condition=new BeingUpgradedTo; condition->load(stream, player, versionMinor); break; case CSpecificBuildingType: condition=new SpecificBuildingType; condition->load(stream, player, versionMinor); break; case CNotSpecificBuildingType: condition=new NotSpecificBuildingType; condition->load(stream, player, versionMinor); break; case CBuildingLevel: condition=new BuildingLevel; condition->load(stream, player, versionMinor); break; case CUpgradable: condition=new Upgradable; condition->load(stream, player, versionMinor); break; case CRessourceTrackerAmount: condition=new RessourceTrackerAmount; condition->load(stream, player, versionMinor); break; case CRessourceTrackerAge: condition=new RessourceTrackerAge; condition->load(stream, player, versionMinor); break; case CTicksPassed: condition=new TicksPassed; condition->load(stream, player, versionMinor); break; } stream->readLeaveSection(); return condition; } void BuildingCondition::save_condition(BuildingCondition* condition, GAGCore::OutputStream *stream) { stream->writeEnterSection("BuildingCondition"); stream->writeUint32(condition->get_type(), "type"); condition->save(stream); stream->writeLeaveSection(); } bool NotUnderConstruction::passes(Echo& echo, int id) { Building* building = echo.get_building_register().get_building(id); bool result=building->constructionResultState==::Building::NO_CONSTRUCTION && !echo.get_building_register().is_building_upgrading(id); return result; } bool NotUnderConstruction::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("NotUnderConstruction"); stream->readLeaveSection(); return true; } void NotUnderConstruction::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("NotUnderConstruction"); stream->writeLeaveSection(); } bool UnderConstruction::passes(Echo& echo, int id) { Building* building = echo.get_building_register().get_building(id); return building->constructionResultState!=::Building::NO_CONSTRUCTION && building->buildingState==Building::ALIVE; } bool UnderConstruction::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("UnderConstruction"); stream->readLeaveSection(); return true; } void UnderConstruction::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("UnderConstruction"); stream->writeLeaveSection(); } SpecificBuildingType::SpecificBuildingType(int building_type) : building_type(building_type) { } bool SpecificBuildingType::passes(Echo& echo, int id) { if(echo.get_building_register().get_type(id)==building_type) return true; return false; } bool SpecificBuildingType::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("SpecificBuildingType"); building_type=stream->readUint32("building_type"); stream->readLeaveSection(); return true; } void SpecificBuildingType::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("SpecificBuildingType"); stream->writeUint32(building_type, "building_type"); stream->writeLeaveSection(); } NotSpecificBuildingType::NotSpecificBuildingType(int building_type) : building_type(building_type) { } bool NotSpecificBuildingType::passes(Echo& echo, int id) { if(echo.get_building_register().get_type(id)!=building_type) return true; return false; } bool NotSpecificBuildingType::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("NotSpecificBuildingType"); building_type=stream->readUint32("building_type"); stream->readLeaveSection(); return true; } void NotSpecificBuildingType::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("NotSpecificBuildingType"); stream->writeUint32(building_type, "building_type"); stream->writeLeaveSection(); } bool BeingUpgraded::passes(Echo& echo, int id) { return echo.get_building_register().is_building_upgrading(id); } bool BeingUpgraded::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("BeingUpgraded"); stream->readLeaveSection(); return true; } void BeingUpgraded::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("BeingUpgraded"); stream->writeLeaveSection(); } BeingUpgradedTo::BeingUpgradedTo(int level) : level(level) { } bool BeingUpgradedTo::passes(Echo& echo, int id) { Building* b= echo.get_building_register().get_building(id); if(!echo.get_building_register().is_building_upgrading(id)) return false; if(b->type->isBuildingSite) { if(b->type->level==(level-1)) { return true; } } else if(b->type->level==(level-2)) { return true; } return false; } bool BeingUpgradedTo::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("BeingUpgradedTo"); level=stream->readUint32("level"); stream->readLeaveSection(); return true; } void BeingUpgradedTo::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("BeingUpgradedTo"); stream->writeUint32(level, "level"); stream->writeLeaveSection(); } BuildingLevel::BuildingLevel(int building_level) : building_level(building_level) { } bool BuildingLevel::passes(Echo& echo, int id) { Building* building = echo.get_building_register().get_building(id); if(building->type->level==building_level-1) return true; return false; } bool BuildingLevel::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("BuildingLevel"); building_level=stream->readUint32("building_level"); stream->readLeaveSection(); return true; } void BuildingLevel::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("BuildingLevel"); stream->writeUint32(building_level, "building_level"); stream->writeLeaveSection(); } bool Upgradable::passes(Echo& echo, int id) { Building* building = echo.get_building_register().get_building(id); if((building->type->shortTypeNum==IntBuildingType::FOOD_BUILDING || building->type->shortTypeNum==IntBuildingType::HEAL_BUILDING || building->type->shortTypeNum==IntBuildingType::SWIMSPEED_BUILDING || building->type->shortTypeNum==IntBuildingType::WALKSPEED_BUILDING || building->type->shortTypeNum==IntBuildingType::ATTACK_BUILDING || building->type->shortTypeNum==IntBuildingType::SCIENCE_BUILDING || building->type->shortTypeNum==IntBuildingType::DEFENSE_BUILDING) && building->constructionResultState==Building::NO_CONSTRUCTION && building->type->level!=2 && building->isHardSpaceForBuildingSite(Building::UPGRADE) && building->hp == building->type->hpMax ) return true; return false; } bool Upgradable::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("Upgradable"); stream->readLeaveSection(); return true; } void Upgradable::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("Upgradable"); stream->writeLeaveSection(); } RessourceTrackerAmount::RessourceTrackerAmount(int amount, TrackerMethod tracker_method) : amount(amount), tracker_method(tracker_method) { } RessourceTrackerAmount::RessourceTrackerAmount() { } bool RessourceTrackerAmount::passes(Echo& echo, int id) { if(tracker_method==Greater) { return echo.get_ressource_tracker(id)->get_total_level() > amount; } else if(tracker_method==Lesser) { return echo.get_ressource_tracker(id)->get_total_level() < amount; } return false; } BuildingConditionType RessourceTrackerAmount::get_type() { return CRessourceTrackerAmount; } bool RessourceTrackerAmount::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("RessourceTrackerAmount"); amount=stream->readUint32("amount"); tracker_method=static_cast(stream->readUint32("tracker_method")); stream->readLeaveSection(); return true; } void RessourceTrackerAmount::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("RessourceTrackerAmount"); stream->writeUint32(amount, "amount"); stream->writeUint32(static_cast(tracker_method), "tracker_method"); stream->writeLeaveSection(); } RessourceTrackerAge::RessourceTrackerAge(int age, TrackerMethod tracker_method) : age(age), tracker_method(tracker_method) { } RessourceTrackerAge::RessourceTrackerAge() { } bool RessourceTrackerAge::passes(Echo& echo, int id) { if(tracker_method==Greater) { return echo.get_ressource_tracker(id)->get_age() > age; } else if(tracker_method==Lesser) { return echo.get_ressource_tracker(id)->get_age() < age; } return false; } BuildingConditionType RessourceTrackerAge::get_type() { return CRessourceTrackerAge; } bool RessourceTrackerAge::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("RessourceTrackerAge"); age=stream->readUint32("age"); tracker_method=static_cast(stream->readUint32("tracker_method")); stream->readLeaveSection(); return true; } void RessourceTrackerAge::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("RessourceTrackerAge"); stream->writeUint32(age, "age"); stream->writeUint32(static_cast(tracker_method), "tracker_method"); stream->writeLeaveSection(); } bool ManagementOrder::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("ManagementOrder"); stream->readEnterSection("conditions"); Uint32 size = stream->readUint32("size"); conditions.resize(size); for(unsigned x=0; xreadEnterSection(x); conditions[x] = boost::shared_ptr(Condition::load_condition(stream, player, versionMinor)); stream->readLeaveSection(); } stream->readLeaveSection(); stream->readLeaveSection(); return true; } void ManagementOrder::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("ManagementOrder"); stream->writeEnterSection("conditions"); stream->writeUint32(conditions.size(), "size"); for(unsigned x=0; xwriteEnterSection(x); Condition::save_condition(conditions[x].get(), stream); stream->writeLeaveSection(); } stream->writeLeaveSection(); stream->writeLeaveSection(); } void ManagementOrder::add_condition(Condition* condition) { conditions.push_back(boost::shared_ptr(condition)); } boost::logic::tribool ManagementOrder::passes_conditions(Echo& echo) { for(unsigned int i=0; ipasses(echo); if(passes) continue; else if(!passes) return false; else return indeterminate; } boost::logic::tribool passes=wait(echo); if(passes) return true; if(!passes) return false; else return indeterminate; return true; } ManagementOrder* ManagementOrder::load_order(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("ManagementOrder"); ManagementOrderType mot=static_cast(stream->readUint32("type")); ManagementOrder* mo=NULL; switch(mot) { case MAssignWorkers: mo=new AssignWorkers; mo->load(stream, player, versionMinor); break; case MChangeSwarm: mo=new ChangeSwarm; mo->load(stream, player, versionMinor); break; case MDestroyBuilding: mo=new DestroyBuilding; mo->load(stream, player, versionMinor); break; case MAddRessourceTracker: mo=new AddRessourceTracker; mo->load(stream, player, versionMinor); break; case MPauseRessourceTracker: mo=new PauseRessourceTracker; mo->load(stream, player, versionMinor); break; case MUnPauseRessourceTracker: mo=new UnPauseRessourceTracker; mo->load(stream, player, versionMinor); break; case MChangeFlagSize: mo=new ChangeFlagSize; mo->load(stream, player, versionMinor); break; case MChangeFlagMinimumLevel: mo=new ChangeFlagMinimumLevel; mo->load(stream, player, versionMinor); break; case MAddArea: mo=new AddArea; mo->load(stream, player, versionMinor); break; case MRemoveArea: mo=new RemoveArea; mo->load(stream, player, versionMinor); break; case MChangeAlliances: mo=new ChangeAlliances; mo->load(stream, player, versionMinor); break; case MUpgradeRepair: mo=new UpgradeRepair; mo->load(stream, player, versionMinor); break; case MSendMessage: mo=new SendMessage; mo->load(stream, player, versionMinor); break; } return mo; } void ManagementOrder::save_order(ManagementOrder* mo, GAGCore::OutputStream *stream) { stream->writeEnterSection("ManagementOrder"); stream->writeUint32(mo->get_type(), "type"); mo->save(stream); stream->writeLeaveSection(); } AssignWorkers::AssignWorkers(int number_of_workers, int building_id) : number_of_workers(number_of_workers), building_id(building_id) { } void AssignWorkers::modify(Echo& echo) { echo.push_order(shared_ptr(new OrderModifyBuilding(echo.get_building_register().get_building(building_id)->gid, number_of_workers))); } boost::logic::tribool AssignWorkers::wait(Echo& echo) { if(echo.get_building_register().is_building_found(building_id)) return true; else if(echo.get_building_register().is_building_pending(building_id)) return false; else return indeterminate; } bool AssignWorkers::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("AssignWorkers"); ManagementOrder::load(stream, player, versionMinor); number_of_workers=stream->readUint32("number_of_workers"); building_id=stream->readUint32("building_id"); stream->readLeaveSection(); return true; } void AssignWorkers::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("AssignWorkers"); ManagementOrder::save(stream); stream->writeUint32(number_of_workers, "number_of_workers"); stream->writeUint32(building_id, "building_id"); stream->writeLeaveSection(); } ChangeSwarm::ChangeSwarm(int worker_ratio, int explorer_ratio, int warrior_ratio, int building_id) : worker_ratio(worker_ratio), explorer_ratio(explorer_ratio), warrior_ratio(warrior_ratio), building_id(building_id) { } void ChangeSwarm::modify(Echo& echo) { Sint32 ratio[NB_UNIT_TYPE]; ratio[0]=worker_ratio; ratio[1]=explorer_ratio; ratio[2]=warrior_ratio; echo.push_order(shared_ptr(new OrderModifySwarm(echo.get_building_register().get_building(building_id)->gid, ratio))); } boost::logic::tribool ChangeSwarm::wait(Echo& echo) { if(echo.get_building_register().is_building_found(building_id)) return true; else if(echo.get_building_register().is_building_pending(building_id)) return false; else return indeterminate; } bool ChangeSwarm::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("ChangeSwarm"); ManagementOrder::load(stream, player, versionMinor); worker_ratio=stream->readUint32("worker_ratio"); explorer_ratio=stream->readUint32("explorer_ratio"); warrior_ratio=stream->readUint32("warrior_ratio"); building_id=stream->readUint32("building_id"); stream->readLeaveSection(); return true; } void ChangeSwarm::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("ChangeSwarm"); ManagementOrder::save(stream); stream->writeUint32(worker_ratio, "worker_ratio"); stream->writeUint32(explorer_ratio, "explorer_ratio"); stream->writeUint32(warrior_ratio, "warrior_ratio"); stream->writeUint32(building_id, "building_id"); stream->writeLeaveSection(); } DestroyBuilding::DestroyBuilding(int building_id) : building_id(building_id) { } void DestroyBuilding::modify(Echo& echo) { echo.push_order(shared_ptr(new OrderDelete(echo.get_building_register().get_building(building_id)->gid))); } boost::logic::tribool DestroyBuilding::wait(Echo& echo) { if(echo.get_building_register().is_building_found(building_id)) return true; else if(echo.get_building_register().is_building_pending(building_id)) return false; else return indeterminate; } bool DestroyBuilding::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("DestroyBuilding"); ManagementOrder::load(stream, player, versionMinor); building_id=stream->readUint32("building_id"); stream->readLeaveSection(); return true; } void DestroyBuilding::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("DestroyBuilding"); ManagementOrder::save(stream); stream->writeUint32(building_id, "building_id"); stream->writeLeaveSection(); } RessourceTracker::RessourceTracker(Echo& echo, int building_id, int length, int ressource) : record(length, 0), position(0), timer(0), length(length), echo(echo), building_id(building_id), ressource(ressource) { } void RessourceTracker::tick() { timer++; if((timer%10)==0) { Building* b = echo.get_building_register().get_building(building_id); record[position]=b->ressources[ressource]; position++; if(position>=record.size()) position=0; } } int RessourceTracker::get_total_level() { int sum=0; for(unsigned int n=0; nreadEnterSection("RessourceTracker"); stream->readEnterSection("record"); Uint32 recordsize=stream->readUint32("size"); record.resize(recordsize); for(unsigned int record_index=0; record_indexreadEnterSection(record_index); record[record_index]=stream->readUint32("quantity_of_ressources"); stream->readLeaveSection(); } stream->readLeaveSection(); position=stream->readUint32("position"); timer=stream->readUint32("timer"); building_id=stream->readUint32("building_id"); length=stream->readUint32("length"); ressource=stream->readUint32("ressource"); stream->readLeaveSection(); return true; } void RessourceTracker::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("RessourceTracker"); stream->writeEnterSection("record"); stream->writeUint32(record.size(), "size"); for(unsigned int record_index=0; record_indexwriteEnterSection(record_index); stream->writeUint32(record[record_index], "quantity_of_ressources"); stream->writeLeaveSection(); } stream->writeLeaveSection(); stream->writeUint32(position, "position"); stream->writeUint32(timer, "timer"); stream->writeUint32(building_id, "building_id"); stream->writeUint32(length, "length"); stream->writeUint32(ressource, "ressource"); stream->writeLeaveSection(); } AddRessourceTracker::AddRessourceTracker(int length, int ressource, int building_id) : length(length), building_id(building_id), ressource(ressource) { } void AddRessourceTracker::modify(Echo& echo) { echo.add_ressource_tracker(new RessourceTracker(echo, building_id, length, ressource), building_id); } boost::logic::tribool AddRessourceTracker::wait(Echo& echo) { if(echo.get_building_register().is_building_found(building_id)) return true; else if(echo.get_building_register().is_building_pending(building_id)) return false; else return indeterminate; } bool AddRessourceTracker::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("AddRessourceTracker"); ManagementOrder::load(stream, player, versionMinor); length=stream->readUint32("length"); building_id=stream->readUint32("building_id"); ressource=stream->readUint32("ressource"); stream->readLeaveSection(); return true; } void AddRessourceTracker::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("AddRessourceTracker"); ManagementOrder::save(stream); stream->writeUint32(length, "length"); stream->writeUint32(building_id, "building_id"); stream->writeUint32(ressource, "ressource"); stream->writeLeaveSection(); } PauseRessourceTracker::PauseRessourceTracker(int building_id) : building_id(building_id) { } void PauseRessourceTracker::modify(Echo& echo) { echo.pause_ressource_tracker(building_id); } boost::logic::tribool PauseRessourceTracker::wait(Echo& echo) { if(echo.get_building_register().is_building_found(building_id)) return true; else if(echo.get_building_register().is_building_pending(building_id)) return false; else return indeterminate; } bool PauseRessourceTracker::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("PauseRessourceTracker"); ManagementOrder::load(stream, player, versionMinor); building_id=stream->readUint32("building_id"); stream->readLeaveSection(); return true; } void PauseRessourceTracker::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("PauseRessourceTracker"); ManagementOrder::save(stream); stream->writeUint32(building_id, "building_id"); stream->writeLeaveSection(); } UnPauseRessourceTracker::UnPauseRessourceTracker(int building_id) : building_id(building_id) { } void UnPauseRessourceTracker::modify(Echo& echo) { echo.unpause_ressource_tracker(building_id); } boost::logic::tribool UnPauseRessourceTracker::wait(Echo& echo) { if(echo.get_building_register().is_building_found(building_id)) return true; else if(echo.get_building_register().is_building_pending(building_id)) return false; else return indeterminate; } bool UnPauseRessourceTracker::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("UnPauseRessourceTracker"); ManagementOrder::load(stream, player, versionMinor); building_id=stream->readUint32("building_id"); stream->readLeaveSection(); return true; } void UnPauseRessourceTracker::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("UnPauseRessourceTracker"); ManagementOrder::save(stream); stream->writeUint32(building_id, "building_id"); stream->writeLeaveSection(); } ChangeFlagSize::ChangeFlagSize(int size, int building_id) : size(size), building_id(building_id) { } void ChangeFlagSize::modify(Echo& echo) { echo.push_order(shared_ptr(new OrderModifyFlag(echo.get_building_register().get_building(building_id)->gid, size))); } boost::logic::tribool ChangeFlagSize::wait(Echo& echo) { if(echo.get_building_register().is_building_found(building_id)) return true; else if(echo.get_building_register().is_building_pending(building_id)) return false; else return indeterminate; } bool ChangeFlagSize::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("ChangeFlagSize"); ManagementOrder::load(stream, player, versionMinor); size=stream->readUint32("size"); building_id=stream->readUint32("building_id"); stream->readLeaveSection(); return true; } void ChangeFlagSize::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("ChangeFlagSize"); ManagementOrder::save(stream); stream->writeUint32(size, "size"); stream->writeUint32(building_id, "building_id"); stream->writeLeaveSection(); } ChangeFlagMinimumLevel::ChangeFlagMinimumLevel(int minimum_level, int building_id) : minimum_level(minimum_level), building_id(building_id) { } void ChangeFlagMinimumLevel::modify(Echo& echo) { echo.push_order(shared_ptr(new OrderModifyMinLevelToFlag(echo.get_building_register().get_building(building_id)->gid, minimum_level-1))); } boost::logic::tribool ChangeFlagMinimumLevel::wait(Echo& echo) { if(echo.get_building_register().is_building_found(building_id)) return true; else if(echo.get_building_register().is_building_pending(building_id)) return false; else return indeterminate; } bool ChangeFlagMinimumLevel::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("ChangeFlagMinimumLevel"); ManagementOrder::load(stream, player, versionMinor); minimum_level=stream->readUint32("minimum_level"); building_id=stream->readUint32("building_id"); stream->readLeaveSection(); return true; } void ChangeFlagMinimumLevel::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("ChangeFlagMinimumLevel"); ManagementOrder::save(stream); stream->writeUint32(minimum_level, "minimum_level"); stream->writeUint32(building_id, "building_id"); stream->writeLeaveSection(); } AddArea::AddArea(AreaType areatype) : areatype(areatype) { } void AddArea::add_location(int x, int y) { locations.push_back(position(x, y)); } void AddArea::modify(Echo& echo) { BrushAccumulator acc; for(std::vector::iterator i=locations.begin(); i!=locations.end(); ++i) { acc.applyBrush(echo.player->map, BrushApplication(echo.player->map->normalizeX(i->x), echo.player->map->normalizeY(i->y), 0)); } if(acc.getApplicationCount()>0) { switch(areatype) { case ClearingArea: echo.push_order(shared_ptr(new OrderAlterateClearArea(echo.player->team->teamNumber, BrushTool::MODE_ADD, &acc))); break; case ForbiddenArea: echo.push_order(shared_ptr(new OrderAlterateForbidden(echo.player->team->teamNumber, BrushTool::MODE_ADD, &acc))); break; case GuardArea: echo.push_order(shared_ptr(new OrderAlterateGuardArea(echo.player->team->teamNumber, BrushTool::MODE_ADD, &acc))); break; } } } boost::logic::tribool AddArea::wait(Echo& echo) { return true; } bool AddArea::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("AddArea"); ManagementOrder::load(stream, player, versionMinor); areatype=static_cast(stream->readUint32("area_type")); stream->readEnterSection("locations"); Uint32 size=stream->readUint32("size"); locations.resize(size); for(Uint32 location_index=0; location_indexreadEnterSection(location_index); locations[location_index]=position(stream->readUint32("posx"), stream->readUint32("posy")); stream->readLeaveSection(); } stream->readLeaveSection(); stream->readLeaveSection(); return true; } void AddArea::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("AddArea"); ManagementOrder::save(stream); stream->writeUint32(areatype, "area_type"); stream->writeEnterSection("locations"); stream->writeUint32(locations.size(), "size"); for(Uint32 location_index=0; location_indexwriteEnterSection(location_index); stream->writeUint32(locations[location_index].x, "posx"); stream->writeUint32(locations[location_index].y, "posy"); stream->writeLeaveSection(); } stream->writeLeaveSection(); stream->writeLeaveSection(); } RemoveArea::RemoveArea(AreaType areatype) : areatype(areatype) { } void RemoveArea::add_location(int x, int y) { locations.push_back(position(x, y)); } void RemoveArea::modify(Echo& echo) { BrushAccumulator acc; for(std::vector::iterator i=locations.begin(); i!=locations.end(); ++i) { acc.applyBrush(echo.player->map, BrushApplication(i->x, i->y, 0)); } if(acc.getApplicationCount()>0) { switch(areatype) { case ClearingArea: echo.push_order(shared_ptr(new OrderAlterateClearArea(echo.player->team->teamNumber, BrushTool::MODE_DEL, &acc))); break; case ForbiddenArea: echo.push_order(shared_ptr(new OrderAlterateForbidden(echo.player->team->teamNumber, BrushTool::MODE_DEL, &acc))); break; case GuardArea: echo.push_order(shared_ptr(new OrderAlterateGuardArea(echo.player->team->teamNumber, BrushTool::MODE_DEL, &acc))); break; } } } boost::logic::tribool RemoveArea::wait(Echo& echo) { return true; } bool RemoveArea::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("RemoveArea"); ManagementOrder::load(stream, player, versionMinor); areatype=static_cast(stream->readUint32("area_type")); stream->readEnterSection("locations"); Uint32 size=stream->readUint32("size"); locations.resize(size); for(Uint32 location_index=0; location_indexreadEnterSection(location_index); locations[location_index]=position(stream->readUint32("posx"), stream->readUint32("posy")); stream->readLeaveSection(); } stream->readLeaveSection(); stream->readLeaveSection(); return true; } void RemoveArea::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("RemoveArea"); ManagementOrder::save(stream); stream->writeUint32(areatype, "area_type"); stream->writeEnterSection("locations"); stream->writeUint32(locations.size(), "size"); for(Uint32 location_index=0; location_indexwriteEnterSection(location_index); stream->writeUint32(locations[location_index].x, "posx"); stream->writeUint32(locations[location_index].y, "posy"); stream->writeLeaveSection(); } stream->writeLeaveSection(); stream->writeLeaveSection(); } ChangeAlliances::ChangeAlliances(int team, boost::logic::tribool is_allied, boost::logic::tribool is_enemy, boost::logic::tribool view_market, boost::logic::tribool view_inn, boost::logic::tribool view_other) : team(team), is_allied(is_allied), is_enemy(is_enemy), view_market(view_market), view_inn(view_inn), view_other(view_other) { } void ChangeAlliances::modify(Echo& echo) { Uint32 alliedmask=echo.allies; Uint32 enemymask=echo.enemies; Uint32 market_mask=echo.market_view; Uint32 inn_mask=echo.inn_view; Uint32 other_mask=echo.other_view; Team* t=echo.player->game->teams[team]; if(is_allied) alliedmask|=t->me; else if(!is_allied) if(alliedmask&t->me) alliedmask^=t->me; if(is_enemy) enemymask|=t->me; else if(!is_enemy) if(enemymask&t->me) enemymask^=t->me; if(view_market) market_mask|=t->me; else if(!view_market) if(market_mask&t->me) market_mask^=t->me; if(view_inn) inn_mask|=t->me; else if(!view_inn) if(inn_mask&t->me) inn_mask^=t->me; if(view_other) other_mask|=t->me; else if(!view_other) if(other_mask&t->me) other_mask^=t->me; echo.allies=alliedmask; echo.enemies=enemymask; echo.market_view=market_mask; echo.inn_view=inn_mask; echo.other_view=other_mask; echo.push_order(shared_ptr(new SetAllianceOrder(echo.player->team->teamNumber, alliedmask, enemymask, market_mask, inn_mask, other_mask))); } boost::logic::tribool ChangeAlliances::wait(Echo& echo) { return true; } bool ChangeAlliances::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("ChangeAlliances"); ManagementOrder::load(stream, player, versionMinor); team=stream->readUint32("team"); Uint8 tmp=stream->readUint8("is_allied"); if(tmp==1) is_allied=true; else if(tmp==0) is_allied=false; else if(tmp==2) is_allied=indeterminate; tmp=stream->readUint8("is_enemy"); if(tmp==1) is_enemy=true; else if(tmp==0) is_enemy=false; else if(tmp==2) is_enemy=indeterminate; tmp=stream->readUint8("view_market"); if(tmp==1) view_market=true; else if(tmp==0) view_market=false; else if(tmp==2) view_market=indeterminate; tmp=stream->readUint8("view_inn"); if(tmp==1) view_inn=true; else if(tmp==0) view_inn=false; else if(tmp==2) view_inn=indeterminate; tmp=stream->readUint8("view_other"); if(tmp==1) view_other=true; else if(tmp==0) view_other=false; else if(tmp==2) view_other=indeterminate; return true; } void ChangeAlliances::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("ChangeAlliances"); ManagementOrder::save(stream); stream->writeUint32(team, "team"); if(is_allied) stream->writeUint8(1, "is_allied"); else if(!is_allied) stream->writeUint8(0, "is_allied"); else stream->writeUint8(2, "is_allied"); if(is_enemy) stream->writeUint8(1, "is_enemy"); else if(!is_enemy) stream->writeUint8(0, "is_enemy"); else stream->writeUint8(2, "is_enemy"); if(view_market) stream->writeUint8(1, "view_market"); else if(!view_market) stream->writeUint8(0, "view_market"); else stream->writeUint8(2, "view_market"); if(view_inn) stream->writeUint8(1, "view_inn"); else if(!view_inn) stream->writeUint8(0, "view_inn"); else stream->writeUint8(2, "view_inn"); if(view_other) stream->writeUint8(1, "view_other"); else if(!view_other) stream->writeUint8(0, "view_other"); else stream->writeUint8(2, "view_other"); stream->writeLeaveSection(); } UpgradeRepair::UpgradeRepair(int id) : id(id) { } void UpgradeRepair::modify(Echo& echo) { echo.push_order(shared_ptr(new OrderConstruction(echo.get_building_register().get_building(id)->gid,1,1))); echo.get_building_register().set_upgrading(id); } boost::logic::tribool UpgradeRepair::wait(Echo& echo) { if(echo.get_building_register().is_building_found(id)) return true; else if(echo.get_building_register().is_building_pending(id)) return false; else return indeterminate; } ManagementOrderType UpgradeRepair::get_type() { return MUpgradeRepair; } bool UpgradeRepair::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("UpgradeRepair"); ManagementOrder::load(stream, player, versionMinor); id=stream->readUint32("id"); stream->readLeaveSection(); return true; } void UpgradeRepair::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("UpgradeRepair"); ManagementOrder::save(stream); stream->writeUint32(id, "id"); stream->writeLeaveSection(); } SendMessage::SendMessage(const std::string& message) : message(message) { } void SendMessage::modify(Echo& echo) { echo.echoai->handle_message(echo, message); } boost::logic::tribool SendMessage::wait(Echo& echo) { return true; } ManagementOrderType SendMessage::get_type() { return MSendMessage; } bool SendMessage::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("SendMessage"); ManagementOrder::load(stream, player, versionMinor); message=stream->readText("message"); stream->readLeaveSection(); return true; } void SendMessage::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("SendMessage"); ManagementOrder::save(stream); stream->writeText(message, "message"); stream->writeLeaveSection(); } building_search_iterator::building_search_iterator() : found_id(-1), is_end(true), search(NULL) { } building_search_iterator::building_search_iterator(BuildingSearch& search) : found_id(-1), is_end(false), search(&search) { set_to_next(); } const unsigned int building_search_iterator::operator*() { return found_id; } building_search_iterator& building_search_iterator::operator++() { set_to_next(); return *this; } building_search_iterator building_search_iterator::operator++(int) { building_search_iterator copy(*this); set_to_next(); return copy; } bool building_search_iterator::operator!=(const building_search_iterator& rhs) const { if(is_end==rhs.is_end) return false; return is_end!=rhs.is_end || position!=rhs.position || found_id!=rhs.found_id ; } void building_search_iterator::set_to_next() { if(is_end) return; if(found_id==-1) { position=search->echo.get_building_register().begin(); } else position++; for(; position!=search->echo.get_building_register().end() && !search->passes_conditions(position->first); position++) { } if(position==search->echo.get_building_register().end()) { is_end=true; return; } found_id=position->first; } BuildingSearch::BuildingSearch(Echo& echo) : echo(echo) { } void BuildingSearch::add_condition(Conditions::BuildingCondition* condition) { conditions.push_back(boost::shared_ptr(condition)); } int BuildingSearch::count_buildings() { int count=0; for(Construction::BuildingRegister::found_iterator i=echo.get_building_register().begin(); i!=echo.get_building_register().end(); ++i) { if(passes_conditions(i->first)) { count++; } } return count; } building_search_iterator BuildingSearch::begin() { return building_search_iterator(*this); } building_search_iterator BuildingSearch::end() { return building_search_iterator(); } bool BuildingSearch::passes_conditions(int b) { for(std::vector >::iterator i = conditions.begin(); i!=conditions.end(); ++i) { if(!(*i)->passes(echo, b)) return false; } return true; } enemy_team_iterator::enemy_team_iterator(Echo& echo) : team_number(-1), is_end(false), echo(&echo) { set_to_next(); } enemy_team_iterator::enemy_team_iterator() : team_number(-1), is_end(true), echo(NULL) { } const unsigned int enemy_team_iterator::operator*() { return team_number; } enemy_team_iterator& enemy_team_iterator::operator++() { set_to_next(); return *this; } enemy_team_iterator enemy_team_iterator::operator++(int) { enemy_team_iterator copy(*this); set_to_next(); return copy; } bool enemy_team_iterator::operator!=(const enemy_team_iterator& rhs) const { if(rhs.is_end && is_end) return false; return rhs.is_end != is_end || rhs.team_number!=team_number; } void enemy_team_iterator::set_to_next() { if(is_end) return; if(team_number==-1) { team_number=0; } else team_number++; for(; echo->player->team->game->teams[team_number]!=NULL && !(echo->player->team->enemies & echo->player->team->game->teams[team_number]->me); team_number++) { } if(echo->player->team->game->teams[team_number]==NULL) { is_end=true; return; } } int SearchTools::is_flag(Echo& echo, int x, int y) { Building** buildings=echo.player->team->myBuildings; for(int n=0; n<1024; ++n) { Building* b=buildings[n]; if(b) { if(b->posX==x && b->posY==y) { if(b->type->shortTypeNum > IntBuildingType::DEFENSE_BUILDING && b->type->shortTypeNum < IntBuildingType::STONE_WALL) { return b->gid; } } } } return NOGBID; } enemy_building_iterator::enemy_building_iterator() : is_end(true) { } enemy_building_iterator::enemy_building_iterator(Echo& echo, int team, int building_type, int level, boost::logic::tribool construction_site) : current_gid(-1), team(team), building_type(building_type), level(level), construction_site(construction_site), is_end(false), echo(&echo) { set_to_next(); } const unsigned int enemy_building_iterator::operator*() { return current_gid; } enemy_building_iterator& enemy_building_iterator::operator++() { set_to_next(); return *this; } enemy_building_iterator enemy_building_iterator::operator++(int) { enemy_building_iterator copy; set_to_next(); return copy; } bool enemy_building_iterator::operator!=(const enemy_building_iterator& rhs) const { if(is_end && rhs.is_end) return false; return is_end!=rhs.is_end || team!=rhs.team || building_type!=rhs.building_type || level!=rhs.level || construction_site!=rhs.construction_site; } void enemy_building_iterator::set_to_next() { if(current_gid==-1) { current_index=0; } else current_index++; while(current_index<1024) { Building* b=echo->player->game->teams[team]->myBuildings[current_index]; if(b) { if( (b->seenByMask&echo->player->team->me // Don't allow AIs to cheat!!!!!! // || echo->get_starting_buildings().find(b->gid)!=echo->get_starting_buildings().end() ) && (building_type==-1 || b->type->shortTypeNum==building_type) && (level==-1 || b->type->level==(level-1))) { if(construction_site) { if(b->type->isBuildingSite) { current_gid=b->gid; break; } } else if(!construction_site) { if(!b->type->isBuildingSite) { current_gid=b->gid; break; } } else { current_gid=b->gid; break; } } } current_index++; } if(current_index==1024) is_end=true; } MapInfo::MapInfo(Echo& echo) : echo(echo) { } int MapInfo::get_width() { return echo.player->map->getW(); } int MapInfo::get_height() { return echo.player->map->getH(); } bool MapInfo::is_forbidden_area(int x, int y) { return echo.player->map->isForbidden(x, y, echo.player->team->me); } bool MapInfo::is_guard_area(int x, int y) { return echo.player->map->isGuardArea(x, y, echo.player->team->me); } bool MapInfo::is_clearing_area(int x, int y) { return echo.player->map->isClearArea(x, y, echo.player->team->me); } bool MapInfo::is_discovered(int x, int y) { return echo.player->map->isMapDiscovered(x, y, echo.player->team->me); } bool MapInfo::is_ressource(int x, int y, int type) { return echo.player->map->isRessourceTakeable(x, y, type); } bool MapInfo::is_water(int x, int y) { return echo.player->map->isWater(x, y); } bool MapInfo::backs_onto_sand(int x, int y) { if(echo.player->map->hasSand(x-1, y)) return true; if(echo.player->map->hasSand(x+1, y)) return true; if(echo.player->map->hasSand(x-1, y-1)) return true; if(echo.player->map->hasSand(x, y-1)) return true; if(echo.player->map->hasSand(x+1, y-1)) return true; if(echo.player->map->hasSand(x-1, y+1)) return true; if(echo.player->map->hasSand(x, y+1)) return true; if(echo.player->map->hasSand(x+1, y+1)) return true; return false; } int MapInfo::get_ammount_ressource(int x, int y) { return echo.player->map->getRessource(x, y).amount; } Echo::Echo(EchoAI* echoai, Player* player) : player(player), echoai(echoai), gm(), br(player, *this), fm(*this), timer(0) { previous_building_id=-1; from_load_timer=0; is_fruit=false; } unsigned int Echo::add_building_order(Construction::BuildingOrder* bo) { building_orders.push_back(boost::shared_ptr(bo)); bo->queue_gradients(get_gradient_manager()); unsigned int id=br.register_building(); bo->id=id; return id; } void Echo::add_management_order(Management::ManagementOrder* mo) { management_orders.push_back(boost::shared_ptr(mo)); } void Echo::update_management_orders() { for(std::vector >::iterator i=management_orders.begin(); i!=management_orders.end();) { boost::logic::tribool passes=(*i)->passes_conditions(*this); if(passes) { (*i)->modify(*this); i=management_orders.erase(i); continue; } else if(!passes) { } else { i=management_orders.erase(i); continue; } ++i; } } void Echo::add_ressource_tracker(Management::RessourceTracker* rt, int building_id) { ressource_trackers[building_id]=boost::make_tuple(boost::shared_ptr(rt), true); } boost::shared_ptr Echo::get_ressource_tracker(int building_id) { if(ressource_trackers.find(building_id)==ressource_trackers.end()) return boost::shared_ptr(); return ressource_trackers[building_id].get<0>(); } void Echo::pause_ressource_tracker(int building_id) { ressource_trackers[building_id].get<1>()=false; } void Echo::unpause_ressource_tracker(int building_id) { ressource_trackers[building_id].get<1>()=true; } void Echo::update_ressource_trackers() { for(std::map, bool> >::iterator i = ressource_trackers.begin(); i!=ressource_trackers.end();) { if(!br.is_building_found(i->first) && !br.is_building_pending(i->first)) { std::map, bool> >::iterator current=i; ++i; ressource_trackers.erase(current); continue; } else { if(i->second.get<1>()) i->second.get<0>()->tick(); } ++i; } } void Echo::update_building_orders() { for(std::vector >::iterator i=building_orders.begin(); i!=building_orders.end();) { boost::logic::tribool passes=(*i)->passes_conditions(*this); if(passes) { if(!(previous_building_id==-1 || br.is_building_found(previous_building_id) || !br.is_building_pending(previous_building_id))) break; position p=(*i)->find_location(*this, player->map, *gm); if(p.x != 0 || p.y != 0) { br.issue_order((*i)->id, p.x, p.y, (*i)->get_building_type()); Sint32 type=-1; if((*i)->get_building_type()>IntBuildingType::DEFENSE_BUILDING && (*i)->get_building_type() buildingsTypes.getTypeNum(IntBuildingType::reverseConversionMap[(*i)->get_building_type()], 0, false); ManagementOrder* mo_flag=new AssignWorkers((*i)->get_number_of_workers(), (*i)->id); add_management_order(mo_flag); } else { type=globalContainer->buildingsTypes.getTypeNum(IntBuildingType::reverseConversionMap[(*i)->get_building_type()], 0, true); ManagementOrder* mo_during_construction=new AssignWorkers((*i)->get_number_of_workers(), (*i)->id); mo_during_construction->add_condition(new ParticularBuilding(new UnderConstruction, (*i)->id)); add_management_order(mo_during_construction); } orders.push_back(shared_ptr(new OrderCreate(player->team->teamNumber, p.x, p.y, type, 1, 1))); previous_building_id=(*i)->id; i=building_orders.erase(i); break; } else { br.remove_building((*i)->id); i=building_orders.erase(i); continue; } } else if(!passes) { } else { br.remove_building((*i)->id); i=building_orders.erase(i); continue; } ++i; } } void Echo::init_starting_buildings() { for(int t=0; t<32; ++t) { if(player->game->teams[t]) { for(int bu=0; bu<1024; ++bu) { Building* b=player->game->teams[t]->myBuildings[bu]; if(b) { starting_buildings.insert(b->gid); } } } } } void Echo::check_fruit() { MapInfo mi(*this); for(int x=0; xreadEnterSection("EchoAI"); signature_check(stream, player, versionMinor); stream->readEnterSection("orders"); Uint32 ordersSize = stream->readUint32("size"); for (Uint32 ordersIndex = 0; ordersIndex < ordersSize; ordersIndex++) { stream->readEnterSection(ordersIndex); size_t size=stream->readUint32("size"); Uint8* buffer = new Uint8[size+1]; stream->read(buffer, size, "data"); orders.push_back(Order::getOrder(buffer, size+1)); // FIXME : clear the container before load stream->readLeaveSection(); } stream->readLeaveSection(); signature_check(stream, player, versionMinor); br.load(stream, player, versionMinor); signature_check(stream, player, versionMinor); fm.load(stream, player, versionMinor); signature_check(stream, player, versionMinor); stream->readEnterSection("management_orders"); Uint32 managementSize=stream->readUint32("size"); for(Uint32 managementIndex = 0; managementIndex < managementSize; ++managementIndex) { stream->readEnterSection(managementIndex); signature_check(stream, player, versionMinor); signature_check(stream, player, versionMinor); boost::shared_ptr mo=boost::shared_ptr(ManagementOrder::load_order(stream, player, versionMinor)); management_orders.push_back(mo); signature_check(stream, player, versionMinor); signature_check(stream, player, versionMinor); stream->readLeaveSection(); } stream->readLeaveSection(); signature_check(stream, player, versionMinor); stream->readEnterSection("building_orders"); Uint32 buildingSize=stream->readUint32("size"); building_orders.resize(buildingSize); for(Uint32 buildingIndex = 0; buildingIndex < buildingSize; ++buildingIndex) { stream->readEnterSection(buildingIndex); building_orders[buildingIndex]=boost::shared_ptr(new BuildingOrder); building_orders[buildingIndex]->load(stream, player, versionMinor); stream->readLeaveSection(); } stream->readLeaveSection(); signature_check(stream, player, versionMinor); stream->readEnterSection("ressource_trackers"); Uint32 ressourceTrackerSize=stream->readUint32("size"); for(Uint32 ressourceTrackerIndex=0; ressourceTrackerIndexreadEnterSection(ressourceTrackerIndex); int id=stream->readUint32("echo_building_id"); boost::shared_ptr rt(new RessourceTracker(*this, stream, player, versionMinor)); bool activated=stream->readUint8("active"); ressource_trackers[id]=boost::make_tuple(rt, activated); stream->readLeaveSection(); } stream->readLeaveSection(); signature_check(stream, player, versionMinor); stream->readEnterSection("starting_buildings"); Uint32 startingBuildingSize=stream->readUint32("size"); for(Uint32 startingBuildingIndex=0; startingBuildingIndexreadEnterSection(startingBuildingIndex); starting_buildings.insert(stream->readUint32("gid")); stream->readLeaveSection(); } stream->readLeaveSection(); signature_check(stream, player, versionMinor); timer=stream->readUint32("timer"); update_gm=stream->readUint8("update_gm"); allies=stream->readUint32("allies"); enemies=stream->readUint32("enemies"); inn_view=stream->readUint32("inn_view"); market_view=stream->readUint32("market_view"); other_view=stream->readUint32("other_view"); signature_check(stream, player, versionMinor); echoai->load(stream, player, versionMinor); signature_check(stream, player, versionMinor); stream->readLeaveSection(); signature_check(stream, player, versionMinor); return true; } void Echo::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("EchoAI"); signature_write(stream); stream->writeEnterSection("orders"); stream->writeUint32((Uint32)orders.size(), "size"); Uint32 ordersIndex = 0; for (std::list >::iterator i = orders.begin(); i!=orders.end(); ++i) { stream->writeEnterSection(ordersIndex); stream->writeUint32((*i)->getDataLength(), "size"); ///one byte indicating the type is required to be written for order. stream->writeUint8((*i)->getOrderType(), "type"); stream->write((*i)->getData(), (*i)->getDataLength(), "data"); stream->writeLeaveSection(); ordersIndex++; } stream->writeLeaveSection(); signature_write(stream); br.save(stream); signature_write(stream); fm.save(stream); signature_write(stream); stream->writeEnterSection("management_orders"); stream->writeUint32(management_orders.size(), "size"); for(Uint32 managementIndex = 0; managementIndex < management_orders.size(); ++managementIndex) { stream->writeEnterSection(managementIndex); signature_write(stream); signature_write(stream); Management::ManagementOrder::save_order(management_orders[managementIndex].get(), stream); signature_write(stream); signature_write(stream); stream->writeLeaveSection(); } stream->writeLeaveSection(); signature_write(stream); stream->writeEnterSection("building_orders"); stream->writeUint32(building_orders.size(), "size"); for(Uint32 buildingIndex = 0; buildingIndex < building_orders.size(); ++buildingIndex) { stream->writeEnterSection(buildingIndex); building_orders[buildingIndex]->save(stream); stream->writeLeaveSection(); } stream->writeLeaveSection(); signature_write(stream); stream->writeEnterSection("ressource_trackers"); stream->writeUint32(ressource_trackers.size(), "size"); Uint32 ressourceTrackerIndex=0; for(tracker_iterator i=ressource_trackers.begin(); i!=ressource_trackers.end(); ++ressourceTrackerIndex, ++i) { stream->writeEnterSection(ressourceTrackerIndex); stream->writeUint32(i->first, "echo_building_id"); i->second.get<0>()->save(stream); stream->writeUint8(i->second.get<1>(), "active"); stream->writeLeaveSection(); } stream->writeLeaveSection(); signature_write(stream); stream->writeEnterSection("starting_buildings"); Uint32 startingBuildingIndex=0; stream->writeUint32(starting_buildings.size(), "size"); for(std::set::iterator i=starting_buildings.begin(); i!=starting_buildings.end(); ++i, ++startingBuildingIndex) { stream->writeEnterSection(startingBuildingIndex); stream->writeUint32(*i, "gid"); stream->writeLeaveSection(); } stream->writeLeaveSection(); signature_write(stream); stream->writeUint32(timer, "timer"); stream->writeUint8(update_gm, "update_gm"); stream->writeUint32(allies, "allies"); stream->writeUint32(enemies, "enemies"); stream->writeUint32(inn_view, "inn_view"); stream->writeUint32(market_view, "market_view"); stream->writeUint32(other_view, "other_view"); signature_write(stream); echoai->save(stream); signature_write(stream); stream->writeLeaveSection(); signature_write(stream); } #include "TextStream.h" boost::shared_ptr Echo::getOrder(void) { // for(int x=0; xmap->getW(); ++x) // { // for(int y=0; ymap->getH(); ++y) // { // player->map->setMapDiscovered(x, y, player->team->me); // } // } /* if(timer%128==0) { OutputStream *stream = new TextOutputStream(Toolkit::getFileManager()->openOutputStreamBackend("glob2.world-desynchronization.dump.txt")); player->game->save(stream, false, "glob2.world-desynchronization.dump.txt"); delete stream; } */ if(!gm) { gm.reset(new GradientManager(player->map)); update_gm=true; for(int x=0; x<32; ++x) { if(player->team->game->players[x]!=NULL) { if(player->team->game->players[x]->type>=BasePlayer::P_AI) { Echo* other=dynamic_cast(player->team->game->players[x]->ai->aiImplementation); if(other) { if(!other->gm) { other->gm=gm; other->update_gm=false; // std::cout<<"Linked with another AI, number "<team->allies; enemies=player->team->enemies; market_view=player->team->sharedVisionExchange; inn_view=player->team->sharedVisionFood; other_view=player->team->sharedVisionOther; } if(!orders.empty()) { boost::shared_ptr order=orders.front(); orders.erase(orders.begin()); return order; } if(update_gm) gm->update(); br.tick(); update_ressource_trackers(); update_management_orders(); echoai->tick(*this); update_management_orders(); update_building_orders(); timer++; from_load_timer++; return boost::shared_ptr(new NullOrder()); } ReachToInfinity::ReachToInfinity() { timer=0; flag_on_cherry=false; flag_on_orange=false; flag_on_prune=false; } bool ReachToInfinity::load(GAGCore::InputStream *stream, Player *player, Sint32 versionMinor) { stream->readEnterSection("ReachToInfinity"); timer=stream->readUint32("timer"); flag_on_cherry=stream->readUint32("flag_on_cherry"); flag_on_orange=stream->readUint32("flag_on_orange"); flag_on_prune=stream->readUint32("flag_on_prune"); stream->readEnterSection("flags_on_enemy"); Uint32 flagsOnEnemySize=stream->readUint32("size"); for(Uint32 flagsOnEnemyIndex=0; flagsOnEnemyIndexreadEnterSection(flagsOnEnemyIndex); flags_on_enemy.insert(stream->readUint32("gid")); stream->readLeaveSection(); } stream->readLeaveSection(); stream->readLeaveSection(); return true; } void ReachToInfinity::save(GAGCore::OutputStream *stream) { stream->writeEnterSection("ReachToInfinity"); stream->writeUint32(timer, "timer"); stream->writeUint32(flag_on_cherry, "flag_on_cherry"); stream->writeUint32(flag_on_orange, "flag_on_orange"); stream->writeUint32(flag_on_prune, "flag_on_prune"); stream->writeEnterSection("flags_on_enemy"); Uint32 flagsOnEnemyIndex=0; stream->writeUint32(flags_on_enemy.size(), "size"); for(std::set::iterator i=flags_on_enemy.begin(); i!=flags_on_enemy.end(); ++i, ++flagsOnEnemyIndex) { stream->writeEnterSection(flagsOnEnemyIndex); stream->writeUint32(*i, "gid"); stream->writeLeaveSection(); } stream->writeLeaveSection(); stream->writeLeaveSection(); } void ReachToInfinity::tick(Echo& echo) { timer++; if(timer==1) { BuildingSearch bs(echo); for(building_search_iterator i = bs.begin(); i!=bs.end(); ++i) { if(echo.get_building_register().get_type(*i)==IntBuildingType::SWARM_BUILDING) { ManagementOrder* mo_completion=new AssignWorkers(5, *i); echo.add_management_order(mo_completion); ManagementOrder* mo_ratios=new ChangeSwarm(15, 1, 0, *i); mo_ratios->add_condition(new ParticularBuilding(new NotUnderConstruction, *i)); echo.add_management_order(mo_ratios); ManagementOrder* mo_tracker=new AddRessourceTracker(12, CORN, *i); echo.add_management_order(mo_tracker); } if(echo.get_building_register().get_type(*i)==IntBuildingType::FOOD_BUILDING) { ManagementOrder* mo_tracker=new AddRessourceTracker(12, CORN, *i); echo.add_management_order(mo_tracker); } } } /* ///This is demonstration code for the advanced use of Conditions if(timer==100) { for(int g=0; g<1; ++g) { int prev_id=-1; int first_id=-1; int fifth_id=-1; for(int n=0; n<15; ++n) { //The main order for the inn BuildingOrder* bo = new BuildingOrder(IntBuildingType::FOOD_BUILDING, 2); //Constraints arround the location of wheat AIEcho::Gradients::GradientInfo gi_wheat; gi_wheat.add_source(new AIEcho::Gradients::Entities::Ressource(CORN)); //You want to be close to wheat bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_wheat, 4)); //You can't be farther than 10 units from wheat bo->add_constraint(new AIEcho::Construction::MaximumDistance(gi_wheat, 10)); //Constraints arround nearby settlement AIEcho::Gradients::GradientInfo gi_building; gi_building.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, false)); gi_building.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You want to be close to other buildings, but wheat is more important bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_building, 2)); AIEcho::Gradients::GradientInfo gi_building_construction; gi_building_construction.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, true)); gi_building_construction.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You don't want to be too close bo->add_constraint(new AIEcho::Construction::MinimumDistance(gi_building_construction, 3)); //Constraints arround the location of fruit AIEcho::Gradients::GradientInfo gi_fruit; gi_fruit.add_source(new AIEcho::Gradients::Entities::Ressource(CHERRY)); gi_fruit.add_source(new AIEcho::Gradients::Entities::Ressource(ORANGE)); gi_fruit.add_source(new AIEcho::Gradients::Entities::Ressource(PRUNE)); //You want to be reasnobly close to fruit, closer if possible bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_fruit, 1)); if(prev_id!=-1) { bo->add_condition(new EitherCondition(new ParticularBuilding(new NotUnderConstruction, prev_id), new BuildingDestroyed(prev_id))); } else bo->add_condition(new Population(true, true, true, 5, Population::Greater)); //Add the building order to the list of orders unsigned int id=echo.add_building_order(bo); if(prev_id!=-1) { ManagementOrder* mo_upgrade = new UpgradeRepair(id); mo_upgrade->add_condition(new ParticularBuilding(new NotUnderConstruction, prev_id)); mo_upgrade->add_condition(new ParticularBuilding(new BuildingLevel(2), prev_id)); echo.add_management_order(mo_upgrade); ManagementOrder* mo_assign=new AssignWorkers(6, id); mo_assign->add_condition(new ParticularBuilding(new UnderConstruction, id)); mo_assign->add_condition(new ParticularBuilding(new BuildingLevel(2), id)); echo.add_management_order(mo_assign); ManagementOrder* mo_finish=new AssignWorkers(2, id); mo_finish->add_condition(new ParticularBuilding(new NotUnderConstruction, id)); mo_finish->add_condition(new ParticularBuilding(new BuildingLevel(2), id)); echo.add_management_order(mo_finish); } if(n==0) { first_id=id; } if(n==4) { fifth_id=id; } ManagementOrder* mo_completion=new AssignWorkers(1, id); mo_completion->add_condition(new ParticularBuilding(new NotUnderConstruction, id)); echo.add_management_order(mo_completion); ManagementOrder* mo_tracker=new AddRessourceTracker(12, id, CORN); mo_tracker->add_condition(new ParticularBuilding(new NotUnderConstruction, id)); echo.add_management_order(mo_tracker); ManagementOrder* mo_delete=new DestroyBuilding(id); mo_delete->add_condition(new ParticularBuilding(new NotUnderConstruction, id)); mo_delete->add_condition(new ParticularBuilding(new RessourceTrackerAge(500, RessourceTrackerAge::Greater), id)); mo_delete->add_condition(new ParticularBuilding(new RessourceTrackerAmount(48, RessourceTrackerAmount::Lesser), id)); echo.add_management_order(mo_delete); ManagementOrder* mo_reconstruct = new SendMessage("construct inn"); mo_reconstruct->add_condition(new BuildingDestroyed(id)); echo.add_management_order(mo_reconstruct); prev_id=id; } ManagementOrder* mo_upgrade = new UpgradeRepair(first_id); mo_upgrade->add_condition(new ParticularBuilding(new NotUnderConstruction, fifth_id)); echo.add_management_order(mo_upgrade); ManagementOrder* mo_assign=new AssignWorkers(6, first_id); mo_assign->add_condition(new ParticularBuilding(new UnderConstruction, first_id)); mo_assign->add_condition(new ParticularBuilding(new BuildingLevel(2), first_id)); echo.add_management_order(mo_assign); ManagementOrder* mo_finish=new AssignWorkers(2, first_id); mo_finish->add_condition(new ParticularBuilding(new NotUnderConstruction, first_id)); mo_finish->add_condition(new ParticularBuilding(new BuildingLevel(2), first_id)); echo.add_management_order(mo_finish); } } */ //Explorer flags on the three nearest fruit trees if((timer%100)==0) { if(echo.is_fruit_on_map()) { // BuildingSearch bs_flag(echo); // bs_flag.add_condition(new SpecificBuildingType(IntBuildingType::EXPLORATION_FLAG)); // const int number=bs_flag.count_buildings(); if(echo.get_team_stats().numberUnitPerType[EXPLORER]>=6 && !flag_on_cherry && !flag_on_orange && !flag_on_prune) { //Constraints arround nearby settlement AIEcho::Gradients::GradientInfo gi_building; gi_building.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, false)); if(!flag_on_cherry) { //The main order for the exploration flag BuildingOrder* bo_cherry = new BuildingOrder(IntBuildingType::EXPLORATION_FLAG, 2); //You want the closest fruit to your settlement possible bo_cherry->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_building, 1)); //Constraint arround the location of fruit AIEcho::Gradients::GradientInfo gi_cherry; gi_cherry.add_source(new AIEcho::Gradients::Entities::Ressource(CHERRY)); //You want to be ontop of the cherry trees bo_cherry->add_constraint(new AIEcho::Construction::MaximumDistance(gi_cherry, 0)); //Add the building order to the list of orders unsigned int id_cherry=echo.add_building_order(bo_cherry); if(id_cherry!=INVALID_BUILDING) { ManagementOrder* mo_completion=new ChangeFlagSize(4, id_cherry); echo.add_management_order(mo_completion); flag_on_cherry=true; for(enemy_team_iterator i(echo); i!=enemy_team_iterator(); ++i) { ManagementOrder* mo_alliance=new ChangeAlliances(*i, indeterminate, indeterminate, indeterminate, true, indeterminate); echo.add_management_order(mo_alliance); } } } if(!flag_on_orange) { //The main order for the exploration flag BuildingOrder* bo_orange = new BuildingOrder(IntBuildingType::EXPLORATION_FLAG, 2); //You want the closest fruit to your settlement possible bo_orange->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_building, 1)); //Constraints arround the location of fruit AIEcho::Gradients::GradientInfo gi_orange; gi_orange.add_source(new AIEcho::Gradients::Entities::Ressource(ORANGE)); //You want to be ontop of the orange trees bo_orange->add_constraint(new AIEcho::Construction::MaximumDistance(gi_orange, 0)); unsigned int id_orange=echo.add_building_order(bo_orange); if(id_orange!=INVALID_BUILDING) { ManagementOrder* mo_completion=new ChangeFlagSize(4, id_orange); echo.add_management_order(mo_completion); flag_on_orange=true; for(enemy_team_iterator i(echo); i!=enemy_team_iterator(); ++i) { ManagementOrder* mo_alliance=new ChangeAlliances(*i, indeterminate, indeterminate, indeterminate, true, indeterminate); echo.add_management_order(mo_alliance); } } } if(!flag_on_prune) { //The main order for the exploration flag BuildingOrder* bo_prune = new BuildingOrder(IntBuildingType::EXPLORATION_FLAG, 2); //You want the closest fruit to your settlement possible bo_prune->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_building, 1)); AIEcho::Gradients::GradientInfo gi_prune; gi_prune.add_source(new AIEcho::Gradients::Entities::Ressource(PRUNE)); //You want to be ontop of the prune trees bo_prune->add_constraint(new AIEcho::Construction::MaximumDistance(gi_prune, 0)); //Add the building order to the list of orders unsigned int id_prune=echo.add_building_order(bo_prune); if(id_prune!=INVALID_BUILDING) { ManagementOrder* mo_completion=new ChangeFlagSize(4, id_prune); echo.add_management_order(mo_completion); flag_on_prune=true; for(enemy_team_iterator i(echo); i!=enemy_team_iterator(); ++i) { ManagementOrder* mo_alliance=new ChangeAlliances(*i, indeterminate, indeterminate, indeterminate, true, indeterminate); echo.add_management_order(mo_alliance); } } } } } } //Place exploration flags on the enemy swarms if((timer%120)==0) { if(echo.get_team_stats().numberUnitPerType[EXPLORER]>=3) { for(enemy_team_iterator i(echo); i!=enemy_team_iterator(); ++i) { for(enemy_building_iterator ebi(echo, *i, IntBuildingType::SWARM_BUILDING, -1, false); ebi!=enemy_building_iterator(); ++ebi) { if(flags_on_enemy.find(*i)!=flags_on_enemy.end()) continue; BuildingOrder* bo = new BuildingOrder(IntBuildingType::EXPLORATION_FLAG, 1); bo->add_constraint(new CenterOfBuilding(*ebi)); unsigned int id=echo.add_building_order(bo); if(id!=INVALID_BUILDING) { ManagementOrder* mo_completion=new ChangeFlagSize(12, id); echo.add_management_order(mo_completion); ManagementOrder* mo_destroyed=new DestroyBuilding(id); mo_destroyed->add_condition(new EnemyBuildingDestroyed(echo, *ebi)); echo.add_management_order(mo_destroyed); flags_on_enemy.insert(*i); } } } } } //Standard Inns near wheat if((timer%200)==0 && (timer%2000)!=0) { BuildingSearch bs_level1(echo); bs_level1.add_condition(new SpecificBuildingType(IntBuildingType::FOOD_BUILDING)); bs_level1.add_condition(new BuildingLevel(1)); const int number1=bs_level1.count_buildings(); BuildingSearch bs_level2(echo); bs_level2.add_condition(new SpecificBuildingType(IntBuildingType::FOOD_BUILDING)); bs_level2.add_condition(new BuildingLevel(2)); const int number2=bs_level2.count_buildings(); BuildingSearch bs_level3(echo); bs_level3.add_condition(new SpecificBuildingType(IntBuildingType::FOOD_BUILDING)); bs_level3.add_condition(new BuildingLevel(3)); const int number3=bs_level3.count_buildings(); if((echo.player->team->stats.getLatestStat()->totalUnit)>=(number1*8 + number2*12 + number3*16)) { //The main order for the inn BuildingOrder* bo = new BuildingOrder(IntBuildingType::FOOD_BUILDING, 2); //Constraints arround the location of wheat AIEcho::Gradients::GradientInfo gi_wheat; gi_wheat.add_source(new AIEcho::Gradients::Entities::Ressource(CORN)); //You want to be close to wheat bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_wheat, 4)); //You can't be farther than 10 units from wheat bo->add_constraint(new AIEcho::Construction::MaximumDistance(gi_wheat, 10)); //Constraints arround nearby settlement AIEcho::Gradients::GradientInfo gi_building; gi_building.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, false)); gi_building.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You want to be close to other buildings, but wheat is more important bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_building, 2)); AIEcho::Gradients::GradientInfo gi_building_construction; gi_building_construction.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, true)); gi_building_construction.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You don't want to be too close bo->add_constraint(new AIEcho::Construction::MinimumDistance(gi_building_construction, 3)); if(echo.is_fruit_on_map()) { //Constraints arround the location of fruit AIEcho::Gradients::GradientInfo gi_fruit; gi_fruit.add_source(new AIEcho::Gradients::Entities::Ressource(CHERRY)); gi_fruit.add_source(new AIEcho::Gradients::Entities::Ressource(ORANGE)); gi_fruit.add_source(new AIEcho::Gradients::Entities::Ressource(PRUNE)); //You want to be reasnobly close to fruit, closer if possible bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_fruit, 1)); } //Add the building order to the list of orders unsigned int id=echo.add_building_order(bo); // std::cout<<"inn ordered, id="<add_condition(new ParticularBuilding(new NotUnderConstruction, id)); echo.add_management_order(mo_completion); ManagementOrder* mo_tracker=new AddRessourceTracker(12, CORN, id); mo_tracker->add_condition(new ParticularBuilding(new NotUnderConstruction, id)); echo.add_management_order(mo_tracker); } } //Standard swarms near wheat. Uses special mechanism, builds more swarms early on. if((timer%2000)==0) { BuildingSearch bs(echo); bs.add_condition(new SpecificBuildingType(IntBuildingType::SWARM_BUILDING)); const int number=bs.count_buildings(); if((number<=3 && (echo.player->team->stats.getLatestStat()->totalUnit/20)>=number) || (echo.player->team->stats.getLatestStat()->totalUnit/50)>=number) { // std::cout<<"Constructing swarm"<add_constraint(new AIEcho::Construction::MinimizedDistance(gi_wheat, 4)); //Constraints arround nearby settlement AIEcho::Gradients::GradientInfo gi_building; gi_building.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, false)); gi_building.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You want to be close to other buildings, but wheat is more important bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_building, 1)); AIEcho::Gradients::GradientInfo gi_building_construction; gi_building_construction.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, true)); gi_building_construction.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You don't want to be too close bo->add_constraint(new AIEcho::Construction::MinimumDistance(gi_building_construction, 3)); //Add the building order to the list of orders unsigned int id=echo.add_building_order(bo); // std::cout<<"Swarm ordered, id="<add_condition(new ParticularBuilding(new NotUnderConstruction, id)); echo.add_management_order(mo_completion); //Change the ratio of the swarm when its finished ManagementOrder* mo_ratios=new ChangeSwarm(15, 1, 0, id); mo_ratios->add_condition(new ParticularBuilding(new NotUnderConstruction, id)); echo.add_management_order(mo_ratios); //Add a tracker ManagementOrder* mo_tracker=new AddRessourceTracker(12, CORN, id); mo_tracker->add_condition(new ParticularBuilding(new NotUnderConstruction, id)); echo.add_management_order(mo_tracker); } } //Standard racetrack near stone and wood if((timer%2000)==500) { BuildingSearch bs(echo); bs.add_condition(new SpecificBuildingType(IntBuildingType::WALKSPEED_BUILDING)); const int number=bs.count_buildings(); if((echo.player->team->stats.getLatestStat()->totalUnit/60)>=number && number<3) { //The main order for the racetrack BuildingOrder* bo = new BuildingOrder(IntBuildingType::WALKSPEED_BUILDING, 6); //Constraints arround the location of wood AIEcho::Gradients::GradientInfo gi_wood; gi_wood.add_source(new AIEcho::Gradients::Entities::Ressource(WOOD)); //You want to be close to wood bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_wood, 4)); //Constraints arround the location of stone AIEcho::Gradients::GradientInfo gi_stone; gi_stone.add_source(new AIEcho::Gradients::Entities::Ressource(STONE)); //You want to be close to stone bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_stone, 1)); //But not to close, so you have room to upgrade bo->add_constraint(new AIEcho::Construction::MinimumDistance(gi_stone, 2)); //Constraints arround nearby settlement AIEcho::Gradients::GradientInfo gi_building; gi_building.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, false)); gi_building.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You want to be close to other buildings, but wheat is more important bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_building, 2)); AIEcho::Gradients::GradientInfo gi_building_construction; gi_building_construction.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, true)); gi_building_construction.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You don't want to be too close bo->add_constraint(new AIEcho::Construction::MinimumDistance(gi_building_construction, 4)); //Add the building order to the list of orders echo.add_building_order(bo); } } //Standard swimming pool near wheat and wood if((timer%2000)==1000) { BuildingSearch bs(echo); bs.add_condition(new SpecificBuildingType(IntBuildingType::SWIMSPEED_BUILDING)); const int number=bs.count_buildings(); if((echo.player->team->stats.getLatestStat()->totalUnit/60)>=number && number<3) { //The main order for the swimmingpool BuildingOrder* bo = new BuildingOrder(IntBuildingType::SWIMSPEED_BUILDING, 6); //Constraints arround the location of wood AIEcho::Gradients::GradientInfo gi_wood; gi_wood.add_source(new AIEcho::Gradients::Entities::Ressource(WOOD)); //You want to be close to wood bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_wood, 4)); //Constraints arround the location of wheat AIEcho::Gradients::GradientInfo gi_wheat; gi_wheat.add_source(new AIEcho::Gradients::Entities::Ressource(CORN)); //You want to be close to wheat bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_wheat, 1)); //Constraints arround the location of stone AIEcho::Gradients::GradientInfo gi_stone; gi_stone.add_source(new AIEcho::Gradients::Entities::Ressource(STONE)); //You don't want to be too close, so you have room to upgrade bo->add_constraint(new AIEcho::Construction::MinimumDistance(gi_stone, 2)); //Constraints arround nearby settlement AIEcho::Gradients::GradientInfo gi_building; gi_building.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, false)); gi_building.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You want to be close to other buildings, but wheat is more important bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_building, 2)); AIEcho::Gradients::GradientInfo gi_building_construction; gi_building_construction.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, true)); gi_building_construction.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You don't want to be too close bo->add_constraint(new AIEcho::Construction::MinimumDistance(gi_building_construction, 4)); //Add the building order to the list of orders echo.add_building_order(bo); } } //Standard school inland away from the enemies if((timer%2000)==1500) { BuildingSearch bs(echo); bs.add_condition(new SpecificBuildingType(IntBuildingType::SCIENCE_BUILDING)); const int number=bs.count_buildings(); if((echo.player->team->stats.getLatestStat()->totalUnit/60)>=number && number<4) { //The main order for the school BuildingOrder* bo = new BuildingOrder(IntBuildingType::SCIENCE_BUILDING, 5); //Constraints arround nearby settlement AIEcho::Gradients::GradientInfo gi_building; gi_building.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, false)); gi_building.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You want to be close to other buildings, but wheat is more important bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_building, 2)); AIEcho::Gradients::GradientInfo gi_building_construction; gi_building_construction.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, true)); gi_building_construction.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You don't want to be too close bo->add_constraint(new AIEcho::Construction::MinimumDistance(gi_building_construction, 4)); //Constraints arround the enemy AIEcho::Gradients::GradientInfo gi_enemy; for(enemy_team_iterator i(echo); i!=enemy_team_iterator(); ++i) { gi_enemy.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(*i, false)); } gi_enemy.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); bo->add_constraint(new AIEcho::Construction::MaximizedDistance(gi_enemy, 3)); //Add the building order to the list of orders echo.add_building_order(bo); } } //Level 1 to level 2 upgrades if((timer%300)==0) { BuildingSearch level_twos(echo); level_twos.add_condition(new BeingUpgradedTo(2)); const int level_two_counts=level_twos.count_buildings(); BuildingSearch schools(echo); schools.add_condition(new SpecificBuildingType(IntBuildingType::SCIENCE_BUILDING)); schools.add_condition(new NotUnderConstruction); const int school_counts=schools.count_buildings(); BuildingSearch buildings(echo); buildings.add_condition(new BuildingLevel(1)); const int total_buildings=buildings.count_buildings(); if(level_two_counts<=(total_buildings/15) && school_counts>0) { BuildingSearch bs(echo); bs.add_condition(new Upgradable); bs.add_condition(new BuildingLevel(1)); if(school_counts<2) bs.add_condition(new NotSpecificBuildingType(IntBuildingType::SCIENCE_BUILDING)); std::vector buildings; std::copy(bs.begin(), bs.end(), std::back_insert_iterator >(buildings)); if(buildings.size()!=0) { int chosen=syncRand()%buildings.size(); ManagementOrder* uro = new UpgradeRepair(buildings[chosen]); echo.add_management_order(uro); int assigned=echo.get_building_register().get_assigned(buildings[chosen]); ManagementOrder* mo_assign=new AssignWorkers(8, buildings[chosen]); mo_assign->add_condition(new ParticularBuilding(new UnderConstruction, buildings[chosen])); echo.add_management_order(mo_assign); if(echo.get_building_register().get_type(buildings[chosen])==IntBuildingType::FOOD_BUILDING) { ManagementOrder* mo_tracker_pause=new PauseRessourceTracker(buildings[chosen]); mo_tracker_pause->add_condition(new ParticularBuilding(new UnderConstruction, buildings[chosen])); echo.add_management_order(mo_tracker_pause); ManagementOrder* mo_tracker_unpause=new UnPauseRessourceTracker(buildings[chosen]); mo_tracker_unpause->add_condition(new ParticularBuilding(new NotUnderConstruction, buildings[chosen])); echo.add_management_order(mo_tracker_unpause); ManagementOrder* mo_completion=new AssignWorkers(3, buildings[chosen]); mo_completion->add_condition(new ParticularBuilding(new NotUnderConstruction, buildings[chosen])); echo.add_management_order(mo_completion); } else { ManagementOrder* mo_assign=new AssignWorkers(assigned, buildings[chosen]); mo_assign->add_condition(new ParticularBuilding(new NotUnderConstruction, buildings[chosen])); echo.add_management_order(mo_assign); } } } } //Level 2 to level 3 upgrades if((timer%300)==0) { BuildingSearch level_threes(echo); level_threes.add_condition(new BeingUpgradedTo(3)); const int level_three_counts=level_threes.count_buildings(); BuildingSearch schools(echo); schools.add_condition(new SpecificBuildingType(IntBuildingType::SCIENCE_BUILDING)); schools.add_condition(new NotUnderConstruction); schools.add_condition(new BuildingLevel(2)); int school_counts=schools.count_buildings(); BuildingSearch schools2(echo); schools2.add_condition(new SpecificBuildingType(IntBuildingType::SCIENCE_BUILDING)); schools2.add_condition(new NotUnderConstruction); schools2.add_condition(new BuildingLevel(3)); school_counts+=schools2.count_buildings(); BuildingSearch buildings(echo); buildings.add_condition(new BuildingLevel(2)); const int total_buildings=buildings.count_buildings(); if(level_three_counts<=(total_buildings/15) && school_counts>0) { BuildingSearch bs(echo); bs.add_condition(new Upgradable); bs.add_condition(new BuildingLevel(2)); if(school_counts<2) bs.add_condition(new NotSpecificBuildingType(IntBuildingType::SCIENCE_BUILDING)); std::vector buildings; std::copy(bs.begin(), bs.end(), std::back_insert_iterator >(buildings)); if(buildings.size()!=0) { int chosen=syncRand()%buildings.size(); ManagementOrder* uro = new UpgradeRepair(buildings[chosen]); echo.add_management_order(uro); int assigned=echo.get_building_register().get_assigned(buildings[chosen]); ManagementOrder* mo_assign=new AssignWorkers(8, buildings[chosen]); mo_assign->add_condition(new ParticularBuilding(new UnderConstruction, buildings[chosen])); echo.add_management_order(mo_assign); if(echo.get_building_register().get_type(buildings[chosen])==IntBuildingType::FOOD_BUILDING) { ManagementOrder* mo_tracker_pause=new PauseRessourceTracker(buildings[chosen]); mo_tracker_pause->add_condition(new ParticularBuilding(new UnderConstruction, buildings[chosen])); echo.add_management_order(mo_tracker_pause); ManagementOrder* mo_tracker_unpause=new UnPauseRessourceTracker(buildings[chosen]); mo_tracker_unpause->add_condition(new ParticularBuilding(new NotUnderConstruction, buildings[chosen])); echo.add_management_order(mo_tracker_unpause); ManagementOrder* mo_completion=new AssignWorkers(6, buildings[chosen]); mo_completion->add_condition(new ParticularBuilding(new NotUnderConstruction, buildings[chosen])); echo.add_management_order(mo_completion); } else { ManagementOrder* mo_assign=new AssignWorkers(assigned, buildings[chosen]); mo_assign->add_condition(new ParticularBuilding(new NotUnderConstruction, buildings[chosen])); echo.add_management_order(mo_assign); } } } } //Delete old inns and swarms that are hard to keep full of wheat if((timer%500)==0) { BuildingSearch inns(echo); inns.add_condition(new SpecificBuildingType(IntBuildingType::FOOD_BUILDING)); inns.add_condition(new NotUnderConstruction); for(building_search_iterator i=inns.begin(); i!=inns.end(); ++i) { boost::shared_ptr rt=echo.get_ressource_tracker(*i); if(rt) { if(rt->get_age()>1500) { if(rt->get_total_level() < 24*echo.get_building_register().get_level(*i)) { ManagementOrder* mo_destroy=new DestroyBuilding(*i); echo.add_management_order(mo_destroy); } } } } BuildingSearch swarms(echo); swarms.add_condition(new SpecificBuildingType(IntBuildingType::SWARM_BUILDING)); swarms.add_condition(new NotUnderConstruction); for(building_search_iterator i=swarms.begin(); i!=swarms.end(); ++i) { boost::shared_ptr rt=echo.get_ressource_tracker(*i); if(rt) { if(rt->get_age()>2500) { if(rt->get_total_level() < 18) { ManagementOrder* mo_destroy=new DestroyBuilding(*i); echo.add_management_order(mo_destroy); } } } } } //Farming wheat and wood near water if((timer%250)==0) { AddArea* mo_farming=new AddArea(ForbiddenArea); RemoveArea* mo_non_farming=new RemoveArea(ForbiddenArea); AIEcho::Gradients::GradientInfo gi_water; gi_water.add_source(new Entities::Water); Gradient& gradient=echo.get_gradient_manager().get_gradient(gi_water); MapInfo mi(echo); for(int x=0; xadd_location(x, y); } else { if((mi.is_ressource(x, y, WOOD) || mi.is_ressource(x, y, CORN)) && mi.is_discovered(x, y) && !mi.is_forbidden_area(x, y) && gradient.get_height(x, y)<10) { mo_farming->add_location(x, y); } } } } } echo.add_management_order(mo_farming); echo.add_management_order(mo_non_farming); } } void ReachToInfinity::handle_message(Echo& echo, const std::string& message) { if(message=="construct inn") { //The main order for the inn BuildingOrder* bo = new BuildingOrder(IntBuildingType::FOOD_BUILDING, 2); //Constraints arround the location of wheat AIEcho::Gradients::GradientInfo gi_wheat; gi_wheat.add_source(new AIEcho::Gradients::Entities::Ressource(CORN)); //You want to be close to wheat bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_wheat, 4)); //You can't be farther than 10 units from wheat bo->add_constraint(new AIEcho::Construction::MaximumDistance(gi_wheat, 10)); //Constraints arround nearby settlement AIEcho::Gradients::GradientInfo gi_building; gi_building.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, false)); gi_building.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You want to be close to other buildings, but wheat is more important bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_building, 2)); AIEcho::Gradients::GradientInfo gi_building_construction; gi_building_construction.add_source(new AIEcho::Gradients::Entities::AnyTeamBuilding(echo.player->team->teamNumber, true)); gi_building_construction.add_obstacle(new AIEcho::Gradients::Entities::AnyRessource); //You don't want to be too close bo->add_constraint(new AIEcho::Construction::MinimumDistance(gi_building_construction, 3)); //Constraints arround the location of fruit if(echo.is_fruit_on_map()) { AIEcho::Gradients::GradientInfo gi_fruit; gi_fruit.add_source(new AIEcho::Gradients::Entities::Ressource(CHERRY)); gi_fruit.add_source(new AIEcho::Gradients::Entities::Ressource(ORANGE)); gi_fruit.add_source(new AIEcho::Gradients::Entities::Ressource(PRUNE)); //You want to be reasnobly close to fruit, closer if possible bo->add_constraint(new AIEcho::Construction::MinimizedDistance(gi_fruit, 1)); } //Add the building order to the list of orders unsigned int id=echo.add_building_order(bo); // std::cout<<"inn ordered, id="<add_condition(new ParticularBuilding(new NotUnderConstruction, id)); echo.add_management_order(mo_completion); ManagementOrder* mo_tracker=new AddRessourceTracker(12, CORN, id); mo_tracker->add_condition(new ParticularBuilding(new NotUnderConstruction, id)); echo.add_management_order(mo_tracker); } }