00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "global.hpp"
00020
00021 #include "ai.hpp"
00022 #include "log.hpp"
00023
00024 #include <cassert>
00025 #include <numeric>
00026
00027 #define DBG_AI LOG_STREAM(debug, ai)
00028 #define LOG_AI LOG_STREAM(info, ai)
00029 #define WRN_AI LOG_STREAM(warn, ai)
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 namespace {
00100
00101 gamemap::location keep_loc = gamemap::location::null_location;
00102
00103 gamemap::location leader_loc = gamemap::location::null_location;
00104
00105
00106 gamemap::location best_leader_loc = gamemap::location::null_location;
00107
00108
00109 bool debug = false;
00110
00111 typedef std::map<gamemap::location ,
00112 std::vector<gamemap::location > > treachmap;
00113
00114 typedef std::vector<std::pair<gamemap::location ,
00115 gamemap::location > > tmoves;
00116 }
00117
00118
00119 static void dispatch(treachmap& reachmap, tmoves& moves);
00120
00121
00122
00123 static bool dispatch_unit_simple(treachmap& reachmap, tmoves& moves);
00124
00125
00126
00127 static bool dispatch_village_simple(
00128 treachmap& reachmap, tmoves& moves, size_t& village_count);
00129
00130
00131 static bool remove_village(
00132 treachmap& reachmap, tmoves& moves, const gamemap::location& village);
00133
00134
00135 static treachmap::iterator remove_unit(
00136 treachmap& reachmap, tmoves& moves, treachmap::iterator unit);
00137
00138
00139 static void dispatch_complex(
00140 treachmap& reachmap, tmoves& moves, const size_t village_count);
00141
00142
00143 static void full_dispatch(treachmap& reachmap, tmoves& moves);
00144
00145
00146 static void dump_reachmap(treachmap& reachmap);
00147
00148 bool ai::get_villages(std::map<gamemap::location,paths>& possible_moves,
00149 const move_map& dstsrc, const move_map& enemy_dstsrc,
00150 unit_map::iterator &leader)
00151 {
00152 DBG_AI << "deciding which villages we want...\n";
00153 const int ticks = SDL_GetTicks();
00154 best_leader_loc = gamemap::location::null_location;
00155 if(leader != units_.end()) {
00156 keep_loc = nearest_keep(leader->first);
00157 leader_loc = leader->first;
00158 } else {
00159 keep_loc = gamemap::location::null_location;
00160 leader_loc = gamemap::location::null_location;
00161 }
00162
00163 debug = (!lg::debug.dont_log(lg::ai));
00164
00165
00166 treachmap reachmap;
00167 for(unit_map::const_iterator u_itor = units_.begin();
00168 u_itor != units_.end(); ++u_itor) {
00169
00170 if(u_itor->second.side() == team_num_
00171 && u_itor->second.movement_left()) {
00172
00173 reachmap.insert(std::make_pair(u_itor->first, std::vector<gamemap::location>()));
00174 }
00175 }
00176
00177
00178 tmoves moves;
00179
00180 DBG_AI << reachmap.size() << " units found who can try to capture a village.\n";
00181
00182 find_villages(reachmap, moves, dstsrc, possible_moves, enemy_dstsrc);
00183
00184 treachmap::iterator itor = reachmap.begin();
00185 while(itor != reachmap.end()) {
00186 if(itor->second.size() == 0) {
00187 itor = remove_unit(reachmap, moves, itor);
00188 } else {
00189 ++itor;
00190 }
00191 }
00192
00193 if(reachmap.size()) {
00194 DBG_AI << reachmap.size() << " units left after removing the ones who "
00195 "can't reach a village, send the to the dispatcher.\n";
00196
00197 dump_reachmap(reachmap);
00198
00199 dispatch(reachmap, moves);
00200 } else {
00201 DBG_AI << "No more units left after removing the ones who can't reach a village.\n";
00202 }
00203
00204 LOG_AI << "Village assignment done: " << (SDL_GetTicks() - ticks)
00205 << " ms, resulted in " << moves.size() << " units being dispatched.\n";
00206
00207
00208
00209 std::pair<location,location> leader_move;
00210
00211 int moves_made = 0;
00212 for(tmoves::const_iterator i = moves.begin(); i != moves.end(); ++i) {
00213
00214 if(leader != units_.end() && leader->first == i->second) {
00215 leader_move = *i;
00216 } else {
00217 if(units_.count(i->first) == 0) {
00218 const location loc = move_unit(i->second,i->first,possible_moves);
00219 ++moves_made;
00220 leader = find_leader(units_, team_num_);
00221
00222
00223 if(loc != i->first) {
00224 return true;
00225 }
00226
00227 const unit_map::const_iterator new_unit = units_.find(loc);
00228
00229 if(new_unit != units_.end() &&
00230 power_projection(i->first,enemy_dstsrc) >= new_unit->second.hitpoints()/4) {
00231 add_target(target(new_unit->first,1.0,target::SUPPORT));
00232 }
00233 }
00234 }
00235 }
00236
00237 if(leader_move.second.valid()) {
00238 if(units_.count(leader_move.first) == 0) {
00239 gamemap::location loc = move_unit(leader_move.second,leader_move.first,possible_moves);
00240 ++moves_made;
00241
00242 leader = units_.find(loc);
00243 }
00244 }
00245
00246 return false;
00247 }
00248
00249 void ai::find_villages(
00250 treachmap& reachmap,
00251 tmoves& moves,
00252 const std::multimap<gamemap::location,gamemap::location>& dstsrc,
00253 const std::map<gamemap::location,paths>& possible_moves,
00254 const std::multimap<gamemap::location,gamemap::location>& enemy_dstsrc) const
00255
00256 {
00257 std::map<location, double> vulnerability;
00258
00259 const bool passive_leader =
00260 utils::string_bool(current_team().ai_parameters()["passive_leader"]);
00261
00262 size_t min_distance = 100000;
00263
00264
00265
00266 std::vector<gamemap::location> dispatched_units;
00267 for(std::multimap<gamemap::location, gamemap::location>::const_iterator
00268 j = dstsrc.begin();
00269 j != dstsrc.end(); ++j) {
00270
00271 const gamemap::location& current_loc = j->first;
00272
00273 if(j->second == leader_loc) {
00274 if(passive_leader) {
00275 continue;
00276 }
00277
00278 const size_t distance = distance_between(keep_loc, current_loc);
00279 if(distance < min_distance) {
00280 min_distance = distance;
00281 best_leader_loc = current_loc;
00282 }
00283 }
00284
00285 if(std::find(dispatched_units.begin(), dispatched_units.end(),
00286 j->second) != dispatched_units.end()) {
00287 continue;
00288 }
00289
00290 if(map_.is_village(current_loc) == false) {
00291 continue;
00292 }
00293
00294 bool want_village = true, owned = false;
00295 for(size_t n = 0; n != teams_.size(); ++n) {
00296 owned = teams_[n].owns_village(current_loc);
00297 if(owned && !current_team().is_enemy(n+1)) {
00298 want_village = false;
00299 }
00300
00301 if(owned) {
00302 break;
00303 }
00304 }
00305
00306 if(want_village == false) {
00307 continue;
00308 }
00309
00310
00311
00312 if(!owned && leader_loc == gamemap::location::null_location) {
00313 continue;
00314 }
00315
00316
00317
00318
00319 if(want_village &&
00320 current_team().gold() > 20 &&
00321 leader_loc == current_loc &&
00322 leader_loc != keep_loc &&
00323 multistep_move_possible(j->second, current_loc, keep_loc, possible_moves) == false) {
00324 continue;
00325 }
00326
00327 double threat = 0.0;
00328 const std::map<location,double>::const_iterator vuln = vulnerability.find(current_loc);
00329 if(vuln != vulnerability.end()) {
00330 threat = vuln->second;
00331 } else {
00332 threat = power_projection(current_loc,enemy_dstsrc);
00333 vulnerability.insert(std::pair<location,double>(current_loc,threat));
00334 }
00335
00336 const unit_map::const_iterator u = units_.find(j->second);
00337 if(u == units_.end() || utils::string_bool(u->second.get_state("guardian"))) {
00338 continue;
00339 }
00340
00341 const unit& un = u->second;
00342 if(un.hitpoints() < (threat*2*un.defense_modifier(map_.get_terrain(current_loc)))/100) {
00343 continue;
00344 }
00345
00346
00347
00348 std::multimap<gamemap::location, gamemap::location>::const_iterator next = j;
00349 ++next;
00350 const bool at_begin = (j == dstsrc.begin());
00351 std::multimap<gamemap::location, gamemap::location>::const_iterator prev = j;
00352 if(!at_begin) {
00353 --prev;
00354 }
00355 #if 1
00356 if((next == dstsrc.end() || next->first != current_loc)
00357 && (at_begin || prev->first != current_loc)) {
00358
00359 DBG_AI << "Dispatched unit at " << j->second << " to village " << j->first << '\n';
00360
00361 moves.push_back(std::make_pair(j->first, j->second));
00362 reachmap.erase(j->second);
00363 dispatched_units.push_back(j->second);
00364 continue;
00365 }
00366 #endif
00367 reachmap[j->second].push_back(current_loc);
00368 }
00369
00370 DBG_AI << moves.size() << " units already dispatched, "
00371 << reachmap.size() << " left to evaluate.\n";
00372 }
00373
00374 static void dispatch(treachmap& reachmap, tmoves& moves)
00375 {
00376 DBG_AI << "Starting simple dispatch.\n";
00377
00378
00379
00380
00381
00382
00383
00384
00385 size_t village_count = 0;
00386 bool dispatched = true;
00387 while(dispatched) {
00388 dispatched = false;
00389
00390 if(dispatch_unit_simple(reachmap, moves)) {
00391 dispatched = true;
00392 } else {
00393 if(reachmap.empty()) {
00394 DBG_AI << "dispatch_unit_simple() found a final solution.\n";
00395 break;
00396 } else {
00397 DBG_AI << "dispatch_unit_simple() couldn't dispatch more units.\n";
00398 }
00399 }
00400
00401 if(dispatch_village_simple(reachmap, moves, village_count)) {
00402 dispatched = true;
00403 } else {
00404 if(reachmap.empty()) {
00405 DBG_AI << "dispatch_village_simple() found a final solution.\n";
00406 break;
00407 } else {
00408 DBG_AI << "dispatch_village_simple() couldn't dispatch more units.\n";
00409 }
00410 }
00411
00412 if(reachmap.size() != 0 && dispatched) {
00413 DBG_AI << reachmap.size() << " unit(s) left restarting simple dispatching.\n";
00414
00415 dump_reachmap(reachmap);
00416 }
00417 }
00418
00419 if(reachmap.size() == 0) {
00420 DBG_AI << "No units left after simple dispatcher.\n";
00421 return;
00422 }
00423
00424 DBG_AI << reachmap.size() << " units left for complex dispatch with "
00425 << village_count << " villages left.\n";
00426
00427 dump_reachmap(reachmap);
00428
00429 dispatch_complex(reachmap, moves, village_count);
00430 }
00431
00432
00433
00434 static bool dispatch_unit_simple(treachmap& reachmap, tmoves& moves)
00435 {
00436 bool result = false;
00437
00438 treachmap::iterator itor = reachmap.begin();
00439 while(itor != reachmap.end()) {
00440 if(itor->second.size() == 1) {
00441 const gamemap::location village = itor->second[0];
00442 result = true;
00443
00444 DBG_AI << "Dispatched unit at " << itor->first << " to village " << village << '\n';
00445 moves.push_back(std::make_pair(village, itor->first));
00446 reachmap.erase(itor++);
00447
00448 if(remove_village(reachmap, moves, village)) {
00449 itor = reachmap.begin();
00450 }
00451
00452 } else {
00453 ++itor;
00454 }
00455 }
00456
00457
00458 if(reachmap.empty()) {
00459
00460 return false;
00461 }
00462
00463 if(reachmap.size() == 1) {
00464
00465 DBG_AI << "Dispatched _last_ unit at " << reachmap.begin()->first
00466 << " to village " << reachmap.begin()->second[0] << '\n';
00467
00468 moves.push_back(std::make_pair(
00469 reachmap.begin()->second[0], reachmap.begin()->first));
00470
00471 reachmap.clear();
00472
00473 return false;
00474 }
00475
00476 return result;
00477 }
00478
00479 static bool dispatch_village_simple(
00480 treachmap& reachmap, tmoves& moves, size_t& village_count)
00481 {
00482
00483 bool result = false;
00484 bool dispatched = true;
00485 while(dispatched) {
00486 dispatched = false;
00487
00488
00489 std::map<gamemap::location ,
00490 std::vector<gamemap::location > >reversemap;
00491
00492 treachmap::const_iterator itor = reachmap.begin();
00493 for(;itor != reachmap.end(); ++itor) {
00494
00495 for(std::vector<gamemap::location>::const_iterator
00496 v_itor = itor->second.begin();
00497 v_itor != itor->second.end(); ++v_itor) {
00498
00499 reversemap[*v_itor].push_back(itor->first);
00500
00501 }
00502 }
00503
00504 village_count = reversemap.size();
00505
00506 itor = reversemap.begin();
00507 while(itor != reversemap.end()) {
00508 if(itor->second.size() == 1) {
00509
00510 const gamemap::location village = itor->first;
00511 dispatched = true;
00512 result = true;
00513
00514 DBG_AI << "Dispatched unit at " << itor->second[0] << " to village " << itor->first << '\n';
00515 moves.push_back(std::make_pair(itor->first, itor->second[0]));
00516
00517 reachmap.erase(itor->second[0]);
00518 remove_village(reachmap, moves, village);
00519
00520
00521 break;
00522 } else {
00523 ++itor;
00524 }
00525 }
00526 }
00527
00528 return result;
00529 }
00530
00531 static bool remove_village(
00532 treachmap& reachmap, tmoves& moves, const gamemap::location& village)
00533 {
00534 bool result = false;
00535 treachmap::iterator itor = reachmap.begin();
00536 while(itor != reachmap.end()) {
00537 itor->second.erase(std::remove(itor->second.begin(), itor->second.end(), village), itor->second.end());
00538 if(itor->second.empty()) {
00539 result = true;
00540 itor = remove_unit(reachmap, moves, itor);
00541 } else {
00542 ++itor;
00543 }
00544 }
00545 return result;
00546 }
00547
00548 static treachmap::iterator remove_unit(
00549 treachmap& reachmap, tmoves& moves, treachmap::iterator unit)
00550 {
00551 assert(unit->second.empty());
00552
00553 if(unit->first == leader_loc && best_leader_loc != gamemap::location::null_location) {
00554 DBG_AI << "Dispatch leader at " << leader_loc << " closer to the keep at "
00555 << best_leader_loc << '\n';
00556
00557 moves.push_back(std::make_pair(best_leader_loc, leader_loc));
00558 }
00559
00560 reachmap.erase(unit++);
00561 return unit;
00562 }
00563
00564 static void dispatch_complex(
00565 treachmap& reachmap, tmoves& moves, const size_t village_count)
00566 {
00567
00568
00569 const size_t unit_count = reachmap.size();
00570
00571 const size_t max_result = unit_count < village_count ? unit_count : village_count;
00572
00573 assert(unit_count >= 2 && village_count >= 2);
00574
00575
00576 if(unit_count == 2 && village_count == 2) {
00577 DBG_AI << "Every unit can reach every village for 2 units, dispatch them.\n";
00578 full_dispatch(reachmap, moves);
00579 return;
00580 }
00581
00582 std::vector<gamemap::location> units(unit_count);
00583 std::vector<size_t> villages_per_unit(unit_count);
00584 std::vector<gamemap::location> villages;
00585 std::vector<size_t> units_per_village(village_count);
00586
00587
00588
00589 std::multimap<size_t ,
00590 size_t > unit_lookup;
00591
00592 std::vector<std::vector<bool> >
00593 matrix(reachmap.size(), std::vector<bool>(village_count, false));
00594
00595 treachmap::const_iterator itor = reachmap.begin();
00596 for(size_t u = 0; u < unit_count; ++u, ++itor) {
00597 units[u] = itor->first;
00598 villages_per_unit[u] = itor->second.size();
00599 unit_lookup.insert(std::make_pair(villages_per_unit[u], u));
00600
00601 assert(itor->second.size() >= 2);
00602
00603 for(size_t v = 0; v < itor->second.size(); ++v) {
00604
00605 size_t v_index;
00606
00607 std::vector<gamemap::location>::const_iterator v_itor =
00608 std::find(villages.begin(), villages.end(), itor->second[v]);
00609 if(v_itor == villages.end()) {
00610 v_index = villages.size();
00611 villages.push_back(itor->second[v]);
00612 } else {
00613 v_index = v_itor - villages.begin();
00614 }
00615
00616 units_per_village[v_index]++;
00617
00618 matrix[u][v_index] = true;
00619 }
00620 }
00621 for(std::vector<size_t>::const_iterator upv_it = units_per_village.begin();
00622 upv_it != units_per_village.end(); ++upv_it) {
00623
00624 assert(*upv_it >=2);
00625 }
00626
00627 if(debug) {
00628
00629 std::cerr << "Reach matrix:\n\nvillage";
00630 size_t u, v;
00631 for(v = 0; v < village_count; ++v) {
00632 std::cerr << '\t' << villages[v];
00633 }
00634 std::cerr << "\ttotal\nunit\n";
00635
00636
00637 for(u = 0; u < unit_count; ++u) {
00638 std::cerr << units[u];
00639
00640 for(size_t v = 0; v < village_count; ++v) {
00641 std::cerr << '\t' << matrix[u][v];
00642 }
00643 std::cerr << "\t" << villages_per_unit[u] << '\n';
00644 }
00645
00646
00647 std::cerr << "total";
00648 for(v = 0; v < village_count; ++v) {
00649 std::cerr << '\t' << units_per_village[v];
00650 }
00651 std::cerr << '\n';
00652 }
00653
00654
00655 const bool reach_all = ((village_count == unit_count)
00656 && (std::accumulate(villages_per_unit.begin(), villages_per_unit.end(), size_t())
00657 == (village_count * unit_count)));
00658
00659 if(reach_all) {
00660 DBG_AI << "Every unit can reach every village, dispatch them\n";
00661 full_dispatch(reachmap, moves);
00662 reachmap.clear();
00663 return;
00664 }
00665
00666
00667 std::multimap<size_t , size_t >
00668 ::const_iterator src_itor = unit_lookup.begin();
00669
00670 while(src_itor != unit_lookup.end() && src_itor->first == 2) {
00671
00672 for(std::multimap<size_t, size_t>::const_iterator
00673 dst_itor = unit_lookup.begin();
00674 dst_itor != unit_lookup.end(); ++ dst_itor) {
00675
00676
00677 if(src_itor == dst_itor) {
00678 continue;
00679 }
00680
00681 std::vector<bool> result;
00682 std::transform(matrix[src_itor->second].begin(), matrix[src_itor->second].end(),
00683 matrix[dst_itor->second].begin(),
00684 std::back_inserter(result),
00685 std::logical_and<bool>()
00686 );
00687
00688 size_t matched = std::count(result.begin(), result.end(), true);
00689
00690
00691 if(matched == 2) {
00692
00693 std::vector<bool>::iterator first = std::find(result.begin(), result.end(), true);
00694 std::vector<bool>::iterator second = std::find(first + 1, result.end(), true);
00695
00696 const gamemap::location village1 = villages[first - result.begin()];
00697 const gamemap::location village2 = villages[second - result.begin()];
00698
00699 const bool perfect = (src_itor->first == 2 &&
00700 dst_itor->first == 2 &&
00701 units_per_village[first - result.begin()] == 2 &&
00702 units_per_village[second - result.begin()] == 2);
00703
00704
00705 DBG_AI << "Found a square.\nDispatched unit at " << units[src_itor->second]
00706 << " to village " << village1 << '\n';
00707 moves.push_back(std::make_pair(village1, units[src_itor->second]));
00708
00709 DBG_AI << "Dispatched unit at " << units[dst_itor->second]
00710 << " to village " << village2 << '\n';
00711 moves.push_back(std::make_pair(village2, units[dst_itor->second]));
00712
00713
00714 reachmap.erase(units[src_itor->second]);
00715 reachmap.erase(units[dst_itor->second]);
00716
00717
00718 if(perfect) {
00719
00720
00721
00722 DBG_AI << "Perfect dispatch, do complex again.\n";
00723 dispatch_complex(reachmap, moves, village_count - 2);
00724 return;
00725 } else {
00726
00727
00728 DBG_AI << "NON Perfect dispatch, do dispatch again.\n";
00729 remove_village(reachmap, moves, village1);
00730 remove_village(reachmap, moves, village2);
00731 dispatch(reachmap, moves);
00732 return;
00733 }
00734 }
00735 }
00736
00737 ++src_itor;
00738 }
00739
00740
00741
00742
00743
00744
00745
00746
00747 std::vector<std::pair<gamemap::location, gamemap::location> > best_result;
00748
00749
00750
00751
00752
00753
00754
00755 const size_t max_options = 8;
00756 if(unit_count >= max_options && village_count >= max_options) {
00757
00758 DBG_AI << "Too many units " << unit_count << " and villages "
00759 << village_count<<" found, evaluate only the first "
00760 << max_options << " options;\n";
00761
00762 std::vector<size_t> perm (max_options, 0);
00763 for(size_t i =0; i < max_options; ++i) {
00764 perm[i] = i;
00765 }
00766 while(std::next_permutation(perm.begin(), perm.end())) {
00767
00768
00769 std::vector<std::pair<gamemap::location,gamemap::location> > result;
00770 for(size_t u = 0; u < max_options; ++u) {
00771 if(matrix[u][perm[u]]) {
00772 result.push_back(std::make_pair(villages[perm[u]], units[u]));
00773
00774 }
00775 }
00776 if(result.size() == max_result) {
00777 best_result.swap(result);
00778 break;
00779 }
00780
00781 if(result.size() > best_result.size()) {
00782 best_result.swap(result);
00783 }
00784 }
00785
00786 std::copy(best_result.begin(), best_result.end(), std::back_inserter(moves));
00787
00788
00789 for(std::vector<std::pair<gamemap::location, gamemap::location> >::const_iterator
00790 itor = best_result.begin(); itor != best_result.end(); ++itor) {
00791 reachmap.erase(itor->second);
00792 }
00793
00794
00795 dispatch(reachmap, moves);
00796 return;
00797
00798 } else if(unit_count <= village_count) {
00799
00800 DBG_AI << "Unit major\n";
00801
00802 std::vector<size_t> perm (unit_count, 0);
00803 for(size_t i =0; i < unit_count; ++i) {
00804 perm[i] = i;
00805 }
00806 while(std::next_permutation(perm.begin(), perm.end())) {
00807
00808 std::vector<std::pair<gamemap::location,gamemap::location> > result;
00809 for(size_t u = 0; u < unit_count; ++u) {
00810 if(matrix[u][perm[u]]) {
00811 result.push_back(std::make_pair(villages[perm[u]], units[u]));
00812
00813 }
00814 }
00815 if(result.size() == max_result) {
00816 std::copy(result.begin(), result.end(), std::back_inserter(moves));
00817 reachmap.clear();
00818 return;
00819 }
00820
00821 if(result.size() > best_result.size()) {
00822 best_result.swap(result);
00823 }
00824 }
00825
00826 std::copy(best_result.begin(), best_result.end(), std::back_inserter(moves));
00827
00828
00829
00830 for(std::vector<std::pair<gamemap::location, gamemap::location> >::const_iterator
00831 itor = best_result.begin(); itor != best_result.end(); ++itor) {
00832 reachmap.erase(itor->second);
00833 }
00834 treachmap::iterator unit = reachmap.find(leader_loc);
00835 if(unit != reachmap.end()) {
00836 unit->second.clear();
00837 remove_unit(reachmap, moves, unit);
00838 }
00839 reachmap.clear();
00840
00841 } else {
00842
00843 DBG_AI << "Village major\n";
00844
00845 std::vector<size_t> perm (village_count, 0);
00846 for(size_t i =0; i < village_count; ++i) {
00847 perm[i] = i;
00848 }
00849 while(std::next_permutation(perm.begin(), perm.end())) {
00850
00851 std::vector<std::pair<gamemap::location,gamemap::location> > result;
00852 for(size_t v = 0; v < village_count; ++v) {
00853 if(matrix[perm[v]][v]) {
00854 result.push_back(std::make_pair(villages[v], units[perm[v]]));
00855
00856 }
00857 }
00858 if(result.size() == max_result) {
00859 std::copy(result.begin(), result.end(), std::back_inserter(moves));
00860 reachmap.clear();
00861 return;
00862 }
00863
00864 if(result.size() > best_result.size()) {
00865 best_result.swap(result);
00866 }
00867 }
00868
00869 std::copy(best_result.begin(), best_result.end(), std::back_inserter(moves));
00870
00871
00872
00873 for(std::vector<std::pair<gamemap::location, gamemap::location> >::const_iterator
00874 itor = best_result.begin(); itor != best_result.end(); ++itor) {
00875 reachmap.erase(itor->second);
00876 }
00877 treachmap::iterator unit = reachmap.find(leader_loc);
00878 if(unit != reachmap.end()) {
00879 unit->second.clear();
00880 remove_unit(reachmap, moves, unit);
00881 }
00882 reachmap.clear();
00883 }
00884 }
00885
00886 static void full_dispatch(treachmap& reachmap, tmoves& moves)
00887 {
00888 treachmap::const_iterator itor = reachmap.begin();
00889 for(size_t i = 0; i < reachmap.size(); ++i, ++itor) {
00890 DBG_AI << "Dispatched unit at " << itor->first
00891 << " to village " << itor->second[i] << '\n';
00892 moves.push_back(std::make_pair(itor->second[i], itor->first));
00893 }
00894 }
00895
00896 static void dump_reachmap(treachmap& reachmap)
00897 {
00898 if(!debug) {
00899 return;
00900 }
00901
00902 for(treachmap::const_iterator itor =
00903 reachmap.begin(); itor != reachmap.end(); ++itor) {
00904
00905 std::cerr << "Reachlist for unit at " << itor->first;
00906
00907 if(itor->second.empty()) {
00908 std::cerr << "\tNone";
00909 }
00910
00911 for(std::vector<gamemap::location>::const_iterator
00912 v_itor = itor->second.begin();
00913 v_itor != itor->second.end(); ++v_itor) {
00914
00915 std::cerr << '\t' << *v_itor;
00916 }
00917 std::cerr << '\n';
00918
00919 }
00920 }
00921
00922 #if 0
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966 int main()
00967 {
00968 const size_t max_matrix = 100;
00969 std::vector<std::vector<bool> > matrix(max_matrix, std::vector<bool>(max_matrix, false));
00970 std::vector<gamemap::location> villages(max_matrix);
00971 std::vector<gamemap::location> units(max_matrix);
00972
00973 srand(10);
00974 for(size_t i = 0; i < max_matrix; ++i) {
00975 for(size_t j = 0; j < max_matrix; ++j) {
00976 matrix[i][j] = ((rand() % 3) == 0);
00977 villages[i] = gamemap::location(rand() % 100, rand() % 100);
00978 units[i] = gamemap::location(rand() % 100, rand() % 100);
00979 }
00980 }
00981
00982
00983 std::vector<std::pair<gamemap::location,gamemap::location> > best_result;
00984 for(size_t option = 1; option < max_matrix; ++option) {
00985
00986 std::vector<size_t> perm (option, 0);
00987 for(size_t i = 0; i < option; ++i) {
00988 perm[i] = i;
00989 }
00990
00991 const int start = SDL_GetTicks();
00992 while(std::next_permutation(perm.begin(), perm.end())) {
00993
00994
00995 std::vector<std::pair<gamemap::location,gamemap::location> > result;
00996 for(size_t u = 0; u < option; ++u) {
00997 if(matrix[u][perm[u]]) {
00998 result.push_back(std::make_pair(villages[perm[u]], units[u]));
00999
01000 }
01001 }
01002 if(result.size() == option) {
01003 best_result.swap(result);
01004 break;
01005 }
01006
01007 if(result.size() > best_result.size()) {
01008 best_result.swap(result);
01009 }
01010 }
01011
01012
01013 std::cerr << "Option count : " << option << " duration " << (SDL_GetTicks() - start) << " ms\n";
01014
01015 }
01016 }
01017
01018 #endif
01019