00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "global.hpp"
00017
00018 #include "ai.hpp"
00019 #include "game_config.hpp"
00020 #include "gettext.hpp"
00021 #include "log.hpp"
00022 #include "map.hpp"
00023 #include "util.hpp"
00024 #include "variable.hpp"
00025 #include "wml_exception.hpp"
00026
00027 #include <cassert>
00028 #include <iostream>
00029
00030 #define LOG_AI LOG_STREAM(info, ai)
00031
00032 struct move_cost_calculator : cost_calculator
00033 {
00034 move_cost_calculator(const unit& u, const gamemap& map,
00035 const unit_map& units,
00036 const gamemap::location& loc,
00037 const ai::move_map& dstsrc,
00038 const ai::move_map& enemy_dstsrc)
00039 : unit_(u), map_(map), units_(units),
00040 loc_(loc), dstsrc_(dstsrc), enemy_dstsrc_(enemy_dstsrc),
00041 avoid_enemies_(u.usage() == "scout")
00042 {}
00043
00044 virtual double cost(const gamemap::location&, const gamemap::location& loc, const double) const
00045 {
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 assert(map_.on_board(loc));
00061
00062 const t_translation::t_terrain terrain = map_[loc];
00063
00064 const double modifier = 1.0;
00065 const double move_cost = unit_.movement_cost(terrain);
00066
00067 const int enemies = 1 + (avoid_enemies_ ? enemy_dstsrc_.count(loc) : 0);
00068 double res = modifier*move_cost*double(enemies);
00069
00070
00071
00072 if (units_.count(loc))
00073 res *= 4.0;
00074
00075 VALIDATE(res > 0,
00076 _("Movement cost is 0, probably a terrain with movement cost of 0."));
00077 return res;
00078 }
00079
00080 private:
00081 const unit& unit_;
00082 const gamemap& map_;
00083 const unit_map& units_;
00084
00085 const gamemap::location loc_;
00086 const ai::move_map dstsrc_, enemy_dstsrc_;
00087 const bool avoid_enemies_;
00088 };
00089
00090 std::vector<ai::target> ai::find_targets(unit_map::const_iterator leader, const move_map& enemy_dstsrc)
00091 {
00092 log_scope2(ai, "finding targets...");
00093
00094 const bool has_leader = leader != units_.end();
00095
00096 std::vector<target> targets;
00097
00098
00099 if(has_leader) {
00100 const double threat = power_projection(leader->first,enemy_dstsrc);
00101 if(threat > 0.0) {
00102
00103 std::set<gamemap::location> threats;
00104
00105 gamemap::location adj[6];
00106 get_adjacent_tiles(leader->first,adj);
00107 for(size_t n = 0; n != 6; ++n) {
00108 std::pair<move_map::const_iterator,move_map::const_iterator> itors = enemy_dstsrc.equal_range(adj[n]);
00109 while(itors.first != itors.second) {
00110 if(units_.count(itors.first->second)) {
00111 threats.insert(itors.first->second);
00112 }
00113
00114 ++itors.first;
00115 }
00116 }
00117
00118 assert(threats.empty() == false);
00119
00120 const double value = threat/double(threats.size());
00121 for(std::set<gamemap::location>::const_iterator i = threats.begin(); i != threats.end(); ++i) {
00122 targets.push_back(target(*i,value,target::THREAT));
00123 }
00124 }
00125 }
00126
00127 if(has_leader && current_team().village_value() > 0.0) {
00128 const std::vector<location>& villages = map_.villages();
00129 for(std::vector<location>::const_iterator t =
00130 villages.begin(); t != villages.end(); ++t) {
00131
00132 assert(map_.on_board(*t));
00133 bool get_village = true;
00134 for(size_t i = 0; i != teams_.size(); ++i) {
00135 if(!current_team().is_enemy(i+1) && teams_[i].owns_village(*t)) {
00136 get_village = false;
00137 break;
00138 }
00139 }
00140
00141 if(get_village) {
00142 targets.push_back(target(*t,current_team().village_value(),target::VILLAGE));
00143 }
00144 }
00145 }
00146
00147 std::vector<team::target>& team_targets = current_team().targets();
00148
00149
00150 unit_map::const_iterator u;
00151 for(u = units_.begin(); u != units_.end(); ++u) {
00152
00153
00154 if(u->second.can_recruit() &&
00155 current_team().is_enemy(u->second.side())) {
00156
00157 assert(map_.on_board(u->first));
00158 targets.push_back(target(u->first,current_team().leader_value(),target::LEADER));
00159 }
00160
00161
00162 for(std::vector<team::target>::iterator j = team_targets.begin();
00163 j != team_targets.end(); ++j) {
00164 if(u->second.matches_filter(&(j->criteria),u->first)) {
00165 LOG_AI << "found explicit target..." << j->value << "\n";
00166 targets.push_back(target(u->first,j->value,target::EXPLICIT));
00167 }
00168 }
00169 }
00170
00171 std::vector<double> new_values;
00172
00173 for(std::vector<target>::iterator i = targets.begin();
00174 i != targets.end(); ++i) {
00175
00176 new_values.push_back(i->value);
00177
00178 for(std::vector<target>::const_iterator j = targets.begin(); j != targets.end(); ++j) {
00179 if(i->loc == j->loc) {
00180 continue;
00181 }
00182
00183 const double distance = abs(j->loc.x - i->loc.x) +
00184 abs(j->loc.y - i->loc.y);
00185 new_values.back() += j->value/(distance*distance);
00186 }
00187 }
00188
00189 assert(new_values.size() == targets.size());
00190 for(size_t n = 0; n != new_values.size(); ++n) {
00191 LOG_AI << "target value: " << targets[n].value << " -> " << new_values[n] << "\n";
00192 targets[n].value = new_values[n];
00193 }
00194
00195 return targets;
00196 }
00197
00198 gamemap::location ai::form_group(const std::vector<location>& route, const move_map& dstsrc, std::set<location>& res)
00199 {
00200 if(route.empty()) {
00201 return location();
00202 }
00203
00204 std::vector<location>::const_iterator i;
00205 for(i = route.begin(); i != route.end(); ++i) {
00206 if(units_.count(*i) > 0) {
00207 continue;
00208 }
00209
00210 size_t n = 0, nunits = res.size();
00211
00212 const std::pair<move_map::const_iterator,move_map::const_iterator> itors = dstsrc.equal_range(*i);
00213 for(move_map::const_iterator j = itors.first; j != itors.second; ++j) {
00214 if(res.count(j->second) != 0) {
00215 ++n;
00216 } else {
00217 const unit_map::const_iterator un = units_.find(j->second);
00218 if(un == units_.end() || un->second.can_recruit() || un->second.movement_left() < un->second.total_movement()) {
00219 continue;
00220 }
00221
00222 res.insert(j->second);
00223 }
00224 }
00225
00226
00227 if(n < nunits) {
00228 break;
00229 }
00230 }
00231
00232 if(i != route.begin()) {
00233 --i;
00234 }
00235
00236 return *i;
00237 }
00238
00239 void ai::enemies_along_path(const std::vector<location>& route, const move_map& dstsrc, std::set<location>& res)
00240 {
00241 for(std::vector<location>::const_iterator i = route.begin(); i != route.end(); ++i) {
00242 gamemap::location adj[6];
00243 get_adjacent_tiles(*i,adj);
00244 for(size_t n = 0; n != 6; ++n) {
00245 const std::pair<move_map::const_iterator,move_map::const_iterator> itors = dstsrc.equal_range(adj[n]);
00246 for(move_map::const_iterator j = itors.first; j != itors.second; ++j) {
00247 res.insert(j->second);
00248 }
00249 }
00250 }
00251 }
00252
00253 bool ai::move_group(const location& dst, const std::vector<location>& route, const std::set<location>& units)
00254 {
00255 const std::vector<location>::const_iterator itor = std::find(route.begin(),route.end(),dst);
00256 if(itor == route.end()) {
00257 return false;
00258 }
00259
00260 LOG_AI << "group has " << units.size() << " members\n";
00261
00262 location next;
00263
00264 size_t direction = 0;
00265
00266
00267 if(itor+1 != route.end()) {
00268 next = *(itor+1);
00269 } else if(itor != route.begin()) {
00270 next = *(itor-1);
00271 }
00272
00273 if(next.valid()) {
00274 location adj[6];
00275 get_adjacent_tiles(dst,adj);
00276
00277 direction = std::find(adj,adj+6,next) - adj;
00278 }
00279
00280 std::deque<location> preferred_moves;
00281 preferred_moves.push_back(dst);
00282
00283 std::map<location,paths> possible_moves;
00284 move_map srcdst, dstsrc;
00285 calculate_possible_moves(possible_moves,srcdst,dstsrc,false);
00286
00287 bool res = false;
00288
00289 for(std::set<location>::const_iterator i = units.begin(); i != units.end(); ++i) {
00290 const unit_map::const_iterator un = units_.find(*i);
00291 if(un == units_.end()) {
00292 continue;
00293 }
00294
00295 location best_loc;
00296 int best_defense = -1;
00297 for(std::deque<location>::const_iterator j = preferred_moves.begin(); j != preferred_moves.end(); ++j) {
00298 if(units_.count(*j)) {
00299 continue;
00300 }
00301
00302 const std::pair<move_map::const_iterator,move_map::const_iterator> itors = dstsrc.equal_range(*j);
00303 move_map::const_iterator m;
00304 for(m = itors.first; m != itors.second; ++m) {
00305 if(m->second == *i) {
00306 break;
00307 }
00308 }
00309
00310 if(m == itors.second) {
00311 continue;
00312 }
00313
00314 const int defense = un->second.defense_modifier(map_.get_terrain(*j));
00315 if(best_loc.valid() == false || defense < best_defense) {
00316 best_loc = *j;
00317 best_defense = defense;
00318 }
00319 }
00320
00321 if(best_loc.valid()) {
00322 res = true;
00323 const location res = move_unit(*i,best_loc,possible_moves);
00324
00325
00326 if(res != best_loc) {
00327 return true;
00328 }
00329
00330 preferred_moves.erase(std::find(preferred_moves.begin(),preferred_moves.end(),best_loc));
00331
00332
00333 location adj[6];
00334 get_adjacent_tiles(best_loc,adj);
00335 for(size_t n = 0; n != 6; ++n) {
00336 if(n != direction && ((n+3)%6) != direction && map_.on_board(adj[n]) &&
00337 units_.count(adj[n]) == 0 && std::count(preferred_moves.begin(),preferred_moves.end(),adj[n]) == 0) {
00338 preferred_moves.push_front(adj[n]);
00339 LOG_AI << "added moves: " << adj[n].x + 1 << "," << adj[n].y + 1 << "\n";
00340 }
00341 }
00342 } else {
00343 LOG_AI << "Could not move group member to any of " << preferred_moves.size() << " locations\n";
00344 }
00345 }
00346
00347 return res;
00348 }
00349
00350 double ai::rate_group(const std::set<location>& group, const std::vector<location>& battlefield) const
00351 {
00352 double strength = 0.0;
00353 for(std::set<location>::const_iterator i = group.begin(); i != group.end(); ++i) {
00354 const unit_map::const_iterator u = units_.find(*i);
00355 if(u == units_.end()) {
00356 continue;
00357 }
00358
00359 const unit& un = u->second;
00360
00361 int defense = 0;
00362 for(std::vector<location>::const_iterator j = battlefield.begin(); j != battlefield.end(); ++j) {
00363 defense += un.defense_modifier(map_.get_terrain(*j));
00364 }
00365
00366 defense /= battlefield.size();
00367
00368 int best_attack = 0;
00369 const std::vector<attack_type>& attacks = un.attacks();
00370 for(std::vector<attack_type>::const_iterator a = attacks.begin(); a != attacks.end(); ++a) {
00371 const int strength = a->num_attacks()*a->damage();
00372 best_attack = maximum<int>(strength,best_attack);
00373 }
00374
00375 const int rating = (defense*best_attack*un.hitpoints())/(100*un.max_hitpoints());
00376 strength += double(rating);
00377 }
00378
00379 return strength;
00380 }
00381
00382 double ai::compare_groups(const std::set<location>& our_group, const std::set<location>& their_group, const std::vector<location>& battlefield) const
00383 {
00384 const double a = rate_group(our_group,battlefield);
00385 const double b = maximum<double>(rate_group(their_group,battlefield),0.01);
00386 return a/b;
00387 }
00388
00389 std::pair<gamemap::location,gamemap::location> ai::choose_move(std::vector<target>& targets, const move_map& srcdst, const move_map& dstsrc, const move_map& enemy_dstsrc)
00390 {
00391 log_scope2(ai, "choosing move");
00392
00393 raise_user_interact();
00394
00395 std::vector<target>::const_iterator ittg;
00396 for(ittg = targets.begin(); ittg != targets.end(); ++ittg) {
00397 assert(map_.on_board(ittg->loc));
00398 }
00399
00400 paths::route best_route;
00401 unit_map::iterator best = units_.end();
00402 double best_rating = 0.1;
00403
00404 std::vector<target>::iterator best_target = targets.end();
00405
00406 unit_map::iterator u;
00407
00408
00409 for(u = units_.begin(); u != units_.end(); ++u) {
00410 if(!(u->second.side() != team_num_ || u->second.can_recruit() || u->second.movement_left() <= 0 || u->second.incapacitated())) {
00411 break;
00412 }
00413 }
00414
00415 if(u == units_.end()) {
00416 LOG_AI << "no eligible units found\n";
00417 return std::pair<location,location>();
00418 }
00419
00420
00421 if(utils::string_bool(u->second.get_state("guardian"))) {
00422 LOG_AI << u->second.type_id() << " is guardian, staying still\n";
00423 return std::pair<location,location>(u->first,u->first);
00424 }
00425
00426 const move_cost_calculator cost_calc(u->second, map_, units_, u->first, dstsrc, enemy_dstsrc);
00427
00428
00429 for(std::vector<target>::iterator tg = targets.begin(); tg != targets.end(); ++tg) {
00430 if(avoided_locations().count(tg->loc) > 0) {
00431 continue;
00432 }
00433
00434 raise_user_interact();
00435
00436 assert(map_.on_board(tg->loc));
00437
00438 const double locStopValue = minimum(tg->value / best_rating, 500.0);
00439 paths::route cur_route = a_star_search(u->first, tg->loc, locStopValue, &cost_calc, map_.w(), map_.h());
00440
00441 if (cur_route.move_left < locStopValue)
00442 {
00443
00444 typedef std::multimap<gamemap::location,gamemap::location>::const_iterator multimapItor;
00445 std::pair<multimapItor,multimapItor> locRange = dstsrc.equal_range(u->first);
00446 while (locRange.first != locRange.second) {
00447 if (locRange.first->second == u->first) {
00448 cur_route.move_left = 0;
00449 }
00450 ++locRange.first;
00451 }
00452 }
00453
00454 double rating = tg->value/maximum<int>(1,cur_route.move_left);
00455
00456
00457
00458 if(tg->type == target::SUPPORT) {
00459 if(cur_route.move_left <= u->second.movement_left()*2) {
00460 rating *= 10.0;
00461 } else {
00462 rating = 0.0;
00463 }
00464 }
00465
00466
00467 if(u->second.usage() == "scout") {
00468 std::set<location> enemies_guarding;
00469 enemies_along_path(cur_route.steps,enemy_dstsrc,enemies_guarding);
00470
00471 if(enemies_guarding.size() > 1) {
00472 rating /= enemies_guarding.size();
00473 } else {
00474
00475
00476
00477 rating *= 100;
00478 }
00479
00480
00481 if(tg->type == target::VILLAGE) {
00482 rating *= lexical_cast_default<int>(current_team().ai_parameters()["scout_village_targetting"],3);
00483 }
00484 }
00485
00486 LOG_AI << tg->value << "/" << cur_route.move_left << " = " << rating << "\n";
00487 if(best_target == targets.end() || rating > best_rating) {
00488 best_rating = rating;
00489 best_target = tg;
00490 best = u;
00491 best_route = cur_route;
00492 if(best_rating == 0)
00493 {
00494 best_rating = 0.000000001;
00495 }
00496 }
00497 }
00498
00499 LOG_AI << "chose target...\n";
00500
00501
00502 if(best_target == targets.end()) {
00503 LOG_AI << "no eligible targets found\n";
00504 return std::pair<location,location>();
00505 }
00506
00507
00508
00509 const bool dumb_ai = utils::string_bool(current_team().ai_parameters()["simple_targetting"]);
00510
00511 if(dumb_ai == false) {
00512 LOG_AI << "complex targetting...\n";
00513
00514 for(++u; u != units_.end(); ++u) {
00515 if(u->second.side() != team_num_ || u->second.can_recruit() ||
00516 u->second.movement_left() <= 0 || utils::string_bool(u->second.get_state("guardian")) || u->second.incapacitated()) {
00517 continue;
00518 }
00519
00520 raise_user_interact();
00521
00522 const move_cost_calculator calc(u->second, map_, units_, u->first, dstsrc, enemy_dstsrc);
00523 const double locStopValue = minimum(best_target->value / best_rating, 100.0);
00524 paths::route cur_route = a_star_search(u->first, best_target->loc, locStopValue, &calc, map_.w(), map_.h());
00525
00526 if (cur_route.move_left < locStopValue)
00527 {
00528
00529 typedef std::multimap<gamemap::location,gamemap::location>::const_iterator multimapItor;
00530 std::pair<multimapItor,multimapItor> locRange = dstsrc.equal_range(u->first);
00531 while (locRange.first != locRange.second) {
00532 if (locRange.first->second == u->first) {
00533 cur_route.move_left = 0;
00534 }
00535 ++locRange.first;
00536 }
00537 }
00538
00539 double rating = best_target->value/maximum<int>(1,cur_route.move_left);
00540
00541
00542
00543 if(best_target->type == target::SUPPORT) {
00544 if(cur_route.move_left <= u->second.movement_left()*2) {
00545 rating *= 10.0;
00546 } else {
00547 rating = 0.0;
00548 }
00549 }
00550
00551
00552 if(u->second.usage() == "scout") {
00553 std::set<location> enemies_guarding;
00554 enemies_along_path(cur_route.steps,enemy_dstsrc,enemies_guarding);
00555
00556 if(enemies_guarding.size() > 1) {
00557 rating /= enemies_guarding.size();
00558 } else {
00559 rating *= 100;
00560 }
00561 }
00562
00563 if(best == units_.end() || rating > best_rating) {
00564 best_rating = rating;
00565 best = u;
00566 best_route = cur_route;
00567 }
00568 }
00569
00570 LOG_AI << "done complex targetting...\n";
00571 } else {
00572 u = units_.end();
00573 }
00574
00575 LOG_AI << "best unit: " << best->first << '\n';
00576
00577 assert(best_target >= targets.begin() && best_target < targets.end());
00578
00579 for(ittg = targets.begin(); ittg != targets.end(); ++ittg) {
00580 assert(map_.on_board(ittg->loc));
00581 }
00582
00583
00584
00585 if(best_target->type == target::SUPPORT) {
00586 LOG_AI << "support...\n";
00587
00588 std::vector<location> locs;
00589 access_points(srcdst,best->first,best_target->loc,locs);
00590
00591 if(locs.empty() == false) {
00592 LOG_AI << "supporting unit at " << best_target->loc.x + 1 << "," << best_target->loc.y + 1 << "\n";
00593 location best_loc;
00594 int best_defense = 0;
00595 double best_vulnerability = 0.0;
00596 int best_distance = 0;
00597
00598 for(std::vector<location>::const_iterator i = locs.begin(); i != locs.end(); ++i) {
00599 const int distance = distance_between(*i,best_target->loc);
00600 const int defense = best->second.defense_modifier(map_.get_terrain(*i));
00601 const double vulnerability = power_projection(*i,enemy_dstsrc);
00602
00603 if(best_loc.valid() == false || defense < best_defense || (defense == best_defense && vulnerability < best_vulnerability)) {
00604 best_loc = *i;
00605 best_defense = defense;
00606 best_vulnerability = vulnerability;
00607 best_distance = distance;
00608 }
00609 }
00610
00611 LOG_AI << "returning support...\n";
00612 return std::pair<location,location>(best->first,best_loc);
00613 }
00614 }
00615
00616 std::map<gamemap::location,paths> dummy_possible_moves;
00617 move_map fullmove_srcdst;
00618 move_map fullmove_dstsrc;
00619 calculate_possible_moves(dummy_possible_moves,fullmove_srcdst,fullmove_dstsrc,false,true);
00620
00621 bool dangerous = false;
00622
00623 if(current_team().ai_parameters()["grouping"] != "no") {
00624 LOG_AI << "grouping...\n";
00625 const unit_map::const_iterator unit_at_target = units_.find(best_target->loc);
00626 int movement = best->second.movement_left();
00627
00628 const bool defensive_grouping = current_team().ai_parameters()["grouping"] == "defensive";
00629
00630
00631
00632
00633 for(std::vector<location>::const_iterator i = best_route.steps.begin(); i != best_route.steps.end() && movement > 0; ++i) {
00634
00635 const double threat = power_projection(*i,enemy_dstsrc);
00636 if((threat >= double(best->second.hitpoints()) && threat > power_projection(*i,fullmove_dstsrc)) ||
00637 (i >= best_route.steps.end()-2 && unit_at_target != units_.end() && current_team().is_enemy(unit_at_target->second.side()))) {
00638 dangerous = true;
00639 break;
00640 }
00641
00642 if(!defensive_grouping) {
00643 movement -= best->second.movement_cost(map_.get_terrain(*i));
00644 }
00645 }
00646
00647 LOG_AI << "done grouping...\n";
00648 }
00649
00650 if(dangerous) {
00651 LOG_AI << "dangerous path\n";
00652 std::set<location> group, enemies;
00653 const location dst = form_group(best_route.steps,dstsrc,group);
00654 enemies_along_path(best_route.steps,enemy_dstsrc,enemies);
00655
00656 const double our_strength = compare_groups(group,enemies,best_route.steps);
00657
00658 if(our_strength > 0.5 + current_team().caution()) {
00659 LOG_AI << "moving group\n";
00660 const bool res = move_group(dst,best_route.steps,group);
00661 if(res) {
00662 return std::pair<location,location>(location(1,1),location());
00663 } else {
00664 LOG_AI << "group didn't move " << group.size() << "\n";
00665
00666
00667 return std::pair<location,location>(best->first,best->first);
00668
00669 }
00670 } else {
00671 LOG_AI << "massing to attack " << best_target->loc.x + 1 << "," << best_target->loc.y + 1
00672 << " " << our_strength << "\n";
00673
00674 const double value = best_target->value;
00675 const location target_loc = best_target->loc;
00676 const location loc = best->first;
00677 const unit& un = best->second;
00678
00679 targets.erase(best_target);
00680
00681
00682 location best_loc;
00683 double best_threat = 0.0;
00684 int best_distance = 0;
00685
00686 const double max_acceptable_threat = un.hitpoints()/4;
00687
00688 std::set<location> mass_locations;
00689
00690 const std::pair<move_map::const_iterator,move_map::const_iterator> itors = srcdst.equal_range(loc);
00691 for(move_map::const_iterator i = itors.first; i != itors.second; ++i) {
00692 const int distance = distance_between(target_loc,i->second);
00693 const int defense = un.defense_modifier(map_.get_terrain(i->second));
00694 const double threat = (power_projection(i->second,enemy_dstsrc)*defense)/100;
00695
00696 if(best_loc.valid() == false || (threat < maximum<double>(best_threat,max_acceptable_threat) && distance < best_distance)) {
00697 best_loc = i->second;
00698 best_threat = threat;
00699 best_distance = distance;
00700 }
00701
00702 if(threat < max_acceptable_threat) {
00703 mass_locations.insert(i->second);
00704 }
00705 }
00706
00707 for(std::set<location>::const_iterator j = mass_locations.begin(); j != mass_locations.end(); ++j) {
00708 if(*j != best_loc && distance_between(*j,best_loc) < 3) {
00709 targets.push_back(target(*j,value*4.0,target::MASS));
00710 }
00711 }
00712
00713 return std::pair<location,location>(loc,best_loc);
00714 }
00715 }
00716
00717 for(std::vector<location>::reverse_iterator ri =
00718 best_route.steps.rbegin(); ri != best_route.steps.rend(); ++ri) {
00719
00720 if(game_config::debug) {
00721
00722 }
00723
00724
00725
00726 bool is_dangerous = false;
00727
00728 typedef std::multimap<location,location>::const_iterator Itor;
00729 std::pair<Itor,Itor> its = dstsrc.equal_range(*ri);
00730 while(its.first != its.second) {
00731 if(its.first->second == best->first) {
00732 if(!should_retreat(its.first->first,best,fullmove_srcdst,fullmove_dstsrc,enemy_dstsrc,
00733 current_team().caution())) {
00734 const double value = best_target->value - best->second.cost()/20.0;
00735
00736 if(value > 0.0 && best_target->type != target::MASS) {
00737
00738
00739 if(is_dangerous) {
00740 targets.push_back(target(its.first->first,value*2.0,target::BATTLE_AID));
00741 }
00742
00743 best_target->value = value;
00744 } else {
00745 targets.erase(best_target);
00746 }
00747
00748 LOG_AI << "Moving to " << its.first->first.x + 1 << "," << its.first->first.y + 1 << "\n";
00749
00750 return std::pair<location,location>(its.first->second,its.first->first);
00751 } else {
00752 LOG_AI << "dangerous!\n";
00753 is_dangerous = true;
00754 }
00755 }
00756
00757 ++its.first;
00758 }
00759 }
00760
00761 if(best != units_.end()) {
00762 LOG_AI << "Could not make good move, staying still\n";
00763
00764
00765
00766 targets.push_back(target(best->first,best_target->value));
00767 return std::pair<location,location>(best->first,best->first);
00768 }
00769
00770 LOG_AI << "Could not find anywhere to move!\n";
00771 return std::pair<location,location>();
00772 }
00773
00774 void ai::access_points(const move_map& srcdst, const location& u, const location& dst, std::vector<location>& out)
00775 {
00776 const unit_map::const_iterator u_it = units_.find(u);
00777 if(u_it == units_.end()) {
00778 return;
00779 }
00780
00781
00782
00783 const std::pair<move_map::const_iterator,move_map::const_iterator> locs = srcdst.equal_range(u);
00784 for(move_map::const_iterator i = locs.first; i != locs.second; ++i) {
00785 const location& loc = i->second;
00786 if (int(distance_between(loc,dst)) <= u_it->second.total_movement()) {
00787 shortest_path_calculator calc(u_it->second, current_team(), units_, teams_, map_);
00788 const paths::route& rt = a_star_search(loc, dst, u_it->second.total_movement(), &calc, map_.w(), map_.h());
00789 if(rt.steps.empty() == false) {
00790 out.push_back(loc);
00791 }
00792 }
00793 }
00794 }