diff --git a/src/economy.c b/src/economy.c index ae13d5ecc..caa771142 100644 --- a/src/economy.c +++ b/src/economy.c @@ -1713,7 +1713,11 @@ static void buy(unit * u, request ** buyorders, struct order *ord) /* ...oder in der Region muß es eine Burg geben. */ building *b = 0; if (r->buildings) { - const struct building_type *bt_castle = bt_find("castle"); + static int cache; + static const struct building_type *bt_castle; + if (bt_changed(&cache)) { + bt_castle = bt_find("castle"); + } for (b = r->buildings; b; b = b->next) { if (b->type == bt_castle && b->size >= 2) { @@ -1799,8 +1803,14 @@ static void expandselling(region * r, request * sellorders, int limit) unit *hafenowner; static int counter[MAXLUXURIES]; static int ncounter = 0; - const struct building_type *castle_bt; + static int bt_cache; + static const struct building_type *castle_bt, *harbour_bt, *caravan_bt; + if (bt_changed(&bt_cache)) { + castle_bt = bt_find("castle"); + harbour_bt = bt_find("harbour"); + caravan_bt = bt_find("caravan"); + } if (ncounter == 0) { const luxury_type *ltype; for (ltype = luxurytypes; ltype; ltype = ltype->next) { @@ -1815,7 +1825,6 @@ static void expandselling(region * r, request * sellorders, int limit) } /* Stelle Eigentümer der größten Burg fest. Bekommt Steuern aus jedem * Verkauf. Wenn zwei Burgen gleicher Größe bekommt gar keiner etwas. */ - castle_bt = bt_find("castle"); for (b = rbuildings(r); b; b = b->next) { if (b->size > maxsize && building_owner(b) != NULL && b->type == castle_bt) { @@ -1829,7 +1838,7 @@ static void expandselling(region * r, request * sellorders, int limit) } } - hafenowner = owner_buildingtyp(r, bt_find("harbour")); + hafenowner = owner_buildingtyp(r, harbour_bt); if (maxb != (building *)NULL && maxowner != (unit *)NULL) { maxeffsize = buildingeffsize(maxb, false); @@ -1851,7 +1860,7 @@ static void expandselling(region * r, request * sellorders, int limit) return; if (r->terrain == newterrain(T_DESERT) - && buildingtype_exists(r, bt_find("caravan"), true)) { + && buildingtype_exists(r, caravan_bt, true)) { max_products = rpeasants(r) * 2 / TRADE_FRACTION; } /* Verkauf: so programmiert, dass er leicht auf mehrere Gueter pro @@ -1978,6 +1987,13 @@ static bool sell(unit * u, request ** sellorders, struct order *ord) region *r = u->region; const char *s; keyword_t kwd; + static int bt_cache; + static const struct building_type *castle_bt, *caravan_bt; + + if (bt_changed(&bt_cache)) { + castle_bt = bt_find("castle"); + caravan_bt = bt_find("caravan"); + } if (u->ship && is_guarded(r, u, GUARD_CREWS)) { cmistake(u, ord, 69, MSG_INCOME); @@ -1994,7 +2010,7 @@ static bool sell(unit * u, request ** sellorders, struct order *ord) unlimited = false; n = rpeasants(r) / TRADE_FRACTION; if (r->terrain == newterrain(T_DESERT) - && buildingtype_exists(r, bt_find("caravan"), true)) + && buildingtype_exists(r, caravan_bt, true)) n *= 2; if (n == 0) { cmistake(u, ord, 303, MSG_COMMERCE); @@ -2027,9 +2043,8 @@ static bool sell(unit * u, request ** sellorders, struct order *ord) /* ...oder in der Region muß es eine Burg geben. */ building *b = 0; if (r->buildings) { - const struct building_type *bt_castle = bt_find("castle"); for (b = r->buildings; b; b = b->next) { - if (b->type == bt_castle && b->size >= 2) break; + if (b->type == castle_bt && b->size >= 2) break; } } if (!b) { @@ -2344,9 +2359,15 @@ static void breedhorses(unit * u) int n, c, breed = 0; const struct resource_type *rhorse = get_resourcetype(R_HORSE); int horses, effsk; + static int bt_cache; + static const struct building_type *stables_bt; + + if (bt_changed(&bt_cache)) { + stables_bt = bt_find("stables"); + } assert(rhorse && rhorse->itype); - if (!active_building(u, bt_find("stables"))) { + if (!active_building(u, stables_bt)) { cmistake(u, u->thisorder, 122, MSG_PRODUCE); return; } @@ -3083,6 +3104,13 @@ void produce(struct region *r) unit *u; bool limited = true; request *nextworker = workers; + static int bt_cache; + static const struct building_type *caravan_bt; + + if (bt_changed(&bt_cache)) { + caravan_bt = bt_find("caravan"); + } + assert(r); /* das sind alles befehle, die 30 tage brauchen, und die in thisorder @@ -3232,7 +3260,7 @@ void produce(struct region *r) if (sellorders) { int limit = rpeasants(r) / TRADE_FRACTION; if (r->terrain == newterrain(T_DESERT) - && buildingtype_exists(r, bt_find("caravan"), true)) + && buildingtype_exists(r, caravan_bt, true)) limit *= 2; expandselling(r, sellorders, limited ? limit : INT_MAX); } diff --git a/src/kernel/building.c b/src/kernel/building.c index 60b588912..0056fba1e 100644 --- a/src/kernel/building.c +++ b/src/kernel/building.c @@ -83,15 +83,28 @@ const building_type *bt_find(const char *name) return bt_find_i(name); } +static int bt_changes = 1; + +bool bt_changed(int *cache) +{ + assert(cache); + if (*cache != bt_changes) { + *cache = bt_changes; + return true; + } + return false; +} + void bt_register(building_type * type) { if (type->init) { type->init(type); } ql_push(&buildingtypes, (void *)type); + ++bt_changes; } -void free_buildingtype(void *ptr) { +static void free_buildingtype(void *ptr) { building_type *btype = (building_type *)ptr; free_construction(btype->construction); free(btype->maintenance); @@ -103,6 +116,7 @@ void free_buildingtypes(void) { ql_foreach(buildingtypes, free_buildingtype); ql_free(buildingtypes); buildingtypes = 0; + ++bt_changes; } building_type *bt_get_or_create(const char *name) diff --git a/src/kernel/building.h b/src/kernel/building.h index 587197276..dad9ffdde 100644 --- a/src/kernel/building.h +++ b/src/kernel/building.h @@ -84,6 +84,7 @@ extern "C" { extern struct attrib_type at_building_action; building_type *bt_get_or_create(const char *name); + bool bt_changed(int *cache); const building_type *bt_find(const char *name); void free_buildingtypes(void); void register_buildings(void); diff --git a/src/kernel/building.test.c b/src/kernel/building.test.c index 2f6fa6e34..755e9319f 100644 --- a/src/kernel/building.test.c +++ b/src/kernel/building.test.c @@ -17,16 +17,20 @@ static void test_register_building(CuTest * tc) { building_type *btype; + int cache = 0; test_cleanup(); btype = (building_type *)calloc(sizeof(building_type), 1); btype->_name = _strdup("herp"); + CuAssertIntEquals(tc, true, bt_changed(&cache)); + CuAssertIntEquals(tc, false, bt_changed(&cache)); bt_register(btype); + CuAssertIntEquals(tc, true, bt_changed(&cache)); CuAssertPtrNotNull(tc, bt_find("herp")); - // free(btype->_name); - // free(btype); + free_buildingtypes(); + CuAssertIntEquals(tc, true, bt_changed(&cache)); test_cleanup(); }