void CAttackHandler::UpdateKMeans() { const int arrowDuration = 300; {//want local variable definitions //get positions of all friendly units and put them in a vector (completed buildings only) int numFriendlies = 0; vector<float3> friendlyPositions; int friendlies[MAXUNITS]; numFriendlies = ai->cb->GetFriendlyUnits(friendlies); for (int i = 0; i < numFriendlies; i++) { int unit = friendlies[i]; CUNIT* u = ai->MyUnits[unit]; //its a building, it has hp, and its mine (0) if (this->UnitBuildingFilter(u->def()) && this->UnitReadyFilter(unit) && u->owner() == 0) { friendlyPositions.push_back(u->pos()); } } //hack to make it at least 1 unit, should only happen when you have no base: if (friendlyPositions.size() < 1) { //it has to be a proper position, unless there are no proper positions. if (numFriendlies > 0 && ai->cb->GetUnitDef(friendlies[0]) && ai->MyUnits[friendlies[0]]->owner() == 0) friendlyPositions.push_back(ai->cb->GetUnitPos(friendlies[0])); else friendlyPositions.push_back(float3(RANDINT % (ai->cb->GetMapWidth()*8), 1000, RANDINT % (ai->cb->GetMapHeight()*8))); //when everything is dead } //calculate a new K. change the formula to adjust max K, needs to be 1 minimum. this->kMeansK = int(min((float)(KMEANS_BASE_MAX_K), 1.0f + sqrtf((float)numFriendlies+0.01f))); //iterate k-means algo over these positions and move the means this->kMeansBase = KMeansIteration(this->kMeansBase, friendlyPositions, this->kMeansK); //now, draw these means on the map int lineWidth = 25; int lineWidth2 = 3; // for (int i = 0; i < kMeansK; i++) { // //ai->cb->CreateLineFigure(kMeansBase[i]+float3(0,400,0), kMeansBase[i], lineWidth, 1, arrowDuration, RANDINT % 59549847); // } } //update enemy position k-means //get positions of all enemy units and put them in a vector (completed buildings only) int numEnemies = 0; vector<float3> enemyPositions; int enemies[MAXUNITS]; numEnemies = ai->cheat->GetEnemyUnits(enemies); for (int i = 0; i < numEnemies; i++) { const UnitDef *ud = ai->cheat->GetUnitDef(enemies[i]); if (this->UnitBuildingFilter(ud)) { // && this->UnitReadyFilter(unit)) { enemyPositions.push_back(ai->cheat->GetUnitPos(enemies[i])); // //L("AttackHandler debug: added enemy building position for k-means " << i); } } //hack to make it at least 1 unit, should only happen when you have no base: if (enemyPositions.size() < 1) { //it has to be a proper position, unless there are no proper positions. if (numEnemies > 0 && ai->cheat->GetUnitDef(enemies[0])) enemyPositions.push_back(ai->cheat->GetUnitPos(enemies[0])); else enemyPositions.push_back(float3(RANDINT % (ai->cb->GetMapWidth()*8), 1000, RANDINT % (ai->cb->GetMapHeight()*8))); //when everything is dead } //calculate a new K. change the formula to adjust max K, needs to be 1 minimum. this->kMeansEnemyK = int(min(float(KMEANS_ENEMY_MAX_K), 1.0f + sqrtf((float)numEnemies+0.01f))); // //L("AttackHandler: doing k-means k:" << kMeansK << " numPositions=" << numFriendlies); //iterate k-means algo over these positions and move the means this->kMeansEnemyBase = KMeansIteration(this->kMeansEnemyBase, enemyPositions, this->kMeansEnemyK); //now, draw these means on the map int lineWidth = 25; // for (int i = 0; i < kMeansEnemyK; i++) { // //L("AttackHandler debug: painting k-means for enemy nr " << i); // //ai->cb->CreateLineFigure(kMeansEnemyBase[i]+float3(300,300,0), kMeansEnemyBase[i], lineWidth, 1, arrowDuration, (RANDINT % 49584985)); // } //base k-means and enemy base k-means are updated. //approach: add up (max - distance) to enemies vector<float> proximity; proximity.resize(kMeansK, 0.0000001f); const float mapDiagonal = sqrt(pow((float)ai->cb->GetMapHeight()*8,2) + pow((float)ai->cb->GetMapWidth()*8,2) + 1.0f); for (int f = 0; f < kMeansK; f++) { for (int e = 0; e < kMeansEnemyK; e++) { proximity[f] += mapDiagonal - kMeansBase[f].distance2D(kMeansEnemyBase[e]); } } //sort kMeans by the proximity score float3 tempPos; float temp; for (int i = 1; i < kMeansK; i++) { //how many are completed for (int j = 0; j < i; j++) { //compare to / switch with if (proximity[i] > proximity[j]) { //switch tempPos = kMeansBase[i]; kMeansBase[i] = kMeansBase[j]; kMeansBase[j] = tempPos; temp = proximity[i]; proximity[i] = proximity[j]; proximity[j] = temp; } } } //okay, so now we have a kMeans list sorted by distance to enemies, 0 being risky and k being safest. //now, draw these means on the map for (int i = 1; i < kMeansK; i++) { //ai->cb->CreateLineFigure(kMeansBase[i-1]+float3(0,100,0), kMeansBase[i]+float3(0,100,0), lineWidth, 1, arrowDuration, (RANDINT % 59549847)); } }