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
8 /*
9 * Hauptklasse fuer Simutrans, Datenstruktur die alles Zusammenhaelt
10 * Hj. Malthaner, 1997
11 */
12
13 #include <algorithm>
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <math.h>
19
20 #include <sys/stat.h>
21
22 #include "simcity.h"
23 #include "simcolor.h"
24 #include "simconvoi.h"
25 #include "simdebug.h"
26 #include "simdepot.h"
27 #include "simfab.h"
28 #include "display/simgraph.h"
29 #include "display/viewport.h"
30 #include "simhalt.h"
31 #include "display/simimg.h"
32 #include "siminteraction.h"
33 #include "simintr.h"
34 #include "simio.h"
35 #include "simlinemgmt.h"
36 #include "simloadingscreen.h"
37 #include "simmenu.h"
38 #include "simmesg.h"
39 #include "simskin.h"
40 #include "simsound.h"
41 #include "simsys.h"
42 #include "simticker.h"
43 #include "simunits.h"
44 #include "simversion.h"
45 #include "display/simview.h"
46 #include "simtool.h"
47 #include "gui/simwin.h"
48 #include "simworld.h"
49
50 #include "tpl/vector_tpl.h"
51 #include "tpl/binary_heap_tpl.h"
52
53 #include "boden/boden.h"
54 #include "boden/wasser.h"
55
56 #include "old_blockmanager.h"
57 #include "vehicle/simvehicle.h"
58 #include "vehicle/simroadtraffic.h"
59 #include "vehicle/simpeople.h"
60 #include "vehicle/movingobj.h"
61 #include "boden/wege/schiene.h"
62
63 #include "obj/zeiger.h"
64 #include "obj/baum.h"
65 #include "obj/signal.h"
66 #include "obj/roadsign.h"
67 #include "obj/wayobj.h"
68 #include "obj/groundobj.h"
69 #include "obj/gebaeude.h"
70 #include "obj/leitung2.h"
71
72 #include "gui/password_frame.h"
73 #include "gui/messagebox.h"
74 #include "gui/help_frame.h"
75 #include "gui/minimap.h"
76 #include "gui/player_frame_t.h"
77
78 #include "network/network.h"
79 #include "network/network_file_transfer.h"
80 #include "network/network_socket_list.h"
81 #include "network/network_cmd_ingame.h"
82 #include "dataobj/height_map_loader.h"
83 #include "dataobj/ribi.h"
84 #include "dataobj/translator.h"
85 #include "dataobj/loadsave.h"
86 #include "dataobj/scenario.h"
87 #include "dataobj/settings.h"
88 #include "dataobj/environment.h"
89 #include "dataobj/powernet.h"
90 #include "dataobj/records.h"
91
92 #include "utils/cbuffer_t.h"
93 #include "utils/simrandom.h"
94 #include "utils/simstring.h"
95
96 #include "network/memory_rw.h"
97
98 #include "bauer/brueckenbauer.h"
99 #include "bauer/tunnelbauer.h"
100 #include "bauer/fabrikbauer.h"
101 #include "bauer/wegbauer.h"
102 #include "bauer/hausbauer.h"
103 #include "bauer/vehikelbauer.h"
104
105 #include "descriptor/ground_desc.h"
106
107 #include "player/simplay.h"
108 #include "player/finance.h"
109 #include "player/ai_passenger.h"
110 #include "player/ai_goods.h"
111 #include "player/ai_scripted.h"
112
113 // forward declaration - management of rotation for scripting
114 namespace script_api
115 {
116 void rotate90();
117 void new_world();
118 };
119
120 // advance 201 ms per sync_step in fast forward mode
121 #define MAGIC_STEP (201)
122
123 // frame per second for fast forward
124 #define FF_PPS (10)
125
126
127 static uint32 last_clients = -1;
128 static uint8 last_active_player_nr = 0;
129 static std::string last_network_game;
130
131 karte_t* karte_t::world = NULL;
132
133 stringhashtable_tpl<karte_t::missing_level_t>missing_pak_names;
134
135 #ifdef MULTI_THREAD
136 #include "utils/simthread.h"
137 #include <semaphore.h>
138
139 bool spawned_world_threads=false; // global job indicator array
140 static simthread_barrier_t world_barrier_start;
141 static simthread_barrier_t world_barrier_end;
142
143
144 // to start a thread
145 typedef struct{
146 karte_t *welt;
147 int thread_num;
148 sint16 x_step;
149 sint16 x_world_max;
150 sint16 y_min;
151 sint16 y_max;
152 sem_t* wait_for_previous;
153 sem_t* signal_to_next;
154 xy_loop_func function;
155 bool keep_running;
156 } world_thread_param_t;
157
158
159 // now the parameters
160 static world_thread_param_t world_thread_param[MAX_THREADS];
161
world_xy_loop_thread(void * ptr)162 void *karte_t::world_xy_loop_thread(void *ptr)
163 {
164 world_thread_param_t *param = reinterpret_cast<world_thread_param_t *>(ptr);
165 while(true) {
166 if(param->keep_running) {
167 simthread_barrier_wait( &world_barrier_start ); // wait for all to start
168 }
169
170 sint16 x_min = 0;
171 sint16 x_max = param->x_step;
172
173 while( x_min < param->x_world_max ) {
174 // wait for predecessor to finish its block
175 if( param->wait_for_previous ) {
176 sem_wait( param->wait_for_previous );
177 }
178 (param->welt->*(param->function))(x_min, x_max, param->y_min, param->y_max);
179
180 // signal to next thread that we finished one block
181 if( param->signal_to_next ) {
182 sem_post( param->signal_to_next );
183 }
184 x_min = x_max;
185 x_max = min(x_max + param->x_step, param->x_world_max);
186 }
187
188 if(param->keep_running) {
189 simthread_barrier_wait( &world_barrier_end ); // wait for all to finish
190 }
191 else {
192 return NULL;
193 }
194 }
195
196 return ptr;
197 }
198 #endif
199
200
world_xy_loop(xy_loop_func function,uint8 flags)201 void karte_t::world_xy_loop(xy_loop_func function, uint8 flags)
202 {
203 const bool use_grids = (flags & GRIDS_FLAG) == GRIDS_FLAG;
204 uint16 max_x = use_grids?(cached_grid_size.x+1):cached_grid_size.x;
205 uint16 max_y = use_grids?(cached_grid_size.y+1):cached_grid_size.y;
206 #ifdef MULTI_THREAD
207 set_random_mode( INTERACTIVE_RANDOM ); // do not allow simrand() here!
208
209 const bool sync_x_steps = (flags & SYNCX_FLAG) == SYNCX_FLAG;
210
211 // semaphores to synchronize progress in x direction
212 sem_t sems[MAX_THREADS-1];
213
214 for( int t = 0; t < env_t::num_threads; t++ ) {
215 if( sync_x_steps && t < env_t::num_threads - 1 ) {
216 sem_init(&sems[t], 0, 0);
217 }
218
219 world_thread_param[t].welt = this;
220 world_thread_param[t].thread_num = t;
221 world_thread_param[t].x_step = min( 64, max_x / env_t::num_threads );
222 world_thread_param[t].x_world_max = max_x;
223 world_thread_param[t].y_min = (t * max_y) / env_t::num_threads;
224 world_thread_param[t].y_max = ((t + 1) * max_y) / env_t::num_threads;
225 world_thread_param[t].function = function;
226
227 world_thread_param[t].wait_for_previous = sync_x_steps && t > 0 ? &sems[t-1] : NULL;
228 world_thread_param[t].signal_to_next = sync_x_steps && t < env_t::num_threads - 1 ? &sems[t] : NULL;
229
230 world_thread_param[t].keep_running = t < env_t::num_threads - 1;
231 }
232
233 if( !spawned_world_threads ) {
234 // we can do the parallel display using posix threads ...
235 pthread_t thread[MAX_THREADS];
236 /* Initialize and set thread detached attribute */
237 pthread_attr_t attr;
238 pthread_attr_init( &attr );
239 pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );
240 // init barrier
241 simthread_barrier_init( &world_barrier_start, NULL, env_t::num_threads );
242 simthread_barrier_init( &world_barrier_end, NULL, env_t::num_threads );
243
244 for( int t = 0; t < env_t::num_threads - 1; t++ ) {
245 if( pthread_create( &thread[t], &attr, world_xy_loop_thread, (void *)&world_thread_param[t] ) ) {
246 dbg->fatal( "karte_t::world_xy_loop()", "cannot multithread, error at thread #%i", t+1 );
247 return;
248 }
249 }
250 spawned_world_threads = true;
251 pthread_attr_destroy( &attr );
252 }
253
254 // and start processing
255 simthread_barrier_wait( &world_barrier_start );
256
257 // the last we can run ourselves
258 world_xy_loop_thread(&world_thread_param[env_t::num_threads-1]);
259
260 simthread_barrier_wait( &world_barrier_end );
261
262 // return from thread
263 for( int t = 0; t < env_t::num_threads - 1; t++ ) {
264 if( sync_x_steps ) {
265 sem_destroy(&sems[t]);
266 }
267 }
268
269 clear_random_mode( INTERACTIVE_RANDOM ); // do not allow simrand() here!
270
271 #else
272 // slow serial way of display
273 (this->*function)( 0, max_x, 0, max_y );
274 #endif
275 }
276
277
rdwr(memory_rw_t * buffer)278 void checklist_t::rdwr(memory_rw_t *buffer)
279 {
280 buffer->rdwr_long(random_seed);
281 buffer->rdwr_short(halt_entry);
282 buffer->rdwr_short(line_entry);
283 buffer->rdwr_short(convoy_entry);
284 }
285
286
print(char * buffer,const char * entity) const287 int checklist_t::print(char *buffer, const char *entity) const
288 {
289 return sprintf(buffer, "%s=[rand=%u halt=%u line=%u cnvy=%u] ", entity, random_seed, halt_entry, line_entry, convoy_entry);
290 }
291
292
recalc_season_snowline(bool set_pending)293 void karte_t::recalc_season_snowline(bool set_pending)
294 {
295 static const sint8 mfactor[12] = { 99, 95, 80, 50, 25, 10, 0, 5, 20, 35, 65, 85 };
296 static const uint8 month_to_season[12] = { 2, 2, 2, 3, 3, 0, 0, 0, 0, 1, 1, 2 };
297
298 // calculate snowline with day precision
299 // use linear interpolation
300 const sint32 ticks_this_month = get_ticks() & (karte_t::ticks_per_world_month - 1);
301 const sint32 factor = mfactor[last_month] + ( ( (mfactor[(last_month + 1) % 12] - mfactor[last_month]) * (ticks_this_month >> 12) ) >> (karte_t::ticks_per_world_month_shift - 12) );
302
303 // just remember them
304 const uint8 old_season = season;
305 const sint16 old_snowline = snowline;
306
307 // and calculate new values
308 season = month_to_season[last_month]; // (2+last_month/3)&3; // summer always zero
309 if( old_season != season && set_pending ) {
310 pending_season_change++;
311 }
312
313 const sint16 winterline = settings.get_winter_snowline();
314 const sint16 summerline = settings.get_climate_borders()[arctic_climate] + 1;
315 snowline = summerline - (sint16)(((summerline-winterline)*factor)/100);
316 if( old_snowline != snowline && set_pending ) {
317 pending_snowline_change++;
318 }
319 }
320
321
perlin_hoehe_loop(sint16 x_min,sint16 x_max,sint16 y_min,sint16 y_max)322 void karte_t::perlin_hoehe_loop( sint16 x_min, sint16 x_max, sint16 y_min, sint16 y_max )
323 {
324 for( int y = y_min; y < y_max; y++ ) {
325 for( int x = x_min; x < x_max; x++ ) {
326 // loop all tiles
327 koord k(x,y);
328 sint16 const h = perlin_hoehe(&settings, k, koord(0, 0));
329 set_grid_hgt( k, (sint8) h);
330 }
331 }
332 }
333
334
335 /**
336 * Height one point in the map with "perlin noise"
337 *
338 * @param frequency in 0..1.0 roughness, the higher the rougher
339 * @param amplitude in 0..160.0 top height of mountains, may not exceed 160.0!!!
340 * @author Hj. Malthaner
341 */
perlin_hoehe(settings_t const * const sets,koord k,koord const size)342 sint32 karte_t::perlin_hoehe(settings_t const* const sets, koord k, koord const size)
343 {
344 // Hajo: to Markus: replace the fixed values with your
345 // settings. Amplitude is the top highness of the
346 // mountains, frequency is something like landscape 'roughness'
347 // amplitude may not be greater than 160.0 !!!
348 // please don't allow frequencies higher than 0.8 it'll
349 // break the AI's pathfinding. Frequency values of 0.5 .. 0.7
350 // seem to be ok, less is boring flat, more is too crumbled
351 // the old defaults are given here: f=0.6, a=160.0
352 switch( sets->get_rotation() ) {
353 // 0: do nothing
354 case 1: k = koord(k.y,size.x-k.x); break;
355 case 2: k = koord(size.x-k.x,size.y-k.y); break;
356 case 3: k = koord(size.y-k.y,k.x); break;
357 }
358 // double perlin_noise_2D(double x, double y, double persistence);
359 // return ((int)(perlin_noise_2D(x, y, 0.6)*160.0)) & 0xFFFFFFF0;
360 k = k + koord(sets->get_origin_x(), sets->get_origin_y());
361 return ((int)(perlin_noise_2D(k.x, k.y, sets->get_map_roughness())*(double)sets->get_max_mountain_height())) / 16;
362 }
363
364
cleanup_grounds_loop(sint16 x_min,sint16 x_max,sint16 y_min,sint16 y_max)365 void karte_t::cleanup_grounds_loop( sint16 x_min, sint16 x_max, sint16 y_min, sint16 y_max )
366 {
367 for( int y = y_min; y < y_max; y++ ) {
368 for( int x = x_min; x < x_max; x++ ) {
369 planquadrat_t *pl = access_nocheck(x,y);
370 grund_t *gr = pl->get_kartenboden();
371 koord k(x,y);
372 uint8 slope = calc_natural_slope(k);
373 sint8 height = min_hgt_nocheck(k);
374 sint8 water_hgt = get_water_hgt_nocheck(k);
375
376 if( height < water_hgt) {
377 const sint8 disp_hn_sw = max( height + corner_sw(slope), water_hgt );
378 const sint8 disp_hn_se = max( height + corner_se(slope), water_hgt );
379 const sint8 disp_hn_ne = max( height + corner_ne(slope), water_hgt );
380 const sint8 disp_hn_nw = max( height + corner_nw(slope), water_hgt );
381 height = water_hgt;
382 slope = (disp_hn_sw - height) + ((disp_hn_se - height) * 3) + ((disp_hn_ne - height) * 9) + ((disp_hn_nw - height) * 27);
383 }
384
385 gr->set_pos( koord3d( k, height) );
386 if( gr->get_typ() != grund_t::wasser && max_hgt_nocheck(k) <= water_hgt ) {
387 // below water but ground => convert
388 pl->kartenboden_setzen( new wasser_t(gr->get_pos()), true /* do not calc_image for water tiles */ );
389 }
390 else if( gr->get_typ() == grund_t::wasser && max_hgt_nocheck(k) > water_hgt ) {
391 // water above ground => to ground
392 pl->kartenboden_setzen( new boden_t(gr->get_pos(), slope ) );
393 }
394 else {
395 gr->set_grund_hang( slope );
396 }
397
398 if( max_hgt_nocheck(k) > water_hgt ) {
399 set_water_hgt(k, groundwater-4);
400 }
401 }
402 }
403 }
404
405
cleanup_karte(int xoff,int yoff)406 void karte_t::cleanup_karte( int xoff, int yoff )
407 {
408 // we need a copy to smooth the map to a realistic level
409 const sint32 grid_size = (get_size().x+1)*(sint32)(get_size().y+1);
410 sint8 *grid_hgts_cpy = new sint8[grid_size];
411 memcpy( grid_hgts_cpy, grid_hgts, grid_size );
412
413 // the trick for smoothing is to raise each tile by one
414 sint32 i,j;
415 for(j=0; j<=get_size().y; j++) {
416 for(i=j>=yoff?0:xoff; i<=get_size().x; i++) {
417 raise_grid_to(i,j, grid_hgts_cpy[i+j*(get_size().x+1)] + 1);
418 }
419 }
420 delete [] grid_hgts_cpy;
421
422 // but to leave the map unchanged, we lower the height again
423 for(j=0; j<=get_size().y; j++) {
424 for(i=j>=yoff?0:xoff; i<=get_size().x; i++) {
425 grid_hgts[i+j*(get_size().x+1)] --;
426 }
427 }
428
429 if( xoff==0 && yoff==0 ) {
430 world_xy_loop(&karte_t::cleanup_grounds_loop, 0);
431 }
432 else {
433 cleanup_grounds_loop( 0, get_size().x, yoff, get_size().y );
434 cleanup_grounds_loop( xoff, get_size().x, 0, yoff );
435 }
436 }
437
438
destroy()439 void karte_t::destroy()
440 {
441 is_sound = false; // karte_t::play_sound_area_clipped needs valid zeiger (pointer/drawer)
442 destroying = true;
443 DBG_MESSAGE("karte_t::destroy()", "destroying world");
444
445 uint32 max_display_progress = 256+stadt.get_count()*10 + haltestelle_t::get_alle_haltestellen().get_count() + convoi_array.get_count() + (cached_size.x*cached_size.y)*2;
446 uint32 old_progress = 0;
447
448 loadingscreen_t ls( translator::translate("Destroying map ..."), max_display_progress, true );
449
450 // rotate the map until it can be saved
451 nosave_warning = false;
452 if( nosave ) {
453 max_display_progress += 256;
454 for( int i=0; i<4 && nosave; i++ ) {
455 DBG_MESSAGE("karte_t::destroy()", "rotating");
456 rotate90();
457 }
458 old_progress += 256;
459 ls.set_max( max_display_progress );
460 ls.set_progress( old_progress );
461 }
462 if(nosave) {
463 dbg->fatal( "karte_t::destroy()","Map cannot be cleanly destroyed in any rotation!" );
464 }
465
466 goods_in_game.clear();
467
468 DBG_MESSAGE("karte_t::destroy()", "label clear");
469 labels.clear();
470
471 if(zeiger) {
472 zeiger->set_pos(koord3d::invalid);
473 delete zeiger;
474 zeiger = NULL;
475 }
476
477 old_progress += 256;
478 ls.set_progress( old_progress );
479
480 // removes all moving stuff from the sync_step
481 sync.clear();
482 sync_eyecandy.clear();
483 sync_way_eyecandy.clear();
484 old_progress += cached_size.x*cached_size.y;
485 ls.set_progress( old_progress );
486 DBG_MESSAGE("karte_t::destroy()", "sync list cleared");
487
488 // alle convois aufraeumen
489 while (!convoi_array.empty()) {
490 convoihandle_t cnv = convoi_array.back();
491 cnv->destroy();
492 old_progress ++;
493 if( (old_progress&0x00FF) == 0 ) {
494 ls.set_progress( old_progress );
495 }
496 }
497 convoi_array.clear();
498 DBG_MESSAGE("karte_t::destroy()", "convois destroyed");
499
500 // alle haltestellen aufraeumen
501 old_progress += haltestelle_t::get_alle_haltestellen().get_count();
502 haltestelle_t::destroy_all();
503 DBG_MESSAGE("karte_t::destroy()", "stops destroyed");
504 ls.set_progress( old_progress );
505
506 // remove all target cities (we can skip recalculation anyway)
507 FOR(slist_tpl<fabrik_t*>, const f, fab_list) {
508 f->clear_target_cities();
509 }
510
511 // delete towns first (will also delete all their houses)
512 // for the next game we need to remember the desired number ...
513 sint32 const no_of_cities = settings.get_city_count();
514 for( uint32 i=0; !stadt.empty(); i++ ) {
515 remove_city(stadt.front());
516 old_progress += 10;
517 if( (i&0x00F) == 0 ) {
518 ls.set_progress( old_progress );
519 }
520 }
521 settings.set_city_count(no_of_cities);
522 DBG_MESSAGE("karte_t::destroy()", "towns destroyed");
523
524 ls.set_progress( old_progress );
525 // dinge aufraeumen
526 cached_grid_size.x = cached_grid_size.y = 1;
527 cached_size.x = cached_size.y = 0;
528 delete [] plan;
529 plan = NULL;
530 DBG_MESSAGE("karte_t::destroy()", "planquadrat destroyed");
531
532 old_progress += (cached_size.x*cached_size.y)/2;
533 ls.set_progress( old_progress );
534
535 // gitter aufraeumen
536 delete [] grid_hgts;
537 grid_hgts = NULL;
538
539 delete [] water_hgts;
540 water_hgts = NULL;
541
542 // player cleanup
543 for(int i=0; i<MAX_PLAYER_COUNT; i++) {
544 delete players[i];
545 players[i] = NULL;
546 }
547 DBG_MESSAGE("karte_t::destroy()", "player destroyed");
548
549 old_progress += (cached_size.x*cached_size.y)/4;
550 ls.set_progress( old_progress );
551
552 // alle fabriken aufraeumen
553 FOR(slist_tpl<fabrik_t*>, const f, fab_list) {
554 delete f;
555 }
556 fab_list.clear();
557 DBG_MESSAGE("karte_t::destroy()", "factories destroyed");
558
559 // hier nur entfernen, aber nicht loeschen
560 attractions.clear();
561 DBG_MESSAGE("karte_t::destroy()", "attraction list destroyed");
562
563 delete scenario;
564 scenario = NULL;
565
566 assert( depot_t::get_depot_list().empty() );
567
568 DBG_MESSAGE("karte_t::destroy()", "world destroyed");
569 destroying = false;
570 }
571
572
add_convoi(convoihandle_t const cnv)573 void karte_t::add_convoi(convoihandle_t const cnv)
574 {
575 assert(cnv.is_bound());
576 convoi_array.append_unique(cnv);
577 }
578
579
rem_convoi(convoihandle_t const cnv)580 void karte_t::rem_convoi(convoihandle_t const cnv)
581 {
582 convoi_array.remove(cnv);
583 }
584
585
add_city(stadt_t * s)586 void karte_t::add_city(stadt_t *s)
587 {
588 settings.set_city_count(settings.get_city_count() + 1);
589 stadt.append(s, s->get_einwohner());
590
591 // Knightly : add links between this city and other cities as well as attractions
592 FOR(weighted_vector_tpl<stadt_t*>, const c, stadt) {
593 c->add_target_city(s);
594 }
595 s->recalc_target_cities();
596 s->recalc_target_attractions();
597 }
598
599
remove_city(stadt_t * s)600 bool karte_t::remove_city(stadt_t *s)
601 {
602 if(s == NULL || stadt.empty()) {
603 // no town there to delete ...
604 return false;
605 }
606
607 // reduce number of towns
608 if(s->get_name()) {
609 DBG_MESSAGE("karte_t::remove_city()", "%s", s->get_name());
610 }
611 stadt.remove(s);
612 DBG_DEBUG4("karte_t::remove_city()", "reduce city to %i", settings.get_city_count() - 1);
613 settings.set_city_count(settings.get_city_count() - 1);
614
615 // Knightly : remove links between this city and other cities
616 FOR(weighted_vector_tpl<stadt_t*>, const c, stadt) {
617 c->remove_target_city(s);
618 }
619
620 // remove all links from factories
621 DBG_DEBUG4("karte_t::remove_city()", "fab_list %i", fab_list.get_count() );
622 FOR(slist_tpl<fabrik_t*>, const f, fab_list) {
623 f->remove_target_city(s);
624 }
625
626 // ok, we can delete this
627 DBG_MESSAGE("karte_t::remove_city()", "delete" );
628 delete s;
629
630 return true;
631 }
632
633
634 // just allocates space;
init_tiles()635 void karte_t::init_tiles()
636 {
637 assert(plan==0);
638
639 uint32 const x = get_size().x;
640 uint32 const y = get_size().y;
641 plan = new planquadrat_t[x * y];
642 grid_hgts = new sint8[(x + 1) * (y + 1)];
643 max_height = min_height = 0;
644 MEMZERON(grid_hgts, (x + 1) * (y + 1));
645 water_hgts = new sint8[x * y];
646 MEMZERON(water_hgts, x * y);
647
648 win_set_world( this );
649 minimap_t::get_instance()->init();
650
651 for(int i=0; i<MAX_PLAYER_COUNT ; i++) {
652 // old default: AI 3 passenger, other goods
653 players[i] = (i<2) ? new player_t(i) : NULL;
654 }
655 active_player = players[0];
656 active_player_nr = 0;
657
658 // defaults without timeline
659 average_speed[0] = 60;
660 average_speed[1] = 80;
661 average_speed[2] = 40;
662 average_speed[3] = 350;
663
664 // clear world records
665 records->clear_speed_records();
666
667 // make timer loop invalid
668 for( int i=0; i<32; i++ ) {
669 last_frame_ms[i] = 0x7FFFFFFFu;
670 last_step_nr[i] = 0xFFFFFFFFu;
671 }
672 last_frame_idx = 0;
673 pending_season_change = 0;
674 pending_snowline_change = 0;
675
676 // init global history
677 for (int year=0; year<MAX_WORLD_HISTORY_YEARS; year++) {
678 for (int cost_type=0; cost_type<MAX_WORLD_COST; cost_type++) {
679 finance_history_year[year][cost_type] = 0;
680 }
681 }
682 for (int month=0; month<MAX_WORLD_HISTORY_MONTHS; month++) {
683 for (int cost_type=0; cost_type<MAX_WORLD_COST; cost_type++) {
684 finance_history_month[month][cost_type] = 0;
685 }
686 }
687 last_month_bev = 0;
688
689 tile_counter = 0;
690
691 convoihandle_t::init( 1024 );
692 linehandle_t::init( 1024 );
693
694 halthandle_t::init( 1024 );
695
696 vehicle_base_t::set_overtaking_offsets( get_settings().is_drive_left() );
697
698 scenario = new scenario_t(this);
699
700 nosave_warning = nosave = false;
701
702 if (env_t::server) {
703 nwc_auth_player_t::init_player_lock_server(this);
704 }
705 }
706
707
set_scenario(scenario_t * s)708 void karte_t::set_scenario(scenario_t *s)
709 {
710 if (scenario != s) {
711 delete scenario;
712 }
713 scenario = s;
714 }
715
716
create_rivers(sint16 number)717 void karte_t::create_rivers( sint16 number )
718 {
719 // First check, whether there is a canal:
720 const way_desc_t* river_desc = way_builder_t::get_desc( env_t::river_type[env_t::river_types-1], 0 );
721 if( river_desc == NULL ) {
722 // should never reaching here ...
723 dbg->warning("karte_t::create_rivers()","There is no river defined!\n");
724 return;
725 }
726
727 // create a vector of the highest points
728 vector_tpl<koord> water_tiles;
729 weighted_vector_tpl<koord> mountain_tiles;
730
731 sint8 last_height = 1;
732 koord last_koord(0,0);
733 const sint16 max_dist = cached_size.y+cached_size.x;
734
735 // trunk of 16 will ensure that rivers are long enough apart ...
736 for( sint16 y = 8; y < cached_size.y; y+=16 ) {
737 for( sint16 x = 8; x < cached_size.x; x+=16 ) {
738 koord k(x,y);
739 grund_t *gr = lookup_kartenboden_nocheck(k);
740 const sint8 h = gr->get_hoehe() - get_water_hgt_nocheck(k);
741 if( gr->is_water() ) {
742 // may be good to start a river here
743 water_tiles.append(k);
744 }
745 else if( h>=last_height || koord_distance(last_koord,k)>simrand(max_dist) ) {
746 // something worth to add here
747 if( h>last_height ) {
748 last_height = h;
749 }
750 last_koord = k;
751 // using h*h as weight would give mountain sources more preferences
752 // on the other hand most rivers do not string near summits ...
753 mountain_tiles.append( k, h );
754 }
755 }
756 }
757 if (water_tiles.empty()) {
758 dbg->message("karte_t::create_rivers()","There aren't any water tiles!\n");
759 return;
760 }
761
762 // now make rivers
763 sint16 retrys = number*2;
764 while( number > 0 && !mountain_tiles.empty() && retrys>0 ) {
765
766 // start with random coordinates
767 koord const start = pick_any_weighted(mountain_tiles);
768 mountain_tiles.remove( start );
769
770 // build a list of matching targets
771 vector_tpl<koord> valid_water_tiles;
772 for( uint32 i=0; i<water_tiles.get_count(); i++ ) {
773 sint16 dist = koord_distance(start,water_tiles[i]);
774 if( settings.get_min_river_length() < dist && dist < settings.get_max_river_length() ) {
775 valid_water_tiles.append( water_tiles[i] );
776 }
777 }
778
779 // now try 256 random locations
780 for( sint32 i=0; i<256 && !valid_water_tiles.empty(); i++ ) {
781 koord const end = pick_any(valid_water_tiles);
782 valid_water_tiles.remove( end );
783 way_builder_t riverbuilder(players[1]);
784 riverbuilder.init_builder(way_builder_t::river, river_desc);
785 sint16 dist = koord_distance(start,end);
786 riverbuilder.set_maximum( dist*50 );
787 riverbuilder.calc_route( lookup_kartenboden(end)->get_pos(), lookup_kartenboden(start)->get_pos() );
788 if( riverbuilder.get_count() >= (uint32)settings.get_min_river_length() ) {
789 // do not built too short rivers
790 riverbuilder.build();
791 number --;
792 retrys++;
793 break;
794 }
795 }
796
797 retrys--;
798 }
799 // we gave up => tell the user
800 if( number>0 ) {
801 dbg->warning( "karte_t::create_rivers()","Too many rivers requested! (%i not constructed)", number );
802 }
803 }
804
805
distribute_groundobjs_cities(int new_city_count,sint32 new_mean_citizen_count,sint16 old_x,sint16 old_y)806 void karte_t::distribute_groundobjs_cities(int new_city_count, sint32 new_mean_citizen_count, sint16 old_x, sint16 old_y )
807 {
808 DBG_DEBUG("karte_t::distribute_groundobjs_cities()","distributing rivers");
809 if( env_t::river_types > 0 && settings.get_river_number() > 0 ) {
810 create_rivers( settings.get_river_number() );
811 }
812
813 DBG_DEBUG("karte_t::distribute_groundobjs_cities()","prepare cities");
814 vector_tpl<koord> *pos = stadt_t::random_place(new_city_count, old_x, old_y);
815
816 if( !pos->empty() ) {
817 const sint32 old_city_count = stadt.get_count();
818 new_city_count = pos->get_count();
819 DBG_DEBUG("karte_t::distribute_groundobjs_cities()", "Creating cities: %d", new_city_count);
820
821 // prissi if we could not generate enough positions ...
822 settings.set_city_count(old_city_count);
823 int old_progress = 16;
824
825 loadingscreen_t ls( translator::translate( "distributing cities" ), 16 + 2 * (old_city_count + new_city_count) + 2 * new_city_count + (old_x == 0 ? settings.get_factory_count() : 0), true, true );
826
827 {
828 // Loop only new cities:
829 #ifdef DEBUG
830 uint32 tbegin = dr_time();
831 #endif
832 for( int i=0; i<new_city_count; i++ ) {
833 stadt_t* s = new stadt_t(players[1], (*pos)[i], 1 );
834 DBG_DEBUG("karte_t::distribute_groundobjs_cities()","Erzeuge stadt %i with %ld inhabitants",i,(s->get_city_history_month())[HIST_CITICENS] );
835 if (s->get_buildings() > 0) {
836 add_city(s);
837 }
838 else {
839 delete(s);
840 }
841 }
842 // center on first city
843 if( old_x+old_y == 0 && stadt.get_count()>0) {
844 viewport->change_world_position( stadt[0]->get_pos() );
845 }
846
847 delete pos;
848 #ifdef DEBUG
849 dbg->message("karte_t::distribute_groundobjs_cities()","took %lu ms for all towns", dr_time()-tbegin );
850 #endif
851
852 uint32 game_start = current_month;
853 // townhalls available since?
854 FOR(vector_tpl<building_desc_t const*>, const desc, *hausbauer_t::get_list(building_desc_t::townhall)) {
855 uint32 intro_year_month = desc->get_intro_year_month();
856 if( intro_year_month<game_start ) {
857 game_start = intro_year_month;
858 }
859 }
860 // streets since when?
861 game_start = max( game_start, way_builder_t::get_earliest_way(road_wt)->get_intro_year_month() );
862
863 uint32 original_start_year = current_month;
864 uint32 original_industry_growth = settings.get_industry_increase_every();
865 settings.set_industry_increase_every( 0 );
866
867 for( uint32 i=old_city_count; i<stadt.get_count(); i++ ) {
868 // Hajo: do final init after world was loaded/created
869 stadt[i]->finish_rd();
870
871 // int citizens=(int)(new_mean_citizen_count*0.9);
872 // citizens = citizens/10+simrand(2*citizens+1);
873 const sint32 citizens = (2500l * new_mean_citizen_count) /(simrand(20000)+100);
874
875 sint32 diff = (original_start_year-game_start)/2;
876 sint32 growth = 32;
877 sint32 current_bev = 1;
878
879 /* grow gradually while aging
880 * the difference to the current end year will be halved,
881 * while the growth step is doubled
882 */
883 current_month = game_start;
884 bool not_updated = false;
885 bool new_town = true;
886 while( current_bev < citizens ) {
887 growth = min( citizens-current_bev, growth*2 );
888 current_bev += growth;
889 stadt[i]->change_size( growth, new_town );
890 // Only "new" for the first change_size call
891 new_town = false;
892 if( current_bev > citizens/2 && not_updated ) {
893 ls.set_progress( ++old_progress );
894 not_updated = true;
895 }
896 current_month += diff;
897 diff >>= 1;
898 }
899
900 // the growth is slow, so update here the progress bar
901 ls.set_progress( ++old_progress );
902 }
903
904 current_month = original_start_year;
905 settings.set_industry_increase_every( original_industry_growth );
906 msg->clear();
907 }
908 finance_history_year[0][WORLD_TOWNS] = finance_history_month[0][WORLD_TOWNS] = stadt.get_count();
909 finance_history_year[0][WORLD_CITICENS] = finance_history_month[0][WORLD_CITICENS] = last_month_bev;
910
911 // Hajo: connect some cities with roads
912 way_desc_t const* desc = settings.get_intercity_road_type(get_timeline_year_month());
913 if(desc == 0) {
914 // Hajo: try some default (might happen with timeline ... )
915 desc = way_builder_t::weg_search(road_wt,80,get_timeline_year_month(),type_flat);
916 }
917
918 way_builder_t bauigel (players[1] );
919 bauigel.init_builder(way_builder_t::strasse | way_builder_t::terraform_flag, desc, tunnel_builder_t::get_tunnel_desc(road_wt,15,get_timeline_year_month()), bridge_builder_t::find_bridge(road_wt,15,get_timeline_year_month()) );
920 bauigel.set_keep_existing_ways(true);
921 bauigel.set_maximum(env_t::intercity_road_length);
922
923 // **** intercity road construction
924 int count = 0;
925 sint32 const n_cities = settings.get_city_count();
926 int const max_count = n_cities * (n_cities - 1) / 2 - old_city_count * (old_city_count - 1) / 2;
927 // something to do??
928 if( max_count > 0 ) {
929 // print("Building intercity roads ...\n");
930 ls.set_max( 16 + 2 * (old_city_count + new_city_count) + 2 * new_city_count + (old_x == 0 ? settings.get_factory_count() : 0) );
931 // find townhall of city i and road in front of it
932 vector_tpl<koord3d> k;
933 for (int i = 0; i < settings.get_city_count(); ++i) {
934 koord k1(stadt[i]->get_townhall_road());
935 if (lookup_kartenboden(k1) && lookup_kartenboden(k1)->hat_weg(road_wt)) {
936 k.append(lookup_kartenboden(k1)->get_pos());
937 }
938 else {
939 // look for a road near the townhall
940 gebaeude_t const* const gb = obj_cast<gebaeude_t>(lookup_kartenboden(stadt[i]->get_pos())->first_obj());
941 bool ok = false;
942 if( gb && gb->is_townhall() ) {
943 koord k_check = stadt[i]->get_pos() + koord(-1,-1);
944 const koord size = gb->get_tile()->get_desc()->get_size(gb->get_tile()->get_layout());
945 koord inc(1,0);
946 // scan all adjacent tiles, take the first that has a road
947 for(sint32 i=0; i<2*size.x+2*size.y+4 && !ok; i++) {
948 grund_t *gr = lookup_kartenboden(k_check);
949 if (gr && gr->hat_weg(road_wt)) {
950 k.append(gr->get_pos());
951 ok = true;
952 }
953 k_check = k_check + inc;
954 if (i==size.x+1) {
955 inc = koord(0,1);
956 }
957 else if (i==size.x+size.y+2) {
958 inc = koord(-1,0);
959 }
960 else if (i==2*size.x+size.y+3) {
961 inc = koord(0,-1);
962 }
963 }
964 }
965 if (!ok) {
966 k.append( koord3d::invalid );
967 }
968 }
969 }
970 // compute all distances
971 uint8 conn_comp=1; // current connection component for phase 0
972 vector_tpl<uint8> city_flag; // city already connected to the graph? >0 nr of connection component
973 array2d_tpl<sint32> city_dist(settings.get_city_count(), settings.get_city_count());
974 for (sint32 i = 0; i < settings.get_city_count(); ++i) {
975 city_dist.at(i,i) = 0;
976 for (sint32 j = i + 1; j < settings.get_city_count(); ++j) {
977 city_dist.at(i,j) = koord_distance(k[i], k[j]);
978 city_dist.at(j,i) = city_dist.at(i,j);
979 // count unbuildable connections to new cities
980 if( j>=old_city_count && city_dist.at(i,j) >= env_t::intercity_road_length ) {
981 count++;
982 }
983 }
984 city_flag.append( i < old_city_count ? conn_comp : 0 );
985
986 // progress bar stuff
987 ls.set_progress( 16 + 2 * new_city_count + count * settings.get_city_count() * 2 / max_count );
988 }
989 // mark first town as connected
990 if (old_city_count==0) {
991 city_flag[0]=conn_comp;
992 }
993
994 // get a default vehikel
995 route_t verbindung;
996 vehicle_t* test_driver;
997 vehicle_desc_t test_drive_desc(road_wt, 500, vehicle_desc_t::diesel );
998 test_driver = vehicle_builder_t::build(koord3d(), players[1], NULL, &test_drive_desc);
999 test_driver->set_flag( obj_t::not_on_map );
1000
1001 bool ready=false;
1002 uint8 phase=0;
1003 // 0 - first phase: built minimum spanning tree (edge weights: city distance)
1004 // 1 - second phase: try to complete the graph, avoid edges that
1005 // == have similar length then already existing connection
1006 // == lead to triangles with an angle >90 deg
1007
1008 while( phase < 2 ) {
1009 ready = true;
1010 koord conn = koord::invalid;
1011 sint32 best = env_t::intercity_road_length;
1012
1013 if( phase == 0 ) {
1014 // loop over all unconnected cities
1015 for (int i = 0; i < settings.get_city_count(); ++i) {
1016 if( city_flag[i] == conn_comp ) {
1017 // loop over all connections to connected cities
1018 for (int j = old_city_count; j < settings.get_city_count(); ++j) {
1019 if( city_flag[j] == 0 ) {
1020 ready=false;
1021 if( city_dist.at(i,j) < best ) {
1022 best = city_dist.at(i,j);
1023 conn = koord(i,j);
1024 }
1025 }
1026 }
1027 }
1028 }
1029 // did we completed a connection component?
1030 if( !ready && best == env_t::intercity_road_length ) {
1031 // next component
1032 conn_comp++;
1033 // try the first not connected city
1034 ready = true;
1035 for( int i = old_city_count; i < settings.get_city_count(); ++i ) {
1036 if( city_flag[i] ==0 ) {
1037 city_flag[i] = conn_comp;
1038 ready = false;
1039 break;
1040 }
1041 }
1042 }
1043 }
1044 else {
1045 // loop over all unconnected cities
1046 for (int i = 0; i < settings.get_city_count(); ++i) {
1047 for (int j = max(old_city_count, i + 1); j < settings.get_city_count(); ++j) {
1048 if( city_dist.at(i,j) < best && city_flag[i] == city_flag[j] ) {
1049 bool ok = true;
1050 // is there a connection i..l..j ? forbid stumpfe winkel
1051 for (int l = 0; l < settings.get_city_count(); ++l) {
1052 if( city_flag[i] == city_flag[l] && city_dist.at(i,l) == env_t::intercity_road_length && city_dist.at(j,l) == env_t::intercity_road_length ) {
1053 // cosine < 0 ?
1054 koord3d d1 = k[i]-k[l];
1055 koord3d d2 = k[j]-k[l];
1056 if( d1.x*d2.x + d1.y*d2.y < 0 ) {
1057 city_dist.at(i,j) = env_t::intercity_road_length+1;
1058 city_dist.at(j,i) = env_t::intercity_road_length+1;
1059 ok = false;
1060 count ++;
1061 break;
1062 }
1063 }
1064 }
1065 if(ok) {
1066 ready = false;
1067 best = city_dist.at(i,j);
1068 conn = koord(i,j);
1069 }
1070 }
1071 }
1072 }
1073 }
1074 // valid connection?
1075 if( conn.x >= 0 ) {
1076 // is there a connection already
1077 const bool connected = ( phase==1 && verbindung.calc_route( this, k[conn.x], k[conn.y], test_driver, 0, 0 ) );
1078 // build this connection?
1079 bool build = false;
1080 // set appropriate max length for way builder
1081 if( connected ) {
1082 if( 2*verbindung.get_count() > (uint32)city_dist.at(conn) ) {
1083 bauigel.set_maximum(verbindung.get_count() / 2);
1084 build = true;
1085 }
1086 }
1087 else {
1088 bauigel.set_maximum(env_t::intercity_road_length);
1089 build = true;
1090 }
1091
1092 if( build ) {
1093 bauigel.calc_route(k[conn.x],k[conn.y]);
1094 }
1095
1096 if( build && bauigel.get_count() >= 2 ) {
1097 bauigel.build();
1098 if (phase==0) {
1099 city_flag[ conn.y ] = conn_comp;
1100 }
1101 // mark as built
1102 city_dist.at(conn) = env_t::intercity_road_length;
1103 city_dist.at(conn.y, conn.x) = env_t::intercity_road_length;
1104 count ++;
1105 }
1106 else {
1107 // do not try again
1108 city_dist.at(conn) = env_t::intercity_road_length+1;
1109 city_dist.at(conn.y, conn.x) = env_t::intercity_road_length+1;
1110 count ++;
1111
1112 if( phase == 0 ) {
1113 // do not try to connect to this connected component again
1114 for( int i = 0; i < settings.get_city_count(); ++i ) {
1115 if( city_flag[i] == conn_comp && city_dist.at(i, conn.y)<env_t::intercity_road_length) {
1116 city_dist.at(i, conn.y) = env_t::intercity_road_length+1;
1117 city_dist.at(conn.y, i) = env_t::intercity_road_length+1;
1118 count++;
1119 }
1120 }
1121 }
1122 }
1123 }
1124
1125 // progress bar stuff
1126 ls.set_progress( 16 + 2 * new_city_count + count * settings.get_city_count() * 2 / max_count );
1127
1128 // next phase?
1129 if(ready) {
1130 phase++;
1131 ready = false;
1132 }
1133 }
1134 delete test_driver;
1135 }
1136 }
1137 else {
1138 // could not generate any town
1139 delete pos;
1140 settings.set_city_count( stadt.get_count() ); // new number of towns (if we did not find enough positions)
1141 }
1142
1143 DBG_DEBUG("karte_t::distribute_groundobjs_cities()","distributing groundobjs");
1144 if( env_t::ground_object_probability > 0 ) {
1145 // add eyecandy like rocky, moles, flowers, ...
1146 koord k;
1147 sint32 queried = simrand(env_t::ground_object_probability*2-1);
1148 for( k.y=0; k.y<get_size().y; k.y++ ) {
1149 for( k.x=(k.y<old_y)?old_x:0; k.x<get_size().x; k.x++ ) {
1150 grund_t *gr = lookup_kartenboden_nocheck(k);
1151 if( gr->get_typ()==grund_t::boden && !gr->hat_wege() ) {
1152 queried --;
1153 if( queried<0 ) {
1154 // test for beach
1155 bool neighbour_water = false;
1156 for(int i=0; i<8; i++) {
1157 if( is_within_limits(k + koord::neighbours[i]) && get_climate( k + koord::neighbours[i] ) == water_climate ) {
1158 neighbour_water = true;
1159 break;
1160 }
1161 }
1162 const climate_bits cl = neighbour_water ? water_climate_bit : (climate_bits)(1<<get_climate(k));
1163 const groundobj_desc_t *desc = groundobj_t::random_groundobj_for_climate( cl, gr->get_grund_hang() );
1164 queried = simrand(env_t::ground_object_probability*2-1);
1165 if(desc) {
1166 gr->obj_add( new groundobj_t( gr->get_pos(), desc ) );
1167 }
1168 }
1169 }
1170 }
1171 }
1172 }
1173
1174 DBG_DEBUG("karte_t::distribute_groundobjs_cities()","distributing movingobjs");
1175 if( env_t::moving_object_probability > 0 ) {
1176 // add animals and so on (must be done after growing and all other objects, that could change ground coordinates)
1177 koord k;
1178 bool has_water = movingobj_t::random_movingobj_for_climate( water_climate )!=NULL;
1179 sint32 queried = simrand(env_t::moving_object_probability*2);
1180 // no need to test the borders, since they are mostly slopes anyway
1181 for(k.y=1; k.y<get_size().y-1; k.y++) {
1182 for(k.x=(k.y<old_y)?old_x:1; k.x<get_size().x-1; k.x++) {
1183 grund_t *gr = lookup_kartenboden_nocheck(k);
1184 // flat ground or open water
1185 if( gr->get_top()==0 && ( (gr->get_typ()==grund_t::boden && gr->get_grund_hang()==slope_t::flat) || (has_water && gr->is_water()) ) ) {
1186 queried --;
1187 if( queried<0 ) {
1188 const groundobj_desc_t *desc = movingobj_t::random_movingobj_for_climate( get_climate(k) );
1189 if( desc && ( desc->get_waytype() != water_wt || gr->get_hoehe() <= get_water_hgt_nocheck(k) ) ) {
1190 if(desc->get_speed()!=0) {
1191 queried = simrand(env_t::moving_object_probability*2);
1192 gr->obj_add( new movingobj_t( gr->get_pos(), desc ) );
1193 }
1194 }
1195 }
1196 }
1197 }
1198 }
1199 }
1200 }
1201
1202
init(settings_t * const sets,sint8 const * const h_field)1203 void karte_t::init(settings_t* const sets, sint8 const* const h_field)
1204 {
1205 clear_random_mode( 7 );
1206 mute_sound(true);
1207 if (env_t::networkmode) {
1208 if (env_t::server) {
1209 network_reset_server();
1210 }
1211 else {
1212 network_core_shutdown();
1213 }
1214 }
1215 step_mode = PAUSE_FLAG;
1216 intr_disable();
1217
1218 if(plan) {
1219 destroy();
1220 }
1221
1222 for( uint i=0; i<MAX_PLAYER_COUNT; i++ ) {
1223 selected_tool[i] = tool_t::general_tool[TOOL_QUERY];
1224 }
1225 if(is_display_init()) {
1226 display_show_pointer(false);
1227 }
1228 viewport->change_world_position( koord(0,0), 0, 0 );
1229
1230 settings = *sets;
1231 // names during creation time
1232 settings.set_name_language_iso(env_t::language_iso);
1233 settings.set_use_timeline(settings.get_use_timeline() & 1);
1234
1235 ticks = 0;
1236 last_step_ticks = ticks;
1237 schedule_counter = 0;
1238 // ticks = 0x7FFFF800; // Testing the 31->32 bit step
1239
1240 last_month = 0;
1241 last_year = settings.get_starting_year();
1242 current_month = last_month + (last_year*12);
1243 set_ticks_per_world_month_shift(settings.get_bits_per_month());
1244 next_month_ticks = karte_t::ticks_per_world_month;
1245 season=(2+last_month/3)&3; // summer always zero
1246 steps = 0;
1247 network_frame_count = 0;
1248 sync_steps = 0;
1249 sync_steps_barrier = sync_steps;
1250 map_counter = 0;
1251 recalc_average_speed(); // resets timeline
1252 koord::locality_factor = settings.get_locality_factor( last_year );
1253
1254 world_maximum_height = sets->get_maximumheight();
1255 world_minimum_height = sets->get_minimumheight();
1256 groundwater = (sint8)sets->get_groundwater(); //29-Nov-01 Markus Weber Changed
1257
1258 init_height_to_climate();
1259 snowline = sets->get_winter_snowline() + groundwater;
1260
1261 if(sets->get_beginner_mode()) {
1262 goods_manager_t::set_multiplier(settings.get_beginner_price_factor());
1263 settings.set_just_in_time( 0 );
1264 }
1265 else {
1266 goods_manager_t::set_multiplier( 1000 );
1267 }
1268
1269 recalc_season_snowline(false);
1270
1271 stadt.clear();
1272
1273 DBG_DEBUG("karte_t::init()","hausbauer_t::new_world()");
1274 // Call this before building cities
1275 hausbauer_t::new_world();
1276
1277 cached_grid_size.x = 0;
1278 cached_grid_size.y = 0;
1279
1280 DBG_DEBUG("karte_t::init()","init_tiles");
1281 init_tiles();
1282
1283 enlarge_map(&settings, h_field);
1284
1285 script_api::new_world();
1286
1287 DBG_DEBUG("karte_t::init()","distributing trees");
1288 if (!settings.get_no_trees()) {
1289 baum_t::distribute_trees(3);
1290 }
1291
1292 DBG_DEBUG("karte_t::init()","built timeline");
1293 private_car_t::build_timeline_list(this);
1294 pedestrian_t::build_timeline_list(this);
1295
1296 nosave_warning = nosave = false;
1297
1298 dbg->error("karte_t::init()", "Creating factories ...");
1299 factory_builder_t::new_world();
1300
1301 int consecutive_build_failures = 0;
1302
1303 loadingscreen_t ls( translator::translate("distributing factories"), 16 + settings.get_city_count() * 4 + settings.get_factory_count(), true, true );
1304
1305 while( fab_list.get_count() < (uint32)settings.get_factory_count() ) {
1306 if( !factory_builder_t::increase_industry_density( false ) ) {
1307 if( ++consecutive_build_failures > 3 ) {
1308 // Industry chain building starts failing consecutively as map approaches full.
1309 break;
1310 }
1311 }
1312 else {
1313 consecutive_build_failures = 0;
1314 }
1315 ls.set_progress( 16 + settings.get_city_count() * 4 + min(fab_list.get_count(),settings.get_factory_count()) );
1316 }
1317
1318 settings.set_factory_count( fab_list.get_count() );
1319 finance_history_year[0][WORLD_FACTORIES] = finance_history_month[0][WORLD_FACTORIES] = fab_list.get_count();
1320
1321 // tourist attractions
1322 factory_builder_t::distribute_attractions(settings.get_tourist_attractions());
1323
1324 dbg->message("karte_t::init()", "Preparing startup ...");
1325 if(zeiger == 0) {
1326 zeiger = new zeiger_t(koord3d::invalid, NULL );
1327 }
1328
1329 // finishes the line preparation and sets id 0 to invalid ...
1330 players[0]->simlinemgmt.finish_rd();
1331
1332 set_tool( tool_t::general_tool[TOOL_QUERY], get_active_player() );
1333
1334 recalc_average_speed();
1335
1336 for (int i = 0; i < MAX_PLAYER_COUNT; i++) {
1337 if( players[i] ) {
1338 players[i]->set_active(settings.player_active[i]);
1339 }
1340 }
1341
1342 active_player_nr = 0;
1343 active_player = players[0];
1344 tool_t::update_toolbars();
1345
1346 set_dirty();
1347 step_mode = PAUSE_FLAG;
1348 simloops = 60;
1349 reset_timer();
1350
1351 if(is_display_init()) {
1352 display_show_pointer(true);
1353 }
1354 mute_sound(false);
1355 }
1356
1357
1358 #define array_koord(px,py) (px + py * get_size().x)
1359
1360
1361 /* Lakes:
1362 * For each height from groundwater+1 to max_lake_height we loop over
1363 * all tiles in the map trying to increase water height to this value
1364 * To start with every tile in the map is checked - but when we fail for
1365 * a tile then it is excluded from subsequent checks
1366 */
create_lakes(int xoff,int yoff)1367 void karte_t::create_lakes( int xoff, int yoff )
1368 {
1369 if( xoff > 0 || yoff > 0 ) {
1370 // too complicated to add lakes to an already existing world...
1371 return;
1372 }
1373
1374 const sint8 max_lake_height = groundwater + 8;
1375 const uint16 size_x = get_size().x;
1376 const uint16 size_y = get_size().y;
1377
1378 sint8 *max_water_hgt = new sint8[size_x * size_y];
1379 memset( max_water_hgt, 1, sizeof(sint8) * size_x * size_y );
1380
1381 sint8 *stage = new sint8[size_x * size_y];
1382 sint8 *new_stage = new sint8[size_x * size_y];
1383 sint8 *local_stage = new sint8[size_x * size_y];
1384
1385 for( sint8 h = groundwater+1; h<max_lake_height; h++ ) {
1386 bool need_to_flood = false;
1387 memset( stage, -1, sizeof(sint8) * size_x * size_y );
1388 for( uint16 y = 1; y < size_y-1; y++ ) {
1389 for( uint16 x = 1; x < size_x-1; x++ ) {
1390 uint32 offset = array_koord(x,y);
1391 if( max_water_hgt[offset]==1 && stage[offset]==-1 ) {
1392
1393 sint8 hgt = lookup_hgt_nocheck( x, y );
1394 const sint8 water_hgt = water_hgts[offset]; // optimised <- get_water_hgt_nocheck(x, y);
1395 const sint8 new_water_hgt = max(hgt, water_hgt);
1396 if( new_water_hgt>max_lake_height ) {
1397 max_water_hgt[offset] = 0;
1398 }
1399 else if( h>new_water_hgt ) {
1400 koord k(x,y);
1401 memcpy( new_stage, stage, sizeof(sint8) * size_x * size_y );
1402 if(can_flood_to_depth( k, h, new_stage, local_stage )) {
1403 sint8 *tmp_stage = new_stage;
1404 new_stage = stage;
1405 stage = tmp_stage;
1406 need_to_flood = true;
1407 }
1408 else {
1409 for( uint16 iy = 1; iy<size_y - 1; iy++ ) {
1410 uint32 offset_end = array_koord(size_x - 1,iy);
1411 for( uint32 local_offset = array_koord(0,iy); local_offset<offset_end; local_offset++ ) {
1412 if( local_stage[local_offset] > -1 ) {
1413 max_water_hgt[local_offset] = 0;
1414 }
1415 }
1416 }
1417 }
1418 }
1419 }
1420 }
1421 }
1422 if(need_to_flood) {
1423 flood_to_depth( h, stage );
1424 }
1425 else {
1426 break;
1427 }
1428 }
1429
1430 delete [] max_water_hgt;
1431 delete [] stage;
1432 delete [] new_stage;
1433 delete [] local_stage;
1434
1435 for (planquadrat_t *pl = plan; pl < (plan + size_x * size_y); pl++) {
1436 pl->correct_water();
1437 }
1438 }
1439
1440
can_flood_to_depth(koord k,sint8 new_water_height,sint8 * stage,sint8 * our_stage) const1441 bool karte_t::can_flood_to_depth( koord k, sint8 new_water_height, sint8 *stage, sint8 *our_stage ) const
1442 {
1443 bool succeeded = true;
1444 if( k == koord::invalid ) {
1445 return false;
1446 }
1447
1448 if( new_water_height < get_groundwater() - 3 ) {
1449 return false;
1450 }
1451
1452 // make a list of tiles to change
1453 // cannot use a recursive method as stack is not large enough!
1454
1455 sint8 *from_dir = new sint8[get_size().x * get_size().y];
1456 bool local_stage = (our_stage==NULL);
1457
1458 if( local_stage ) {
1459 our_stage = new sint8[get_size().x * get_size().y];
1460 }
1461
1462 memset( from_dir, -1, sizeof(sint8) * get_size().x * get_size().y );
1463 memset( our_stage, -1, sizeof(sint8) * get_size().x * get_size().y );
1464 uint32 offset = array_koord(k.x,k.y);
1465 stage[offset]=0;
1466 our_stage[offset]=0;
1467 do {
1468 for( int i = our_stage[offset]; i < 8; i++ ) {
1469 koord k_neighbour = k + koord::neighbours[i];
1470 if( is_within_limits(k_neighbour) ) {
1471 const uint32 neighbour_offset = array_koord(k_neighbour.x,k_neighbour.y);
1472
1473 // already visited
1474 if(our_stage[neighbour_offset] != -1) goto next_neighbour;
1475
1476 // water height above
1477 if(water_hgts[neighbour_offset] >= new_water_height) goto next_neighbour;
1478
1479 grund_t *gr2 = lookup_kartenboden_nocheck(k_neighbour);
1480 if( !gr2 ) goto next_neighbour;
1481
1482 sint8 neighbour_height = gr2->get_hoehe();
1483
1484 // land height above
1485 if(neighbour_height >= new_water_height) goto next_neighbour;
1486
1487 //move on to next tile
1488 from_dir[neighbour_offset] = i;
1489 stage[neighbour_offset] = 0;
1490 our_stage[neighbour_offset] = 0;
1491 our_stage[offset] = i;
1492 k = k_neighbour;
1493 offset = array_koord(k.x,k.y);
1494 break;
1495 }
1496 else {
1497 // edge of map - we keep iterating so we can mark all connected tiles as failing
1498 succeeded = false;
1499 }
1500 next_neighbour:
1501 //return back to previous tile
1502 if( i==7 ) {
1503 k = k - koord::neighbours[from_dir[offset]];
1504 }
1505 }
1506 offset = array_koord(k.x,k.y);
1507 } while( from_dir[offset] != -1 );
1508
1509 delete [] from_dir;
1510
1511 if( local_stage ) {
1512 delete [] our_stage;
1513 }
1514
1515 return succeeded;
1516 }
1517
1518
flood_to_depth(sint8 new_water_height,sint8 * stage)1519 void karte_t::flood_to_depth( sint8 new_water_height, sint8 *stage )
1520 {
1521 const uint16 size_x = get_size().x;
1522 const uint16 size_y = get_size().y;
1523
1524 uint32 offset_max = size_x*size_y;
1525 for( uint32 offset = 0; offset < offset_max; offset++ ) {
1526 if( stage[offset] == -1 ) {
1527 continue;
1528 }
1529 water_hgts[offset] = new_water_height;
1530 }
1531 }
1532
1533
create_beaches(int xoff,int yoff)1534 void karte_t::create_beaches( int xoff, int yoff )
1535 {
1536 const uint16 size_x = get_size().x;
1537 const uint16 size_y = get_size().y;
1538
1539 // bays have wide beaches
1540 for( uint16 iy = 0; iy < size_y; iy++ ) {
1541 for( uint16 ix = (iy >= yoff - 19) ? 0 : max( xoff - 19, 0 ); ix < size_x; ix++ ) {
1542 grund_t *gr = lookup_kartenboden_nocheck(ix,iy);
1543 if( gr->is_water() && gr->get_hoehe()==groundwater && gr->kann_alle_obj_entfernen(NULL)==NULL) {
1544 koord k( ix, iy );
1545 uint8 neighbour_water = 0;
1546 bool water[8];
1547 // check whether nearby tiles are water
1548 for( int i = 0; i < 8; i++ ) {
1549 grund_t *gr2 = lookup_kartenboden( k + koord::neighbours[i] );
1550 water[i] = (!gr2 || gr2->is_water());
1551 }
1552
1553 // make a count of nearby tiles - where tiles on opposite (+-1 direction) sides are water these count much more so we don't block straits
1554 for( int i = 0; i < 8; i++ ) {
1555 if( water[i] ) {
1556 neighbour_water++;
1557 if( water[(i + 3) & 7] || water[(i + 4) & 7] || water[(i + 5) & 7] ) {
1558 neighbour_water++;
1559 }
1560 }
1561 }
1562
1563 // if not much nearby water then turn into a beach
1564 if( neighbour_water < 4 ) {
1565 set_water_hgt( k, gr->get_hoehe() - 1 );
1566 raise_grid_to( ix, iy, gr->get_hoehe() );
1567 raise_grid_to( ix + 1, iy, gr->get_hoehe() );
1568 raise_grid_to( ix, iy + 1, gr->get_hoehe() );
1569 raise_grid_to( ix + 1, iy + 1 , gr->get_hoehe() );
1570 access_nocheck(k)->correct_water();
1571 access_nocheck(k)->set_climate( desert_climate );
1572 }
1573 }
1574 }
1575 }
1576
1577 // headlands should not have beaches at all
1578 for( uint16 iy = 0; iy < size_y; iy++ ) {
1579 for( uint16 ix = (iy >= yoff - 19) ? 0 : max( xoff - 19, 0 ); ix < size_x; ix++ ) {
1580 koord k( ix, iy );
1581 grund_t *gr = lookup_kartenboden_nocheck(k);
1582 if( !gr->is_water() && gr->get_pos().z == groundwater ) {
1583 uint8 neighbour_water = 0;
1584 for( int i = 0; i < 8; i++ ) {
1585 grund_t *gr2 = lookup_kartenboden( k + koord::neighbours[i] );
1586 if( !gr2 || gr2->is_water() ) {
1587 neighbour_water++;
1588 }
1589 }
1590 // if a lot of water nearby we are a headland
1591 if( neighbour_water > 3 ) {
1592 access_nocheck(k)->set_climate( get_climate_at_height( groundwater + 1 ) );
1593 }
1594 }
1595 }
1596 }
1597
1598 // remove any isolated 1 tile beaches
1599 for( uint16 iy = 0; iy < size_y; iy++ ) {
1600 for( uint16 ix = (iy >= yoff - 19) ? 0 : max( xoff - 19, 0 ); ix < size_x; ix++ ) {
1601 koord k( ix, iy );
1602 if( access_nocheck(k)->get_climate() == desert_climate ) {
1603 uint8 neighbour_beach = 0;
1604 //look up neighbouring climates
1605 climate neighbour_climate[8];
1606 for( int i = 0; i < 8; i++ ) {
1607 koord k_neighbour = k + koord::neighbours[i];
1608 if( !is_within_limits(k_neighbour) ) {
1609 k_neighbour = get_closest_coordinate(k_neighbour);
1610 }
1611 neighbour_climate[i] = get_climate( k_neighbour );
1612 }
1613
1614 // get transition climate - look for each corner in turn
1615 for( int i = 0; i < 4; i++ ) {
1616 climate transition_climate = (climate) max( max( neighbour_climate[(i * 2 + 1) & 7], neighbour_climate[(i * 2 + 3) & 7] ), neighbour_climate[(i * 2 + 2) & 7] );
1617 climate min_climate = (climate) min( min( neighbour_climate[(i * 2 + 1) & 7], neighbour_climate[(i * 2 + 3) & 7] ), neighbour_climate[(i * 2 + 2) & 7] );
1618 if( min_climate <= desert_climate && transition_climate == desert_climate ) {
1619 neighbour_beach++;
1620 }
1621 }
1622 if( neighbour_beach == 0 ) {
1623 access_nocheck(k)->set_climate( get_climate_at_height( groundwater + 1 ) );
1624 }
1625 }
1626 }
1627 }
1628 }
1629
1630
init_height_to_climate()1631 void karte_t::init_height_to_climate()
1632 {
1633 // create height table
1634 sint16 climate_border[MAX_CLIMATES];
1635 memcpy(climate_border, get_settings().get_climate_borders(), sizeof(climate_border));
1636 // set climate_border[0] to sea level
1637 climate_border[0] = groundwater;
1638
1639 for( int cl=0; cl<MAX_CLIMATES-1; cl++ ) {
1640 if(climate_border[cl]>climate_border[arctic_climate]) {
1641 // unused climate
1642 climate_border[cl] = groundwater-1;
1643 }
1644 }
1645
1646 // now arrange the remaining ones
1647 for( uint h=0; h<lengthof(height_to_climate); h++ ) {
1648 sint16 current_height = 999; // current maximum
1649 sint16 current_cl = arctic_climate; // and the climate
1650 for( int cl=0; cl<MAX_CLIMATES; cl++ ) {
1651 if( climate_border[cl] >= (sint16)h + groundwater && climate_border[cl] < current_height ) {
1652 current_height = climate_border[cl];
1653 current_cl = cl;
1654 }
1655 }
1656 height_to_climate[h] = (uint8)current_cl;
1657 }
1658 }
1659
1660
enlarge_map(settings_t const * sets,sint8 const * const h_field)1661 void karte_t::enlarge_map(settings_t const* sets, sint8 const* const h_field)
1662 {
1663 sint16 new_size_x = sets->get_size_x();
1664 sint16 new_size_y = sets->get_size_y();
1665
1666 if( cached_grid_size.y>0 && cached_grid_size.y!=new_size_y ) {
1667 // to keep the labels
1668 grund_t::enlarge_map( new_size_x, new_size_y );
1669 }
1670
1671 planquadrat_t *new_plan = new planquadrat_t[new_size_x*new_size_y];
1672 sint8 *new_grid_hgts = new sint8[(new_size_x + 1) * (new_size_y + 1)];
1673 sint8 *new_water_hgts = new sint8[new_size_x * new_size_y];
1674
1675 memset( new_grid_hgts, groundwater, sizeof(sint8) * (new_size_x + 1) * (new_size_y + 1) );
1676 memset( new_water_hgts, groundwater, sizeof(sint8) * new_size_x * new_size_y );
1677
1678 sint16 old_x = cached_grid_size.x;
1679 sint16 old_y = cached_grid_size.y;
1680
1681 settings.set_size_x(new_size_x);
1682 settings.set_size_y(new_size_y);
1683 cached_grid_size.x = new_size_x;
1684 cached_grid_size.y = new_size_y;
1685 cached_size_max = max(cached_grid_size.x,cached_grid_size.y);
1686 cached_size.x = cached_grid_size.x-1;
1687 cached_size.y = cached_grid_size.y-1;
1688
1689 intr_disable();
1690
1691 const bool minimap_was_visible = minimap_t::is_visible;
1692
1693 int max_display_progress;
1694
1695 // If this is not called by karte_t::init
1696 if( old_x != 0 ) {
1697 mute_sound(true);
1698 minimap_t::is_visible = false;
1699
1700 if(is_display_init()) {
1701 display_show_pointer(false);
1702 }
1703
1704 // Copy old values:
1705 for (sint16 iy = 0; iy<old_y; iy++) {
1706 for (sint16 ix = 0; ix<old_x; ix++) {
1707 uint32 nr = ix+(iy*old_x);
1708 uint32 nnr = ix+(iy*new_size_x);
1709 swap(new_plan[nnr], plan[nr]);
1710 new_water_hgts[nnr] = water_hgts[nr];
1711 }
1712 }
1713 for (sint16 iy = 0; iy<=old_y; iy++) {
1714 for (sint16 ix = 0; ix<=old_x; ix++) {
1715 uint32 nr = ix+(iy*(old_x+1));
1716 uint32 nnr = ix+(iy*(new_size_x+1));
1717 new_grid_hgts[nnr] = grid_hgts[nr];
1718 }
1719 }
1720 max_display_progress = 16 + sets->get_city_count()*2 + stadt.get_count()*4;
1721 }
1722 else {
1723 max_display_progress = 16 + sets->get_city_count() * 4 + settings.get_factory_count();
1724 }
1725 loadingscreen_t ls( translator::translate( old_x ? "enlarge map" : "Init map ..."), max_display_progress, true, true );
1726
1727 delete [] plan;
1728 plan = new_plan;
1729 delete [] grid_hgts;
1730 grid_hgts = new_grid_hgts;
1731 delete [] water_hgts;
1732 water_hgts = new_water_hgts;
1733
1734 if( old_x==0 ) {
1735 // init max and min with defaults
1736 max_height = groundwater;
1737 min_height = groundwater;
1738 }
1739
1740 setsimrand(0xFFFFFFFF, settings.get_map_number());
1741 clear_random_mode( 0xFFFF );
1742 set_random_mode( MAP_CREATE_RANDOM );
1743
1744 if( old_x == 0 && !settings.heightfield.empty() ) {
1745 // init from file
1746 for(int y=0; y<cached_grid_size.y; y++) {
1747 for(int x=0; x<cached_grid_size.x; x++) {
1748 grid_hgts[x + y*(cached_grid_size.x+1)] = h_field[x+(y*(sint32)cached_grid_size.x)]+1;
1749 }
1750 grid_hgts[cached_grid_size.x + y*(cached_grid_size.x+1)] = grid_hgts[cached_grid_size.x-1 + y*(cached_grid_size.x+1)];
1751 }
1752 // lower border
1753 memcpy( grid_hgts+(cached_grid_size.x+1)*(sint32)cached_grid_size.y, grid_hgts+(cached_grid_size.x+1)*(sint32)(cached_grid_size.y-1), cached_grid_size.x+1 );
1754 ls.set_progress(2);
1755 }
1756 else {
1757 if( sets->get_rotation()==0 && sets->get_origin_x()==0 && sets->get_origin_y()==0) {
1758 // otherwise negative offsets may occur, so we cache only non-rotated maps
1759 init_perlin_map(new_size_x,new_size_y);
1760 }
1761 if ( old_x > 0 && old_y > 0 ) {
1762 // loop only new tiles:
1763 for( sint16 y = 0; y<=new_size_y; y++ ) {
1764 for( sint16 x = (y>old_y) ? 0 : old_x+1; x<=new_size_x; x++ ) {
1765 koord k(x,y);
1766 sint16 const h = perlin_hoehe(&settings, k, koord(old_x, old_y));
1767 set_grid_hgt( k, (sint8) h);
1768 }
1769 ls.set_progress( (y*16)/new_size_y );
1770 }
1771 }
1772 else {
1773 world_xy_loop(&karte_t::perlin_hoehe_loop, GRIDS_FLAG);
1774 ls.set_progress(2);
1775 }
1776 exit_perlin_map();
1777 }
1778
1779 /** @note First we'll copy the border heights to the adjacent tile.
1780 * The best way I could find is raising the first new grid point to
1781 * the same height the adjacent old grid point was and lowering to the
1782 * same height again. This doesn't preserve the old area 100%, but it respects it
1783 * somehow.
1784 *
1785 * This does not work for water tiles as for them get_hoehe will return the
1786 * z-coordinate of the water surface, not the height of the underwater
1787 * landscape.
1788 */
1789
1790 sint32 i;
1791 grund_t *gr;
1792 sint8 h;
1793
1794 if ( old_x > 0 && old_y > 0){
1795 for(i=0; i<old_x; i++) {
1796 gr = lookup_kartenboden_nocheck(i, old_y-1);
1797 if (!gr->is_water()) {
1798 h = gr->get_hoehe(slope4_t::corner_SW);
1799 raise_grid_to(i, old_y+1, h);
1800 lower_grid_to(i, old_y+1, h );
1801 }
1802 }
1803 for(i=0; i<old_y; i++) {
1804 gr = lookup_kartenboden_nocheck(old_x-1, i);
1805 if (!gr->is_water()) {
1806 h = gr->get_hoehe(slope4_t::corner_NE);
1807 raise_grid_to(old_x+1, i, h);
1808 lower_grid_to(old_x+1, i, h);
1809 }
1810 }
1811 gr = lookup_kartenboden_nocheck(old_x-1, old_y -1);
1812 if (!gr->is_water()) {
1813 h = gr->get_hoehe(slope4_t::corner_SE);
1814 raise_grid_to(old_x+1, old_y+1, h);
1815 lower_grid_to(old_x+1, old_y+1, h);
1816 }
1817 }
1818
1819 if ( old_x > 0 && old_y > 0 ) {
1820 // create grounds on new part
1821 for (sint16 iy = 0; iy<new_size_y; iy++) {
1822 for (sint16 ix = (iy>=old_y)?0:old_x; ix<new_size_x; ix++) {
1823 koord k(ix,iy);
1824 access_nocheck(k)->kartenboden_setzen( new boden_t( koord3d( ix, iy, max( min_hgt_nocheck(k), get_water_hgt_nocheck(k) ) ), 0 ) );
1825 }
1826 }
1827 }
1828 else {
1829 world_xy_loop(&karte_t::create_grounds_loop, 0);
1830 ls.set_progress(10);
1831 }
1832
1833 // update height bounds
1834 for( sint16 iy = 0; iy < new_size_y; iy++ ) {
1835 for( sint16 ix = (iy >= old_y) ? 0 : max( old_x, 0 ); ix < new_size_x; ix++ ) {
1836 sint8 hgt = lookup_kartenboden_nocheck(ix, iy)->get_hoehe();
1837 if (hgt < min_height) {
1838 min_height = hgt;
1839 }
1840 if (hgt > max_height) {
1841 max_height = hgt;
1842 }
1843 }
1844 }
1845
1846 if ( old_x == 0 && old_y == 0 ) {
1847 ls.set_progress(11);
1848 }
1849
1850 // smooth the new part, reassign slopes on new part
1851 cleanup_karte( old_x, old_y );
1852 if ( old_x == 0 && old_y == 0 ) {
1853 ls.set_progress(12);
1854 }
1855
1856 if( sets->get_lake() ) {
1857 create_lakes( old_x, old_y );
1858 }
1859
1860 if ( old_x == 0 && old_y == 0 ) {
1861 ls.set_progress(13);
1862 }
1863
1864 // set climates in new area and old map near seam
1865 for( sint16 iy = 0; iy < new_size_y; iy++ ) {
1866 for( sint16 ix = (iy >= old_y - 19) ? 0 : max( old_x - 19, 0 ); ix < new_size_x; ix++ ) {
1867 calc_climate( koord( ix, iy ), false );
1868 }
1869 }
1870 if ( old_x == 0 && old_y == 0 ) {
1871 ls.set_progress(14);
1872 }
1873
1874 create_beaches( old_x, old_y );
1875 if ( old_x == 0 && old_y == 0 ) {
1876 ls.set_progress(15);
1877 }
1878
1879 if ( old_x > 0 && old_y > 0 ) {
1880 // and calculate transitions in a 1 tile larger area
1881 for( sint16 iy = 0; iy < new_size_y; iy++ ) {
1882 for( sint16 ix = (iy >= old_y - 20) ? 0 : max( old_x - 20, 0 ); ix < new_size_x; ix++ ) {
1883 recalc_transitions( koord( ix, iy ) );
1884 }
1885 }
1886 }
1887 else {
1888 // new world -> calculate all transitions
1889 world_xy_loop(&karte_t::recalc_transitions_loop, 0);
1890 ls.set_progress(16);
1891 }
1892
1893 // now recalc the images of the old map near the seam ...
1894 for( sint16 y = 0; y < old_y - 20; y++ ) {
1895 for( sint16 x = max( old_x - 20, 0 ); x < old_x; x++ ) {
1896 lookup_kartenboden_nocheck(x,y)->calc_image();
1897 }
1898 }
1899 for( sint16 y = max( old_y - 20, 0 ); y < old_y; y++) {
1900 for( sint16 x = 0; x < old_x; x++ ) {
1901 lookup_kartenboden_nocheck(x,y)->calc_image();
1902 }
1903 }
1904
1905 // eventual update origin
1906 switch( settings.get_rotation() ) {
1907 case 1: {
1908 settings.set_origin_y( settings.get_origin_y() - new_size_y + old_y );
1909 break;
1910 }
1911 case 2: {
1912 settings.set_origin_x( settings.get_origin_x() - new_size_x + old_x );
1913 settings.set_origin_y( settings.get_origin_y() - new_size_y + old_y );
1914 break;
1915 }
1916 case 3: {
1917 settings.set_origin_x( settings.get_origin_x() - new_size_y + old_y );
1918 break;
1919 }
1920 }
1921
1922 distribute_groundobjs_cities( sets->get_city_count(), sets->get_mean_citizen_count(), old_x, old_y );
1923
1924 // hausbauer_t::new_world(); <- this would reinit monuments! do not do this!
1925 factory_builder_t::new_world();
1926 set_schedule_counter();
1927
1928 // Refresh the haltlist for the affected tiles / stations.
1929 // It is enough to check the tile just at the border ...
1930 uint16 const cov = settings.get_station_coverage();
1931 if( old_y < new_size_y ) {
1932 for( sint16 y=0; y<old_y; y++ ) {
1933 for( sint16 x=max(0,old_x-cov); x<old_x; x++ ) {
1934 const planquadrat_t* pl = access_nocheck(x,y);
1935 for( uint8 i=0; i < pl->get_boden_count(); i++ ) {
1936 // update halt
1937 halthandle_t h = pl->get_boden_bei(i)->get_halt();
1938 if( h.is_bound() ) {
1939 for( sint16 xp=max(0,x-cov); xp<min(new_size_x,x+cov+1); xp++ ) {
1940 for( sint16 yp=y; yp<min(new_size_y,y+cov+1); yp++ ) {
1941 access_nocheck(xp,yp)->add_to_haltlist(h);
1942 }
1943 }
1944 }
1945 }
1946 }
1947 }
1948 }
1949 if( old_x < new_size_x ) {
1950 for( sint16 y=max(0,old_y-cov); y<old_y; y++ ) {
1951 for( sint16 x=0; x<old_x; x++ ) {
1952 const planquadrat_t* pl = access_nocheck(x,y);
1953 for( uint8 i=0; i < pl->get_boden_count(); i++ ) {
1954 // update halt
1955 halthandle_t h = pl->get_boden_bei(i)->get_halt();
1956 if( h.is_bound() ) {
1957 for( sint16 xp=x; xp<min(new_size_x,x+cov+1); xp++ ) {
1958 for( sint16 yp=max(0,y-cov); yp<min(new_size_y,y+cov+1); yp++ ) {
1959 access_nocheck(xp,yp)->add_to_haltlist(h);
1960 }
1961 }
1962 }
1963 }
1964 }
1965 }
1966 }
1967 clear_random_mode( MAP_CREATE_RANDOM );
1968
1969 if ( old_x != 0 ) {
1970 if(is_display_init()) {
1971 display_show_pointer(true);
1972 }
1973 mute_sound(false);
1974
1975 minimap_t::is_visible = minimap_was_visible;
1976 minimap_t::get_instance()->init();
1977 minimap_t::get_instance()->calc_map();
1978 minimap_t::get_instance()->set_display_mode( minimap_t::get_instance()->get_display_mode() );
1979
1980 set_dirty();
1981 reset_timer();
1982 }
1983 // update main menu
1984 tool_t::update_toolbars();
1985 }
1986
1987
1988
karte_t()1989 karte_t::karte_t() :
1990 settings(env_t::default_settings),
1991 convoi_array(0),
1992 attractions(16),
1993 stadt(0)
1994 {
1995 destroying = false;
1996
1997 // length of day and other time stuff
1998 ticks_per_world_month_shift = 20;
1999 ticks_per_world_month = (1 << ticks_per_world_month_shift);
2000 last_step_ticks = 0;
2001 server_last_announce_time = 0;
2002 last_interaction = dr_time();
2003 step_mode = PAUSE_FLAG;
2004 time_multiplier = 16;
2005 next_midi_time = next_step_time = last_step_time = 0;
2006 fix_ratio_frame_time = 200;
2007 idle_time = 0;
2008 network_frame_count = 0;
2009 sync_steps = 0;
2010 sync_steps_barrier = sync_steps;
2011
2012 for( uint i=0; i<MAX_PLAYER_COUNT; i++ ) {
2013 selected_tool[i] = tool_t::general_tool[TOOL_QUERY];
2014 }
2015
2016 viewport = new viewport_t(this);
2017
2018 set_dirty();
2019
2020 // for new world just set load version to current savegame version
2021 load_version = loadsave_t::int_version( env_t::savegame_version_str, NULL );
2022
2023 // standard prices
2024 goods_manager_t::set_multiplier( 1000 );
2025
2026 zeiger = 0;
2027 plan = 0;
2028
2029 grid_hgts = 0;
2030 water_hgts = 0;
2031 schedule_counter = 0;
2032 nosave_warning = nosave = false;
2033 loaded_rotation = 0;
2034 last_year = 1930;
2035 last_month = 0;
2036
2037 for(int i=0; i<MAX_PLAYER_COUNT ; i++) {
2038 players[i] = NULL;
2039 MEMZERO(player_password_hash[i]);
2040 }
2041
2042 // no distance to show at first ...
2043 show_distance = koord3d::invalid;
2044 scenario = NULL;
2045
2046 map_counter = 0;
2047
2048 msg = new message_t();
2049 cached_size.x = 0;
2050 cached_size.y = 0;
2051
2052 records = new records_t(this->msg);
2053
2054 // generate ground textures once
2055 ground_desc_t::init_ground_textures(this);
2056
2057 // set single instance
2058 world = this;
2059 }
2060
2061
~karte_t()2062 karte_t::~karte_t()
2063 {
2064 is_sound = false;
2065
2066 destroy();
2067
2068 // not deleting the tools of this map ...
2069 delete viewport;
2070 delete msg;
2071 delete records;
2072
2073 // unset single instance
2074 if (world == this) {
2075 world = NULL;
2076 }
2077 }
2078
can_lower_plan_to(const player_t * player,sint16 x,sint16 y,sint8 h) const2079 const char* karte_t::can_lower_plan_to(const player_t *player, sint16 x, sint16 y, sint8 h) const
2080 {
2081 const planquadrat_t *plan = access(x,y);
2082
2083 if( plan==NULL ) {
2084 return "";
2085 }
2086
2087 if( h < groundwater - 3 ) {
2088 return "";
2089 }
2090
2091 const sint8 hmax = plan->get_kartenboden()->get_hoehe();
2092 if( (hmax == h || hmax == h - 1) && (plan->get_kartenboden()->get_grund_hang() == 0 || is_plan_height_changeable( x, y )) ) {
2093 return NULL;
2094 }
2095
2096 if( !is_plan_height_changeable(x, y) ) {
2097 return "";
2098 }
2099
2100 // tunnel slope below?
2101 grund_t *gr = plan->get_boden_in_hoehe( h - 1 );
2102 if( !gr ) {
2103 gr = plan->get_boden_in_hoehe( h - 2 );
2104 }
2105 if( !gr && settings.get_way_height_clearance()==2 ) {
2106 gr = plan->get_boden_in_hoehe( h - 3 );
2107 }
2108 if( gr && h < gr->get_pos().z + slope_t::max_diff( gr->get_weg_hang() ) + settings.get_way_height_clearance() ) {
2109 return "";
2110 }
2111
2112 // tunnel below?
2113 while(h < hmax) {
2114 if(plan->get_boden_in_hoehe(h)) {
2115 return "";
2116 }
2117 h ++;
2118 }
2119
2120 // check allowance by scenario
2121 if (get_scenario()->is_scripted()) {
2122 return get_scenario()->is_work_allowed_here(player, TOOL_LOWER_LAND|GENERAL_TOOL, ignore_wt, plan->get_kartenboden()->get_pos());
2123 }
2124
2125 return NULL;
2126 }
2127
2128
can_raise_plan_to(const player_t * player,sint16 x,sint16 y,sint8 h) const2129 const char* karte_t::can_raise_plan_to(const player_t *player, sint16 x, sint16 y, sint8 h) const
2130 {
2131 const planquadrat_t *plan = access(x,y);
2132 if( plan == 0 || !is_plan_height_changeable(x, y) ) {
2133 return "";
2134 }
2135
2136 // irgendwo eine Bruecke im Weg?
2137 int hmin = plan->get_kartenboden()->get_hoehe();
2138 while(h > hmin) {
2139 if(plan->get_boden_in_hoehe(h)) {
2140 return "";
2141 }
2142 h --;
2143 }
2144
2145 // check allowance by scenario
2146 if (get_scenario()->is_scripted()) {
2147 return get_scenario()->is_work_allowed_here(player, TOOL_RAISE_LAND|GENERAL_TOOL, ignore_wt, plan->get_kartenboden()->get_pos());
2148 }
2149
2150 return NULL;
2151 }
2152
2153
is_plan_height_changeable(sint16 x,sint16 y) const2154 bool karte_t::is_plan_height_changeable(sint16 x, sint16 y) const
2155 {
2156 const planquadrat_t *plan = access(x,y);
2157 bool ok = true;
2158
2159 if(plan != NULL) {
2160 grund_t *gr = plan->get_kartenboden();
2161
2162 ok = (gr->ist_natur() || gr->is_water()) && !gr->hat_wege() && !gr->is_halt();
2163
2164 for( int i=0; ok && i<gr->get_top(); i++ ) {
2165 const obj_t *obj = gr->obj_bei(i);
2166 assert(obj != NULL);
2167 ok =
2168 obj->get_typ() == obj_t::baum ||
2169 obj->get_typ() == obj_t::zeiger ||
2170 obj->get_typ() == obj_t::wolke ||
2171 obj->get_typ() == obj_t::sync_wolke ||
2172 obj->get_typ() == obj_t::async_wolke ||
2173 obj->get_typ() == obj_t::groundobj;
2174 }
2175 }
2176
2177 return ok;
2178 }
2179
2180
comp(const karte_t::terraformer_t::node_t & a,const karte_t::terraformer_t::node_t & b)2181 bool karte_t::terraformer_t::node_t::comp(const karte_t::terraformer_t::node_t& a, const karte_t::terraformer_t::node_t& b)
2182 {
2183 int diff = a.x- b.x;
2184 if (diff == 0) {
2185 diff = a.y - b.y;
2186 }
2187 return diff<0;
2188 }
2189
2190
add_node(bool raise,sint16 x,sint16 y,sint8 hsw,sint8 hse,sint8 hne,sint8 hnw)2191 void karte_t::terraformer_t::add_node(bool raise, sint16 x, sint16 y, sint8 hsw, sint8 hse, sint8 hne, sint8 hnw)
2192 {
2193 if (!welt->is_within_limits(x,y)) {
2194 return;
2195 }
2196 node_t test(x, y, hsw, hse, hne, hnw, actual_flag^3);
2197 node_t *other = list.insert_unique_ordered(test, node_t::comp);
2198
2199 sint8 factor = raise ? +1 : -1;
2200
2201 if (other) {
2202 for(int i=0; i<4; i++) {
2203 if (factor*other->h[i] < factor*test.h[i]) {
2204 other->h[i] = test.h[i];
2205 other->changed |= actual_flag^3;
2206 ready = false;
2207 }
2208 }
2209 }
2210 else {
2211 ready = false;
2212 }
2213 }
2214
add_raise_node(sint16 x,sint16 y,sint8 hsw,sint8 hse,sint8 hne,sint8 hnw)2215 void karte_t::terraformer_t::add_raise_node(sint16 x, sint16 y, sint8 hsw, sint8 hse, sint8 hne, sint8 hnw)
2216 {
2217 add_node(true, x, y, hsw, hse, hne, hnw);
2218 }
2219
add_lower_node(sint16 x,sint16 y,sint8 hsw,sint8 hse,sint8 hne,sint8 hnw)2220 void karte_t::terraformer_t::add_lower_node(sint16 x, sint16 y, sint8 hsw, sint8 hse, sint8 hne, sint8 hnw)
2221 {
2222 add_node(false, x, y, hsw, hse, hne, hnw);
2223 }
2224
iterate(bool raise)2225 void karte_t::terraformer_t::iterate(bool raise)
2226 {
2227 while( !ready) {
2228 actual_flag ^= 3; // flip bits
2229 // clear new_flag bit
2230 FOR(vector_tpl<node_t>, &i, list) {
2231 i.changed &= actual_flag;
2232 }
2233 // process nodes with actual_flag set
2234 ready = true;
2235 for(uint32 j=0; j < list.get_count(); j++) {
2236 node_t& i = list[j];
2237 if (i.changed & actual_flag) {
2238 i.changed &= ~ actual_flag;
2239 if (raise) {
2240 welt->prepare_raise(*this, i.x, i.y, i.h[0], i.h[1], i.h[2], i.h[3]);
2241 }
2242 else {
2243 welt->prepare_lower(*this, i.x, i.y, i.h[0], i.h[1], i.h[2], i.h[3]);
2244 }
2245 }
2246 }
2247 }
2248 }
2249
2250
can_raise_all(const player_t * player,bool keep_water) const2251 const char* karte_t::terraformer_t::can_raise_all(const player_t *player, bool keep_water) const
2252 {
2253 const char* err = NULL;
2254 FOR(vector_tpl<node_t>, const &i, list) {
2255 err = welt->can_raise_to(player, i.x, i.y, keep_water, i.h[0], i.h[1], i.h[2], i.h[3]);
2256 if (err) return err;
2257 }
2258 return NULL;
2259 }
2260
can_lower_all(const player_t * player) const2261 const char* karte_t::terraformer_t::can_lower_all(const player_t *player) const
2262 {
2263 const char* err = NULL;
2264 FOR(vector_tpl<node_t>, const &i, list) {
2265 err = welt->can_lower_to(player, i.x, i.y, i.h[0], i.h[1], i.h[2], i.h[3]);
2266 if (err) {
2267 return err;
2268 }
2269 }
2270 return NULL;
2271 }
2272
raise_all()2273 int karte_t::terraformer_t::raise_all()
2274 {
2275 int n=0;
2276 FOR(vector_tpl<node_t>, &i, list) {
2277 n += welt->raise_to(i.x, i.y, i.h[0], i.h[1], i.h[2], i.h[3]);
2278 }
2279 return n;
2280 }
2281
lower_all()2282 int karte_t::terraformer_t::lower_all()
2283 {
2284 int n=0;
2285 FOR(vector_tpl<node_t>, &i, list) {
2286 n += welt->lower_to(i.x, i.y, i.h[0], i.h[1], i.h[2], i.h[3]);
2287 }
2288 return n;
2289 }
2290
2291
can_raise_to(const player_t * player,sint16 x,sint16 y,bool keep_water,sint8 hsw,sint8 hse,sint8 hne,sint8 hnw) const2292 const char* karte_t::can_raise_to(const player_t *player, sint16 x, sint16 y, bool keep_water, sint8 hsw, sint8 hse, sint8 hne, sint8 hnw) const
2293 {
2294 assert(is_within_limits(x,y));
2295 grund_t *gr = lookup_kartenboden_nocheck(x,y);
2296 const sint8 water_hgt = get_water_hgt_nocheck(x,y);
2297
2298 const sint8 max_hgt = max(max(hsw,hse),max(hne,hnw));
2299
2300 if( gr->is_water() && keep_water && max_hgt > water_hgt ) {
2301 return "";
2302 }
2303
2304 const char* err = can_raise_plan_to(player, x, y, max_hgt);
2305
2306 return err;
2307 }
2308
2309
prepare_raise(terraformer_t & digger,sint16 x,sint16 y,sint8 hsw,sint8 hse,sint8 hne,sint8 hnw)2310 void karte_t::prepare_raise(terraformer_t& digger, sint16 x, sint16 y, sint8 hsw, sint8 hse, sint8 hne, sint8 hnw)
2311 {
2312 assert(is_within_limits(x,y));
2313 grund_t *gr = lookup_kartenboden_nocheck(x,y);
2314 const sint8 water_hgt = get_water_hgt_nocheck(x,y);
2315 const sint8 h0 = gr->get_hoehe();
2316 // old height
2317 const sint8 h0_sw = gr->is_water() ? min(water_hgt, lookup_hgt_nocheck(x,y+1) ) : h0 + corner_sw( gr->get_grund_hang() );
2318 const sint8 h0_se = gr->is_water() ? min(water_hgt, lookup_hgt_nocheck(x+1,y+1) ) : h0 + corner_se( gr->get_grund_hang() );
2319 const sint8 h0_ne = gr->is_water() ? min(water_hgt, lookup_hgt_nocheck(x+1,y) ) : h0 + corner_ne( gr->get_grund_hang() );
2320 const sint8 h0_nw = gr->is_water() ? min(water_hgt, lookup_hgt_nocheck(x,y) ) : h0 + corner_nw( gr->get_grund_hang() );
2321
2322 // new height
2323 const sint8 hn_sw = max(hsw, h0_sw);
2324 const sint8 hn_se = max(hse, h0_se);
2325 const sint8 hn_ne = max(hne, h0_ne);
2326 const sint8 hn_nw = max(hnw, h0_nw);
2327
2328 // nothing to do?
2329 if( !gr->is_water() && h0_sw >= hsw && h0_se >= hse && h0_ne >= hne && h0_nw >= hnw ) {
2330 return;
2331 }
2332
2333 // calc new height and slope
2334 const sint8 hneu = min( min( hn_sw, hn_se ), min( hn_ne, hn_nw ) );
2335 const sint8 hmaxneu = max( max( hn_sw, hn_se ), max( hn_ne, hn_nw ) );
2336
2337 const uint8 max_hdiff = ground_desc_t::double_grounds ? 2 : 1;
2338
2339 bool ok = (hmaxneu - hneu <= max_hdiff); // may fail on water tiles since lookup_hgt might be modified from previous raise_to calls
2340 if( !ok && !gr->is_water() ) {
2341 assert(false);
2342 }
2343
2344 // sw
2345 if (h0_sw < hsw) {
2346 digger.add_raise_node( x - 1, y + 1, hsw - max_hdiff, hsw - max_hdiff, hsw, hsw - max_hdiff );
2347 }
2348 // s
2349 if (h0_sw < hsw || h0_se < hse) {
2350 const sint8 hs = max( hse, hsw ) - max_hdiff;
2351 digger.add_raise_node( x, y + 1, hs, hs, hse, hsw );
2352 }
2353 // se
2354 if (h0_se < hse) {
2355 digger.add_raise_node( x + 1, y + 1, hse - max_hdiff, hse - max_hdiff, hse - max_hdiff, hse );
2356 }
2357 // e
2358 if (h0_se < hse || h0_ne < hne) {
2359 const sint8 he = max( hse, hne ) - max_hdiff;
2360 digger.add_raise_node( x + 1, y, hse, he, he, hne );
2361 }
2362 // ne
2363 if (h0_ne < hne) {
2364 digger.add_raise_node( x + 1,y - 1, hne, hne - max_hdiff, hne - max_hdiff, hne - max_hdiff );
2365 }
2366 // n
2367 if (h0_nw < hnw || h0_ne < hne) {
2368 const sint8 hn = max( hnw, hne ) - max_hdiff;
2369 digger.add_raise_node( x, y - 1, hnw, hne, hn, hn );
2370 }
2371 // nw
2372 if (h0_nw < hnw) {
2373 digger.add_raise_node( x - 1, y - 1, hnw - max_hdiff, hnw, hnw - max_hdiff, hnw - max_hdiff );
2374 }
2375 // w
2376 if (h0_sw < hsw || h0_nw < hnw) {
2377 const sint8 hw = max( hnw, hsw ) - max_hdiff;
2378 digger.add_raise_node( x - 1, y, hw, hsw, hnw, hw );
2379 }
2380 }
2381
2382
raise_to(sint16 x,sint16 y,sint8 hsw,sint8 hse,sint8 hne,sint8 hnw)2383 int karte_t::raise_to(sint16 x, sint16 y, sint8 hsw, sint8 hse, sint8 hne, sint8 hnw)
2384 {
2385 int n=0;
2386 assert(is_within_limits(x,y));
2387 grund_t *gr = lookup_kartenboden_nocheck(x,y);
2388 const sint8 water_hgt = get_water_hgt_nocheck(x,y);
2389 const sint8 h0 = gr->get_hoehe();
2390
2391 // old height
2392 const sint8 h0_sw = gr->is_water() ? min(water_hgt, lookup_hgt_nocheck(x,y+1) ) : h0 + corner_sw( gr->get_grund_hang() );
2393 const sint8 h0_se = gr->is_water() ? min(water_hgt, lookup_hgt_nocheck(x+1,y+1) ) : h0 + corner_se( gr->get_grund_hang() );
2394 const sint8 h0_ne = gr->is_water() ? min(water_hgt, lookup_hgt_nocheck(x+1,y) ) : h0 + corner_ne( gr->get_grund_hang() );
2395 const sint8 h0_nw = gr->is_water() ? min(water_hgt, lookup_hgt_nocheck(x,y) ) : h0 + corner_nw( gr->get_grund_hang() );
2396
2397 // new height
2398 const sint8 hn_sw = max(hsw, h0_sw);
2399 const sint8 hn_se = max(hse, h0_se);
2400 const sint8 hn_ne = max(hne, h0_ne);
2401 const sint8 hn_nw = max(hnw, h0_nw);
2402 // nothing to do?
2403 if( !gr->is_water() && h0_sw >= hsw && h0_se >= hse && h0_ne >= hne && h0_nw >= hnw ) {
2404 return 0;
2405 }
2406
2407 // calc new height and slope
2408 const sint8 hneu = min( min( hn_sw, hn_se ), min( hn_ne, hn_nw ) );
2409 const sint8 hmaxneu = max( max( hn_sw, hn_se ), max( hn_ne, hn_nw ) );
2410
2411 const uint8 max_hdiff = ground_desc_t::double_grounds ? 2 : 1;
2412 const sint8 disp_hneu = max( hneu, water_hgt );
2413 const sint8 disp_hn_sw = max( hn_sw, water_hgt );
2414 const sint8 disp_hn_se = max( hn_se, water_hgt );
2415 const sint8 disp_hn_ne = max( hn_ne, water_hgt );
2416 const sint8 disp_hn_nw = max( hn_nw, water_hgt );
2417 const uint8 sneu = (disp_hn_sw - disp_hneu) + ((disp_hn_se - disp_hneu) * 3) + ((disp_hn_ne - disp_hneu) * 9) + ((disp_hn_nw - disp_hneu) * 27);
2418
2419 bool ok = (hmaxneu - hneu <= max_hdiff); // may fail on water tiles since lookup_hgt might be modified from previous raise_to calls
2420 if (!ok && !gr->is_water()) {
2421 assert(false);
2422 }
2423 // change height and slope, for water tiles only if they will become land
2424 if( !gr->is_water() || (hmaxneu > water_hgt || (hneu == water_hgt && hmaxneu == water_hgt) ) ) {
2425 gr->set_pos( koord3d( x, y, disp_hneu ) );
2426 gr->set_grund_hang( (slope_t::type)sneu );
2427 access_nocheck(x,y)->angehoben();
2428 set_water_hgt(x, y, groundwater-4);
2429 }
2430
2431 // update north point in grid
2432 set_grid_hgt(x, y, hn_nw);
2433 calc_climate(koord(x,y), true);
2434 if ( x == cached_size.x ) {
2435 // update eastern grid coordinates too if we are in the edge.
2436 set_grid_hgt(x+1, y, hn_ne);
2437 set_grid_hgt(x+1, y+1, hn_se);
2438 }
2439 if ( y == cached_size.y ) {
2440 // update southern grid coordinates too if we are in the edge.
2441 set_grid_hgt(x, y+1, hn_sw);
2442 set_grid_hgt(x+1, y+1, hn_se);
2443 }
2444
2445 n += hn_sw - h0_sw + hn_se - h0_se + hn_ne - h0_ne + hn_nw - h0_nw;
2446
2447 lookup_kartenboden_nocheck(x,y)->calc_image();
2448 if ( (x+1) < cached_size.x ) {
2449 lookup_kartenboden_nocheck(x+1,y)->calc_image();
2450 }
2451 if ( (y+1) < cached_size.y ) {
2452 lookup_kartenboden_nocheck(x,y+1)->calc_image();
2453 }
2454
2455 return n;
2456 }
2457
2458
2459 // raise height in the hgt-array
raise_grid_to(sint16 x,sint16 y,sint8 h)2460 void karte_t::raise_grid_to(sint16 x, sint16 y, sint8 h)
2461 {
2462 if(is_within_grid_limits(x,y)) {
2463 const sint32 offset = x + y*(cached_grid_size.x+1);
2464
2465 if( grid_hgts[offset] < h ) {
2466 grid_hgts[offset] = h;
2467
2468 const sint8 hh = h - (ground_desc_t::double_grounds ? 2 : 1);
2469
2470 // set new height of neighbor grid points
2471 raise_grid_to(x-1, y-1, hh);
2472 raise_grid_to(x , y-1, hh);
2473 raise_grid_to(x+1, y-1, hh);
2474 raise_grid_to(x-1, y , hh);
2475 raise_grid_to(x+1, y , hh);
2476 raise_grid_to(x-1, y+1, hh);
2477 raise_grid_to(x , y+1, hh);
2478 raise_grid_to(x+1, y+1, hh);
2479 }
2480 }
2481 }
2482
2483
grid_raise(const player_t * player,koord k,const char * & err)2484 int karte_t::grid_raise(const player_t *player, koord k, const char*&err)
2485 {
2486 int n = 0;
2487
2488 if(is_within_grid_limits(k)) {
2489
2490 const grund_t *gr = lookup_kartenboden_gridcoords(k);
2491 const slope_t::type corner_to_raise = get_corner_to_operate(k);
2492
2493 const sint16 x = gr->get_pos().x;
2494 const sint16 y = gr->get_pos().y;
2495 const sint8 hgt = gr->get_hoehe(corner_to_raise);
2496
2497 sint8 hsw, hse, hne, hnw;
2498 if( !gr->is_water() ) {
2499 const sint8 f = ground_desc_t::double_grounds ? 2 : 1;
2500 const sint8 o = ground_desc_t::double_grounds ? 1 : 0;
2501
2502 hsw = hgt - o + scorner_sw( corner_to_raise ) * f;
2503 hse = hgt - o + scorner_se( corner_to_raise ) * f;
2504 hne = hgt - o + scorner_ne( corner_to_raise ) * f;
2505 hnw = hgt - o + scorner_nw( corner_to_raise ) * f;
2506 }
2507 else {
2508 hsw = hse = hne = hnw = hgt;
2509 }
2510
2511 terraformer_t digger(this);
2512 digger.add_raise_node(x, y, hsw, hse, hne, hnw);
2513 digger.iterate(true);
2514
2515 err = digger.can_raise_all(player);
2516 if (err) {
2517 return 0;
2518 }
2519 n = digger.raise_all();
2520
2521 // force world full redraw, or background could be dirty.
2522 set_dirty();
2523
2524 if( max_height < lookup_kartenboden_gridcoords(k)->get_hoehe() ) {
2525 max_height = lookup_kartenboden_gridcoords(k)->get_hoehe();
2526 }
2527 }
2528 return (n+3)>>2;
2529 }
2530
2531
prepare_lower(terraformer_t & digger,sint16 x,sint16 y,sint8 hsw,sint8 hse,sint8 hne,sint8 hnw)2532 void karte_t::prepare_lower(terraformer_t& digger, sint16 x, sint16 y, sint8 hsw, sint8 hse, sint8 hne, sint8 hnw)
2533 {
2534 assert(is_within_limits(x,y));
2535 grund_t *gr = lookup_kartenboden_nocheck(x,y);
2536 const sint8 water_hgt = get_water_hgt_nocheck(x,y);
2537 const sint8 h0 = gr->get_hoehe();
2538 // which corners have to be raised?
2539 const sint8 h0_sw = gr->is_water() ? min( water_hgt, lookup_hgt_nocheck(x,y+1) ) : h0 + corner_sw( gr->get_grund_hang() );
2540 const sint8 h0_se = gr->is_water() ? min( water_hgt, lookup_hgt_nocheck(x+1,y+1) ) : h0 + corner_se( gr->get_grund_hang() );
2541 const sint8 h0_ne = gr->is_water() ? min( water_hgt, lookup_hgt_nocheck(x,y+1) ) : h0 + corner_ne( gr->get_grund_hang() );
2542 const sint8 h0_nw = gr->is_water() ? min( water_hgt, lookup_hgt_nocheck(x,y) ) : h0 + corner_nw( gr->get_grund_hang() );
2543
2544 const uint8 max_hdiff = ground_desc_t::double_grounds ? 2 : 1;
2545
2546 // sw
2547 if (h0_sw > hsw) {
2548 digger.add_lower_node(x - 1, y + 1, hsw + max_hdiff, hsw + max_hdiff, hsw, hsw + max_hdiff);
2549 }
2550 // s
2551 if (h0_se > hse || h0_sw > hsw) {
2552 const sint8 hs = min( hse, hsw ) + max_hdiff;
2553 digger.add_lower_node( x, y + 1, hs, hs, hse, hsw);
2554 }
2555 // se
2556 if (h0_se > hse) {
2557 digger.add_lower_node( x + 1, y + 1, hse + max_hdiff, hse + max_hdiff, hse + max_hdiff, hse);
2558 }
2559 // e
2560 if (h0_se > hse || h0_ne > hne) {
2561 const sint8 he = max( hse, hne ) + max_hdiff;
2562 digger.add_lower_node( x + 1,y, hse, he, he, hne);
2563 }
2564 // ne
2565 if (h0_ne > hne) {
2566 digger.add_lower_node( x + 1, y - 1, hne, hne + max_hdiff, hne + max_hdiff, hne + max_hdiff);
2567 }
2568 // n
2569 if (h0_nw > hnw || h0_ne > hne) {
2570 const sint8 hn = min( hnw, hne ) + max_hdiff;
2571 digger.add_lower_node( x, y - 1, hnw, hne, hn, hn);
2572 }
2573 // nw
2574 if (h0_nw > hnw) {
2575 digger.add_lower_node( x - 1, y - 1, hnw + max_hdiff, hnw, hnw + max_hdiff, hnw + max_hdiff);
2576 }
2577 // w
2578 if (h0_nw > hnw || h0_sw > hsw) {
2579 const sint8 hw = min( hnw, hsw ) + max_hdiff;
2580 digger.add_lower_node( x - 1, y, hw, hsw, hnw, hw);
2581 }
2582 }
2583
2584 // lower plan
2585 // new heights for each corner given
2586 // only test corners in ctest to avoid infinite loops
can_lower_to(const player_t * player,sint16 x,sint16 y,sint8 hsw,sint8 hse,sint8 hne,sint8 hnw) const2587 const char* karte_t::can_lower_to(const player_t* player, sint16 x, sint16 y, sint8 hsw, sint8 hse, sint8 hne, sint8 hnw) const
2588 {
2589 assert(is_within_limits(x,y));
2590
2591 const sint8 hneu = min( min( hsw, hse ), min( hne, hnw ) );
2592 // water heights
2593 // check if need to lower water height for higher neighbouring tiles
2594 for( sint16 i = 0 ; i < 8 ; i++ ) {
2595 const koord neighbour = koord( x, y ) + koord::neighbours[i];
2596 if( is_within_limits(neighbour) && get_water_hgt_nocheck(neighbour) > hneu ) {
2597 if (!is_plan_height_changeable( neighbour.x, neighbour.y )) {
2598 return "";
2599 }
2600 }
2601 }
2602
2603 return can_lower_plan_to(player, x, y, hneu );
2604 }
2605
2606
lower_to(sint16 x,sint16 y,sint8 hsw,sint8 hse,sint8 hne,sint8 hnw)2607 int karte_t::lower_to(sint16 x, sint16 y, sint8 hsw, sint8 hse, sint8 hne, sint8 hnw)
2608 {
2609 int n=0;
2610 assert(is_within_limits(x,y));
2611 grund_t *gr = lookup_kartenboden_nocheck(x,y);
2612 const uint8 old_slope = gr->get_grund_hang();
2613 sint8 water_hgt = get_water_hgt_nocheck(x,y);
2614 const sint8 h0 = gr->get_hoehe();
2615 // old height
2616 const sint8 h0_sw = gr->is_water() ? min( water_hgt, lookup_hgt_nocheck(x,y+1) ) : h0 + corner_sw( gr->get_grund_hang() );
2617 const sint8 h0_se = gr->is_water() ? min( water_hgt, lookup_hgt_nocheck(x+1,y+1) ) : h0 + corner_se( gr->get_grund_hang() );
2618 const sint8 h0_ne = gr->is_water() ? min( water_hgt, lookup_hgt_nocheck(x+1,y) ) : h0 + corner_ne( gr->get_grund_hang() );
2619 const sint8 h0_nw = gr->is_water() ? min( water_hgt, lookup_hgt_nocheck(x,y) ) : h0 + corner_nw( gr->get_grund_hang() );
2620 // new height
2621 const sint8 hn_sw = min(hsw, h0_sw);
2622 const sint8 hn_se = min(hse, h0_se);
2623 const sint8 hn_ne = min(hne, h0_ne);
2624 const sint8 hn_nw = min(hnw, h0_nw);
2625 // nothing to do?
2626 if( gr->is_water() ) {
2627 if( h0_nw <= hnw ) {
2628 return 0;
2629 }
2630 }
2631 else {
2632 if( h0_sw <= hsw && h0_se <= hse && h0_ne <= hne && h0_nw <= hnw ) {
2633 return 0;
2634 }
2635 }
2636
2637 // calc new height and slope
2638 const sint8 hneu = min( min( hn_sw, hn_se ), min( hn_ne, hn_nw ) );
2639 const sint8 hmaxneu = max( max( hn_sw, hn_se ), max( hn_ne, hn_nw ) );
2640
2641 // only slope could have been shores
2642 if( old_slope ) {
2643 // if there are any shore corners, then the new tile must be all water since it is lowered
2644 const bool make_water =
2645 get_water_hgt_nocheck(x,y) <= lookup_hgt_nocheck(x,y) ||
2646 get_water_hgt_nocheck(x+1,y) <= lookup_hgt_nocheck(x+1,y) ||
2647 get_water_hgt_nocheck(x,y+1) <= lookup_hgt_nocheck(x,y+1) ||
2648 get_water_hgt_nocheck(x+1,y+1) <= lookup_hgt_nocheck(x+1,y+1);
2649 if( make_water ) {
2650 sint8 water_table = water_hgt >= hneu ? water_hgt : hneu;
2651 set_water_hgt(x, y, water_table );
2652 }
2653 }
2654
2655 if( hneu >= water_hgt ) {
2656 // calculate water table from surrounding tiles - start off with height on this tile
2657 sint8 water_table = water_hgt >= h0 ? water_hgt : groundwater - 4;
2658
2659 /* we test each corner in turn to see whether it is at the base height of the tile
2660 if it is we then mark the 3 surrounding tiles for that corner for checking
2661 surrounding tiles are indicated by bits going anti-clockwise from
2662 (binary) 00000001 for north-west through to (binary) 10000000 for north
2663 as this is the order of directions used by koord::neighbours[] */
2664
2665 uint8 neighbour_flags = 0;
2666
2667 if( hn_nw == hneu ) {
2668 neighbour_flags |= 0x83;
2669 }
2670 if( hn_ne == hneu ) {
2671 neighbour_flags |= 0xe0;
2672 }
2673 if( hn_se == hneu ) {
2674 neighbour_flags |= 0x38;
2675 }
2676 if( hn_sw == hneu ) {
2677 neighbour_flags |= 0x0e;
2678 }
2679
2680 for( sint16 i = 0; i < 8 ; i++ ) {
2681 const koord neighbour = koord( x, y ) + koord::neighbours[i];
2682
2683 // here we look at the bit in neighbour_flags for this direction
2684 // we shift it i bits to the right and test the least significant bit
2685
2686 if( is_within_limits( neighbour ) && ((neighbour_flags >> i) & 1) ) {
2687 grund_t *gr2 = lookup_kartenboden_nocheck( neighbour );
2688 const sint8 water_hgt_neighbour = get_water_hgt_nocheck( neighbour );
2689 if( gr2 && (water_hgt_neighbour >= gr2->get_hoehe()) && water_hgt_neighbour <= hneu ) {
2690 water_table = max( water_table, water_hgt_neighbour );
2691 }
2692 }
2693 }
2694
2695 for( sint16 i = 0; i < 8 ; i++ ) {
2696 const koord neighbour = koord( x, y ) + koord::neighbours[i];
2697 if( is_within_limits( neighbour ) ) {
2698 grund_t *gr2 = lookup_kartenboden_nocheck( neighbour );
2699 if( gr2 && gr2->get_hoehe() < water_table ) {
2700 i = 8;
2701 water_table = groundwater - 4;
2702 }
2703 }
2704 }
2705
2706 // only allow water table to be lowered (except for case of sea level)
2707 // this prevents severe (errors!
2708 if( water_table < get_water_hgt_nocheck(x,y) ) {
2709 water_hgt = water_table;
2710 set_water_hgt(x, y, water_table );
2711 }
2712 }
2713
2714 // calc new height and slope
2715 const sint8 disp_hneu = max( hneu, water_hgt );
2716 const sint8 disp_hn_sw = max( hn_sw, water_hgt );
2717 const sint8 disp_hn_se = max( hn_se, water_hgt );
2718 const sint8 disp_hn_ne = max( hn_ne, water_hgt );
2719 const sint8 disp_hn_nw = max( hn_nw, water_hgt );
2720 const uint8 sneu = (disp_hn_sw - disp_hneu) + ((disp_hn_se - disp_hneu) * 3) + ((disp_hn_ne - disp_hneu) * 9) + ((disp_hn_nw - disp_hneu) * 27);
2721
2722 // change height and slope for land tiles only
2723 if( !gr->is_water() || (hmaxneu > water_hgt) ) {
2724 gr->set_pos( koord3d( x, y, disp_hneu ) );
2725 gr->set_grund_hang( (slope_t::type)sneu );
2726 access_nocheck(x,y)->abgesenkt();
2727 }
2728 // update north point in grid
2729 set_grid_hgt(x, y, hn_nw);
2730 if ( x == cached_size.x ) {
2731 // update eastern grid coordinates too if we are in the edge.
2732 set_grid_hgt(x+1, y, hn_ne);
2733 set_grid_hgt(x+1, y+1, hn_se);
2734 }
2735 if ( y == cached_size.y ) {
2736 // update southern grid coordinates too if we are in the edge.
2737 set_grid_hgt(x, y+1, hn_sw);
2738 set_grid_hgt(x+1, y+1, hn_se);
2739 }
2740
2741 // water heights
2742 // lower water height for higher neighbouring tiles
2743 // find out how high water is
2744 for( sint16 i = 0; i < 8; i++ ) {
2745 const koord neighbour = koord( x, y ) + koord::neighbours[i];
2746 if( is_within_limits( neighbour ) ) {
2747 const sint8 water_hgt_neighbour = get_water_hgt_nocheck( neighbour );
2748 if(water_hgt_neighbour > hneu ) {
2749 if( min_hgt_nocheck( neighbour ) < water_hgt_neighbour ) {
2750 // convert to flat ground before lowering water level
2751 raise_grid_to( neighbour.x, neighbour.y, water_hgt_neighbour );
2752 raise_grid_to( neighbour.x + 1, neighbour.y, water_hgt_neighbour );
2753 raise_grid_to( neighbour.x, neighbour.y + 1, water_hgt_neighbour );
2754 raise_grid_to( neighbour.x + 1, neighbour.y + 1, water_hgt_neighbour );
2755 }
2756 set_water_hgt( neighbour, hneu );
2757 access_nocheck(neighbour)->correct_water();
2758 }
2759 }
2760 }
2761
2762 calc_climate( koord( x, y ), false );
2763 for( sint16 i = 0; i < 8; i++ ) {
2764 const koord neighbour = koord( x, y ) + koord::neighbours[i];
2765 calc_climate( neighbour, false );
2766 }
2767
2768 // recalc landscape images - need to extend 2 in each direction
2769 for( sint16 j = y - 2; j <= y + 2; j++ ) {
2770 for( sint16 i = x - 2; i <= x + 2; i++ ) {
2771 if( is_within_limits( i, j ) /*&& (i != x || j != y)*/ ) {
2772 recalc_transitions( koord (i, j ) );
2773 }
2774 }
2775 }
2776
2777 n += h0_sw-hn_sw + h0_se-hn_se + h0_ne-hn_ne + h0_nw-hn_nw;
2778
2779 lookup_kartenboden_nocheck(x,y)->calc_image();
2780 if( (x+1) < cached_size.x ) {
2781 lookup_kartenboden_nocheck(x+1,y)->calc_image();
2782 }
2783 if( (y+1) < cached_size.y ) {
2784 lookup_kartenboden_nocheck(x,y+1)->calc_image();
2785 }
2786 return n;
2787 }
2788
2789
lower_grid_to(sint16 x,sint16 y,sint8 h)2790 void karte_t::lower_grid_to(sint16 x, sint16 y, sint8 h)
2791 {
2792 if(is_within_grid_limits(x,y)) {
2793 const sint32 offset = x + y*(cached_grid_size.x+1);
2794
2795 if( grid_hgts[offset] > h ) {
2796 grid_hgts[offset] = h;
2797 sint8 hh = h + 2;
2798 // set new height of neighbor grid points
2799 lower_grid_to(x-1, y-1, hh);
2800 lower_grid_to(x , y-1, hh);
2801 lower_grid_to(x+1, y-1, hh);
2802 lower_grid_to(x-1, y , hh);
2803 lower_grid_to(x+1, y , hh);
2804 lower_grid_to(x-1, y+1, hh);
2805 lower_grid_to(x , y+1, hh);
2806 lower_grid_to(x+1, y+1, hh);
2807 }
2808 }
2809 }
2810
2811
grid_lower(const player_t * player,koord k,const char * & err)2812 int karte_t::grid_lower(const player_t *player, koord k, const char*&err)
2813 {
2814 int n = 0;
2815
2816 if(is_within_grid_limits(k)) {
2817
2818 const grund_t *gr = lookup_kartenboden_gridcoords(k);
2819 const slope_t::type corner_to_lower = get_corner_to_operate(k);
2820
2821 const sint16 x = gr->get_pos().x;
2822 const sint16 y = gr->get_pos().y;
2823 const sint8 hgt = gr->get_hoehe(corner_to_lower);
2824
2825 const sint8 f = ground_desc_t::double_grounds ? 2 : 1;
2826 const sint8 o = ground_desc_t::double_grounds ? 1 : 0;
2827 const sint8 hsw = hgt + o - scorner_sw( corner_to_lower ) * f;
2828 const sint8 hse = hgt + o - scorner_se( corner_to_lower ) * f;
2829 const sint8 hne = hgt + o - scorner_ne( corner_to_lower ) * f;
2830 const sint8 hnw = hgt + o - scorner_nw( corner_to_lower ) * f;
2831
2832 terraformer_t digger(this);
2833 digger.add_lower_node(x, y, hsw, hse, hne, hnw);
2834 digger.iterate(false);
2835
2836 err = digger.can_lower_all(player);
2837 if (err) {
2838 return 0;
2839 }
2840
2841 n = digger.lower_all();
2842 err = NULL;
2843
2844 // force world full redraw, or background could be dirty.
2845 set_dirty();
2846
2847 if( min_height > min_hgt_nocheck( koord(x,y) ) ) {
2848 min_height = min_hgt_nocheck( koord(x,y) );
2849 }
2850 }
2851 return (n+3)>>2;
2852 }
2853
2854
can_flatten_tile(player_t * player,koord k,sint8 hgt,bool keep_water,bool make_underwater_hill)2855 bool karte_t::can_flatten_tile(player_t *player, koord k, sint8 hgt, bool keep_water, bool make_underwater_hill)
2856 {
2857 return flatten_tile(player, k, hgt, keep_water, make_underwater_hill, true /* just check */);
2858 }
2859
2860
2861 // make a flat level at this position (only used for AI at the moment)
flatten_tile(player_t * player,koord k,sint8 hgt,bool keep_water,bool make_underwater_hill,bool justcheck)2862 bool karte_t::flatten_tile(player_t *player, koord k, sint8 hgt, bool keep_water, bool make_underwater_hill, bool justcheck)
2863 {
2864 int n = 0;
2865 bool ok = true;
2866 const grund_t *gr = lookup_kartenboden(k);
2867 const slope_t::type slope = gr->get_grund_hang();
2868 const sint8 old_hgt = make_underwater_hill && gr->is_water() ? min_hgt(k) : gr->get_hoehe();
2869 const sint8 max_hgt = old_hgt + slope_t::max_diff(slope);
2870 if( max_hgt > hgt ) {
2871
2872 terraformer_t digger(this);
2873 digger.add_lower_node(k.x, k.y, hgt, hgt, hgt, hgt);
2874 digger.iterate(false);
2875
2876 ok = digger.can_lower_all(player) == NULL;
2877
2878 if (ok && !justcheck) {
2879 n += digger.lower_all();
2880 }
2881 }
2882 if( ok && old_hgt < hgt ) {
2883
2884 terraformer_t digger(this);
2885 digger.add_raise_node(k.x, k.y, hgt, hgt, hgt, hgt);
2886 digger.iterate(true);
2887
2888 ok = digger.can_raise_all(player, keep_water) == NULL;
2889
2890 if (ok && !justcheck) {
2891 n += digger.raise_all();
2892 }
2893 }
2894 // was changed => pay for it
2895 if(n>0) {
2896 n = (n+3) >> 2;
2897 player_t::book_construction_costs(player, n * settings.cst_alter_land, k, ignore_wt);
2898 }
2899 return ok;
2900 }
2901
2902
store_player_password_hash(uint8 player_nr,const pwd_hash_t & hash)2903 void karte_t::store_player_password_hash( uint8 player_nr, const pwd_hash_t& hash )
2904 {
2905 player_password_hash[player_nr] = hash;
2906 }
2907
2908
clear_player_password_hashes()2909 void karte_t::clear_player_password_hashes()
2910 {
2911 for(int i=0; i<MAX_PLAYER_COUNT ; i++) {
2912 player_password_hash[i].clear();
2913 if (players[i]) {
2914 players[i]->check_unlock(player_password_hash[i]);
2915 }
2916 }
2917 }
2918
2919
rdwr_player_password_hashes(loadsave_t * file)2920 void karte_t::rdwr_player_password_hashes(loadsave_t *file)
2921 {
2922 pwd_hash_t dummy;
2923 for( int i=0; i<PLAYER_UNOWNED; i++ ) {
2924 pwd_hash_t *p = players[i] ? &players[i]->access_password_hash() : &dummy;
2925 for( uint8 j=0; j<20; j++) {
2926 file->rdwr_byte( (*p)[j] );
2927 }
2928 }
2929 }
2930
2931
call_change_player_tool(uint8 cmd,uint8 player_nr,uint16 param,bool scripted_call)2932 void karte_t::call_change_player_tool(uint8 cmd, uint8 player_nr, uint16 param, bool scripted_call)
2933 {
2934 if (env_t::networkmode) {
2935 nwc_chg_player_t *nwc = new nwc_chg_player_t(sync_steps, map_counter, cmd, player_nr, param, scripted_call);
2936
2937 network_send_server(nwc);
2938 }
2939 else {
2940 change_player_tool(cmd, player_nr, param, !get_public_player()->is_locked() || scripted_call, true);
2941 // update the window
2942 ki_kontroll_t* playerwin = (ki_kontroll_t*)win_get_magic(magic_ki_kontroll_t);
2943 if (playerwin) {
2944 playerwin->update_data();
2945 }
2946 }
2947 }
2948
2949
change_player_tool(uint8 cmd,uint8 player_nr,uint16 param,bool public_player_unlocked,bool exec)2950 bool karte_t::change_player_tool(uint8 cmd, uint8 player_nr, uint16 param, bool public_player_unlocked, bool exec)
2951 {
2952 switch(cmd) {
2953 case new_player: {
2954 // only public player can start AI
2955 if( (param != player_t::HUMAN && !public_player_unlocked) || param >= player_t::MAX_AI ) {
2956 return false;
2957 }
2958 // range check, player already existent?
2959 if( player_nr >= PLAYER_UNOWNED || get_player(player_nr) ) {
2960 return false;
2961 }
2962 if(exec) {
2963 init_new_player( player_nr, (uint8) param );
2964 // activate/deactivate AI immediately
2965 player_t *player = get_player(player_nr);
2966 if (param != player_t::HUMAN && player) {
2967 player->set_active(true);
2968 settings.set_player_active(player_nr, player->is_active());
2969 }
2970 }
2971 return true;
2972 }
2973 case toggle_freeplay: {
2974 // only public player can change freeplay mode
2975 if (!public_player_unlocked || !settings.get_allow_player_change()) {
2976 return false;
2977 }
2978 if (exec) {
2979 settings.set_freeplay( !settings.is_freeplay() );
2980 }
2981 return true;
2982 }
2983 case delete_player: {
2984 // range check, player existent?
2985 if ( player_nr >= PLAYER_UNOWNED || get_player(player_nr)==NULL ) {
2986 return false;
2987 }
2988 if (exec) {
2989 remove_player(player_nr);
2990 }
2991 return true;
2992 }
2993 // unknown command: delete
2994 default: ;
2995 }
2996 return false;
2997 }
2998
2999
set_tool(tool_t * tool_in,player_t * player)3000 void karte_t::set_tool( tool_t *tool_in, player_t *player )
3001 {
3002 if( get_random_mode()&LOAD_RANDOM ) {
3003 dbg->warning("karte_t::set_tool", "Ignored tool %i during loading.", tool_in->get_id() );
3004 return;
3005 }
3006 bool needs_check = !tool_in->no_check();
3007 // check for scenario conditions
3008 if( needs_check && !scenario->is_tool_allowed(player, tool_in->get_id(), tool_in->get_waytype()) ) {
3009 return;
3010 }
3011 // check for password-protected players
3012 if( (!tool_in->is_init_network_save() || !tool_in->is_work_network_save()) && needs_check &&
3013 !(tool_in->get_id()==(TOOL_CHANGE_PLAYER|SIMPLE_TOOL) || tool_in->get_id()==(TOOL_ADD_MESSAGE|SIMPLE_TOOL)) &&
3014 player && player->is_locked() ) {
3015 // player is currently password protected => request unlock first
3016 create_win( -1, -1, new password_frame_t(player), w_info, magic_pwd_t + player->get_player_nr() );
3017 return;
3018 }
3019 tool_in->flags |= event_get_last_control_shift();
3020 if(!env_t::networkmode || tool_in->is_init_network_save() ) {
3021 local_set_tool(tool_in, player);
3022 }
3023 else {
3024 // queue tool for network
3025 nwc_tool_t *nwc = new nwc_tool_t(player, tool_in, zeiger->get_pos(), steps, map_counter, true);
3026 network_send_server(nwc);
3027 }
3028 }
3029
3030
3031 // set a new tool on our client, calls init
local_set_tool(tool_t * tool_in,player_t * player)3032 void karte_t::local_set_tool( tool_t *tool_in, player_t * player )
3033 {
3034 tool_in->flags |= tool_t::WFL_LOCAL;
3035 // now call init
3036 bool init_result = tool_in->init(player);
3037 // for unsafe tools init() must return false
3038 assert(tool_in->is_init_network_save() || !init_result);
3039
3040 if (player && init_result && !tool_in->is_scripted()) {
3041
3042 set_dirty();
3043 tool_t *sp_tool = selected_tool[player->get_player_nr()];
3044 if(tool_in != sp_tool) {
3045
3046 // reinit same tool => do not play sound twice
3047 sound_play(SFX_SELECT);
3048
3049 // only exit, if it is not the same tool again ...
3050 sp_tool->flags |= tool_t::WFL_LOCAL;
3051 sp_tool->exit(player);
3052 sp_tool->flags =0;
3053 }
3054
3055 if( player==active_player ) {
3056 // reset pointer
3057 koord3d zpos = zeiger->get_pos();
3058 // remove marks
3059 zeiger->change_pos( koord3d::invalid );
3060 // set new cursor properties
3061 tool_in->init_cursor(zeiger);
3062 // .. and mark again (if the position is acceptable for the tool)
3063 if( tool_in->check_valid_pos(zpos.get_2d())) {
3064 zeiger->change_pos( zpos );
3065 }
3066 else {
3067 zeiger->change_pos( koord3d::invalid );
3068 }
3069 }
3070 selected_tool[player->get_player_nr()] = tool_in;
3071 }
3072 tool_in->flags = 0;
3073 toolbar_last_used_t::last_used_tools->append( tool_in, player );
3074 }
3075
3076
min_hgt_nocheck(const koord k) const3077 sint8 karte_t::min_hgt_nocheck(const koord k) const
3078 {
3079 // more optimised version of min_hgt code
3080 const sint8 * p = &grid_hgts[k.x + k.y*(sint32)(cached_grid_size.x+1)];
3081
3082 const int h1 = *p;
3083 const int h2 = *(p+1);
3084 const int h3 = *(p+get_size().x+2);
3085 const int h4 = *(p+get_size().x+1);
3086
3087 return min(min(h1,h2), min(h3,h4));
3088 }
3089
3090
max_hgt_nocheck(const koord k) const3091 sint8 karte_t::max_hgt_nocheck(const koord k) const
3092 {
3093 // more optimised version of max_hgt code
3094 const sint8 * p = &grid_hgts[k.x + k.y*(sint32)(cached_grid_size.x+1)];
3095
3096 const int h1 = *p;
3097 const int h2 = *(p+1);
3098 const int h3 = *(p+get_size().x+2);
3099 const int h4 = *(p+get_size().x+1);
3100
3101 return max(max(h1,h2), max(h3,h4));
3102 }
3103
3104
min_hgt(const koord k) const3105 sint8 karte_t::min_hgt(const koord k) const
3106 {
3107 const sint8 h1 = lookup_hgt(k);
3108 const sint8 h2 = lookup_hgt(k+koord(1, 0));
3109 const sint8 h3 = lookup_hgt(k+koord(1, 1));
3110 const sint8 h4 = lookup_hgt(k+koord(0, 1));
3111
3112 return min(min(h1,h2), min(h3,h4));
3113 }
3114
3115
max_hgt(const koord k) const3116 sint8 karte_t::max_hgt(const koord k) const
3117 {
3118 const sint8 h1 = lookup_hgt(k);
3119 const sint8 h2 = lookup_hgt(k+koord(1, 0));
3120 const sint8 h3 = lookup_hgt(k+koord(1, 1));
3121 const sint8 h4 = lookup_hgt(k+koord(0, 1));
3122
3123 return max(max(h1,h2), max(h3,h4));
3124 }
3125
3126
3127 planquadrat_t *rotate90_new_plan;
3128 sint8 *rotate90_new_water;
3129
rotate90_plans(sint16 x_min,sint16 x_max,sint16 y_min,sint16 y_max)3130 void karte_t::rotate90_plans(sint16 x_min, sint16 x_max, sint16 y_min, sint16 y_max)
3131 {
3132 const int LOOP_BLOCK = 64;
3133 if( (loaded_rotation + settings.get_rotation()) & 1 ) { // 1 || 3
3134 for( int yy = y_min; yy < y_max; yy += LOOP_BLOCK ) {
3135 for( int xx = x_min; xx < x_max; xx += LOOP_BLOCK ) {
3136 for( int y = yy; y < min(yy + LOOP_BLOCK, y_max); y++ ) {
3137 for( int x = xx; x < min(xx + LOOP_BLOCK, x_max); x++ ) {
3138 const int nr = x + (y * cached_grid_size.x);
3139 const int new_nr = (cached_size.y - y) + (x * cached_grid_size.y);
3140 // first rotate everything on the ground(s)
3141 for( uint i = 0; i < plan[nr].get_boden_count(); i++ ) {
3142 plan[nr].get_boden_bei(i)->rotate90();
3143 }
3144 // rotate climate transitions
3145 rotate_transitions( koord( x, y ) );
3146 // now: rotate all things on the map
3147 swap(rotate90_new_plan[new_nr], plan[nr]);
3148 }
3149 }
3150 }
3151 }
3152 }
3153 else {
3154 // first: rotate all things on the map
3155 for( int xx = x_min; xx < x_max; xx += LOOP_BLOCK ) {
3156 for( int yy = y_min; yy < y_max; yy += LOOP_BLOCK ) {
3157 for( int x = xx; x < min(xx + LOOP_BLOCK, x_max); x++ ) {
3158 for( int y=yy; y < min(yy + LOOP_BLOCK, y_max); y++ ) {
3159 // rotate climate transitions
3160 rotate_transitions( koord( x, y ) );
3161 const int nr = x + (y * cached_grid_size.x);
3162 const int new_nr = (cached_size.y - y) + (x * cached_grid_size.y);
3163 swap(rotate90_new_plan[new_nr], plan[nr]);
3164 }
3165 }
3166 }
3167 }
3168 // now rotate everything on the ground(s)
3169 for( int xx = x_min; xx < x_max; xx += LOOP_BLOCK ) {
3170 for( int yy = y_min; yy < y_max; yy += LOOP_BLOCK ) {
3171 for( int x = xx; x < min(xx + LOOP_BLOCK, x_max); x++ ) {
3172 for( int y = yy; y < min(yy + LOOP_BLOCK, y_max); y++ ) {
3173 const int new_nr = (cached_size.y - y) + (x * cached_grid_size.y);
3174 for( uint i = 0; i < rotate90_new_plan[new_nr].get_boden_count(); i++ ) {
3175 rotate90_new_plan[new_nr].get_boden_bei(i)->rotate90();
3176 }
3177 }
3178 }
3179 }
3180 }
3181 }
3182
3183 // rotate water
3184 for( int xx = 0; xx < cached_grid_size.x; xx += LOOP_BLOCK ) {
3185 for( int yy = y_min; yy < y_max; yy += LOOP_BLOCK ) {
3186 for( int x = xx; x < min( xx + LOOP_BLOCK, cached_grid_size.x ); x++ ) {
3187 int nr = x + (yy * cached_grid_size.x);
3188 int new_nr = (cached_size.y - yy) + (x * cached_grid_size.y);
3189 for( int y = yy; y < min( yy + LOOP_BLOCK, y_max ); y++ ) {
3190 rotate90_new_water[new_nr] = water_hgts[nr];
3191 nr += cached_grid_size.x;
3192 new_nr--;
3193 }
3194 }
3195 }
3196 }
3197 }
3198
3199
rotate90()3200 void karte_t::rotate90()
3201 {
3202 DBG_MESSAGE( "karte_t::rotate90()", "called" );
3203 // assume we can save this rotation
3204 nosave_warning = nosave = false;
3205
3206 //announce current target rotation
3207 settings.rotate90();
3208
3209 // clear marked region
3210 zeiger->change_pos( koord3d::invalid );
3211
3212 // preprocessing, detach stops from factories to prevent crash
3213 FOR(vector_tpl<halthandle_t>, const s, haltestelle_t::get_alle_haltestellen()) {
3214 s->release_factory_links();
3215 }
3216
3217 //rotate plans in parallel posix thread ...
3218 rotate90_new_plan = new planquadrat_t[cached_grid_size.y * cached_grid_size.x];
3219 rotate90_new_water = new sint8[cached_grid_size.y * cached_grid_size.x];
3220
3221 world_xy_loop(&karte_t::rotate90_plans, 0);
3222
3223 grund_t::finish_rotate90();
3224
3225 delete [] plan;
3226 plan = rotate90_new_plan;
3227 delete [] water_hgts;
3228 water_hgts = rotate90_new_water;
3229
3230 // rotate heightmap
3231 sint8 *new_hgts = new sint8[(cached_grid_size.x+1)*(cached_grid_size.y+1)];
3232 const int LOOP_BLOCK = 64;
3233 for( int yy=0; yy<=cached_grid_size.y; yy+=LOOP_BLOCK ) {
3234 for( int xx=0; xx<=cached_grid_size.x; xx+=LOOP_BLOCK ) {
3235 for( int x=xx; x<=min(xx+LOOP_BLOCK,cached_grid_size.x); x++ ) {
3236 for( int y=yy; y<=min(yy+LOOP_BLOCK,cached_grid_size.y); y++ ) {
3237 const int nr = x+(y*(cached_grid_size.x+1));
3238 const int new_nr = (cached_grid_size.y-y)+(x*(cached_grid_size.y+1));
3239 new_hgts[new_nr] = grid_hgts[nr];
3240 }
3241 }
3242 }
3243 }
3244 delete [] grid_hgts;
3245 grid_hgts = new_hgts;
3246
3247 // rotate borders
3248 sint16 xw = cached_size.x;
3249 cached_size.x = cached_size.y;
3250 cached_size.y = xw;
3251
3252 int wx = cached_grid_size.x;
3253 cached_grid_size.x = cached_grid_size.y;
3254 cached_grid_size.y = wx;
3255
3256 // now step all towns (to generate passengers)
3257 FOR(weighted_vector_tpl<stadt_t*>, const i, stadt) {
3258 i->rotate90(cached_size.x);
3259 }
3260
3261 // fixed order factory, halts, convois
3262 FOR(slist_tpl<fabrik_t*>, const f, fab_list) {
3263 f->rotate90(cached_size.x);
3264 }
3265 // after rotation of factories, rotate everything that holds freight: stations and convoys
3266 FOR(vector_tpl<halthandle_t>, const s, haltestelle_t::get_alle_haltestellen()) {
3267 s->rotate90(cached_size.x);
3268 }
3269
3270 FOR(vector_tpl<convoihandle_t>, const i, convoi_array) {
3271 i->rotate90(cached_size.x);
3272 }
3273
3274 for( int i=0; i<MAX_PLAYER_COUNT; i++ ) {
3275 if( players[i] ) {
3276 players[i]->rotate90( cached_size.x );
3277 }
3278 }
3279
3280 // rotate label texts
3281 FOR(slist_tpl<koord>, & l, labels) {
3282 l.rotate90(cached_size.x);
3283 }
3284
3285 // rotate view
3286 viewport->rotate90( cached_size.x );
3287
3288 // rotate messages
3289 msg->rotate90( cached_size.x );
3290
3291 // rotate view in dialog windows
3292 win_rotate90( cached_size.x );
3293
3294 if( cached_grid_size.x != cached_grid_size.y ) {
3295 // the map must be reinit
3296 minimap_t::get_instance()->init();
3297 }
3298
3299 // rotate map search array
3300 factory_builder_t::new_world();
3301
3302 // update minimap
3303 if( minimap_t::is_visible) {
3304 minimap_t::get_instance()->set_display_mode( minimap_t::get_instance()->get_display_mode() );
3305 }
3306
3307 get_scenario()->rotate90( cached_size.x );
3308
3309 script_api::rotate90();
3310
3311 // finally recalculate schedules for goods in transit ...
3312 set_schedule_counter();
3313
3314 set_dirty();
3315 }
3316 // -------- Verwaltung von Fabriken -----------------------------
3317
3318
add_fab(fabrik_t * fab)3319 bool karte_t::add_fab(fabrik_t *fab)
3320 {
3321 //DBG_MESSAGE("karte_t::add_fab()","fab = %p",fab);
3322 assert(fab != NULL);
3323 fab_list.insert( fab );
3324 goods_in_game.clear(); // Force rebuild of goods list
3325 return true;
3326 }
3327
3328
3329 // beware: must remove also links from stops and towns
rem_fab(fabrik_t * fab)3330 bool karte_t::rem_fab(fabrik_t *fab)
3331 {
3332 if(!fab_list.remove( fab )) {
3333 return false;
3334 }
3335
3336 // Force rebuild of goods list
3337 goods_in_game.clear();
3338
3339 // now all the interwoven connections must be cleared
3340 koord k = fab->get_pos().get_2d();
3341 planquadrat_t* plan = access(k);
3342 if(plan) {
3343
3344 // we need a copy, since the verbinde fabriken is modifying the list
3345 halthandle_t list[16];
3346 const uint8 count = plan->get_haltlist_count();
3347 assert(count<16);
3348 memcpy( list, plan->get_haltlist(), count*sizeof(halthandle_t) );
3349 for( uint8 i=0; i<count; i++ ) {
3350 // first remove all the tiles that do not connect
3351 plan->remove_from_haltlist( list[i] );
3352 // then reconnect
3353 list[i]->verbinde_fabriken();
3354 }
3355
3356 // remove all links from factories
3357 FOR(slist_tpl<fabrik_t*>, const fab, fab_list) {
3358 fab->rem_lieferziel(k);
3359 fab->rem_supplier(k);
3360 }
3361
3362 // remove all links to cities
3363 fab->clear_target_cities();
3364
3365 // finally delete it
3366 delete fab;
3367
3368 // recalculate factory position map
3369 factory_builder_t::new_world();
3370 }
3371 return true;
3372 }
3373
3374
3375 /*----------------------------------------------------------------------------------------------------------------------*/
3376 /* same procedure for tourist attractions */
3377
3378
add_attraction(gebaeude_t * gb)3379 void karte_t::add_attraction(gebaeude_t *gb)
3380 {
3381 assert(gb != NULL);
3382 attractions.append( gb, gb->get_tile()->get_desc()->get_level() );
3383
3384 // Knightly : add links between this attraction and all cities
3385 FOR(weighted_vector_tpl<stadt_t*>, const c, stadt) {
3386 c->add_target_attraction(gb);
3387 }
3388 }
3389
3390
remove_attraction(gebaeude_t * gb)3391 void karte_t::remove_attraction(gebaeude_t *gb)
3392 {
3393 assert(gb != NULL);
3394 attractions.remove( gb );
3395
3396 // Knightly : remove links between this attraction and all cities
3397 FOR(weighted_vector_tpl<stadt_t*>, const c, stadt) {
3398 c->remove_target_attraction(gb);
3399 }
3400 }
3401
3402
3403 // -------- Verwaltung von Staedten -----------------------------
3404
find_nearest_city(const koord k) const3405 stadt_t *karte_t::find_nearest_city(const koord k) const
3406 {
3407 uint32 min_dist = 99999999;
3408 bool contains = false;
3409 stadt_t *best = NULL; // within city limits
3410
3411 if( is_within_limits(k) ) {
3412 FOR( weighted_vector_tpl<stadt_t*>, const s, stadt ) {
3413 if( k.x >= s->get_linksoben().x && k.y >= s->get_linksoben().y && k.x < s->get_rechtsunten().x && k.y < s->get_rechtsunten().y ) {
3414 const uint32 dist = koord_distance( k, s->get_center() );
3415 if( !contains ) {
3416 // no city within limits => this is best
3417 best = s;
3418 min_dist = dist;
3419 }
3420 else if( dist < min_dist ) {
3421 best = s;
3422 min_dist = dist;
3423 }
3424 contains = true;
3425 }
3426 else if( !contains ) {
3427 // so far no cities found within its city limit
3428 const uint32 dist = koord_distance( k, s->get_center() );
3429 if( dist < min_dist ) {
3430 best = s;
3431 min_dist = dist;
3432 }
3433 }
3434 }
3435 }
3436 return best;
3437 }
3438
3439
3440 // -------- Verwaltung von synchronen Objekten ------------------
3441
add(sync_steppable * obj)3442 void karte_t::sync_list_t::add(sync_steppable *obj)
3443 {
3444 assert(!sync_step_running);
3445 list.append(obj);
3446 }
3447
remove(sync_steppable * obj)3448 void karte_t::sync_list_t::remove(sync_steppable *obj)
3449 {
3450 if(sync_step_running) {
3451 if (obj == currently_deleting) {
3452 return;
3453 }
3454 assert(false);
3455 }
3456 else {
3457 list.remove(obj);
3458 }
3459 }
3460
clear()3461 void karte_t::sync_list_t::clear()
3462 {
3463 list.clear();
3464 currently_deleting = NULL;
3465 sync_step_running = false;
3466 }
3467
sync_step(uint32 delta_t)3468 void karte_t::sync_list_t::sync_step(uint32 delta_t)
3469 {
3470 sync_step_running = true;
3471 currently_deleting = NULL;
3472
3473 for(uint32 i=0; i<list.get_count();i++) {
3474 sync_steppable *ss = list[i];
3475 switch(ss->sync_step(delta_t)) {
3476 case SYNC_OK:
3477 break;
3478 case SYNC_DELETE:
3479 currently_deleting = ss;
3480 delete ss;
3481 currently_deleting = NULL;
3482 /* fall-through */
3483 case SYNC_REMOVE:
3484 ss = list.pop_back();
3485 if (i < list.get_count()) {
3486 list[i] = ss;
3487 }
3488 }
3489 }
3490 sync_step_running = false;
3491 }
3492
3493
3494 /*
3495 * this routine is called before an image is displayed
3496 * it moves vehicles and pedestrians
3497 * only time consuming thing are done in step()
3498 * everything else is done here
3499 */
sync_step(uint32 delta_t,bool do_sync_step,bool display)3500 void karte_t::sync_step(uint32 delta_t, bool do_sync_step, bool display )
3501 {
3502 set_random_mode( SYNC_STEP_RANDOM );
3503 if(do_sync_step) {
3504 // only omitted, when called to display a new frame during fast forward
3505
3506 // just for progress
3507 if( delta_t > 10000 ) {
3508 dbg->error( "karte_t::sync_step()", "delta_t too large: %li", delta_t );
3509 delta_t = 10000;
3510 }
3511 ticks += delta_t;
3512
3513 set_random_mode( INTERACTIVE_RANDOM );
3514
3515 /* animations do not require exact sync
3516 * foundations etc are added removed frequently during city growth
3517 * => they are now in a hastable!
3518 */
3519 sync_eyecandy.sync_step( delta_t );
3520
3521 /* pedestrians do not require exact sync and are added/removed frequently
3522 * => they are now in a hastable!
3523 */
3524 sync_way_eyecandy.sync_step( delta_t );
3525
3526 clear_random_mode( INTERACTIVE_RANDOM );
3527
3528 sync.sync_step( delta_t );
3529
3530 ticker::update();
3531 }
3532
3533 if(display) {
3534 // only omitted in fast forward mode for the magic steps
3535
3536 for(int x=0; x<MAX_PLAYER_COUNT-1; x++) {
3537 if(players[x]) {
3538 players[x]->age_messages(delta_t);
3539 }
3540 }
3541
3542 // change view due to following a convoi?
3543 convoihandle_t follow_convoi = viewport->get_follow_convoi();
3544 if(follow_convoi.is_bound() && follow_convoi->get_vehicle_count()>0) {
3545 vehicle_t const& v = *follow_convoi->front();
3546 koord3d const new_pos = v.get_pos();
3547 if(new_pos!=koord3d::invalid) {
3548 const sint16 rw = get_tile_raster_width();
3549 int new_xoff = 0;
3550 int new_yoff = 0;
3551 v.get_screen_offset( new_xoff, new_yoff, get_tile_raster_width() );
3552 new_xoff -= tile_raster_scale_x(-v.get_xoff(), rw);
3553 new_yoff -= tile_raster_scale_y(-v.get_yoff(), rw) + tile_raster_scale_y(new_pos.z * TILE_HEIGHT_STEP, rw);
3554 viewport->change_world_position( new_pos.get_2d(), -new_xoff, -new_yoff );
3555
3556 // auto underground to follow convois
3557 if( env_t::follow_convoi_underground ) {
3558 grund_t *gr = lookup_kartenboden( new_pos.get_2d() );
3559 bool redraw = false;
3560 if( new_pos.z < gr->get_hoehe() ) {
3561 redraw = grund_t::underground_mode == grund_t::ugm_none ? grund_t::underground_level != new_pos.z : true;
3562 grund_t::set_underground_mode( env_t::follow_convoi_underground, new_pos.z );
3563 }
3564 else {
3565 redraw = grund_t::underground_mode != grund_t::ugm_none;
3566 grund_t::set_underground_mode( grund_t::ugm_none, 0 );
3567 }
3568 if( redraw ) {
3569 // recalc all images on map
3570 update_underground();
3571 }
3572 }
3573 }
3574 }
3575
3576 // display new frame with water animation
3577 intr_refresh_display( false );
3578 update_frame_sleep_time();
3579 }
3580 clear_random_mode( SYNC_STEP_RANDOM );
3581 }
3582
3583
3584 // does all the magic about frame timing
update_frame_sleep_time()3585 void karte_t::update_frame_sleep_time()
3586 {
3587 // get average frame time
3588 uint32 last_ms = dr_time();
3589 last_frame_ms[last_frame_idx] = last_ms;
3590 last_frame_idx = (last_frame_idx+1) % 32;
3591 sint32 ms_diff = (sint32)( last_ms - last_frame_ms[last_frame_idx] );
3592 if(ms_diff > 0) {
3593 realFPS = (32000u*16) / ms_diff;
3594 }
3595 else {
3596 realFPS = env_t::fps*16;
3597 simloops = 60;
3598 }
3599
3600 if( step_mode&PAUSE_FLAG ) {
3601 // not changing pauses
3602 next_step_time = dr_time() + 1000 / env_t::fps;
3603 idle_time = 100;
3604 }
3605 else if( step_mode==FIX_RATIO) {
3606 simloops = realFPS/16;
3607 }
3608 else if(step_mode==NORMAL) {
3609 // calculate simloops
3610 uint16 last_step = (steps+31)%32;
3611 if(last_step_nr[last_step]>last_step_nr[steps%32]) {
3612 simloops = (10000*32l)/(last_step_nr[last_step]-last_step_nr[steps%32]);
3613 }
3614 // (de-)activate faster redraw
3615 env_t::simple_drawing = (env_t::simple_drawing_normal >= get_tile_raster_width());
3616
3617 // calculate and activate fast redraw ..
3618 if( realFPS > (env_t::fps*17/16) ) {
3619 // decrease fast tile zoom by one
3620 if( env_t::simple_drawing_normal > env_t::simple_drawing_default ) {
3621 env_t::simple_drawing_normal --;
3622 }
3623 }
3624 else if( realFPS < env_t::fps*16/2 ) {
3625 // activate simple redraw
3626 env_t::simple_drawing_normal = max( env_t::simple_drawing_normal, get_tile_raster_width()+1 );
3627 }
3628 else if( realFPS < (env_t::fps*15) ) {
3629 // increase fast tile redraw by one if below current tile size
3630 if( env_t::simple_drawing_normal <= (get_tile_raster_width()*3)/2 ) {
3631 env_t::simple_drawing_normal ++;
3632 }
3633 }
3634 else if( idle_time > 0 ) {
3635 // decrease fast tile zoom by one
3636 if( env_t::simple_drawing_normal > env_t::simple_drawing_default ) {
3637 env_t::simple_drawing_normal --;
3638 }
3639 }
3640 env_t::simple_drawing = (env_t::simple_drawing_normal >= get_tile_raster_width());
3641
3642 // way too slow => try to increase time ...
3643 if( last_ms-last_interaction > 100 ) {
3644 if( last_ms-last_interaction > 500 ) {
3645 set_frame_time( 1+get_frame_time() );
3646 // more than 1s since last zoom => check if zoom out is a way to improve it
3647 if( last_ms-last_interaction > 5000 && get_current_tile_raster_width() < 32 ) {
3648 zoom_factor_up();
3649 set_dirty();
3650 last_interaction = last_ms-1000;
3651 }
3652 }
3653 else {
3654 increase_frame_time();
3655 increase_frame_time();
3656 increase_frame_time();
3657 increase_frame_time();
3658 }
3659 }
3660 else {
3661 // change frame spacing ... (pause will be changed by step() directly)
3662 if(realFPS>(env_t::fps*17)) {
3663 increase_frame_time();
3664 }
3665 else if(realFPS<env_t::fps*16) { //15 for deadband
3666 if( 1000u*16/get_frame_time() < 2*realFPS ) {
3667 if( realFPS < (env_t::fps*16/2) ) {
3668 set_frame_time( get_frame_time()-1 );
3669 next_step_time = last_ms;
3670 }
3671 else {
3672 reduce_frame_time();
3673 }
3674 }
3675 else {
3676 // do not set time too short!
3677 set_frame_time( 500/max(1,realFPS/16) );
3678 next_step_time = last_ms;
3679 }
3680 }
3681 }
3682 }
3683 else { // here only with fyst forward ...
3684 // try to get 10 fps or lower rate (if set)
3685 uint32 frame_intervall = max( 100, 1000/env_t::fps );
3686 if(get_frame_time()>frame_intervall) {
3687 reduce_frame_time();
3688 }
3689 else {
3690 increase_frame_time();
3691 }
3692 // (de-)activate faster redraw
3693 env_t::simple_drawing = env_t::simple_drawing_fast_forward || (env_t::simple_drawing_normal >= get_tile_raster_width());
3694 }
3695 }
3696
3697
3698 // add an amount to a subcategory
buche(sint64 const betrag,player_cost const type)3699 void karte_t::buche(sint64 const betrag, player_cost const type)
3700 {
3701 assert(type < MAX_WORLD_COST);
3702 finance_history_year[0][type] += betrag;
3703 finance_history_month[0][type] += betrag;
3704 // to do: check for dependencies
3705 }
3706
3707
get_population(stadt_t const * const c)3708 inline sint32 get_population(stadt_t const* const c)
3709 {
3710 return c->get_einwohner();
3711 }
3712
3713
new_month()3714 void karte_t::new_month()
3715 {
3716 bool need_locality_update = false;
3717
3718 update_history();
3719
3720 // advance history ...
3721 last_month_bev = finance_history_month[0][WORLD_CITICENS];
3722 for( int hist=0; hist<karte_t::MAX_WORLD_COST; hist++ ) {
3723 for( int y=MAX_WORLD_HISTORY_MONTHS-1; y>0; y-- ) {
3724 finance_history_month[y][hist] = finance_history_month[y-1][hist];
3725 }
3726 }
3727
3728 current_month ++;
3729 last_month ++;
3730 if( last_month > 11 ) {
3731 last_month = 0;
3732 // check for changed distance weight
3733 uint32 old_locality_factor = koord::locality_factor;
3734 koord::locality_factor = settings.get_locality_factor( last_year+1 );
3735 need_locality_update = (old_locality_factor != koord::locality_factor);
3736 }
3737 DBG_MESSAGE("karte_t::new_month()","Month (%d/%d) has started", (last_month%12)+1, last_month/12 );
3738
3739 // this should be done before a map update, since the map may want an update of the way usage
3740 // DBG_MESSAGE("karte_t::new_month()","ways");
3741 FOR(slist_tpl<weg_t*>, const w, weg_t::get_alle_wege()) {
3742 w->new_month();
3743 }
3744
3745 // recalc old settings (and maybe update the stops with the current values)
3746 minimap_t::get_instance()->new_month();
3747
3748 INT_CHECK("simworld 1701");
3749
3750 // DBG_MESSAGE("karte_t::new_month()","convois");
3751 // hsiegeln - call new month for convois
3752 FOR(vector_tpl<convoihandle_t>, const cnv, convoi_array) {
3753 cnv->new_month();
3754 }
3755
3756 INT_CHECK("simworld 1701");
3757
3758 // DBG_MESSAGE("karte_t::new_month()","factories");
3759 FOR(slist_tpl<fabrik_t*>, const fab, fab_list) {
3760 fab->new_month();
3761 }
3762 INT_CHECK("simworld 1278");
3763
3764
3765 // DBG_MESSAGE("karte_t::new_month()","cities");
3766 stadt.update_weights(get_population);
3767 FOR(weighted_vector_tpl<stadt_t*>, const i, stadt) {
3768 i->new_month(need_locality_update);
3769 }
3770
3771 INT_CHECK("simworld 1282");
3772
3773 // player
3774 for(uint i=0; i<MAX_PLAYER_COUNT; i++) {
3775 if( i>=2 && last_month == 0 && !settings.is_freeplay() ) {
3776 // remove all player (but first and second) who went bankrupt during last year
3777 if( players[i] != NULL && players[i]->get_finance()->is_bancrupted() )
3778 {
3779 remove_player(i);
3780 }
3781 }
3782
3783 if( players[i] != NULL ) {
3784 // if returns false -> remove player
3785 if (!players[i]->new_month()) {
3786 remove_player(i);
3787 }
3788 }
3789 }
3790 // update the window
3791 ki_kontroll_t* playerwin = (ki_kontroll_t*)win_get_magic(magic_ki_kontroll_t);
3792 if( playerwin ) {
3793 playerwin->update_data();
3794 }
3795
3796 INT_CHECK("simworld 1289");
3797
3798 // DBG_MESSAGE("karte_t::new_month()","halts");
3799 FOR(vector_tpl<halthandle_t>, const s, haltestelle_t::get_alle_haltestellen()) {
3800 s->new_month();
3801 INT_CHECK("simworld 1877");
3802 }
3803
3804 INT_CHECK("simworld 2522");
3805 depot_t::new_month();
3806
3807 scenario->new_month();
3808
3809 // now switch year to get the right year for all timeline stuff ...
3810 if( last_month == 0 ) {
3811 new_year();
3812 INT_CHECK("simworld 1299");
3813 }
3814
3815 way_builder_t::new_month();
3816 INT_CHECK("simworld 1299");
3817
3818 recalc_average_speed();
3819 INT_CHECK("simworld 1921");
3820
3821 // update toolbars (i.e. new waytypes
3822 tool_t::update_toolbars();
3823
3824 // no autosave in networkmode or when the new world dialogue is shown
3825 if( !env_t::networkmode && env_t::autosave>0 && last_month%env_t::autosave==0 && !win_get_magic(magic_welt_gui_t) ) {
3826 char buf[128];
3827 sprintf( buf, "save/autosave%02i.sve", last_month+1 );
3828 save( buf, loadsave_t::autosave_mode, env_t::savegame_version_str, true );
3829 }
3830 }
3831
3832
new_year()3833 void karte_t::new_year()
3834 {
3835 last_year = current_month/12;
3836
3837 // advance history ...
3838 for( int hist=0; hist<karte_t::MAX_WORLD_COST; hist++ ) {
3839 for( int y=MAX_WORLD_HISTORY_YEARS-1; y>0; y-- ) {
3840 finance_history_year[y][hist] = finance_history_year[y-1][hist];
3841 }
3842 }
3843
3844 DBG_MESSAGE("karte_t::new_year()","speedbonus for %d %i, %i, %i, %i, %i, %i, %i, %i", last_year,
3845 average_speed[0], average_speed[1], average_speed[2], average_speed[3], average_speed[4], average_speed[5], average_speed[6], average_speed[7] );
3846
3847 cbuffer_t buf;
3848 buf.printf( translator::translate("Year %i has started."), last_year );
3849 msg->add_message(buf,koord::invalid,message_t::general,color_idx_to_rgb(COL_BLACK),skinverwaltung_t::neujahrsymbol->get_image_id(0));
3850
3851 FOR(vector_tpl<convoihandle_t>, const cnv, convoi_array) {
3852 cnv->new_year();
3853 }
3854
3855 for(int i=0; i<MAX_PLAYER_COUNT; i++) {
3856 if( players[i] != NULL ) {
3857 players[i]->new_year();
3858 }
3859 }
3860
3861 scenario->new_year();
3862 }
3863
3864
3865 // recalculated speed bonus for different vehicles
3866 // and takes care of all timeline stuff
recalc_average_speed()3867 void karte_t::recalc_average_speed()
3868 {
3869 // retire/allocate vehicles
3870 private_car_t::build_timeline_list(this);
3871 pedestrian_t::build_timeline_list(this);
3872
3873 for(int i=road_wt; i<=narrowgauge_wt; i++) {
3874 const int typ = i==4 ? 3 : (i-1)&7;
3875 average_speed[typ] = vehicle_builder_t::get_speedbonus( this->get_timeline_year_month(), i==4 ? air_wt : (waytype_t)i );
3876 }
3877
3878 // DBG_MESSAGE("karte_t::recalc_average_speed()","");
3879 if(use_timeline()) {
3880 for(int i=road_wt; i<=air_wt; i++) {
3881 const char *vehicle_type=NULL;
3882 switch(i) {
3883 case road_wt:
3884 vehicle_type = "road vehicle";
3885 break;
3886 case track_wt:
3887 vehicle_type = "rail car";
3888 break;
3889 case water_wt:
3890 vehicle_type = "water vehicle";
3891 break;
3892 case monorail_wt:
3893 vehicle_type = "monorail vehicle";
3894 break;
3895 case tram_wt:
3896 vehicle_type = "street car";
3897 break;
3898 case air_wt:
3899 vehicle_type = "airplane";
3900 break;
3901 case maglev_wt:
3902 vehicle_type = "maglev vehicle";
3903 break;
3904 case narrowgauge_wt:
3905 vehicle_type = "narrowgauge vehicle";
3906 break;
3907 default:
3908 // this is not a valid waytype
3909 continue;
3910 }
3911 vehicle_type = translator::translate( vehicle_type );
3912
3913 FOR(slist_tpl<vehicle_desc_t const*>, const info, vehicle_builder_t::get_info((waytype_t)i)) {
3914 const uint16 intro_month = info->get_intro_year_month();
3915 if(intro_month == current_month) {
3916 cbuffer_t buf;
3917 buf.printf( translator::translate("New %s now available:\n%s\n"), vehicle_type, translator::translate(info->get_name()) );
3918 msg->add_message(buf,koord::invalid,message_t::new_vehicle,NEW_VEHICLE,info->get_base_image());
3919 }
3920
3921 const uint16 retire_month = info->get_retire_year_month();
3922 if(retire_month == current_month) {
3923 cbuffer_t buf;
3924 buf.printf( translator::translate("Production of %s has been stopped:\n%s\n"), vehicle_type, translator::translate(info->get_name()) );
3925 msg->add_message(buf,koord::invalid,message_t::new_vehicle,NEW_VEHICLE,info->get_base_image());
3926 }
3927 }
3928 }
3929
3930 // city road (try to use always a timeline)
3931 if (way_desc_t const* city_road_test = settings.get_city_road_type(current_month) ) {
3932 city_road = city_road_test;
3933 }
3934 else {
3935 DBG_MESSAGE("karte_t::new_month()","Month %d has started", last_month);
3936 city_road = way_builder_t::weg_search(road_wt,50,get_timeline_year_month(),type_flat);
3937 }
3938
3939 }
3940 else {
3941 // defaults
3942 city_road = settings.get_city_road_type(0);
3943 if(city_road==NULL) {
3944 city_road = way_builder_t::weg_search(road_wt,50,0,type_flat);
3945 }
3946 }
3947 }
3948
3949
3950 // returns the current speed record
get_record_speed(waytype_t w) const3951 sint32 karte_t::get_record_speed( waytype_t w ) const
3952 {
3953 return records->get_record_speed(w);
3954 }
3955
3956
3957 // sets the new speed record
notify_record(convoihandle_t cnv,sint32 max_speed,koord k)3958 void karte_t::notify_record( convoihandle_t cnv, sint32 max_speed, koord k )
3959 {
3960 records->notify_record(cnv, max_speed, k, current_month);
3961 }
3962
3963
set_schedule_counter()3964 void karte_t::set_schedule_counter()
3965 {
3966 // do not call this from gui when playing in network mode!
3967 assert( (get_random_mode() & INTERACTIVE_RANDOM) == 0 );
3968
3969 schedule_counter++;
3970 }
3971
3972
step()3973 void karte_t::step()
3974 {
3975 DBG_DEBUG4("karte_t::step", "start step");
3976 uint32 time = dr_time();
3977
3978 // calculate delta_t before handling overflow in ticks
3979 uint32 delta_t = ticks - last_step_ticks;
3980
3981 // first: check for new month
3982 if(ticks > next_month_ticks) {
3983
3984 if( next_month_ticks > next_month_ticks+karte_t::ticks_per_world_month ) {
3985 // avoid overflow here ...
3986 dbg->warning("karte_t::step()", "Ticks were overflowing => reset");
3987 ticks %= karte_t::ticks_per_world_month;
3988 next_month_ticks %= karte_t::ticks_per_world_month;
3989 }
3990 next_month_ticks += karte_t::ticks_per_world_month;
3991
3992 DBG_DEBUG4("karte_t::step", "calling new_month");
3993 new_month();
3994 }
3995
3996 DBG_DEBUG4("karte_t::step", "time calculations");
3997 if( step_mode==NORMAL ) {
3998 /* Try to maintain a decent pause, with a step every 170-250 ms (~5,5 simloops/s)
3999 * Also avoid too large or negative steps
4000 */
4001
4002 // needs plausibility check?!?
4003 if(delta_t>10000) {
4004 dbg->error( "karte_t::step()", "delta_t (%li) out of bounds!", delta_t );
4005 last_step_ticks = ticks;
4006 next_step_time = time+10;
4007 return;
4008 }
4009 idle_time = 0;
4010 last_step_nr[steps%32] = ticks;
4011 next_step_time = time+(3200/get_time_multiplier());
4012 }
4013 else if( step_mode==FAST_FORWARD ) {
4014 // fast forward first: get average simloops (i.e. calculate acceleration)
4015 last_step_nr[steps%32] = dr_time();
4016 int last_5_simloops = simloops;
4017 if( last_step_nr[(steps+32-5)%32] < last_step_nr[steps%32] ) {
4018 // since 5 steps=1s
4019 last_5_simloops = (1000) / (last_step_nr[steps%32]-last_step_nr[(steps+32-5)%32]);
4020 }
4021 if( last_step_nr[(steps+1)%32] < last_step_nr[steps%32] ) {
4022 simloops = (10000*32) / (last_step_nr[steps%32]-last_step_nr[(steps+1)%32]);
4023 }
4024 // now try to approach the target speed
4025 if(last_5_simloops<env_t::max_acceleration) {
4026 if(idle_time>0) {
4027 idle_time --;
4028 }
4029 }
4030 else if(simloops>8u*env_t::max_acceleration) {
4031 if(idle_time + 10u < get_frame_time()) {
4032 idle_time ++;
4033 }
4034 }
4035 // cap it ...
4036 if( idle_time + 10u >= get_frame_time()) {
4037 idle_time = get_frame_time()-10;
4038 }
4039 next_step_time = time+idle_time;
4040 }
4041 else {
4042 // network mode
4043 }
4044 // now do the step ...
4045 last_step_ticks = ticks;
4046 steps ++;
4047
4048 // to make sure the tick counter will be updated
4049 INT_CHECK("karte_t::step");
4050
4051 // check for pending seasons change
4052 const bool season_change = pending_season_change > 0;
4053 const bool snowline_change = pending_snowline_change > 0;
4054 if( season_change || snowline_change ) {
4055 DBG_DEBUG4("karte_t::step", "pending_season_change");
4056 // process
4057 const uint32 end_count = min( cached_grid_size.x * cached_grid_size.y, tile_counter + max( 16384, cached_grid_size.x * cached_grid_size.y / 16 ) );
4058 while( tile_counter < end_count ) {
4059 plan[tile_counter].check_season_snowline( season_change, snowline_change );
4060 tile_counter++;
4061 if( (tile_counter & 0x3FF) == 0 ) {
4062 INT_CHECK("karte_t::step");
4063 }
4064 }
4065
4066 if( tile_counter >= (uint32)cached_grid_size.x * (uint32)cached_grid_size.y ) {
4067 if( season_change ) {
4068 pending_season_change--;
4069 }
4070 if( snowline_change ) {
4071 pending_snowline_change--;
4072 }
4073 tile_counter = 0;
4074 }
4075 }
4076
4077 // to make sure the tick counter will be updated
4078 INT_CHECK("karte_t::step");
4079
4080 DBG_DEBUG4("karte_t::step", "step convois");
4081 // since convois will be deleted during stepping, we need to step backwards
4082 for (size_t i = convoi_array.get_count(); i-- != 0;) {
4083 convoihandle_t cnv = convoi_array[i];
4084 cnv->step();
4085 if((i&7)==0) {
4086 INT_CHECK("simworld 1947");
4087 }
4088 }
4089
4090 // now step all towns (to generate passengers)
4091 DBG_DEBUG4("karte_t::step", "step cities");
4092 sint64 bev=0;
4093 FOR(weighted_vector_tpl<stadt_t*>, const i, stadt) {
4094 i->step(delta_t);
4095 bev += i->get_finance_history_month(0, HIST_CITICENS);
4096 }
4097
4098 // the inhabitants stuff
4099 finance_history_month[0][WORLD_CITICENS] = bev;
4100
4101 DBG_DEBUG4("karte_t::step", "step factories");
4102 FOR(slist_tpl<fabrik_t*>, const f, fab_list) {
4103 f->step(delta_t);
4104 }
4105 finance_history_year[0][WORLD_FACTORIES] = finance_history_month[0][WORLD_FACTORIES] = fab_list.get_count();
4106
4107 // step powerlines - required order: powernet, pumpe then senke
4108 DBG_DEBUG4("karte_t::step", "step poweline stuff");
4109 powernet_t::step_all(delta_t);
4110 pumpe_t::step_all(delta_t);
4111 senke_t::step_all(delta_t);
4112
4113 DBG_DEBUG4("karte_t::step", "step players");
4114 // then step all players
4115 for( int i=0; i<MAX_PLAYER_COUNT; i++ ) {
4116 if( players[i] != NULL ) {
4117 players[i]->step();
4118 }
4119 }
4120
4121 DBG_DEBUG4("karte_t::step", "step halts");
4122 haltestelle_t::step_all();
4123
4124 // ok, next step
4125 INT_CHECK("simworld 1975");
4126
4127 recalc_season_snowline(true);
4128
4129 // number of playing clients changed
4130 if( env_t::server && last_clients!=socket_list_t::get_playing_clients() ) {
4131 if( env_t::server_announce ) {
4132 // inform the master server
4133 announce_server( 1 );
4134 }
4135
4136 // check if player has left and send message
4137 for(uint32 i=0; i < socket_list_t::get_count(); i++) {
4138 socket_info_t& info = socket_list_t::get_client(i);
4139 if (info.state == socket_info_t::has_left) {
4140 nwc_nick_t::server_tools(this, i, nwc_nick_t::FAREWELL, NULL);
4141 info.state = socket_info_t::inactive;
4142 }
4143 }
4144 last_clients = socket_list_t::get_playing_clients();
4145 // add message via tool
4146 cbuffer_t buf;
4147 buf.printf("%d,", message_t::general | message_t::local_flag);
4148 buf.printf(translator::translate("Now %u clients connected.", settings.get_name_language_id()), last_clients);
4149 tool_t *tmp_tool = create_tool( TOOL_ADD_MESSAGE | SIMPLE_TOOL );
4150 tmp_tool->set_default_param( buf );
4151 set_tool( tmp_tool, NULL );
4152 // since init always returns false, it is safe to delete immediately
4153 delete tmp_tool;
4154 }
4155
4156 if( get_scenario()->is_scripted() ) {
4157 get_scenario()->step();
4158 }
4159 DBG_DEBUG4("karte_t::step", "end");
4160 }
4161
4162
4163 // recalculates world statistics for older versions
restore_history(bool restore_transported_only)4164 void karte_t::restore_history(bool restore_transported_only)
4165 {
4166 // update total transported, including passenger and mail
4167 for( int m=min(MAX_WORLD_HISTORY_MONTHS,MAX_PLAYER_HISTORY_MONTHS)-1; m>0; m-- ) {
4168 sint64 transported = 0;
4169 for( uint i=0; i<MAX_PLAYER_COUNT; i++ ) {
4170 if( players[i]!=NULL ) {
4171 players[i]->get_finance()->calc_finance_history();
4172 transported += players[i]->get_finance()->get_history_veh_month( TT_ALL, m, ATV_TRANSPORTED );
4173 }
4174 }
4175 finance_history_month[m][WORLD_TRANSPORTED_GOODS] = max(transported, finance_history_month[m][WORLD_TRANSPORTED_GOODS]);
4176 }
4177 for( int y=min(MAX_WORLD_HISTORY_YEARS,MAX_CITY_HISTORY_YEARS)-1; y>0; y-- ) {
4178 sint64 transported_year = 0;
4179 for( uint i=0; i<MAX_PLAYER_COUNT; i++ ) {
4180 if( players[i] ) {
4181 transported_year += players[i]->get_finance()->get_history_veh_year( TT_ALL, y, ATV_TRANSPORTED );
4182 }
4183 }
4184 finance_history_year[y][WORLD_TRANSPORTED_GOODS] = max(transported_year, finance_history_year[y][WORLD_TRANSPORTED_GOODS]);
4185 }
4186 if (restore_transported_only) {
4187 return;
4188 }
4189
4190 last_month_bev = -1;
4191 for( int m=12-1; m>0; m-- ) {
4192 // now step all towns (to generate passengers)
4193 sint64 bev=0;
4194 sint64 total_pas = 1, trans_pas = 0;
4195 sint64 total_mail = 1, trans_mail = 0;
4196 sint64 total_goods = 1, supplied_goods = 0;
4197 FOR(weighted_vector_tpl<stadt_t*>, const i, stadt) {
4198 bev += i->get_finance_history_month(m, HIST_CITICENS);
4199 trans_pas += i->get_finance_history_month(m, HIST_PAS_TRANSPORTED);
4200 total_pas += i->get_finance_history_month(m, HIST_PAS_GENERATED);
4201 trans_mail += i->get_finance_history_month(m, HIST_MAIL_TRANSPORTED);
4202 total_mail += i->get_finance_history_month(m, HIST_MAIL_GENERATED);
4203 supplied_goods += i->get_finance_history_month(m, HIST_GOODS_RECEIVED);
4204 total_goods += i->get_finance_history_month(m, HIST_GOODS_NEEDED);
4205 }
4206
4207 // the inhabitants stuff
4208 if(last_month_bev == -1) {
4209 last_month_bev = bev;
4210 }
4211 finance_history_month[m][WORLD_GROWTH] = bev-last_month_bev;
4212 finance_history_month[m][WORLD_CITICENS] = bev;
4213 last_month_bev = bev;
4214
4215 // transportation ratio and total number
4216 finance_history_month[m][WORLD_PAS_RATIO] = (10000*trans_pas)/total_pas;
4217 finance_history_month[m][WORLD_PAS_GENERATED] = total_pas-1;
4218 finance_history_month[m][WORLD_MAIL_RATIO] = (10000*trans_mail)/total_mail;
4219 finance_history_month[m][WORLD_MAIL_GENERATED] = total_mail-1;
4220 finance_history_month[m][WORLD_GOODS_RATIO] = (10000*supplied_goods)/total_goods;
4221 }
4222
4223 sint64 bev_last_year = -1;
4224 for( int y=min(MAX_WORLD_HISTORY_YEARS,MAX_CITY_HISTORY_YEARS)-1; y>0; y-- ) {
4225 // now step all towns (to generate passengers)
4226 sint64 bev=0;
4227 sint64 total_pas_year = 1, trans_pas_year = 0;
4228 sint64 total_mail_year = 1, trans_mail_year = 0;
4229 sint64 total_goods_year = 1, supplied_goods_year = 0;
4230 FOR(weighted_vector_tpl<stadt_t*>, const i, stadt) {
4231 bev += i->get_finance_history_year(y, HIST_CITICENS);
4232 trans_pas_year += i->get_finance_history_year(y, HIST_PAS_TRANSPORTED);
4233 total_pas_year += i->get_finance_history_year(y, HIST_PAS_GENERATED);
4234 trans_mail_year += i->get_finance_history_year(y, HIST_MAIL_TRANSPORTED);
4235 total_mail_year += i->get_finance_history_year(y, HIST_MAIL_GENERATED);
4236 supplied_goods_year += i->get_finance_history_year(y, HIST_GOODS_RECEIVED);
4237 total_goods_year += i->get_finance_history_year(y, HIST_GOODS_NEEDED);
4238 }
4239
4240 // the inhabitants stuff
4241 if(bev_last_year == -1) {
4242 bev_last_year = bev;
4243 }
4244 finance_history_year[y][WORLD_GROWTH] = bev-bev_last_year;
4245 finance_history_year[y][WORLD_CITICENS] = bev;
4246 bev_last_year = bev;
4247
4248 // transportation ratio and total number
4249 finance_history_year[y][WORLD_PAS_RATIO] = (10000*trans_pas_year)/total_pas_year;
4250 finance_history_year[y][WORLD_PAS_GENERATED] = total_pas_year-1;
4251 finance_history_year[y][WORLD_MAIL_RATIO] = (10000*trans_mail_year)/total_mail_year;
4252 finance_history_year[y][WORLD_MAIL_GENERATED] = total_mail_year-1;
4253 finance_history_year[y][WORLD_GOODS_RATIO] = (10000*supplied_goods_year)/total_goods_year;
4254 }
4255
4256 // fix current month/year
4257 update_history();
4258 }
4259
4260
update_history()4261 void karte_t::update_history()
4262 {
4263 finance_history_year[0][WORLD_CONVOIS] = finance_history_month[0][WORLD_CONVOIS] = convoi_array.get_count();
4264 finance_history_year[0][WORLD_FACTORIES] = finance_history_month[0][WORLD_FACTORIES] = fab_list.get_count();
4265
4266 // now step all towns (to generate passengers)
4267 sint64 bev=0;
4268 sint64 total_pas = 1, trans_pas = 0;
4269 sint64 total_mail = 1, trans_mail = 0;
4270 sint64 total_goods = 1, supplied_goods = 0;
4271 sint64 total_pas_year = 1, trans_pas_year = 0;
4272 sint64 total_mail_year = 1, trans_mail_year = 0;
4273 sint64 total_goods_year = 1, supplied_goods_year = 0;
4274 FOR(weighted_vector_tpl<stadt_t*>, const i, stadt) {
4275 bev += i->get_finance_history_month(0, HIST_CITICENS);
4276 trans_pas += i->get_finance_history_month(0, HIST_PAS_TRANSPORTED);
4277 total_pas += i->get_finance_history_month(0, HIST_PAS_GENERATED);
4278 trans_mail += i->get_finance_history_month(0, HIST_MAIL_TRANSPORTED);
4279 total_mail += i->get_finance_history_month(0, HIST_MAIL_GENERATED);
4280 supplied_goods += i->get_finance_history_month(0, HIST_GOODS_RECEIVED);
4281 total_goods += i->get_finance_history_month(0, HIST_GOODS_NEEDED);
4282 trans_pas_year += i->get_finance_history_year( 0, HIST_PAS_TRANSPORTED);
4283 total_pas_year += i->get_finance_history_year( 0, HIST_PAS_GENERATED);
4284 trans_mail_year += i->get_finance_history_year( 0, HIST_MAIL_TRANSPORTED);
4285 total_mail_year += i->get_finance_history_year( 0, HIST_MAIL_GENERATED);
4286 supplied_goods_year += i->get_finance_history_year( 0, HIST_GOODS_RECEIVED);
4287 total_goods_year += i->get_finance_history_year( 0, HIST_GOODS_NEEDED);
4288 }
4289
4290 finance_history_month[0][WORLD_GROWTH] = bev-last_month_bev;
4291 finance_history_year[0][WORLD_GROWTH] = bev - (finance_history_year[1][WORLD_CITICENS]==0 ? finance_history_month[0][WORLD_CITICENS] : finance_history_year[1][WORLD_CITICENS]);
4292
4293 // the inhabitants stuff
4294 finance_history_year[0][WORLD_TOWNS] = finance_history_month[0][WORLD_TOWNS] = stadt.get_count();
4295 finance_history_year[0][WORLD_CITICENS] = finance_history_month[0][WORLD_CITICENS] = bev;
4296 finance_history_month[0][WORLD_GROWTH] = bev-last_month_bev;
4297 finance_history_year[0][WORLD_GROWTH] = bev - (finance_history_year[1][WORLD_CITICENS]==0 ? finance_history_month[0][WORLD_CITICENS] : finance_history_year[1][WORLD_CITICENS]);
4298
4299 // transportation ratio and total number
4300 finance_history_month[0][WORLD_PAS_RATIO] = (10000*trans_pas)/total_pas;
4301 finance_history_month[0][WORLD_PAS_GENERATED] = total_pas-1;
4302 finance_history_month[0][WORLD_MAIL_RATIO] = (10000*trans_mail)/total_mail;
4303 finance_history_month[0][WORLD_MAIL_GENERATED] = total_mail-1;
4304 finance_history_month[0][WORLD_GOODS_RATIO] = (10000*supplied_goods)/total_goods;
4305
4306 finance_history_year[0][WORLD_PAS_RATIO] = (10000*trans_pas_year)/total_pas_year;
4307 finance_history_year[0][WORLD_PAS_GENERATED] = total_pas_year-1;
4308 finance_history_year[0][WORLD_MAIL_RATIO] = (10000*trans_mail_year)/total_mail_year;
4309 finance_history_year[0][WORLD_MAIL_GENERATED] = total_mail_year-1;
4310 finance_history_year[0][WORLD_GOODS_RATIO] = (10000*supplied_goods_year)/total_goods_year;
4311
4312 // update total transported, including passenger and mail
4313 sint64 transported = 0;
4314 sint64 transported_year = 0;
4315 for( uint i=0; i<MAX_PLAYER_COUNT; i++ ) {
4316 if( players[i]!=NULL ) {
4317 players[i]->get_finance()->calc_finance_history();
4318 transported += players[i]->get_finance()->get_history_veh_month( TT_ALL, 0, ATV_TRANSPORTED_GOOD );
4319 transported_year += players[i]->get_finance()->get_history_veh_year( TT_ALL, 0, ATV_TRANSPORTED_GOOD );
4320 }
4321 }
4322 finance_history_month[0][WORLD_TRANSPORTED_GOODS] = transported;
4323 finance_history_year[0][WORLD_TRANSPORTED_GOODS] = transported_year;
4324 }
4325
4326
median(sint8 a,sint8 b,sint8 c)4327 static sint8 median( sint8 a, sint8 b, sint8 c )
4328 {
4329 #if 0
4330 if( a==b || a==c ) {
4331 return a;
4332 }
4333 else if( b==c ) {
4334 return b;
4335 }
4336 else {
4337 // noting matches
4338 // return (3*128+1 + a+b+c)/3-128;
4339 return -128;
4340 }
4341 #elif 0
4342 if( a<=b ) {
4343 return b<=c ? b : max(a,c);
4344 }
4345 else {
4346 return b>c ? b : min(a,c);
4347 }
4348 #else
4349 return (6*128+3 + a+a+b+b+c+c)/6-128;
4350 #endif
4351 }
4352
4353
recalc_natural_slope(const koord k,sint8 & new_height) const4354 uint8 karte_t::recalc_natural_slope( const koord k, sint8 &new_height ) const
4355 {
4356 grund_t *gr = lookup_kartenboden(k);
4357 if(!gr) {
4358 return slope_t::flat;
4359 }
4360 else {
4361 const sint8 max_hdiff = ground_desc_t::double_grounds ? 2 : 1;
4362
4363 sint8 corner_height[4];
4364
4365 // get neighbour corner heights
4366 sint8 neighbour_height[8][4];
4367 get_neighbour_heights( k, neighbour_height );
4368
4369 //check whether neighbours are foundations
4370 bool neighbour_fundament[8];
4371 for( int i = 0; i < 8; i++ ) {
4372 grund_t *gr2 = lookup_kartenboden( k + koord::neighbours[i] );
4373 neighbour_fundament[i] = (gr2 && gr2->get_typ() == grund_t::fundament);
4374 }
4375
4376 for( uint8 i = 0; i < 4; i++ ) { // 0 = sw, 1 = se etc.
4377 // corner_sw (i=0): tests vs neighbour 1:w (corner 2 j=1),2:sw (corner 3) and 3:s (corner 4)
4378 // corner_se (i=1): tests vs neighbour 3:s (corner 3 j=2),4:se (corner 4) and 5:e (corner 1)
4379 // corner_ne (i=2): tests vs neighbour 5:e (corner 4 j=3),6:ne (corner 1) and 7:n (corner 2)
4380 // corner_nw (i=3): tests vs neighbour 7:n (corner 1 j=0),0:nw (corner 2) and 1:w (corner 3)
4381
4382 sint16 median_height = 0;
4383 uint8 natural_corners = 0;
4384 for( int j = 1; j < 4; j++ ) {
4385 if( !neighbour_fundament[(i * 2 + j) & 7] ) {
4386 natural_corners++;
4387 median_height += neighbour_height[(i * 2 + j) & 7][(i + j) & 3];
4388 }
4389 }
4390 switch( natural_corners ) {
4391 case 1: {
4392 corner_height[i] = (sint8)median_height;
4393 break;
4394 }
4395 case 2: {
4396 corner_height[i] = median_height >> 1;
4397 break;
4398 }
4399 default: {
4400 // take the average of all 3 corners (if no natural corners just use the artificial ones anyway)
4401 corner_height[i] = median( neighbour_height[(i * 2 + 1) & 7][(i + 1) & 3], neighbour_height[(i * 2 + 2) & 7][(i + 2) & 3], neighbour_height[(i * 2 + 3) & 7][(i + 3) & 3] );
4402 break;
4403 }
4404 }
4405 }
4406
4407 // new height of that tile ...
4408 sint8 min_height = min( min( corner_height[0], corner_height[1] ), min( corner_height[2], corner_height[3] ) );
4409 sint8 max_height = max( max( corner_height[0], corner_height[1] ), max( corner_height[2], corner_height[3] ) );
4410 /* check for an artificial slope on a steep sidewall */
4411 bool not_ok = abs( max_height - min_height ) > max_hdiff || min_height == -128;
4412
4413 sint8 old_height = gr->get_hoehe();
4414 new_height = min_height;
4415
4416 // now we must make clear, that there is no ground above/below the slope
4417 if( old_height!=new_height ) {
4418 not_ok |= lookup(koord3d(k,new_height))!=NULL;
4419 if( old_height > new_height ) {
4420 not_ok |= lookup(koord3d(k,old_height-1))!=NULL;
4421 }
4422 if( old_height < new_height ) {
4423 not_ok |= lookup(koord3d(k,old_height+1))!=NULL;
4424 }
4425 }
4426
4427 if( not_ok ) {
4428 /* difference too high or ground above/below
4429 * we just keep it as it was ...
4430 */
4431 new_height = old_height;
4432 return gr->get_grund_hang();
4433 }
4434
4435 const sint16 d1 = min( corner_height[0] - new_height, max_hdiff );
4436 const sint16 d2 = min( corner_height[1] - new_height, max_hdiff );
4437 const sint16 d3 = min( corner_height[2] - new_height, max_hdiff );
4438 const sint16 d4 = min( corner_height[3] - new_height, max_hdiff );
4439 return d4 * 27 + d3 * 9 + d2 * 3 + d1;
4440 }
4441 return 0;
4442 }
4443
4444
calc_natural_slope(const koord k) const4445 uint8 karte_t::calc_natural_slope( const koord k ) const
4446 {
4447 if(is_within_grid_limits(k.x, k.y)) {
4448
4449 const sint8 * p = &grid_hgts[k.x + k.y*(sint32)(get_size().x+1)];
4450
4451 const int h1 = *p;
4452 const int h2 = *(p+1);
4453 const int h3 = *(p+get_size().x+2);
4454 const int h4 = *(p+get_size().x+1);
4455
4456 const int mini = min(min(h1,h2), min(h3,h4));
4457
4458 const int d1=h1-mini;
4459 const int d2=h2-mini;
4460 const int d3=h3-mini;
4461 const int d4=h4-mini;
4462
4463 return d1 * 27 + d2 * 9 + d3 * 3 + d4;
4464 }
4465 return 0;
4466 }
4467
4468
is_water(koord k,koord dim) const4469 bool karte_t::is_water(koord k, koord dim) const
4470 {
4471 koord k_check;
4472 for( k_check.x = k.x; k_check.x < k.x + dim.x; k_check.x++ ) {
4473 for( k_check.y = k.y; k_check.y < k.y + dim.y; k_check.y++ ) {
4474 if( !is_within_grid_limits( k_check + koord(1, 1) ) || max_hgt(k_check) > get_water_hgt(k_check) ) {
4475 return false;
4476 }
4477 }
4478 }
4479 return true;
4480 }
4481
4482
square_is_free(koord k,sint16 w,sint16 h,int * last_y,climate_bits cl) const4483 bool karte_t::square_is_free(koord k, sint16 w, sint16 h, int *last_y, climate_bits cl) const
4484 {
4485 if(k.x < 0 || k.y < 0 || k.x+w > get_size().x || k.y+h > get_size().y) {
4486 return false;
4487 }
4488
4489 grund_t *gr = lookup_kartenboden(k);
4490 const sint16 platz_h = gr->get_grund_hang() ? max_hgt(k) : gr->get_hoehe(); // remember the max height of the first tile
4491
4492 koord k_check;
4493 for(k_check.y=k.y+h-1; k_check.y>=k.y; k_check.y--) {
4494 for(k_check.x=k.x; k_check.x<k.x+w; k_check.x++) {
4495 const grund_t *gr = lookup_kartenboden(k_check);
4496
4497 // we can built, if: max height all the same, everything removable and no buildings there
4498 slope_t::type slope = gr->get_grund_hang();
4499 sint8 max_height = gr->get_hoehe() + slope_t::max_diff(slope);
4500 climate test_climate = get_climate(k_check);
4501 if( cl & (1 << water_climate) && test_climate != water_climate ) {
4502 bool neighbour_water = false;
4503 for(int i=0; i<8 && !neighbour_water; i++) {
4504 if( is_within_limits(k_check + koord::neighbours[i]) && get_climate( k_check + koord::neighbours[i] ) == water_climate ) {
4505 neighbour_water = true;
4506 }
4507 }
4508 if( neighbour_water ) {
4509 test_climate = water_climate;
4510 }
4511 }
4512 if( platz_h != max_height || !gr->ist_natur() || gr->kann_alle_obj_entfernen(NULL) != NULL ||
4513 (cl & (1 << test_climate)) == 0 || ( slope && (lookup( gr->get_pos()+koord3d(0,0,1) ) ||
4514 (slope_t::max_diff(slope)==2 && lookup( gr->get_pos()+koord3d(0,0,2) )) )) ) {
4515 if( last_y ) {
4516 *last_y = k_check.y;
4517 }
4518 return false;
4519 }
4520 }
4521 }
4522 return true;
4523 }
4524
4525
find_squares(sint16 w,sint16 h,climate_bits cl,sint16 old_x,sint16 old_y) const4526 slist_tpl<koord> *karte_t::find_squares(sint16 w, sint16 h, climate_bits cl, sint16 old_x, sint16 old_y) const
4527 {
4528 slist_tpl<koord> * list = new slist_tpl<koord>();
4529 koord start;
4530 int last_y;
4531
4532 DBG_DEBUG("karte_t::finde_plaetze()","for size (%i,%i) in map (%i,%i)",w,h,get_size().x,get_size().y );
4533 for(start.x=0; start.x<get_size().x-w; start.x++) {
4534 for(start.y=start.x<old_x?old_y:0; start.y<get_size().y-h; start.y++) {
4535 if(square_is_free(start, w, h, &last_y, cl)) {
4536 list->insert(start);
4537 }
4538 else {
4539 // Optimiert fuer groessere Felder, hehe!
4540 // Die Idee: wenn bei 2x2 die untere Reihe nicht geht, koennen
4541 // wir gleich 2 tiefer weitermachen! V. Meyer
4542 start.y = last_y;
4543 }
4544 }
4545 }
4546 return list;
4547 }
4548
4549
4550 /**
4551 * Play a sound, but only if near enough.
4552 * Sounds are muted by distance and clipped completely if too far away.
4553 *
4554 * @author Hj. Malthaner
4555 */
play_sound_area_clipped(koord const k,uint16 const idx) const4556 bool karte_t::play_sound_area_clipped(koord const k, uint16 const idx) const
4557 {
4558 if(is_sound && zeiger) {
4559 const int dist = koord_distance( k, zeiger->get_pos() );
4560
4561 if(dist < 100) {
4562 int xw = (2*display_get_width())/get_tile_raster_width();
4563 int yw = (4*display_get_height())/get_tile_raster_width();
4564
4565 uint8 const volume = (uint8)(255U * (xw + yw) / (xw + yw + 64 * dist));
4566 if (volume > 8) {
4567 sound_play(idx, volume);
4568 }
4569 }
4570 return dist < 25;
4571 }
4572 return false;
4573 }
4574
4575
save(const char * filename,loadsave_t::mode_t savemode,const char * version_str,bool silent)4576 void karte_t::save(const char *filename, loadsave_t::mode_t savemode, const char *version_str, bool silent )
4577 {
4578 DBG_MESSAGE("karte_t::save()", "saving game to '%s'", filename);
4579 loadsave_t file;
4580 std::string savename = filename;
4581 savename[savename.length()-1] = '_';
4582
4583 display_show_load_pointer( true );
4584 if(!file.wr_open( savename.c_str(), savemode, env_t::objfilename.c_str(), version_str )) {
4585 create_win(new news_img("Kann Spielstand\nnicht speichern.\n"), w_info, magic_none);
4586 dbg->error("karte_t::save()","cannot open file for writing! check permissions!");
4587 }
4588 else {
4589 save(&file,silent);
4590 const char *success = file.close();
4591 if(success) {
4592 static char err_str[512];
4593 sprintf( err_str, translator::translate("Error during saving:\n%s"), success );
4594 create_win( new news_img(err_str), w_time_delete, magic_none);
4595 }
4596 else {
4597 dr_rename( savename.c_str(), filename );
4598 if(!silent) {
4599 create_win( new news_img("Spielstand wurde\ngespeichert!\n"), w_time_delete, magic_none);
4600 // update the filename, if no autosave
4601 settings.set_filename(filename);
4602 }
4603 }
4604 reset_interaction();
4605 }
4606 display_show_load_pointer( false );
4607 }
4608
4609
save(loadsave_t * file,bool silent)4610 void karte_t::save(loadsave_t *file,bool silent)
4611 {
4612 bool needs_redraw = false;
4613
4614 loadingscreen_t *ls = NULL;
4615 DBG_MESSAGE("karte_t::save(loadsave_t *file)", "start");
4616 if(!silent) {
4617 ls = new loadingscreen_t( translator::translate("Saving map ..."), get_size().y );
4618 }
4619
4620 // rotate the map until it can be saved completely
4621 for( int i=0; i<4 && nosave_warning; i++ ) {
4622 rotate90();
4623 needs_redraw = true;
4624 }
4625 // seems not successful
4626 if(nosave_warning) {
4627 // but then we try to rotate until only warnings => some buildings may be broken, but factories should be fine
4628 for( int i=0; i<4 && nosave; i++ ) {
4629 rotate90();
4630 needs_redraw = true;
4631 }
4632 if( nosave ) {
4633 dbg->error( "karte_t::save()","Map cannot be saved in any rotation!" );
4634 create_win( new news_img("Map may be not saveable in any rotation!"), w_info, magic_none);
4635 // still broken, but we try anyway to save it ...
4636 }
4637 }
4638 // only broken buildings => just warn
4639 if(nosave_warning) {
4640 dbg->error( "karte_t::save()","Some buildings may be broken by saving!" );
4641 }
4642
4643 /* If the current tool is a two_click_tool_t, call cleanup() in order to delete dummy grounds (tunnel + monorail preview)
4644 * THIS MUST NOT BE DONE IN NETWORK MODE!
4645 */
4646 for( uint8 sp_nr=0; sp_nr<MAX_PLAYER_COUNT; sp_nr++ ) {
4647 if (two_click_tool_t* tool = dynamic_cast<two_click_tool_t*>(selected_tool[sp_nr])) {
4648 tool->cleanup();
4649 }
4650 }
4651
4652 file->set_buffered(true);
4653
4654 // do not set value for empty player
4655 uint8 old_players[MAX_PLAYER_COUNT];
4656 for( int i=0; i<MAX_PLAYER_COUNT; i++ ) {
4657 old_players[i] = settings.get_player_type(i);
4658 if( players[i]==NULL ) {
4659 settings.set_player_type(i, player_t::EMPTY);
4660 }
4661 }
4662 settings.rdwr(file);
4663 for( int i=0; i<MAX_PLAYER_COUNT; i++ ) {
4664 settings.set_player_type(i, old_players[i]);
4665 }
4666
4667 file->rdwr_long(ticks);
4668 file->rdwr_long(last_month);
4669 file->rdwr_long(last_year);
4670
4671 // rdwr satic states
4672 senke_t::static_rdwr(file);
4673
4674 // rdwr cityrules for networkgames
4675 if(file->is_version_atleast(102, 3)) {
4676 bool do_rdwr = env_t::networkmode;
4677 file->rdwr_bool(do_rdwr);
4678 if (do_rdwr) {
4679 stadt_t::cityrules_rdwr(file);
4680 if(file->is_version_atleast(102, 4)) {
4681 vehicle_builder_t::rdwr_speedbonus(file);
4682 }
4683 }
4684 }
4685
4686 FOR(weighted_vector_tpl<stadt_t*>, const i, stadt) {
4687 i->rdwr(file);
4688 if(silent) {
4689 INT_CHECK("saving");
4690 }
4691 }
4692 DBG_MESSAGE("karte_t::save(loadsave_t *file)", "saved cities ok");
4693
4694 for(int j=0; j<get_size().y; j++) {
4695 for(int i=0; i<get_size().x; i++) {
4696 plan[i+j*cached_grid_size.x].rdwr(file, koord(i,j) );
4697 }
4698 if(silent) {
4699 INT_CHECK("saving");
4700 }
4701 else {
4702 ls->set_progress(j);
4703 }
4704 }
4705 DBG_MESSAGE("karte_t::save(loadsave_t *file)", "saved tiles");
4706
4707 if( file->is_version_less(102, 2) ) {
4708 // not needed any more
4709 for(int j=0; j<(get_size().y+1)*(sint32)(get_size().x+1); j++) {
4710 file->rdwr_byte(grid_hgts[j]);
4711 }
4712 DBG_MESSAGE("karte_t::save(loadsave_t *file)", "saved hgt");
4713 }
4714
4715 sint32 fabs = fab_list.get_count();
4716 file->rdwr_long(fabs);
4717 FOR(slist_tpl<fabrik_t*>, const f, fab_list) {
4718 f->rdwr(file);
4719 if(silent) {
4720 INT_CHECK("saving");
4721 }
4722 }
4723 DBG_MESSAGE("karte_t::save(loadsave_t *file)", "saved fabs");
4724
4725 sint32 haltcount=haltestelle_t::get_alle_haltestellen().get_count();
4726 file->rdwr_long(haltcount);
4727 FOR(vector_tpl<halthandle_t>, const s, haltestelle_t::get_alle_haltestellen()) {
4728 s->rdwr(file);
4729 }
4730 DBG_MESSAGE("karte_t::save(loadsave_t *file)", "saved stops");
4731
4732 // save number of convois
4733 if( file->is_version_atleast(101, 0) ) {
4734 uint16 i=convoi_array.get_count();
4735 file->rdwr_short(i);
4736 }
4737 FOR(vector_tpl<convoihandle_t>, const cnv, convoi_array) {
4738 // one MUST NOT call INT_CHECK here or else the convoi will be broken during reloading!
4739 cnv->rdwr(file);
4740 }
4741 if( file->is_version_less(101, 0) ) {
4742 file->wr_obj_id("Ende Convois");
4743 }
4744 if(silent) {
4745 INT_CHECK("saving");
4746 }
4747 DBG_MESSAGE("karte_t::save(loadsave_t *file)", "saved %i convois",convoi_array.get_count());
4748
4749 for(int i=0; i<MAX_PLAYER_COUNT; i++) {
4750 // **** REMOVE IF SOON! *********
4751 if(file->is_version_less(101, 0)) {
4752 if( i<8 ) {
4753 if( players[i] ) {
4754 players[i]->rdwr(file);
4755 }
4756 else {
4757 // simulate old ones ...
4758 player_t *player = new player_t( i );
4759 player->rdwr(file);
4760 delete player;
4761 }
4762 }
4763 }
4764 else {
4765 if( players[i] ) {
4766 players[i]->rdwr(file);
4767 }
4768 }
4769 }
4770 DBG_MESSAGE("karte_t::save(loadsave_t *file)", "saved players");
4771
4772 // saving messages
4773 if( file->is_version_atleast(102, 5) ) {
4774 msg->rdwr(file);
4775 }
4776 DBG_MESSAGE("karte_t::save(loadsave_t *file)", "saved messages");
4777
4778 // centered on what?
4779 sint32 dummy = viewport->get_world_position().x;
4780 file->rdwr_long(dummy);
4781 dummy = viewport->get_world_position().y;
4782 file->rdwr_long(dummy);
4783
4784 if(file->is_version_atleast(99, 18)) {
4785 // most recent version is 99018
4786 for (int year = 0; year</*MAX_WORLD_HISTORY_YEARS*/12; year++) {
4787 for (int cost_type = 0; cost_type</*MAX_WORLD_COST*/12; cost_type++) {
4788 file->rdwr_longlong(finance_history_year[year][cost_type]);
4789 }
4790 }
4791 for (int month = 0;month</*MAX_WORLD_HISTORY_MONTHS*/12;month++) {
4792 for (int cost_type = 0; cost_type</*MAX_WORLD_COST*/12; cost_type++) {
4793 file->rdwr_longlong(finance_history_month[month][cost_type]);
4794 }
4795 }
4796 }
4797
4798 // finally a possible scenario
4799 scenario->rdwr( file );
4800
4801 if( file->is_version_atleast(112, 8) ) {
4802 xml_tag_t t( file, "motd_t" );
4803
4804 dr_chdir( env_t::user_dir );
4805 // maybe show message about server
4806 DBG_MESSAGE("karte_t::save(loadsave_t *file)", "motd filename %s", env_t::server_motd_filename.c_str() );
4807 if( FILE *fmotd = dr_fopen( env_t::server_motd_filename.c_str(), "r" ) ) {
4808 struct stat st;
4809 stat( env_t::server_motd_filename.c_str(), &st );
4810 sint32 len = min( 32760, st.st_size+1 );
4811 char *motd = (char *)malloc( len );
4812 fread( motd, len-1, 1, fmotd );
4813 fclose( fmotd );
4814 motd[len-1] = 0;
4815 file->rdwr_str( motd, len );
4816 free( motd );
4817 }
4818 else {
4819 // no message
4820 plainstring motd("");
4821 file->rdwr_str( motd );
4822 }
4823 }
4824
4825 // save all open windows (upon request)
4826 file->rdwr_byte( active_player_nr );
4827 rdwr_all_win(file);
4828
4829 file->set_buffered(false);
4830
4831 if(needs_redraw) {
4832 update_map();
4833 }
4834 if(!silent) {
4835 delete ls;
4836 }
4837 }
4838
4839
4840 // store missing obj during load and their severity
add_missing_paks(const char * name,missing_level_t level)4841 void karte_t::add_missing_paks( const char *name, missing_level_t level )
4842 {
4843 if( missing_pak_names.get( name )==NOT_MISSING ) {
4844 missing_pak_names.put( strdup(name), level );
4845 }
4846 }
4847
4848
4849
switch_server(bool start_server,bool port_forwarding)4850 void karte_t::switch_server( bool start_server, bool port_forwarding )
4851 {
4852 if( !start_server ) {
4853 // end current server session
4854
4855 if( env_t::server ) {
4856 // take down server
4857 announce_server(2);
4858 remove_port_forwarding( env_t::server );
4859 }
4860 network_core_shutdown();
4861 env_t::easy_server = 0;
4862
4863 clear_random_mode( INTERACTIVE_RANDOM );
4864 step_mode = NORMAL;
4865 reset_timer();
4866 clear_command_queue();
4867 last_active_player_nr = active_player_nr;
4868
4869 if( port_forwarding && env_t::fps<=15 ) {
4870 env_t::fps = 25;
4871 }
4872 }
4873 else {
4874
4875 // convert current game into server game
4876 if( env_t::server ) {
4877 // kick all clients out
4878 network_reset_server();
4879 }
4880 else {
4881 // now start a server with defaults
4882 env_t::networkmode = network_init_server( env_t::server_port );
4883 if( env_t::networkmode ) {
4884
4885 // query IP and try to open ports on router
4886 char IP[256], altIP[256];
4887 if( port_forwarding && prepare_for_server( IP, altIP, env_t::server_port ) ) {
4888 // we have forwarded a port in router, so we can continue
4889 env_t::server_dns = IP;
4890 if( env_t::server_name.empty() ) {
4891 env_t::server_name = std::string("Server at ")+IP;
4892 }
4893 env_t::server_alt_dns = altIP;
4894 env_t::server_announce = 1;
4895 env_t::easy_server = 1;
4896 if( env_t::fps>15 ) {
4897 env_t::fps = 15;
4898 }
4899 }
4900
4901 reset_timer();
4902 clear_command_queue();
4903
4904 // meaningless to use a locked map; there are passwords now
4905 settings.set_allow_player_change(true);
4906 // language of map becomes server language
4907 settings.set_name_language_iso(translator::get_lang()->iso_base);
4908
4909 nwc_auth_player_t::init_player_lock_server(this);
4910
4911 last_active_player_nr = active_player_nr;
4912 }
4913 }
4914 }
4915 }
4916
4917
4918
4919 // just the preliminaries, opens the file, checks the versions ...
load(const char * filename)4920 bool karte_t::load(const char *filename)
4921 {
4922 cbuffer_t name;
4923 bool ok = false;
4924 bool restore_player_nr = false;
4925 bool server_reload_pwd_hashes = false;
4926 mute_sound(true);
4927 display_show_load_pointer(true);
4928 loadsave_t file;
4929
4930 // clear hash table with missing paks (may cause some small memory loss though)
4931 missing_pak_names.clear();
4932
4933 DBG_MESSAGE("karte_t::load", "loading game from '%s'", filename);
4934
4935 // reloading same game? Remember pos
4936 const koord oldpos = settings.get_filename()[0]>0 && strncmp(filename,settings.get_filename(),strlen(settings.get_filename()))==0 ? viewport->get_world_position() : koord::invalid;
4937
4938 if( strstart(filename, "net:") ) {
4939
4940 // probably finish network mode?
4941 if( env_t::networkmode ) {
4942 network_core_shutdown();
4943 }
4944 dr_chdir( env_t::user_dir );
4945 const char *err = network_connect(filename+4, this);
4946 if(err) {
4947 create_win( new news_img(err), w_info, magic_none );
4948 display_show_load_pointer(false);
4949 step_mode = NORMAL;
4950 return false;
4951 }
4952 else {
4953 env_t::networkmode = true;
4954 name.printf( "client%i-network.sve", network_get_client_id() );
4955 restore_player_nr = strcmp( last_network_game.c_str(), filename )==0;
4956 if( !restore_player_nr ) {
4957 last_network_game = filename;
4958 }
4959 }
4960 }
4961 else {
4962 // probably finish network mode first?
4963 if( env_t::networkmode ) {
4964 if( env_t::server ) {
4965 char fn[256];
4966 sprintf( fn, "server%d-network.sve", env_t::server );
4967 if( strcmp(filename, fn) != 0 ) {
4968 // stay in networkmode, but disconnect clients
4969 dbg->warning("karte_t::load","disconnecting all clients");
4970 }
4971 else {
4972 // read password hashes from separate file
4973 // as they are not in the savegame to avoid sending them over network
4974 server_reload_pwd_hashes = true;
4975 }
4976 }
4977 else {
4978 // check, if reload during sync
4979 char fn[256];
4980 sprintf( fn, "client%i-network.sve", network_get_client_id() );
4981 if( strcmp(filename,fn)!=0 ) {
4982 // no sync => finish network mode
4983 dbg->warning("karte_t::load","finished network mode");
4984 network_disconnect();
4985 finish_loop = false; // do not trigger intro screen
4986 // closing the socket will tell the server, I am away too
4987 }
4988 }
4989 }
4990 name.append(filename);
4991 }
4992
4993 if(!file.rd_open(name)) {
4994
4995 if( file.get_version_int()==0 || file.get_version_int()>loadsave_t::int_version(SAVEGAME_VER_NR, NULL ) ) {
4996 dbg->warning("karte_t::load()", translator::translate("WRONGSAVE") );
4997 create_win( new news_img("WRONGSAVE"), w_info, magic_none );
4998 }
4999 else {
5000 dbg->warning("karte_t::load()", translator::translate("Kann Spielstand\nnicht laden.\n") );
5001 create_win(new news_img("Kann Spielstand\nnicht laden.\n"), w_info, magic_none);
5002 }
5003 }
5004 else if(file.is_version_less(84, 6)) {
5005 // too old
5006 dbg->warning("karte_t::load()", translator::translate("WRONGSAVE") );
5007 create_win(new news_img("WRONGSAVE"), w_info, magic_none);
5008 }
5009 else {
5010 DBG_MESSAGE("karte_t::load()","Savegame version is %u", file.get_version_int());
5011
5012 load(&file);
5013
5014 if( env_t::networkmode ) {
5015 clear_command_queue();
5016 }
5017
5018 if( env_t::server ) {
5019 step_mode = FIX_RATIO;
5020 if( env_t::server ) {
5021 // meaningless to use a locked map; there are passwords now
5022 settings.set_allow_player_change(true);
5023 // language of map becomes server language
5024 settings.set_name_language_iso(translator::get_lang()->iso_base);
5025 }
5026
5027 if( server_reload_pwd_hashes ) {
5028 char fn[256];
5029 sprintf( fn, "server%d-pwdhash.sve", env_t::server );
5030 loadsave_t pwdfile;
5031 if( pwdfile.rd_open(fn) ) {
5032 rdwr_player_password_hashes( &pwdfile );
5033 // correct locking info
5034 nwc_auth_player_t::init_player_lock_server(this);
5035 pwdfile.close();
5036 }
5037 }
5038 }
5039 else if( env_t::networkmode ) {
5040 step_mode = PAUSE_FLAG|FIX_RATIO;
5041 switch_active_player( last_active_player_nr, true );
5042 if( is_within_limits(oldpos) ) {
5043 // go to position when last disconnected
5044 viewport->change_world_position( oldpos );
5045 }
5046 }
5047 else {
5048 step_mode = NORMAL;
5049 }
5050
5051 ok = true;
5052 file.close();
5053
5054 if( !scenario->rdwr_ok() ) {
5055 // error during loading of savegame of scenario
5056 const char* err = scenario->get_error_text();
5057 if (err == NULL) {
5058 err = "Loading scenario failed.";
5059 }
5060 create_win( new news_img( err ), w_info, magic_none);
5061 delete scenario;
5062 scenario = new scenario_t(this);
5063 }
5064 else if( !env_t::networkmode || !env_t::restore_UI ) {
5065 // warning message about missing paks
5066 if( !missing_pak_names.empty() ) {
5067
5068 cbuffer_t msg;
5069 msg.append("<title>");
5070 msg.append(translator::translate("Missing pakfiles"));
5071 msg.append("</title>\n");
5072
5073 cbuffer_t error_paks;
5074 cbuffer_t warning_paks;
5075
5076 cbuffer_t paklog;
5077 paklog.append( "\n" );
5078 FOR(stringhashtable_tpl<missing_level_t>, const& i, missing_pak_names) {
5079 if (i.value <= MISSING_ERROR) {
5080 error_paks.append(translator::translate(i.key));
5081 error_paks.append("<br>\n");
5082 paklog.append( i.key );
5083 paklog.append("\n" );
5084 }
5085 else {
5086 warning_paks.append(translator::translate(i.key));
5087 warning_paks.append("<br>\n");
5088 }
5089 }
5090
5091 if( error_paks.len()>0 ) {
5092 msg.append("<h1>");
5093 msg.append(translator::translate("Pak which may cause severe errors:"));
5094 msg.append("</h1><br>\n");
5095 msg.append("<br>\n");
5096 msg.append( error_paks );
5097 msg.append("<br>\n");
5098 dbg->warning( "The following paks are missing and may cause errors", paklog );
5099 }
5100
5101 if( warning_paks.len()>0 ) {
5102 msg.append("<h1>");
5103 msg.append(translator::translate("Pak which may cause visual errors:"));
5104 msg.append("</h1><br>\n");
5105 msg.append("<br>\n");
5106 msg.append( warning_paks );
5107 msg.append("<br>\n");
5108 }
5109
5110 help_frame_t *win = new help_frame_t();
5111 win->set_text( msg );
5112 create_win(win, w_info, magic_pakset_info_t);
5113 }
5114 // will not notify if we restore everything
5115 if( scenario->is_scripted() ) {
5116 scenario->open_info_win();
5117 }
5118 create_win( new news_img("Spielstand wurde\ngeladen!\n"), w_time_delete, magic_none);
5119 }
5120 set_dirty();
5121
5122 reset_timer();
5123 recalc_average_speed();
5124 mute_sound(false);
5125
5126 tool_t::update_toolbars();
5127 toolbar_last_used_t::last_used_tools->clear();
5128 set_tool( tool_t::general_tool[TOOL_QUERY], get_active_player() );
5129 }
5130 settings.set_filename(filename);
5131 display_show_load_pointer(false);
5132 return ok;
5133 }
5134
5135
5136
5137 #ifdef MULTI_THREAD
5138 static pthread_mutex_t height_mutex;
5139 static recursive_mutex_maker_t height_mutex_maker(height_mutex);
5140 #endif
5141
5142
plans_finish_rd(sint16 x_min,sint16 x_max,sint16 y_min,sint16 y_max)5143 void karte_t::plans_finish_rd( sint16 x_min, sint16 x_max, sint16 y_min, sint16 y_max )
5144 {
5145 sint8 min_h = min_height, max_h = max_height;
5146 for( int y = y_min; y < y_max; y++ ) {
5147 for( int x = x_min; x < x_max; x++ ) {
5148 planquadrat_t *plan = access_nocheck(x,y);
5149 plan->sort_haltlist();
5150 const int boden_count = plan->get_boden_count();
5151 for( int schicht = 0; schicht < boden_count; schicht++ ) {
5152 grund_t *gr = plan->get_boden_bei(schicht);
5153 if( min_h > gr->get_hoehe() ) {
5154 min_h = gr->get_hoehe();
5155 }
5156 else if( max_h < gr->get_hoehe() ) {
5157 max_h = gr->get_hoehe();
5158 }
5159 for( int n = 0; n < gr->get_top(); n++ ) {
5160 obj_t *obj = gr->obj_bei(n);
5161 if(obj) {
5162 obj->finish_rd();
5163 }
5164 }
5165 if( load_version<=111000 && gr->ist_natur() ) {
5166 gr->sort_trees();
5167 }
5168 gr->calc_image();
5169 }
5170 }
5171 }
5172 // update heights
5173 #ifdef MULTI_THREAD
5174 pthread_mutex_lock( &height_mutex );
5175 if( min_height > min_h ) {
5176 min_height = min_h;
5177 }
5178 if( max_height < max_h ) {
5179 max_height = max_h;
5180 }
5181 pthread_mutex_unlock( &height_mutex );
5182 #else
5183 min_height = min_h;
5184 max_height = max_h;
5185 #endif
5186 }
5187
5188
load(loadsave_t * file)5189 void karte_t::load(loadsave_t *file)
5190 {
5191 char buf[80];
5192
5193 intr_disable();
5194 dbg->message("karte_t::load()", "Prepare for loading" );
5195
5196 for( uint8 sp_nr=0; sp_nr<MAX_PLAYER_COUNT; sp_nr++ ) {
5197 if (two_click_tool_t* tool = dynamic_cast<two_click_tool_t*>(selected_tool[sp_nr])) {
5198 tool->cleanup();
5199 }
5200 }
5201 destroy_all_win(true);
5202
5203 clear_random_mode(~LOAD_RANDOM);
5204 set_random_mode(LOAD_RANDOM);
5205 destroy();
5206
5207 loadingscreen_t ls(translator::translate("Loading map ..."), 1, true, true );
5208
5209 tile_counter = 0;
5210 simloops = 60;
5211
5212 // zum laden vorbereiten -> tabelle loeschen
5213 powernet_t::new_world();
5214 pumpe_t::new_world();
5215 senke_t::new_world();
5216 script_api::new_world();
5217
5218 file->set_buffered(true);
5219
5220 // jetzt geht das laden los
5221 dbg->warning("karte_t::load", "Fileversion: %u", file->get_version_int());
5222 settings = env_t::default_settings;
5223 settings.rdwr(file);
5224 loaded_rotation = settings.get_rotation();
5225
5226 // some functions (finish_rd) need to know what version was loaded
5227 load_version = file->get_version_int();
5228
5229 if( env_t::networkmode ) {
5230 // to have games synchronized, transfer random counter too
5231 setsimrand(settings.get_random_counter(), 0xFFFFFFFFu );
5232 translator::init_custom_names(settings.get_name_language_id());
5233 }
5234
5235 if( !env_t::networkmode || (env_t::server && socket_list_t::get_playing_clients()==0) ) {
5236 if (settings.get_allow_player_change() && env_t::default_settings.get_use_timeline() < 2) {
5237 // not locked => eventually switch off timeline settings, if explicitly stated
5238 settings.set_use_timeline(env_t::default_settings.get_use_timeline());
5239 DBG_DEBUG("karte_t::load", "timeline: reset to %i", env_t::default_settings.get_use_timeline() );
5240 }
5241 }
5242 if (settings.get_beginner_mode()) {
5243 goods_manager_t::set_multiplier(settings.get_beginner_price_factor());
5244 }
5245 else {
5246 goods_manager_t::set_multiplier( 1000 );
5247 }
5248
5249 world_maximum_height = settings.get_maximumheight();
5250 world_minimum_height = settings.get_minimumheight();
5251
5252 groundwater = (sint8)(settings.get_groundwater());
5253 min_height = max_height = groundwater;
5254 DBG_DEBUG("karte_t::load()","groundwater %i",groundwater);
5255
5256 if( file->is_version_less(112, 7) ) {
5257 // r7930 fixed a bug in init_height_to_climate
5258 // recover old behavior to not mix up climate when loading old savegames
5259 groundwater = settings.get_climate_borders()[0];
5260 init_height_to_climate();
5261 groundwater = settings.get_groundwater();
5262 }
5263 else {
5264 init_height_to_climate();
5265 }
5266
5267 // just an initialisation for the loading
5268 season = (2+last_month/3)&3; // summer always zero
5269 snowline = settings.get_winter_snowline() + groundwater;
5270
5271 DBG_DEBUG("karte_t::load", "settings loaded (size %i,%i) timeline=%i beginner=%i", settings.get_size_x(), settings.get_size_y(), settings.get_use_timeline(), settings.get_beginner_mode());
5272
5273 // wird gecached, um den Pointerzugriff zu sparen, da
5274 // die size _sehr_ oft referenziert wird
5275 cached_grid_size.x = settings.get_size_x();
5276 cached_grid_size.y = settings.get_size_y();
5277 cached_size_max = max(cached_grid_size.x,cached_grid_size.y);
5278 cached_size.x = cached_grid_size.x-1;
5279 cached_size.y = cached_grid_size.y-1;
5280 viewport->set_x_off(0);
5281 viewport->set_y_off(0);
5282
5283 // Update minimap for new world
5284 minimap_t::get_instance()->init();
5285
5286 ls.set_max( get_size().y*2+256 );
5287 init_tiles();
5288
5289
5290 // reinit pointer with new pointer object and old values
5291 zeiger = new zeiger_t(koord3d::invalid, NULL );
5292
5293 hausbauer_t::new_world();
5294 factory_builder_t::new_world();
5295
5296 DBG_DEBUG("karte_t::load", "init felder ok");
5297
5298 file->rdwr_long(ticks);
5299 file->rdwr_long(last_month);
5300 file->rdwr_long(last_year);
5301 if(file->is_version_less(86, 6)) {
5302 last_year += env_t::default_settings.get_starting_year();
5303 }
5304 // old game might have wrong month
5305 last_month %= 12;
5306 // set the current month count
5307 set_ticks_per_world_month_shift(settings.get_bits_per_month());
5308 current_month = last_month + (last_year*12);
5309 season = (2+last_month/3)&3; // summer always zero
5310 next_month_ticks = ( (ticks >> karte_t::ticks_per_world_month_shift) + 1 ) << karte_t::ticks_per_world_month_shift;
5311 last_step_ticks = ticks;
5312 steps = 0;
5313 network_frame_count = 0;
5314 sync_steps = 0;
5315 sync_steps_barrier = sync_steps;
5316 step_mode = PAUSE_FLAG;
5317
5318 DBG_MESSAGE("karte_t::load()","savegame loading at tick count %i",ticks);
5319 recalc_average_speed(); // resets timeline
5320 koord::locality_factor = settings.get_locality_factor( last_year ); // resets weight factor
5321 // recalc_average_speed may have opened message windows
5322 destroy_all_win(true);
5323
5324 DBG_MESSAGE("karte_t::load()", "init player");
5325 for(int i=0; i<MAX_PLAYER_COUNT; i++) {
5326 if( file->is_version_atleast(101, 0) ) {
5327 // since we have different kind of AIs
5328 delete players[i];
5329 players[i] = NULL;
5330 init_new_player(i, settings.player_type[i]);
5331 }
5332 else if(i<8) {
5333 // get the old player ...
5334 if( players[i]==NULL ) {
5335 init_new_player( i, (i==3) ? player_t::AI_PASSENGER : player_t::AI_GOODS );
5336 }
5337 settings.player_type[i] = players[i]->get_ai_id();
5338 }
5339 }
5340 // so far, player 1 will be active (may change in future)
5341 active_player = players[0];
5342 active_player_nr = 0;
5343
5344 // rdwr static states
5345 senke_t::static_rdwr(file);
5346
5347 // rdwr cityrules, speedbonus for networkgames
5348 if(file->is_version_atleast(102, 3)) {
5349 bool do_rdwr = env_t::networkmode;
5350 file->rdwr_bool(do_rdwr);
5351 if (do_rdwr) {
5352 stadt_t::cityrules_rdwr(file);
5353 if(file->is_version_atleast(102, 4)) {
5354 vehicle_builder_t::rdwr_speedbonus(file);
5355 }
5356 }
5357 }
5358 DBG_DEBUG("karte_t::load", "init %i cities", settings.get_city_count());
5359 stadt.clear();
5360 stadt.resize(settings.get_city_count());
5361 for (int i = 0; i < settings.get_city_count(); ++i) {
5362 stadt_t *s = new stadt_t(file);
5363 stadt.append( s, s->get_einwohner());
5364 }
5365
5366 DBG_MESSAGE("karte_t::load()","loading blocks");
5367 old_blockmanager_t::rdwr(this, file);
5368
5369 DBG_MESSAGE("karte_t::load()","loading tiles");
5370 for (int y = 0; y < get_size().y; y++) {
5371 for (int x = 0; x < get_size().x; x++) {
5372 plan[x+y*cached_grid_size.x].rdwr(file, koord(x,y) );
5373 }
5374 if(file->is_eof()) {
5375 dbg->fatal("karte_t::load()","Savegame file mangled (too short)!");
5376 }
5377 ls.set_progress( y/2 );
5378 }
5379
5380 if(file->is_version_less(99, 5)) {
5381 DBG_MESSAGE("karte_t::load()","loading grid for older versions");
5382 for (int y = 0; y <= get_size().y; y++) {
5383 for (int x = 0; x <= get_size().x; x++) {
5384 sint32 hgt;
5385 file->rdwr_long(hgt);
5386 // old height step was 16!
5387 set_grid_hgt(x, y, hgt/16 );
5388 }
5389 }
5390 }
5391 else if( file->is_version_less(102, 2) ) {
5392 // hgt now bytes
5393 DBG_MESSAGE("karte_t::load()","loading grid for older versions");
5394 for( sint32 i=0; i<(get_size().y+1)*(sint32)(get_size().x+1); i++ ) {
5395 file->rdwr_byte(grid_hgts[i]);
5396 }
5397 }
5398
5399 if(file->is_version_less(88, 9)) {
5400 DBG_MESSAGE("karte_t::load()","loading slopes from older version");
5401 // Hajo: load slopes for older versions
5402 // now part of the grund_t structure
5403 for (int y = 0; y < get_size().y; y++) {
5404 for (int x = 0; x < get_size().x; x++) {
5405 sint8 slope;
5406 file->rdwr_byte(slope);
5407 // convert slopes from old single height saved game
5408 slope = (scorner_sw(slope) + scorner_se(slope) * 3 + scorner_ne(slope) * 9 + scorner_nw(slope) * 27) * env_t::pak_height_conversion_factor;
5409 access_nocheck(x, y)->get_kartenboden()->set_grund_hang(slope);
5410 }
5411 }
5412 }
5413
5414 if(file->is_version_less(88, 1)) {
5415 // because from 88.01.4 on the foundations are handled differently
5416 for (int y = 0; y < get_size().y; y++) {
5417 for (int x = 0; x < get_size().x; x++) {
5418 koord k(x,y);
5419 grund_t *gr = access_nocheck(x, y)->get_kartenboden();
5420 if( gr->get_typ()==grund_t::fundament ) {
5421 gr->set_hoehe( max_hgt_nocheck(k) );
5422 gr->set_grund_hang( slope_t::flat );
5423 // transfer object to on new grund
5424 for( int i=0; i<gr->get_top(); i++ ) {
5425 gr->obj_bei(i)->set_pos( gr->get_pos() );
5426 }
5427 }
5428 }
5429 }
5430 }
5431
5432 if( file->is_version_less(112, 7) ) {
5433 // set climates
5434 for( sint16 y = 0; y < get_size().y; y++ ) {
5435 for( sint16 x = 0; x < get_size().x; x++ ) {
5436 calc_climate( koord( x, y ), false );
5437 }
5438 }
5439 }
5440
5441 // Update minimap for new world
5442 DBG_MESSAGE("karte_t::load()", "init minimap");
5443 win_set_world( this );
5444 minimap_t::get_instance()->init();
5445
5446 // tick all power nets so that they update with loaded power
5447 powernet_t::step_all(1);
5448
5449 // load factories
5450 sint32 fabs;
5451 file->rdwr_long(fabs);
5452 DBG_MESSAGE("karte_t::load()", "prepare for %i factories", fabs);
5453
5454 for(sint32 i = 0; i < fabs; i++) {
5455 // list in gleicher reihenfolge wie vor dem speichern wieder aufbauen
5456 fabrik_t *fab = new fabrik_t(file);
5457 if(fab->get_desc()) {
5458 fab_list.append( fab );
5459 }
5460 else {
5461 dbg->error("karte_t::load()","Unknown factory skipped!");
5462 delete fab;
5463 }
5464 if(i&7) {
5465 ls.set_progress( get_size().y/2+(128*i)/fabs );
5466 }
5467 }
5468
5469 // load linemanagement status (and lines)
5470 // @author hsiegeln
5471 if (file->is_version_atleast(82, 4) && file->is_version_less(88, 3)) {
5472 DBG_MESSAGE("karte_t::load()", "load linemanagement");
5473 get_player(0)->simlinemgmt.rdwr(file, get_player(0));
5474 }
5475 // end load linemanagement
5476
5477 DBG_MESSAGE("karte_t::load()", "load stops");
5478 // now load the stops
5479 // (the players will be load later and overwrite some values,
5480 // like the total number of stops build (for the numbered station feature)
5481 haltestelle_t::start_load_game();
5482 if(file->is_version_atleast(99, 8)) {
5483 sint32 halt_count;
5484 file->rdwr_long(halt_count);
5485 DBG_MESSAGE("karte_t::load()","%d halts loaded",halt_count);
5486 for(int i=0; i<halt_count; i++) {
5487 halthandle_t halt = haltestelle_t::create( file );
5488 if(!halt->existiert_in_welt()) {
5489 dbg->warning("karte_t::load()", "could not restore stop near %i,%i", halt->get_init_pos().x, halt->get_init_pos().y );
5490 }
5491 ls.set_progress( get_size().y/2+128+(get_size().y*i)/(2*halt_count) );
5492 }
5493 }
5494
5495 DBG_MESSAGE("karte_t::load()", "load convois");
5496 uint16 convoi_nr = 65535;
5497 uint16 max_convoi = 65535;
5498 if( file->is_version_atleast(101, 0) ) {
5499 file->rdwr_short(convoi_nr);
5500 max_convoi = convoi_nr;
5501 }
5502 while( convoi_nr-->0 ) {
5503
5504 if( file->is_version_less(101, 0) ) {
5505 file->rd_obj_id(buf, 79);
5506 if (strcmp(buf, "Ende Convois") == 0) {
5507 break;
5508 }
5509 }
5510 convoi_t *cnv = new convoi_t(file);
5511 convoi_array.append(cnv->self);
5512
5513 if(cnv->in_depot()) {
5514 grund_t * gr = lookup(cnv->get_pos());
5515 depot_t *dep = gr ? gr->get_depot() : 0;
5516 if(dep) {
5517 cnv->betrete_depot(dep);
5518 }
5519 else {
5520 dbg->error("karte_t::load()", "no depot for convoi, blocks may now be wrongly reserved!");
5521 cnv->destroy();
5522 }
5523 }
5524 else {
5525 sync.add( cnv );
5526 }
5527 if( (convoi_array.get_count()&7) == 0 ) {
5528 ls.set_progress( get_size().y+(get_size().y*convoi_array.get_count())/(2*max_convoi)+128 );
5529 }
5530 }
5531 DBG_MESSAGE("karte_t::load()", "%d convois/trains loaded", convoi_array.get_count());
5532
5533 // now the player can be loaded
5534 for(int i=0; i<MAX_PLAYER_COUNT; i++) {
5535 if( players[i] ) {
5536 players[i]->rdwr(file);
5537 settings.player_active[i] = players[i]->is_active();
5538 }
5539 else {
5540 settings.player_active[i] = false;
5541 }
5542 ls.set_progress( (get_size().y*3)/2+128+8*i );
5543 }
5544 DBG_MESSAGE("karte_t::load()", "players loaded");
5545
5546 // loading messages
5547 if( file->is_version_atleast(102, 5) ) {
5548 msg->rdwr(file);
5549 }
5550 else if( !env_t::networkmode ) {
5551 msg->clear();
5552 }
5553 DBG_MESSAGE("karte_t::load()", "messages loaded");
5554
5555 // nachdem die welt jetzt geladen ist koennen die Blockstrecken neu
5556 // angelegt werden
5557 old_blockmanager_t::finish_rd(this);
5558 DBG_MESSAGE("karte_t::load()", "blocks loaded");
5559
5560 sint32 mi,mj;
5561 file->rdwr_long(mi);
5562 file->rdwr_long(mj);
5563 DBG_MESSAGE("karte_t::load()", "Setting view to %d,%d", mi,mj);
5564 viewport->change_world_position( koord3d(mi,mj,0) );
5565
5566 // right season for recalculations
5567 recalc_season_snowline(false);
5568
5569 DBG_MESSAGE("karte_t::load()", "%d ways loaded",weg_t::get_alle_wege().get_count());
5570
5571 ls.set_progress( (get_size().y*3)/2+256 );
5572
5573 world_xy_loop(&karte_t::plans_finish_rd, SYNCX_FLAG);
5574
5575 if( file->is_version_less(112, 7) ) {
5576 // set transitions - has to be done after plans_finish_rd
5577 world_xy_loop(&karte_t::recalc_transitions_loop, 0);
5578 }
5579
5580 ls.set_progress( (get_size().y*3)/2+256+get_size().y/8 );
5581
5582 DBG_MESSAGE("karte_t::load()", "laden_abschliesen for tiles finished" );
5583
5584 // must finish loading cities first before cleaning up factories
5585 weighted_vector_tpl<stadt_t*> new_weighted_stadt(stadt.get_count() + 1);
5586 FOR(weighted_vector_tpl<stadt_t*>, const s, stadt) {
5587 s->finish_rd();
5588 s->recalc_target_cities();
5589 new_weighted_stadt.append(s, s->get_einwohner());
5590 INT_CHECK("simworld 1278");
5591 }
5592 swap(stadt, new_weighted_stadt);
5593 DBG_MESSAGE("karte_t::load()", "cities initialized");
5594
5595 ls.set_progress( (get_size().y*3)/2+256+get_size().y/4 );
5596
5597 DBG_MESSAGE("karte_t::load()", "clean up factories");
5598 FOR(slist_tpl<fabrik_t*>, const f, fab_list) {
5599 f->finish_rd();
5600 }
5601
5602 DBG_MESSAGE("karte_t::load()", "%d factories loaded", fab_list.get_count());
5603
5604 // old versions did not save factory connections
5605 if(file->is_version_less(99, 14)) {
5606 sint32 const temp_min = settings.get_factory_worker_minimum_towns();
5607 sint32 const temp_max = settings.get_factory_worker_maximum_towns();
5608 // this needs to avoid the first city to be connected to all town
5609 settings.set_factory_worker_minimum_towns(0);
5610 settings.set_factory_worker_maximum_towns(stadt.get_count() + 1);
5611 FOR(weighted_vector_tpl<stadt_t*>, const i, stadt) {
5612 i->verbinde_fabriken();
5613 }
5614 settings.set_factory_worker_minimum_towns(temp_min);
5615 settings.set_factory_worker_maximum_towns(temp_max);
5616 }
5617 ls.set_progress( (get_size().y*3)/2+256+get_size().y/3 );
5618
5619 // resolve dummy stops into real stops first ...
5620 FOR(vector_tpl<halthandle_t>, const i, haltestelle_t::get_alle_haltestellen()) {
5621 if (i->get_owner() && i->existiert_in_welt()) {
5622 i->finish_rd();
5623 }
5624 }
5625
5626 // ... before removing dummy stops
5627 for( vector_tpl<halthandle_t>::const_iterator i=haltestelle_t::get_alle_haltestellen().begin(); i!=haltestelle_t::get_alle_haltestellen().end(); ) {
5628 halthandle_t const h = *i;
5629 if( !h->get_owner() || !h->existiert_in_welt() ) {
5630 // this stop was only needed for loading goods ...
5631 haltestelle_t::destroy(h); // remove from list
5632 }
5633 else {
5634 ++i;
5635 }
5636 }
5637
5638 ls.set_progress( (get_size().y*3)/2+256+(get_size().y*3)/8 );
5639
5640 // adding lines and other stuff for convois
5641 for(unsigned i=0; i<convoi_array.get_count(); i++ ) {
5642 convoihandle_t cnv = convoi_array[i];
5643 cnv->finish_rd();
5644 // was deleted during loading => use same position again
5645 if(!cnv.is_bound()) {
5646 i--;
5647 }
5648 }
5649 haltestelle_t::end_load_game();
5650
5651 // register all line stops and change line types, if needed
5652 for(int i=0; i<MAX_PLAYER_COUNT ; i++) {
5653 if( players[i] ) {
5654 players[i]->finish_rd();
5655 }
5656 }
5657
5658 #ifdef DEBUG
5659 uint32 dt = dr_time();
5660 #endif
5661 // recalculate halt connections
5662 haltestelle_t::reset_routing();
5663 do {
5664 haltestelle_t::step_all();
5665 } while ( haltestelle_t::get_rerouting_status()==RECONNECTING );
5666 #ifdef DEBUG
5667 dbg->message("rebuild_destinations()","for all haltstellen_t took %ld ms", dr_time()-dt );
5668 #endif
5669
5670 #if 0
5671 // reroute goods for benchmarking
5672 dt = dr_time();
5673 FOR(vector_tpl<halthandle_t>, const i, haltestelle_t::get_alle_haltestellen()) {
5674 sint16 dummy = 0x7FFF;
5675 i->reroute_goods(dummy);
5676 }
5677 DBG_MESSAGE("reroute_goods()","for all haltstellen_t took %ld ms", dr_time()-dt );
5678 #endif
5679
5680 // load history/create world history
5681 if(file->is_version_less(99, 18)) {
5682 restore_history(false);
5683 }
5684 else {
5685 for (int year = 0; year</*MAX_WORLD_HISTORY_YEARS*/12; year++) {
5686 for (int cost_type = 0; cost_type</*MAX_WORLD_COST*/12; cost_type++) {
5687 file->rdwr_longlong(finance_history_year[year][cost_type]);
5688 }
5689 }
5690 for (int month = 0;month</*MAX_WORLD_HISTORY_MONTHS*/12;month++) {
5691 for (int cost_type = 0; cost_type</*MAX_WORLD_COST*/12; cost_type++) {
5692 file->rdwr_longlong(finance_history_month[month][cost_type]);
5693 }
5694 }
5695 last_month_bev = finance_history_month[1][WORLD_CITICENS];
5696
5697 if (file->is_version_atleast(112, 5) && file->is_version_less(120, 6)) {
5698 restore_history(true);
5699 }
5700 }
5701
5702 // finally: do we run a scenario?
5703 if(file->is_version_atleast(99, 18)) {
5704 scenario->rdwr(file);
5705 }
5706
5707 // restore locked state
5708 // network game this will be done in nwc_sync_t::do_command
5709 if( !env_t::networkmode ) {
5710 for( uint8 i=0; i<PLAYER_UNOWNED; i++ ) {
5711 if( players[i] ) {
5712 players[i]->check_unlock( player_password_hash[i] );
5713 }
5714 }
5715 }
5716
5717 // initialize lock info for local server player
5718 // if call from sync command, lock info will be corrected there
5719 if( env_t::server ) {
5720 nwc_auth_player_t::init_player_lock_server(this);
5721 }
5722
5723 // show message about server
5724 if( file->is_version_atleast(112, 8) ) {
5725 xml_tag_t t( file, "motd_t" );
5726 char msg[32766];
5727 file->rdwr_str( msg, 32766 );
5728 if( *msg && !env_t::server ) {
5729 // if not empty ...
5730 help_frame_t *win = new help_frame_t();
5731 win->set_text( msg );
5732 create_win(win, w_info, magic_motd);
5733 }
5734 }
5735
5736 if( file->is_version_atleast(102, 4) ) {
5737 if( env_t::restore_UI ) {
5738 file->rdwr_byte( active_player_nr );
5739 active_player = players[active_player_nr];
5740 /* restore all open windows
5741 * otherwise it will be ignored
5742 * which is save, since it is the end of file
5743 */
5744 rdwr_all_win( file );
5745 }
5746 }
5747
5748 file->set_buffered(false);
5749 clear_random_mode(LOAD_RANDOM);
5750
5751 // loading finished, reset savegame version to current
5752 load_version = loadsave_t::int_version( env_t::savegame_version_str, NULL );
5753
5754 dbg->warning("karte_t::load()","loaded savegame from %i/%i, next month=%i, ticks=%i (per month=1<<%i)",last_month,last_year,next_month_ticks,ticks,karte_t::ticks_per_world_month_shift);
5755 }
5756
5757
5758 // recalcs all ground tiles on the map
update_map_intern(sint16 x_min,sint16 x_max,sint16 y_min,sint16 y_max)5759 void karte_t::update_map_intern(sint16 x_min, sint16 x_max, sint16 y_min, sint16 y_max)
5760 {
5761 if( (loaded_rotation + settings.get_rotation()) & 1 ) { // 1 || 3 // ~14% faster loop blocking rotations 1 and 3
5762 const int LOOP_BLOCK = 128;
5763 for( int xx = x_min; xx < x_max; xx += LOOP_BLOCK ) {
5764 for( int yy = y_min; yy < y_max; yy += LOOP_BLOCK ) {
5765 for( int y = yy; y < min(yy + LOOP_BLOCK, y_max); y++ ) {
5766 for( int x = xx; x < min(xx + LOOP_BLOCK, x_max); x++ ) {
5767 const int nr = y * cached_grid_size.x + x;
5768 for( uint i = 0; i < plan[nr].get_boden_count(); i++ ) {
5769 plan[nr].get_boden_bei(i)->calc_image();
5770 }
5771 }
5772 }
5773 }
5774 }
5775 }
5776 else {
5777 for( int y = y_min; y < y_max; y++ ) {
5778 for( int x = x_min; x < x_max; x++ ) {
5779 const int nr = y * cached_grid_size.x + x;
5780 for( uint i = 0; i < plan[nr].get_boden_count(); i++ ) {
5781 plan[nr].get_boden_bei(i)->calc_image();
5782 }
5783 }
5784 }
5785 }
5786 }
5787
5788
5789 // recalcs all ground tiles on the map
update_map()5790 void karte_t::update_map()
5791 {
5792 DBG_MESSAGE( "karte_t::update_map()", "" );
5793 world_xy_loop(&karte_t::update_map_intern, SYNCX_FLAG);
5794 set_dirty();
5795 }
5796
5797
update_underground()5798 void karte_t::update_underground()
5799 {
5800 DBG_MESSAGE( "karte_t::update_underground_map()", "" );
5801 get_view()->clear_prepared();
5802 world_view_t::invalidate_all();
5803 set_dirty();
5804 }
5805
prepare_tiles(rect_t const & new_area,rect_t const & old_area)5806 void karte_t::prepare_tiles(rect_t const &new_area, rect_t const &old_area) {
5807 if (new_area == old_area) {
5808 // area already prepared
5809 return;
5810 }
5811
5812 size_t const prepare_rects_capacity = rect_t::MAX_FRAGMENT_DIFFERENCE_COUNT;
5813 rect_t prepare_rects[prepare_rects_capacity];
5814 size_t const prepare_rects_length = new_area.fragment_difference(old_area, prepare_rects, prepare_rects_capacity);
5815
5816 // additional tiles to prepare for correct hiding behaviour
5817 sint16 const prefix_tiles_x = min(grund_t::MAXIMUM_HIDE_TEST_DISTANCE, new_area.origin.x);
5818 sint16 const prefix_tiles_y = min(grund_t::MAXIMUM_HIDE_TEST_DISTANCE, new_area.origin.y);
5819
5820 for (size_t rect_index = 0 ; rect_index < prepare_rects_length ; rect_index++) {
5821 rect_t const &prepare_rect = prepare_rects[rect_index];
5822
5823 sint16 x_start = prepare_rect.origin.x;
5824 sint16 const x_end = x_start + prepare_rect.size.x;
5825 if (x_start == new_area.origin.x) {
5826 x_start-= prefix_tiles_x;
5827 }
5828
5829 sint16 y_start = prepare_rect.origin.y;
5830 sint16 const y_end = y_start + prepare_rect.size.y;
5831 if (y_start == new_area.origin.y) {
5832 y_start-= prefix_tiles_y;
5833 }
5834
5835 for (sint16 y = y_start ; y < y_end ; y++) {
5836 for (sint16 x = x_start ; x < x_end ; x++) {
5837 const planquadrat_t &tile = plan[y * cached_grid_size.x + x];
5838 tile.update_underground();
5839 }
5840 }
5841 }
5842 }
5843
calc_climate(koord k,bool recalc)5844 void karte_t::calc_climate(koord k, bool recalc)
5845 {
5846 planquadrat_t *pl = access(k);
5847 if( !pl ) {
5848 return;
5849 }
5850
5851 grund_t *gr = pl->get_kartenboden();
5852 if( gr ) {
5853 if( !gr->is_water() ) {
5854 bool beach = false;
5855 if( gr->get_pos().z == groundwater ) {
5856 for( int i = 0; i < 8 && !beach; i++ ) {
5857 grund_t *gr2 = lookup_kartenboden( k + koord::neighbours[i] );
5858 if( gr2 && gr2->is_water() ) {
5859 beach = true;
5860 }
5861 }
5862 }
5863 pl->set_climate( beach ? desert_climate : get_climate_at_height( max( gr->get_pos().z, groundwater + 1 ) ) );
5864 }
5865 else {
5866 pl->set_climate( water_climate );
5867 }
5868 pl->set_climate_transition_flag(false);
5869 pl->set_climate_corners(0);
5870 }
5871
5872 if( recalc ) {
5873 recalc_transitions(k);
5874 for( int i = 0; i < 8; i++ ) {
5875 recalc_transitions( k + koord::neighbours[i] );
5876 }
5877 }
5878 }
5879
5880
5881 // fills array with neighbour heights
get_neighbour_heights(const koord k,sint8 neighbour_height[8][4]) const5882 void karte_t::get_neighbour_heights(const koord k, sint8 neighbour_height[8][4]) const
5883 {
5884 for( int i = 0; i < 8; i++ ) { // 0 = nw, 1 = w etc.
5885 planquadrat_t *pl2 = access( k + koord::neighbours[i] );
5886 if( pl2 ) {
5887 grund_t *gr2 = pl2->get_kartenboden();
5888 slope_t::type slope_corner = gr2->get_grund_hang();
5889 for( int j = 0; j < 4; j++ ) {
5890 neighbour_height[i][j] = gr2->get_hoehe() + slope_corner % 3;
5891 slope_corner /= 3;
5892 }
5893 }
5894 else {
5895 switch(i) {
5896 case 0: // nw
5897 neighbour_height[i][0] = groundwater;
5898 neighbour_height[i][1] = max( lookup_hgt( k+koord(0,0) ), get_water_hgt( k ) );
5899 neighbour_height[i][2] = groundwater;
5900 neighbour_height[i][3] = groundwater;
5901 break;
5902 case 1: // w
5903 neighbour_height[i][0] = groundwater;
5904 neighbour_height[i][1] = max( lookup_hgt( k+koord(0,1) ), get_water_hgt( k ) );
5905 neighbour_height[i][2] = max( lookup_hgt( k+koord(0,0) ), get_water_hgt( k ) );
5906 neighbour_height[i][3] = groundwater;
5907 break;
5908 case 2: // sw
5909 neighbour_height[i][0] = groundwater;
5910 neighbour_height[i][1] = groundwater;
5911 neighbour_height[i][2] = max( lookup_hgt( k+koord(0,1) ), get_water_hgt( k ) );
5912 neighbour_height[i][3] = groundwater;
5913 break;
5914 case 3: // s
5915 neighbour_height[i][0] = groundwater;
5916 neighbour_height[i][1] = groundwater;
5917 neighbour_height[i][2] = max( lookup_hgt( k+koord(1,1) ), get_water_hgt( k ) );
5918 neighbour_height[i][3] = max( lookup_hgt( k+koord(0,1) ), get_water_hgt( k ) );
5919 break;
5920 case 4: // se
5921 neighbour_height[i][0] = groundwater;
5922 neighbour_height[i][1] = groundwater;
5923 neighbour_height[i][2] = groundwater;
5924 neighbour_height[i][3] = max( lookup_hgt( k+koord(1,1) ), get_water_hgt( k ) );
5925 break;
5926 case 5: // e
5927 neighbour_height[i][0] = max( lookup_hgt( k+koord(1,1) ), get_water_hgt( k ) );
5928 neighbour_height[i][1] = groundwater;
5929 neighbour_height[i][2] = groundwater;
5930 neighbour_height[i][3] = max( lookup_hgt( k+koord(1,0) ), get_water_hgt( k ) );
5931 break;
5932 case 6: // ne
5933 neighbour_height[i][0] = max( lookup_hgt( k+koord(1,0) ), get_water_hgt( k ) );
5934 neighbour_height[i][1] = groundwater;
5935 neighbour_height[i][2] = groundwater;
5936 neighbour_height[i][3] = groundwater;
5937 break;
5938 case 7: // n
5939 neighbour_height[i][0] = max( lookup_hgt( k+koord(0,0) ), get_water_hgt( k ) );
5940 neighbour_height[i][1] = max( lookup_hgt( k+koord(1,0) ), get_water_hgt( k ) );
5941 neighbour_height[i][2] = groundwater;
5942 neighbour_height[i][3] = groundwater;
5943 break;
5944 }
5945
5946 /*neighbour_height[i][0] = groundwater;
5947 neighbour_height[i][1] = groundwater;
5948 neighbour_height[i][2] = groundwater;
5949 neighbour_height[i][3] = groundwater;*/
5950 }
5951 }
5952 }
5953
5954
rotate_transitions(koord k)5955 void karte_t::rotate_transitions(koord k)
5956 {
5957 planquadrat_t *pl = access(k);
5958 if( !pl ) {
5959 return;
5960 }
5961
5962 uint8 climate_corners = pl->get_climate_corners();
5963 if( climate_corners != 0 ) {
5964 climate_corners = (climate_corners >> 1) | ((climate_corners & 1) << 3);
5965 pl->set_climate_corners( climate_corners );
5966 }
5967 }
5968
5969
recalc_transitions_loop(sint16 x_min,sint16 x_max,sint16 y_min,sint16 y_max)5970 void karte_t::recalc_transitions_loop( sint16 x_min, sint16 x_max, sint16 y_min, sint16 y_max )
5971 {
5972 for( int y = y_min; y < y_max; y++ ) {
5973 for( int x = x_min; x < x_max; x++ ) {
5974 recalc_transitions( koord( x, y ) );
5975 }
5976 }
5977 }
5978
5979
recalc_transitions(koord k)5980 void karte_t::recalc_transitions(koord k)
5981 {
5982 planquadrat_t *pl = access(k);
5983 if( !pl ) {
5984 return;
5985 }
5986
5987 grund_t *gr = pl->get_kartenboden();
5988 if( !gr->is_water() ) {
5989 // get neighbour corner heights
5990 sint8 neighbour_height[8][4];
5991 get_neighbour_heights( k, neighbour_height );
5992
5993 // look up neighbouring climates
5994 climate neighbour_climate[8];
5995 for( int i = 0; i < 8; i++ ) { // 0 = nw, 1 = w etc.
5996 koord k_neighbour = k + koord::neighbours[i];
5997 if( !is_within_limits(k_neighbour) ) {
5998 k_neighbour = get_closest_coordinate(k_neighbour);
5999 }
6000 neighbour_climate[i] = get_climate( k_neighbour );
6001 }
6002
6003 uint8 climate_corners = 0;
6004 climate climate0 = get_climate(k);
6005
6006 slope_t::type slope_corner = gr->get_grund_hang();
6007 for( uint8 i = 0; i < 4; i++ ) { // 0 = sw, 1 = se etc.
6008 // corner_sw (i=0): tests vs neighbour 1:w (corner 2 j=1),2:sw (corner 3) and 3:s (corner 4)
6009 // corner_se (i=1): tests vs neighbour 3:s (corner 3 j=2),4:se (corner 4) and 5:e (corner 1)
6010 // corner_ne (i=2): tests vs neighbour 5:e (corner 4 j=3),6:ne (corner 1) and 7:n (corner 2)
6011 // corner_nw (i=3): tests vs neighbour 7:n (corner 1 j=0),0:nw (corner 2) and 1:w (corner 3)
6012 sint8 corner_height = gr->get_hoehe() + slope_corner % 3;
6013
6014 climate transition_climate = water_climate;
6015 climate min_climate = arctic_climate;
6016
6017 for( int j = 1; j < 4; j++ ) {
6018 if( corner_height == neighbour_height[(i * 2 + j) & 7][(i + j) & 3]) {
6019 climate climatej = neighbour_climate[(i * 2 + j) & 7];
6020 climatej > transition_climate ? transition_climate = climatej : 0;
6021 climatej < min_climate ? min_climate = climatej : 0;
6022 }
6023 }
6024
6025 if( min_climate == water_climate || transition_climate > climate0 ) {
6026 climate_corners |= 1 << i;
6027 }
6028 slope_corner /= 3;
6029 }
6030 pl->set_climate_transition_flag( climate_corners != 0 );
6031 pl->set_climate_corners( climate_corners );
6032 }
6033 gr->calc_image();
6034 }
6035
6036
create_grounds_loop(sint16 x_min,sint16 x_max,sint16 y_min,sint16 y_max)6037 void karte_t::create_grounds_loop( sint16 x_min, sint16 x_max, sint16 y_min, sint16 y_max )
6038 {
6039 for( int y = y_min; y < y_max; y++ ) {
6040 for( int x = x_min; x < x_max; x++ ) {
6041 koord k(x,y);
6042 access_nocheck(k)->kartenboden_setzen( new boden_t( koord3d( x, y, max(min_hgt_nocheck(k),get_water_hgt_nocheck(k)) ), 0 ) );
6043 }
6044 }
6045 }
6046
6047
sp2num(player_t * player)6048 uint8 karte_t::sp2num(player_t *player)
6049 {
6050 if( player==NULL ) {
6051 return PLAYER_UNOWNED;
6052 }
6053 for(int i=0; i<MAX_PLAYER_COUNT; i++) {
6054 if(players[i] == player) {
6055 return i;
6056 }
6057 }
6058 dbg->fatal( "karte_t::sp2num()", "called with an invalid player!" );
6059 }
6060
6061
load_heightfield(settings_t * const sets)6062 void karte_t::load_heightfield(settings_t* const sets)
6063 {
6064 sint16 w, h;
6065 sint8 *h_field;
6066 height_map_loader_t hml(sets);
6067 if(hml.get_height_data_from_file(sets->heightfield.c_str(), (sint8)(sets->get_groundwater()), h_field, w, h, false )) {
6068 sets->set_size(w,h);
6069 // create map
6070 init(sets,h_field);
6071 delete [] h_field;
6072 }
6073 else {
6074 dbg->error("karte_t::load_heightfield()","Cant open file '%s'", sets->heightfield.c_str());
6075 create_win( new news_img("\nCan't open heightfield file.\n"), w_info, magic_none );
6076 }
6077 }
6078
6079
mark_area(const koord3d pos,const koord size,const bool mark) const6080 void karte_t::mark_area( const koord3d pos, const koord size, const bool mark ) const
6081 {
6082 for( sint16 y=pos.y; y<pos.y+size.y; y++ ) {
6083 for( sint16 x=pos.x; x<pos.x+size.x; x++ ) {
6084 grund_t *gr = lookup( koord3d(x,y,pos.z));
6085 if (!gr) {
6086 gr = lookup_kartenboden( x,y );
6087 }
6088 if(gr) {
6089 if(mark) {
6090 gr->set_flag(grund_t::marked);
6091 }
6092 else {
6093 gr->clear_flag(grund_t::marked);
6094 }
6095 gr->set_flag(grund_t::dirty);
6096 }
6097 }
6098 }
6099 }
6100
6101
reset_timer()6102 void karte_t::reset_timer()
6103 {
6104 // Reset timers
6105 uint32 last_tick_sync = dr_time();
6106 mouse_rest_time = last_tick_sync;
6107 sound_wait_time = AMBIENT_SOUND_INTERVALL;
6108 intr_set_last_time(last_tick_sync);
6109
6110 if( env_t::networkmode && (step_mode&PAUSE_FLAG)==0 ) {
6111 step_mode = FIX_RATIO;
6112 }
6113
6114 last_step_time = last_interaction = last_tick_sync;
6115 last_step_ticks = ticks;
6116
6117 // reinit simloop counter
6118 for( int i=0; i<32; i++ ) {
6119 last_step_nr[i] = steps;
6120 }
6121
6122 if( step_mode&PAUSE_FLAG ) {
6123 intr_disable();
6124 }
6125 else if(step_mode==FAST_FORWARD) {
6126 next_step_time = last_tick_sync+1;
6127 idle_time = 0;
6128 set_frame_time( 100 );
6129 time_multiplier = 16;
6130 intr_enable();
6131 }
6132 else if(step_mode==FIX_RATIO) {
6133 last_frame_idx = 0;
6134 fix_ratio_frame_time = 1000 / clamp(settings.get_frames_per_second(), 5, 100);
6135 next_step_time = last_tick_sync + fix_ratio_frame_time;
6136 set_frame_time( fix_ratio_frame_time );
6137 intr_disable();
6138 // other stuff needed to synchronize
6139 tile_counter = 0;
6140 pending_season_change = 1;
6141 pending_snowline_change = 1;
6142 }
6143 else {
6144 // make timer loop invalid
6145 for( int i=0; i<32; i++ ) {
6146 last_frame_ms[i] = dr_time();
6147 }
6148 last_frame_idx = 0;
6149 simloops = 60;
6150
6151 set_frame_time( 1000/env_t::fps );
6152 next_step_time = last_tick_sync+(3200/get_time_multiplier() );
6153 intr_enable();
6154 }
6155 DBG_MESSAGE("karte_t::reset_timer()","called, mode=$%X", step_mode);
6156 }
6157
6158
reset_interaction()6159 void karte_t::reset_interaction()
6160 {
6161 last_interaction = dr_time();
6162 }
6163
6164
set_map_counter(uint32 new_map_counter)6165 void karte_t::set_map_counter(uint32 new_map_counter)
6166 {
6167 map_counter = new_map_counter;
6168 if( env_t::server ) {
6169 nwc_ready_t::append_map_counter(map_counter);
6170 }
6171 }
6172
6173
generate_new_map_counter() const6174 uint32 karte_t::generate_new_map_counter() const
6175 {
6176 return dr_time();
6177 }
6178
6179
6180 // jump one year ahead
6181 // (not updating history!)
step_year()6182 void karte_t::step_year()
6183 {
6184 DBG_MESSAGE("karte_t::step_year()","called");
6185 current_month += 12;
6186 last_year ++;
6187 reset_timer();
6188 recalc_average_speed();
6189 koord::locality_factor = settings.get_locality_factor( last_year );
6190 FOR(weighted_vector_tpl<stadt_t*>, const i, stadt) {
6191 i->recalc_target_cities();
6192 i->recalc_target_attractions();
6193 }
6194 }
6195
6196
6197 // jump one or more months ahead
6198 // (updating history!)
step_month(sint16 months)6199 void karte_t::step_month( sint16 months )
6200 {
6201 while( months-->0 ) {
6202 new_month();
6203 }
6204 reset_timer();
6205 }
6206
6207
get_time_multiplier() const6208 sint32 karte_t::get_time_multiplier() const
6209 {
6210 return step_mode==FAST_FORWARD ? env_t::max_acceleration : time_multiplier;
6211 }
6212
6213
change_time_multiplier(sint32 delta)6214 void karte_t::change_time_multiplier(sint32 delta)
6215 {
6216 if( step_mode == FAST_FORWARD ) {
6217 if( env_t::max_acceleration+delta > 2 ) {
6218 env_t::max_acceleration += delta;
6219 }
6220 }
6221 else {
6222 time_multiplier += delta;
6223 if(time_multiplier<=0) {
6224 time_multiplier = 1;
6225 }
6226 if(step_mode!=NORMAL) {
6227 step_mode = NORMAL;
6228 reset_timer();
6229 }
6230 }
6231 }
6232
6233
set_pause(bool p)6234 void karte_t::set_pause(bool p)
6235 {
6236 bool pause = step_mode&PAUSE_FLAG;
6237 if(p!=pause) {
6238 step_mode ^= PAUSE_FLAG;
6239 if(p) {
6240 intr_disable();
6241 }
6242 else {
6243 reset_timer();
6244 }
6245 }
6246 }
6247
6248
set_fast_forward(bool ff)6249 void karte_t::set_fast_forward(bool ff)
6250 {
6251 if( !env_t::networkmode ) {
6252 if( ff ) {
6253 if( step_mode==NORMAL ) {
6254 step_mode = FAST_FORWARD;
6255 reset_timer();
6256 }
6257 }
6258 else {
6259 if( step_mode==FAST_FORWARD ) {
6260 step_mode = NORMAL;
6261 reset_timer();
6262 }
6263 }
6264 }
6265 }
6266
6267
get_closest_coordinate(koord outside_pos)6268 koord karte_t::get_closest_coordinate(koord outside_pos)
6269 {
6270 outside_pos.clip_min(koord(0,0));
6271 outside_pos.clip_max(koord(get_size().x-1,get_size().y-1));
6272
6273 return outside_pos;
6274 }
6275
6276
6277 /* creates a new player with this type */
init_new_player(uint8 new_player_in,uint8 type)6278 const char *karte_t::init_new_player(uint8 new_player_in, uint8 type)
6279 {
6280 if( new_player_in>=PLAYER_UNOWNED || get_player(new_player_in)!=NULL ) {
6281 return "Id invalid/already in use!";
6282 }
6283 switch( type ) {
6284 case player_t::EMPTY: break;
6285 case player_t::HUMAN: players[new_player_in] = new player_t(new_player_in); break;
6286 case player_t::AI_GOODS: players[new_player_in] = new ai_goods_t(new_player_in); break;
6287 case player_t::AI_PASSENGER: players[new_player_in] = new ai_passenger_t(new_player_in); break;
6288 case player_t::AI_SCRIPTED: players[new_player_in] = new ai_scripted_t(new_player_in); break;
6289 default: return "Unknown AI type!";
6290 }
6291 settings.set_player_type(new_player_in, type);
6292 return NULL;
6293 }
6294
6295
remove_player(uint8 player_nr)6296 void karte_t::remove_player(uint8 player_nr)
6297 {
6298 if ( player_nr!=1 && player_nr<PLAYER_UNOWNED && players[player_nr]!=NULL) {
6299 players[player_nr]->ai_bankrupt();
6300 delete players[player_nr];
6301 players[player_nr] = 0;
6302 nwc_chg_player_t::company_removed(player_nr);
6303 // if default human, create new instace of it (to avoid crashes)
6304 if( player_nr == 0 ) {
6305 players[0] = new player_t( 0 );
6306 }
6307 // if currently still active => reset to default human
6308 if( player_nr == active_player_nr ) {
6309 active_player_nr = 0;
6310 active_player = players[0];
6311 if( !env_t::server ) {
6312 create_win( display_get_width()/2-128, 40, new news_img("Bankrott:\n\nDu bist bankrott.\n"), w_info, magic_none);
6313 }
6314 }
6315 }
6316 }
6317
6318
6319 /* goes to next active player */
switch_active_player(uint8 new_player,bool silent)6320 void karte_t::switch_active_player(uint8 new_player, bool silent)
6321 {
6322 for( uint8 i=0; i<MAX_PLAYER_COUNT; i++ ) {
6323 if( players[(i+new_player)%MAX_PLAYER_COUNT] != NULL ) {
6324 new_player = (i+new_player)%MAX_PLAYER_COUNT;
6325 break;
6326 }
6327 }
6328 koord3d old_zeiger_pos = zeiger->get_pos();
6329
6330 // no cheating allowed?
6331 if (!settings.get_allow_player_change() && players[1]->is_locked()) {
6332 active_player_nr = 0;
6333 active_player = players[0];
6334 if(new_player!=0) {
6335 create_win( new news_img("On this map, you are not\nallowed to change player!\n"), w_time_delete, magic_none);
6336 }
6337 }
6338 else {
6339 zeiger->change_pos( koord3d::invalid ); // unmark area
6340 // exit active tool to remove pointers (for two_click_tool_t's, stop mover, factory linker)
6341 if(selected_tool[active_player_nr]) {
6342 selected_tool[active_player_nr]->exit(active_player);
6343 }
6344 active_player_nr = new_player;
6345 active_player = players[new_player];
6346 if( !silent ) {
6347 // tell the player
6348 cbuffer_t buf;
6349 buf.printf( translator::translate("Now active as %s.\n"), get_active_player()->get_name() );
6350 msg->add_message(buf, koord::invalid, message_t::ai | message_t::local_flag, PLAYER_FLAG|get_active_player()->get_player_nr(), IMG_EMPTY);
6351 }
6352
6353 // update menu entries
6354 tool_t::update_toolbars();
6355 set_dirty();
6356 }
6357
6358 // update pointer image / area
6359 selected_tool[active_player_nr]->init_cursor(zeiger);
6360 // set position / mark area
6361 zeiger->change_pos( old_zeiger_pos );
6362 }
6363
6364
stop(bool exit_game)6365 void karte_t::stop(bool exit_game)
6366 {
6367 finish_loop = true;
6368 env_t::quit_simutrans = exit_game;
6369 }
6370
6371
network_game_set_pause(bool pause_,uint32 syncsteps_)6372 void karte_t::network_game_set_pause(bool pause_, uint32 syncsteps_)
6373 {
6374 if (env_t::networkmode) {
6375 time_multiplier = 16; // reset to normal speed
6376 sync_steps = syncsteps_;
6377 sync_steps_barrier = sync_steps;
6378 steps = sync_steps / settings.get_frames_per_step();
6379 network_frame_count = sync_steps % settings.get_frames_per_step();
6380 dbg->warning("karte_t::network_game_set_pause", "steps=%d sync_steps=%d pause=%d", steps, sync_steps, pause_);
6381 if (pause_) {
6382 if (!env_t::server) {
6383 reset_timer();
6384 step_mode = PAUSE_FLAG|FIX_RATIO;
6385 }
6386 else {
6387 // TODO
6388 }
6389 }
6390 else {
6391 step_mode = FIX_RATIO;
6392 reset_timer();
6393 if( !env_t::server ) {
6394 // allow server to run ahead the specified number of frames, plus an extra 50%. Better to catch up than be ahead.
6395 next_step_time = dr_time() + (settings.get_server_frames_ahead() + (uint32)env_t::additional_client_frames_behind) * fix_ratio_frame_time * 3 / 2;
6396 }
6397 }
6398 }
6399 else {
6400 set_pause(pause_);
6401 }
6402 }
6403
6404
call_work(tool_t * tool,player_t * player,koord3d pos,bool & suspended)6405 const char* karte_t::call_work(tool_t *tool, player_t *player, koord3d pos, bool &suspended)
6406 {
6407 const char *err = NULL;
6408 if (!env_t::networkmode || tool->is_work_network_save() || tool->is_work_here_network_save( player, pos) ) {
6409 // do the work
6410 tool->flags |= tool_t::WFL_LOCAL;
6411 // check allowance by scenario
6412 if ( (tool->flags & tool_t::WFL_NO_CHK) == 0 && get_scenario()->is_scripted()) {
6413 if (!get_scenario()->is_tool_allowed(player, tool->get_id(), tool->get_waytype()) ) {
6414 err = "";
6415 }
6416 else {
6417 err = get_scenario()->is_work_allowed_here(player, tool->get_id(), tool->get_waytype(), pos);
6418 }
6419 }
6420 if (err == NULL) {
6421 err = tool->work(player, pos);
6422 }
6423 suspended = false;
6424 }
6425 else {
6426 // queue tool for network
6427 nwc_tool_t *nwc = new nwc_tool_t(player, tool, pos, get_steps(), get_map_counter(), false);
6428 network_send_server(nwc);
6429 suspended = true;
6430 // reset tool
6431 tool->init(player);
6432 }
6433 return err;
6434 }
6435
6436
6437 static slist_tpl<network_world_command_t*> command_queue;
6438
command_queue_append(network_world_command_t * nwc) const6439 void karte_t::command_queue_append(network_world_command_t* nwc) const
6440 {
6441 slist_tpl<network_world_command_t*>::iterator i = command_queue.begin();
6442 slist_tpl<network_world_command_t*>::iterator end = command_queue.end();
6443 while(i != end && network_world_command_t::cmp(*i, nwc)) {
6444 ++i;
6445 }
6446 command_queue.insert(i, nwc);
6447 }
6448
6449
clear_command_queue() const6450 void karte_t::clear_command_queue() const
6451 {
6452 while (!command_queue.empty()) {
6453 delete command_queue.remove_first();
6454 }
6455 }
6456
6457
encode_URI(cbuffer_t & buf,char const * const text)6458 static void encode_URI(cbuffer_t& buf, char const* const text)
6459 {
6460 for (char const* i = text; *i != '\0'; ++i) {
6461 char const c = *i;
6462 if (('A' <= c && c <= 'Z') ||
6463 ('a' <= c && c <= 'z') ||
6464 ('0' <= c && c <= '9') ||
6465 c == '-' || c == '.' || c == '_' || c == '~') {
6466 char const two[] = { c, '\0' };
6467 buf.append(two);
6468 } else {
6469 buf.printf("%%%02X", (unsigned char)c);
6470 }
6471 }
6472 }
6473
6474
process_network_commands(sint32 * ms_difference)6475 void karte_t::process_network_commands(sint32 *ms_difference)
6476 {
6477 // did we receive a new command?
6478 uint32 ms = dr_time();
6479 sint32 time_to_next_step = (sint32)next_step_time - (sint32)ms;
6480 network_command_t *nwc = network_check_activity( this, time_to_next_step > 0 ? min( time_to_next_step, 5) : 0 );
6481 if( nwc==NULL && !network_check_server_connection() ) {
6482 dbg->warning("karte_t::process_network_commands", "lost connection to server");
6483 network_disconnect();
6484 return;
6485 }
6486
6487 // process the received command
6488 while( nwc ) {
6489 // check timing
6490 uint16 const nwcid = nwc->get_id();
6491 if( nwcid == NWC_CHECK || nwcid == NWC_STEP ) {
6492 // pull out server sync step
6493 const uint32 server_sync_step = nwcid == NWC_CHECK ? dynamic_cast<nwc_check_t *>(nwc)->server_sync_step : dynamic_cast<nwc_step_t *>(nwc)->get_sync_step();
6494
6495 // are we on time?
6496 *ms_difference = 0;
6497 const uint32 timems = dr_time();
6498 const sint32 time_to_next = (sint32)next_step_time - (sint32)timems; // +'ve - still waiting for next, -'ve - lagging
6499 const sint64 frame_timediff = ((sint64)server_sync_step - sync_steps - settings.get_server_frames_ahead() - env_t::additional_client_frames_behind) * fix_ratio_frame_time; // +'ve - server is ahead, -'ve - client is ahead
6500 const sint64 timediff = time_to_next + frame_timediff;
6501 dbg->warning("NWC_CHECK", "time difference to server %lli", frame_timediff );
6502
6503 if( frame_timediff < (0 - (sint64)settings.get_server_frames_ahead() - (sint64)env_t::additional_client_frames_behind) * (sint64)fix_ratio_frame_time / 2 ) {
6504 // running way ahead - more than half margin, simply set next_step_time ahead to where it should be
6505 next_step_time = (sint64)timems - frame_timediff;
6506 }
6507 else if( frame_timediff < 0 ) {
6508 // running ahead
6509 if( time_to_next > -frame_timediff ) {
6510 // already waiting longer than how far we're ahead, so set wait time shorter to the time ahead.
6511 next_step_time = (sint64)timems - frame_timediff;
6512 }
6513 else if( nwcid == NWC_CHECK ) {
6514 // gentle slowing down
6515 *ms_difference = timediff;
6516 }
6517 }
6518 else if( frame_timediff > 0 ) {
6519 // running behind
6520 if( time_to_next > (sint32)fix_ratio_frame_time / 4 ) {
6521 // behind but we're still waiting for the next step time - get going.
6522 next_step_time = timems;
6523 *ms_difference = frame_timediff;
6524 }
6525 else if( nwcid == NWC_CHECK ) {
6526 // gentle catching up
6527 *ms_difference = timediff;
6528 }
6529 }
6530
6531 if( sync_steps_barrier < server_sync_step ) {
6532 sync_steps_barrier = server_sync_step;
6533 }
6534 }
6535
6536 // check random number generator states
6537 if( env_t::server && nwcid == NWC_TOOL ) {
6538 nwc_tool_t *nwt = dynamic_cast<nwc_tool_t *>(nwc);
6539 if( nwt->is_from_initiator() ) {
6540 if( nwt->last_sync_step>sync_steps ) {
6541 dbg->warning("karte_t::process_network_commands", "client was too fast (skipping command)" );
6542 delete nwc;
6543 nwc = NULL;
6544 }
6545 // out of sync => drop client (but we can only compare if nwt->last_sync_step is not too old)
6546 else if( is_checklist_available(nwt->last_sync_step) && LCHKLST(nwt->last_sync_step)!=nwt->last_checklist ) {
6547 // lost synchronisation -> server kicks client out actively
6548 char buf[256];
6549 const int offset = LCHKLST(nwt->last_sync_step).print(buf, "server");
6550 nwt->last_checklist.print(buf + offset, "initiator");
6551 dbg->warning("karte_t::process_network_commands", "kicking client due to checklist mismatch : sync_step=%u %s", nwt->last_sync_step, buf);
6552 socket_list_t::remove_client( nwc->get_sender() );
6553 delete nwc;
6554 nwc = NULL;
6555 }
6556 }
6557 }
6558
6559 // execute command, append to command queue if necessary
6560 if(nwc && nwc->execute(this)) {
6561 // network_world_command_t's will be appended to command queue in execute
6562 // all others have to be deleted here
6563 delete nwc;
6564
6565 }
6566 // fetch the next command
6567 nwc = network_get_received_command();
6568 }
6569 uint32 next_command_step = get_next_command_step();
6570
6571 // send data
6572 ms = dr_time();
6573 network_process_send_queues( next_step_time>ms ? min( next_step_time-ms, 5) : 0 );
6574
6575 // process enqueued network world commands
6576 while( !command_queue.empty() && (next_command_step<=sync_steps/* || step_mode&PAUSE_FLAG*/) ) {
6577 network_world_command_t *nwc = command_queue.remove_first();
6578 if (nwc) {
6579 do_network_world_command(nwc);
6580 delete nwc;
6581 }
6582 next_command_step = get_next_command_step();
6583 }
6584 }
6585
do_network_world_command(network_world_command_t * nwc)6586 void karte_t::do_network_world_command(network_world_command_t *nwc)
6587 {
6588 // want to execute something in the past?
6589 if (nwc->get_sync_step() < sync_steps) {
6590 if (!nwc->ignore_old_events()) {
6591 dbg->warning("karte_t:::do_network_world_command", "wanted to do_command(%d) in the past", nwc->get_id());
6592 network_disconnect();
6593 }
6594 }
6595 // check map counter
6596 else if (nwc->get_map_counter() != map_counter) {
6597 dbg->warning("karte_t:::do_network_world_command", "wanted to do_command(%d) from another world", nwc->get_id());
6598 }
6599 // check random counter?
6600 else if( nwc->get_id()==NWC_CHECK ) {
6601 nwc_check_t* nwcheck = (nwc_check_t*)nwc;
6602 // this was the random number at the previous sync step on the server
6603 const checklist_t &server_checklist = nwcheck->server_checklist;
6604 const uint32 server_sync_step = nwcheck->server_sync_step;
6605 char buf[256];
6606 const int offset = server_checklist.print(buf, "server");
6607 LCHKLST(server_sync_step).print(buf + offset, "client");
6608 dbg->warning("karte_t:::do_network_world_command", "sync_step=%u %s", server_sync_step, buf);
6609 if( LCHKLST(server_sync_step)!=server_checklist ) {
6610 dbg->warning("karte_t:::do_network_world_command", "disconnecting due to checklist mismatch" );
6611 network_disconnect();
6612 }
6613 }
6614 else {
6615 if( nwc->get_id()==NWC_TOOL ) {
6616 nwc_tool_t *nwt = dynamic_cast<nwc_tool_t *>(nwc);
6617 if( is_checklist_available(nwt->last_sync_step) && LCHKLST(nwt->last_sync_step)!=nwt->last_checklist ) {
6618 // lost synchronisation ...
6619 char buf[256];
6620 const int offset = nwt->last_checklist.print(buf, "server");
6621 LCHKLST(nwt->last_sync_step).print(buf + offset, "executor");
6622 dbg->warning("karte_t:::do_network_world_command", "skipping command due to checklist mismatch : sync_step=%u %s", nwt->last_sync_step, buf);
6623 if( !env_t::server ) {
6624 network_disconnect();
6625 }
6626 return;
6627 }
6628 }
6629 nwc->do_command(this);
6630 }
6631 }
6632
get_next_command_step()6633 uint32 karte_t::get_next_command_step()
6634 {
6635 // when execute next command?
6636 if( !command_queue.empty() ) {
6637 return command_queue.front()->get_sync_step();
6638 }
6639 else {
6640 return 0xFFFFFFFFu;
6641 }
6642 }
6643
get_sound_id(grund_t * gr)6644 sint16 karte_t::get_sound_id(grund_t *gr)
6645 {
6646 if( gr->ist_natur() || gr->is_water() ) {
6647 sint16 id = NO_SOUND;
6648 if( gr->get_pos().z >= get_snowline() ) {
6649 id = sound_desc_t::climate_sounds[ arctic_climate ];
6650 }
6651 else {
6652 id = sound_desc_t::climate_sounds[get_climate( zeiger->get_pos().get_2d() )];
6653 }
6654 if (id != NO_SOUND) {
6655 return id;
6656 }
6657 // try, if there is another sound ready
6658 if( zeiger->get_pos().z==groundwater && !gr->is_water() ) {
6659 return sound_desc_t::beach_sound;
6660 }
6661 else if( gr->get_top()>0 && gr->obj_bei(0)->get_typ()==obj_t::baum ) {
6662 return sound_desc_t::forest_sound;
6663 }
6664 }
6665 return NO_SOUND;
6666 }
6667
6668
interactive(uint32 quit_month)6669 bool karte_t::interactive(uint32 quit_month)
6670 {
6671
6672 finish_loop = false;
6673 sync_steps = 0;
6674 sync_steps_barrier = sync_steps;
6675
6676 network_frame_count = 0;
6677 vector_tpl<uint16>hashes_ok; // bit set: this client can do something with this player
6678
6679 if( !scenario->rdwr_ok() ) {
6680 // error during loading of savegame of scenario
6681 create_win( new news_img( scenario->get_error_text() ), w_info, magic_none);
6682 scenario->stop();
6683 }
6684 // only needed for network
6685 if( env_t::networkmode ) {
6686 // clear the checklist history
6687 for( int i=0; i<LAST_CHECKLISTS_COUNT; ++i ) {
6688 last_checklists[i] = checklist_t();
6689 }
6690 }
6691 sint32 ms_difference = 0;
6692 reset_timer();
6693 DBG_DEBUG4("karte_t::interactive", "welcome in this routine");
6694
6695 if( env_t::server ) {
6696 step_mode |= FIX_RATIO;
6697
6698 reset_timer();
6699 // Announce server startup to the listing server
6700 if( env_t::server_announce ) {
6701 announce_server( 0 );
6702 }
6703 }
6704
6705 DBG_DEBUG4("karte_t::interactive", "start the loop");
6706 do {
6707 // check for too much time eaten by frame updates ...
6708 if( step_mode==NORMAL ) {
6709 DBG_DEBUG4("karte_t::interactive", "decide to play a sound");
6710 last_interaction = dr_time();
6711 if( sound_wait_time < last_interaction - mouse_rest_time ) {
6712 // we play an ambient sound, if enabled
6713 grund_t *gr = lookup(zeiger->get_pos());
6714 if( gr ) {
6715 sint16 id = get_sound_id(gr);
6716 if( id!=NO_SOUND ) {
6717 sound_play(id);
6718 }
6719 }
6720 sound_wait_time *= 2;
6721 }
6722 DBG_DEBUG4("karte_t::interactive", "end of sound");
6723 }
6724
6725 // check events queued since our last iteration
6726 eventmanager->check_events();
6727
6728 if (env_t::quit_simutrans){
6729 break;
6730 }
6731
6732 if( env_t::networkmode ) {
6733 process_network_commands(&ms_difference);
6734 }
6735 else {
6736 // we wait here for maximum 9ms
6737 // average is 5 ms, so we usually
6738 // are quite responsive
6739 DBG_DEBUG4("karte_t::interactive", "can I get some sleep?");
6740 INT_CHECK( "karte_t::interactive()" );
6741 const sint32 wait_time = (sint32)next_step_time - (sint32)dr_time();
6742 if(wait_time>0) {
6743 if( wait_time < 4 ) {
6744 dr_sleep( wait_time );
6745 }
6746 else {
6747 dr_sleep( 3 );
6748 }
6749 INT_CHECK( "karte_t::interactive()" );
6750 }
6751 DBG_DEBUG4("karte_t::interactive", "end of sleep");
6752 }
6753
6754 uint32 time = dr_time();
6755
6756 // check midi if next songs needs to be started
6757 if( (sint32)next_midi_time - (sint32)time <= 0 ) {
6758 DBG_DEBUG4("karte_t::interactive", "checkmidi");
6759 check_midi();
6760 next_midi_time = time + 1500; // check every 1.5 s if we need to start next song
6761 }
6762
6763 // time for the next step?
6764 if( (sint32)next_step_time - (sint32)time <= 0 ) {
6765 if( step_mode&PAUSE_FLAG ) {
6766 // only update display
6767 sync_step( 0, false, true );
6768 idle_time = 100;
6769 }
6770 else if( env_t::networkmode && !env_t::server && sync_steps >= sync_steps_barrier ) {
6771 sync_step( 0, false, true );
6772 next_step_time = time + fix_ratio_frame_time;
6773 }
6774 else {
6775 if( step_mode==FAST_FORWARD ) {
6776 sync_step( 100, true, false );
6777 set_random_mode( STEP_RANDOM );
6778 step();
6779 clear_random_mode( STEP_RANDOM );
6780 }
6781 else if( step_mode==FIX_RATIO ) {
6782 if( env_t::server ) {
6783 next_step_time += fix_ratio_frame_time;
6784 }
6785 else {
6786 const sint32 lag_time = (sint32)time - (sint32)next_step_time;
6787 if( lag_time > 0 ) {
6788 ms_difference += lag_time;
6789 next_step_time = time;
6790 }
6791
6792 const sint32 nst_diff = clamp( ms_difference, -fix_ratio_frame_time * 2, fix_ratio_frame_time * 8 ) / 10; // allows timerate between 83% and 500% of normal
6793 next_step_time += fix_ratio_frame_time - nst_diff;
6794 ms_difference -= nst_diff;
6795 }
6796
6797 sync_step( (fix_ratio_frame_time*time_multiplier)/16, true, true );
6798 if (++network_frame_count == settings.get_frames_per_step()) {
6799 // ever fourth frame
6800 set_random_mode( STEP_RANDOM );
6801 step();
6802 clear_random_mode( STEP_RANDOM );
6803 network_frame_count = 0;
6804 }
6805 sync_steps = steps * settings.get_frames_per_step() + network_frame_count;
6806 LCHKLST(sync_steps) = checklist_t(get_random_seed(), halthandle_t::get_next_check(), linehandle_t::get_next_check(), convoihandle_t::get_next_check());
6807 // some server side tasks
6808 if( env_t::networkmode && env_t::server ) {
6809 // broadcast sync info regularly and when lagged
6810 const sint64 timelag = (sint32)dr_time() - (sint32)next_step_time;
6811 if( (network_frame_count == 0 && timelag > fix_ratio_frame_time * settings.get_server_frames_ahead() / 2) || (sync_steps % env_t::server_sync_steps_between_checks) == 0 ) {
6812 if( timelag > fix_ratio_frame_time * settings.get_frames_per_step() ) {
6813 // log when server is lagged more than one step
6814 dbg->warning("karte_t::interactive", "server lagging by %lli", timelag );
6815 }
6816
6817 nwc_check_t* nwc = new nwc_check_t(sync_steps + 1, map_counter, LCHKLST(sync_steps), sync_steps);
6818 network_send_all(nwc, true);
6819 }
6820 else {
6821 // broadcast sync_step
6822 nwc_step_t* nwcstep = new nwc_step_t(sync_steps, map_counter);
6823 network_send_all(nwcstep, true);
6824 }
6825 }
6826 #if DEBUG>4
6827 if( env_t::networkmode && (sync_steps & 7)==0 && env_t::verbose_debug>4 ) {
6828 dbg->message("karte_t::interactive", "time=%lu sync=%d rand=%d", dr_time(), sync_steps, LRAND(sync_steps));
6829 }
6830 #endif
6831
6832 // no clients -> pause game
6833 if ( env_t::networkmode && env_t::pause_server_no_clients && socket_list_t::get_playing_clients() == 0 && !nwc_join_t::is_pending() ) {
6834 set_pause(true);
6835 }
6836 }
6837 else {
6838 INT_CHECK( "karte_t::interactive()" );
6839 set_random_mode( STEP_RANDOM );
6840 step();
6841 clear_random_mode( STEP_RANDOM );
6842 idle_time = ((idle_time*7) + next_step_time - dr_time())/8;
6843 INT_CHECK( "karte_t::interactive()" );
6844 }
6845 }
6846 }
6847
6848 // Interval-based server announcements
6849 if ( env_t::server && env_t::server_announce && env_t::server_announce_interval > 0 &&
6850 dr_time() - server_last_announce_time >= (uint32)env_t::server_announce_interval * 1000 ) {
6851 announce_server( 1 );
6852 }
6853
6854 DBG_DEBUG4("karte_t::interactive", "point of loop return");
6855 } while(!finish_loop && get_current_month()<quit_month);
6856
6857 if( get_current_month() >= quit_month ) {
6858 env_t::quit_simutrans = true;
6859 }
6860
6861 // On quit announce server as being offline
6862 if( env_t::server && env_t::server_announce ) {
6863 announce_server( 2 );
6864 }
6865
6866 intr_enable();
6867 display_show_pointer(true);
6868 return finish_loop;
6869 #undef LRAND
6870 }
6871
6872
6873 // Announce server to central listing server
6874 // Status is one of:
6875 // 0 - startup
6876 // 1 - interval
6877 // 2 - shutdown
announce_server(int status)6878 void karte_t::announce_server(int status)
6879 {
6880 DBG_DEBUG( "announce_server()", "status: %i", status );
6881 // Announce game info to server, format is:
6882 // st=on&dns=server.com&port=13353&rev=1234&pak=pak128&name=some+name&time=3,1923&size=256,256&active=[0-16]&locked=[0-16]&clients=[0-16]&towns=15&citizens=3245&factories=33&convoys=56&stops=17
6883 // (This is the data part of an HTTP POST)
6884 if( env_t::server && env_t::server_announce ) {
6885 // in easy_server mode, we assume the IP may change frequently and thus query it before each announce
6886 cbuffer_t buf, altbuf;
6887 if( env_t::easy_server && status<2 && get_external_IP(buf,altbuf) ) {
6888 // ipdate IP just in case
6889 if( status == 1 && (env_t::server_dns.compare( buf ) || env_t::server_alt_dns.compare( altbuf )) ) {
6890 announce_server( 2 );
6891 status = 0; // since starting with new IP
6892 // if we had uPnP, we may need to drill another hole in the firewall again; the delay is no problem, since all clients will be lost anyway
6893 char IP[256], altIP[256];
6894 prepare_for_server( IP, altIP, env_t::server_port );
6895 }
6896 // now update DNS info
6897 env_t::server_dns = (const char *)buf;
6898 env_t::server_alt_dns = (const char *)altbuf;
6899 }
6900 // Always send dns and port as these are used as the unique identifier for the server
6901 buf.clear();
6902 buf.append( "&dns=" );
6903 encode_URI( buf, env_t::server_dns.c_str() );
6904 buf.append( "&alt_dns=" );
6905 encode_URI( buf, env_t::server_alt_dns.c_str() );
6906 buf.printf( "&port=%u", env_t::server );
6907 // Always send announce interval to allow listing server to predict next announce
6908 buf.printf( "&aiv=%u", env_t::server_announce_interval );
6909 // Always send status, either online or offline
6910 if ( status == 0 || status == 1 ) {
6911 buf.append( "&st=1" );
6912 }
6913 else {
6914 buf.append( "&st=0" );
6915 }
6916 #ifndef REVISION
6917 # define REVISION 0
6918 #endif
6919 // Simple revision used for matching (integer)
6920 buf.printf( "&rev=%d", atol( QUOTEME(REVISION) ) );
6921 // Complex version string used for display
6922 buf.printf( "&ver=Simutrans %s (r%s) built %s", QUOTEME(VERSION_NUMBER), QUOTEME(REVISION), QUOTEME(VERSION_DATE) );
6923 // Pakset version
6924 buf.append( "&pak=" );
6925 // Announce pak set, ideally get this from the copyright field of ground.Outside.pak
6926 char const* const copyright = ground_desc_t::outside->get_copyright();
6927 if (copyright && STRICMP("none", copyright) != 0) {
6928 // construct from outside object copyright string
6929 encode_URI( buf, copyright );
6930 }
6931 else {
6932 // construct from pak name
6933 std::string pak_name = env_t::objfilename;
6934 pak_name.erase( pak_name.length() - 1 );
6935 encode_URI( buf, pak_name.c_str() );
6936 }
6937 // TODO - change this to be the start date of the current map
6938 buf.printf( "&start=%u,%u", settings.get_starting_month() + 1, settings.get_starting_year() );
6939 // Add server name for listing
6940 buf.append( "&name=" );
6941 encode_URI( buf, env_t::server_name.c_str() );
6942 // Add server comments for listing
6943 buf.append( "&comments=" );
6944 encode_URI( buf, env_t::server_comments.c_str() );
6945 // Add server maintainer email for listing
6946 buf.append( "&email=" );
6947 encode_URI( buf, env_t::server_email.c_str() );
6948 // Add server pakset URL for listing
6949 buf.append( "&pakurl=" );
6950 encode_URI( buf, env_t::server_pakurl.c_str() );
6951 // Add server info URL for listing
6952 buf.append( "&infurl=" );
6953 encode_URI( buf, env_t::server_infurl.c_str() );
6954
6955 // Now add the game data part
6956 uint8 active = 0, locked = 0;
6957 for( uint8 i=0; i<MAX_PLAYER_COUNT; i++ ) {
6958 if( players[i] && players[i]->get_ai_id()!=player_t::EMPTY ) {
6959 active ++;
6960 if( players[i]->is_locked() ) {
6961 locked ++;
6962 }
6963 }
6964 }
6965 buf.printf( "&time=%u,%u", (get_current_month() % 12) + 1, get_current_month() / 12 );
6966 buf.printf( "&size=%u,%u", get_size().x, get_size().y );
6967 buf.printf( "&active=%u", active );
6968 buf.printf( "&locked=%u", locked );
6969 buf.printf( "&clients=%u", socket_list_t::get_playing_clients() );
6970 buf.printf( "&towns=%u", stadt.get_count() );
6971 buf.printf( "&citizens=%u", stadt.get_sum_weight() );
6972 buf.printf( "&factories=%u", fab_list.get_count() );
6973 buf.printf( "&convoys=%u", convoys().get_count());
6974 buf.printf( "&stops=%u", haltestelle_t::get_alle_haltestellen().get_count() );
6975
6976 network_http_post( ANNOUNCE_SERVER, ANNOUNCE_URL, buf, NULL );
6977
6978 // Record time of this announce
6979 server_last_announce_time = dr_time();
6980 }
6981 }
6982
6983
network_disconnect()6984 void karte_t::network_disconnect()
6985 {
6986 // force disconnect
6987 dbg->warning("karte_t::network_disconnect()", "Lost synchronisation with server.");
6988 network_core_shutdown();
6989 destroy_all_win(true);
6990
6991 clear_random_mode( INTERACTIVE_RANDOM );
6992 step_mode = NORMAL;
6993 reset_timer();
6994 clear_command_queue();
6995 create_win( display_get_width()/2-128, 40, new news_img("Lost synchronisation\nwith server."), w_info, magic_none);
6996 ticker::add_msg( translator::translate("Lost synchronisation\nwith server."), koord::invalid, color_idx_to_rgb(COL_BLACK) );
6997 last_active_player_nr = active_player_nr;
6998
6999 stop(false);
7000 }
7001
7002
sort_ware_by_name(const goods_desc_t * a,const goods_desc_t * b)7003 static bool sort_ware_by_name(const goods_desc_t* a, const goods_desc_t* b)
7004 {
7005 int diff = strcmp(translator::translate(a->get_name()), translator::translate(b->get_name()));
7006 return diff < 0;
7007 }
7008
7009
7010 // Returns a list of goods produced by factories that exist in current game
get_goods_list()7011 const vector_tpl<const goods_desc_t*> &karte_t::get_goods_list()
7012 {
7013 if (goods_in_game.empty()) {
7014 // Goods list needs to be rebuilt
7015
7016 // Reset last vehicle filter in all depots, in case goods list has changed
7017 FOR(slist_tpl<depot_t*>, const d, depot_t::get_depot_list()) {
7018 d->selected_filter = VEHICLE_FILTER_RELEVANT;
7019 }
7020
7021 FOR(slist_tpl<fabrik_t*>, const factory, get_fab_list()) {
7022 slist_tpl<goods_desc_t const*>* const produced_goods = factory->get_produced_goods();
7023 FOR(slist_tpl<goods_desc_t const*>, const good, *produced_goods) {
7024 goods_in_game.insert_unique_ordered(good, sort_ware_by_name);
7025 }
7026 delete produced_goods;
7027 }
7028 goods_in_game.insert_at(0, goods_manager_t::passengers);
7029 goods_in_game.insert_at(1, goods_manager_t::mail);
7030 }
7031
7032 return goods_in_game;
7033 }
7034
get_public_player() const7035 player_t *karte_t::get_public_player() const
7036 {
7037 return get_player(1);
7038 }
7039