[Freeciv-Dev] (PR#11907) a better init_min_production
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=11907 >
Well, here's an updated patch. This also uses is_free_worked_tile to
avoid hard-coding the free-city-center.
Pruning by everything except shields and food is dropped again. This is
still an improvement over the current version since it uses pcity->usage.
However I think with the current method of trade-routes it is impossible
ever to do pruning by trade or luxury or gold.
1. We can't prune directly by gold since only taxmen make gold.
Tile-workers don't make gold they make trade.
2. We can't convert the gold minimum into a trade minimum because
taxmen don't make trade.
3. We might be able to convert trade into gold directly at the pruning
stage in compute_max_stats_heuristic, allowing (again) pruning by gold,
except...
4. Without even more recalculation in compute_max_stats_heuristic there
is no way at all to account for trade routes in compute_max_stats_heuristic.
Maybe something can be done but that can wait for later. For the moment
this patch is sufficient.
I tried running it on client-side CM and got identical results to what
we have now.
As a side note the CM should have a debug mode that skips all pruning
and does a full search. This will be super slow (exponentially slower
than the current code, probably) but would allow sanity checks by
comparing it to the pruned searches.
-jason
? 1
? diff
Index: common/aicore/cm.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/aicore/cm.c,v
retrieving revision 1.62
diff -u -r1.62 cm.c
--- common/aicore/cm.c 7 Apr 2005 04:36:02 -0000 1.62
+++ common/aicore/cm.c 19 Apr 2005 07:33:00 -0000
@@ -1518,67 +1518,45 @@
****************************************************************************/
static void init_min_production(struct cm_state *state)
{
- int x = CITY_MAP_RADIUS, y = CITY_MAP_RADIUS;
- int usage[O_COUNT];
struct city *pcity = state->pcity;
bool is_celebrating = base_city_celebrating(pcity);
- struct city backup;
- /* make sure the city's numbers make sense (sometimes they don't,
- * somehow) */
- memcpy(&backup, pcity, sizeof(*pcity));
- generic_city_refresh(pcity, FALSE, NULL);
+ /* We used to call generic_city_refresh here, but that's no longer
+ * necessary since it's called at the start of cm_query_result. */
memset(state->min_production, 0, sizeof(state->min_production));
+ output_type_iterate(o) {
+ /* Calculate minimum output. This assumes no waste. Pruning
+ * is done mainly based on minimum production, so we want to find the
+ * absolute highest minimum possible. However if the minimum we find
+ * here is incorrectly too high, then the algorithm will fail. */
+ int min;
+
+ if (o != O_SHIELD && o != O_FOOD) {
+ /* min-production calculations are only possible for food and
+ * shields. The others depend on complex trade calculations
+ * that cannot be accounted for since the bonus from trade
+ * routes depends on the amount of trade in an unpredictable way. */
+ continue;
+ }
+
+ /* 1. Calculate the minimum final production that is needed.
+ * 2. Divide by the bonus (rounding down) to get the minimum citizen
+ * production that is needed.
+ * 3. Subtract off any "free" production (trade routes, tithes, and
+ * city-center). */
+ min = pcity->usage[o] + state->parameter.minimal_surplus[o];
+ min = min * 100 / pcity->bonus[o];
+ city_map_iterate(x, y) {
+ if (is_free_worked_tile(x, y)) {
+ min -= base_city_get_output_tile(x, y, pcity, is_celebrating, o);
+ }
+ } city_map_iterate_end;
+ state->min_production[o] = MAX(min, 0);
+ } output_type_iterate_end;
- /* If the city is content, then we know the food usage is just
- * prod-surplus; otherwise, we know it's at least 2*size but we
- * can't easily compute the settlers. */
- if (!city_unhappy(pcity)) {
- usage[O_FOOD] = pcity->prod[O_FOOD] - pcity->surplus[O_FOOD];
- } else {
- usage[O_FOOD] = pcity->size * 2;
- }
- state->min_production[O_FOOD] = usage[O_FOOD]
- + state->parameter.minimal_surplus[O_FOOD]
- - base_city_get_output_tile(x, y, pcity, is_celebrating, O_FOOD);
-
- /* surplus = (factories-waste) * production - shield_usage, so:
- * production = (surplus + shield_usage)/(factories-waste)
- * waste >= 0, so:
- * production >= (surplus + usage)/factories
- * Solving with surplus >= min_surplus, we get:
- * production >= (min_surplus + usage)/factories
- * 'factories' is the pcity->bonus[O_SHIELD]/100. Increase it a bit to avoid
- * rounding errors.
- *
- * pcity->prod[O_SHIELD] = (factories-waste) * production.
- * Therefore, shield_usage = pcity->prod[O_SHIELD] - pcity->shield_surplus
- */
- if (!city_unhappy(pcity)) {
- double sbonus;
-
- usage[O_SHIELD] = pcity->prod[O_SHIELD] - pcity->surplus[O_SHIELD];
-
- sbonus = ((double)pcity->bonus[O_SHIELD]) / 100.0;
- sbonus += .1;
- state->min_production[O_SHIELD]
- = ((usage[O_SHIELD] + state->parameter.minimal_surplus[O_SHIELD])
- / sbonus);
- state->min_production[O_SHIELD]
- -= base_city_get_output_tile(x, y, pcity, is_celebrating, O_SHIELD);
- } else {
- /* Dunno what the usage is, so it's pointless to set the
- * min_production */
- usage[O_SHIELD] = 0;
- state->min_production[O_SHIELD] = 0;
- }
-
- /* we should be able to get a min_production on gold and trade, too;
- also, lux, if require_happy, but not otherwise */
-
- /* undo any effects from the refresh */
- memcpy(pcity, &backup, sizeof(*pcity));
+ /* We could get a minimum on luxury if we knew how many luxuries were
+ * needed to make us content. */
}
/****************************************************************************
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Freeciv-Dev] (PR#11907) a better init_min_production,
Jason Short <=
|
|