1 /*
2 * Copyright (c) 1997 - 2001 Hj. Malthaner
3 *
4 * This file is part of the Simutrans project under the artistic license.
5 * (see license.txt)
6 *
7 * construction of cities, creation of passengers
8 *
9 */
10
11 #include <string>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <math.h>
16
17 #include "boden/wege/strasse.h"
18 #include "boden/grund.h"
19 #include "boden/boden.h"
20 #include "gui/simwin.h"
21 #include "simworld.h"
22 #include "simware.h"
23 #include "player/simplay.h"
24 #include "simplan.h"
25 #include "display/simimg.h"
26 #include "vehicle/simroadtraffic.h"
27 #include "simhalt.h"
28 #include "simfab.h"
29 #include "simcity.h"
30 #include "simmesg.h"
31 #include "simcolor.h"
32
33 #include "gui/minimap.h"
34 #include "gui/city_info.h"
35
36 #include "descriptor/building_desc.h"
37
38 #include "simintr.h"
39 #include "simdebug.h"
40
41 #include "obj/gebaeude.h"
42
43 #include "dataobj/translator.h"
44 #include "dataobj/settings.h"
45 #include "dataobj/loadsave.h"
46 #include "dataobj/tabfile.h"
47 #include "dataobj/environment.h"
48
49 #include "finder/building_placefinder.h"
50 #include "bauer/wegbauer.h"
51 #include "bauer/brueckenbauer.h"
52 #include "bauer/hausbauer.h"
53 #include "bauer/fabrikbauer.h"
54 #include "utils/cbuffer_t.h"
55 #include "utils/simrandom.h"
56 #include "utils/simstring.h"
57
58
59 #define PACKET_SIZE (7)
60
61 /**
62 * This variable is used to control the fractional precision of growth to prevent loss when quantities are small.
63 * Growth calculations use 64 bit signed integers.
64 * Although this is actually scale factor, a power of two is recommended for optimization purposes.
65 */
66 static sint64 const CITYGROWTH_PER_CITICEN = 1ll << 32; // Q31.32 fractional form.
67
68 karte_ptr_t stadt_t::welt; // one is enough ...
69
70
71 /********************************* From here on cityrules stuff *****************************************/
72
73
74 /**
75 * in this fixed interval, construction will happen
76 * 21s = 21000 per house
77 */
78 const uint32 stadt_t::city_growth_step = 21000;
79
80 /**
81 * this is the default factor to prefer clustering
82 */
83 uint32 stadt_t::cluster_factor = 10;
84
85 /*
86 * chance to do renovation instead new building (in percent)
87 * @author prissi
88 */
89 static uint32 renovation_percentage = 12;
90
91 /*
92 * minimum ratio of city area to building area to allow expansion
93 * the higher this value, the slower the city expansion if there are still "holes"
94 * @author prissi
95 */
96 static uint32 min_building_density = 25;
97
98 // the following are the scores for the different building types
99 static sint16 ind_start_score = 0;
100 static sint16 com_start_score = -10;
101 static sint16 res_start_score = 0;
102
103 // order: res, com, ind
104 static sint16 ind_neighbour_score[] = { -8, 0, 8 };
105 static sint16 com_neighbour_score[] = { 1, 8, 1 };
106 static sint16 res_neighbour_score[] = { 8, 0, -8 };
107
108 /**
109 * Rule data structure
110 * maximum 7x7 rules
111 * @author Hj. Malthaner
112 */
113 class rule_entry_t {
114 public:
115 uint8 x,y;
116 char flag;
rule_entry_t(uint8 x_=0,uint8 y_=0,char f_='.')117 rule_entry_t(uint8 x_=0, uint8 y_=0, char f_='.') : x(x_), y(y_), flag(f_) {}
118
rdwr(loadsave_t * file)119 void rdwr(loadsave_t* file)
120 {
121 file->rdwr_byte(x);
122 file->rdwr_byte(y);
123 uint8 c = flag;
124 file->rdwr_byte(c);
125 flag = c;
126 }
127 };
128
129 class rule_t {
130 public:
131 sint16 chance;
132 vector_tpl<rule_entry_t> rule;
rule_t(uint32 count=0)133 rule_t(uint32 count=0) : chance(0), rule(count) {}
134
rdwr(loadsave_t * file)135 void rdwr(loadsave_t* file)
136 {
137 file->rdwr_short(chance);
138
139 if (file->is_loading()) {
140 rule.clear();
141 }
142 uint32 count = rule.get_count();
143 file->rdwr_long(count);
144 for(uint32 i=0; i<count; i++) {
145 if (file->is_loading()) {
146 rule.append(rule_entry_t());
147 }
148 rule[i].rdwr(file);
149 }
150 }
151 };
152
153 // house rules
154 static vector_tpl<rule_t *> house_rules;
155
156 // and road rules
157 static vector_tpl<rule_t *> road_rules;
158
159 /**
160 * Symbols in rules:
161 * S = not a road
162 * s = is a road
163 * n = is nature/empty
164 * H = not a house
165 * h = is a house
166 * T = not a stop // added in 88.03.3
167 * t = is a stop // added in 88.03.3
168 * u = good slope for way
169 * U = not a slope for ways
170 * . = beliebig
171 */
172
173 // here '.' is ignored, since it will not be tested anyway
174 static char const* const allowed_chars_in_rule = "SsnHhTtUu";
175
176 /*
177 * @param pos position to check
178 * @param regel the rule to evaluate
179 * @return true on match, false otherwise
180 * @author Hj. Malthaner
181 */
bewerte_loc(const koord pos,const rule_t & regel,int rotation)182 bool stadt_t::bewerte_loc(const koord pos, const rule_t ®el, int rotation)
183 {
184 //printf("Test for (%s) in rotation %d\n", pos.get_str(), rotation);
185 koord k;
186
187 FOR(vector_tpl<rule_entry_t>, const& r, regel.rule) {
188 uint8 x,y;
189 switch (rotation) {
190 default:
191 case 0: x=r.x; y=r.y; break;
192 case 90: x=r.y; y=6-r.x; break;
193 case 180: x=6-r.x; y=6-r.y; break;
194 case 270: x=6-r.y; y=r.x; break;
195 }
196
197 const koord k(pos.x+x-3, pos.y+y-3);
198 const grund_t* gr = welt->lookup_kartenboden(k);
199 if (gr == NULL) {
200 // outside of the map => cannot apply this rule
201 return false;
202 }
203 switch (r.flag) {
204 case 's':
205 // road?
206 if (!gr->hat_weg(road_wt)) return false;
207 break;
208 case 'S':
209 // not road?
210 if (gr->hat_weg(road_wt)) return false;
211 break;
212 case 'h':
213 // is house
214 if (gr->get_typ() != grund_t::fundament || gr->obj_bei(0)->get_typ()!=obj_t::gebaeude) return false;
215 break;
216 case 'H':
217 // no house
218 if (gr->get_typ() == grund_t::fundament) return false;
219 break;
220 case 'n':
221 // nature/empty
222 if (!gr->ist_natur() || gr->kann_alle_obj_entfernen(NULL) != NULL) return false;
223 break;
224 case 'U':
225 // unbuildable for road
226 if (!slope_t::is_way(gr->get_grund_hang())) return false;
227 break;
228 case 'u':
229 // road may be buildable
230 if (slope_t::is_way(gr->get_grund_hang())) return false;
231 break;
232 case 't':
233 // here is a stop/extension building
234 if (!gr->is_halt()) return false;
235 break;
236 case 'T':
237 // no stop
238 if (gr->is_halt()) return false;
239 break;
240 default: ;
241 // ignore
242 }
243 }
244 return true;
245 }
246
247
248 /**
249 * Check rule in all transformations at given position
250 * prissi: but the rules should explicitly forbid building then?!?
251 * @author Hj. Malthaner
252 */
bewerte_pos(const koord pos,const rule_t & regel)253 sint32 stadt_t::bewerte_pos(const koord pos, const rule_t ®el)
254 {
255 // will be called only a single time, so we can stop after a single match
256 if(bewerte_loc(pos, regel, 0) ||
257 bewerte_loc(pos, regel, 90) ||
258 bewerte_loc(pos, regel, 180) ||
259 bewerte_loc(pos, regel, 270)) {
260 return 1;
261 }
262 return 0;
263 }
264
265
bewerte_strasse(koord k,sint32 rd,const rule_t & regel)266 void stadt_t::bewerte_strasse(koord k, sint32 rd, const rule_t ®el)
267 {
268 if (simrand(rd) == 0) {
269 best_strasse.check(k, bewerte_pos(k, regel));
270 }
271 }
272
273
bewerte_haus(koord k,sint32 rd,const rule_t & regel)274 void stadt_t::bewerte_haus(koord k, sint32 rd, const rule_t ®el)
275 {
276 if (simrand(rd) == 0) {
277 best_haus.check(k, bewerte_pos(k, regel));
278 }
279 }
280
281
282 /**
283 * Reads city configuration data
284 * @author Hj. Malthaner
285 */
cityrules_init(const std::string & objfilename)286 bool stadt_t::cityrules_init(const std::string &objfilename)
287 {
288 tabfile_t cityconf;
289 // first take user data, then user global data
290 const std::string user_dir=env_t::user_dir;
291 if (!cityconf.open((user_dir+"cityrules.tab").c_str())) {
292 if (!cityconf.open((objfilename+"config/cityrules.tab").c_str())) {
293 dbg->fatal("stadt_t::init()", "Can't read cityrules.tab" );
294 return false;
295 }
296 }
297
298 tabfileobj_t contents;
299 cityconf.read(contents);
300
301 char buf[128];
302
303 cluster_factor = (uint32)contents.get_int("cluster_factor", 10);
304 renovation_percentage = (uint32)contents.get_int("renovation_percentage", 25);
305 // to keep compatible with the typo, here both are ok
306 min_building_density = (uint32)contents.get_int("minimum_building_desity", 25);
307 min_building_density = (uint32)contents.get_int("minimum_building_density", min_building_density);
308
309 // init the building value tables
310 ind_start_score = contents.get_int("ind_start_score", 0);
311 ind_neighbour_score[0] = contents.get_int("ind_near_res", -8);
312 ind_neighbour_score[1] = contents.get_int("ind_near_com", 0);
313 ind_neighbour_score[2] = contents.get_int("ind_near_ind", 8);
314
315 com_start_score = contents.get_int("com_start_score", -10);
316 com_neighbour_score[0] = contents.get_int("com_near_res", 1);
317 com_neighbour_score[1] = contents.get_int("com_near_com", 8);
318 com_neighbour_score[2] = contents.get_int("com_near_ind", 1);
319
320 res_start_score = contents.get_int("res_start_score", 0);
321 res_neighbour_score[0] = contents.get_int("res_near_res", 8);
322 res_neighbour_score[1] = contents.get_int("res_near_com", 0);
323 res_neighbour_score[2] = contents.get_int("res_near_ind", -8);
324
325 uint32 num_house_rules = 0;
326 for (;;) {
327 sprintf(buf, "house_%d", num_house_rules + 1);
328 if (contents.get_string(buf, 0)) {
329 num_house_rules++;
330 } else {
331 break;
332 }
333 }
334 DBG_MESSAGE("stadt_t::init()", "Read %d house building rules", num_house_rules);
335
336 uint32 num_road_rules = 0;
337 for (;;) {
338 sprintf(buf, "road_%d", num_road_rules + 1);
339 if (contents.get_string(buf, 0)) {
340 num_road_rules++;
341 } else {
342 break;
343 }
344 }
345 DBG_MESSAGE("stadt_t::init()", "Read %d road building rules", num_road_rules);
346
347 clear_ptr_vector( house_rules );
348 for (uint32 i = 0; i < num_house_rules; i++) {
349 house_rules.append(new rule_t());
350 sprintf(buf, "house_%d.chance", i + 1);
351 house_rules[i]->chance = contents.get_int(buf, 0);
352
353 sprintf(buf, "house_%d", i + 1);
354 const char* rule = contents.get_string(buf, "");
355
356 // skip leading spaces (use . for padding)
357 while (*rule == ' ') {
358 rule++;
359 }
360
361 // find out rule size
362 size_t size = 0;
363 size_t maxlen = strlen(rule);
364 while (size < maxlen && rule[size]!=' ') {
365 size++;
366 }
367
368 if (size > 7 || maxlen < size * (size + 1) - 1 || (size & 1) == 0 || size <= 2 ) {
369 dbg->fatal("stadt_t::cityrules_init()", "house rule %d has bad format!", i + 1);
370 }
371
372 // put rule into memory
373 const uint8 offset = (7 - (uint)size) / 2;
374 for (uint y = 0; y < size; y++) {
375 for (uint x = 0; x < size; x++) {
376 const char flag = rule[x + y * (size + 1)];
377 // check for allowed characters; ignore '.';
378 // leave midpoint out, should be 'n', which is checked in build() anyway
379 if ((x+offset!=3 || y+offset!=3) && (flag!=0 && strchr(allowed_chars_in_rule, flag))) {
380 house_rules[i]->rule.append(rule_entry_t(x+offset,y+offset,flag));
381 }
382 else {
383 if ((x+offset!=3 || y+offset!=3) && flag!='.') {
384 dbg->warning("stadt_t::cityrules_init()", "house rule %d entry (%d,%d) is '%c' and will be ignored", i + 1, x+offset, y+offset, flag);
385 }
386 }
387 }
388 }
389 }
390
391 clear_ptr_vector( road_rules );
392 for (uint32 i = 0; i < num_road_rules; i++) {
393 road_rules.append(new rule_t());
394 sprintf(buf, "road_%d.chance", i + 1);
395 road_rules[i]->chance = contents.get_int(buf, 0);
396
397 sprintf(buf, "road_%d", i + 1);
398 const char* rule = contents.get_string(buf, "");
399
400 // skip leading spaces (use . for padding)
401 while (*rule == ' ') {
402 rule++;
403 }
404
405 // find out rule size
406 size_t size = 0;
407 size_t maxlen = strlen(rule);
408 while (size < maxlen && rule[size] != ' ') {
409 size++;
410 }
411
412 if ( size > 7 || maxlen < size * (size + 1) - 1 || (size & 1) == 0 || size <= 2 ) {
413 dbg->fatal("stadt_t::cityrules_init()", "road rule %d has bad format!", i + 1);
414 }
415
416 // put rule into memory
417 const uint8 offset = (7 - (uint)size) / 2;
418 for (uint y = 0; y < size; y++) {
419 for (uint x = 0; x < size; x++) {
420 const char flag = rule[x + y * (size + 1)];
421 // check for allowed characters; ignore '.';
422 // leave midpoint out, should be 'n', which is checked in build() anyway
423 if ((x+offset!=3 || y+offset!=3) && (flag!=0 && strchr(allowed_chars_in_rule, flag))) {
424 road_rules[i]->rule.append(rule_entry_t(x+offset,y+offset,flag));
425 }
426 else {
427 if ((x+offset!=3 || y+offset!=3) && flag!='.') {
428 dbg->warning("stadt_t::cityrules_init()", "road rule %d entry (%d,%d) is '%c' and will be ignored", i + 1, x+offset, y+offset, flag);
429 }
430 }
431 }
432 }
433 }
434 return true;
435 }
436
437 /**
438 * Reads/writes city configuration data from/to a savegame
439 * called from karte_t::speichern and karte_t::laden
440 * only written for networkgames
441 * @author Dwachs
442 */
cityrules_rdwr(loadsave_t * file)443 void stadt_t::cityrules_rdwr(loadsave_t *file)
444 {
445 if( file->is_version_atleast(112, 8) ) {
446 file->rdwr_long( cluster_factor );
447 }
448
449 file->rdwr_long(renovation_percentage);
450 file->rdwr_long(min_building_density);
451
452 file->rdwr_short(ind_start_score);
453 file->rdwr_short(ind_neighbour_score[0]);
454 file->rdwr_short(ind_neighbour_score[1]);
455 file->rdwr_short(ind_neighbour_score[2]);
456
457 file->rdwr_short(com_start_score);
458 file->rdwr_short(com_neighbour_score[0]);
459 file->rdwr_short(com_neighbour_score[1]);
460 file->rdwr_short(com_neighbour_score[2]);
461
462 file->rdwr_short(res_start_score);
463 file->rdwr_short(res_neighbour_score[0]);
464 file->rdwr_short(res_neighbour_score[1]);
465 file->rdwr_short(res_neighbour_score[2]);
466
467 // house rules
468 if (file->is_loading()) {
469 clear_ptr_vector( house_rules );
470 }
471 uint32 count = house_rules.get_count();
472 file->rdwr_long(count);
473 for(uint32 i=0; i<count; i++) {
474 if (file->is_loading()) {
475 house_rules.append(new rule_t());
476 }
477 house_rules[i]->rdwr(file);
478 }
479 // road rules
480 if (file->is_loading()) {
481 clear_ptr_vector( road_rules );
482 }
483 count = road_rules.get_count();
484 file->rdwr_long(count);
485 for(uint32 i=0; i<count; i++) {
486 if (file->is_loading()) {
487 road_rules.append(new rule_t());
488 }
489 road_rules[i]->rdwr(file);
490 }
491 }
492
493 /**
494 * monument_placefinder_t:
495 *
496 * Search a free place for a monument building
497 * Im Gegensatz zum building_placefinder_t werden Strassen auf den Raendern
498 * toleriert.
499 *
500 * 22-Dec-02: Hajo: added safety checks for gr != 0 and plan != 0
501 *
502 * @author V. Meyer
503 */
504 class monument_placefinder_t : public placefinder_t {
505 public:
monument_placefinder_t(karte_t * welt,sint16 radius)506 monument_placefinder_t(karte_t* welt, sint16 radius) : placefinder_t(welt, radius) {}
507
is_tile_ok(koord pos,koord d,climate_bits cl) const508 bool is_tile_ok(koord pos, koord d, climate_bits cl) const OVERRIDE
509 {
510 const planquadrat_t* plan = welt->access(pos + d);
511
512 // Hajo: can't build here
513 if (plan == NULL) {
514 return false;
515 }
516
517 const grund_t* gr = plan->get_kartenboden();
518 if( ((1 << welt->get_climate( gr->get_pos().get_2d() )) & cl) == 0 ) {
519 return false;
520 }
521
522 if (is_boundary_tile(d)) {
523 return
524 gr->get_grund_hang() == slope_t::flat && // Flat
525 gr->get_typ() == grund_t::boden && // Boden -> no building
526 (!gr->hat_wege() || gr->hat_weg(road_wt)) && // only roads
527 gr->kann_alle_obj_entfernen(NULL) == NULL; // Irgendwas verbaut den Platz?
528 }
529 else {
530 return
531 gr->get_grund_hang() == slope_t::flat &&
532 gr->get_typ() == grund_t::boden &&
533 gr->ist_natur() && // No way here
534 gr->kann_alle_obj_entfernen(NULL) == NULL; // Irgendwas verbaut den Platz?
535 }
536 }
537 };
538
539
540 /**
541 * townhall_placefinder_t:
542 *
543 * 22-Dec-02: Hajo: added safety checks for gr != 0 and plan != 0
544 *
545 * @author V. Meyer
546 */
547 class townhall_placefinder_t : public placefinder_t {
548 public:
townhall_placefinder_t(karte_t * welt,uint8 dir_)549 townhall_placefinder_t(karte_t* welt, uint8 dir_) : placefinder_t(welt), dir(dir_) {}
550
is_tile_ok(koord pos,koord d,climate_bits cl) const551 bool is_tile_ok(koord pos, koord d, climate_bits cl) const OVERRIDE
552 {
553 const grund_t* gr = welt->lookup_kartenboden(pos + d);
554 if (gr == NULL || gr->get_grund_hang() != slope_t::flat) {
555 return false;
556 }
557
558 if( ((1 << welt->get_climate( gr->get_pos().get_2d() )) & cl) == 0 ) {
559 return false;
560 }
561
562 if (d.x > 0 || d.y > 0) {
563 if (welt->lookup_kartenboden(pos)->get_hoehe() != gr->get_hoehe()) {
564 // height wrong!
565 return false;
566 }
567 }
568
569 if ( ((dir & ribi_t::south)!=0 && d.y == h - 1) ||
570 ((dir & ribi_t::west)!=0 && d.x == 0) ||
571 ((dir & ribi_t::north)!=0 && d.y == 0) ||
572 ((dir & ribi_t::east)!=0 && d.x == w - 1)) {
573 // we want to build a road here:
574 return
575 gr->get_typ() == grund_t::boden &&
576 (!gr->hat_wege() || (gr->hat_weg(road_wt) && !gr->has_two_ways())) && // build only on roads, no other ways
577 !gr->is_halt() &&
578 gr->kann_alle_obj_entfernen(NULL) == NULL;
579 } else {
580 // we want to build the townhall here: maybe replace existing buildings
581 return ((gr->get_typ()==grund_t::boden && gr->ist_natur()) || gr->get_typ()==grund_t::fundament) &&
582 gr->kann_alle_obj_entfernen(NULL) == NULL;
583 }
584 }
585 private:
586 uint8 dir;
587 };
588
589
compare_gebaeude_pos(const gebaeude_t * a,const gebaeude_t * b)590 static bool compare_gebaeude_pos(const gebaeude_t* a, const gebaeude_t* b)
591 {
592 const uint32 pos_a = (a->get_pos().y<<16)+a->get_pos().x;
593 const uint32 pos_b = (b->get_pos().y<<16)+b->get_pos().x;
594 return pos_a<pos_b;
595 }
596
597
598 // this function adds houses to the city house list
add_gebaeude_to_stadt(const gebaeude_t * gb,bool ordered)599 void stadt_t::add_gebaeude_to_stadt(const gebaeude_t* gb, bool ordered)
600 {
601 if (gb != NULL) {
602 const building_tile_desc_t* tile = gb->get_tile();
603 koord size = tile->get_desc()->get_size(tile->get_layout());
604 const koord pos = gb->get_pos().get_2d() - tile->get_offset();
605 koord k;
606
607 // add all tiles
608 for (k.y = 0; k.y < size.y; k.y++) {
609 for (k.x = 0; k.x < size.x; k.x++) {
610 if (gebaeude_t* const add_gb = obj_cast<gebaeude_t>(welt->lookup_kartenboden(pos + k)->first_obj())) {
611 if (gb->is_same_building(add_gb)) {
612
613 if( ordered ) {
614 buildings.insert_ordered(add_gb, tile->get_desc()->get_level() + 1, compare_gebaeude_pos);
615 }
616 else {
617 buildings.append(add_gb, tile->get_desc()->get_level() + 1);
618 }
619
620 add_gb->set_stadt(this);
621 if (add_gb->get_tile()->get_desc()->is_townhall()) {
622 has_townhall = true;
623 }
624 }
625 else {
626 // found tile of another building, ignore it
627 }
628 }
629 }
630 }
631 // no update of city limits
632 // as has_low_density may depend on the order the buildings list is filled
633 if (!ordered) {
634 // check borders
635 pruefe_grenzen(pos);
636 if(size!=koord(1,1)) {
637 pruefe_grenzen(pos+size-koord(1,1));
638 }
639 }
640 }
641 }
642
643
644 // this function removes houses from the city house list
remove_gebaeude_from_stadt(gebaeude_t * gb)645 void stadt_t::remove_gebaeude_from_stadt(gebaeude_t* gb)
646 {
647 buildings.remove(gb);
648 gb->set_stadt(NULL);
649 recalc_city_size();
650 }
651
652
653 // just updates the weight count of this building (after a renovation)
update_gebaeude_from_stadt(gebaeude_t * gb)654 void stadt_t::update_gebaeude_from_stadt(gebaeude_t* gb)
655 {
656 buildings.remove(gb);
657 buildings.append(gb, gb->get_tile()->get_desc()->get_level() + 1);
658 }
659
660
pruefe_grenzen(koord k)661 void stadt_t::pruefe_grenzen(koord k)
662 {
663 // WARNING: do not call this during multithreaded loading,
664 // as has_low_density may depend on the order the buildings list is filled
665 if( has_low_density ) {
666 // has extra wide borders => change density calculation
667 has_low_density = (buildings.get_count()<10 || (buildings.get_count()*100l)/(abs(ur.x-lo.x-4)*abs(ur.y-lo.y-4)+1) > min_building_density);
668 if(!has_low_density) {
669 // full recalc needed due to map borders ...
670 recalc_city_size();
671 return;
672 }
673 }
674 else {
675 has_low_density = (buildings.get_count()<10 || (buildings.get_count()*100l)/((ur.x-lo.x)*(ur.y-lo.y)+1) > min_building_density);
676 if(has_low_density) {
677 // wide borders again ..
678 lo -= koord(2,2);
679 ur += koord(2,2);
680 }
681 }
682 // now just add single coordinates
683 if( has_low_density ) {
684 lo.clip_max(k-koord(2,2));
685 ur.clip_min(k+koord(2,2));
686 }
687 else {
688 // first grow within ...
689 lo.clip_max(k);
690 ur.clip_min(k);
691 }
692
693 lo.clip_min(koord(0,0));
694 ur.clip_max(koord(welt->get_size().x-1,welt->get_size().y-1));
695 }
696
697
698 // recalculate the spreading of a city
699 // will be updated also after house deletion
recalc_city_size()700 void stadt_t::recalc_city_size()
701 {
702 // WARNING: do not call this during multithreaded loading,
703 // as has_low_density may depend on the order the buildings list is filled
704 lo = pos;
705 ur = pos;
706 FOR(weighted_vector_tpl<gebaeude_t*>, const i, buildings) {
707 if (i->get_tile()->get_desc()->get_type() != building_desc_t::headquarters) {
708 koord const& gb_pos = i->get_pos().get_2d();
709 lo.clip_max(gb_pos);
710 ur.clip_min(gb_pos);
711 }
712 }
713
714 has_low_density = (buildings.get_count()<10 || (buildings.get_count()*100l)/((ur.x-lo.x)*(ur.y-lo.y)+1) > min_building_density);
715 if( has_low_density ) {
716 // wider borders for faster growth of sparse small towns
717 lo -= koord(2,2);
718 ur += koord(2,2);
719 }
720
721 lo.clip_min(koord(0,0));
722 ur.clip_max(koord(welt->get_size().x-1,welt->get_size().y-1));
723 }
724
725
init_pax_destinations()726 void stadt_t::init_pax_destinations()
727 {
728 pax_destinations_old.clear();
729 pax_destinations_new.clear();
730 pax_destinations_new_change = 0;
731 }
732
733
rdwr(loadsave_t * file)734 void stadt_t::factory_entry_t::rdwr(loadsave_t *file)
735 {
736 if( file->is_version_atleast(110, 5) ) {
737 koord factory_pos;
738 if( file->is_saving() ) {
739 factory_pos = factory->get_pos().get_2d();
740 }
741 factory_pos.rdwr( file );
742 if( file->is_loading() ) {
743 // position will be resolved back into fabrik_t* later
744 factory_pos_x = factory_pos.x;
745 factory_pos_y = factory_pos.y;
746 }
747 file->rdwr_long( demand );
748 file->rdwr_long( supply );
749 file->rdwr_long( remaining );
750 }
751 }
752
753
resolve_factory()754 void stadt_t::factory_entry_t::resolve_factory()
755 {
756 factory = fabrik_t::get_fab( koord(factory_pos_x, factory_pos_y) );
757 }
758
759
get_entry(const fabrik_t * const factory) const760 const stadt_t::factory_entry_t* stadt_t::factory_set_t::get_entry(const fabrik_t *const factory) const
761 {
762 FOR(vector_tpl<factory_entry_t>, const& e, entries) {
763 if (e.factory == factory) {
764 return &e;
765 }
766 }
767 return NULL; // not found
768 }
769
770
get_random_entry()771 stadt_t::factory_entry_t* stadt_t::factory_set_t::get_random_entry()
772 {
773 if( total_remaining>0 ) {
774 sint32 weight = simrand(total_remaining);
775 FOR(vector_tpl<factory_entry_t>, & entry, entries) {
776 if( entry.remaining>0 ) {
777 if( weight<entry.remaining ) {
778 return &entry;
779 }
780 weight -= entry.remaining;
781 }
782 }
783 }
784 return NULL;
785 }
786
787
update_factory(fabrik_t * const factory,const sint32 demand)788 void stadt_t::factory_set_t::update_factory(fabrik_t *const factory, const sint32 demand)
789 {
790 if( entries.is_contained( factory_entry_t(factory) ) ) {
791 // existing target factory
792 factory_entry_t &entry = entries[ entries.index_of( factory_entry_t(factory) ) ];
793 total_demand += demand - entry.demand;
794 entry.demand = demand;
795 // entry.supply, entry.remaining and total_remaining will be adjusted in recalc_generation_ratio()
796 }
797 else {
798 // new target factory
799 entries.append( factory_entry_t(factory, demand) );
800 total_demand += demand;
801 }
802 ratio_stale = true; // always trigger recalculation of ratio
803 }
804
805
remove_factory(fabrik_t * const factory)806 void stadt_t::factory_set_t::remove_factory(fabrik_t *const factory)
807 {
808 if( entries.is_contained( factory_entry_t(factory) ) ) {
809 factory_entry_t &entry = entries[ entries.index_of( factory_entry_t(factory) ) ];
810 total_demand -= entry.demand;
811 total_remaining -= entry.remaining;
812 entries.remove( entry );
813 ratio_stale = true;
814 }
815 }
816
817
818 #define SUPPLY_BITS (3)
819 #define SUPPLY_FACTOR (9) // out of 2^SUPPLY_BITS
recalc_generation_ratio(const sint32 default_percent,const sint64 * city_stats,const int stats_count,const int stat_type)820 void stadt_t::factory_set_t::recalc_generation_ratio(const sint32 default_percent, const sint64 *city_stats, const int stats_count, const int stat_type)
821 {
822 ratio_stale = false; // reset flag
823
824 // calculate an average of at most 3 previous months' pax/mail generation amounts
825 uint32 months = 0;
826 sint64 average_generated = 0;
827 sint64 month_generated;
828 while( months<3 && (month_generated=city_stats[(months+1)*stats_count+stat_type])>0 ) {
829 average_generated += month_generated;
830 ++months;
831 }
832 if( months>1 ) {
833 average_generated /= months;
834 }
835
836 /* ratio formula -> ((supply * 100) / total) shifted by RATIO_BITS */
837 // we supply 1/8 more than demand
838 const sint32 target_supply = (total_demand * SUPPLY_FACTOR + ((1<<(DEMAND_BITS+SUPPLY_BITS))-1)) >> (DEMAND_BITS+SUPPLY_BITS);
839 if( total_demand==0 ) {
840 // no demand -> zero ratio
841 generation_ratio = 0;
842 }
843 else if( !welt->get_settings().get_factory_enforce_demand() || average_generated == 0 ) {
844 // demand not enforced or no pax generation data from previous month(s) -> simply use default ratio
845 generation_ratio = (uint32)default_percent << RATIO_BITS;
846 }
847 else {
848 // ratio of target supply (plus allowances for rounding up) to previous months' average generated pax (less 6.25% or 1/16 allowance for fluctuation), capped by default ratio
849 const sint64 default_ratio = (sint64)default_percent << RATIO_BITS;
850 const sint64 supply_ratio = ((sint64)((target_supply+(sint32)entries.get_count())*100)<<RATIO_BITS) / (average_generated-(average_generated>>4)+1);
851 generation_ratio = (uint32)( default_ratio<supply_ratio ? default_ratio : supply_ratio );
852 }
853
854 // adjust supply and remaining figures
855 if( welt->get_settings().get_factory_enforce_demand() && (generation_ratio >> RATIO_BITS) == (uint32)default_percent && average_generated > 0 && total_demand > 0 ) {
856 const sint64 supply_promille = ( ( (average_generated << 10) * (sint64)default_percent ) / 100 ) / (sint64)target_supply;
857 if( supply_promille < 1024 ) {
858 // expected supply is really smaller than target supply
859 FOR(vector_tpl<factory_entry_t>, & entry, entries) {
860 const sint32 new_supply = (sint32)( ( (sint64)entry.demand * SUPPLY_FACTOR * supply_promille + ((1<<(DEMAND_BITS+SUPPLY_BITS+10))-1) ) >> (DEMAND_BITS+SUPPLY_BITS+10) );
861 const sint32 delta_supply = new_supply - entry.supply;
862 if( delta_supply==0 ) {
863 continue;
864 }
865 else if( delta_supply>0 || (entry.remaining+delta_supply)>=0 ) {
866 // adjust remaining figures by the change in supply
867 total_remaining += delta_supply;
868 entry.remaining += delta_supply;
869 }
870 else {
871 // avoid deducting more than allowed
872 total_remaining -= entry.remaining;
873 entry.remaining = 0;
874 }
875 entry.supply = new_supply;
876 }
877 return;
878 }
879 }
880 // expected supply is unknown or sufficient to meet target supply
881 FOR(vector_tpl<factory_entry_t>, & entry, entries) {
882 const sint32 new_supply = ( entry.demand * SUPPLY_FACTOR + ((1<<(DEMAND_BITS+SUPPLY_BITS))-1) ) >> (DEMAND_BITS+SUPPLY_BITS);
883 const sint32 delta_supply = new_supply - entry.supply;
884 if( delta_supply==0 ) {
885 continue;
886 }
887 else if( delta_supply>0 || (entry.remaining+delta_supply)>=0 ) {
888 // adjust remaining figures by the change in supply
889 total_remaining += delta_supply;
890 entry.remaining += delta_supply;
891 }
892 else {
893 // avoid deducting more than allowed
894 total_remaining -= entry.remaining;
895 entry.remaining = 0;
896 }
897 entry.supply = new_supply;
898 }
899 }
900
901
new_month()902 void stadt_t::factory_set_t::new_month()
903 {
904 FOR(vector_tpl<factory_entry_t>, & e, entries) {
905 e.new_month();
906 }
907 total_remaining = 0;
908 total_generated = 0;
909 ratio_stale = true;
910 }
911
912
rdwr(loadsave_t * file)913 void stadt_t::factory_set_t::rdwr(loadsave_t *file)
914 {
915 if( file->is_version_atleast(110, 5) ) {
916 uint32 entry_count = entries.get_count();
917 file->rdwr_long(entry_count);
918 if( file->is_loading() ) {
919 entries.resize( entry_count );
920 factory_entry_t entry;
921 for( uint32 e=0; e<entry_count; ++e ) {
922 entry.rdwr( file );
923 total_demand += entry.demand;
924 total_remaining += entry.remaining;
925 entries.append( entry );
926 }
927 }
928 else {
929 for( uint32 e=0; e<entry_count; ++e ) {
930 entries[e].rdwr( file );
931 }
932 }
933 file->rdwr_long( total_generated );
934 }
935 }
936
937
resolve_factories()938 void stadt_t::factory_set_t::resolve_factories()
939 {
940 uint32 remove_count = 0;
941 FOR(vector_tpl<factory_entry_t>, & e, entries) {
942 e.resolve_factory();
943 if (!e.factory) {
944 remove_count ++;
945 }
946 }
947 for( uint32 e=0; e<remove_count; ++e ) {
948 this->remove_factory( NULL );
949 }
950 }
951
952
~stadt_t()953 stadt_t::~stadt_t()
954 {
955 // close info win
956 destroy_win((ptrdiff_t)this);
957
958 if( minimap_t::get_instance()->is_city_selected(this) ) {
959 minimap_t::get_instance()->set_selected_city(NULL);
960 }
961
962 // only if there is still a world left to delete from
963 if( welt->get_size().x > 1 ) {
964
965 welt->lookup_kartenboden(pos)->set_text(NULL);
966
967 if (!welt->is_destroying()) {
968 // remove city info and houses
969 while (!buildings.empty()) {
970
971 gebaeude_t* const gb = buildings.pop_back();
972 assert( gb!=NULL && !buildings.is_contained(gb) );
973
974 if(gb->get_tile()->get_desc()->get_type()==building_desc_t::headquarters) {
975 stadt_t *city = welt->find_nearest_city(gb->get_pos().get_2d());
976 gb->set_stadt( city );
977 if(city) {
978 city->buildings.append(gb, gb->get_passagier_level());
979 }
980 }
981 else {
982 gb->set_stadt( NULL );
983 hausbauer_t::remove(welt->get_public_player(),gb);
984 }
985 }
986 // avoid the bookkeeping if world gets destroyed
987 }
988 }
989 }
990
991
name_used(weighted_vector_tpl<stadt_t * > const & cities,char const * const name)992 static bool name_used(weighted_vector_tpl<stadt_t*> const& cities, char const* const name)
993 {
994 FOR(weighted_vector_tpl<stadt_t*>, const i, cities) {
995 if (strcmp(i->get_name(), name) == 0) {
996 return true;
997 }
998 }
999 return false;
1000 }
1001
1002
stadt_t(player_t * player,koord pos,sint32 citizens)1003 stadt_t::stadt_t(player_t* player, koord pos, sint32 citizens) :
1004 buildings(16),
1005 pax_destinations_old(koord(PAX_DESTINATIONS_SIZE, PAX_DESTINATIONS_SIZE)),
1006 pax_destinations_new(koord(PAX_DESTINATIONS_SIZE, PAX_DESTINATIONS_SIZE))
1007 {
1008 assert(welt->is_within_limits(pos));
1009
1010 step_count = 0;
1011 pax_destinations_new_change = 0;
1012 next_step = 0;
1013 step_interval = 1;
1014 next_growth_step = 0;
1015 has_low_density = false;
1016 has_townhall = false;
1017
1018 stadtinfo_options = 3; // citizen and growth
1019
1020 owner = player;
1021
1022 this->pos = pos;
1023 last_center = koord::invalid;
1024
1025 bev = 0;
1026 arb = 0;
1027 won = 0;
1028
1029 lo = ur = pos;
1030
1031 /* get a unique cityname */
1032 char const* n = "simcity";
1033 weighted_vector_tpl<stadt_t*> const& staedte = welt->get_cities();
1034
1035 const vector_tpl<char*>& city_names = translator::get_city_name_list();
1036
1037 // make sure we do only ONE random call regardless of how many names are available (to avoid desyncs in network games)
1038 if( const uint32 count = city_names.get_count() ) {
1039 uint32 idx = simrand( count );
1040 static const uint32 some_primes[] = { 19, 31, 109, 199, 409, 571, 631, 829, 1489, 1999, 2341, 2971, 3529, 4621, 4789, 7039, 7669, 8779, 9721 };
1041 // find prime that does not divide count
1042 uint32 offset = 1;
1043 for( uint8 i=0; i < lengthof(some_primes); i++ ) {
1044 if( count % some_primes[i] != 0 ) {
1045 offset = some_primes[i];
1046 break;
1047 }
1048 }
1049 // as count % offset != 0 we are guaranteed to test all city names
1050 for(uint32 i=0; i<count; i++) {
1051 char const* const cand = city_names[idx];
1052 if( !name_used(staedte, cand) ) {
1053 n = cand;
1054 break;
1055 }
1056 idx = (idx+offset) % count;
1057 }
1058 }
1059 else {
1060 /* the one random call to avoid desyncs */
1061 simrand(5);
1062 }
1063 DBG_MESSAGE("stadt_t::stadt_t()", "founding new city named '%s'", n);
1064 name = n;
1065 has_townhall = false;
1066
1067 // 1. Rathaus bei 0 Leuten bauen
1068 check_bau_townhall(true);
1069
1070 unsupplied_city_growth = 0;
1071 allow_citygrowth = true;
1072
1073 // only build any houses if townhall is already there
1074 // city should be deleted if it has no buildings
1075 if (!buildings.empty()) {
1076 change_size( citizens, true );
1077 }
1078
1079 // fill with start citizen ...
1080 sint64 bew = get_einwohner();
1081 for (uint year = 0; year < MAX_CITY_HISTORY_YEARS; year++) {
1082 city_history_year[year][HIST_CITICENS] = bew;
1083 }
1084 for (uint month = 0; month < MAX_CITY_HISTORY_MONTHS; month++) {
1085 city_history_month[month][HIST_CITICENS] = bew;
1086 }
1087
1088 // initialize history array
1089 for (uint year = 0; year < MAX_CITY_HISTORY_YEARS; year++) {
1090 for (uint hist_type = 1; hist_type < MAX_CITY_HISTORY; hist_type++) {
1091 city_history_year[year][hist_type] = 0;
1092 }
1093 }
1094 for (uint month = 0; month < MAX_CITY_HISTORY_YEARS; month++) {
1095 for (uint hist_type = 1; hist_type < MAX_CITY_HISTORY; hist_type++) {
1096 city_history_month[month][hist_type] = 0;
1097 }
1098 }
1099 city_history_year[0][HIST_CITICENS] = get_einwohner();
1100 city_history_month[0][HIST_CITICENS] = get_einwohner();
1101 #ifdef DESTINATION_CITYCARS
1102 number_of_cars = 0;
1103 #endif
1104 }
1105
1106
stadt_t(loadsave_t * file)1107 stadt_t::stadt_t(loadsave_t* file) :
1108 buildings(16),
1109 pax_destinations_old(koord(PAX_DESTINATIONS_SIZE, PAX_DESTINATIONS_SIZE)),
1110 pax_destinations_new(koord(PAX_DESTINATIONS_SIZE, PAX_DESTINATIONS_SIZE))
1111 {
1112 step_count = 0;
1113 next_step = 0;
1114 step_interval = 1;
1115 next_growth_step = 0;
1116 has_low_density = false;
1117 has_townhall = false;
1118
1119 unsupplied_city_growth = 0;
1120 stadtinfo_options = 3;
1121
1122 rdwr(file);
1123 }
1124
1125
rdwr(loadsave_t * file)1126 void stadt_t::rdwr(loadsave_t* file)
1127 {
1128 sint32 owner_n;
1129
1130 if (file->is_saving()) {
1131 owner_n = welt->sp2num(owner);
1132 }
1133 file->rdwr_str(name);
1134 pos.rdwr(file);
1135 uint32 lli = lo.x;
1136 uint32 lob = lo.y;
1137 uint32 lre = ur.x;
1138 uint32 lun = ur.y;
1139 file->rdwr_long(lli);
1140 file->rdwr_long(lob);
1141 file->rdwr_long(lre);
1142 file->rdwr_long(lun);
1143 lo.x = lli;
1144 lo.y = lob;
1145 ur.x = lre;
1146 ur.y = lun;
1147 file->rdwr_long(owner_n);
1148 file->rdwr_long(bev);
1149 file->rdwr_long(arb);
1150 file->rdwr_long(won);
1151
1152 if( file->is_version_atleast(112, 9) ) {
1153 // Must record the partial (less than 1 citizen) growth factor
1154 // Otherwise we will get network desyncs
1155 // Also allows accumulation of small growth factors
1156 file->rdwr_longlong(unsupplied_city_growth);
1157 }
1158 else if( file->is_loading() ) {
1159 unsupplied_city_growth = 0;
1160 }
1161 // old values zentrum_namen_cnt : aussen_namen_cnt
1162 if(file->is_version_less(99, 18)) {
1163 sint32 dummy=0;
1164 file->rdwr_long(dummy);
1165 file->rdwr_long(dummy);
1166 }
1167
1168 if (file->is_loading()) {
1169 owner = welt->get_player(owner_n);
1170 }
1171
1172 if(file->is_loading()) {
1173 // initialize history array
1174 for (uint year = 0; year < MAX_CITY_HISTORY_YEARS; year++) {
1175 for (uint hist_type = 0; hist_type < MAX_CITY_HISTORY; hist_type++) {
1176 city_history_year[year][hist_type] = 0;
1177 }
1178 }
1179 for (uint month = 0; month < MAX_CITY_HISTORY_MONTHS; month++) {
1180 for (uint hist_type = 0; hist_type < MAX_CITY_HISTORY; hist_type++) {
1181 city_history_month[month][hist_type] = 0;
1182 }
1183 }
1184 city_history_year[0][HIST_CITICENS] = get_einwohner();
1185 city_history_year[0][HIST_CITICENS] = get_einwohner();
1186 }
1187
1188 // we probably need to load/save the city history
1189 if (file->is_version_less(86, 0)) {
1190 DBG_DEBUG("stadt_t::rdwr()", "is old version: No history!");
1191 } else if(file->is_version_less(99, 16)) {
1192 // 86.00.0 introduced city history
1193 for (uint year = 0; year < MAX_CITY_HISTORY_YEARS; year++) {
1194 for (uint hist_type = 0; hist_type < 2; hist_type++) {
1195 file->rdwr_longlong(city_history_year[year][hist_type]);
1196 }
1197 for (uint hist_type = 4; hist_type < 6; hist_type++) {
1198 file->rdwr_longlong(city_history_year[year][hist_type]);
1199 }
1200 }
1201 for (uint month = 0; month < MAX_CITY_HISTORY_MONTHS; month++) {
1202 for (uint hist_type = 0; hist_type < 2; hist_type++) {
1203 file->rdwr_longlong(city_history_month[month][hist_type]);
1204 }
1205 for (uint hist_type = 4; hist_type < 6; hist_type++) {
1206 file->rdwr_longlong(city_history_month[month][hist_type]);
1207 }
1208 }
1209 // not needed any more
1210 sint32 dummy = 0;
1211 file->rdwr_long(dummy);
1212 file->rdwr_long(dummy);
1213 file->rdwr_long(dummy);
1214 file->rdwr_long(dummy);
1215 }
1216 else if( file->is_version_less(120, 1) ) {
1217 // 99.17.0 extended city history
1218 for (uint year = 0; year < MAX_CITY_HISTORY_YEARS; year++) {
1219 for (uint hist_type = 0; hist_type < MAX_CITY_HISTORY; hist_type++) {
1220 if( hist_type==HIST_PAS_WALKED || hist_type==HIST_MAIL_WALKED ) {
1221 continue;
1222 }
1223 file->rdwr_longlong(city_history_year[year][hist_type]);
1224 }
1225 }
1226 for (uint month = 0; month < MAX_CITY_HISTORY_MONTHS; month++) {
1227 for (uint hist_type = 0; hist_type < MAX_CITY_HISTORY; hist_type++) {
1228 if( hist_type==HIST_PAS_WALKED || hist_type==HIST_MAIL_WALKED ) {
1229 continue;
1230 }
1231 file->rdwr_longlong(city_history_month[month][hist_type]);
1232 }
1233 }
1234 // save button settings for this town
1235 file->rdwr_long( stadtinfo_options);
1236 }
1237 else {
1238 // 120,001 with walking (direct connections) recored seperately
1239 for (uint year = 0; year < MAX_CITY_HISTORY_YEARS; year++) {
1240 for (uint hist_type = 0; hist_type < MAX_CITY_HISTORY; hist_type++) {
1241 file->rdwr_longlong(city_history_year[year][hist_type]);
1242 }
1243 }
1244 for (uint month = 0; month < MAX_CITY_HISTORY_MONTHS; month++) {
1245 for (uint hist_type = 0; hist_type < MAX_CITY_HISTORY; hist_type++) {
1246 file->rdwr_longlong(city_history_month[month][hist_type]);
1247 }
1248 }
1249 // save button settings for this town
1250 file->rdwr_long( stadtinfo_options);
1251 }
1252
1253 // differential history
1254 if ( file->is_version_less(120, 1) ) {
1255 if ( file->is_loading() ) {
1256 // Initalize differential statistics assuming a differential of 0.
1257 city_growth_get_factors(city_growth_factor_previous, 0);
1258 }
1259 }
1260 else {
1261 // load/save differential statistics.
1262 for (uint32 i = 0; i < GROWTH_FACTOR_NUMBER; i++) {
1263 file->rdwr_longlong(city_growth_factor_previous[i].demand);
1264 file->rdwr_longlong(city_growth_factor_previous[i].supplied);
1265 }
1266 }
1267
1268 if(file->is_version_atleast(99, 15) && file->is_version_less(99, 16)) {
1269 sint32 dummy = 0;
1270 file->rdwr_long(dummy);
1271 file->rdwr_long(dummy);
1272 }
1273
1274 // since 102.2 there are static cities
1275 if(file->is_version_atleast(102, 2)) {
1276 file->rdwr_bool(allow_citygrowth);
1277 }
1278 else if( file->is_loading() ) {
1279 allow_citygrowth = true;
1280 }
1281 // save townhall road position
1282 if(file->is_version_atleast(102, 3)) {
1283 townhall_road.rdwr(file);
1284 }
1285 else if( file->is_loading() ) {
1286 townhall_road = koord::invalid;
1287 }
1288
1289 // data related to target factories
1290 target_factories_pax.rdwr( file );
1291 target_factories_mail.rdwr( file );
1292
1293 if(file->is_loading()) {
1294 // 08-Jan-03: Due to some bugs in the special buildings/town hall
1295 // placement code, li,re,ob,un could've gotten irregular values
1296 // If a game is loaded, the game might suffer from such an mistake
1297 // and we need to correct it here.
1298 DBG_MESSAGE("stadt_t::rdwr()", "borders (%i,%i) -> (%i,%i)", lo.x, lo.y, ur.x, ur.y);
1299
1300 // recalculate borders
1301 recalc_city_size();
1302 }
1303 }
1304
1305
finish_rd()1306 void stadt_t::finish_rd()
1307 {
1308 step_count = 0;
1309 next_step = 0;
1310 next_growth_step = 0;
1311
1312 // there might be broken savegames
1313 if (!name) {
1314 set_name( "simcity" );
1315 }
1316
1317 if (!has_townhall) {
1318 dbg->warning("stadt_t::finish_rd()", "City %s has no valid townhall after loading the savegame, try to build a new one.", get_name());
1319 check_bau_townhall(true);
1320 }
1321 // new city => need to grow
1322 if (buildings.empty()) {
1323 step_grow_city(true);
1324 }
1325
1326 // clear the minimaps
1327 init_pax_destinations();
1328
1329 // init step counter with meaningful value
1330 step_interval = (2 << 18u) / (buildings.get_count() * 4 + 1);
1331 if (step_interval < 1) {
1332 step_interval = 1;
1333 }
1334
1335 if(townhall_road==koord::invalid) {
1336 // guess road tile based on current orientation
1337 gebaeude_t const* const gb = obj_cast<gebaeude_t>(welt->lookup_kartenboden(pos)->first_obj());
1338 if( gb && gb->is_townhall() ) {
1339 koord k(gb->get_tile()->get_desc()->get_size(gb->get_tile()->get_layout()));
1340 switch (gb->get_tile()->get_layout()) {
1341 default:
1342 case 0:
1343 townhall_road = pos + koord(0, k.y);
1344 break;
1345 case 1:
1346 townhall_road = pos + koord(k.x, 0);
1347 break;
1348 case 2:
1349 townhall_road = pos + koord(0, -1);
1350 break;
1351 case 3:
1352 townhall_road = pos + koord(-1, 0);
1353 break;
1354 }
1355 }
1356 }
1357 recalc_city_size();
1358
1359 next_step = 0;
1360 next_growth_step = 0;
1361
1362 // resolve target factories
1363 target_factories_pax.resolve_factories();
1364 target_factories_mail.resolve_factories();
1365 }
1366
1367
rotate90(const sint16 y_size)1368 void stadt_t::rotate90( const sint16 y_size )
1369 {
1370 // rotate town origin
1371 pos.rotate90( y_size );
1372 townhall_road.rotate90( y_size );
1373 // rotate an rectangle
1374 lo.rotate90( y_size );
1375 ur.rotate90( y_size );
1376 sint16 lox = lo.x;
1377 lo.x = ur.x;
1378 ur.x = lox;
1379 // reset building search
1380 best_strasse.reset(pos);
1381 best_haus.reset(pos);
1382 // townhall position may be changed a little!
1383 sparse_tpl<PIXVAL> pax_destinations_temp(koord( PAX_DESTINATIONS_SIZE, PAX_DESTINATIONS_SIZE ));
1384
1385 PIXVAL color;
1386 koord pos;
1387 for( uint16 i = 0; i < pax_destinations_new.get_data_count(); i++ ) {
1388 pax_destinations_new.get_nonzero(i, pos, color);
1389 assert( color != 0 );
1390 pax_destinations_temp.set( PAX_DESTINATIONS_SIZE-1-pos.y, pos.x, color );
1391 }
1392 swap<PIXVAL>( pax_destinations_temp, pax_destinations_new );
1393
1394 pax_destinations_temp.clear();
1395 for( uint16 i = 0; i < pax_destinations_old.get_data_count(); i++ ) {
1396 pax_destinations_old.get_nonzero(i, pos, color);
1397 assert( color != 0 );
1398 pax_destinations_temp.set( PAX_DESTINATIONS_SIZE-1-pos.y, pos.x, color );
1399 }
1400 pax_destinations_new_change ++;
1401 swap<PIXVAL>( pax_destinations_temp, pax_destinations_old );
1402 }
1403
1404
set_name(const char * new_name)1405 void stadt_t::set_name(const char *new_name)
1406 {
1407 if (new_name == NULL) {
1408 return;
1409 }
1410 name = new_name;
1411 grund_t *gr = welt->lookup_kartenboden(pos);
1412 if(gr) {
1413 gr->set_text( new_name );
1414 }
1415 city_info_t *win = dynamic_cast<city_info_t*>(win_get_magic((ptrdiff_t)this));
1416 if (win) {
1417 win->update_data();
1418 }
1419 }
1420
1421
1422 /* show city info dialogue
1423 * @author prissi
1424 */
open_info_window()1425 void stadt_t::open_info_window()
1426 {
1427 create_win( new city_info_t(this), w_info, (ptrdiff_t)this );
1428 }
1429
1430
1431 /* calculates the factories which belongs to certain cities */
verbinde_fabriken()1432 void stadt_t::verbinde_fabriken()
1433 {
1434 DBG_MESSAGE("stadt_t::verbinde_fabriken()", "search factories near %s (center at %i,%i)", get_name(), pos.x, pos.y);
1435 assert( target_factories_pax.get_entries().empty() );
1436 assert( target_factories_mail.get_entries().empty() );
1437
1438 FOR(slist_tpl<fabrik_t*>, const fab, welt->get_fab_list()) {
1439 const uint32 count = fab->get_target_cities().get_count();
1440 if( count < welt->get_settings().get_factory_worker_maximum_towns() && koord_distance(fab->get_pos(), pos) < welt->get_settings().get_factory_worker_radius() ) {
1441 fab->add_target_city(this);
1442 }
1443 }
1444 DBG_MESSAGE("stadt_t::verbinde_fabriken()", "is connected with %i/%i factories (total demand=%i/%i) for pax/mail.", target_factories_pax.get_entries().get_count(), target_factories_mail.get_entries().get_count(), target_factories_pax.total_demand, target_factories_mail.total_demand);
1445 }
1446
1447
1448 /* change size of city
1449 * @author prissi */
change_size(sint64 delta_citizen,bool new_town)1450 void stadt_t::change_size( sint64 delta_citizen, bool new_town)
1451 {
1452 DBG_MESSAGE("stadt_t::change_size()", "%i + %i", bev, delta_citizen);
1453 if( delta_citizen > 0 ) {
1454 unsupplied_city_growth += delta_citizen * CITYGROWTH_PER_CITICEN;
1455 step_grow_city(new_town);
1456 }
1457 if( delta_citizen < 0 ) {
1458 if( bev > -delta_citizen ) {
1459 bev += (sint32)delta_citizen;
1460 }
1461 else {
1462 // remove_city();
1463 bev = 1;
1464 }
1465 step_grow_city(new_town);
1466 }
1467 DBG_MESSAGE("stadt_t::change_size()", "%i+%i", bev, delta_citizen);
1468 }
1469
1470
step(uint32 delta_t)1471 void stadt_t::step(uint32 delta_t)
1472 {
1473 // recalculate factory going ratios where necessary
1474 const sint16 factory_worker_percentage = welt->get_settings().get_factory_worker_percentage();
1475 if( target_factories_pax.ratio_stale ) {
1476 target_factories_pax.recalc_generation_ratio( factory_worker_percentage, *city_history_month, MAX_CITY_HISTORY, HIST_PAS_GENERATED);
1477 }
1478 if( target_factories_mail.ratio_stale ) {
1479 target_factories_mail.recalc_generation_ratio( factory_worker_percentage, *city_history_month, MAX_CITY_HISTORY, HIST_MAIL_GENERATED);
1480 }
1481
1482 // is it time for the next step?
1483 next_step += delta_t;
1484 next_growth_step += delta_t;
1485
1486 step_interval = (1 << 21U) / (buildings.get_count() * welt->get_settings().get_passenger_factor() + 1);
1487 if (step_interval < 1) {
1488 step_interval = 1;
1489 }
1490
1491 while(stadt_t::city_growth_step < next_growth_step) {
1492 calc_growth();
1493 step_grow_city();
1494 next_growth_step -= stadt_t::city_growth_step;
1495 }
1496
1497 // create passenger rate proportional to town size
1498 while(step_interval < next_step) {
1499 step_passagiere();
1500 step_count++;
1501 next_step -= step_interval;
1502 }
1503
1504 // update history (might be changed do to construction/destroying of houses)
1505 city_history_month[0][HIST_CITICENS] = get_einwohner(); // total number
1506 city_history_year[0][HIST_CITICENS] = get_einwohner();
1507
1508 city_history_month[0][HIST_GROWTH] = city_history_month[0][HIST_CITICENS]-city_history_month[1][HIST_CITICENS]; // growth
1509 city_history_year[0][HIST_GROWTH] = city_history_year[0][HIST_CITICENS]-city_history_year[1][HIST_CITICENS];
1510
1511 city_history_month[0][HIST_BUILDING] = buildings.get_count();
1512 city_history_year[0][HIST_BUILDING] = buildings.get_count();
1513 }
1514
1515
1516 /* updates the city history
1517 * @author prissi
1518 */
roll_history()1519 void stadt_t::roll_history()
1520 {
1521 // roll months
1522 for (int i = MAX_CITY_HISTORY_MONTHS - 1; i > 0; i--) {
1523 for (int hist_type = 0; hist_type < MAX_CITY_HISTORY; hist_type++) {
1524 city_history_month[i][hist_type] = city_history_month[i - 1][hist_type];
1525 }
1526 }
1527 // init this month
1528 for (int hist_type = 1; hist_type < MAX_CITY_HISTORY; hist_type++) {
1529 city_history_month[0][hist_type] = 0;
1530 }
1531 city_history_month[0][HIST_CITICENS] = get_einwohner();
1532 city_history_month[0][HIST_BUILDING] = buildings.get_count();
1533 city_history_month[0][HIST_GOODS_NEEDED] = 0;
1534
1535 //need to roll year too?
1536 if (welt->get_last_month() == 0) {
1537 for (int i = MAX_CITY_HISTORY_YEARS - 1; i > 0; i--) {
1538 for (int hist_type = 0; hist_type < MAX_CITY_HISTORY; hist_type++) {
1539 city_history_year[i][hist_type] = city_history_year[i - 1][hist_type];
1540 }
1541 }
1542 // init this year
1543 for (int hist_type = 1; hist_type < MAX_CITY_HISTORY; hist_type++) {
1544 city_history_year[0][hist_type] = 0;
1545 }
1546 city_history_year[0][HIST_CITICENS] = get_einwohner();
1547 city_history_year[0][HIST_BUILDING] = buildings.get_count();
1548 city_history_year[0][HIST_GOODS_NEEDED] = 0;
1549 }
1550
1551 }
1552
city_growth_get_factors(city_growth_factor_t (& factors)[GROWTH_FACTOR_NUMBER],uint32 const month) const1553 void stadt_t::city_growth_get_factors(city_growth_factor_t(&factors)[GROWTH_FACTOR_NUMBER], uint32 const month) const {
1554 // optimize view of history for convenience
1555 sint64 const (&h)[MAX_CITY_HISTORY] = city_history_month[month];
1556
1557 // go through each index one at a time
1558 uint32 index = 0;
1559
1560 // passenger growth factors
1561 factors[index].demand = h[HIST_PAS_GENERATED];
1562 factors[index++].supplied = h[HIST_PAS_TRANSPORTED] + h[HIST_PAS_WALKED];
1563
1564 // mail growth factors
1565 factors[index].demand = h[HIST_MAIL_GENERATED];
1566 factors[index++].supplied = h[HIST_MAIL_TRANSPORTED] + h[HIST_MAIL_WALKED];
1567
1568 // goods growth factors
1569 factors[index].demand = h[HIST_GOODS_NEEDED];
1570 factors[index++].supplied = h[HIST_GOODS_RECEIVED];
1571 }
1572
city_growth_base(uint32 const rprec,uint32 const cprec)1573 sint32 stadt_t::city_growth_base(uint32 const rprec, uint32 const cprec)
1574 {
1575 // Resolve constant references.
1576 settings_t const & s = welt->get_settings();
1577 sint32 const weight[GROWTH_FACTOR_NUMBER] = { s.get_passenger_multiplier(), s.get_mail_multiplier(),
1578 s.get_goods_multiplier() };
1579
1580 sint32 acc = 0; // The weighted satisfaction accululator.
1581 sint32 div = 0; // The weight dividend.
1582 sint32 total = 0; // The total weight.
1583
1584 // initalize const growth array
1585 city_growth_factor_t growthfactors[GROWTH_FACTOR_NUMBER];
1586 city_growth_get_factors(growthfactors, 0);
1587
1588 // Loop through each growth factor and compute it.
1589 for( uint32 i = 0; i < GROWTH_FACTOR_NUMBER; i += 1 ) {
1590 // Resolve the weight.
1591 total += weight[i];
1592
1593 // Compute the differentials.
1594 sint64 const had = growthfactors[i].demand - city_growth_factor_previous[i].demand;
1595 city_growth_factor_previous[i].demand = growthfactors[i].demand;
1596 sint64 const got = growthfactors[i].supplied - city_growth_factor_previous[i].supplied;
1597 city_growth_factor_previous[i].supplied = growthfactors[i].supplied;
1598
1599 // If we had anything to satisfy add it to weighting otherwise skip.
1600 if( had == 0 ) {
1601 continue;
1602 }
1603
1604 // Compute fractional satisfaction.
1605 sint32 const frac = (sint32)((got << cprec) / had);
1606
1607 // Add to weight and div.
1608 acc += frac * weight[i];
1609 div += weight[i];
1610 }
1611
1612 // If there was not anything to satisfy then use last month averages.
1613 if ( div == 0 ) {
1614 // initalize growth factor array
1615 city_growth_factor_t prev_growthfactors[GROWTH_FACTOR_NUMBER];
1616 city_growth_get_factors(prev_growthfactors, 1);
1617
1618 for( uint32 i = 0; i < GROWTH_FACTOR_NUMBER; i += 1 ){
1619
1620 // Extract the values of growth.
1621 sint64 const had = prev_growthfactors[i].demand;
1622 sint64 const got = prev_growthfactors[i].supplied;
1623
1624 // If we had anything to satisfy add it to weighting otherwise skip.
1625 if( had == 0 ) {
1626 continue;
1627 }
1628
1629 // Compute fractional satisfaction.
1630 sint32 const frac = (sint32)((got << cprec) / had);
1631
1632 // Add to weight and div.
1633 acc += frac * weight[i];
1634 div += weight[i];
1635 }
1636 }
1637
1638 // Return computed result. If still no demand then assume no growth to prevent self-growing new hamlets.
1639 return div != 0 ? (total * (acc / div)) >> (cprec - rprec) : 0;
1640 }
1641
1642
city_growth_monthly(uint32 const month)1643 void stadt_t::city_growth_monthly(uint32 const month)
1644 {
1645 // initalize growth factor array
1646 city_growth_factor_t growthfactors[GROWTH_FACTOR_NUMBER];
1647 city_growth_get_factors(growthfactors, month);
1648
1649 // Perform roll over.
1650 for( uint32 i = 0; i < GROWTH_FACTOR_NUMBER; i += 1 ){
1651 // Compute the differentials.
1652 sint64 const had = growthfactors[i].demand - city_growth_factor_previous[i].demand;
1653 city_growth_factor_previous[i].demand = -had;
1654 sint64 const got = growthfactors[i].supplied - city_growth_factor_previous[i].supplied;
1655 city_growth_factor_previous[i].supplied = -got;
1656 }
1657 }
1658
1659
new_month(bool recalc_destinations)1660 void stadt_t::new_month( bool recalc_destinations )
1661 {
1662 swap<PIXVAL>( pax_destinations_old, pax_destinations_new );
1663 pax_destinations_new.clear();
1664 pax_destinations_new_change = 0;
1665
1666 city_growth_monthly(0);
1667 roll_history();
1668 target_factories_pax.new_month();
1669 target_factories_mail.new_month();
1670
1671 const sint16 factory_worker_percentage = welt->get_settings().get_factory_worker_percentage();
1672 // settings_t const& s = welt->get_settings();
1673 target_factories_pax.recalc_generation_ratio( factory_worker_percentage, *city_history_month, MAX_CITY_HISTORY, HIST_PAS_GENERATED);
1674 target_factories_mail.recalc_generation_ratio( factory_worker_percentage, *city_history_month, MAX_CITY_HISTORY, HIST_MAIL_GENERATED);
1675 recalc_target_cities();
1676
1677 // center has moved => change attraction weights
1678 if( recalc_destinations || last_center != get_center() ) {
1679 last_center = get_center();
1680 recalc_target_attractions();
1681 }
1682
1683 if( !private_car_t::list_empty() && welt->get_settings().get_traffic_level() > 0 ) {
1684 // spawn eventual citycars
1685 // the more transported, the less are spawned
1686 // the larger the city, the more spawned ...
1687
1688 /* original implementation that is replaced by integer-only version below
1689 double pfactor = (double)(city_history_month[1][HIST_PAS_TRANSPORTED]) / (double)(city_history_month[1][HIST_PAS_GENERATED]+1);
1690 double mfactor = (double)(city_history_month[1][HIST_MAIL_TRANSPORTED]) / (double)(city_history_month[1][HIST_MAIL_GENERATED]+1);
1691 double gfactor = (double)(city_history_month[1][HIST_GOODS_RECEIVED]) / (double)(city_history_month[1][HIST_GOODS_NEEDED]+1);
1692
1693 double factor = pfactor > mfactor ? (gfactor > pfactor ? gfactor : pfactor ) : mfactor;
1694 factor = (1.0-factor)*city_history_month[1][HIST_CITICENS];
1695 factor = log10( factor );
1696 */
1697
1698 // placeholder for fractions
1699 # define decl_stat(name, i0, i1) sint64 name##_stat[2]; name##_stat[0] = city_history_month[1][i0]; name##_stat[1] = city_history_month[1][i1]+1;
1700
1701 // defines and initializes local sint64[2] arrays
1702 decl_stat(pax, HIST_PAS_TRANSPORTED, HIST_PAS_GENERATED);
1703 decl_stat(mail, HIST_MAIL_TRANSPORTED, HIST_MAIL_GENERATED);
1704 decl_stat(good, HIST_GOODS_RECEIVED, HIST_GOODS_NEEDED);
1705
1706 // true if s1[0] / s1[1] > s2[0] / s2[1]
1707 # define comp_stats(s1,s2) ( s1[0]*s2[1] > s2[0]*s1[1] )
1708 // computes (1.0 - s[0]/s[1]) * city_history_month[1][HIST_CITICENS]
1709 # define comp_factor(s) (city_history_month[1][HIST_CITICENS] *( s[1]-s[0] )) / s[1]
1710
1711 uint32 factor = (uint32)( comp_stats(pax_stat, mail_stat) ? (comp_stats(good_stat, pax_stat) ? comp_factor(good_stat) : comp_factor(pax_stat)) : comp_factor(mail_stat) );
1712 factor = log10(factor);
1713
1714 #ifndef DESTINATION_CITYCARS
1715 uint16 number_of_cars = simrand( factor * welt->get_settings().get_traffic_level() ) / 16;
1716
1717 city_history_month[0][HIST_CITYCARS] = number_of_cars;
1718 city_history_year[0][HIST_CITYCARS] += number_of_cars;
1719
1720 koord k;
1721 koord pos = get_zufallspunkt();
1722 for (k.y = pos.y - 3; k.y < pos.y + 3; k.y++) {
1723 for (k.x = pos.x - 3; k.x < pos.x + 3; k.x++) {
1724 if(number_of_cars==0) {
1725 return;
1726 }
1727
1728 grund_t* gr = welt->lookup_kartenboden(k);
1729 if( gr != NULL && gr->get_weg(road_wt) && ribi_t::is_twoway(gr->get_weg_ribi_unmasked(road_wt)) && gr->find<private_car_t>() == NULL) {
1730 private_car_t* vt = new private_car_t(gr, koord::invalid);
1731 gr->obj_add(vt);
1732 welt->sync.add(vt);
1733 number_of_cars--;
1734 }
1735 }
1736 }
1737
1738 // correct statistics for ungenerated cars
1739 city_history_month[0][HIST_CITYCARS] -= number_of_cars;
1740 city_history_year[0][HIST_CITYCARS] -= number_of_cars;
1741 #else
1742 city_history_month[0][HIST_CITYCARS] = 0;
1743 number_of_cars = simrand( factor * welt->get_settings().get_traffic_level() ) / 16;
1744 #endif
1745 }
1746 }
1747
1748
calc_growth()1749 void stadt_t::calc_growth()
1750 {
1751 // now iterate over all factories to get the ratio of producing version non-producing factories
1752 // we use the incoming storage as a measure and we will only look for end consumers (power stations, markets)
1753 FOR(vector_tpl<factory_entry_t>, const& i, target_factories_pax.get_entries()) {
1754 fabrik_t *const fab = i.factory;
1755 if (fab->get_lieferziele().empty() && !fab->get_suppliers().empty()) {
1756 // consumer => check for it storage
1757 const factory_desc_t *const desc = fab->get_desc();
1758 for( int i=0; i<desc->get_supplier_count(); i++ ) {
1759 city_history_month[0][HIST_GOODS_NEEDED] ++;
1760 city_history_year[0][HIST_GOODS_NEEDED] ++;
1761 if( fab->input_vorrat_an( desc->get_supplier(i)->get_input_type() )>0 ) {
1762 city_history_month[0][HIST_GOODS_RECEIVED] ++;
1763 city_history_year[0][HIST_GOODS_RECEIVED] ++;
1764 }
1765 }
1766 }
1767 }
1768
1769 // maybe this town should stay static
1770 if( !allow_citygrowth ) {
1771 unsupplied_city_growth = 0;
1772 return;
1773 }
1774
1775 // Compute base growth.
1776 sint32 const total_supply_percentage = city_growth_base();
1777
1778 // By construction, this is a percentage times 2^6 (Q25.6).
1779 // Although intended to be out of 100, it can be more or less.
1780 // We will divide it by 2^4=16 for traditional reasons, which means
1781 // it generates 2^2 (=4) or fewer people at 100%.
1782
1783 // smaller towns should grow slower to have villages for a longer time
1784 sint32 const weight_factor =
1785 bev < 1000 ? welt->get_settings().get_growthfactor_small() :
1786 bev < 10000 ? welt->get_settings().get_growthfactor_medium() :
1787 welt->get_settings().get_growthfactor_large();
1788
1789 // now compute the growth for this step
1790 sint32 growth_factor = weight_factor > 0 ? total_supply_percentage / weight_factor : 0;
1791
1792 // Scale up growth to have a larger fractional component. This allows small growth units to accumulate in the case of long months.
1793 sint64 new_unsupplied_city_growth = growth_factor * (CITYGROWTH_PER_CITICEN / 16);
1794
1795 // Growth is scaled down by month length.
1796 // The result is that ~ the same monthly growth will occur independent of month length.
1797 new_unsupplied_city_growth = welt->inverse_scale_with_month_length( new_unsupplied_city_growth );
1798
1799 // Add the computed growth to the growth accumulator.
1800 // Future growth scale factors can be applied here.
1801 unsupplied_city_growth += new_unsupplied_city_growth;
1802 }
1803
1804
1805 // does constructions ...
step_grow_city(bool new_town)1806 void stadt_t::step_grow_city( bool new_town )
1807 {
1808 // Try harder to build if this is a new town
1809 int num_tries = new_town ? 1000 : 30;
1810
1811 // since we use internally a finer value ...
1812 const sint64 growth_steps = unsupplied_city_growth / CITYGROWTH_PER_CITICEN;
1813 if( growth_steps > 0 ) {
1814 unsupplied_city_growth %= CITYGROWTH_PER_CITICEN;
1815 }
1816
1817 // Hajo: let city grow in steps of 1
1818 // @author prissi: No growth without development
1819 for( sint64 n = 0; n < growth_steps; n++ ) {
1820 bev++;
1821
1822 for( int i = 0; i < num_tries && bev * 2 > won + arb + 100; i++ ) {
1823 build();
1824 }
1825
1826 check_bau_spezial(new_town);
1827 check_bau_townhall(new_town);
1828 check_bau_factory(new_town); // add industry? (not during creation)
1829 INT_CHECK("simcity 275");
1830 }
1831 }
1832
1833
1834 /* this creates passengers and mail for everything is is therefore one of the CPU hogs of the machine
1835 * think trice, before applying optimisation here ...
1836 */
step_passagiere()1837 void stadt_t::step_passagiere()
1838 {
1839 // decide whether to generate passengers or mail
1840 const bool ispass = simrand(GENERATE_RATIO_PASS + GENERATE_RATIO_MAIL) < GENERATE_RATIO_PASS;
1841 const goods_desc_t *const wtyp = ispass ? goods_manager_t::passengers : goods_manager_t::mail;
1842 const uint32 history_type = ispass ? HIST_BASE_PASS : HIST_BASE_MAIL;
1843 factory_set_t &target_factories = ispass ? target_factories_pax : target_factories_mail;
1844
1845 // restart at first building?
1846 if (step_count >= buildings.get_count()) {
1847 step_count = 0;
1848 }
1849 if (buildings.empty()) {
1850 return;
1851 }
1852 const gebaeude_t* gb = buildings[step_count];
1853
1854 // prissi: since now backtravels occur, we damp the numbers a little
1855 const uint32 num_pax =
1856 (ispass) ?
1857 (gb->get_tile()->get_desc()->get_level() + 6) >> 2 :
1858 (gb->get_tile()->get_desc()->get_mail_level() + 8) >> 3 ;
1859
1860 // create pedestrians in the near area?
1861 if (welt->get_settings().get_random_pedestrians() && ispass) {
1862 haltestelle_t::generate_pedestrians(gb->get_pos(), num_pax);
1863 }
1864
1865 // suitable start search
1866 const koord origin_pos = gb->get_pos().get_2d();
1867 const planquadrat_t *const plan = welt->access(origin_pos);
1868 const halthandle_t *const halt_list = plan->get_haltlist();
1869
1870 // suitable start search
1871 static vector_tpl<halthandle_t> start_halts(16);
1872 start_halts.clear();
1873 for (uint h = 0; h < plan->get_haltlist_count(); h++) {
1874 halthandle_t halt = halt_list[h];
1875 if( halt.is_bound() && halt->is_enabled(wtyp) && !halt->is_overcrowded(wtyp->get_index()) ) {
1876 start_halts.append(halt);
1877 }
1878 }
1879
1880 // Hajo: track number of generated passengers.
1881 city_history_year[0][history_type + HIST_OFFSET_GENERATED] += num_pax;
1882 city_history_month[0][history_type + HIST_OFFSET_GENERATED] += num_pax;
1883
1884 // only continue, if this is a good start halt
1885 if( !start_halts.empty() ) {
1886 // Find passenger destination
1887 for( uint pax_routed=0, pax_left_to_do=0; pax_routed < num_pax; pax_routed += pax_left_to_do ) {
1888 // number of passengers that want to travel
1889 // Hajo: for efficiency we try to route not every
1890 // single pax, but packets. If possible, we do 7 passengers at a time
1891 // the last packet might have less then 7 pax
1892 pax_left_to_do = min(PACKET_SIZE, num_pax - pax_routed);
1893
1894 // search target for the passenger
1895 pax_return_type will_return;
1896 factory_entry_t *factory_entry = NULL;
1897 stadt_t *dest_city = NULL;
1898 const koord dest_pos = find_destination(target_factories, city_history_month[0][history_type + HIST_OFFSET_GENERATED], &will_return, factory_entry, dest_city);
1899 if( factory_entry ) {
1900 if (welt->get_settings().get_factory_enforce_demand()) {
1901 // ensure no more than remaining amount
1902 pax_left_to_do = min( pax_left_to_do, factory_entry->remaining );
1903 factory_entry->remaining -= pax_left_to_do;
1904 target_factories.total_remaining -= pax_left_to_do;
1905 }
1906 target_factories.total_generated += pax_left_to_do;
1907 factory_entry->factory->book_stat(pax_left_to_do, ispass ? FAB_PAX_GENERATED : FAB_MAIL_GENERATED);
1908 }
1909
1910 ware_t pax(wtyp);
1911 pax.set_zielpos(dest_pos);
1912 pax.menge = pax_left_to_do;
1913 pax.to_factory = ( factory_entry ? 1 : 0 );
1914
1915 ware_t return_pax(wtyp);
1916
1917 // now, finally search a route; this consumes most of the time
1918 int const route_result = haltestelle_t::search_route( &start_halts[0], start_halts.get_count(), welt->get_settings().is_no_routing_over_overcrowding(), pax, &return_pax);
1919 halthandle_t start_halt = return_pax.get_ziel();
1920 if( route_result==haltestelle_t::ROUTE_OK ) {
1921 // so we have happy traveling passengers
1922 start_halt->starte_mit_route(pax);
1923 start_halt->add_pax_happy(pax.menge);
1924
1925 // people were transported so are logged
1926 city_history_year[0][history_type + HIST_OFFSET_TRANSPORTED] += pax_left_to_do;
1927 city_history_month[0][history_type + HIST_OFFSET_TRANSPORTED] += pax_left_to_do;
1928
1929 // destination logged
1930 merke_passagier_ziel(dest_pos, color_idx_to_rgb(COL_YELLOW));
1931 }
1932 else if( route_result==haltestelle_t::ROUTE_WALK ) {
1933 if( factory_entry ) {
1934 // workers and mail delivered instantly to factory
1935 factory_entry->factory->liefere_an(wtyp, pax_left_to_do);
1936 }
1937
1938 // log walked at stop
1939 start_halt->add_pax_walked(pax_left_to_do);
1940
1941 // people who walk or deliver by hand logged as walking
1942 city_history_year[0][history_type + HIST_OFFSET_WALKED] += pax_left_to_do;
1943 city_history_month[0][history_type + HIST_OFFSET_WALKED] += pax_left_to_do;
1944
1945 // probably not a good idea to mark them as player only cares about remote traffic
1946 //merke_passagier_ziel(dest_pos, color_idx_to_rgb(COL_YELLOW));
1947 }
1948 else if( route_result==haltestelle_t::ROUTE_OVERCROWDED ) {
1949 // overcrowded routes cause unhappiness to be logged
1950
1951 if( start_halt.is_bound() ) {
1952 start_halt->add_pax_unhappy(pax_left_to_do);
1953 }
1954 else {
1955 // all routes to goal are overcrowded -> register at first stop (closest)
1956 FOR(vector_tpl<halthandle_t>, const s, start_halts) {
1957 s->add_pax_unhappy(pax_left_to_do);
1958 merke_passagier_ziel(dest_pos, color_idx_to_rgb(COL_ORANGE));
1959 break;
1960 }
1961 }
1962
1963 // destination logged
1964 merke_passagier_ziel(dest_pos, color_idx_to_rgb(COL_ORANGE));
1965 }
1966 else if ( route_result == haltestelle_t::NO_ROUTE ) {
1967 // since there is no route from any start halt -> register no route at first halts (closest)
1968 FOR(vector_tpl<halthandle_t>, const s, start_halts) {
1969 s->add_pax_no_route(pax_left_to_do);
1970 break;
1971 }
1972 merke_passagier_ziel(dest_pos, color_idx_to_rgb(COL_DARK_ORANGE));
1973 #ifdef DESTINATION_CITYCARS
1974 //citycars with destination
1975 generate_private_cars( origin_pos, dest_pos );
1976 #endif
1977 }
1978
1979 // return passenger traffic
1980 if( will_return != no_return ) {
1981 // compute return amount
1982 uint32 pax_return = pax_left_to_do;
1983
1984 // apply return modifiers
1985 if( will_return != city_return && wtyp == goods_manager_t::mail ) {
1986 // attractions and factories return more mail than they receive
1987 pax_return *= MAIL_RETURN_MULTIPLIER_PRODUCERS;
1988 }
1989
1990 // log potential return passengers at destination city
1991 dest_city->city_history_year[0][history_type + HIST_OFFSET_GENERATED] += pax_return;
1992 dest_city->city_history_month[0][history_type + HIST_OFFSET_GENERATED] += pax_return;
1993
1994 // factories generate return traffic
1995 if ( factory_entry ) {
1996 factory_entry->factory->book_stat(pax_return, (ispass ? FAB_PAX_GENERATED : FAB_MAIL_GENERATED));
1997 }
1998
1999 // route type specific logic
2000 if( route_result == haltestelle_t::ROUTE_OK ) {
2001 // send return packet
2002 halthandle_t return_halt = pax.get_ziel();
2003 if( !return_halt->is_overcrowded(wtyp->get_index()) ) {
2004 // stop can receive passengers
2005
2006 // register departed pax/mail at factory
2007 if (factory_entry) {
2008 factory_entry->factory->book_stat(pax_return, ispass ? FAB_PAX_DEPARTED : FAB_MAIL_DEPARTED);
2009 }
2010
2011 // setup ware packet
2012 return_pax.menge = pax_return;
2013 return_pax.set_zielpos(origin_pos);
2014 return_halt->starte_mit_route(return_pax);
2015
2016 // log departed at stop
2017 return_halt->add_pax_happy(pax_return);
2018
2019 // log departed at destination city
2020 dest_city->city_history_year[0][history_type + HIST_OFFSET_TRANSPORTED] += pax_return;
2021 dest_city->city_history_month[0][history_type + HIST_OFFSET_TRANSPORTED] += pax_return;
2022 }
2023 else {
2024 // stop is crowded
2025 return_halt->add_pax_unhappy(pax_return);
2026 }
2027
2028 }
2029 else if( route_result == haltestelle_t::ROUTE_WALK ) {
2030 // walking can produce return flow as a result of commuters to industry, monuments or stupidly big stops
2031
2032 // register departed pax/mail at factory
2033 if ( factory_entry ) {
2034 factory_entry->factory->book_stat(pax_return, ispass ? FAB_PAX_DEPARTED : FAB_MAIL_DEPARTED);
2035 }
2036
2037 // log walked at stop (source and destination stops are the same)
2038 start_halt->add_pax_walked(pax_return);
2039
2040 // log people who walk or deliver by hand
2041 dest_city->city_history_year[0][history_type + HIST_OFFSET_WALKED] += pax_return;
2042 dest_city->city_history_month[0][history_type + HIST_OFFSET_WALKED] += pax_return;
2043 }
2044 else if( route_result == haltestelle_t::ROUTE_OVERCROWDED ) {
2045 // overcrowded routes cause unhappiness to be logged
2046
2047 if (pax.get_ziel().is_bound()) {
2048 pax.get_ziel()->add_pax_unhappy(pax_return);
2049 }
2050 else {
2051 // the unhappy passengers will be added to the first stops near destination (might be none)
2052 const planquadrat_t *const dest_plan = welt->access(dest_pos);
2053 const halthandle_t *const dest_halt_list = dest_plan->get_haltlist();
2054 for (uint h = 0; h < dest_plan->get_haltlist_count(); h++) {
2055 halthandle_t halt = dest_halt_list[h];
2056 if (halt->is_enabled(wtyp)) {
2057 halt->add_pax_unhappy(pax_return);
2058 break;
2059 }
2060 }
2061 }
2062 }
2063 else if (route_result == haltestelle_t::NO_ROUTE) {
2064 // passengers who cannot find a route will be added to the first stops near destination (might be none)
2065 const planquadrat_t *const dest_plan = welt->access(dest_pos);
2066 const halthandle_t *const dest_halt_list = dest_plan->get_haltlist();
2067 for (uint h = 0; h < dest_plan->get_haltlist_count(); h++) {
2068 halthandle_t halt = dest_halt_list[h];
2069 if (halt->is_enabled(wtyp)) {
2070 halt->add_pax_no_route(pax_return);
2071 break;
2072 }
2073 }
2074 }
2075 }
2076 INT_CHECK( "simcity 1579" );
2077 }
2078 }
2079 else {
2080 // assume no free stop to start at all
2081 bool is_there_any_stop = false;
2082
2083 // the unhappy passengers will be added to the first stop if any
2084 for( uint h=0; h<plan->get_haltlist_count(); h++ ) {
2085 halthandle_t halt = plan->get_haltlist()[h];
2086 if( halt->is_enabled(wtyp) ) {
2087 halt->add_pax_unhappy(num_pax);
2088 is_there_any_stop = true; // only overcrowded
2089 break;
2090 }
2091 }
2092
2093 // all passengers without suitable start:
2094 // fake one ride to get a proper display of destinations (although there may be more) ...
2095 pax_return_type will_return;
2096 factory_entry_t *factory_entry = NULL;
2097 stadt_t *dest_city = NULL;
2098 const koord ziel = find_destination(target_factories, city_history_month[0][history_type + HIST_OFFSET_GENERATED], &will_return, factory_entry, dest_city);
2099 if( factory_entry ) {
2100 // consider at most 1 packet's amount as factory-going
2101 sint32 amount = min(PACKET_SIZE, num_pax);
2102 if( welt->get_settings().get_factory_enforce_demand() ) {
2103 // ensure no more than remaining amount
2104 amount = min( amount, factory_entry->remaining );
2105 factory_entry->remaining -= amount;
2106 target_factories.total_remaining -= amount;
2107 }
2108 target_factories.total_generated += amount;
2109 factory_entry->factory->book_stat( amount, ( ispass ? FAB_PAX_GENERATED : FAB_MAIL_GENERATED ) );
2110 }
2111
2112
2113 // log reverse flow at destination city for accurate tally
2114 if( will_return != no_return ) {
2115 uint32 pax_return = num_pax;
2116
2117 // apply return modifiers
2118 if( will_return != city_return && wtyp == goods_manager_t::mail ) {
2119 // attractions and factories return more mail than they receive
2120 pax_return *= MAIL_RETURN_MULTIPLIER_PRODUCERS;
2121 }
2122
2123 // log potential return passengers at destination city
2124 dest_city->city_history_year[0][history_type + HIST_OFFSET_GENERATED] += pax_return;
2125 dest_city->city_history_month[0][history_type + HIST_OFFSET_GENERATED] += pax_return;
2126
2127 // factories generate return traffic
2128 if ( factory_entry ) {
2129 factory_entry->factory->book_stat(pax_return, (ispass ? FAB_PAX_GENERATED : FAB_MAIL_GENERATED));
2130 }
2131
2132 // passengers with no route will be added to the first stops near destination (might be none)
2133 const planquadrat_t *const dest_plan = welt->access(ziel);
2134 const halthandle_t *const dest_halt_list = dest_plan->get_haltlist();
2135 for (uint h = 0; h < dest_plan->get_haltlist_count(); h++) {
2136 halthandle_t halt = dest_halt_list[h];
2137 if ( halt->is_enabled(wtyp) ) {
2138 if( is_there_any_stop ) {
2139 // "just" overcrowded
2140 halt->add_pax_unhappy(pax_return);
2141 }
2142 else {
2143 // no stops at all
2144 halt->add_pax_no_route(pax_return);
2145 }
2146 break;
2147 }
2148 }
2149 }
2150
2151 #ifdef DESTINATION_CITYCARS
2152 //citycars with destination
2153 generate_private_cars( origin_pos, ziel );
2154 #endif
2155 merke_passagier_ziel(ziel, color_idx_to_rgb(COL_ORANGE));
2156 // we show unhappy instead no route for destination stop
2157 }
2158 }
2159
2160
2161 /**
2162 * returns a random and uniformly distributed point within city borders
2163 * @author Hj. Malthaner
2164 */
get_zufallspunkt() const2165 koord stadt_t::get_zufallspunkt() const
2166 {
2167 if(!buildings.empty()) {
2168 gebaeude_t* const gb = pick_any_weighted(buildings);
2169 koord k = gb->get_pos().get_2d();
2170 if(!welt->is_within_limits(k)) {
2171 // this building should not be in this list, since it has been already deleted!
2172 dbg->error("stadt_t::get_zufallspunkt()", "illegal building in city list of %s: %p removing!", this->get_name(), gb);
2173 const_cast<stadt_t*>(this)->buildings.remove(gb);
2174 k = koord(0, 0);
2175 }
2176 return k;
2177 }
2178 // might happen on slow computers during creation of new cities or start of map
2179 return koord(0,0);
2180 }
2181
2182
add_target_city(stadt_t * const city)2183 void stadt_t::add_target_city(stadt_t *const city)
2184 {
2185 target_cities.append(
2186 city,
2187 weight_by_distance( city->get_einwohner()+1, shortest_distance( get_center(), city->get_center() ) )
2188 );
2189 }
2190
2191
recalc_target_cities()2192 void stadt_t::recalc_target_cities()
2193 {
2194 target_cities.clear();
2195 FOR(weighted_vector_tpl<stadt_t*>, const c, welt->get_cities()) {
2196 add_target_city(c);
2197 }
2198 }
2199
2200
add_target_attraction(gebaeude_t * const attraction)2201 void stadt_t::add_target_attraction(gebaeude_t *const attraction)
2202 {
2203 assert( attraction != NULL );
2204 target_attractions.append(
2205 attraction,
2206 weight_by_distance( attraction->get_passagier_level() << 4, shortest_distance( get_center(), attraction->get_pos().get_2d() ) )
2207 );
2208 }
2209
2210
recalc_target_attractions()2211 void stadt_t::recalc_target_attractions()
2212 {
2213 target_attractions.clear();
2214 FOR(weighted_vector_tpl<gebaeude_t*>, const a, welt->get_attractions()) {
2215 add_target_attraction(a);
2216 }
2217 }
2218
2219
2220 /* this function generates a random target for passenger/mail
2221 * changing this strongly affects selection of targets and thus game strategy
2222 */
find_destination(factory_set_t & target_factories,const sint64 generated,pax_return_type * will_return,factory_entry_t * & factory_entry,stadt_t * & dest_city)2223 koord stadt_t::find_destination(factory_set_t &target_factories, const sint64 generated, pax_return_type* will_return, factory_entry_t* &factory_entry, stadt_t* &dest_city)
2224 {
2225 // generate factory traffic when required
2226 if( target_factories.total_remaining>0 && (sint64)target_factories.generation_ratio>((sint64)(target_factories.total_generated*100)<<RATIO_BITS)/(generated+1) ) {
2227 factory_entry_t *const entry = target_factories.get_random_entry();
2228 assert( entry );
2229 *will_return = factory_return; // worker will return
2230 factory_entry = entry;
2231 dest_city = this; // factory is part of city
2232 return entry->factory->get_pos().get_2d();
2233 }
2234
2235 // chance to generate tourist traffic
2236 const sint16 rand = simrand(100 - (target_factories.generation_ratio >> RATIO_BITS));
2237 if( rand < welt->get_settings().get_tourist_percentage() && target_attractions.get_sum_weight() > 0 ) {
2238 *will_return = tourist_return; // tourists will return
2239 gebaeude_t *const &attraction = pick_any_weighted(target_attractions);
2240 dest_city = attraction->get_stadt(); // unsure if return value always valid
2241 if (dest_city == NULL) {
2242 // if destination city was invalid assume this city is the source
2243 dest_city = this;
2244 }
2245 return attraction->get_pos().get_2d();
2246 }
2247
2248 // generate general traffic between buildings
2249
2250 // since the locality is already taken into account for us, we just use the random weight
2251 stadt_t *const selected_city = pick_any_weighted( target_cities );
2252 // no return trip if the destination is inside the same city
2253 *will_return = selected_city == this ? no_return : city_return;
2254 dest_city = selected_city;
2255 // find a random spot inside the selected city
2256 return selected_city->get_zufallspunkt();
2257
2258 }
2259
2260
merke_passagier_ziel(koord k,PIXVAL color)2261 void stadt_t::merke_passagier_ziel(koord k, PIXVAL color)
2262 {
2263 const koord p = koord(
2264 ((k.x * PAX_DESTINATIONS_SIZE) / welt->get_size().x) & (PAX_DESTINATIONS_SIZE-1),
2265 ((k.y * PAX_DESTINATIONS_SIZE) / welt->get_size().y) & (PAX_DESTINATIONS_SIZE-1)
2266 );
2267 pax_destinations_new_change ++;
2268 pax_destinations_new.set(p, color);
2269 }
2270
2271
2272 /**
2273 * building_place_with_road_finder:
2274 * Search a free place for a building using function suche_platz() (search place).
2275 * added: Minimum distance between monuments
2276 * @author V. Meyer/prissi
2277 */
2278 class building_place_with_road_finder: public building_placefinder_t
2279 {
2280 public:
2281 /// if false, this will the check 'do not build next other to special buildings'
2282 bool big_city;
2283
building_place_with_road_finder(karte_t * welt,sint16 radius,bool big)2284 building_place_with_road_finder(karte_t* welt, sint16 radius, bool big) : building_placefinder_t(welt, radius), big_city(big) {}
2285
2286 // get distance to next special building
find_dist_next_special(koord pos) const2287 int find_dist_next_special(koord pos) const
2288 {
2289 const weighted_vector_tpl<gebaeude_t*>& attractions = welt->get_attractions();
2290 int dist = welt->get_size().x * welt->get_size().y;
2291 FOR( weighted_vector_tpl<gebaeude_t*>, const i, attractions ) {
2292 int const d = koord_distance(i->get_pos(), pos);
2293 if( d < dist ) {
2294 dist = d;
2295 }
2296 }
2297 FOR( weighted_vector_tpl<stadt_t *>, const city, welt->get_cities() ) {
2298 int const d = koord_distance(city->get_pos(), pos);
2299 if( d < dist ) {
2300 dist = d;
2301 }
2302 }
2303 return dist;
2304 }
2305
is_area_ok(koord pos,sint16 w,sint16 h,climate_bits cl) const2306 bool is_area_ok(koord pos, sint16 w, sint16 h, climate_bits cl) const OVERRIDE
2307 {
2308 if( !building_placefinder_t::is_area_ok(pos, w, h, cl) ) {
2309 return false;
2310 }
2311 bool next_to_road = false;
2312 // not direct next to factories or townhalls
2313 for (sint16 x = -1; x < w; x++) {
2314 for (sint16 y = -1; y < h; y++) {
2315 grund_t *gr = welt->lookup_kartenboden(pos + koord(x,y));
2316 if (!gr) {
2317 return false;
2318 }
2319 if ( 0 <= x && x < w-1 && 0 <= y && y < h-1) {
2320 // inside: nothing on top like elevated monorails?
2321 if( gr->get_leitung()!=NULL || welt->lookup(gr->get_pos()+koord3d(0,0,1) )!=NULL) {
2322 // something on top (monorail or powerlines)
2323 return false;
2324 }
2325
2326 }
2327 else {
2328 // border: not direct next to special buildings
2329 if (big_city) {
2330 if( gebaeude_t *gb=gr->find<gebaeude_t>() ) {
2331 const building_desc_t::btype utyp = gb->get_tile()->get_desc()->get_type();
2332 if( building_desc_t::attraction_city <= utyp && utyp <= building_desc_t::headquarters) {
2333 return false;
2334 }
2335 }
2336 }
2337 // but near a road if possible
2338 if (!next_to_road) {
2339 next_to_road = gr->hat_weg(road_wt);
2340 }
2341 }
2342 }
2343 }
2344 if (!next_to_road) {
2345 return false;
2346 }
2347
2348 // try to built a little away from previous ones
2349 if (big_city && find_dist_next_special(pos) < w + h + welt->get_settings().get_special_building_distance() ) {
2350 return false;
2351 }
2352 return true;
2353 }
2354 };
2355
2356
check_bau_spezial(bool new_town)2357 void stadt_t::check_bau_spezial(bool new_town)
2358 {
2359 // tourist attraction buildings
2360 const building_desc_t* desc = hausbauer_t::get_special( bev, building_desc_t::attraction_city, welt->get_timeline_year_month(), new_town, welt->get_climate(pos) );
2361 if (desc != NULL) {
2362 if (simrand(100) < (uint)desc->get_distribution_weight()) {
2363
2364 bool big_city = buildings.get_count() >= 10;
2365 bool is_rotate = desc->get_all_layouts() > 1;
2366 sint16 radius = koord_distance( get_rechtsunten(), get_linksoben() )/2 + 10;
2367 // find place
2368 koord best_pos = building_place_with_road_finder(welt, radius, big_city).find_place(pos, desc->get_x(), desc->get_y(), desc->get_allowed_climate_bits(), &is_rotate);
2369
2370 if (best_pos != koord::invalid) {
2371 // then built it
2372 int rotate = 0;
2373 if (desc->get_all_layouts() > 1) {
2374 rotate = (simrand(20) & 2) + is_rotate;
2375 }
2376 hausbauer_t::build( owner, welt->lookup_kartenboden(best_pos)->get_pos(), rotate, desc );
2377 // tell the player, if not during initialization
2378 if (!new_town) {
2379 cbuffer_t buf;
2380 buf.printf( translator::translate("To attract more tourists\n%s built\na %s\nwith the aid of\n%i tax payers."), get_name(), make_single_line_string(translator::translate(desc->get_name()), 2), get_einwohner());
2381 welt->get_message()->add_message(buf, best_pos, message_t::city, CITY_KI, desc->get_tile(0)->get_background(0, 0, 0));
2382 }
2383 }
2384 }
2385 }
2386
2387 if ((bev & 511) == 0) {
2388 // Build a monument
2389 desc = hausbauer_t::get_random_monument(welt->get_timeline_year_month());
2390 if (desc) {
2391 koord total_size = koord(2 + desc->get_x(), 2 + desc->get_y());
2392 sint16 radius = koord_distance( get_rechtsunten(), get_linksoben() )/2 + 10;
2393 koord best_pos(monument_placefinder_t(welt, radius).find_place(pos, total_size.x, total_size.y, desc->get_allowed_climate_bits()));
2394
2395 if (best_pos != koord::invalid) {
2396 // check if borders around the monument are inside the map limits
2397 const bool pre_ok = welt->is_within_limits( koord(best_pos) - koord(1, 1) ) && \
2398 welt->is_within_limits( koord(best_pos) + total_size + koord(1, 1) );
2399 if (!pre_ok){
2400 return;
2401 }
2402
2403 bool ok=false;
2404
2405 // We build the monument only if there is already at least one road
2406 for (int i = 0; i < total_size.x && !ok; i++) {
2407 ok = ok ||
2408 welt->access(best_pos + koord(i, -1))->get_kartenboden()->hat_weg(road_wt) ||
2409 welt->access(best_pos + koord(i, total_size.y))->get_kartenboden()->hat_weg(road_wt);
2410 }
2411 for (int i = 0; i < total_size.y && !ok; i++) {
2412 ok = ok ||
2413 welt->access(best_pos + koord(total_size.x, i))->get_kartenboden()->hat_weg(road_wt) ||
2414 welt->access(best_pos + koord(-1, i))->get_kartenboden()->hat_weg(road_wt);
2415 }
2416 if (ok) {
2417 // build roads around the monument
2418 sint16 h=welt->lookup_kartenboden(best_pos)->get_hoehe();
2419 for (int i = 0; i < total_size.y; i++) {
2420 // only build in same height and not on slopes...
2421 const grund_t *gr = welt->lookup_kartenboden(best_pos + koord(0, i));
2422 if(gr->get_hoehe()==h && gr->get_grund_hang()==0) {
2423 build_road(best_pos + koord(0, i), NULL, true);
2424 }
2425 gr = welt->lookup_kartenboden(best_pos + koord(total_size.x - 1, i));
2426 if(gr->get_hoehe()==h && gr->get_grund_hang()==0) {
2427 build_road(best_pos + koord(total_size.x - 1, i), NULL, true);
2428 }
2429 }
2430 for (int i = 0; i < total_size.x; i++) {
2431 // only build in same height and not on slopes...
2432 const grund_t *gr = welt->lookup_kartenboden(best_pos + koord(i, 0));
2433 if(gr->get_hoehe()==h && gr->get_grund_hang()==0) {
2434 build_road(best_pos + koord(i, 0), NULL, true);
2435 }
2436 gr = welt->lookup_kartenboden(best_pos + koord(i, total_size.y - 1));
2437 if(gr->get_hoehe()==h && gr->get_grund_hang()==0) {
2438 build_road(best_pos + koord(i, total_size.y - 1), NULL, true);
2439 }
2440 }
2441 // and then build it
2442 const gebaeude_t* gb = hausbauer_t::build(owner, welt->lookup_kartenboden(best_pos + koord(1, 1))->get_pos(), 0, desc);
2443 hausbauer_t::monument_erected(desc);
2444 add_gebaeude_to_stadt(gb);
2445 // tell the player, if not during initialization
2446 if (!new_town) {
2447 cbuffer_t buf;
2448 buf.printf( translator::translate("With a big festival\n%s built\na new monument.\n%i citicens rejoiced."), get_name(), get_einwohner() );
2449 welt->get_message()->add_message(buf, best_pos + koord(1, 1), message_t::city, CITY_KI, desc->get_tile(0)->get_background(0, 0, 0));
2450 }
2451 }
2452 }
2453 }
2454 }
2455 }
2456
2457
check_bau_townhall(bool new_town)2458 void stadt_t::check_bau_townhall(bool new_town)
2459 {
2460 const building_desc_t* desc = hausbauer_t::get_special( has_townhall ? bev : 0, building_desc_t::townhall, welt->get_timeline_year_month(), (bev == 0) || !has_townhall, welt->get_climate(pos) );
2461 if(desc != NULL) {
2462 grund_t* gr = welt->lookup_kartenboden(pos);
2463 gebaeude_t* gb = obj_cast<gebaeude_t>(gr->first_obj());
2464 bool neugruendung = !has_townhall || !gb || !gb->is_townhall();
2465 bool umziehen = !neugruendung;
2466 koord alte_str(koord::invalid);
2467 koord best_pos(pos);
2468 koord k;
2469 int old_layout(0);
2470
2471 DBG_MESSAGE("check_bau_townhall()", "bev=%d, new=%d name=%s", bev, neugruendung, name.c_str());
2472
2473 if( umziehen ) {
2474
2475 const building_desc_t* desc_old = gb->get_tile()->get_desc();
2476 if (desc_old->get_level() == desc->get_level()) {
2477 DBG_MESSAGE("check_bau_townhall()", "town hall already ok.");
2478 return; // Rathaus ist schon okay
2479 }
2480 old_layout = gb->get_tile()->get_layout();
2481 const sint8 old_z = gb->get_pos().z;
2482 koord pos_alt = best_pos = gr->get_pos().get_2d() - gb->get_tile()->get_offset();
2483 // guess layout for broken townhall's
2484 if(desc_old->get_x() != desc_old->get_y() && desc_old->get_all_layouts()==1) {
2485 // test all layouts
2486 koord corner_offset(desc_old->get_x()-1, desc_old->get_y()-1);
2487 for(uint8 test_layout = 0; test_layout<4; test_layout++) {
2488 // is there a part of our townhall in this corner
2489 grund_t *gr0 = welt->lookup_kartenboden(pos + corner_offset);
2490 gebaeude_t const* const gb0 = gr0 ? obj_cast<gebaeude_t>(gr0->first_obj()) : 0;
2491 if (gb0 && gb0->is_townhall() && gb0->get_tile()->get_desc()==desc_old && gb0->get_stadt()==this) {
2492 old_layout = test_layout;
2493 pos_alt = best_pos = gr->get_pos().get_2d() + koord(test_layout%3!=0 ? corner_offset.x : 0, test_layout&2 ? corner_offset.y : 0);
2494 break;
2495 }
2496 corner_offset = koord(-corner_offset.y, corner_offset.x);
2497 }
2498 }
2499 koord groesse_alt = desc_old->get_size(old_layout);
2500
2501 // do we need to move
2502 if( old_layout<=desc->get_all_layouts() && desc->get_x(old_layout) <= groesse_alt.x && desc->get_y(old_layout) <= groesse_alt.y ) {
2503 // no, the size is ok
2504 // still need to check whether the existing townhall is not broken in some way
2505 umziehen = false;
2506 for(k.y = 0; k.y < groesse_alt.y; k.y ++) {
2507 for(k.x = 0; k.x < groesse_alt.x; k.x ++) {
2508 // for buildings with holes the hole could be on a different height ->gr==NULL
2509 bool ok = false;
2510 if (grund_t *gr = welt->lookup_kartenboden(k + pos)) {
2511 if(gebaeude_t *gb_part = gr->find<gebaeude_t>()) {
2512 // there may be buildings with holes, so we only remove our building!
2513 if(gb_part->get_tile() == desc_old->get_tile(old_layout, k.x, k.y)) {
2514 ok = true;
2515 }
2516 }
2517 }
2518 umziehen |= !ok;
2519 }
2520 }
2521 if (!umziehen) {
2522 // correct position if new townhall is smaller than old
2523 if( old_layout == 0 ) {
2524 best_pos.y -= desc->get_y(old_layout) - groesse_alt.y;
2525 }
2526 else if (old_layout == 1) {
2527 best_pos.x -= desc->get_x(old_layout) - groesse_alt.x;
2528 }
2529 }
2530 }
2531 if (umziehen) {
2532 // we need to built a new road, thus we will use the old as a starting point (if found)
2533 if (welt->lookup_kartenboden(townhall_road) && welt->lookup_kartenboden(townhall_road)->hat_weg(road_wt)) {
2534 alte_str = townhall_road;
2535 }
2536 else {
2537 koord k = pos + (old_layout==0 ? koord(0, desc_old->get_y()) : koord(desc_old->get_x(),0) );
2538 if (welt->lookup_kartenboden(k)->hat_weg(road_wt)) {
2539 alte_str = k;
2540 }
2541 else {
2542 k = pos - (old_layout==0 ? koord(0, desc_old->get_y()) : koord(desc_old->get_x(),0) );
2543 if (welt->lookup_kartenboden(k)->hat_weg(road_wt)) {
2544 alte_str = k;
2545 }
2546 }
2547 }
2548 }
2549
2550 // remove old townhall
2551 if( gb ) {
2552 DBG_MESSAGE("stadt_t::check_bau_townhall()", "delete townhall at (%s)", pos_alt.get_str());
2553 hausbauer_t::remove(NULL, gb);
2554 }
2555
2556 // replace old space by normal houses level 0 (must be 1x1!)
2557 if( umziehen ) {
2558 for (k.x = 0; k.x < groesse_alt.x; k.x++) {
2559 for (k.y = 0; k.y < groesse_alt.y; k.y++) {
2560 // we iterate over all tiles, since the townhalls are allowed sizes bigger than 1x1
2561 const koord pos = pos_alt + k;
2562 gr = welt->lookup_kartenboden(pos);
2563 if (gr && gr->ist_natur() && gr->kann_alle_obj_entfernen(NULL) == NULL &&
2564 ( gr->get_grund_hang() == slope_t::flat || welt->lookup(koord3d(k, welt->max_hgt(k))) == NULL ) ) {
2565 DBG_MESSAGE("stadt_t::check_bau_townhall()", "fill empty spot at (%s)", pos.get_str());
2566 build_city_building(pos);
2567 }
2568 }
2569 }
2570 }
2571 else {
2572 // make tiles flat, hausbauer_t::remove could have set some natural slopes
2573 for( k.x = 0; k.x < desc->get_x(old_layout); k.x++ ) {
2574 for( k.y = 0; k.y < desc->get_y(old_layout); k.y++ ) {
2575 gr = welt->lookup_kartenboden(best_pos + k);
2576 if( gr && gr->ist_natur() ) {
2577 // make flat and use right height
2578 gr->set_grund_hang(slope_t::flat);
2579 gr->set_pos( koord3d( best_pos + k, old_z ) );
2580 }
2581 }
2582 }
2583 }
2584 }
2585
2586 // Now built the new townhall (remember old orientation)
2587 int layout = umziehen || neugruendung ? simrand(desc->get_all_layouts()) : old_layout % desc->get_all_layouts();
2588 // on which side should we place the road?
2589 uint8 dir;
2590 // offset of building within searched place, start and end of road
2591 koord offset(0,0), road0(0,0),road1(0,0);
2592 dir = ribi_t::layout_to_ribi[layout & 3];
2593 switch(dir) {
2594 case ribi_t::east:
2595 road0.x = desc->get_x(layout);
2596 road1.x = desc->get_x(layout);
2597 road1.y = desc->get_y(layout)-1;
2598 break;
2599 case ribi_t::north:
2600 road1.x = desc->get_x(layout)-1;
2601 if (neugruendung || umziehen) {
2602 offset.y = 1;
2603 }
2604 else {
2605 // offset already included in position of old townhall
2606 road0.y=-1;
2607 road1.y=-1;
2608 }
2609 break;
2610 case ribi_t::west:
2611 road1.y = desc->get_y(layout)-1;
2612 if (neugruendung || umziehen) {
2613 offset.x = 1;
2614 }
2615 else {
2616 // offset already included in in position of old townhall
2617 road0.x=-1;
2618 road1.x=-1;
2619 }
2620 break;
2621 case ribi_t::south:
2622 default:
2623 road0.y = desc->get_y(layout);
2624 road1.x = desc->get_x(layout)-1;
2625 road1.y = desc->get_y(layout);
2626 }
2627 if (neugruendung || umziehen) {
2628 best_pos = townhall_placefinder_t(welt, dir).find_place(pos, desc->get_x(layout) + (dir & ribi_t::eastwest ? 1 : 0), desc->get_y(layout) + (dir & ribi_t::northsouth ? 1 : 0), desc->get_allowed_climate_bits());
2629 }
2630 // check, if the was something found
2631 if(best_pos==koord::invalid) {
2632 dbg->error( "stadt_t::check_bau_townhall", "no better position found!" );
2633 return;
2634 }
2635 gebaeude_t const* const new_gb = hausbauer_t::build(owner, welt->lookup_kartenboden(best_pos + offset)->get_pos(), layout, desc);
2636 DBG_MESSAGE("new townhall", "use layout=%i", layout);
2637 add_gebaeude_to_stadt(new_gb);
2638 // sets has_townhall to true
2639 DBG_MESSAGE("stadt_t::check_bau_townhall()", "add townhall (bev=%i, ptr=%p)", buildings.get_sum_weight(),welt->lookup_kartenboden(best_pos)->first_obj());
2640
2641 // if not during initialization
2642 if (!new_town) {
2643 cbuffer_t buf;
2644 buf.printf(translator::translate("%s wasted\nyour money with a\nnew townhall\nwhen it reached\n%i inhabitants."), name.c_str(), get_einwohner());
2645 welt->get_message()->add_message(buf, best_pos, message_t::city, CITY_KI, desc->get_tile(layout, 0, 0)->get_background(0, 0, 0));
2646 }
2647 else {
2648 welt->lookup_kartenboden(best_pos + offset)->set_text( name );
2649 }
2650
2651 if (neugruendung || umziehen) {
2652 // build the road in front of the townhall
2653 if (road0!=road1) {
2654 way_builder_t bauigel(NULL);
2655 bauigel.init_builder(way_builder_t::strasse, welt->get_city_road(), NULL, NULL);
2656 bauigel.set_build_sidewalk(true);
2657 bauigel.calc_straight_route(welt->lookup_kartenboden(best_pos + road0)->get_pos(), welt->lookup_kartenboden(best_pos + road1)->get_pos());
2658 bauigel.build();
2659 }
2660 else {
2661 build_road(best_pos + road0, NULL, true);
2662 }
2663 townhall_road = best_pos + road0;
2664 }
2665 if (umziehen && alte_str != koord::invalid) {
2666 // Strasse vom ehemaligen Rathaus zum neuen verlegen.
2667 way_builder_t bauer(NULL);
2668 bauer.init_builder(way_builder_t::strasse | way_builder_t::terraform_flag, welt->get_city_road());
2669 bauer.calc_route(welt->lookup_kartenboden(alte_str)->get_pos(), welt->lookup_kartenboden(townhall_road)->get_pos());
2670 bauer.build();
2671 }
2672 else if (neugruendung) {
2673 lo = best_pos+offset - koord(2, 2);
2674 ur = best_pos+offset + koord(desc->get_x(layout), desc->get_y(layout)) + koord(2, 2);
2675 }
2676 const koord new_pos = best_pos + offset;
2677 if( pos!=new_pos ) {
2678 // update position (where the name is)
2679 welt->lookup_kartenboden(pos)->set_text( NULL );
2680 pos = new_pos;
2681 welt->lookup_kartenboden(pos)->set_text( name );
2682 }
2683 }
2684 }
2685
2686
2687 /* eventually adds a new industry
2688 * so with growing number of inhabitants the industry grows
2689 * @date 12.1.05
2690 * @author prissi
2691 */
check_bau_factory(bool new_town)2692 void stadt_t::check_bau_factory(bool new_town)
2693 {
2694 uint32 const inc = welt->get_settings().get_industry_increase_every();
2695 if( !new_town && inc > 0 && bev % inc == 0 ) {
2696 uint32 const div = bev / inc;
2697 for( uint8 i = 0; i < 8; i++ ) {
2698 if( div == (1u<<i) ) {
2699 DBG_MESSAGE("stadt_t::check_bau_factory", "adding new industry at %i inhabitants.", get_einwohner());
2700 factory_builder_t::increase_industry_density( true );
2701 }
2702 }
2703 }
2704 }
2705
2706
2707 // find out, what building matches best
bewerte_res_com_ind(const koord pos,int & ind_score,int & com_score,int & res_score)2708 void stadt_t::bewerte_res_com_ind(const koord pos, int &ind_score, int &com_score, int &res_score)
2709 {
2710 koord k;
2711
2712 ind_score = ind_start_score;
2713 com_score = com_start_score;
2714 res_score = res_start_score;
2715
2716 for (k.y = pos.y - 2; k.y <= pos.y + 2; k.y++) {
2717 for (k.x = pos.x - 2; k.x <= pos.x + 2; k.x++) {
2718
2719 building_desc_t::btype t = building_desc_t::unknown;
2720 if (const grund_t* gr = welt->lookup_kartenboden(k)) {
2721 if (gebaeude_t const* const gb = obj_cast<gebaeude_t>(gr->first_obj())) {
2722 t = gb->get_tile()->get_desc()->get_type();
2723 }
2724 }
2725
2726 int i = -1;
2727 switch(t) {
2728 case building_desc_t::city_res: i = 0; break;
2729 case building_desc_t::city_com: i = 1; break;
2730 case building_desc_t::city_ind: i = 2; break;
2731 default: ;
2732 }
2733 if (i >= 0) {
2734 ind_score += ind_neighbour_score[i];
2735 com_score += com_neighbour_score[i];
2736 res_score += res_neighbour_score[i];
2737 }
2738 }
2739 }
2740 }
2741
2742
2743 // return the eight neighbors:
2744 // orthogonal before diagonal
2745 static koord const neighbors[] = {
2746 koord( 0, 1),
2747 koord( 1, 0),
2748 koord( 0, -1),
2749 koord(-1, 0),
2750 // now the diagonals
2751 koord( 1, 1),
2752 koord( 1, -1),
2753 koord(-1, 1),
2754 koord(-1, -1)
2755 };
2756
2757 static koord const area3x3[] = {
2758 koord( 0, 1), // 1x2
2759 koord( 1, 0), // 2x1
2760 koord( 1, 1), // 2x2
2761 koord( 2, 0), // 3x1
2762 koord( 2, 1), // 3x2
2763 koord( 0, 2), // 1x3
2764 koord( 2, 2) // 3x3
2765 };
2766
2767 // updates one surrounding road with current city road
update_city_street(koord pos)2768 bool update_city_street(koord pos)
2769 {
2770 // !!! We should take the bulding size into consideration, missing!!!
2771 const way_desc_t* cr = world()->get_city_road();
2772 for( int i=0; i<8; i++ ) {
2773 if( grund_t *gr = world()->lookup_kartenboden(pos+neighbors[i]) ) {
2774 if( weg_t* const weg = gr->get_weg(road_wt) ) {
2775 // Check if any changes are needed.
2776 if( !weg->hat_gehweg() || weg->get_desc() != cr ) {
2777 player_t *sp = weg->get_owner();
2778 if( sp ){
2779 player_t::add_maintenance(sp, -weg->get_desc()->get_maintenance(), road_wt);
2780 weg->set_owner(NULL); // make public
2781 }
2782 weg->set_gehweg(true);
2783 weg->set_desc(cr);
2784 gr->calc_image();
2785 minimap_t::get_instance()->calc_map_pixel(pos+neighbors[i]);
2786 return true; // update only one road per renovation
2787 }
2788 }
2789 }
2790 }
2791 return false;
2792 }
2793
2794
2795 // return layout
2796 #define CHECK_NEIGHBOUR (128)
2797 static int const building_layout[] = { CHECK_NEIGHBOUR | 0, 0, 1, 4, 2, 0, 5, CHECK_NEIGHBOUR | 1, 3, 7, 1, CHECK_NEIGHBOUR | 0, 6, CHECK_NEIGHBOUR | 3, CHECK_NEIGHBOUR | 2, CHECK_NEIGHBOUR | 0 };
2798
2799
2800 // calculates the "best" oreintation of a citybuilding
orient_city_building(const koord k,const building_desc_t * h,koord maxarea)2801 int stadt_t::orient_city_building(const koord k, const building_desc_t *h, koord maxarea )
2802 {
2803 /*******************************************************
2804 * these are the layout possible for city buildings
2805 ********************************************************
2806 dims=1,1,1
2807 +---+
2808 |000|
2809 |0 0|
2810 |000|
2811 +---+
2812 dims=1,1,2
2813 +---+
2814 |001|
2815 |1 1|
2816 |100|
2817 +---+
2818 dims=1,1,4
2819 +---+
2820 |221|
2821 |3 1|
2822 |300|
2823 +---+
2824 dims=1,1,8
2825 +---+
2826 |625|
2827 |3 1|
2828 |704|
2829 +---+
2830 ********************************************************/
2831
2832 // we have something to built here ...
2833 if( h == NULL ) {
2834 return -1;
2835 }
2836
2837 // old, highly sophisticated routines for 1x1 buildings
2838 if( h->get_x()*h->get_y()==1 ) {
2839 if( grund_t *gr = welt->lookup_kartenboden(k) ) {
2840 int rotation = 0;
2841 int max_layout = h->get_all_layouts()-1;
2842 if( max_layout ) {
2843 // check for pavement
2844 int streetdir = 0;
2845 for( int i = 0; i < 4; i++ ) {
2846 // Neighbors goes through these in 'preferred' order, orthogonal first
2847 gr = welt->lookup_kartenboden(k + neighbors[i]);
2848 if( gr && gr->get_weg_hang() == gr->get_grund_hang() && gr->hat_weg(road_wt) ){
2849 streetdir += (1 << i);
2850 }
2851 }
2852 // not completely unique layout, see if any of the neighbouring building gives a hint
2853 rotation = building_layout[streetdir] & ~CHECK_NEIGHBOUR;
2854 // for four rotation stop here ...
2855 if( max_layout<7 ) {
2856 return rotation & max_layout;
2857 }
2858 // now this is an eight roation building, so we must put in more effort
2859 bool unique_orientation = !(building_layout[streetdir] & CHECK_NEIGHBOUR);
2860 if( !unique_orientation ) {
2861 // no unique answer, check nearby buildings (more likely to fail)
2862 int gb_dir = 0;
2863 for( int i = 0; i < 4; i++ ) {
2864 // look for adjacent buildings
2865 gr = welt->lookup_kartenboden(k + neighbors[i]);
2866 if( gr && gr->get_typ()==grund_t::fundament ){
2867 if( gr->find<gebaeude_t>() ) {
2868 gb_dir |= (1<<i);
2869 }
2870 }
2871 }
2872 // lets hope this gives an unique answer
2873 static uint8 gb_dir_to_layout[16] = { CHECK_NEIGHBOUR, 1, 0, 6, 1, 1, 7, CHECK_NEIGHBOUR, 0, 5, 0, CHECK_NEIGHBOUR, 4, CHECK_NEIGHBOUR, CHECK_NEIGHBOUR, CHECK_NEIGHBOUR };
2874 if( gb_dir_to_layout[gb_dir] == CHECK_NEIGHBOUR ) {
2875 return rotation;
2876 }
2877 // ok our answer is unique, now we just check for left and right via street nearby
2878 rotation = gb_dir_to_layout[gb_dir];
2879 if( rotation<2 ) {
2880 // check on which side is the road
2881 if( streetdir & 0x0C ) {
2882 return rotation + 2;
2883 }
2884 }
2885 }
2886 }
2887 return rotation;
2888 }
2889 return -1;
2890 }
2891
2892 // if we arrive here, we have a multitile building
2893 if( grund_t *gr = welt->lookup_kartenboden(k) ) {
2894 int rotation = -1;
2895 int max_layout = h->get_all_layouts()-1;
2896 if( max_layout ) {
2897
2898 // we counting the streetiles, but asymmetric buildings will have an uneven number; we init with negative width
2899 int streetdir[4];
2900 for( int i = 0; i < 4; i++ ) {
2901 streetdir[i] = -h->get_x(i&1);
2902 }
2903 int roads_found = 0;
2904
2905 // now just counting street tiles north/south of the house ...
2906 sint16 extra_offset = h->get_y(0)-1;
2907 for( int offset = -1; offset <= h->get_x(0); offset++ ) {
2908 gr = welt->lookup_kartenboden(k + koord(offset,1+extra_offset) );
2909 if( gr && gr->hat_weg(road_wt) ){
2910 streetdir[0] ++;
2911 roads_found ++;
2912 }
2913 gr = welt->lookup_kartenboden(k + koord(offset,-1) );
2914 if( gr && gr->hat_weg(road_wt) ){
2915 streetdir[2] ++;
2916 roads_found ++;
2917 }
2918 }
2919 // ... and east/west
2920 for( int offset = -1; offset <= h->get_x(1); offset++ ) {
2921 // Neighbors goes through these in 'preferred' order, orthogonal first
2922 gr = welt->lookup_kartenboden(k + koord(1+extra_offset,offset) );
2923 if( gr && gr->hat_weg(road_wt) ){
2924 streetdir[1] ++;
2925 roads_found ++;
2926 }
2927 // Neighbors goes through these in 'preferred' order, orthogonal first
2928 gr = welt->lookup_kartenboden(k + koord(-1,offset) );
2929 if( gr && gr->hat_weg(road_wt) ){
2930 streetdir[3] ++;
2931 roads_found ++;
2932 }
2933 }
2934
2935 // first, make sure we found some roads
2936 if( roads_found > 0 ) {
2937
2938 // now find the two sides with most streets around
2939 int largest_dir_count = -9999, largest_2nd_count = -9999;
2940 int largest_dir = -1, largest_2nd_dir = -1;
2941 for( int i=0; i<4; i++ ) {
2942 if( streetdir[i] > largest_dir_count ) {
2943 largest_dir_count = streetdir[i];
2944 largest_dir = i;
2945 }
2946 else if( streetdir[i] > largest_2nd_count ) {
2947 largest_2nd_dir = i;
2948 }
2949 }
2950
2951 // so we have two adjacent corners with the most roads
2952 if( max_layout > 3 && ((largest_2nd_dir-largest_dir)==1 || (largest_2nd_dir-largest_dir)==3) ) {
2953 // corner cases: only roads on two sides
2954 if( streetdir[0]<0 && streetdir[1]<0 ) {
2955 rotation = 7;
2956 }
2957 else if( streetdir[2]<0 && streetdir[3]<0 ) {
2958 rotation = 4;
2959 }
2960 else if( streetdir[3]<0 && streetdir[0]<0 ) {
2961 rotation = 5;
2962 }
2963 else if( streetdir[0]<0 && streetdir[1]<0 ) {
2964 rotation = 6;
2965 }
2966 // some valid found?
2967 if( rotation >=0 && h->get_x(rotation) <= maxarea.x && h->get_y(rotation) <= maxarea.y ) {
2968 return rotation;
2969 }
2970 }
2971
2972 // now we have to check right of it
2973 if( streetdir[(largest_dir+1)&3] == largest_dir_count ) {
2974 // but since we take the first, if the next two corner have the same street count, better rotate one further
2975 if( streetdir[(largest_dir+2)&3] == largest_dir_count ) {
2976 // both next corners same count
2977 rotation = largest_dir+1;
2978 }
2979 else {
2980 rotation = largest_dir;
2981 }
2982 rotation &= max_layout;
2983 }
2984 // and left of it
2985 else if( streetdir[(largest_dir+3)&3] == largest_dir_count ) {
2986 // but since we take the first, if the next two corner have the same street count, better rotate one further
2987 if( streetdir[(largest_dir+2)&3] == largest_dir_count ) {
2988 // both next corners same count
2989 rotation = largest_dir+3;
2990 }
2991 else {
2992 rotation = largest_dir;
2993 }
2994 rotation &= max_layout;
2995 }
2996 // this is the really only longest one
2997 else {
2998 rotation = largest_dir & max_layout;
2999 }
3000
3001 // some valid found?
3002 if( rotation >= 0 && h->get_x(rotation) <= maxarea.x && h->get_y(rotation) <= maxarea.y ) {
3003 return rotation;
3004 }
3005
3006 return -1;
3007 }
3008
3009 // no roads or not fitting
3010 if( roads_found == 0 ) {
3011 bool even_ok = (maxarea.x <= h->get_x(0) && maxarea.y <= h->get_y(0));
3012 bool odd_ok = (maxarea.x <= h->get_x(1) && maxarea.y <= h->get_y(1));
3013
3014 if( even_ok && odd_ok ) {
3015 // no roads at all and both rotations fit => random oreintation (but no corner)
3016 return simrand(4) % max_layout;
3017 }
3018 else if( even_ok ) {
3019 return (simrand(2)*2) % max_layout;
3020 }
3021 else if( odd_ok ) {
3022 return (simrand(2)*2+1) % max_layout;
3023 }
3024 // nothing fits, should not happen!
3025 assert(1);
3026 }
3027
3028 // we have a preferred orientation, but it does not fit => gave up
3029 return -1;
3030 }
3031
3032 // we landed here but maxlayout == 1, so we have only to test for fit
3033 if( maxarea.x <= h->get_x(0) && maxarea.y <= h->get_y(0) ) {
3034 return 0;
3035 }
3036
3037 }
3038
3039 return -1;
3040 }
3041
3042
build_city_building(const koord k)3043 void stadt_t::build_city_building(const koord k)
3044 {
3045 grund_t* gr = welt->lookup_kartenboden(k);
3046
3047 // Not building on ways (this was actually tested before be the cityrules), but you can construct manually
3048 if( !gr->ist_natur() ) {
3049 return;
3050 }
3051 // test ownership of all objects that can block construction
3052 for( uint8 i = 0; i < gr->obj_count(); i++ ) {
3053 obj_t *const obj = gr->obj_bei(i);
3054 if( obj->is_deletable(NULL) != NULL && obj->get_typ() != obj_t::pillar ) {
3055 return;
3056 }
3057 }
3058 // Refuse to build on a slope, when there is a ground right on top of it (=> the house would sit on the bridge then!)
3059 if( gr->get_grund_hang() != slope_t::flat && welt->lookup(koord3d(k, welt->max_hgt(k))) != NULL ) {
3060 return;
3061 }
3062
3063 // Divide unemployed by 4, because it counts towards commercial and industrial,
3064 // and both of those count 'double' for population relative to residential.
3065 int employment_wanted = get_unemployed() / 4;
3066 int housing_wanted = get_homeless();
3067
3068 int industrial_suitability, commercial_suitability, residential_suitability;
3069 bewerte_res_com_ind(k, industrial_suitability, commercial_suitability, residential_suitability );
3070
3071 const int sum_industrial = industrial_suitability + employment_wanted;
3072 const int sum_commercial = commercial_suitability + employment_wanted;
3073 const int sum_residential = residential_suitability + housing_wanted;
3074
3075 // does the timeline allow this building?
3076 const uint16 current_month = welt->get_timeline_year_month();
3077 const climate cl = welt->get_climate(k);
3078
3079
3080 // Run through orthogonal neighbors (only) looking for which cluster to build
3081 // This is a bitmap -- up to 32 clustering types are allowed.
3082 uint32 neighbor_building_clusters = 0;
3083 uint8 area_level=0; // used to calculate the maximum size
3084 sint8 zpos = gr->get_pos().z + slope_t::max_diff(gr->get_grund_hang());
3085 for( int i = 0; i < 4; i++ ) {
3086 grund_t* gr = welt->lookup_kartenboden(k + neighbors[i]);
3087 if( gr && gr->get_typ() == grund_t::fundament && gr->obj_bei(0)->get_typ() == obj_t::gebaeude ) {
3088 // We have a building as a neighbor...
3089 if( gebaeude_t const* const gb = obj_cast<gebaeude_t>(gr->first_obj()) ) {
3090 // We really have a building as a neighbor...
3091 const building_desc_t* neighbor_building = gb->get_tile()->get_desc();
3092 neighbor_building_clusters |= neighbor_building->get_clusters();
3093 if( gb->get_pos().z == zpos && neighbor_building->get_x()*neighbor_building->get_y()==1 ) {
3094 // also in right height and citybuilding, and (1x1) (so we don not tear down existing larger building, even if we can do that)
3095 area_level |= (neighbor_building->is_city_building() << i);
3096 }
3097 }
3098 else if( gr->ist_natur() && gr->get_pos().z+slope_t::max_diff(gr->get_grund_hang())==zpos ) {
3099 // we can of course also build on nature
3100 area_level |= (1 << i);
3101 }
3102 }
3103 }
3104
3105 // since the above test is only enough for 2x1 and 1x2, we must test more tiles, if we want larger
3106 koord maxsize=koord(1,1);
3107 switch( area_level&3 ) {
3108 case 3:
3109 if( hausbauer_t::get_largest_city_building_area() > 2 ) {
3110 // now test the remaining tiles for even laregr size
3111 for( area_level=2; area_level < 8; area_level++ ) {
3112 grund_t* gr = welt->lookup_kartenboden(k + area3x3[area_level]);
3113 if( gr && gr->get_typ() == grund_t::fundament && gr->obj_bei(0)->get_typ() == obj_t::gebaeude ) {
3114 // We have a building as a neighbor...
3115 if( gebaeude_t const* const testgb = obj_cast<gebaeude_t>(gr->first_obj()) ) {
3116 // We really have a building as a neighbor...
3117 const building_desc_t* neighbor_building = testgb->get_tile()->get_desc();
3118 if( testgb->get_pos().z == zpos && neighbor_building->is_city_building() && neighbor_building->get_x()*neighbor_building->get_y()==1 ) {
3119 // also in right height and citybuilding
3120 maxsize = area3x3[area_level]+koord(1,1);
3121 continue;
3122 }
3123 }
3124 else if( gr->ist_natur() && gr->get_pos().z+slope_t::max_diff(gr->get_grund_hang())==zpos ) {
3125 // we can of course also build on nature
3126 maxsize = area3x3[area_level]+koord(1,1);
3127 continue;
3128 }
3129 }
3130 // we only reach here upon unsuitable ground
3131 break;
3132 }
3133 }
3134 break;
3135 case 2:
3136 maxsize = area3x3[1]+koord(1,1);
3137 break;
3138 case 1:
3139 maxsize = area3x3[0]+koord(1,1);
3140 break;
3141 default:
3142 break;
3143 }
3144
3145 // Find a house to build
3146 const building_desc_t* h = NULL;
3147
3148 if (sum_commercial > sum_industrial && sum_commercial >= sum_residential) {
3149 h = hausbauer_t::get_commercial(0, current_month, cl, neighbor_building_clusters, koord(1,1), maxsize);
3150 if (h != NULL) {
3151 arb += (h->get_level()+1) * 20;
3152 }
3153 }
3154
3155 if (h == NULL && sum_industrial > sum_residential && sum_industrial >= sum_commercial) {
3156 h = hausbauer_t::get_industrial(0, current_month, cl, neighbor_building_clusters, koord(1,1), maxsize);
3157 if (h != NULL) {
3158 arb += (h->get_level()+1) * 20;
3159 }
3160 }
3161
3162 if (h == NULL && sum_residential > sum_industrial && sum_residential >= sum_commercial) {
3163 h = hausbauer_t::get_residential(0, current_month, cl, neighbor_building_clusters, koord(1,1), maxsize);
3164 if (h != NULL) {
3165 // will be aligned next to a street
3166 won += (h->get_level()+1) * 10;
3167 }
3168 }
3169
3170 // so we found at least one suitable building for this place
3171 int rotation = orient_city_building( k, h, maxsize );
3172 if( rotation >= 0 ) {
3173 const gebaeude_t* gb = hausbauer_t::build(NULL, welt->lookup_kartenboden(k)->get_pos(), rotation, h);
3174 add_gebaeude_to_stadt(gb);
3175 }
3176 // to be extended for larger building ...
3177 update_city_street(k);
3178 }
3179
3180
3181
renovate_city_building(gebaeude_t * gb)3182 void stadt_t::renovate_city_building(gebaeude_t *gb)
3183 {
3184 const building_desc_t::btype alt_typ = gb->get_tile()->get_desc()->get_type();
3185 if( !gb->is_city_building() ) {
3186 return; // only renovate res, com, ind
3187 }
3188
3189 // Now we are sure that this is a city building
3190 const building_desc_t *gb_desc = gb->get_tile()->get_desc();
3191 const int level = gb_desc->get_level();
3192
3193 koord k = gb->get_pos().get_2d() - gb->get_tile()->get_offset();
3194
3195 // Divide unemployed by 4, because it counts towards commercial and industrial,
3196 // and both of those count 'double' for population relative to residential.
3197 const int employment_wanted = get_unemployed() / 4;
3198 const int housing_wanted = get_homeless() / 4;
3199
3200 int industrial_suitability, commercial_suitability, residential_suitability;
3201 bewerte_res_com_ind(k, industrial_suitability, commercial_suitability, residential_suitability );
3202
3203 const int sum_industrial = industrial_suitability + employment_wanted;
3204 const int sum_commercial = commercial_suitability + employment_wanted;
3205 const int sum_residential = residential_suitability + housing_wanted;
3206
3207 // does the timeline allow this building?
3208 const uint16 current_month = welt->get_timeline_year_month();
3209 const climate cl = welt->get_climate( gb->get_pos().get_2d() );
3210
3211 // Run through orthogonal neighbors (only), and oneself looking for which cluster to build
3212 // This is a bitmap -- up to 32 clustering types are allowed.
3213 uint32 neighbor_building_clusters = gb->get_tile()->get_desc()->get_clusters();
3214 sint8 zpos = gb->get_pos().z;
3215 koord minsize = gb->get_tile()->get_desc()->get_size(gb->get_tile()->get_layout());
3216 for( int i = 0; i < 4; i++ ) {
3217 // since we handle buildings larger than (1x1) we add an offset
3218 koord ktest = k + neighbors[i];
3219 if( neighbors[i].x > 0 ) {
3220 ktest.x += minsize.x - 1;
3221 }
3222 if( neighbors[i].y > 0 ) {
3223 ktest.y += minsize.y - 1;
3224 }
3225 grund_t* gr = welt->lookup_kartenboden(ktest);
3226 if( gr && gr->get_typ() == grund_t::fundament && gr->obj_bei(0)->get_typ() == obj_t::gebaeude ) {
3227 // We have a building as a neighbor...
3228 if( gebaeude_t const* const testgb = obj_cast<gebaeude_t>(gr->first_obj()) ) {
3229 // We really have a building as a neighbor...
3230 const building_desc_t* neighbor_building = testgb->get_tile()->get_desc();
3231 neighbor_building_clusters |= neighbor_building->get_clusters();
3232 }
3233 }
3234 }
3235
3236 // now test the surrounding tiles for larger size
3237 koord maxsize=minsize;
3238 if( hausbauer_t::get_largest_city_building_area() > 1 ) {
3239 for( int area_level=0; area_level < 8; area_level++ ) {
3240 grund_t* gr = welt->lookup_kartenboden(k + area3x3[area_level]);
3241 if( gr && gr->get_typ() == grund_t::fundament && gr->obj_bei(0)->get_typ() == obj_t::gebaeude ) {
3242 // We have a building as a neighbor...
3243 if( gebaeude_t const* const testgb = obj_cast<gebaeude_t>(gr->first_obj()) ) {
3244 // We really have a building as a neighbor...
3245 const building_desc_t* neighbor_building = testgb->get_tile()->get_desc();
3246 if( gb->get_tile()->get_desc() == neighbor_building && testgb->get_tile()->get_offset() == area3x3[area_level] ) {
3247 // part of same building
3248 maxsize = area3x3[area_level]+koord(1,1);
3249 continue;
3250 }
3251 if( testgb->get_pos().z == zpos && neighbor_building && neighbor_building->get_x()*neighbor_building->get_y()==1 ) {
3252 // also in right height and citybuilding
3253 maxsize = area3x3[area_level]+koord(1,1);
3254 continue;
3255 }
3256 }
3257 #if 0
3258 /* since we only replace tiles, natur is not allowed for the moment, but could be easily changed */
3259 else if( gr->ist_natur() && gr->get_pos().z+slope_t::max_diff(gr->get_grund_hang())==zpos ) {
3260 // we can of course also build on nature
3261 maxsize = area3x3[area_level]+koord(1,1);
3262 continue;
3263 }
3264 #endif
3265 }
3266 // we only reach here upon unsuitable ground
3267 break;
3268 }
3269 }
3270
3271 building_desc_t::btype want_to_have = building_desc_t::unknown;
3272 int sum = 0;
3273
3274 // try to build
3275 const building_desc_t* h = NULL;
3276 if (sum_commercial > sum_industrial && sum_commercial > sum_residential) {
3277 // we must check, if we can really update to higher level ...
3278 const int try_level = (alt_typ == building_desc_t::city_com ? level + 1 : level);
3279 h = hausbauer_t::get_commercial(try_level, current_month, cl, neighbor_building_clusters, minsize, maxsize );
3280 if( h != NULL && h->get_level() >= try_level ) {
3281 want_to_have = building_desc_t::city_com;
3282 sum = sum_commercial;
3283 }
3284 }
3285 // check for industry, also if we wanted com, but there was no com good enough ...
3286 if( (sum_industrial > sum_commercial && sum_industrial > sum_residential)
3287 || (sum_commercial > sum_residential && want_to_have == building_desc_t::unknown) ) {
3288 // we must check, if we can really update to higher level ...
3289 const int try_level = (alt_typ == building_desc_t::city_ind ? level + 1 : level);
3290 h = hausbauer_t::get_industrial(try_level , current_month, cl, neighbor_building_clusters, minsize, maxsize );
3291 if( h != NULL && h->get_level() >= try_level ) {
3292 want_to_have = building_desc_t::city_ind;
3293 sum = sum_industrial;
3294 }
3295 }
3296 // check for residence
3297 // (sum_wohnung>sum_industrie && sum_wohnung>sum_gewerbe
3298 if( want_to_have == building_desc_t::unknown ) {
3299 // we must check, if we can really update to higher level ...
3300 const int try_level = (alt_typ == building_desc_t::city_res ? level + 1 : level);
3301 h = hausbauer_t::get_residential(try_level, current_month, cl, neighbor_building_clusters, minsize, maxsize );
3302 if( h != NULL && h->get_level() >= try_level ) {
3303 want_to_have = building_desc_t::city_res;
3304 sum = sum_residential;
3305 }
3306 else {
3307 h = NULL;
3308 }
3309 }
3310
3311 if (alt_typ != want_to_have) {
3312 sum -= level * 10;
3313 }
3314
3315 // good enough to renovate, and we found a building?
3316 if( sum > 0 && h != NULL ) {
3317 // DBG_MESSAGE("stadt_t::renovate_city_building()", "renovation at %i,%i (%i level) of typ %i to typ %i with desire %i", k.x, k.y, alt_typ, want_to_have, sum);
3318
3319 // no renovation for now, if new is smaller
3320 assert( gb_desc->get_x()*gb_desc->get_y() <= h->get_x()*h->get_y() );
3321
3322 int rotation = 0;
3323 if( h->get_all_layouts()>1 ) {
3324
3325 // only do this of symmetric of small enough building
3326 if( h->get_x()==h->get_y() || (h->get_x()<maxsize.y && h->get_x()<maxsize.x) ) {
3327 // check for pavement
3328 int streetdir = 0;
3329 for( int i = 0; i < 4; i++ ) {
3330 // Neighbors goes through these in 'preferred' order, orthogonal first
3331 grund_t *gr = welt->lookup_kartenboden(k + neighbors[i]);
3332 if( gr && gr->get_weg_hang() == gr->get_grund_hang() && gr->hat_weg(road_wt) ){
3333 streetdir += (1 << i);
3334 }
3335 }
3336 // not completely unique layout, see if any of the neighbouring building gives a hint
3337 rotation = building_layout[streetdir] & ~CHECK_NEIGHBOUR;
3338 bool unique_orientation = !(building_layout[streetdir] & CHECK_NEIGHBOUR);
3339 // only streets in diagonal corners => make a house there in L direction
3340 if( !streetdir ) {
3341 int count = 0;
3342 for( int i = 4; i < 8; i++ ) {
3343 // Neighbors goes through these in 'preferred' order, orthogonal first
3344 grund_t *gr = welt->lookup_kartenboden(k + neighbors[i]);
3345 if( gr && gr->get_weg_hang() == gr->get_grund_hang() && gr->hat_weg(road_wt) ) {
3346 rotation = i;
3347 count ++;
3348 }
3349 }
3350 unique_orientation = (count==1);
3351 }
3352 if( !unique_orientation ) {
3353 int max_layout = h->get_all_layouts()-1;
3354 for( int i = 0; i < 4; i++ ) {
3355 // Neighbors goes through these in 'preferred' order, orthogonal first
3356 grund_t *gr = welt->lookup_kartenboden(k + neighbors[i]);
3357 if( gr && gr->get_typ()==grund_t::fundament ){
3358 if( gebaeude_t *gb = gr->find<gebaeude_t>() ) {
3359 if( gb->get_tile()->get_desc()->get_all_layouts() > max_layout ) {
3360 // so take the roation of the next bilding with similar or more rotations
3361 rotation = gb->get_tile()->get_layout();
3362 max_layout = gb->get_tile()->get_desc()->get_all_layouts();
3363 if( h->get_clusters() == 0 && gb->get_tile()->get_desc() == h ) {
3364 // we only renovate, if there is not an identical building (unless its a cluster)
3365 return;
3366 }
3367 }
3368 }
3369 }
3370 }
3371 }
3372 }
3373 else {
3374 // asymmetric building
3375 rotation = (h->get_x(0)<=maxsize.x && h->get_y(0)<=maxsize.y) ? 0 : 1;
3376 }
3377 }
3378
3379 // we only renovate, if there is not an identical building (unless its a cluster)
3380 if( !h->get_clusters() ) {
3381 for( int i = 0; i < 8; i++ ) {
3382 koord p = k;
3383 p.x += neighbors[i].x > 0 ? h->get_x( rotation ) : neighbors[i].x;
3384 p.y += neighbors[i].y > 0 ? h->get_y( rotation ) : neighbors[i].y;
3385 grund_t *gr = welt->lookup_kartenboden(p);
3386 if( gr && gr->get_typ() == grund_t::fundament ) {
3387 if( gebaeude_t *gb = gr->find<gebaeude_t>() ) {
3388 if( gb->get_tile()->get_desc() == h ) {
3389 // same building => do not renovate
3390 return;
3391 }
3392 }
3393 }
3394 }
3395 }
3396
3397 // ok now finally replace
3398 for( int x=0; x<h->get_x(rotation); x++ ) {
3399 for( int y=0; y<h->get_y(rotation); y++ ) {
3400 koord kpos = k+koord(x,y);
3401 grund_t *gr = welt->lookup_kartenboden(kpos);
3402 gebaeude_t *oldgb = gr->find<gebaeude_t>();
3403 switch(oldgb->get_tile()->get_desc()->get_type()) {
3404 case building_desc_t::city_res: won -= level * 10; break;
3405 case building_desc_t::city_com: arb -= level * 20; break;
3406 case building_desc_t::city_ind: arb -= level * 20; break;
3407 default: break;
3408 }
3409 // exchange building; try to face it to street in front
3410 oldgb->mark_images_dirty();
3411 oldgb->set_tile( h->get_tile(rotation, x, y), true );
3412 welt->lookup_kartenboden(kpos)->calc_image();
3413 update_gebaeude_from_stadt(oldgb);
3414 update_city_street(kpos);
3415 switch(h->get_type()) {
3416 case building_desc_t::city_res: won += h->get_level() * 10; break;
3417 case building_desc_t::city_com: arb += h->get_level() * 20; break;
3418 case building_desc_t::city_ind: arb += h->get_level() * 20; break;
3419 default: break;
3420 }
3421 }
3422 }
3423 }
3424 }
3425
3426
3427 #ifdef DESTINATION_CITYCARS
generate_private_cars(koord pos,koord target)3428 void stadt_t::generate_private_cars(koord pos, koord target)
3429 {
3430 if (!private_car_t::list_empty() && number_of_cars>0 ) {
3431 koord k;
3432 for (k.y = pos.y - 1; k.y <= pos.y + 1; k.y++) {
3433 for (k.x = pos.x - 1; k.x <= pos.x + 1; k.x++) {
3434 if( grund_t* gr = welt->lookup_kartenboden(k) ) {
3435 const weg_t* weg = gr->get_weg(road_wt);
3436 if (weg != NULL && (
3437 gr->get_weg_ribi_unmasked(road_wt) == ribi_t::northsouth ||
3438 gr->get_weg_ribi_unmasked(road_wt) == ribi_t::eastwest
3439 )) {
3440 // already a car here => avoid congestion
3441 if(gr->obj_bei(gr->get_top()-1)->is_moving()) {
3442 continue;
3443 }
3444 private_car_t* vt = new private_car_t(gr, target);
3445 gr->obj_add(vt);
3446 welt->sync.add(vt);
3447 city_history_month[0][HIST_CITYCARS] ++;
3448 city_history_year[0][HIST_CITYCARS] ++;
3449 number_of_cars --;
3450 return;
3451 }
3452 }
3453 }
3454 }
3455 }
3456 }
3457 #endif
3458
3459
3460 /**
3461 * baut ein Stueck Strasse
3462 *
3463 * @param k Bauposition
3464 *
3465 * @author Hj. Malthaner, V. Meyer
3466 */
build_road(const koord k,player_t * player_,bool forced)3467 bool stadt_t::build_road(const koord k, player_t* player_, bool forced)
3468 {
3469 grund_t* bd = welt->lookup_kartenboden(k);
3470
3471 if (bd->get_typ() != grund_t::boden) {
3472 // not on water, monorails, foundations, tunnel or bridges
3473 return false;
3474 }
3475
3476 // we must not built on water or runways etc.
3477 if( bd->hat_wege() && !bd->hat_weg(road_wt) && !bd->hat_weg(track_wt) ) {
3478 return false;
3479 }
3480
3481 // somebody else's things on it?
3482 if( bd->kann_alle_obj_entfernen(NULL) ) {
3483 return false;
3484 }
3485
3486 // dwachs: If not able to built here, try to make artificial slope
3487 slope_t::type slope = bd->get_grund_hang();
3488 if (!slope_t::is_way(slope)) {
3489 climate c = welt->get_climate(k);
3490 if (welt->can_flatten_tile(NULL, k, bd->get_hoehe()+1, true)) {
3491 welt->flatten_tile(NULL, k, bd->get_hoehe()+1, true);
3492 }
3493 else if( bd->get_hoehe() > welt->get_water_hgt(k) && welt->can_flatten_tile(NULL, k, bd->get_hoehe() ) ) {
3494 welt->flatten_tile(NULL, k, bd->get_hoehe());
3495 }
3496 else {
3497 return false;
3498 }
3499 // kartenboden may have changed - also ensure is land
3500 bd = welt->lookup_kartenboden(k);
3501 if (bd->get_typ() == grund_t::wasser) {
3502 welt->set_water_hgt(k, bd->get_hoehe()-1);
3503 welt->access(k)->correct_water();
3504 welt->set_climate(k, c, true);
3505 bd = welt->lookup_kartenboden(k);
3506 }
3507 }
3508
3509 // initially allow all possible directions ...
3510 ribi_t::ribi allowed_dir = (bd->get_grund_hang() != slope_t::flat ? ribi_t::doubles(ribi_type(bd->get_weg_hang())) : (ribi_t::ribi)ribi_t::all);
3511
3512 // we have here a road: check for four corner stops
3513 const gebaeude_t* gb = bd->find<gebaeude_t>();
3514 if(gb) {
3515 // nothing to connect
3516 if(gb->get_tile()->get_desc()->get_all_layouts()==4) {
3517 // single way
3518 allowed_dir = ribi_t::layout_to_ribi[gb->get_tile()->get_layout()];
3519 }
3520 else if(gb->get_tile()->get_desc()->get_all_layouts()) {
3521 // through way
3522 allowed_dir = ribi_t::doubles( ribi_t::layout_to_ribi[gb->get_tile()->get_layout() & 1] );
3523 }
3524 else {
3525 dbg->error("stadt_t::build_road()", "building on road with not directions at %i,%i?!?", k.x, k.y );
3526 }
3527 }
3528
3529 // we must not built on water or runways etc.
3530 // only crossing or tramways allowed
3531 if( bd->hat_weg(track_wt) ) {
3532 weg_t* sch = bd->get_weg(track_wt);
3533 if (sch->get_desc()->get_styp() != type_tram) {
3534 // not a tramway
3535 ribi_t::ribi r = sch->get_ribi_unmasked();
3536 if (!ribi_t::is_straight(r)) {
3537 // no building on crossings, curves, dead ends
3538 return false;
3539 }
3540 // just the other directions are allowed
3541 allowed_dir &= ~r;
3542 }
3543 }
3544
3545 // determine now, in which directions we can connect to another road
3546 ribi_t::ribi connection_roads = ribi_t::none;
3547 // add ribi's to connection_roads if possible
3548 for (int r = 0; r < 4; r++) {
3549 if (ribi_t::nsew[r] & allowed_dir) {
3550 // now we have to check for several problems ...
3551 grund_t* bd2;
3552 if(bd->get_neighbour(bd2, invalid_wt, ribi_t::nsew[r])) {
3553 if(bd2->get_typ()==grund_t::fundament || bd2->get_typ()==grund_t::wasser) {
3554 // not connecting to a building of course ...
3555 }
3556 else if (!bd2->ist_karten_boden()) {
3557 // do not connect to elevated ways / bridges
3558 }
3559 else if (bd2->get_typ()==grund_t::tunnelboden && ribi_t::nsew[r]!=ribi_type(bd2->get_grund_hang())) {
3560 // not the correct slope
3561 }
3562 else if (bd2->get_typ()==grund_t::brueckenboden
3563 && (bd2->get_grund_hang()==slope_t::flat ? ribi_t::nsew[r]!=ribi_type(bd2->get_weg_hang())
3564 : ribi_t::backward(ribi_t::nsew[r])!=ribi_type(bd2->get_grund_hang()))) {
3565 // not the correct slope
3566 }
3567 else if(bd2->hat_weg(road_wt)) {
3568 const gebaeude_t* gb = bd2->find<gebaeude_t>();
3569 if(gb) {
3570 uint8 layouts = gb->get_tile()->get_desc()->get_all_layouts();
3571 // nothing to connect
3572 if(layouts==4) {
3573 // single way
3574 if(ribi_t::nsew[r]==ribi_t::backward(ribi_t::layout_to_ribi[gb->get_tile()->get_layout()])) {
3575 // allowed ...
3576 connection_roads |= ribi_t::nsew[r];
3577 }
3578 }
3579 else if(layouts==2 || layouts==8 || layouts==16) {
3580 // through way
3581 if((ribi_t::doubles( ribi_t::layout_to_ribi[gb->get_tile()->get_layout() & 1] )&ribi_t::nsew[r])!=0) {
3582 // allowed ...
3583 connection_roads |= ribi_t::nsew[r];
3584 }
3585 }
3586 else {
3587 dbg->error("stadt_t::build_road()", "building on road with not directions at %i,%i?!?", k.x, k.y );
3588 }
3589 }
3590 else if(bd2->get_depot()) {
3591 // do not enter depots
3592 }
3593 else {
3594 // check slopes
3595 way_builder_t bauer( NULL );
3596 bauer.init_builder( way_builder_t::strasse | way_builder_t::terraform_flag, welt->get_city_road() );
3597 if( bauer.check_slope( bd, bd2 ) ) {
3598 // allowed ...
3599 connection_roads |= ribi_t::nsew[r];
3600 }
3601 }
3602 }
3603 }
3604 }
3605 }
3606
3607 // now add the ribis to the other ways (if there)
3608 for (int r = 0; r < 4; r++) {
3609 if (ribi_t::nsew[r] & connection_roads) {
3610 grund_t* bd2 = welt->lookup_kartenboden(k + koord::nsew[r]);
3611 weg_t* w2 = bd2->get_weg(road_wt);
3612 w2->ribi_add(ribi_t::backward(ribi_t::nsew[r]));
3613 bd2->calc_image();
3614 bd2->set_flag( grund_t::dirty );
3615 }
3616 }
3617
3618 if (connection_roads != ribi_t::none || forced) {
3619
3620 if (!bd->weg_erweitern(road_wt, connection_roads)) {
3621 strasse_t* weg = new strasse_t();
3622 // Hajo: city roads should not belong to any player => so we can ignore any construction costs ...
3623 weg->set_desc(welt->get_city_road());
3624 weg->set_gehweg(true);
3625 bd->neuen_weg_bauen(weg, connection_roads, player_);
3626 bd->calc_image(); // otherwise the
3627 }
3628 // check to bridge a river
3629 if(ribi_t::is_single(connection_roads)) {
3630 koord zv = koord(ribi_t::backward(connection_roads));
3631 grund_t *bd_next = welt->lookup_kartenboden( k + zv );
3632 if(bd_next && (bd_next->is_water() || (bd_next->hat_weg(water_wt) && bd_next->get_weg(water_wt)->get_desc()->get_styp()== type_river))) {
3633 // ok there is a river
3634 const bridge_desc_t *bridge = bridge_builder_t::find_bridge(road_wt, welt->get_city_road()->get_topspeed(), welt->get_timeline_year_month() );
3635 if( bridge==NULL ) {
3636 // does not have a bridge available ...
3637 return false;
3638 }
3639 const char *err = NULL;
3640 sint8 bridge_height;
3641 koord3d end = bridge_builder_t::find_end_pos(NULL, bd->get_pos(), zv, bridge, err, bridge_height, false);
3642 if(err || koord_distance( k, end.get_2d())>3) {
3643 // try to find shortest possible
3644 end = bridge_builder_t::find_end_pos(NULL, bd->get_pos(), zv, bridge, err, bridge_height, true);
3645 }
3646 if((err==NULL||*err == 0) && koord_distance( k, end.get_2d())<=3 && welt->is_within_limits((end+zv).get_2d())) {
3647 bridge_builder_t::build_bridge(NULL, bd->get_pos(), end, zv, bridge_height, bridge, welt->get_city_road());
3648 // try to build one connecting piece of road
3649 build_road( (end+zv).get_2d(), NULL, false);
3650 // try to build a house near the bridge end
3651 uint32 old_count = buildings.get_count();
3652 for(uint8 i=0; i<lengthof(koord::neighbours) && buildings.get_count() == old_count; i++) {
3653 koord c(end.get_2d()+zv+koord::neighbours[i]);
3654 if (welt->is_within_limits(c)) {
3655 build_city_building(end.get_2d()+zv+koord::neighbours[i]);
3656 }
3657 }
3658 }
3659 }
3660 }
3661 return true;
3662 }
3663
3664 return false;
3665 }
3666
3667
3668 // will check a single random pos in the city, then build will be called
build()3669 void stadt_t::build()
3670 {
3671 const koord k(lo + koord::koord_random(ur.x - lo.x + 2,ur.y - lo.y + 2)-koord(1,1) );
3672
3673 // do not build on any border tile
3674 if( !welt->is_within_limits(k+koord(1,1)) || k.x<=0 || k.y<=0 ) {
3675 return;
3676 }
3677
3678 grund_t *gr = welt->lookup_kartenboden(k);
3679 if(gr==NULL) {
3680 return;
3681 }
3682
3683 // checks only make sense on empty ground
3684 if(gr->ist_natur()) {
3685
3686 // since only a single location is checked, we can stop after we have found a positive rule
3687 best_strasse.reset(k);
3688 const uint32 num_road_rules = road_rules.get_count();
3689 uint32 offset = simrand(num_road_rules); // start with random rule
3690 for (uint32 i = 0; i < num_road_rules && !best_strasse.found(); i++) {
3691 uint32 rule = ( i+offset ) % num_road_rules;
3692 bewerte_strasse(k, 8 + road_rules[rule]->chance, *road_rules[rule]);
3693 }
3694 // ok => then built road
3695 if (best_strasse.found()) {
3696 build_road(best_strasse.get_pos(), NULL, false);
3697 INT_CHECK("simcity 1156");
3698 return;
3699 }
3700
3701 // not good for road => test for house
3702
3703 // since only a single location is checked, we can stop after we have found a positive rule
3704 best_haus.reset(k);
3705 const uint32 num_house_rules = house_rules.get_count();
3706 offset = simrand(num_house_rules); // start with random rule
3707 for( uint32 i = 0; i < num_house_rules && !best_haus.found(); i++ ) {
3708 uint32 rule = ( i+offset ) % num_house_rules;
3709 bewerte_haus(k, 8 + house_rules[rule]->chance, *house_rules[rule]);
3710 }
3711 // one rule applied?
3712 if( best_haus.found() ) {
3713 build_city_building(best_haus.get_pos());
3714 INT_CHECK("simcity 1163");
3715 return;
3716 }
3717
3718 }
3719
3720 // renovation (only done when nothing matches a certain location
3721 if( !buildings.empty() && simrand(100) <= renovation_percentage ) {
3722 // try to find a public owned building
3723 for( uint8 i=0; i<4; i++ ) {
3724 gebaeude_t* const gb = pick_any(buildings);
3725 if( player_t::check_owner(gb->get_owner(),NULL) ) {
3726 renovate_city_building(gb);
3727 break;
3728 }
3729 }
3730 INT_CHECK("simcity 876");
3731 }
3732 }
3733
3734
3735 // find suitable places for cities
random_place(const sint32 count,sint16 old_x,sint16 old_y)3736 vector_tpl<koord>* stadt_t::random_place(const sint32 count, sint16 old_x, sint16 old_y)
3737 {
3738 int cl = 0;
3739 for (int i = 0; i < MAX_CLIMATES; i++) {
3740 if (hausbauer_t::get_special(0, building_desc_t::townhall, welt->get_timeline_year_month(), false, (climate)i)) {
3741 cl |= (1 << i);
3742 }
3743 }
3744 DBG_DEBUG("karte_t::init()", "get random places in climates %x", cl);
3745 // search at least places which are 5x5 squares large
3746 slist_tpl<koord>* list = welt->find_squares( 5, 5, (climate_bits)cl, old_x, old_y);
3747 DBG_DEBUG("karte_t::init()", "found %i places", list->get_count());
3748 vector_tpl<koord>* result = new vector_tpl<koord>(count);
3749
3750 // pre processed array: max 1 city from each square can be built
3751 // each entry represents a cell of minimum_city_distance/2 length and width
3752 const uint32 minimum_city_distance = welt->get_settings().get_minimum_city_distance();
3753 const uint32 xmax = (2*welt->get_size().x)/minimum_city_distance+1;
3754 const uint32 ymax = (2*welt->get_size().y)/minimum_city_distance+1;
3755 array2d_tpl< vector_tpl<koord> > places(xmax, ymax);
3756 while (!list->empty()) {
3757 const koord k = list->remove_first();
3758 places.at( (2*k.x)/minimum_city_distance, (2*k.y)/minimum_city_distance).append(k);
3759 }
3760 // weighted index vector into places array
3761 weighted_vector_tpl<koord> index_to_places(xmax*ymax);
3762 for(uint32 i=0; i<xmax; i++) {
3763 for(uint32 j=0; j<ymax; j++) {
3764 vector_tpl<koord> const& p = places.at(i, j);
3765 if (!p.empty()) {
3766 index_to_places.append(koord(i,j), p.get_count());
3767 }
3768 }
3769 }
3770 // post-processing array:
3771 // each entry represents a cell of minimum_city_distance length and width
3772 // to limit the search for neighboring cities
3773 const uint32 xmax2 = welt->get_size().x/minimum_city_distance+1;
3774 const uint32 ymax2 = welt->get_size().y/minimum_city_distance+1;
3775 array2d_tpl< vector_tpl<koord> > result_places(xmax2, ymax2);
3776
3777 for (int i = 0; i < count; i++) {
3778 // check distances of all cities to their respective neighbours
3779 while (!index_to_places.empty()) {
3780 // find a random cell
3781 koord const ip = pick_any_weighted(index_to_places);
3782 // remove this cell from index list
3783 index_to_places.remove(ip);
3784 vector_tpl<koord>& p = places.at(ip);
3785 // get random place in the cell
3786 if (p.empty()) continue;
3787 uint32 const j = simrand(p.get_count());
3788 koord const k = p[j];
3789
3790 const koord k2mcd = koord( k.x/minimum_city_distance, k.y/minimum_city_distance );
3791 for (sint32 i = k2mcd.x - 1; i <= k2mcd.x + 1; ++i) {
3792 for (sint32 j = k2mcd.y - 1; j <= k2mcd.y + 1; ++j) {
3793 if (i>=0 && i<(sint32)xmax2 && j>=0 && j<(sint32)ymax2) {
3794 FOR(vector_tpl<koord>, const& l, result_places.at(i, j)) {
3795 if (koord_distance(k, l) < minimum_city_distance) {
3796 goto too_close;
3797 }
3798 }
3799 }
3800 }
3801 }
3802
3803 // all cities are far enough => ok, find next place
3804 result->append(k);
3805 result_places.at(k2mcd).append(k);
3806 break;
3807
3808 too_close:
3809 // remove the place from the list
3810 p.remove_at(j);
3811 // re-insert in index list with new weight
3812 if (!p.empty()) {
3813 index_to_places.append(ip, p.get_count());
3814 }
3815 // if we reached here, the city was not far enough => try again
3816 }
3817
3818 if (index_to_places.empty() && i < count - 1) {
3819 dbg->warning("stadt_t::random_place()", "Not enough places found!");
3820 break;
3821 }
3822 }
3823 delete list;
3824
3825 return result;
3826 }
3827