← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/ai_production_hints into lp:widelands

 

TiborB has proposed merging lp:~widelands-dev/widelands/ai_production_hints into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/ai_production_hints/+merge/329636

AI hints now allow multiple hints / supported ware for one productionsite
-- 
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/ai_production_hints into lp:widelands.
=== modified file 'data/tribes/buildings/productionsites/atlanteans/fishbreeders_house/init.lua'
--- data/tribes/buildings/productionsites/atlanteans/fishbreeders_house/init.lua	2017-02-11 12:04:33 +0000
+++ data/tribes/buildings/productionsites/atlanteans/fishbreeders_house/init.lua	2017-08-25 19:19:24 +0000
@@ -27,7 +27,7 @@
 
    aihints = {
       needs_water = true,
-      renews_map_resource = "fish",
+      supports_production_of = { "fish" },
       prohibited_till = 700,
       forced_after = 900
    },

=== modified file 'data/tribes/buildings/productionsites/atlanteans/foresters_house/init.lua'
--- data/tribes/buildings/productionsites/atlanteans/foresters_house/init.lua	2015-12-11 16:54:00 +0000
+++ data/tribes/buildings/productionsites/atlanteans/foresters_house/init.lua	2017-08-25 19:19:24 +0000
@@ -28,7 +28,7 @@
 
    aihints = {
       space_consumer = true,
-      renews_map_resource = "log",
+      supports_production_of = { "log" },
       prohibited_till = 240
    },
 

=== modified file 'data/tribes/buildings/productionsites/barbarians/gamekeepers_hut/init.lua'
--- data/tribes/buildings/productionsites/barbarians/gamekeepers_hut/init.lua	2017-06-26 19:48:43 +0000
+++ data/tribes/buildings/productionsites/barbarians/gamekeepers_hut/init.lua	2017-08-25 19:19:24 +0000
@@ -34,7 +34,7 @@
    },
 
    aihints = {
-      renews_map_resource = "meat",
+      supports_production_of = { "meat" },
       prohibited_till = 900,
       basic_amount = 1
    },

=== modified file 'data/tribes/buildings/productionsites/barbarians/rangers_hut/init.lua'
--- data/tribes/buildings/productionsites/barbarians/rangers_hut/init.lua	2017-06-26 19:48:43 +0000
+++ data/tribes/buildings/productionsites/barbarians/rangers_hut/init.lua	2017-08-25 19:19:24 +0000
@@ -32,7 +32,7 @@
    },
 
    aihints = {
-      renews_map_resource = "log",
+      supports_production_of = { "log" },
       space_consumer = true,
       basic_amount = 1
    },

=== modified file 'data/tribes/buildings/productionsites/empire/foresters_house/init.lua'
--- data/tribes/buildings/productionsites/empire/foresters_house/init.lua	2015-12-11 16:54:00 +0000
+++ data/tribes/buildings/productionsites/empire/foresters_house/init.lua	2017-08-25 19:19:24 +0000
@@ -28,7 +28,7 @@
 
    aihints = {
       space_consumer = true,
-      renews_map_resource = "log",
+      supports_production_of = { "log" },
       prohibited_till = 200
    },
 

=== modified file 'src/ai/ai_help_structs.h'
--- src/ai/ai_help_structs.h	2017-08-20 17:45:42 +0000
+++ src/ai/ai_help_structs.h	2017-08-25 19:19:24 +0000
@@ -452,7 +452,7 @@
 	std::unordered_set<Widelands::DescriptionIndex> substitute_inputs;
 	int32_t substitutes_count;
 
-	int16_t production_hint;
+	std::set<DescriptionIndex> production_hints;
 
 	// information needed for decision on new building construction
 	int16_t max_preciousness;

=== modified file 'src/ai/ai_hints.cc'
--- src/ai/ai_hints.cc	2017-06-27 17:58:30 +0000
+++ src/ai/ai_hints.cc	2017-08-25 19:19:24 +0000
@@ -22,9 +22,7 @@
 #include <memory>
 
 BuildingHints::BuildingHints(std::unique_ptr<LuaTable> table)
-   : renews_map_resource_(
-        table->has_key("renews_map_resource") ? table->get_string("renews_map_resource") : ""),
-     mines_(table->has_key("mines") ? table->get_string("mines") : ""),
+   : mines_(table->has_key("mines") ? table->get_string("mines") : ""),
      log_producer_(table->has_key("logproducer") ? table->get_bool("logproducer") : false),
      granite_producer_(table->has_key("graniteproducer") ? table->get_bool("graniteproducer") :
                                                            false),
