1 /* 2 * Copyright (c) 1997 - 2001 Hansj�rg Malthaner 3 * 4 * This file is part of the Simutrans project under the artistic license. 5 * (see license.txt) 6 */ 7 8 #ifndef simcity_h 9 #define simcity_h 10 11 #include "simobj.h" 12 #include "obj/gebaeude.h" 13 14 #include "tpl/vector_tpl.h" 15 #include "tpl/weighted_vector_tpl.h" 16 #include "tpl/sparse_tpl.h" 17 #include "utils/plainstring.h" 18 19 #include <string> 20 21 class building_desc_t; 22 class karte_ptr_t; 23 class player_t; 24 class rule_t; 25 26 27 #define MAX_CITY_HISTORY_YEARS (12) // number of years to keep history 28 #define MAX_CITY_HISTORY_MONTHS (12) // number of months to keep history 29 30 #define PAX_DESTINATIONS_SIZE (256) // size of the minimap (sparse array) 31 32 enum city_cost { 33 HIST_CITICENS=0,// total people 34 HIST_GROWTH, // growth (just for convenience) 35 HIST_BUILDING, // number of buildings 36 HIST_CITYCARS, // number of citycars generated 37 HIST_PAS_TRANSPORTED, // number of passengers who could start their journey 38 HIST_PAS_WALKED, // direct transfer 39 HIST_PAS_GENERATED, // total number generated 40 HIST_MAIL_TRANSPORTED, // letters that could be sent 41 HIST_MAIL_WALKED, // direct handover 42 HIST_MAIL_GENERATED, // all letters generated 43 HIST_GOODS_RECEIVED, // times all storages were not empty 44 HIST_GOODS_NEEDED, // times storages checked 45 HIST_POWER_RECEIVED, // power consumption (not used at the moment!) 46 MAX_CITY_HISTORY // Total number of items in array 47 }; 48 49 // The base offset for passenger statistics. 50 static const uint32 HIST_BASE_PASS = HIST_PAS_TRANSPORTED; 51 52 // The base offset for mail statistics. 53 static const uint32 HIST_BASE_MAIL = HIST_MAIL_TRANSPORTED; 54 55 // The offset for transported statistic for passengers and mail. 56 static const uint32 HIST_OFFSET_TRANSPORTED = 0; 57 58 // The offset for walked statistic for passengers and mail. 59 static const uint32 HIST_OFFSET_WALKED = 1; 60 61 // The offset for generated statistic for passengers and mail. 62 static const uint32 HIST_OFFSET_GENERATED = 2; 63 64 // The number of growth factors kept track of. 65 static const uint32 GROWTH_FACTOR_NUMBER = 3; 66 67 // Mail return multiplier used by mail producers (attractions and factories). 68 static const uint32 MAIL_RETURN_MULTIPLIER_PRODUCERS = 3; 69 70 // Passenger generation ratio. This many parts to mail generation ratio parts. 71 static const uint32 GENERATE_RATIO_PASS = 3; 72 73 // Mail generation ratio. This many parts to passenger generation ratio parts. 74 static const uint32 GENERATE_RATIO_MAIL = 1; 75 76 /** 77 * Die Objecte der Klasse stadt_t bilden die Staedte in Simu. Sie 78 * wachsen automatisch. 79 * @author Hj. Malthaner 80 */ 81 class stadt_t 82 { 83 /** 84 * best_t: 85 * 86 * Kleine Hilfsklasse - speichert die beste Bewertung einer Position. 87 * 88 * @author V. Meyer 89 */ 90 class best_t { 91 sint32 best_wert; 92 koord best_pos; 93 public: reset(koord pos)94 void reset(koord pos) { best_wert = 0; best_pos = pos; } 95 check(koord pos,sint32 wert)96 void check(koord pos, sint32 wert) { 97 if(wert > best_wert) { 98 best_wert = wert; 99 best_pos = pos; 100 } 101 } 102 found()103 bool found() const { return best_wert > 0; } 104 get_pos()105 koord get_pos() const { return best_pos;} 106 // sint32 get_wert() const { return best_wert; } 107 }; 108 109 public: 110 /** 111 * Reads city configuration data from config/cityrules.tab 112 * @author Hj. Malthaner 113 */ 114 static bool cityrules_init(const std::string &objpathname); 115 /** 116 * Reads/writes city configuration data from/to a savegame 117 * called from settings_t::rdwr 118 * only written for networkgames 119 * @author Dwachs 120 */ 121 static void cityrules_rdwr(loadsave_t *file); 122 123 static uint32 get_industry_increase(); 124 static void set_industry_increase(uint32 ind_increase); 125 static uint32 get_minimum_city_distance(); 126 static void set_minimum_city_distance(uint32 s); set_cluster_factor(uint32 factor)127 static void set_cluster_factor( uint32 factor ) { stadt_t::cluster_factor = factor; } get_cluster_factor()128 static uint32 get_cluster_factor() { return stadt_t::cluster_factor; } 129 130 private: 131 static karte_ptr_t welt; 132 player_t *owner; 133 plainstring name; 134 135 weighted_vector_tpl <gebaeude_t *> buildings; 136 137 sparse_tpl<PIXVAL> pax_destinations_old; 138 sparse_tpl<PIXVAL> pax_destinations_new; 139 140 // this counter will increment by one for every change => dialogs can question, if they need to update map 141 uint32 pax_destinations_new_change; 142 143 koord pos; // Gruendungsplanquadrat der City 144 koord townhall_road; // road in front of townhall 145 koord lo, ur; // max size of housing area 146 koord last_center; 147 bool has_low_density; // in this case extend borders by two 148 149 bool allow_citygrowth; // town can be static and will grow (true by default) 150 151 bool has_townhall; 152 // this counter indicate which building will be processed next 153 uint32 step_count; 154 155 /** 156 * step so every house is asked once per month 157 * i.e. 262144/(number of houses) per step 158 * @author Hj. Malthaner 159 */ 160 uint32 step_interval; 161 162 /** 163 * next passenger generation timer 164 * @author Hj. Malthaner 165 */ 166 uint32 next_step; 167 168 /** 169 * in this fixed interval, construction will happen 170 */ 171 static const uint32 city_growth_step; 172 173 /** 174 * When to do growth next 175 * @author Hj. Malthaner 176 */ 177 uint32 next_growth_step; 178 179 static uint32 cluster_factor; 180 181 // attribute for the population (Bevoelkerung) 182 sint32 bev; // total population (bevoelkerung) 183 sint32 arb; // with a job (arbeit) 184 sint32 won; // with a residence (wohnung) 185 186 /** 187 * Un-supplied city growth needs 188 * A value of 2^32 means 1 new resident 189 * @author Nathanael Nerode (neroden) 190 */ 191 sint64 unsupplied_city_growth; 192 193 /** 194 * City history 195 * Current month stats are not appropiate to determine satisfaction for growth. 196 * @author prissi 197 */ 198 sint64 city_history_year[MAX_CITY_HISTORY_YEARS][MAX_CITY_HISTORY]; 199 sint64 city_history_month[MAX_CITY_HISTORY_MONTHS][MAX_CITY_HISTORY]; 200 201 /* updates the city history 202 * @author prissi 203 */ 204 void roll_history(); 205 206 /* Members used to determine satisfaction for growth rate. 207 * Satisfaction of this month cannot be used as it is an averaging filter for the entire month up to the present. 208 * Instead the average over a number of growth ticks is used, defaulting to last month average if nothing is available. 209 * @author DrSuperGood 210 */ 211 private: 212 // The growth factor type in form of the amount demanded and what was received. 213 struct city_growth_factor_t { 214 // The wanted value. 215 sint64 demand; 216 // The received value. 217 sint64 supplied; 218 city_growth_factor_tcity_growth_factor_t219 city_growth_factor_t() : demand(0), supplied(0){} 220 }; 221 222 // The previous values of the growth factors. Used to get delta between ticks and must be saved for determinism. 223 city_growth_factor_t city_growth_factor_previous[GROWTH_FACTOR_NUMBER]; 224 225 /* Method to generate comparable growth factor data. 226 * This allows one to alter the logic which computes growth. 227 * @param factors factor array. 228 * @param month the month which is to be used for the growth factors. 229 */ 230 void city_growth_get_factors(city_growth_factor_t (&factors)[GROWTH_FACTOR_NUMBER], uint32 const month) const; 231 232 /* Method to compute base growth using growth factors. 233 * Logs differences in growth factors as well. 234 * rprec : The returned fractional precision (out of sint32). 235 * cprec : The computation fractional precision (out of sint32). 236 */ 237 sint32 city_growth_base(uint32 const rprec = 6, uint32 const cprec = 16); 238 239 /* Method to roll previous growth factors at end of month, called before history rolls over. 240 * Needed to prevent loss of data (not set to 0) and while keeping reasonable (no insane values). 241 * month : The month index of what is now the "last month". 242 */ 243 void city_growth_monthly(uint32 const month); 244 245 public: 246 /** 247 * Returns pointer to history for city 248 * @author hsiegeln 249 */ get_city_history_year()250 sint64* get_city_history_year() { return *city_history_year; } get_city_history_month()251 sint64* get_city_history_month() { return *city_history_month; } 252 253 uint32 stadtinfo_options; 254 255 /* end of history related things */ 256 private: 257 sint32 best_haus_wert; 258 sint32 best_strasse_wert; 259 260 best_t best_haus; 261 best_t best_strasse; 262 263 public: 264 /** 265 * Classes for storing and manipulating target factories and their data 266 * @author Knightly 267 */ 268 struct factory_entry_t 269 { 270 union 271 { 272 fabrik_t *factory; 273 struct 274 { 275 sint16 factory_pos_x; 276 sint16 factory_pos_y; 277 }; 278 }; 279 sint32 demand; // amount demanded by the factory; shifted by DEMAND_BITS 280 sint32 supply; // amount that the city can supply 281 sint32 remaining; // portion of supply which has not realised yet; remaining <= supply 282 factory_entry_tfactory_entry_t283 factory_entry_t() : factory(NULL), demand(0), supply(0), remaining(0) { } factory_entry_tfactory_entry_t284 factory_entry_t(fabrik_t *_factory) : factory(_factory), demand(0), supply(0), remaining(0) { } factory_entry_tfactory_entry_t285 factory_entry_t(fabrik_t *_factory, sint32 _demand) : factory(_factory), demand(_demand), supply(0), remaining(0) { } 286 287 bool operator == (const factory_entry_t &other) const { return ( this->factory==other.factory ); } new_monthfactory_entry_t288 void new_month() { supply = 0; remaining = 0; } 289 void rdwr(loadsave_t *file); 290 void resolve_factory(); 291 }; 292 #define RATIO_BITS (25) 293 struct factory_set_t 294 { 295 vector_tpl<factory_entry_t> entries; 296 sint32 total_demand; // shifted by DEMAND_BITS 297 sint32 total_remaining; 298 sint32 total_generated; 299 uint32 generation_ratio; 300 bool ratio_stale; 301 factory_set_tfactory_set_t302 factory_set_t() : total_demand(0), total_remaining(0), total_generated(0), generation_ratio(0), ratio_stale(true) { } 303 get_entriesfactory_set_t304 const vector_tpl<factory_entry_t>& get_entries() const { return entries; } 305 const factory_entry_t* get_entry(const fabrik_t *const factory) const; 306 factory_entry_t* get_random_entry(); 307 void update_factory(fabrik_t *const factory, const sint32 demand); 308 void remove_factory(fabrik_t *const factory); 309 void recalc_generation_ratio(const sint32 default_percent, const sint64 *city_stats, const int stats_count, const int stat_type); 310 void new_month(); 311 void rdwr(loadsave_t *file); 312 void resolve_factories(); 313 }; 314 315 private: 316 /** 317 * Data of target factories for pax/mail 318 * @author Knightly 319 */ 320 factory_set_t target_factories_pax; 321 factory_set_t target_factories_mail; 322 323 /** 324 * Initialization of pax_destinations_old/new 325 * @author Hj. Malthaner 326 */ 327 void init_pax_destinations(); 328 329 /** 330 * Recalculates city borders (after loading and deletion). 331 * @warning Do not call this during multithreaded loading! 332 */ 333 void recalc_city_size(); 334 335 // calculates the growth rate for next growth_interval using all the different indicators 336 void calc_growth(); 337 338 /** 339 * Build new buildings when growing city 340 * @author Hj. Malthaner 341 */ 342 void step_grow_city(bool new_town = false); 343 344 enum pax_return_type { no_return, factory_return, tourist_return, city_return }; 345 346 /** 347 * verteilt die Passagiere auf die Haltestellen 348 * @author Hj. Malthaner 349 */ 350 void step_passagiere(); 351 352 /** 353 * ein Passagierziel in die Zielkarte eintragen 354 * @author Hj. Malthaner 355 */ 356 void merke_passagier_ziel(koord ziel, PIXVAL color); 357 358 /** 359 * baut Spezialgebaeude, z.B Stadion 360 * @author Hj. Malthaner 361 */ 362 void check_bau_spezial(bool); 363 364 /** 365 * baut ein angemessenes Rathaus 366 * @author V. Meyer 367 */ 368 void check_bau_townhall(bool); 369 370 /** 371 * constructs a new consumer 372 * @author prissi 373 */ 374 void check_bau_factory(bool); 375 376 377 // find out, what building matches best 378 void bewerte_res_com_ind(const koord pos, int &ind, int &com, int &res); 379 380 /** 381 * Build/renovates a city building at Planquadrat (tile) x,y 382 */ 383 void build_city_building(koord pos); 384 void renovate_city_building(gebaeude_t *gb); 385 386 #ifdef DESTINATION_CITYCARS 387 sint16 number_of_cars; // allowed number of cars to spawn per month 388 void generate_private_cars(koord pos, koord target); 389 #endif 390 391 /** 392 * baut ein Stueck Strasse 393 * 394 * @param k Bauposition 395 * 396 * @author Hj. Malthaner, V. Meyer 397 */ 398 bool build_road(const koord k, player_t *player_, bool forced); 399 400 void build(); 401 402 /** 403 * @param pos position to check 404 * @param regel the rule to evaluate 405 * @return true on match, false otherwise 406 * @author Hj. Malthaner 407 */ 408 static bool bewerte_loc(koord pos, const rule_t ®el, int rotation); 409 410 /** 411 * Check rule in all transformations at given position 412 * @author Hj. Malthaner 413 */ 414 static sint32 bewerte_pos(koord pos, const rule_t ®el); 415 416 void bewerte_strasse(koord pos, sint32 rd, const rule_t ®el); 417 void bewerte_haus(koord pos, sint32 rd, const rule_t ®el); 418 419 /** 420 * Updates city limits: tile at @p pos belongs to city. 421 * @warning Do not call this during multithreaded loading! 422 */ 423 void pruefe_grenzen(koord pos); 424 425 public: 426 /** 427 * sucht arbeitspl�tze f�r die Einwohner 428 * @author Hj. Malthaner 429 */ 430 void verbinde_fabriken(); 431 432 /** 433 * Returns the data set associated with the pax/mail target factories 434 * @author: prissi 435 */ get_target_factories_for_pax()436 const factory_set_t& get_target_factories_for_pax() const { return target_factories_pax; } get_target_factories_for_mail()437 const factory_set_t& get_target_factories_for_mail() const { return target_factories_mail; } access_target_factories_for_pax()438 factory_set_t& access_target_factories_for_pax() { return target_factories_pax; } access_target_factories_for_mail()439 factory_set_t& access_target_factories_for_mail() { return target_factories_mail; } 440 441 // calculated the "best" orietation of city buildings, also used by editor, thus public 442 static int orient_city_building(const koord k, const building_desc_t *h, koord maxarea ); 443 444 // this function removes houses from the city house list 445 // (called when removed by player, or by town) 446 void remove_gebaeude_from_stadt(gebaeude_t *gb); 447 448 /** 449 * This function adds houses to the city house list. 450 * @param ordered true for multithreaded loading, will insert buidings ordered, will not update city limits 451 */ 452 void add_gebaeude_to_stadt(const gebaeude_t *gb, bool ordered=false); 453 454 // changes the weight; must be called if there is a new definition (tile) for that house 455 void update_gebaeude_from_stadt(gebaeude_t *gb); 456 457 /** 458 * Returns the finance history for cities 459 * @author hsiegeln 460 */ get_finance_history_year(int year,int type)461 sint64 get_finance_history_year(int year, int type) { return city_history_year[year][type]; } get_finance_history_month(int month,int type)462 sint64 get_finance_history_month(int month, int type) { return city_history_month[month][type]; } 463 464 // growth number (smoothed!) get_wachstum()465 sint32 get_wachstum() const {return ((sint32)city_history_month[0][HIST_GROWTH]*5) + (sint32)(city_history_month[1][HIST_GROWTH]*4) + (sint32)city_history_month[2][HIST_GROWTH]; } 466 467 /** 468 * ermittelt die Einwohnerzahl der City 469 * @author Hj. Malthaner 470 */ get_einwohner()471 sint32 get_einwohner() const {return (buildings.get_sum_weight()*6)+((2*bev-arb-won)>>1);} 472 get_buildings()473 uint32 get_buildings() const { return buildings.get_count(); } get_unemployed()474 sint32 get_unemployed() const { return bev - arb; } get_homeless()475 sint32 get_homeless() const { return bev - won; } 476 477 /** 478 * Return the city name. 479 * @author Hj. Malthaner 480 */ get_name()481 const char *get_name() const { return name; } 482 483 /** 484 * Erm�glicht Zugriff auf Namesnarray 485 * @author Hj. Malthaner 486 */ 487 void set_name( const char *name ); 488 489 /** 490 * gibt einen zuf�llingen gleichverteilten Punkt innerhalb der 491 * Citygrenzen zur�ck 492 * @author Hj. Malthaner 493 */ 494 koord get_zufallspunkt() const; 495 496 /** 497 * gibt das pax-statistik-array f�r letzten monat zur�ck 498 * @author Hj. Malthaner 499 */ get_pax_destinations_old()500 const sparse_tpl<PIXVAL>* get_pax_destinations_old() const { return &pax_destinations_old; } 501 502 /** 503 * gibt das pax-statistik-array f�r den aktuellen monat zur�ck 504 * @author Hj. Malthaner 505 */ get_pax_destinations_new()506 const sparse_tpl<PIXVAL>* get_pax_destinations_new() const { return &pax_destinations_new; } 507 508 /* this counter will increment by one for every change 509 * => dialogs can question, if they need to update map 510 * @author prissi 511 */ get_pax_destinations_new_change()512 uint32 get_pax_destinations_new_change() const { return pax_destinations_new_change; } 513 514 /** 515 * Erzeugt eine neue City auf Planquadrat (x,y) die dem Spieler sp 516 * gehoert. 517 * @param player The owner of the city 518 * @param x x-Planquadratkoordinate 519 * @param y y-Planquadratkoordinate 520 * @param number of citizens 521 * @author Hj. Malthaner 522 */ 523 stadt_t(player_t* player, koord pos, sint32 citizens); 524 525 /** 526 * Erzeugt eine neue City nach Angaben aus der Datei file. 527 * @param welt Die Karte zu der die City gehoeren soll. 528 * @param file Zeiger auf die Datei mit den Citybaudaten. 529 * @see stadt_t::speichern() 530 * @author Hj. Malthaner 531 */ 532 stadt_t(loadsave_t *file); 533 534 // closes window and that stuff 535 ~stadt_t(); 536 537 /** 538 * Speichert die Daten der City in der Datei file so, dass daraus 539 * die City wieder erzeugt werden kann. Die Gebaude und strassen der 540 * City werden nicht mit der City gespeichert sondern mit den 541 * Planquadraten auf denen sie stehen. 542 * @see stadt_t::stadt_t() 543 * @see planquadrat_t 544 * @author Hj. Malthaner 545 */ 546 void rdwr(loadsave_t *file); 547 548 /** 549 * Called when loading of savegame is finished to correctly init data. 550 */ 551 void finish_rd(); 552 553 void rotate90( const sint16 y_size ); 554 555 /* change size of city 556 * @author prissi */ 557 void change_size( sint64 delta_citizens, bool new_town = false ); 558 559 // when ng is false, no town growth any more set_citygrowth_yesno(bool ng)560 void set_citygrowth_yesno( bool ng ) { allow_citygrowth = ng; } get_citygrowth()561 bool get_citygrowth() const { return allow_citygrowth; } 562 563 void step(uint32 delta_t); 564 565 void new_month( bool recalc_destinations ); 566 567 private: 568 /** 569 * List of target cities weighted by both city size and distance 570 * @author Knightly 571 */ 572 weighted_vector_tpl<stadt_t *> target_cities; 573 574 /** 575 * List of target attractions weighted by both passenger level and distance 576 * @author Knightly 577 */ 578 weighted_vector_tpl<gebaeude_t *> target_attractions; 579 580 public: 581 /** 582 * Functions for manipulating the list of target cities 583 * @author Knightly 584 */ 585 void add_target_city(stadt_t *const city); remove_target_city(stadt_t * const city)586 void remove_target_city(stadt_t *const city) { target_cities.remove( city ); } 587 void recalc_target_cities(); 588 589 /** 590 * Functions for manipulating the list of target attractions 591 * @author Knightly 592 */ 593 void add_target_attraction(gebaeude_t *const attraction); remove_target_attraction(gebaeude_t * const attraction)594 void remove_target_attraction(gebaeude_t *const attraction) { target_attractions.remove( attraction ); } 595 void recalc_target_attractions(); 596 597 /** 598 * Search for a possible Passenger or Mail destination. 599 * @param target_factories the factory set to use (eg passenger or mail). 600 * @param generated number of passengers already generated, used to fairly distribute to factories. 601 * @param will_return set to the jounrey return type on return. 602 * @param factory_entry set to the destination factory, if any. 603 * @param dest_city set to the destination city for return flow use. 604 * @author Hj. Malthaner 605 */ 606 koord find_destination(factory_set_t &target_factories, const sint64 generated, pax_return_type* will_return, factory_entry_t* &factory_entry, stadt_t* &dest_city); 607 608 /** 609 * Gibt die Gruendungsposition der City zurueck. 610 * @return die Koordinaten des Gruendungsplanquadrates 611 * @author Hj. Malthaner 612 */ get_pos()613 inline koord get_pos() const {return pos;} get_townhall_road()614 inline koord get_townhall_road() const {return townhall_road;} 615 get_linksoben()616 inline koord get_linksoben() const { return lo;} get_rechtsunten()617 inline koord get_rechtsunten() const { return ur;} 618 get_center()619 koord get_center() const { return lo/2 + ur/2; } 620 621 /** 622 * Erzeugt ein Array zufaelliger Startkoordinaten, 623 * die fuer eine Citygruendung geeignet sind. 624 * @param wl Die Karte auf der die City gegruendet werden soll. 625 * @param count die Anzahl der zu liefernden Koordinaten 626 * @author Hj. Malthaner 627 * @param old_x, old_y: Generate no cities in (0,0) - (old_x, old_y) 628 * @author Gerd Wachsmuth 629 */ 630 static vector_tpl<koord> *random_place(sint32 count, sint16 old_x, sint16 old_y); 631 // geeigneten platz zur Citygruendung durch Zufall ermitteln 632 633 void open_info_window(); 634 }; 635 636 #endif 637