Merge lp:~mxsscott/widelands/carli2-ai-improvements into lp:widelands

Proposed by Mark Scott
Status: Rejected
Rejected by: SirVer
Proposed branch: lp:~mxsscott/widelands/carli2-ai-improvements
Merge into: lp:widelands
Diff against target: 752 lines (+358/-242)
5 files modified
src/ai/ai_help_structs.h (+1/-0)
src/ai/defaultai.cc (+351/-242)
src/ai/defaultai.h (+4/-0)
src/logic/militarysite.h (+1/-0)
tribes/barbarians/fernery/conf (+1/-0)
To merge this branch: bzr merge lp:~mxsscott/widelands/carli2-ai-improvements
Reviewer Review Type Date Requested Status
SirVer Needs Fixing
Review via email: mp+142009@code.launchpad.net

Description of the change

(Branch author is carli2: https://code.launchpad.net/~s3734770 - having bzr problems)

 - Add "demand" to wares
 - missing input wares count as demand
 - missing soldiers add demand to weapons
 - a depth pass filter is applied to demand in order to get stable values
 - enhancements are now priorized correctly

gains:
 - all three tribes manage to recruit soldiers
 - the AI is able to finish its enemy after 90 minutes
 - great improvement for AIs economy

To post a comment you must log in.
Revision history for this message
SirVer (sirver) wrote :

see http://wl.widelands.org/forum/topic/648/?page=3#post-8562. More comments and review welcome.

review: Needs Fixing
Revision history for this message
SirVer (sirver) wrote :

Setting to rejected because there was no followup - feel free to reopen or discuss more.

Unmerged revisions

6478. By carli <https://launchpad.net/~s3734770>

AI improvements

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h 2012-09-21 21:36:07 +0000
+++ src/ai/ai_help_structs.h 2013-01-05 13:44:24 +0000
@@ -274,6 +274,7 @@
274 uint8_t producers;274 uint8_t producers;
275 uint8_t consumers;275 uint8_t consumers;
276 uint8_t preciousness;276 uint8_t preciousness;
277 float demand;
277};278};
278279
279#endif280#endif
280281
=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc 2012-09-21 21:36:07 +0000
+++ src/ai/defaultai.cc 2013-01-05 13:44:24 +0000
@@ -30,6 +30,7 @@
30#include "economy/economy.h"30#include "economy/economy.h"
31#include "economy/flag.h"31#include "economy/flag.h"
32#include "economy/road.h"32#include "economy/road.h"
33#include "economy/wares_queue.h"
33#include "logic/findimmovable.h"34#include "logic/findimmovable.h"
34#include "logic/findnode.h"35#include "logic/findnode.h"
35#include "log.h"36#include "log.h"
@@ -75,7 +76,8 @@
75 next_attack_consideration_due(300000),76 next_attack_consideration_due(300000),
76 inhibit_road_building (0),77 inhibit_road_building (0),
77 time_of_last_construction (0),78 time_of_last_construction (0),
78 numof_warehouses (0)79 numof_warehouses (0),
80 military_demand (0.0)
79{}81{}
8082
81DefaultAI::~DefaultAI()83DefaultAI::~DefaultAI()
@@ -136,6 +138,9 @@
136 // handled by the AI itself.138 // handled by the AI itself.
137 update_all_not_buildable_fields();139 update_all_not_buildable_fields();
138140
141 // now update the statistics of what we need (wares and military power)
142 update_demand();
143
139 // IF defaultAI is AGGRESSIVE - we definitely should consider to attack as144 // IF defaultAI is AGGRESSIVE - we definitely should consider to attack as
140 // often as possible.145 // often as possible.
141 if (type == AGGRESSIVE)146 if (type == AGGRESSIVE)
@@ -234,6 +239,7 @@
234 wares.at(i).producers = 0;239 wares.at(i).producers = 0;
235 wares.at(i).consumers = 0;240 wares.at(i).consumers = 0;
236 wares.at(i).preciousness = tribe->get_ware_descr(i)->preciousness();241 wares.at(i).preciousness = tribe->get_ware_descr(i)->preciousness();
242 wares.at(i).demand = 0;
237 }243 }
238244
239 // collect information about the different buildings our tribe can construct245 // collect information about the different buildings our tribe can construct
@@ -472,6 +478,85 @@
472 }478 }
473}479}
474480
481/***
482 * updates all needs of the economy
483 */
484void DefaultAI::update_demand()
485{
486 // military buildings need soldiers: count them!
487 for
488 (std::list<MilitarySiteObserver>::iterator i =
489 militarysites.begin();
490 i != militarysites.end();
491 ++i)
492 {
493 military_demand += i->site->missingSoldiers();
494 }
495 military_demand += 1; // some extra points such that we always get new soldiers
496 military_demand *= 0.99;
497 military_demand = std::max(military_demand, (type + 2) * (float) 2000.0); // then limit it to some degree.
498 // enable logging for debug purpose
499 //printf("mil = %f\n", military_demand);
500
501 // now we know how much military we need, so we
502 // need the wares to build the soldiers
503 Ware_Index const nr_workers = tribe->get_nrworkers();
504 for (Ware_Index i = Ware_Index::First(); i < nr_workers; ++i) {
505 // Find all build costs for soldiers
506 // is it a soldier?
507 if(tribe->get_worker_descr(i)->get_worker_type() == Worker_Descr::SOLDIER) {
508 Worker_Descr::Buildcost::const_iterator end = tribe->get_worker_descr(i)->buildcost().end();
509 for(Worker_Descr::Buildcost::const_iterator it = tribe->get_worker_descr(i)->buildcost().begin(); it != end; ++it) {
510 if(tribe->ware_index(it->first))
511 wares.at(tribe->ware_index(it->first)).demand += it->second * military_demand / 100.0; // Add soldier-need priority
512 }
513 }
514 }
515
516
517 // production buildings need inputs
518 std::list<ProductionSiteObserver>::const_iterator i =
519 productionsites.begin();
520 while(1)
521 {
522 // iterate through both: production buildings and mines
523 if(i == productionsites.end())
524 i = mines.begin();
525 if(i == mines.end())
526 break;
527 // count all empty slots
528 for
529 (ProductionSite::Input_Queues::const_iterator j =
530 i->site->warequeues().begin();
531 j != i->site->warequeues().end();
532 j++)
533 {
534 if((*j)->get_filled() == 0)
535 // count queues that are empty
536 wares.at((*j)->get_ware()).demand += 1;
537 }
538 i++;
539 }
540
541 /* TODO: Iterate over all construction sites and add material need
542 // Remark: construction materials are also handled by other code, but this
543 // code could do it more scalable for big empires
544
545 Buildcost::const_iterator end = bld.buildcost().end();
546 for(Buildcost::const_iterator it = bld.buildcost().begin(); it != end; ++it) {
547 wares.at(it->first).demand += it->second; // Add build-need priority
548 }*/
549
550 // now decrease the total ammount a bit
551 Ware_Index nr_wares = tribe->get_nrwares();
552 for (Ware_Index i = Ware_Index::First(); i < nr_wares; ++i)
553 {
554 wares.at(i).demand *= 0.99;
555 // enable logging for debug purpose
556 //printf("ware %s: %f\n", tribe->get_ware_descr(i)->name().c_str(), wares.at(i).demand);
557 }
558}
559
475560
476/// Updates one buildable field561/// Updates one buildable field
477void DefaultAI::update_buildable_field562void DefaultAI::update_buildable_field
@@ -860,245 +945,7 @@
860 if (bo.desc->get_size() > maxsize)945 if (bo.desc->get_size() > maxsize)
861 continue;946 continue;
862947
863 int32_t prio = 0;948 int32_t prio = calculate_building_prio(bo, bf, expand_factor);
864
865 if (bo.type == BuildingObserver::PRODUCTIONSITE) {
866 // Don't build another building of this type, if there is already
867 // one that is unoccupied at the moment
868 if (bo.unoccupied)
869 continue;
870 if (bo.need_trees) {
871 // Priority of woodcutters depend on the number of near trees
872 prio += bf->trees_nearby * 3;
873 prio /= 3 * (1 + bf->producers_nearby.at(bo.outputs.at(0)));
874
875 // TODO improve this - it's still useless to place lumberjack huts randomly
876 /*if (prio <= 0) // no, sometimes we need wood without having a forest
877 continue;*/
878
879 // Check if the produced wares are needed
880 Ware_Index wt(static_cast<size_t>(bo.outputs.at(0)));
881 container_iterate(std::list<EconomyObserver *>, economies, l) {
882 // Don't check if the economy has no warehouse.
883 if ((*l.current)->economy.warehouses().empty())
884 continue;
885 if ((*l.current)->economy.needs_ware(wt))
886 prio += 1 + wares.at(bo.outputs.at(0)).preciousness;
887 }
888
889 if (bo.total_count() < 2) {
890 prio *= 6; // big bonus for the basics
891 if (bo.total_count() == 0)
892 prio *= 4; // even more for the absolute basics
893 }
894 } else if (bo.need_stones) {
895 // Priority of quarries depend on the number of near stones
896 prio += bf->stones_nearby * 3;
897 prio /= 3 * (1 + bf->producers_nearby.at(bo.outputs.at(0)));
898 if (bo.total_count() < 2) {
899 prio *= 6; // big bonus for the basics
900 if (bo.total_count() == 0)
901 prio *= 4; // even more for the absolute basics
902 }
903 } else if (bo.production_hint >= 0) {
904 // production hint (f.e. associate forester with trunks)
905
906 // Calculate the need for this building
907 int16_t inout = wares.at(bo.production_hint).consumers;
908 if
909 (tribe->safe_ware_index("trunk").value()
910 ==
911 bo.production_hint)
912 inout += total_constructionsites / 4;
913 inout -= wares.at(bo.production_hint).producers;
914 if (inout < 1)
915 inout = 1;
916 // the ware they're refreshing
917 Ware_Index wt(static_cast<size_t>(bo.production_hint));
918 container_iterate(std::list<EconomyObserver *>, economies, l) {
919 // Don't check if the economy has no warehouse.
920 if ((*l.current)->economy.warehouses().empty())
921 continue;
922 if ((*l.current)->economy.needs_ware(wt)) {
923 prio += wares.at(bo.production_hint).preciousness * inout * 2;
924 break;
925 }
926 }
927
928 // Do not build too many of these buildings, but still care
929 // to build at least two.
930 // And add bonus near buildings outputting production_hint ware.
931 prio += (5 * bf->producers_nearby.at(bo.production_hint)) / 2;
932 prio -= bo.total_count() * 2;
933 prio /= bo.total_count() + 1;
934 prio += (bf->producers_nearby.at(bo.production_hint) - 1) * 5;
935 if (bo.total_count() > 2)
936 prio -= bo.total_count();
937 else {
938 prio += wares.at(bo.production_hint).preciousness;
939 prio *= 3;
940 }
941 if (prio < 0)
942 continue;
943 } else if (bo.recruitment) {
944 // "recruitment centeres" like the donkey farm should be build up
945 // as soon as a basic infrastructure was completed.
946 // and of course the defaultAI should think of further
947 // constructions of that type later in game.
948 prio -= 12; // start calculation with an offset
949 prio += productionsites.size() + mines.size();
950 prio -= (bo.total_count()) * 40;
951 prio *= 2;
952
953 // take care about borders and enemies
954 prio = recalc_with_border_range(*bf, prio);
955 } else { // "normal" productionsites
956
957 // ToDo: prefer soldier producing things
958 // Ware_Index const soldier_index = tribe().worker_index("soldier");
959
960 if (bo.is_basic && (bo.total_count() == 0))
961 prio += 100; // for very important buildings
962
963 // Check if the produced wares are needed
964 container_iterate(std::list<EconomyObserver *>, economies, l) {
965 // Don't check if the economy has no warehouse.
966 if ((*l.current)->economy.warehouses().empty())
967 continue;
968 for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
969 Ware_Index wt(static_cast<size_t>(bo.outputs.at(m)));
970
971 // if we have too much of it (avoids mass storage)
972 if
973 ((*l.current)->economy.stock_ware(wt) > 6 *
974 (*l.current)->economy.ware_target_quantity(wt).permanent)
975 prio -= 20;
976
977 // if the economy needs this ware
978 if ((*l.current)->economy.needs_ware(wt)) {
979 prio += 1 + wares.at(bo.outputs.at(m)).preciousness;
980 if (bo.total_count() == 0)
981 // big bonus, this site might be elemental
982 prio += 3 * wares.at(bo.outputs.at(m)).preciousness;
983 }
984
985 // we can enhance this building. build more
986 // maybe the enhancement can produce needed ware
987 if (bo.desc->enhancements().size() > 0) {
988 // this code builds more metalworks
989 if (bo.total_count() == 0)
990 prio += 2;
991 if (bo.total_count() == 1)
992 prio += 8;
993 }
994 }
995 for (uint32_t m = 0; m < bo.inputs.size(); ++m) {
996 Ware_Index wt(static_cast<size_t>(bo.inputs.at(m)));
997
998 // if the economies don't need it: "waste" it
999 if (!(*l.current)->economy.needs_ware(wt)) {
1000 if (bo.total_count() == 0 && bo.prod_build_material)
1001 // big bonus, this site might be elemental
1002 prio += 3 * wares.at(bo.inputs.at(m)).preciousness;
1003 }
1004 }
1005 }
1006
1007 // If the produced wares are needed
1008 if (prio > 0) {
1009 int32_t inout_prio = 0;
1010 for (size_t k = 0; k < bo.inputs.size(); ++k) {
1011 inout_prio += bf->producers_nearby.at(bo.inputs.at(k));
1012 inout_prio -= bf->consumers_nearby.at(bo.inputs.at(k)) / 2;
1013 }
1014 for (size_t k = 0; k < bo.outputs.size(); ++k)
1015 inout_prio += bf->consumers_nearby.at(bo.outputs.at(k));
1016 prio += 2 * inout_prio;
1017 prio = calculate_need_for_ps(bo, prio);
1018 } else
1019 continue;
1020
1021 // take care about borders and enemies
1022 prio = recalc_with_border_range(*bf, prio);
1023
1024 // do not construct more than one building,
1025 // if supply line is already broken.
1026 if (!check_supply(bo) && bo.total_count() > 0)
1027 prio -= 12;
1028
1029 }
1030 } else if (bo.type == BuildingObserver::MILITARYSITE) {
1031 if (!bf->unowned_land_nearby)
1032 continue;
1033 prio = bf->unowned_land_nearby * (1 + type);
1034 prio -= bf->military_influence * (5 - type);
1035 // set to at least 1
1036 prio = prio > 0 ? prio : 1;
1037 prio *= expand_factor;
1038 prio /= 2;
1039
1040 if (bf->enemy_nearby)
1041 prio *= 2;
1042 else
1043 prio -= bf->military_influence * 2;
1044
1045 if (bf->avoid_military)
1046 prio /= 5;
1047
1048 prio -= militarysites.size() - productionsites.size() / (3 - type);
1049
1050 } else if (bo.type == BuildingObserver::WAREHOUSE) {
1051 // Build one warehouse for ~every 35 productionsites and mines.
1052 // Militarysites are slightly important as well, to have a bigger
1053 // chance for a warehouses (containing waiting soldiers or wares
1054 // needed for soldier training) near the frontier.
1055 prio += productionsites.size() + mines.size();
1056 prio += militarysites.size() / 3;
1057 prio -= (bo.cnt_under_construction + numof_warehouses) * 35;
1058 prio *= 2;
1059
1060 // take care about borders and enemies
1061 prio = recalc_with_border_range(*bf, prio);
1062
1063 } else if (bo.type == BuildingObserver::TRAININGSITE) {
1064 // Start building trainingsites when there are already more than 50
1065 // other buildings. That should be enough for a working economy.
1066 // On the other hand only build more trainingsites of the same
1067 // type if the economy is really big.
1068 prio += productionsites.size() + militarysites.size();
1069 prio += mines.size();
1070 prio += type * 10; // +0 / +10 / +20 for DEFF/NORM/AGGR
1071 prio = prio / (bo.total_count() + 1);
1072 prio -= (bo.total_count() + 1) * 70;
1073
1074 // take care about borders and enemies
1075 prio = recalc_with_border_range(*bf, prio);
1076 }
1077
1078 // avoid to have too many construction sites
1079 // but still enable the player to build up basic productionsites
1080 if
1081 (bo.type != BuildingObserver::PRODUCTIONSITE ||
1082 !bo.is_basic || bo.total_count() > 0)
1083 prio /=
1084 1 + bo.cnt_under_construction * (bo.cnt_under_construction + 1);
1085
1086 // add big penalty if water is needed, but is not near
1087 if (bo.need_water) {
1088 if (bf->water_nearby < 3)
1089 continue;
1090 int effect = bf->water_nearby - 8;
1091 prio +=
1092 effect > 0 ?
1093 static_cast<int>(sqrt(static_cast<double>(effect))) : effect;
1094 // if same producers are nearby, then give some penalty
1095 for (size_t k = 0; k < bo.outputs.size(); ++k)
1096 if (bf->producers_nearby.at(bo.outputs.at(k)) > 0)
1097 prio -= 3;
1098 }
1099
1100 // think of space consuming buildings nearby like farms or vineyards
1101 prio /= 1 + bf->space_consumers_nearby;
1102949
1103 // Stop here, if priority is 0 or less.950 // Stop here, if priority is 0 or less.
1104 if (prio <= 0)951 if (prio <= 0)
@@ -1199,6 +1046,7 @@
1199 uint32_t ioprio = 0;1046 uint32_t ioprio = 0;
1200 for (uint32_t m = 0; m < bo.outputs.size(); ++m) {1047 for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
1201 ioprio += 5 * wares.at(bo.outputs.at(m)).preciousness;1048 ioprio += 5 * wares.at(bo.outputs.at(m)).preciousness;
1049 ioprio += round(wares.at(bo.outputs.at(m)).demand / 100.0);
1202 }1050 }
12031051
1204 // tribes that have enhanceable mines should build more mines1052 // tribes that have enhanceable mines should build more mines
@@ -1214,7 +1062,7 @@
1214 // multiply with current statistics of all other buildings of this1062 // multiply with current statistics of all other buildings of this
1215 // type to avoid constructing buildings where already some are running1063 // type to avoid constructing buildings where already some are running
1216 // on low resources.1064 // on low resources.
1217 prio *= 5 + bo.current_stats;1065 prio *= 45 + bo.current_stats;
1218 prio /= 100;1066 prio /= 100;
12191067
1220 if (onlymissing) // mines aren't *that* important1068 if (onlymissing) // mines aren't *that* important
@@ -1252,6 +1100,262 @@
1252 return true;1100 return true;
1253}1101}
12541102
1103int32_t DefaultAI::calculate_building_prio(BuildingObserver & bo, BuildableField * const bf, uint32_t expand_factor)
1104{
1105 int32_t prio = 0;
1106
1107 if (bo.type == BuildingObserver::PRODUCTIONSITE) {
1108 // Don't build another building of this type, if there is already
1109 // one that is unoccupied at the moment
1110 if (bo.unoccupied)
1111 return -1;
1112 if (bo.need_trees) {
1113 // Priority of woodcutters depend on the number of near trees
1114 prio += bf->trees_nearby * 3;
1115 prio /= 3 * (1 + bf->producers_nearby.at(bo.outputs.at(0)));
1116
1117 // TODO improve this - it's still useless to place lumberjack huts randomly
1118 /*if (prio <= 0) // no, sometimes we need wood without having a forest
1119 return -1;*/
1120
1121 // Check if the produced wares are needed
1122 Ware_Index wt(static_cast<size_t>(bo.outputs.at(0)));
1123 container_iterate(std::list<EconomyObserver *>, economies, l) {
1124 // Don't check if the economy has no warehouse.
1125 if ((*l.current)->economy.warehouses().empty())
1126 continue;
1127 if ((*l.current)->economy.needs_ware(wt))
1128 prio += 1 + wares.at(bo.outputs.at(0)).preciousness;
1129 }
1130
1131 if (bo.total_count() < 2) {
1132 prio *= 6; // big bonus for the basics
1133 if (bo.total_count() == 0)
1134 prio *= 4; // even more for the absolute basics
1135 }
1136 } else if (bo.need_stones) {
1137 // Priority of quarries depend on the number of near stones
1138 prio += bf->stones_nearby * 3;
1139 prio /= 3 * (1 + bf->producers_nearby.at(bo.outputs.at(0)));
1140 if (bo.total_count() < 2) {
1141 prio *= 6; // big bonus for the basics
1142 if (bo.total_count() == 0)
1143 prio *= 4; // even more for the absolute basics
1144 }
1145 } else if (bo.production_hint >= 0) {
1146 // production hint (f.e. associate forester with trunks)
1147
1148 // Calculate the need for this building
1149 int16_t inout = wares.at(bo.production_hint).consumers;
1150 if
1151 (tribe->safe_ware_index("trunk").value()
1152 ==
1153 bo.production_hint)
1154 inout += total_constructionsites / 4;
1155 inout -= wares.at(bo.production_hint).producers;
1156 if (inout < 1)
1157 inout = 1;
1158 // the ware they're refreshing
1159 Ware_Index wt(static_cast<size_t>(bo.production_hint));
1160 container_iterate(std::list<EconomyObserver *>, economies, l) {
1161 // Don't check if the economy has no warehouse.
1162 if ((*l.current)->economy.warehouses().empty())
1163 continue;
1164 if ((*l.current)->economy.needs_ware(wt)) {
1165 prio += wares.at(bo.production_hint).preciousness * inout * 2;
1166 break;
1167 }
1168 }
1169
1170 // Do not build too many of these buildings, but still care
1171 // to build at least two.
1172 // And add bonus near buildings outputting production_hint ware.
1173 prio += (5 * bf->producers_nearby.at(bo.production_hint)) / 2;
1174 prio -= bo.total_count() * 2;
1175 prio /= bo.total_count() + 1;
1176 prio += (bf->producers_nearby.at(bo.production_hint) - 1) * 5;
1177 if (bo.total_count() > 2)
1178 prio -= bo.total_count();
1179 else {
1180 prio += wares.at(bo.production_hint).preciousness;
1181 prio *= 3;
1182 }
1183 if (prio < 0)
1184 return -1;
1185 } else if (bo.recruitment) {
1186 // "recruitment centeres" like the donkey farm should be build up
1187 // as soon as a basic infrastructure was completed.
1188 // and of course the defaultAI should think of further
1189 // constructions of that type later in game.
1190 prio -= 12; // start calculation with an offset
1191 prio += productionsites.size() + mines.size();
1192 prio -= (bo.total_count()) * 40;
1193 prio *= 2;
1194
1195 // take care about borders and enemies
1196 prio = recalc_with_border_range(*bf, prio);
1197 } else { // "normal" productionsites
1198
1199 if (bo.is_basic && (bo.total_count() == 0))
1200 prio += 100; // for very important buildings
1201
1202 // we can enhance this building. build more
1203 // maybe the enhancement can produce needed ware
1204 // TODO: rather plan an enhanced building from bottom up
1205 for (std::set<Building_Index>::const_iterator enhancement =
1206 bo.desc->enhancements().begin();
1207 enhancement != bo.desc->enhancements().end();
1208 enhancement++) {
1209 // when we build a, we can build b, too...
1210 BuildingObserver & bo2 = buildings[*enhancement];
1211 // so simply add the score of the building behind it...
1212 uint32_t prio2 = calculate_building_prio(bo2, bf, expand_factor);
1213 if (prio2 * (1 + bo.total_count()) > prio * (1 + bo2.total_count()))
1214 prio = prio / 2 + prio2; // we want to build the enhanced building instead of this
1215 }
1216
1217
1218 // Check if the produced wares are needed
1219 container_iterate(std::list<EconomyObserver *>, economies, l) {
1220 // Don't check if the economy has no warehouse.
1221 if ((*l.current)->economy.warehouses().empty())
1222 continue;
1223 for (uint32_t m = 0; m < bo.outputs.size(); ++m) {
1224 Ware_Index wt(static_cast<size_t>(bo.outputs.at(m)));
1225
1226 // Our main instinct: what we actually need
1227 // for military, production and construction
1228 prio += round(wares.at(bo.outputs.at(m)).demand / 50.0);
1229
1230 // if we have too much of it (avoids mass storage)
1231 if
1232 ((*l.current)->economy.stock_ware(wt) > 6 *
1233 (*l.current)->economy.ware_target_quantity(wt).permanent)
1234 prio -= 20;
1235
1236 // if the economy needs this ware
1237 if ((*l.current)->economy.needs_ware(wt)) {
1238 prio += 1 + wares.at(bo.outputs.at(m)).preciousness;
1239 if (bo.total_count() == 0)
1240 // big bonus, this site might be elemental
1241 prio += 3 * wares.at(bo.outputs.at(m)).preciousness;
1242 }
1243 }
1244 for (uint32_t m = 0; m < bo.inputs.size(); ++m) {
1245 Ware_Index wt(static_cast<size_t>(bo.inputs.at(m)));
1246
1247 // Wares that are needed should not be consumed too much
1248 prio -= round(wares.at(wt).demand / 100.0);
1249
1250 // if the economies don't need it: "waste" it
1251 if (!(*l.current)->economy.needs_ware(wt)) {
1252 prio++;
1253 if (bo.total_count() == 0 && bo.prod_build_material)
1254 // big bonus, this site might be elemental
1255 prio += 3 * wares.at(bo.inputs.at(m)).preciousness;
1256 }
1257 }
1258 }
1259
1260 // If the produced wares are needed
1261 if (prio > 0) {
1262 int32_t inout_prio = 0;
1263 for (size_t k = 0; k < bo.inputs.size(); ++k) {
1264 inout_prio += bf->producers_nearby.at(bo.inputs.at(k));
1265 inout_prio -= bf->consumers_nearby.at(bo.inputs.at(k)) / 2;
1266 }
1267 for (size_t k = 0; k < bo.outputs.size(); ++k)
1268 inout_prio += bf->consumers_nearby.at(bo.outputs.at(k));
1269 prio += 2 * inout_prio;
1270 prio = calculate_need_for_ps(bo, prio);
1271 } else
1272 return -1;
1273
1274 // take care about borders and enemies
1275 prio = recalc_with_border_range(*bf, prio);
1276
1277 // do not construct more than one building,
1278 // if supply line is already broken.
1279 if (!check_supply(bo) && bo.total_count() > 0)
1280 prio -= 12;
1281
1282 }
1283 } else if (bo.type == BuildingObserver::MILITARYSITE) {
1284 if (!bf->unowned_land_nearby)
1285 return -1;
1286 prio = bf->unowned_land_nearby * (1 + type);
1287 prio -= bf->military_influence * (5 - type);
1288 // set to at least 1
1289 prio = prio > 0 ? prio : 1;
1290 prio *= expand_factor;
1291 prio /= 2;
1292
1293 if (bf->enemy_nearby)
1294 prio *= 2;
1295 else
1296 prio -= bf->military_influence * 2;
1297
1298 if (bf->avoid_military)
1299 prio /= 5;
1300
1301 prio -= militarysites.size() - productionsites.size() / (3 - type);
1302
1303 } else if (bo.type == BuildingObserver::WAREHOUSE) {
1304 // Build one warehouse for ~every 35 productionsites and mines.
1305 // Militarysites are slightly important as well, to have a bigger
1306 // chance for a warehouses (containing waiting soldiers or wares
1307 // needed for soldier training) near the frontier.
1308 prio += productionsites.size() + mines.size();
1309 prio += militarysites.size() / 3;
1310 prio -= (bo.cnt_under_construction + numof_warehouses) * 35;
1311 prio *= 2;
1312
1313 // take care about borders and enemies
1314 prio = recalc_with_border_range(*bf, prio);
1315
1316 } else if (bo.type == BuildingObserver::TRAININGSITE) {
1317 // Start building trainingsites when there are already more than 50
1318 // other buildings. That should be enough for a working economy.
1319 // On the other hand only build more trainingsites of the same
1320 // type if the economy is really big.
1321 prio += productionsites.size() + militarysites.size();
1322 prio += mines.size();
1323 prio += type * 10; // +0 / +10 / +20 for DEFF/NORM/AGGR
1324 prio = prio / (bo.total_count() + 1);
1325 prio -= (bo.total_count() + 1) * 70;
1326
1327 // take care about borders and enemies
1328 prio = recalc_with_border_range(*bf, prio);
1329 }
1330
1331 // avoid to have too many construction sites
1332 // but still enable the player to build up basic productionsites
1333 if
1334 (bo.type != BuildingObserver::PRODUCTIONSITE ||
1335 !bo.is_basic || bo.total_count() > 0)
1336 prio /=
1337 1 + bo.cnt_under_construction * (bo.cnt_under_construction + 1);
1338
1339 // add big penalty if water is needed, but is not near
1340 if (bo.need_water) {
1341 if (bf->water_nearby < 3)
1342 return -1;
1343 int effect = bf->water_nearby - 8;
1344 prio +=
1345 effect > 0 ?
1346 static_cast<int>(sqrt(static_cast<double>(effect))) : effect;
1347 // if same producers are nearby, then give some penalty
1348 for (size_t k = 0; k < bo.outputs.size(); ++k)
1349 if (bf->producers_nearby.at(bo.outputs.at(k)) > 0)
1350 prio -= 3;
1351 }
1352
1353 // think of space consuming buildings nearby like farms or vineyards
1354 prio /= 1 + bf->space_consumers_nearby;
1355
1356 return prio;
1357}
1358
1255/**1359/**
1256 * This function searches for places where a new road is needed to connect two1360 * This function searches for places where a new road is needed to connect two
1257 * economies. It then sends the request to build the road.1361 * economies. It then sends the request to build the road.
@@ -1722,7 +1826,9 @@
1722 if (!site.site->has_workers(*x.current, game()))1826 if (!site.site->has_workers(*x.current, game()))
1723 continue;1827 continue;
17241828
1725 int32_t prio = 0; // priority for enhancement1829 /*BuildableField bf(map.get_fcoords(site.site->get_position()));
1830 int32_t prio = calculate_building_prio(en_bo, &bf, 0); // priority for enhancement*/
1831 int32_t prio = 0;
17261832
1727 // Find new outputs of enhanced building1833 // Find new outputs of enhanced building
1728 std::vector<int16_t> & current_outputs = site.bo->outputs;1834 std::vector<int16_t> & current_outputs = site.bo->outputs;
@@ -1742,6 +1848,7 @@
1742 // Check if the new wares are needed in economy of the building1848 // Check if the new wares are needed in economy of the building
1743 for (uint32_t i = 0; i < new_outputs.size(); ++i) {1849 for (uint32_t i = 0; i < new_outputs.size(); ++i) {
1744 Ware_Index wt(static_cast<size_t>(new_outputs.at(i)));1850 Ware_Index wt(static_cast<size_t>(new_outputs.at(i)));
1851 prio += round(wares.at(new_outputs.at(i)).demand / 50.0);
1745 if (site.site->economy().needs_ware(wt))1852 if (site.site->economy().needs_ware(wt))
1746 prio += 2 + wares.at(new_outputs.at(i)).preciousness;1853 prio += 2 + wares.at(new_outputs.at(i)).preciousness;
1747 }1854 }
@@ -2012,6 +2119,7 @@
2012 for (uint32_t k = 0; k < bo.inputs.size(); ++k) {2119 for (uint32_t k = 0; k < bo.inputs.size(); ++k) {
2013 prio += 2 * wares.at(bo.inputs.at(k)).producers;2120 prio += 2 * wares.at(bo.inputs.at(k)).producers;
2014 prio -= wares.at(bo.inputs.at(k)).consumers;2121 prio -= wares.at(bo.inputs.at(k)).consumers;
2122 prio -= round(wares.at(bo.inputs.at(k)).demand / 100.0);
2015 }2123 }
2016 if (bo.inputs.empty())2124 if (bo.inputs.empty())
2017 prio += 4;2125 prio += 4;
@@ -2021,6 +2129,7 @@
2021 WareObserver & wo = wares.at(bo.outputs.at(k));2129 WareObserver & wo = wares.at(bo.outputs.at(k));
2022 if (wo.consumers > 0) {2130 if (wo.consumers > 0) {
2023 output_prio += wo.preciousness;2131 output_prio += wo.preciousness;
2132 output_prio += round(wo.demand / 100.0);
2024 output_prio += wo.consumers * 2;2133 output_prio += wo.consumers * 2;
2025 output_prio -= wo.producers * 2;2134 output_prio -= wo.producers * 2;
2026 if (bo.total_count() == 0)2135 if (bo.total_count() == 0)
20272136
=== modified file 'src/ai/defaultai.h'
--- src/ai/defaultai.h 2012-02-20 15:54:26 +0000
+++ src/ai/defaultai.h 2013-01-05 13:44:24 +0000
@@ -118,6 +118,7 @@
118 void update_all_buildable_fields (int32_t);118 void update_all_buildable_fields (int32_t);
119 void update_all_mineable_fields (int32_t);119 void update_all_mineable_fields (int32_t);
120 void update_all_not_buildable_fields ();120 void update_all_not_buildable_fields ();
121 void update_demand();
121122
122 void update_buildable_field(BuildableField &, uint16_t = 6, bool = false);123 void update_buildable_field(BuildableField &, uint16_t = 6, bool = false);
123 void update_mineable_field (MineableField &);124 void update_mineable_field (MineableField &);
@@ -138,6 +139,7 @@
138139
139 int32_t recalc_with_border_range(const BuildableField &, int32_t);140 int32_t recalc_with_border_range(const BuildableField &, int32_t);
140 int32_t calculate_need_for_ps(BuildingObserver &, int32_t);141 int32_t calculate_need_for_ps(BuildingObserver &, int32_t);
142 int32_t calculate_building_prio(BuildingObserver & bo, BuildableField * const bf, uint32_t expand_factor);
141143
142 void consider_productionsite_influence144 void consider_productionsite_influence
143 (BuildableField &, Widelands::Coords, BuildingObserver const &);145 (BuildableField &, Widelands::Coords, BuildingObserver const &);
@@ -193,6 +195,8 @@
193 int32_t time_of_last_construction;195 int32_t time_of_last_construction;
194196
195 uint16_t numof_warehouses;197 uint16_t numof_warehouses;
198
199 float military_demand;
196};200};
197201
198#endif202#endif
199203
=== modified file 'src/logic/militarysite.h'
--- src/logic/militarysite.h 2012-02-15 21:25:34 +0000
+++ src/logic/militarysite.h 2013-01-05 13:44:24 +0000
@@ -75,6 +75,7 @@
75 // Begin implementation of SoldierControl75 // Begin implementation of SoldierControl
76 virtual std::vector<Soldier *> presentSoldiers() const;76 virtual std::vector<Soldier *> presentSoldiers() const;
77 virtual std::vector<Soldier *> stationedSoldiers() const;77 virtual std::vector<Soldier *> stationedSoldiers() const;
78 virtual uint32_t missingSoldiers() { return m_capacity - stationedSoldiers().size(); }
78 virtual uint32_t minSoldierCapacity() const throw ();79 virtual uint32_t minSoldierCapacity() const throw ();
79 virtual uint32_t maxSoldierCapacity() const throw ();80 virtual uint32_t maxSoldierCapacity() const throw ();
80 virtual uint32_t soldierCapacity() const;81 virtual uint32_t soldierCapacity() const;
8182
=== modified file 'tribes/barbarians/fernery/conf'
--- tribes/barbarians/fernery/conf 2011-09-12 17:29:32 +0000
+++ tribes/barbarians/fernery/conf 2013-01-05 13:44:24 +0000
@@ -3,6 +3,7 @@
33
4[aihints]4[aihints]
5space_consumer=true5space_consumer=true
6is_basic=true
67
7[buildcost]8[buildcost]
8trunk=59trunk=5

Subscribers

People subscribed via source and target branches

to status/vote changes: