1 #include "house_evolution.h"
2 
3 #include "building/house.h"
4 #include "building/model.h"
5 #include "building/monument.h"
6 #include "city/houses.h"
7 #include "city/resource.h"
8 #include "core/calc.h"
9 #include "core/time.h"
10 #include "game/resource.h"
11 #include "game/time.h"
12 #include "game/undo.h"
13 #include "map/building.h"
14 #include "map/grid.h"
15 #include "map/routing_terrain.h"
16 #include "map/tiles.h"
17 
18 #define DEVOLVE_DELAY 2
19 #define DEVOLVE_DELAY_WITH_VENUS 20
20 
21 typedef enum {
22     EVOLVE = 1,
23     NONE = 0,
24     DEVOLVE = -1
25 } evolve_status;
26 
27 static int active_devolve_delay;
28 
check_evolve_desirability(building * house,int bonus)29 static int check_evolve_desirability(building *house, int bonus)
30 {
31     int level = house->subtype.house_level;
32     level -= bonus;
33     level = calc_bound(level, HOUSE_MIN, HOUSE_MAX);
34     const model_house *model = model_get_house(level);
35     int evolve_des = model->evolve_desirability;
36     if (level >= HOUSE_LUXURY_PALACE) {
37         evolve_des = 1000;
38     }
39     int current_des = house->desirability;
40     int status;
41     if (current_des <= model->devolve_desirability) {
42         status = DEVOLVE;
43     } else if (current_des >= evolve_des) {
44         status = EVOLVE;
45     } else {
46         status = NONE;
47     }
48     house->data.house.evolve_text_id = status; // BUG? -1 in an unsigned char?
49     return status;
50 }
51 
has_required_goods_and_services(building * house,int for_upgrade,int with_bonus,house_demands * demands)52 static int has_required_goods_and_services(building *house, int for_upgrade, int with_bonus, house_demands *demands)
53 {
54     int level = house->subtype.house_level;
55     if (for_upgrade) {
56         ++level;
57     }
58     if (with_bonus) {
59         --level;
60     }
61     level = calc_bound(level, HOUSE_MIN, HOUSE_MAX);
62     const model_house *model = model_get_house(level);
63     // water
64     int water = model->water;
65     if (!house->has_water_access) {
66         if (water >= 2) {
67             ++demands->missing.fountain;
68             return 0;
69         }
70         if (water == 1 && !house->has_well_access) {
71             ++demands->missing.well;
72             return 0;
73         }
74     }
75     // entertainment
76     int entertainment = model->entertainment;
77     if (house->data.house.entertainment < entertainment) {
78         if (house->data.house.entertainment) {
79             ++demands->missing.more_entertainment;
80         } else {
81             ++demands->missing.entertainment;
82         }
83         return 0;
84     }
85     // education
86     int education = model->education;
87     if (house->data.house.education < education) {
88         if (house->data.house.education) {
89             ++demands->missing.more_education;
90         } else {
91             ++demands->missing.education;
92         }
93         return 0;
94     }
95     if (education == 2) {
96         ++demands->requiring.school;
97         ++demands->requiring.library;
98     } else if (education == 1) {
99         ++demands->requiring.school;
100     }
101     // religion
102     int religion = model->religion;
103     if (house->data.house.num_gods < religion) {
104         if (religion == 1) {
105             ++demands->missing.religion;
106             return 0;
107         } else if (religion == 2) {
108             ++demands->missing.second_religion;
109             return 0;
110         } else if (religion == 3) {
111             ++demands->missing.third_religion;
112             return 0;
113         }
114     } else if (religion > 0) {
115         ++demands->requiring.religion;
116     }
117     // barber
118     int barber = model->barber;
119     if (house->data.house.barber < barber) {
120         ++demands->missing.barber;
121         return 0;
122     }
123     if (barber == 1) {
124         ++demands->requiring.barber;
125     }
126     // bathhouse
127     int bathhouse = model->bathhouse;
128     if (house->data.house.bathhouse < bathhouse) {
129         ++demands->missing.bathhouse;
130         return 0;
131     }
132     if (bathhouse == 1) {
133         ++demands->requiring.bathhouse;
134     }
135     // health
136     int health = model->health;
137     if (house->data.house.health < health) {
138         if (health < 2) {
139             ++demands->missing.clinic;
140         } else {
141             ++demands->missing.hospital;
142         }
143         return 0;
144     }
145     if (health >= 1) {
146         ++demands->requiring.clinic;
147     }
148     // food types
149     int foodtypes_required = model->food_types;
150     int foodtypes_available = 0;
151     for (int i = INVENTORY_MIN_FOOD; i < INVENTORY_MAX_FOOD; i++) {
152         if (house->data.house.inventory[i]) {
153             foodtypes_available++;
154         }
155     }
156     if (foodtypes_available < foodtypes_required) {
157         ++demands->missing.food;
158         return 0;
159     }
160     // goods
161     if (house->data.house.inventory[INVENTORY_POTTERY] < model->pottery) {
162         return 0;
163     }
164     if (house->data.house.inventory[INVENTORY_OIL] < model->oil) {
165         return 0;
166     }
167     if (house->data.house.inventory[INVENTORY_FURNITURE] < model->furniture) {
168         return 0;
169     }
170     int wine = model->wine;
171     if (wine && house->data.house.inventory[INVENTORY_WINE] <= 0) {
172         return 0;
173     }
174     if (wine > 1 && !city_resource_multiple_wine_available()) {
175         ++demands->missing.second_wine;
176         return 0;
177     }
178     return 1;
179 }
180 
check_requirements(building * house,house_demands * demands)181 static int check_requirements(building *house, house_demands *demands)
182 {
183     int bonus = 0;
184     if (building_monument_pantheon_module_is_active(PANTHEON_MODULE_2_HOUSING_EVOLUTION) && house->house_pantheon_access) {
185         bonus++;
186     }
187     int status = check_evolve_desirability(house, bonus);
188     if (!has_required_goods_and_services(house, 0, bonus, demands)) {
189         status = DEVOLVE;
190     } else if (status == EVOLVE) {
191         status = has_required_goods_and_services(house, 1, bonus, demands);
192     }
193     return status;
194 }
195 
has_devolve_delay(building * house,evolve_status status)196 static int has_devolve_delay(building *house, evolve_status status)
197 {
198     if (status == DEVOLVE && house->data.house.devolve_delay < active_devolve_delay) {
199         house->data.house.devolve_delay++;
200         return 1;
201     } else {
202         house->data.house.devolve_delay = 0;
203         return 0;
204     }
205 }
206 
evolve_small_tent(building * house,house_demands * demands)207 static int evolve_small_tent(building *house, house_demands *demands)
208 {
209     if (house->house_population > 0) {
210         building_house_merge(house);
211         evolve_status status = check_requirements(house, demands);
212         if (status == EVOLVE) {
213             building_house_change_to(house, BUILDING_HOUSE_LARGE_TENT);
214         }
215     }
216     return 0;
217 }
218 
evolve_large_tent(building * house,house_demands * demands)219 static int evolve_large_tent(building *house, house_demands *demands)
220 {
221     if (house->house_population > 0) {
222         building_house_merge(house);
223         evolve_status status = check_requirements(house, demands);
224         if (!has_devolve_delay(house, status)) {
225             if (status == EVOLVE) {
226                 building_house_change_to(house, BUILDING_HOUSE_SMALL_SHACK);
227             } else if (status == DEVOLVE) {
228                 building_house_change_to(house, BUILDING_HOUSE_SMALL_TENT);
229             }
230         }
231     }
232     return 0;
233 }
234 
evolve_small_shack(building * house,house_demands * demands)235 static int evolve_small_shack(building *house, house_demands *demands)
236 {
237     building_house_merge(house);
238     int status = check_requirements(house, demands);
239     if (!has_devolve_delay(house, status)) {
240         if (status == EVOLVE) {
241             building_house_change_to(house, BUILDING_HOUSE_LARGE_SHACK);
242         } else if (status == DEVOLVE) {
243             building_house_change_to(house, BUILDING_HOUSE_LARGE_TENT);
244         }
245     }
246     return 0;
247 }
248 
evolve_large_shack(building * house,house_demands * demands)249 static int evolve_large_shack(building *house, house_demands *demands)
250 {
251     building_house_merge(house);
252     int status = check_requirements(house, demands);
253     if (!has_devolve_delay(house, status)) {
254         if (status == EVOLVE) {
255             building_house_change_to(house, BUILDING_HOUSE_SMALL_HOVEL);
256         } else if (status == DEVOLVE) {
257             building_house_change_to(house, BUILDING_HOUSE_SMALL_SHACK);
258         }
259     }
260     return 0;
261 }
262 
evolve_small_hovel(building * house,house_demands * demands)263 static int evolve_small_hovel(building *house, house_demands *demands)
264 {
265     building_house_merge(house);
266     int status = check_requirements(house, demands);
267     if (!has_devolve_delay(house, status)) {
268         if (status == EVOLVE) {
269             building_house_change_to(house, BUILDING_HOUSE_LARGE_HOVEL);
270         } else if (status == DEVOLVE) {
271             building_house_change_to(house, BUILDING_HOUSE_LARGE_SHACK);
272         }
273     }
274     return 0;
275 }
276 
evolve_large_hovel(building * house,house_demands * demands)277 static int evolve_large_hovel(building *house, house_demands *demands)
278 {
279     building_house_merge(house);
280     int status = check_requirements(house, demands);
281     if (!has_devolve_delay(house, status)) {
282         if (status == EVOLVE) {
283             building_house_change_to(house, BUILDING_HOUSE_SMALL_CASA);
284         } else if (status == DEVOLVE) {
285             building_house_change_to(house, BUILDING_HOUSE_SMALL_HOVEL);
286         }
287     }
288     return 0;
289 }
290 
evolve_small_casa(building * house,house_demands * demands)291 static int evolve_small_casa(building *house, house_demands *demands)
292 {
293     building_house_merge(house);
294     int status = check_requirements(house, demands);
295     if (!has_devolve_delay(house, status)) {
296         if (status == EVOLVE) {
297             building_house_change_to(house, BUILDING_HOUSE_LARGE_CASA);
298         } else if (status == DEVOLVE) {
299             building_house_change_to(house, BUILDING_HOUSE_LARGE_HOVEL);
300         }
301     }
302     return 0;
303 }
304 
evolve_large_casa(building * house,house_demands * demands)305 static int evolve_large_casa(building *house, house_demands *demands)
306 {
307     building_house_merge(house);
308     int status = check_requirements(house, demands);
309     if (!has_devolve_delay(house, status)) {
310         if (status == EVOLVE) {
311             building_house_change_to(house, BUILDING_HOUSE_SMALL_INSULA);
312         } else if (status == DEVOLVE) {
313             building_house_change_to(house, BUILDING_HOUSE_SMALL_CASA);
314         }
315     }
316     return 0;
317 }
318 
evolve_small_insula(building * house,house_demands * demands)319 static int evolve_small_insula(building *house, house_demands *demands)
320 {
321     building_house_merge(house);
322     int status = check_requirements(house, demands);
323     if (!has_devolve_delay(house, status)) {
324         if (status == EVOLVE) {
325             building_house_change_to(house, BUILDING_HOUSE_MEDIUM_INSULA);
326         } else if (status == DEVOLVE) {
327             building_house_change_to(house, BUILDING_HOUSE_LARGE_CASA);
328         }
329     }
330     return 0;
331 }
332 
evolve_medium_insula(building * house,house_demands * demands)333 static int evolve_medium_insula(building *house, house_demands *demands)
334 {
335     building_house_merge(house);
336     int status = check_requirements(house, demands);
337     if (!has_devolve_delay(house, status)) {
338         if (status == EVOLVE) {
339             if (building_house_can_expand(house, 4)) {
340                 game_undo_disable();
341                 house->house_is_merged = 0;
342                 building_house_expand_to_large_insula(house);
343                 map_tiles_update_all_gardens();
344                 return 1;
345             }
346         } else if (status == DEVOLVE) {
347             building_house_change_to(house, BUILDING_HOUSE_SMALL_INSULA);
348         }
349     }
350     return 0;
351 }
352 
evolve_large_insula(building * house,house_demands * demands)353 static int evolve_large_insula(building *house, house_demands *demands)
354 {
355     int status = check_requirements(house, demands);
356     if (!has_devolve_delay(house, status)) {
357         if (status == EVOLVE) {
358             building_house_change_to(house, BUILDING_HOUSE_GRAND_INSULA);
359         } else if (status == DEVOLVE) {
360             game_undo_disable();
361             building_house_devolve_from_large_insula(house);
362         }
363     }
364     return 0;
365 }
366 
evolve_grand_insula(building * house,house_demands * demands)367 static int evolve_grand_insula(building *house, house_demands *demands)
368 {
369     int status = check_requirements(house, demands);
370     if (!has_devolve_delay(house, status)) {
371         if (status == EVOLVE) {
372             building_house_change_to(house, BUILDING_HOUSE_SMALL_VILLA);
373         } else if (status == DEVOLVE) {
374             building_house_change_to(house, BUILDING_HOUSE_LARGE_INSULA);
375         }
376     }
377     return 0;
378 }
379 
evolve_small_villa(building * house,house_demands * demands)380 static int evolve_small_villa(building *house, house_demands *demands)
381 {
382     int status = check_requirements(house, demands);
383     if (!has_devolve_delay(house, status)) {
384         if (status == EVOLVE) {
385             building_house_change_to(house, BUILDING_HOUSE_MEDIUM_VILLA);
386         } else if (status == DEVOLVE) {
387             building_house_change_to(house, BUILDING_HOUSE_GRAND_INSULA);
388         }
389     }
390     return 0;
391 }
392 
evolve_medium_villa(building * house,house_demands * demands)393 static int evolve_medium_villa(building *house, house_demands *demands)
394 {
395     int status = check_requirements(house, demands);
396     if (!has_devolve_delay(house, status)) {
397         if (status == EVOLVE) {
398             if (building_house_can_expand(house, 9)) {
399                 game_undo_disable();
400                 building_house_expand_to_large_villa(house);
401                 map_tiles_update_all_gardens();
402                 return 1;
403             }
404         } else if (status == DEVOLVE) {
405             building_house_change_to(house, BUILDING_HOUSE_SMALL_VILLA);
406         }
407     }
408     return 0;
409 }
410 
evolve_large_villa(building * house,house_demands * demands)411 static int evolve_large_villa(building *house, house_demands *demands)
412 {
413     int status = check_requirements(house, demands);
414     if (!has_devolve_delay(house, status)) {
415         if (status == EVOLVE) {
416             building_house_change_to(house, BUILDING_HOUSE_GRAND_VILLA);
417         } else if (status == DEVOLVE) {
418             game_undo_disable();
419             building_house_devolve_from_large_villa(house);
420         }
421     }
422     return 0;
423 }
424 
evolve_grand_villa(building * house,house_demands * demands)425 static int evolve_grand_villa(building *house, house_demands *demands)
426 {
427     int status = check_requirements(house, demands);
428     if (!has_devolve_delay(house, status)) {
429         if (status == EVOLVE) {
430             building_house_change_to(house, BUILDING_HOUSE_SMALL_PALACE);
431         } else if (status == DEVOLVE) {
432             building_house_change_to(house, BUILDING_HOUSE_LARGE_VILLA);
433         }
434     }
435     return 0;
436 }
437 
evolve_small_palace(building * house,house_demands * demands)438 static int evolve_small_palace(building *house, house_demands *demands)
439 {
440     int status = check_requirements(house, demands);
441     if (!has_devolve_delay(house, status)) {
442         if (status == EVOLVE) {
443             building_house_change_to(house, BUILDING_HOUSE_MEDIUM_PALACE);
444         } else if (status == DEVOLVE) {
445             building_house_change_to(house, BUILDING_HOUSE_GRAND_VILLA);
446         }
447     }
448     return 0;
449 }
450 
evolve_medium_palace(building * house,house_demands * demands)451 static int evolve_medium_palace(building *house, house_demands *demands)
452 {
453     int status = check_requirements(house, demands);
454     if (!has_devolve_delay(house, status)) {
455         if (status == EVOLVE) {
456             if (building_house_can_expand(house, 16)) {
457                 game_undo_disable();
458                 building_house_expand_to_large_palace(house);
459                 map_tiles_update_all_gardens();
460                 return 1;
461             }
462         } else if (status == DEVOLVE) {
463             building_house_change_to(house, BUILDING_HOUSE_SMALL_PALACE);
464         }
465     }
466     return 0;
467 }
468 
evolve_large_palace(building * house,house_demands * demands)469 static int evolve_large_palace(building *house, house_demands *demands)
470 {
471     int status = check_requirements(house, demands);
472     if (!has_devolve_delay(house, status)) {
473         if (status == EVOLVE) {
474             building_house_change_to(house, BUILDING_HOUSE_LUXURY_PALACE);
475         } else if (status == DEVOLVE) {
476             game_undo_disable();
477             building_house_devolve_from_large_palace(house);
478         }
479     }
480     return 0;
481 }
482 
evolve_luxury_palace(building * house,house_demands * demands)483 static int evolve_luxury_palace(building *house, house_demands *demands)
484 {
485     int bonus = (int) (building_monument_pantheon_module_is_active(PANTHEON_MODULE_2_HOUSING_EVOLUTION) && house->house_pantheon_access);
486     int status = check_evolve_desirability(house, bonus);
487     if (!has_required_goods_and_services(house, 0, bonus, demands)) {
488         status = DEVOLVE;
489     }
490     if (!has_devolve_delay(house, status) && status == DEVOLVE) {
491         building_house_change_to(house, BUILDING_HOUSE_LARGE_PALACE);
492     }
493     return 0;
494 }
495 
consume_resource(building * b,int inventory,int amount)496 static void consume_resource(building *b, int inventory, int amount)
497 {
498     if (amount > 0) {
499         if (amount > b->data.house.inventory[inventory]) {
500             b->data.house.inventory[inventory] = 0;
501         } else {
502             b->data.house.inventory[inventory] -= amount;
503         }
504     }
505 }
506 
consume_resources(building * b)507 static void consume_resources(building *b)
508 {
509     int consumption_reduction[INVENTORY_MAX] = { 0 };
510 
511     // mercury module 1 - pottery and furniture reduced by 20%
512     if (building_monument_gt_module_is_active(MERCURY_MODULE_1_POTTERY_FURN)) {
513         consumption_reduction[INVENTORY_POTTERY] += 20;
514         consumption_reduction[INVENTORY_FURNITURE] += 20;
515     }
516     // mercury module 2 - oil and wine reduced by 20%
517     if (b->data.house.temple_mercury && building_monument_gt_module_is_active(MERCURY_MODULE_2_OIL_WINE)) {
518         consumption_reduction[INVENTORY_WINE] += 20;
519         consumption_reduction[INVENTORY_OIL] += 20;
520     }
521     // mars module 2 - all goods reduced by 10%
522     if (b->data.house.temple_mars && building_monument_gt_module_is_active(MARS_MODULE_2_ALL_GOODS)) {
523         consumption_reduction[INVENTORY_WINE] += 10;
524         consumption_reduction[INVENTORY_OIL] += 10;
525         consumption_reduction[INVENTORY_POTTERY] += 10;
526         consumption_reduction[INVENTORY_FURNITURE] += 10;
527     }
528 
529     for (inventory_type inventory = INVENTORY_MIN_GOOD; inventory < INVENTORY_MAX_GOOD; inventory++) {
530         if (!consumption_reduction[inventory] ||
531             (game_time_total_months() % (100 / consumption_reduction[inventory]))) {
532             consume_resource(b, inventory, model_house_uses_inventory(b->subtype.house_level, inventory));
533         }
534     }
535 }
536 
537 static int (*evolve_callback[])(building *, house_demands *) = {
538     evolve_small_tent, evolve_large_tent, evolve_small_shack, evolve_large_shack,
539     evolve_small_hovel, evolve_large_hovel, evolve_small_casa, evolve_large_casa,
540     evolve_small_insula, evolve_medium_insula, evolve_large_insula, evolve_grand_insula,
541     evolve_small_villa, evolve_medium_villa, evolve_large_villa, evolve_grand_villa,
542     evolve_small_palace, evolve_medium_palace, evolve_large_palace, evolve_luxury_palace
543 };
544 
building_house_process_evolve_and_consume_goods(void)545 void building_house_process_evolve_and_consume_goods(void)
546 {
547     city_houses_reset_demands();
548     house_demands *demands = city_houses_demands();
549     int has_expanded = 0;
550 
551     if (building_monument_working(BUILDING_GRAND_TEMPLE_VENUS)) {
552         active_devolve_delay = DEVOLVE_DELAY_WITH_VENUS;
553     } else {
554         active_devolve_delay = DEVOLVE_DELAY;
555     }
556 
557     time_millis last_update = time_get_millis();
558 
559     for (building_type type = BUILDING_HOUSE_VACANT_LOT; type <= BUILDING_HOUSE_LUXURY_PALACE; type++) {
560         building *next_of_type = 0; // evolve_callback changes the building type
561         for (building *b = building_first_of_type(type); b; b = next_of_type) {
562             next_of_type = b->next_of_type;
563             if (b->state != BUILDING_STATE_IN_USE || b->last_update == last_update) {
564                 continue;
565             }
566             building_house_check_for_corruption(b);
567             has_expanded |= evolve_callback[b->type - BUILDING_HOUSE_VACANT_LOT](b, demands);
568             if (game_time_day() == 0 || game_time_day() == 7) {
569                 consume_resources(b);
570             }
571             b->last_update = last_update;
572         }
573     }
574     if (has_expanded) {
575         map_routing_update_land();
576     }
577 }
578 
building_house_determine_evolve_text(building * house,int worst_desirability_building)579 void building_house_determine_evolve_text(building *house, int worst_desirability_building)
580 {
581     int level = house->subtype.house_level;
582     if (building_monument_pantheon_module_is_active(PANTHEON_MODULE_2_HOUSING_EVOLUTION) && house->house_pantheon_access) {
583         level--;
584     }
585     level = calc_bound(level, HOUSE_MIN, HOUSE_MAX);
586 
587     // this house will devolve soon because...
588 
589     const model_house *model = model_get_house(level);
590     // desirability
591     if (house->desirability <= model->devolve_desirability) {
592         house->data.house.evolve_text_id = 0;
593         return;
594     }
595     // water
596     int water = model->water;
597     if (water == 1 && !house->has_water_access && !house->has_well_access) {
598         house->data.house.evolve_text_id = 1;
599         return;
600     }
601     if (water == 2 && !house->has_water_access) {
602         house->data.house.evolve_text_id = 2;
603         return;
604     }
605     // entertainment
606     int entertainment = model->entertainment;
607     if (house->data.house.entertainment < entertainment) {
608         if (!house->data.house.entertainment) {
609             house->data.house.evolve_text_id = 3;
610         } else if (entertainment < 10) {
611             house->data.house.evolve_text_id = 4;
612         } else if (entertainment < 25) {
613             house->data.house.evolve_text_id = 5;
614         } else if (entertainment < 50) {
615             house->data.house.evolve_text_id = 6;
616         } else if (entertainment < 80) {
617             house->data.house.evolve_text_id = 7;
618         } else {
619             house->data.house.evolve_text_id = 8;
620         }
621         return;
622     }
623     // food types
624     int foodtypes_required = model->food_types;
625     int foodtypes_available = 0;
626     for (int i = INVENTORY_MIN_FOOD; i < INVENTORY_MAX_FOOD; i++) {
627         if (house->data.house.inventory[i]) {
628             foodtypes_available++;
629         }
630     }
631     if (foodtypes_available < foodtypes_required) {
632         if (foodtypes_required == 1) {
633             house->data.house.evolve_text_id = 9;
634             return;
635         } else if (foodtypes_required == 2) {
636             house->data.house.evolve_text_id = 10;
637             return;
638         } else if (foodtypes_required == 3) {
639             house->data.house.evolve_text_id = 11;
640             return;
641         }
642     }
643     // education
644     int education = model->education;
645     if (house->data.house.education < education) {
646         if (education == 1) {
647             house->data.house.evolve_text_id = 14;
648             return;
649         } else if (education == 2) {
650             if (house->data.house.school) {
651                 house->data.house.evolve_text_id = 15;
652                 return;
653             } else if (house->data.house.library) {
654                 house->data.house.evolve_text_id = 16;
655                 return;
656             }
657         } else if (education == 3) {
658             house->data.house.evolve_text_id = 17;
659             return;
660         }
661     }
662     // bathhouse
663     if (house->data.house.bathhouse < model->bathhouse) {
664         house->data.house.evolve_text_id = 18;
665         return;
666     }
667     // pottery
668     if (house->data.house.inventory[INVENTORY_POTTERY] < model->pottery) {
669         house->data.house.evolve_text_id = 19;
670         return;
671     }
672     // religion
673     int religion = model->religion;
674     if (house->data.house.num_gods < religion) {
675         if (religion == 1) {
676             house->data.house.evolve_text_id = 20;
677             return;
678         } else if (religion == 2) {
679             house->data.house.evolve_text_id = 21;
680             return;
681         } else if (religion == 3) {
682             house->data.house.evolve_text_id = 22;
683             return;
684         }
685     }
686     // barber
687     if (house->data.house.barber < model->barber) {
688         house->data.house.evolve_text_id = 23;
689         return;
690     }
691     // health
692     int health = model->health;
693     if (house->data.house.health < health) {
694         if (health == 1) {
695             house->data.house.evolve_text_id = 24;
696         } else if (house->data.house.clinic) {
697             house->data.house.evolve_text_id = 25;
698         } else {
699             house->data.house.evolve_text_id = 26;
700         }
701         return;
702     }
703     // oil
704     if (house->data.house.inventory[INVENTORY_OIL] < model->oil) {
705         house->data.house.evolve_text_id = 27;
706         return;
707     }
708     // furniture
709     if (house->data.house.inventory[INVENTORY_FURNITURE] < model->furniture) {
710         house->data.house.evolve_text_id = 28;
711         return;
712     }
713     // wine
714     int wine = model->wine;
715     if (house->data.house.inventory[INVENTORY_WINE] < wine) {
716         house->data.house.evolve_text_id = 29;
717         return;
718     }
719     if (wine > 1 && !city_resource_multiple_wine_available()) {
720         house->data.house.evolve_text_id = 65;
721         return;
722     }
723     if (level >= HOUSE_LUXURY_PALACE) { // max level!
724         house->data.house.evolve_text_id = 60;
725         return;
726     }
727 
728     // this house will evolve if ...
729 
730     // desirability
731     if (house->desirability < model->evolve_desirability) {
732         if (worst_desirability_building) {
733             house->data.house.evolve_text_id = 62;
734         } else {
735             house->data.house.evolve_text_id = 30;
736         }
737         return;
738     }
739     model = model_get_house(++level);
740     // water
741     water = model->water;
742     if (water == 1 && !house->has_water_access && !house->has_well_access) {
743         house->data.house.evolve_text_id = 31;
744         return;
745     }
746     if (water == 2 && !house->has_water_access) {
747         house->data.house.evolve_text_id = 32;
748         return;
749     }
750     // entertainment
751     entertainment = model->entertainment;
752     if (house->data.house.entertainment < entertainment) {
753         if (!house->data.house.entertainment) {
754             house->data.house.evolve_text_id = 33;
755         } else if (entertainment < 10) {
756             house->data.house.evolve_text_id = 34;
757         } else if (entertainment < 25) {
758             house->data.house.evolve_text_id = 35;
759         } else if (entertainment < 50) {
760             house->data.house.evolve_text_id = 36;
761         } else if (entertainment < 80) {
762             house->data.house.evolve_text_id = 37;
763         } else {
764             house->data.house.evolve_text_id = 38;
765         }
766         return;
767     }
768     // food types
769     foodtypes_required = model->food_types;
770     if (foodtypes_available < foodtypes_required) {
771         if (foodtypes_required == 1) {
772             house->data.house.evolve_text_id = 39;
773             return;
774         } else if (foodtypes_required == 2) {
775             house->data.house.evolve_text_id = 40;
776             return;
777         } else if (foodtypes_required == 3) {
778             house->data.house.evolve_text_id = 41;
779             return;
780         }
781     }
782     // education
783     education = model->education;
784     if (house->data.house.education < education) {
785         if (education == 1) {
786             house->data.house.evolve_text_id = 44;
787             return;
788         } else if (education == 2) {
789             if (house->data.house.school) {
790                 house->data.house.evolve_text_id = 45;
791                 return;
792             } else if (house->data.house.library) {
793                 house->data.house.evolve_text_id = 46;
794                 return;
795             }
796         } else if (education == 3) {
797             house->data.house.evolve_text_id = 47;
798             return;
799         }
800     }
801     // bathhouse
802     if (house->data.house.bathhouse < model->bathhouse) {
803         house->data.house.evolve_text_id = 48;
804         return;
805     }
806     // pottery
807     if (house->data.house.inventory[INVENTORY_POTTERY] < model->pottery) {
808         house->data.house.evolve_text_id = 49;
809         return;
810     }
811     // religion
812     religion = model->religion;
813     if (house->data.house.num_gods < religion) {
814         if (religion == 1) {
815             house->data.house.evolve_text_id = 50;
816             return;
817         } else if (religion == 2) {
818             house->data.house.evolve_text_id = 51;
819             return;
820         } else if (religion == 3) {
821             house->data.house.evolve_text_id = 52;
822             return;
823         }
824     }
825     // barber
826     if (house->data.house.barber < model->barber) {
827         house->data.house.evolve_text_id = 53;
828         return;
829     }
830     // health
831     health = model->health;
832     if (house->data.house.health < health) {
833         if (health == 1) {
834             house->data.house.evolve_text_id = 54;
835         } else if (house->data.house.clinic) {
836             house->data.house.evolve_text_id = 55;
837         } else {
838             house->data.house.evolve_text_id = 56;
839         }
840         return;
841     }
842     // oil
843     if (house->data.house.inventory[INVENTORY_OIL] < model->oil) {
844         house->data.house.evolve_text_id = 57;
845         return;
846     }
847     // furniture
848     if (house->data.house.inventory[INVENTORY_FURNITURE] < model->furniture) {
849         house->data.house.evolve_text_id = 58;
850         return;
851     }
852     // wine
853     wine = model->wine;
854     if (house->data.house.inventory[INVENTORY_WINE] < wine) {
855         house->data.house.evolve_text_id = 59;
856         return;
857     }
858     if (wine > 1 && !city_resource_multiple_wine_available()) {
859         house->data.house.evolve_text_id = 66;
860         return;
861     }
862     // house is evolving
863     house->data.house.evolve_text_id = 61;
864     if (house->data.house.no_space_to_expand == 1) {
865         // house would like to evolve but can't
866         house->data.house.evolve_text_id = 64;
867     }
868 }
869 
building_house_determine_worst_desirability_building(const building * house)870 int building_house_determine_worst_desirability_building(const building *house)
871 {
872     int lowest_desirability = 0;
873     int lowest_building_id = 0;
874     int x_min, y_min, x_max, y_max;
875     map_grid_get_area(house->x, house->y, 1, 6, &x_min, &y_min, &x_max, &y_max);
876 
877     for (int y = y_min; y <= y_max; y++) {
878         for (int x = x_min; x <= x_max; x++) {
879             int building_id = map_building_at(map_grid_offset(x, y));
880             if (building_id <= 0) {
881                 continue;
882             }
883             building *b = building_get(building_id);
884             if (b->state != BUILDING_STATE_IN_USE || building_id == house->id) {
885                 continue;
886             }
887             if (!b->house_size || b->type < house->type) {
888                 int des = model_get_building(b->type)->desirability_value;
889                 if (des < 0) {
890                     // simplified desirability calculation
891                     int step_size = model_get_building(b->type)->desirability_step_size;
892                     int range = model_get_building(b->type)->desirability_range;
893                     int dist = calc_maximum_distance(x, y, house->x, house->y);
894                     if (dist <= range) {
895                         while (--dist > 1) {
896                             des += step_size;
897                         }
898                         if (des < lowest_desirability) {
899                             lowest_desirability = des;
900                             lowest_building_id = building_id;
901                         }
902                     }
903                 }
904             }
905         }
906     }
907     return lowest_building_id;
908 }
909