00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00022 #include "AI.h"
00023 #include "globals.h"
00024 #include <utility>
00025
00026 namespace AI
00027 {
00028 typedef vector<City*>::iterator CityIter;
00029 typedef vector<MilitaryUnit*>::iterator UnitIter;
00030
00031
00032
00033
00034 Player::Player(const Vec3D teamColor,
00035 vector<MilitaryUnit*> &units,
00036 vector<City*> &cities,
00037 Map::WorldMap wm) : m_teamColor(teamColor),
00038 m_units(units),
00039 m_cities(cities),
00040 m_threatMap(wm.gridWidth, vector<FLOAT>(wm.gridHeight)),
00041 m_worldMap(wm)
00042 {
00043
00044 }
00045
00046
00047
00048 void Player::update()
00049 {
00050 buildThreatMap();
00051
00052
00054
00055 vector<MilitaryUnit*> myUnits;
00056 UnitIter unitIter;
00057 for(unitIter = m_units.begin(); unitIter != m_units.end(); ++unitIter)
00058 {
00059 if( (*unitIter)->color() == m_teamColor ) myUnits.push_back((*unitIter));
00060 }
00061
00062
00063 vector<City*> neutralCities;
00064 vector<City*> enemyCities;
00065 CityIter cityIter;
00066 for(cityIter = m_cities.begin(); cityIter != m_cities.end(); ++cityIter)
00067 {
00068 if( (*cityIter)->color() == Globals::NO_OWNER )
00069 neutralCities.push_back(*cityIter);
00070 else if( (*cityIter)->color() != m_teamColor )
00071 enemyCities.push_back(*cityIter);
00072 }
00073
00074 if( !neutralCities.empty() )
00075 {
00076
00077 sort(neutralCities.begin(), neutralCities.end(), CityLessThreatened(m_threatMap, m_worldMap) );
00078
00079 size_t numCities = neutralCities.size();
00080 size_t city;
00081 for(unitIter = myUnits.begin(), city=0; (unitIter != myUnits.end()) && city < numCities; ++unitIter, ++city)
00082 {
00083 if(!(*unitIter)->isIdle()) (*unitIter)->goal( neutralCities[city]->position() );
00084 }
00085
00086 }
00087
00088 else
00089 {
00090
00091 sort(enemyCities.begin(), enemyCities.end(), CityLessThreatened(m_threatMap, m_worldMap) );
00092
00093
00094
00095
00096
00097
00098
00099
00100 for(cityIter = enemyCities.begin(); cityIter != enemyCities.end(); ++cityIter)
00101 {
00102 sendUnitsToCity(myUnits, *cityIter);
00103 }
00104 }
00105
00106 }
00107
00108
00109
00110 Vec3D Player::color() const { return m_teamColor; }
00111
00112 const ThreatMap &Player::threatMap() { return m_threatMap; }
00113
00114
00115
00116
00117
00118 Player::CityLessThreatened::CityLessThreatened(ThreatMap &tm, Map::WorldMap &wm):
00119 m_threatMap(tm), m_worldMap(wm) { }
00120
00121
00122 BOOL Player::CityLessThreatened::operator ()(City *c1, City *c2) const
00123 {
00124 Int2Tuple c1Coords = m_worldMap.worldToGridCoord(c1->position());
00125 Int2Tuple c2Coords = m_worldMap.worldToGridCoord(c2->position());
00126 return m_threatMap[c1Coords.a][c1Coords.b] < m_threatMap[c2Coords.a][c2Coords.b];
00127 }
00128
00129
00130 void Player::clearThreatMap()
00131 {
00132 for(int i=0; i < m_worldMap.gridHeight; ++i)
00133 for(int j=0; j < m_worldMap.gridWidth; ++j)
00134 m_threatMap[i][j] = 0.0f;
00135 }
00136
00137
00138
00139
00140
00141 void Player::buildThreatMap()
00142 {
00143 clearThreatMap();
00144 for(UnitIter iter=m_units.begin(); iter != m_units.end(); ++iter)
00145 {
00146
00147
00148 if( (*iter)->color() != m_teamColor )
00149 {
00150
00151
00152 Int2Tuple gridCoord = m_worldMap.worldToGridCoord((*iter)->position());
00153 m_threatMap[gridCoord.a][gridCoord.b] += AI::unitThreatIncr;
00154
00155 int endRow = gridCoord.a+1 <= m_worldMap.gridHeight-1 ? gridCoord.a+1 : m_worldMap.gridHeight-1;
00156 int endCol = gridCoord.b+1 <= m_worldMap.gridWidth-1 ? gridCoord.b+1 : m_worldMap.gridWidth-1;
00157 for(int row=(gridCoord.a-1 >= 0 ? gridCoord.a-1 : 0); row <= endRow; ++row)
00158 {
00159 for(int col=(gridCoord.b-1 >= 0 ? gridCoord.b-1 : 0); col <= endCol; ++col)
00160 m_threatMap[row][col] += AI::unitThreatIncr;
00161 }
00162
00163 }
00164 }
00165
00166 }
00167
00168
00169 typedef pair<MilitaryUnit*, FLOAT> UnitDist;
00170
00171 class SmallerDistToCity
00172 {
00173 public:
00174 BOOL operator()(UnitDist &ud1, UnitDist ud2) { return ud1.second < ud2.second; }
00175 };
00176
00180 void Player::sendUnitsToCity(vector<MilitaryUnit*> &units, const City *city)
00181 {
00182
00183 vector<UnitDist> unitDists;
00184 for(UnitIter iter=units.begin(); iter != units.end(); ++iter)
00185 {
00186 unitDists.push_back(UnitDist((*iter), Helper::distXY((*iter)->position(), city->position())));
00187 }
00188
00189
00190 sort(unitDists.begin(), unitDists.end(), SmallerDistToCity());
00191
00192 if(unitDists.size() > 0 && (!unitDists[0].first->isIdle())) unitDists[0].first->goal(city->position());
00193 if(unitDists.size() >= 2 && !unitDists[1].first->isIdle())
00194 {
00195 unitDists[1].first->goal(city->position());
00196 }
00197
00198 }
00199
00200
00201 }