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 &regel, 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 &regel);
415 
416 	void bewerte_strasse(koord pos, sint32 rd, const rule_t &regel);
417 	void bewerte_haus(koord pos, sint32 rd, const rule_t &regel);
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