@@ -48,6 +46,11 @@
      trainingsites_max_percent_(table->has_key("trainingsites_max_percent") ?
                                    table->get_int("trainingsites_max_percent") :
                                    0) {
+	if (table->has_key("supports_production_of")) {
+		for (const std::string& ware_name : table->get_table("supports_production_of")->array_entries<std::string>()) {
+			supported_production_.insert(ware_name);
+		}
+	}
 }
 
 void BuildingHints::set_trainingsites_max_percent(int percent) {

=== modified file 'src/ai/ai_hints.h'
--- src/ai/ai_hints.h	2017-06-26 15:09:21 +0000
+++ src/ai/ai_hints.h	2017-08-25 19:19:24 +0000
@@ -26,6 +26,7 @@
 
 #include "base/log.h"
 #include "base/macros.h"
+#include "scripting/lua_interface.h"
 #include "scripting/lua_table.h"
 
 /// This struct is used to read out the data given in [aihints] section of a
@@ -36,12 +37,8 @@
 	~BuildingHints() {
 	}
 
-	bool renews_map_resource() const {
-		return !renews_map_resource_.empty();
-	}
-
-	std::string get_renews_map_resource() const {
-		return renews_map_resource_;
+	std::set<std::string> get_supported_production_() const {
+		return supported_production_;
 	}
 
 	bool has_mines() const {
@@ -118,13 +115,12 @@
 	uint8_t trainingsites_max_percent() const;
 
 private:
-	std::string renews_map_resource_;
 	std::string mines_;
 	bool log_producer_;
 	bool granite_producer_;
 	bool needs_water_;
 	bool mines_water_;
-	bool recruitment_;  // whether building recruits special workers
+	bool recruitment_;
 	bool space_consumer_;
 	bool expansion_;
 	bool fighting_;
@@ -137,6 +133,7 @@
 	int16_t very_weak_ai_limit_;
 	int16_t weak_ai_limit_;
 	int trainingsites_max_percent_;
+	std::set<std::string> supported_production_;
 
 	DISALLOW_COPY_AND_ASSIGN(BuildingHints);
 };

=== modified file 'src/ai/defaultai.cc'
--- src/ai/defaultai.cc	2017-08-20 17:45:42 +0000
+++ src/ai/defaultai.cc	2017-08-25 19:19:24 +0000
@@ -612,7 +612,6 @@
 		bo.construction_decision_time = -60 * 60 * 1000;
 		bo.last_building_built = kNever;
 		bo.build_material_shortage = false;
-		bo.production_hint = kUncalculated;
 		bo.current_stats = 0;
 		bo.unoccupied_count = 0;
 		bo.unconnected_count = 0;
@@ -657,15 +656,13 @@
 		bo.max_preciousness = 0;
 		bo.max_needed_preciousness = 0;
 
-		if (bh.renews_map_resource()) {
-			bo.production_hint = tribe_->safe_ware_index(bh.get_renews_map_resource());
+		for (auto ph : bh.get_supported_production_()) {
+			bo.production_hints.insert(tribe_->safe_ware_index(ph));
 		}
-
 		// I just presume cut wood is named "log" in the game
-		if (tribe_->safe_ware_index("log") == bo.production_hint) {
+		if (bo.production_hints.count(tribe_->safe_ware_index("log"))) {
 			bo.set_is(BuildingAttribute::kRanger);
 		}
-
 		// Is total count of this building limited by AI mode?
 		if (type_ == Widelands::AiType::kVeryWeak && bh.get_very_weak_ai_limit() >= 0) {
 			bo.cnt_limit_by_aimode = bh.get_very_weak_ai_limit();
@@ -858,6 +855,7 @@
 	// create e.g. two barracks or bakeries, the impact on the AI must be considered
 	assert(count_buildings_with_attribute(BuildingAttribute::kBarracks) == 1);
 	assert(count_buildings_with_attribute(BuildingAttribute::kLogRefiner) == 1);
+	assert(count_buildings_with_attribute(BuildingAttribute::kRanger) == 1);
 	assert(count_buildings_with_attribute(BuildingAttribute::kWell) == 1);
 	assert(count_buildings_with_attribute(BuildingAttribute::kLumberjack) == 1);
 	assert(count_buildings_with_attribute(BuildingAttribute::kHunter) == 1);
@@ -2558,7 +2556,7 @@
 						prio *= 3;
 					}
 
-				} else if (bo.production_hint >= 0) {
+				} else if (!bo.production_hints.empty()) {
 					if (bo.is(BuildingAttribute::kRanger)) {
 						assert(bo.cnt_target > 0);
 					}
@@ -2580,18 +2578,22 @@
 
 						prio -= bf->water_nearby / 5;
 
-						prio += management_data.neuron_pool[67].get_result_safe(
-						           bf->producers_nearby.at(bo.production_hint) * 5, kAbsValue) /
+						for (auto ph : bo.production_hints) {
+							prio += management_data.neuron_pool[67].get_result_safe(
+						           bf->producers_nearby.at(ph) * 5, kAbsValue) /
 						        2;
+						}
 
 						prio +=
 						   management_data.neuron_pool[49].get_result_safe(bf->trees_nearby, kAbsValue) /
 						   5;
 
-						prio += bf->producers_nearby.at(bo.production_hint) * 5 -
-						        (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) * 15 -
-						        bf->space_consumers_nearby * 5 - bf->rocks_nearby / 3 +
-						        bf->supporters_nearby.at(bo.production_hint) * 3;
+						for (auto ph : bo.production_hints) {
+							prio += bf->producers_nearby.at(ph) * 5 -
+							        (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) * 15 -
+							        bf->space_consumers_nearby * 5 - bf->rocks_nearby / 3 +
+							        bf->supporters_nearby.at(ph) * 3;
+						}
 
 					} else {  // FISH BREEDERS and GAME KEEPERS
 
@@ -2618,8 +2620,10 @@
 							           (40 - current_stocklevel) / 2, kAbsValue);
 						}
 
-						prio += bf->producers_nearby.at(bo.production_hint) * 10;
-						prio -= bf->supporters_nearby.at(bo.production_hint) * 20;
+						for (auto ph : bo.production_hints) {
+							prio += bf->producers_nearby.at(ph) * 10;
+							prio -= bf->supporters_nearby.at(ph) * 20;
+						}
 
 						if (bf->enemy_nearby) {
 							prio -= 20;
@@ -2632,7 +2636,7 @@
 					prio -= (bf->enemy_nearby) * 100;
 					prio -= (expansion_type.get_expansion_type() != ExpansionMode::kEconomy) * 100;
 				} else {  // finally normal productionsites
-					assert(bo.production_hint < 0);
+					assert(bo.production_hints.empty());
 
 					if (bo.new_building == BuildingNecessity::kForced) {
 						prio += 150;
@@ -3908,7 +3912,7 @@
 
 	// All other SPACE_CONSUMERS without input and above target_count
 	if (site.bo->inputs.empty()                       // does not consume anything
-	    && site.bo->production_hint == kUncalculated  // not a renewing building (forester...)
+	    && site.bo->production_hints.empty()          // not a renewing building (forester...)
 	    && site.bo->is(BuildingAttribute::kSpaceConsumer) &&
 	    !site.bo->is(BuildingAttribute::kRanger)) {
 
@@ -3976,7 +3980,7 @@
 
 	// remaining buildings without inputs and not supporting ones (fishers only left probably and
 	// hunters)
-	if (site.bo->inputs.empty() && site.bo->production_hint < 0 && site.site->can_start_working() &&
+	if (site.bo->inputs.empty() && site.bo->production_hints.empty() && site.site->can_start_working() &&
 	    !site.bo->is(BuildingAttribute::kSpaceConsumer) &&
 	    site.site->get_statistics_percent() < 10 &&
 	    ((game().get_gametime() - site.built_time) > 10 * 60 * 1000)) {
@@ -3993,7 +3997,7 @@
 
 	// supporting productionsites (rangers)
 	// stop/start them based on stock avaiable
-	if (site.bo->production_hint >= 0) {
+	if (!site.bo->production_hints.empty()) {
 
 		if (!site.bo->is(BuildingAttribute::kRanger)) {
 			// other supporting sites, like fish breeders, gamekeepers are not dismantled at all
@@ -4737,7 +4741,7 @@
 		           bo.cnt_under_construction + bo.unoccupied_count == 0) {
 			bo.max_needed_preciousness = bo.max_preciousness;  // even when rocks are not needed
 			return BuildingNecessity::kAllowed;
-		} else if (bo.production_hint >= 0) {
+		} else if (!bo.production_hints.empty()) {
 
 			if (bo.cnt_under_construction + bo.unoccupied_count - bo.unconnected_count > 0) {
 				return BuildingNecessity::kForbidden;
@@ -5214,8 +5218,16 @@
 uint32_t
 DefaultAI::get_stocklevel(BuildingObserver& bo, const uint32_t gametime, const WareWorker what) {
 	if (bo.stocklevel_time < gametime - 5 * 1000) {
-		if (bo.production_hint > 0) {
-			bo.stocklevel_count = calculate_stocklevel(static_cast<size_t>(bo.production_hint), what);
+		if (!bo.production_hints.empty()) {
+			// looking for smallest value
+			bo.stocklevel_count = std::numeric_limits<uint32_t>::max();
+			for (auto ph : bo.production_hints ) {
+				const uint32_t res = calculate_stocklevel(static_cast<size_t>(ph), what);
+				if (res < bo.stocklevel_count) {
+					bo.stocklevel_count = res;
+				}
+			}
+			assert (bo.stocklevel_count < std::numeric_limits<uint32_t>::max());
 		} else if (!bo.outputs.empty()) {
 			bo.stocklevel_count = calculate_stocklevel(bo, what);
 		} else {
@@ -5285,8 +5297,10 @@
 		++field.producers_nearby.at(bo.outputs.at(i));
 	}
 
-	if (bo.production_hint >= 0) {
-		++field.supporters_nearby.at(bo.production_hint);
+	if (!bo.production_hints.empty()) {
+		for (auto ph : bo.production_hints) {
+			++field.supporters_nearby.at(ph);
+		}
 	}
 
 	if (bo.is(BuildingAttribute::kRanger)) {


Follow ups