1 /*
2  * Copyright (c) 1997 - 2001 Hansjoerg Malthaner
3  *
4  * This file is part of the Simutrans project under the artistic licence.
5  * (see licence.txt)
6  *
7  * Ways (Roads, Railways, etc.)
8  *
9  * Hj. Malthaner
10  */
11 
12 #include <algorithm>
13 
14 #include "../simdebug.h"
15 #include "../simworld.h"
16 #include "../simtool.h"
17 #include "../simmesg.h"
18 #include "../simintr.h"
19 #include "../player/simplay.h"
20 #include "../simplan.h"
21 #include "../simdepot.h"
22 
23 #include "wegbauer.h"
24 #include "brueckenbauer.h"
25 #include "tunnelbauer.h"
26 
27 #include "../descriptor/way_desc.h"
28 #include "../descriptor/tunnel_desc.h"
29 #include "../descriptor/building_desc.h"
30 #include "../descriptor/crossing_desc.h"
31 
32 #include "../boden/wege/strasse.h"
33 #include "../boden/wege/schiene.h"
34 #include "../boden/wege/monorail.h"
35 #include "../boden/wege/maglev.h"
36 #include "../boden/wege/narrowgauge.h"
37 #include "../boden/wege/kanal.h"
38 #include "../boden/wege/runway.h"
39 #include "../boden/brueckenboden.h"
40 #include "../boden/monorailboden.h"
41 #include "../boden/tunnelboden.h"
42 #include "../boden/grund.h"
43 
44 #include "../dataobj/environment.h"
45 #include "../dataobj/route.h"
46 #include "../dataobj/marker.h"
47 #include "../dataobj/translator.h"
48 #include "../dataobj/scenario.h"
49 
50 #include "../utils/simrandom.h"
51 
52 // binary heap, since we only need insert and pop
53 #include "../tpl/binary_heap_tpl.h" // fastest
54 
55 #include "../obj/field.h"
56 #include "../obj/gebaeude.h"
57 #include "../obj/bruecke.h"
58 #include "../obj/tunnel.h"
59 #include "../obj/crossing.h"
60 #include "../obj/leitung2.h"
61 #include "../obj/groundobj.h"
62 #include "../obj/wayobj.h"
63 
64 #include "../ifc/simtestdriver.h"
65 
66 #include "../tpl/stringhashtable_tpl.h"
67 
68 #include "../gui/minimap.h" // for debugging
69 #include "../gui/tool_selector.h"
70 #include "../gui/messagebox.h"
71 
72 #ifdef DEBUG_ROUTES
73 #include "../simsys.h"
74 #endif
75 
76 // built bridges automatically
77 //#define AUTOMATIC_BRIDGES
78 
79 // built tunnels automatically
80 //#define AUTOMATIC_TUNNELS
81 
82 // lookup also return route and take the better of the two
83 #define REVERSE_CALC_ROUTE_TOO
84 
85 karte_ptr_t way_builder_t::welt;
86 
87 const way_desc_t *way_builder_t::leitung_desc = NULL;
88 
89 static stringhashtable_tpl <const way_desc_t *> desc_table;
90 
91 
set_default(way_desc_t const * & def,waytype_t const wtyp,systemtype_t const system_type=type_flat,sint32 const speed_limit=1)92 static void set_default(way_desc_t const*& def, waytype_t const wtyp, systemtype_t const system_type = type_flat, sint32 const speed_limit = 1)
93 {
94 	def = way_builder_t::weg_search(wtyp, speed_limit, 0, system_type);
95 	if (def == NULL) {
96 		def = way_builder_t::weg_search(wtyp, 1, 0, type_all);
97 	}
98 }
99 
100 
successfully_loaded()101 bool way_builder_t::successfully_loaded()
102 {
103 	// some defaults to avoid hardcoded values
104 	set_default(strasse_t::default_strasse,         road_wt,        type_flat, 50);
105 	if(  strasse_t::default_strasse == NULL ) {
106 		dbg->fatal( "way_builder_t::successfully_loaded()", "No road found at all!" );
107 		return false;
108 	}
109 
110 	set_default(schiene_t::default_schiene,         track_wt,       type_flat, 80);
111 	set_default(monorail_t::default_monorail,       monorail_wt,    type_elevated); // Only elevated?
112 	set_default(maglev_t::default_maglev,           maglev_wt,      type_elevated); // Only elevated?
113 	set_default(narrowgauge_t::default_narrowgauge, narrowgauge_wt);
114 	set_default(kanal_t::default_kanal,             water_wt,       type_all); // Also find hidden rivers.
115 	set_default(runway_t::default_runway,           air_wt,         type_runway);
116 	set_default(way_builder_t::leitung_desc,          powerline_wt);
117 
118 	return true;
119 }
120 
121 
register_desc(way_desc_t * desc)122 bool way_builder_t::register_desc(way_desc_t *desc)
123 {
124 	if(  const way_desc_t *old_desc = desc_table.remove(desc->get_name())  ) {
125 		dbg->doubled( "way", desc->get_name() );
126 		tool_t::general_tool.remove( old_desc->get_builder() );
127 		delete old_desc->get_builder();
128 		delete old_desc;
129 	}
130 
131 	if(  desc->get_cursor()->get_image_id(1)!=IMG_EMPTY  ) {
132 		// add the tool
133 		tool_build_way_t *tool = new tool_build_way_t();
134 		tool->set_icon( desc->get_cursor()->get_image_id(1) );
135 		tool->cursor = desc->get_cursor()->get_image_id(0);
136 		tool->set_default_param(desc->get_name());
137 		tool_t::general_tool.append( tool );
138 		desc->set_builder( tool );
139 	}
140 	else {
141 		desc->set_builder( NULL );
142 	}
143 	desc_table.put(desc->get_name(), desc);
144 	return true;
145 }
146 
147 
get_way_list(const waytype_t wtyp,systemtype_t styp)148 const vector_tpl<const way_desc_t *>&  way_builder_t::get_way_list(const waytype_t wtyp, systemtype_t styp)
149 {
150 	static vector_tpl<const way_desc_t *> dummy;
151 	dummy.clear();
152 	const uint16 time = welt->get_timeline_year_month();
153 	FOR(stringhashtable_tpl<way_desc_t const*>, const& i, desc_table) {
154 		way_desc_t const* const test = i.value;
155 		if( test->get_wtyp()==wtyp  &&  test->get_styp()== styp  &&  test->is_available(time)  &&  test->get_builder() ) {
156 			dummy.append(test);
157 		}
158 	}
159 	return dummy;
160 }
161 
162 
163 /**
164  * Finds a way with a given speed limit for a given waytype
165  * It finds:
166  *  - the slowest way, as fast as speed limit
167  *  - if no way faster than speed limit, the fastest way.
168  * The timeline is also respected.
169  * @author prissi, gerw
170  */
weg_search(const waytype_t wtyp,const sint32 speed_limit,const uint16 time,const systemtype_t system_type)171 const way_desc_t* way_builder_t::weg_search(const waytype_t wtyp, const sint32 speed_limit, const uint16 time, const systemtype_t system_type)
172 {
173 	const way_desc_t* best = NULL;
174 	bool best_allowed = false; // Does the best way fulfil the timeline?
175 	FOR(stringhashtable_tpl<way_desc_t const*>, const& i, desc_table) {
176 		way_desc_t const* const test = i.value;
177 		if(  ((test->get_wtyp()==wtyp  &&
178 			(test->get_styp()==system_type  ||  system_type==type_all))  ||  (test->get_wtyp()==track_wt  &&  test->get_styp()==type_tram  &&  wtyp==tram_wt))
179 			&&  test->get_cursor()->get_image_id(1)!=IMG_EMPTY  ) {
180 			bool test_allowed = test->get_intro_year_month()<=time  &&  time<test->get_retire_year_month();
181 				if(  !best_allowed  ||  time==0  ||  test_allowed  ) {
182 					if(  best==NULL  ||
183 						( best->get_topspeed() <  test->get_topspeed()  &&  test->get_topspeed() <=     speed_limit  )    || // closer to desired speed (from the low end)
184 						(     speed_limit      <  best->get_topspeed()  &&  test->get_topspeed() <   best->get_topspeed()) || // respects speed_limit better
185 						( time!=0  &&  !best_allowed  &&  test_allowed)                                                       // current choice is actually not really allowed, timewise
186 						) {
187 							best = test;
188 							best_allowed = test_allowed;
189 					}
190 				}
191 		}
192 	}
193 	return best;
194 }
195 
196 
197 
get_earliest_way(const waytype_t wtyp)198 const way_desc_t *way_builder_t::get_earliest_way(const waytype_t wtyp)
199 {
200 	const way_desc_t *desc = NULL;
201 	FOR(stringhashtable_tpl<way_desc_t const*>, const& i, desc_table) {
202 		way_desc_t const* const test = i.value;
203 		if(  test->get_wtyp()==wtyp  &&  (desc==NULL  ||  test->get_intro_year_month()<desc->get_intro_year_month())  ) {
204 			desc = test;
205 		}
206 	}
207 	return desc;
208 }
209 
210 
211 
get_latest_way(const waytype_t wtyp)212 const way_desc_t *way_builder_t::get_latest_way(const waytype_t wtyp)
213 {
214 	const way_desc_t *desc = NULL;
215 	FOR(stringhashtable_tpl<way_desc_t const*>, const& i, desc_table) {
216 		way_desc_t const* const test = i.value;
217 		if(  test->get_wtyp()==wtyp  &&  (desc==NULL  ||  test->get_retire_year_month()>desc->get_retire_year_month())  ) {
218 			desc = test;
219 		}
220 	}
221 	return desc;
222 }
223 
224 
225 // ture if the way is available with timely
waytype_available(const waytype_t wtyp,uint16 time)226 bool way_builder_t::waytype_available( const waytype_t wtyp, uint16 time )
227 {
228 	if(  time==0  ) {
229 		return true;
230 	}
231 
232 	FOR(stringhashtable_tpl<way_desc_t const*>, const& i, desc_table) {
233 		way_desc_t const* const test = i.value;
234 		if(  test->get_wtyp()==wtyp  &&  test->get_intro_year_month()<=time  &&  test->get_retire_year_month()>time  ) {
235 			return true;
236 		}
237 	}
238 	return false;
239 }
240 
241 
242 
get_desc(const char * way_name,const uint16 time)243 const way_desc_t * way_builder_t::get_desc(const char * way_name, const uint16 time)
244 {
245 //DBG_MESSAGE("way_builder_t::get_desc","return desc for %s in (%i)",way_name, time/12);
246 	const way_desc_t *desc = desc_table.get(way_name);
247 	if(  desc  &&  desc->is_available(time)  ) {
248 		return desc;
249 	}
250 	return NULL;
251 }
252 
253 
254 
255 // generates timeline message
new_month()256 void way_builder_t::new_month()
257 {
258 	const uint16 current_month = welt->get_timeline_year_month();
259 	if(current_month!=0) {
260 		// check, what changed
261 		slist_tpl <const way_desc_t *> matching;
262 		FOR(stringhashtable_tpl<way_desc_t const*>, const& i, desc_table) {
263 			way_desc_t const* const desc = i.value;
264 			cbuffer_t buf;
265 
266 			const uint16 intro_month = desc->get_intro_year_month();
267 			if(intro_month == current_month) {
268 				buf.printf( translator::translate("way %s now available:\n"), translator::translate(desc->get_name()) );
269 				welt->get_message()->add_message(buf,koord::invalid,message_t::new_vehicle,NEW_VEHICLE,desc->get_image_id(5,0));
270 			}
271 
272 			const uint16 retire_month = desc->get_retire_year_month();
273 			if(retire_month == current_month) {
274 				buf.printf( translator::translate("way %s cannot longer used:\n"), translator::translate(desc->get_name()) );
275 				welt->get_message()->add_message(buf,koord::invalid,message_t::new_vehicle,NEW_VEHICLE,desc->get_image_id(5,0));
276 			}
277 		}
278 
279 	}
280 }
281 
282 
compare_ways(const way_desc_t * a,const way_desc_t * b)283 static bool compare_ways(const way_desc_t* a, const way_desc_t* b)
284 {
285 	int cmp = a->get_topspeed() - b->get_topspeed();
286 	if(cmp==0) {
287 		cmp = (int)a->get_intro_year_month() - (int)b->get_intro_year_month();
288 	}
289 	if(cmp==0) {
290 		cmp = strcmp(a->get_name(), b->get_name());
291 	}
292 	return cmp<0;
293 }
294 
295 
296 /**
297  * Fill menu with icons of given waytype, return number of added entries
298  * @author Hj. Malthaner/prissi/dariok
299  */
fill_menu(tool_selector_t * tool_selector,const waytype_t wtyp,const systemtype_t styp,sint16)300 void way_builder_t::fill_menu(tool_selector_t *tool_selector, const waytype_t wtyp, const systemtype_t styp, sint16 /*ok_sound*/)
301 {
302 	// check if scenario forbids this
303 	const waytype_t rwtyp = wtyp!=track_wt  || styp!=type_tram  ? wtyp : tram_wt;
304 	if (!welt->get_scenario()->is_tool_allowed(welt->get_active_player(), TOOL_BUILD_WAY | GENERAL_TOOL, rwtyp)) {
305 		return;
306 	}
307 
308 	const uint16 time = welt->get_timeline_year_month();
309 
310 	// list of matching types (sorted by speed)
311 	vector_tpl<const way_desc_t*> matching;
312 
313 	FOR(stringhashtable_tpl<way_desc_t const*>, const& i, desc_table) {
314 		way_desc_t const* const desc = i.value;
315 		if (  desc->get_styp()==styp &&  desc->get_wtyp()==wtyp  &&  desc->get_builder()  &&  desc->is_available(time)  ) {
316 				matching.append(desc);
317 		}
318 	}
319 	std::sort(matching.begin(), matching.end(), compare_ways);
320 
321 	// now add sorted ways ...
322 	FOR(vector_tpl<way_desc_t const*>, const i, matching) {
323 		tool_selector->add_tool_selector(i->get_builder());
324 	}
325 }
326 
327 
328 /* allow for railroad crossing
329  * @author prissi
330  */
check_crossing(const koord zv,const grund_t * bd,waytype_t wtyp0,const player_t * player) const331 bool way_builder_t::check_crossing(const koord zv, const grund_t *bd, waytype_t wtyp0, const player_t *player) const
332 {
333 	const waytype_t wtyp = wtyp0==tram_wt ? track_wt : wtyp0;
334 	// nothing to cross here
335 	if (!bd->hat_wege()) {
336 		return true;
337 	}
338 	// no triple crossings please
339 	if (bd->has_two_ways() && !bd->hat_weg(wtyp)) {
340 		return false;
341 	}
342 	const weg_t *w = bd->get_weg_nr(0);
343 	// index of our wtype at the tile (must exists due to triple-crossing-check above)
344 	const uint8 iwtyp = w->get_waytype() != wtyp;
345 	// get the other way
346 	if(iwtyp==0) {
347 		w = bd->get_weg_nr(1);
348 		// no other way here
349 		if (w==NULL) {
350 			return true;
351 		}
352 	}
353 	// special case: tram track on road
354 	if ( (wtyp==road_wt  &&  w->get_waytype()==track_wt  &&  w->get_desc()->get_styp()==type_tram)  ||
355 		     (wtyp0==tram_wt  &&  w->get_waytype()==road_wt) ) {
356 		return true;
357 	}
358 	// right owner of the other way
359 	if(!check_owner(w->get_owner(),player)) {
360 		return false;
361 	}
362 	// check for existing crossing
363 	crossing_t *cr = bd->find<crossing_t>();
364 	if (cr) {
365 		// index of the waytype in ns-direction at the crossing
366 		const uint8 ns_way = cr->get_dir();
367 		// only cross with the right direction
368 		return (ns_way==iwtyp ? ribi_t::is_straight_ns(ribi_type(zv)) : ribi_t::is_straight_ew(ribi_type(zv)));
369 	}
370 	// no crossings in tunnels
371 	if((bautyp & tunnel_flag)!=0  || bd->ist_tunnel()) {
372 		return false;
373 	}
374 	// no crossings on elevated ways
375 	if((bautyp & elevated_flag)!=0  ||  bd->get_typ()==grund_t::monorailboden) {
376 		return false;
377 	}
378 	// crossing available and ribis ok
379 	if(crossing_logic_t::get_crossing(wtyp, w->get_waytype(), 0, 0, welt->get_timeline_year_month())!=NULL) {
380 		ribi_t::ribi w_ribi = w->get_ribi_unmasked();
381 		// it is our way we want to cross: can we built a crossing here?
382 		// both ways must be straight and no ends
383 		return  ribi_t::is_straight(w_ribi)
384 					&&  !ribi_t::is_single(w_ribi)
385 					&&  ribi_t::is_straight(ribi_type(zv))
386 				&&  (w_ribi&ribi_type(zv))==0;
387 	}
388 	// cannot build crossing here
389 	return false;
390 }
391 
392 
393 /* crossing of powerlines, or no powerline
394  * @author prissi
395  */
check_powerline(const koord zv,const grund_t * bd) const396 bool way_builder_t::check_powerline(const koord zv, const grund_t *bd) const
397 {
398 	if(zv==koord(0,0)) {
399 		return true;
400 	}
401 	leitung_t* lt = bd->find<leitung_t>();
402 	if(lt!=NULL) {
403 		ribi_t::ribi lt_ribi = lt->get_ribi();
404 		// it is our way we want to cross: can we built a crossing here?
405 		// both ways must be straight and no ends
406 		return
407 		  ribi_t::is_straight(lt_ribi)
408 		  &&  !ribi_t::is_single(lt_ribi)
409 		  &&  ribi_t::is_straight(ribi_type(zv))
410 		  &&  (lt_ribi&ribi_type(zv))==0
411 		  &&  !bd->ist_tunnel();
412 	}
413 	// check for transformer
414 	if (bd->find<pumpe_t>() != NULL || bd->find<senke_t>()  != NULL) {
415 		return false;
416 	}
417 	// ok, there is not high power transmission stuff going on here
418 	return true;
419 }
420 
421 
422 // allowed slope?
check_slope(const grund_t * from,const grund_t * to)423 bool way_builder_t::check_slope( const grund_t *from, const grund_t *to )
424 {
425 	const koord from_pos=from->get_pos().get_2d();
426 	const koord to_pos=to->get_pos().get_2d();
427 	const koord zv=to_pos-from_pos;
428 
429 	if(  !desc->has_double_slopes()
430 		&&  (    (from->get_weg_hang()  &&  !(from->get_weg_hang() & 7))
431 		      ||   (to->get_weg_hang()  &&    !(to->get_weg_hang() & 7))  )  ) {
432 		return false;
433 	}
434 
435 	if(from==to) {
436 		if(!slope_t::is_way(from->get_weg_hang())) {
437 			return false;
438 		}
439 	}
440 	else {
441 		if(from->get_weg_hang()  &&  ribi_t::doubles(ribi_type(from->get_weg_hang()))!=ribi_t::doubles(ribi_type(zv))) {
442 			return false;
443 		}
444 		if(to->get_weg_hang()  &&  ribi_t::doubles(ribi_type(to->get_weg_hang()))!=ribi_t::doubles(ribi_type(zv))) {
445 			return false;
446 		}
447 	}
448 
449 	return true;
450 }
451 
452 
453 // allowed owner?
check_owner(const player_t * player1,const player_t * player2) const454 bool way_builder_t::check_owner( const player_t *player1, const player_t *player2 ) const
455 {
456 	// unowned, mine or public property or superuser ... ?
457 	return player1==NULL  ||  player1==player2  ||  player1==welt->get_public_player()  ||  player2==welt->get_public_player();
458 }
459 
460 
461 /* do not go through depots, station buildings etc. ...
462  * direction results from layout
463  */
check_building(const grund_t * to,const koord dir) const464 bool way_builder_t::check_building( const grund_t *to, const koord dir ) const
465 {
466 	if(dir==koord(0,0)) {
467 		return true;
468 	}
469 	if(to->obj_count()<=0) {
470 		return true;
471 	}
472 
473 	// first find all kind of buildings
474 	gebaeude_t *gb = to->find<gebaeude_t>();
475 	if(gb==NULL) {
476 		// but depots might be overlooked ...
477 		depot_t* depot = to->get_depot();
478 		// no road to tram depot and vice-versa
479 		if (depot) {
480 			if ( (waytype_t)(bautyp&bautyp_mask) != depot->get_waytype() ) {
481 				return false;
482 			}
483 		}
484 		gb = depot;
485 	}
486 	// check, if we may enter
487 	if(gb) {
488 		// now check for directions
489 		uint8 layouts = gb->get_tile()->get_desc()->get_all_layouts();
490 		uint8 layout = gb->get_tile()->get_layout();
491 		ribi_t::ribi r = ribi_type(dir);
492 		if(  layouts&1  ) {
493 			return false;
494 		}
495 		if(  layouts==4  ) {
496 			return  r == ribi_t::layout_to_ribi[layout];
497 		}
498 		return ribi_t::is_straight( r | ribi_t::doubles(ribi_t::layout_to_ribi[layout&1]) );
499 	}
500 	return true;
501 }
502 
503 
504 /* This is the core routine for the way search
505  * it will check
506  * A) allowed step
507  * B) if allowed, calculate the cost for the step from from to to
508  * @author prissi
509  */
is_allowed_step(const grund_t * from,const grund_t * to,sint32 * costs,bool is_upperlayer) const510 bool way_builder_t::is_allowed_step(const grund_t *from, const grund_t *to, sint32 *costs, bool is_upperlayer ) const
511 {
512 	const koord from_pos=from->get_pos().get_2d();
513 	const koord to_pos=to->get_pos().get_2d();
514 	const koord zv=to_pos-from_pos;
515 	// fake empty elevated tiles
516 	static monorailboden_t to_dummy(koord3d::invalid, slope_t::flat);
517 	static monorailboden_t from_dummy(koord3d::invalid, slope_t::flat);
518 
519 	if(bautyp==luft  &&  (from->get_grund_hang()+to->get_grund_hang()!=0  ||  (from->hat_wege()  &&  from->hat_weg(air_wt)==0)  ||  (to->hat_wege()  &&  to->hat_weg(air_wt)==0))) {
520 		// absolutely no slopes for runways, neither other ways
521 		return false;
522 	}
523 
524 	bool to_flat = false; // to tile will be flattened
525 	if(from==to) {
526 		if((bautyp&tunnel_flag)  &&  !slope_t::is_way(from->get_weg_hang())) {
527 			return false;
528 		}
529 	}
530 	else {
531 		// check slopes
532 		bool ok_slope = from->get_weg_hang() == slope_t::flat  ||  ribi_t::doubles(ribi_type(from->get_weg_hang()))==ribi_t::doubles(ribi_type(zv));
533 		ok_slope &= to->get_weg_hang() == slope_t::flat  ||  ribi_t::doubles(ribi_type(to->get_weg_hang()))==ribi_t::doubles(ribi_type(zv));
534 
535 		// try terraforming
536 		if (!ok_slope) {
537 			uint8 dummy,to_slope;
538 			if (  (bautyp & terraform_flag) != 0  &&  from->ist_natur()  &&  to->ist_natur()  &&  check_terraforming(from,to,&dummy,&to_slope) ) {
539 				to_flat = to_slope == slope_t::flat;
540 			}
541 			else {
542 				// slopes not ok and no terraforming possible
543 				return false;
544 			}
545 		}
546 	}
547 
548 	// ok, slopes are ok
549 	bool ok = true;
550 
551 	// check scenario conditions
552 	if (welt->get_scenario()->is_work_allowed_here(player_builder, (bautyp&tunnel_flag ? TOOL_BUILD_TUNNEL : TOOL_BUILD_WAY)|GENERAL_TOOL, bautyp&bautyp_mask, to->get_pos()) != NULL) {
553 		return false;
554 	}
555 
556 	// universal check for elevated things ...
557 	if(bautyp&elevated_flag) {
558 		if(  is_upperlayer  ) {
559 			if(  (to->get_typ() != grund_t::monorailboden ||  to->get_weg_nr(0)->get_desc()->get_wtyp()!=desc->get_wtyp()  ||  !check_owner(to->obj_bei(0)->get_owner(),player_builder) )  ||  (from->get_typ() != grund_t::monorailboden ||  from->get_weg_nr(0)->get_desc()->get_wtyp()!=desc->get_wtyp()  ||  !check_owner(from->obj_bei(0)->get_owner(),player_builder) )  ) {
560 				return false;
561 			}
562 		}
563 		else {
564 			if(  to->hat_weg(air_wt)  ||  welt->lookup_hgt( to_pos ) < welt->get_water_hgt( to_pos )  ||  !check_powerline( zv, to )  ||  (!to->ist_karten_boden()  &&  to->get_typ() != grund_t::monorailboden)  ||  to->get_typ() == grund_t::brueckenboden  ||  to->get_typ() == grund_t::tunnelboden  ) {
565 				// no suitable ground below!
566 				return false;
567 			}
568 			gebaeude_t *gb = to->find<gebaeude_t>();
569 			if(gb==NULL) {
570 				// but depots might be overlooked ...
571 				gb = to->get_depot();
572 			}
573 			if(gb) {
574 				// no halt => citybuilding => do not touch
575 				// also check for too high buildings ...
576 				if(!check_owner(gb->get_owner(),player_builder)  ||  gb->get_tile()->get_background(0,1,0)!=IMG_EMPTY) {
577 					return false;
578 				}
579 				// building above houses is expensive ... avoid it!
580 				*costs += 4;
581 			}
582 			// absolutely nothing allowed here for set which want double clearance
583 			if(  welt->get_settings().get_way_height_clearance()==2  &&  welt->lookup( to->get_pos()+koord3d(0,0,1) )  ) {
584 				return false;
585 			}
586 			// up to now 'to' and 'from' referred to the ground one height step below the elevated way
587 			// now get the grounds at the right height
588 			koord3d pos = to->get_pos() + koord3d( 0, 0, welt->get_settings().get_way_height_clearance() );
589 			grund_t *to2 = welt->lookup(pos);
590 			if(to2) {
591 				if(to2->get_weg_nr(0)) {
592 					// already an elevated ground here => it will have always a way object, that indicates ownership
593 					ok = to2->get_typ()==grund_t::monorailboden  &&  check_owner(to2->obj_bei(0)->get_owner(),player_builder);
594 					ok &= to2->get_weg_nr(0)->get_desc()->get_wtyp()==desc->get_wtyp();
595 				}
596 				else {
597 					ok = to2->find<leitung_t>()==NULL;
598 				}
599 				if (!ok) {
600 					return false;
601 				}
602 				to = to2;
603 			}
604 			else {
605 				// simulate empty elevated tile
606 				to_dummy.set_pos(pos);
607 				to_dummy.set_grund_hang(to->get_grund_hang());
608 				to = &to_dummy;
609 			}
610 
611 			pos = from->get_pos() + koord3d( 0, 0, env_t::pak_height_conversion_factor );
612 			grund_t *from2 = welt->lookup(pos);
613 			if(from2) {
614 				from = from2;
615 			}
616 			else {
617 				// simulate empty elevated tile
618 				from_dummy.set_pos(pos);
619 				from_dummy.set_grund_hang(from->get_grund_hang());
620 				from = &from_dummy;
621 			}
622 			// now 'from' and 'to' point to grounds at the right height
623 		}
624 	}
625 
626 	if(  welt->get_settings().get_way_height_clearance()==2  ) {
627 		// cannot build if conversion factor 2, we aren't powerline and way with maximum speed > 0 or powerline 1 tile below
628 		grund_t *to2 = welt->lookup( to->get_pos() + koord3d(0, 0, -1) );
629 		if(  to2 && (((bautyp&bautyp_mask)!=leitung  &&  to2->get_weg_nr(0)  &&  to2->get_weg_nr(0)->get_desc()->get_topspeed()>0) || to2->get_leitung())  ) {
630 			return false;
631 		}
632 		// tile above cannot have way unless we are a way (not powerline) with a maximum speed of 0, or be surface if we are underground
633 		to2 = welt->lookup( to->get_pos() + koord3d(0, 0, 1) );
634 		if(  to2  &&  ((to2->get_weg_nr(0)  &&  (desc->get_topspeed()>0  ||  (bautyp&bautyp_mask)==leitung))  ||  (bautyp & tunnel_flag) != 0)  ) {
635 			return false;
636 		}
637 	}
638 
639 	// universal check for depots/stops/...
640 	if(  !check_building( from, zv )  ||  !check_building( to, -zv )  ) {
641 		return false;
642 	}
643 
644 	// universal check for bridges: enter bridges in bridge direction
645 	if( to->get_typ()==grund_t::brueckenboden ) {
646 		ribi_t::ribi br = ribi_type(zv);
647 		br  = to->hat_wege()    ? to->get_weg_nr(0)->get_ribi_unmasked() : (ribi_t::ribi)ribi_t::none;
648 		br |= to->get_leitung() ? to->get_leitung()->get_ribi()          : (ribi_t::ribi)ribi_t::none;
649 		if(!ribi_t::is_straight(br)) {
650 			return false;
651 		}
652 	}
653 	if( from->get_typ()==grund_t::brueckenboden ) {
654 		ribi_t::ribi br = ribi_type(zv);
655 		br  = from->hat_wege()    ? from->get_weg_nr(0)->get_ribi_unmasked() : (ribi_t::ribi)ribi_t::none;
656 		br |= from->get_leitung() ? from->get_leitung()->get_ribi()          : (ribi_t::ribi)ribi_t::none;
657 		if(!ribi_t::is_straight(br)) {
658 			return false;
659 		}
660 	}
661 
662 	// universal check: do not switch to tunnel through cliffs!
663 	if( from->get_typ() == grund_t::tunnelboden  &&  to->get_typ() != grund_t::tunnelboden  &&  !from->ist_karten_boden() ) {
664 		return false;
665 	}
666 	if( to->get_typ()==grund_t::tunnelboden  &&  from->get_typ() != grund_t::tunnelboden   &&  !to->ist_karten_boden() ) {
667 		return false;
668 	}
669 
670 	// universal check for crossings
671 	if (to!=from  &&  (bautyp&bautyp_mask)!=leitung) {
672 		waytype_t const wtyp = (bautyp == river) ? water_wt : (waytype_t)(bautyp & bautyp_mask);
673 		if(!check_crossing(zv,to,wtyp,player_builder)  ||  !check_crossing(-zv,from,wtyp,player_builder)) {
674 			return false;
675 		}
676 	}
677 
678 	// universal check for building under powerlines
679 	if ((bautyp&bautyp_mask)!=leitung) {
680 		if (!check_powerline(zv,to)  ||  !check_powerline(-zv,from)) {
681 			return false;
682 		}
683 	}
684 
685 	bool fundament = to->get_typ()==grund_t::fundament;
686 
687 	// now check way specific stuff
688 	settings_t const& s = welt->get_settings();
689 	switch(bautyp&bautyp_mask) {
690 
691 		case strasse:
692 		{
693 			const weg_t *str=to->get_weg(road_wt);
694 
695 			// we allow connection to any road
696 			ok = (str  ||  !fundament)  &&  !to->is_water();
697 			if(!ok) {
698 				return false;
699 			}
700 			// check for end/start of bridge or tunnel
701 			// fail if no proper way exists, or the way's ribi are not 0 and are not matching the slope type
702 			ribi_t::ribi test_ribi = (str ? str->get_ribi_unmasked() : 0) | ribi_type(zv);
703 			if(to->get_weg_hang()!=to->get_grund_hang()  &&  (str==NULL  ||  !(ribi_t::is_straight(test_ribi) || test_ribi==0 ))) {
704 				return false;
705 			}
706 			// calculate costs
707 			*costs = str ? 0 : s.way_count_straight;
708 			if((str==NULL  &&  to->hat_wege())  ||  (str  &&  to->has_two_ways())) {
709 				*costs += 4;	// avoid crossings
710 			}
711 			if(to->get_weg_hang()!=0  &&  !to_flat) {
712 				*costs += s.way_count_slope;
713 			}
714 		}
715 		break;
716 
717 		case schiene:
718 		default:
719 		{
720 			const weg_t *sch=to->get_weg(desc->get_wtyp());
721 			// extra check for AI construction (not adding to existing tracks!)
722 			if((bautyp&bot_flag)!=0  &&  (sch  ||  to->get_halt().is_bound())) {
723 				return false;
724 			}
725 			// ok, regular construction here
726 			// if no way there: check for right ground type, otherwise check owner
727 			ok = sch==NULL  ?  (!fundament  &&  !to->is_water())  :  check_owner(sch->get_owner(),player_builder);
728 			if(!ok) {
729 				return false;
730 			}
731 			// check for end/start of bridge or tunnel
732 			// fail if no proper way exists, or the way's ribi are not 0 and are not matching the slope type
733 			ribi_t::ribi test_ribi = (sch ? sch->get_ribi_unmasked() : 0) | ribi_type(zv);
734 			if(to->get_weg_hang()!=to->get_grund_hang()  &&  (sch==NULL  ||  !(ribi_t::is_straight(test_ribi) || test_ribi==0 ))) {
735 				return false;
736 			}
737 			// calculate costs
738 			*costs = s.way_count_straight;
739 			if (!sch) *costs += 1; // only prefer existing rails a little
740 			if((sch  &&  to->has_two_ways())  ||  (sch==NULL  &&  to->hat_wege())) {
741 				*costs += 4;	// avoid crossings
742 			}
743 			if(to->get_weg_hang()!=0  &&  !to_flat) {
744 				*costs += s.way_count_slope;
745 			}
746 		}
747 		break;
748 
749 		case schiene_tram: // Dario: Tramway
750 		{
751 			const weg_t *sch=to->get_weg(track_wt);
752 			// roads are checked in check_crossing
753 			// if no way there: check for right ground type, otherwise check owner
754 			ok = sch==NULL  ?  (!fundament  &&  !to->is_water())  :  check_owner(sch->get_owner(),player_builder);
755 			// tram track allowed in road tunnels, but only along existing roads / tracks
756 			if(from!=to) {
757 				if(from->ist_tunnel()) {
758 					const ribi_t::ribi ribi = from->get_weg_ribi_unmasked(road_wt)  |  from->get_weg_ribi_unmasked(track_wt)  |  ribi_t::doubles(ribi_type(from->get_grund_hang()));
759 					ok = ok && ((ribi & ribi_type(zv))==ribi_type(zv));
760 				}
761 				if(to->ist_tunnel()) {
762 					const ribi_t::ribi ribi = to->get_weg_ribi_unmasked(road_wt)  |  to->get_weg_ribi_unmasked(track_wt)  |  ribi_t::doubles(ribi_type(to->get_grund_hang()));
763 					ok = ok && ((ribi & ribi_type(-zv))==ribi_type(-zv));
764 				}
765 			}
766 			if(ok) {
767 				// calculate costs
768 				*costs = s.way_count_straight;
769 				if (!to->hat_weg(track_wt)) *costs += 1; // only prefer existing rails a little
770 				// prefer own track
771 				if(to->hat_weg(road_wt)) {
772 					*costs += s.way_count_straight;
773 				}
774 				if(to->get_weg_hang()!=0  &&  !to_flat) {
775 					*costs += s.way_count_slope;
776 				}
777 			}
778 		}
779 		break;
780 
781 		case leitung:
782 			ok = !to->is_water()  &&  (to->get_weg(air_wt)==NULL);
783 			ok &= !(to->ist_tunnel() && to->hat_wege());
784 			if(to->get_weg_nr(0)!=NULL) {
785 				// only 90 deg crossings, only a single way
786 				ribi_t::ribi w_ribi= to->get_weg_nr(0)->get_ribi_unmasked();
787 				ok &= ribi_t::is_straight(w_ribi)  &&  !ribi_t::is_single(w_ribi)  &&  ribi_t::is_straight(ribi_type(zv))  &&  (w_ribi&ribi_type(zv))==0;
788 			}
789 			if(to->has_two_ways()) {
790 				// only 90 deg crossings, only for trams ...
791 				ribi_t::ribi w_ribi= to->get_weg_nr(1)->get_ribi_unmasked();
792 				ok &= ribi_t::is_straight(w_ribi)  &&  !ribi_t::is_single(w_ribi)  &&  ribi_t::is_straight(ribi_type(zv))  &&  (w_ribi&ribi_type(zv))==0;
793 			}
794 			// do not connect to other powerlines
795 			{
796 				leitung_t *lt = to->get_leitung();
797 				ok &= (lt==NULL)  ||  check_owner(player_builder, lt->get_owner());
798 			}
799 
800 			if(to->get_typ()!=grund_t::tunnelboden) {
801 				// only fields are allowed
802 				if(to->get_typ()==grund_t::fundament) {
803 					ok &= to->find<field_t>()!=NULL;
804 				}
805 				// no bridges and monorails here in the air
806 				ok &= (welt->access(to_pos)->get_boden_in_hoehe(to->get_pos().z+1)==NULL);
807 			}
808 
809 			// calculate costs
810 			if(ok) {
811 				*costs = s.way_count_straight;
812 				if(  !to->get_leitung()  ) {
813 					// extra malus for not following an existing line or going on ways
814 					*costs += s.way_count_double_curve + (to->hat_wege() ? 8 : 0); // prefer existing powerlines
815 				}
816 			}
817 		break;
818 
819 		case wasser:
820 		{
821 			const weg_t *canal = to->get_weg(water_wt);
822 			// if no way there: check for right ground type, otherwise check owner
823 			ok = canal  ||  !fundament;
824 			// calculate costs
825 			if(ok) {
826 				*costs = to->is_water() ||  canal  ? s.way_count_straight : s.way_count_leaving_road; // prefer water very much
827 				if(to->get_weg_hang()!=0  &&  !to_flat) {
828 					*costs += s.way_count_slope * 2;
829 				}
830 			}
831 			break;
832 		}
833 
834 		case river:
835 			if(  to->is_water()  ) {
836 				ok = true;
837 				// do not care while in ocean
838 				*costs = 1;
839 			}
840 			else {
841 				// only downstream
842 				ok = from->get_pos().z>=to->get_pos().z  &&  (to->hat_weg(water_wt)  ||  !to->hat_wege());
843 				// calculate costs
844 				if(ok) {
845 					// prefer existing rivers:
846 					*costs = to->hat_weg(water_wt) ? 10 : 10+simrand(s.way_count_90_curve);
847 					if(to->get_weg_hang()!=0  &&  !to_flat) {
848 						*costs += s.way_count_slope * 10;
849 					}
850 				}
851 			}
852 			break;
853 
854 		case luft: // hsiegeln: runway
855 			{
856 				const weg_t *w = to->get_weg(air_wt);
857 				if(  w  &&  w->get_desc()->get_styp()==type_runway  &&  desc->get_styp()!=type_runway  &&  ribi_t::is_single(w->get_ribi_unmasked())  ) {
858 					// cannot go over the end of a runway with a taxiway
859 					return false;
860 				}
861 				ok = !to->is_water() && (w  ||  !to->hat_wege())  &&  to->find<leitung_t>()==NULL  &&  !fundament;
862 				// calculate costs
863 				*costs = s.way_count_straight;
864 			}
865 			break;
866 	}
867 	return ok;
868 }
869 
check_terraforming(const grund_t * from,const grund_t * to,uint8 * new_from_slope,uint8 * new_to_slope) const870 bool way_builder_t::check_terraforming( const grund_t *from, const grund_t *to, uint8* new_from_slope, uint8* new_to_slope) const
871 {
872 	// only for normal green tiles
873 	const slope_t::type from_slope = from->get_weg_hang();
874 	const slope_t::type to_slope = to->get_weg_hang();
875 	const sint8 from_hgt = from->get_hoehe();
876 	const sint8 to_hgt = to->get_hoehe();
877 	// we may change slope of a tile if it is sloped already
878 	if(  (from_slope == slope_t::flat  ||  from->get_hoehe() == welt->get_water_hgt( from->get_pos().get_2d() ))
879 	  &&  (to_slope == slope_t::flat  ||  to->get_hoehe() == welt->get_water_hgt( to->get_pos().get_2d() ))  ) {
880 		return false;
881 	}
882 	else if(  abs( from_hgt - to_hgt ) <= (desc->has_double_slopes() ? 2 : 1)  ) {
883 		// extra check for double heights
884 		if(  abs( from_hgt - to_hgt) == 2  &&  (welt->lookup( from->get_pos() - koord3d(0,0,2) ) != NULL  ||  welt->lookup( from->get_pos() + koord3d(0, 0, 2) ) != NULL
885 		  ||  welt->lookup( to->get_pos() - koord3d(0, 0, 2) ) != NULL  ||  welt->lookup( to->get_pos() + koord3d(0, 0, 2) ) != NULL)  ) {
886 			return false;
887 		}
888 		// monorail above / tunnel below
889 		if (welt->lookup(from->get_pos() - koord3d(0,0,1))!=NULL  ||  welt->lookup(from->get_pos() + koord3d(0,0,1))!=NULL
890 			||  welt->lookup(to->get_pos() - koord3d(0,0,1))!=NULL  ||  welt->lookup(to->get_pos() + koord3d(0,0,1))!=NULL) {
891 				return false;
892 		}
893 		// can safely change slope of at least one of the tiles
894 		if (new_from_slope == NULL) {
895 			return true;
896 		}
897 		// now calculate new slopes
898 		assert(new_from_slope);
899 		assert(new_to_slope);
900 		// direction of way
901 		const koord dir = (to->get_pos() - from->get_pos()).get_2d();
902 		sint8 start  = from_hgt * 2;
903 		sint8 middle = from_hgt * 2;
904 		sint8 end    = to_hgt * 2;
905 		// get 3 heights - start (min start from, but should be same), middle (average end from/average start to), end (min end to)
906 		if(  dir == koord::north  ) {
907 			start  += corner_sw(from_slope) + corner_se(from_slope);
908 			middle += corner_ne(from_slope) + corner_nw(from_slope);
909 			end    += corner_ne(to_slope) + corner_nw(to_slope);
910 		}
911 		else if(  dir == koord::east  ) {
912 			start  += corner_sw(from_slope) + corner_nw(from_slope);
913 			middle += corner_se(from_slope) + corner_ne(from_slope);
914 			end    += corner_se(to_slope) + corner_ne(to_slope);
915 		}
916 		else if(  dir == koord::south  ) {
917 			start  += corner_ne(from_slope) + corner_nw(from_slope);
918 			middle += corner_sw(from_slope) + corner_se(from_slope);
919 			end    += corner_sw(to_slope) + corner_se(to_slope);
920 		}
921 		else if(  dir == koord::west  ) {
922 			start  += corner_se(from_slope) + corner_ne(from_slope);
923 			middle += corner_sw(from_slope) + corner_nw(from_slope);
924 			end    += corner_sw(to_slope) + corner_nw(to_slope);
925 		}
926 		// work out intermediate height:
927 		if(  end == start  ) {
928 			middle = start;
929 		}
930 		else {
931 			//  end < start   to ist wegbar?assert from ist_wegbar:middle = end + 1
932 			//  end > start   to ist wegbar?assert from ist_wegbar:middle = end - 1
933 			if(  !slope_t::is_way( to_slope )  ) {
934 				middle = (start + end) / 2;
935 			}
936 		}
937 		// prevent middle being invalid
938 		if(  middle >> 1 > from_hgt + 2  ) {
939 			middle = (from_hgt + 2) * 2;
940 		}
941 		if(  middle >> 1 > to_hgt + 2  ) {
942 			middle = (to_hgt + 2) * 2;
943 		}
944 		if(  middle >> 1 < from_hgt  ) {
945 			middle = from_hgt * 2;
946 		}
947 		if(  middle >> 1 < to_hgt  ) {
948 			middle = to_hgt * 2;
949 		}
950 		const uint8 m_from = (middle >> 1) - from_hgt;
951 		const uint8 m_to = (middle >> 1) - to_hgt;
952 
953 		// write middle heights
954 		if(  dir == koord::north  ) {
955 			*new_from_slope = corner_sw(from_slope) + corner_se(from_slope) * 3 + m_from * 9              + m_from * 27;
956 			*new_to_slope =   m_to                + m_to * 3                + corner_ne(to_slope) * 9   + corner_nw(to_slope) * 27;
957 		}
958 		else if(  dir == koord::east  ) {
959 			*new_from_slope = corner_sw(from_slope) + m_from * 3              + m_from * 9              + corner_nw(from_slope) * 27;
960 			*new_to_slope =   m_to                + corner_se(to_slope) * 3   + corner_ne(to_slope) * 9   + m_to * 27;
961 		}
962 		else if(  dir == koord::south  ) {
963 			*new_from_slope = m_from              + m_from * 3              + corner_ne(from_slope) * 9 + corner_nw(from_slope) * 27;
964 			*new_to_slope =   corner_sw(to_slope)   + corner_se(to_slope) * 3   + m_to * 9                + m_to * 27;
965 		}
966 		else if(  dir == koord::west  ) {
967 			*new_from_slope = m_from              + corner_se(from_slope) * 3 + corner_ne(from_slope) * 9 + m_from * 27;
968 			*new_to_slope =   corner_sw(to_slope)   + m_to * 3                + m_to * 9                + corner_nw(to_slope) * 27;
969 		}
970 		return true;
971 	}
972 	return false;
973 }
974 
do_terraforming()975 void way_builder_t::do_terraforming()
976 {
977 	uint32 last_terraformed = terraform_index.get_count();
978 
979 	FOR(vector_tpl<uint32>, const i, terraform_index) { // index in route
980 		grund_t *from = welt->lookup(route[i]);
981 		uint8 from_slope = from->get_grund_hang();
982 
983 		grund_t *to = welt->lookup(route[i+1]);
984 		uint8 to_slope = to->get_grund_hang();
985 		// calculate new slopes
986 		check_terraforming(from, to, &from_slope, &to_slope);
987 		bool changed = false;
988 		// change slope of from
989 		if(  from_slope != from->get_grund_hang()  ) {
990 			if(  from_slope == slope_t::raised  ) {
991 				from->set_hoehe( from->get_hoehe() + 2 );
992 				from->set_grund_hang( slope_t::flat );
993 				route[i].z = from->get_hoehe();
994 			}
995 			else if(  from_slope != slope_t::raised / 2  ) {
996 				// bit of a hack to recognise single height slopes shifted up 1
997 				if(  from_slope > slope_t::raised / 2  &&  slope_t::is_single( from_slope-slope_t::raised / 2 )  ) {
998 					from->set_hoehe( from->get_hoehe() + 1 );
999 					from_slope -= slope_t::raised / 2;
1000 					route[i].z = from->get_hoehe();
1001 				}
1002 				from->set_grund_hang( from_slope );
1003 			}
1004 			else {
1005 				from->set_hoehe( from->get_hoehe() + 1 );
1006 				from->set_grund_hang( slope_t::flat );
1007 				route[i].z = from->get_hoehe();
1008 			}
1009 			changed = true;
1010 			if (last_terraformed != i) {
1011 				// charge player
1012 				player_t::book_construction_costs(player_builder, welt->get_settings().cst_set_slope, from->get_pos().get_2d(), ignore_wt);
1013 			}
1014 		}
1015 		// change slope of to
1016 		if(  to_slope != to->get_grund_hang()  ) {
1017 			if(  to_slope == slope_t::raised  ) {
1018 				to->set_hoehe( to->get_hoehe() + 2 );
1019 				to->set_grund_hang( slope_t::flat );
1020 				route[i + 1].z = to->get_hoehe();
1021 			}
1022 			else if(  to_slope != slope_t::raised / 2  ) {
1023 				// bit of a hack to recognise single height slopes shifted up 1
1024 				if(  to_slope > slope_t::raised / 2  &&  slope_t::is_single( to_slope-slope_t::raised / 2 )  ) {
1025 					to->set_hoehe( to->get_hoehe() + 1 );
1026 					to_slope -= slope_t::raised / 2;
1027 					route[i + 1].z = to->get_hoehe();
1028 				}
1029 				to->set_grund_hang(to_slope);
1030 			}
1031 			else {
1032 				to->set_hoehe( to->get_hoehe() + 1);
1033 				to->set_grund_hang(slope_t::flat);
1034 				route[i+1].z = to->get_hoehe();
1035 			}
1036 			changed = true;
1037 			// charge player
1038 			player_t::book_construction_costs(player_builder, welt->get_settings().cst_set_slope, to->get_pos().get_2d(), ignore_wt);
1039 			last_terraformed = i+1; // do not pay twice for terraforming one tile
1040 		}
1041 		// recalc slope image of neighbors
1042 		if (changed) {
1043 			for(uint8 j=0; j<2; j++) {
1044 				for(uint8 x=0; x<2; x++) {
1045 					for(uint8 y=0; y<2; y++) {
1046 						grund_t *gr = welt->lookup_kartenboden(route[i+j].get_2d()+koord(x,y));
1047 						if (gr) {
1048 							gr->calc_image();
1049 						}
1050 					}
1051 				}
1052 			}
1053 		}
1054 	}
1055 }
1056 
check_for_bridge(const grund_t * parent_from,const grund_t * from,const vector_tpl<koord3d> & ziel)1057 void way_builder_t::check_for_bridge(const grund_t* parent_from, const grund_t* from, const vector_tpl<koord3d> &ziel)
1058 {
1059 	// wrong starting slope or tile already occupied with a way ...
1060 	if (!slope_t::is_way(from->get_grund_hang())) {
1061 		return;
1062 	}
1063 
1064 	/*
1065 	 * now check existing ways:
1066 	 * no tunnels/bridges at crossings and no track tunnels/bridges on roads (but road tunnels/bridges on tram are allowed).
1067 	 * (keep in mind, that our waytype isn't currently on the tile and will be built later)
1068 	 */
1069 	const weg_t *way0 = from->get_weg_nr(0);
1070 	const weg_t *way1 = from->get_weg_nr(1);
1071 	if(  way0  ) {
1072 		switch(  bautyp&bautyp_mask  ) {
1073 			case schiene_tram:
1074 			case strasse: {
1075 				const weg_t *other = way1;
1076 				if (  way0->get_waytype() != desc->get_wtyp()  ) {
1077 					if (  way1  ) {
1078 						// two different ways
1079 						return;
1080 					}
1081 					other = way0;
1082 				}
1083 				if (  other  ) {
1084 					if (  (bautyp&bautyp_mask) == strasse  ) {
1085 						if (  other->get_waytype() != track_wt  ||  other->get_desc()->get_styp()!=type_tram  ) {
1086 							// road only on tram
1087 							return;
1088 						}
1089 					}
1090 					else {
1091 						if (  other->get_waytype() != road_wt  ) {
1092 							// tram only on road
1093 							return;
1094 						}
1095 					}
1096 				}
1097 			}
1098 			/* FALLTHROUGH */
1099 
1100 			default:
1101 				if (way0->get_waytype()!=desc->get_wtyp()  ||  way1!=NULL) {
1102 					// no other ways allowed
1103 					return;
1104 				}
1105 		}
1106 	}
1107 
1108 	const koord zv=from->get_pos().get_2d()-parent_from->get_pos().get_2d();
1109 	const ribi_t::ribi ribi = ribi_type(zv);
1110 
1111 	// now check ribis of existing ways
1112 	const ribi_t::ribi wayribi = way0 ? way0->get_ribi_unmasked() | (way1 ? way1->get_ribi_unmasked() : (ribi_t::ribi)ribi_t::none) : (ribi_t::ribi)ribi_t::none;
1113 	if (  wayribi & (~ribi)  ) {
1114 		// curves at bridge start
1115 		return;
1116 	}
1117 
1118 	// ok, so now we do a closer investigation
1119 	if(  bridge_desc  && (  ribi_type(from->get_grund_hang()) == ribi_t::backward(ribi_type(zv))  ||  from->get_grund_hang() == 0  )
1120 		&&  bridge_builder_t::can_place_ramp(player_builder, from, desc->get_wtyp(),ribi_t::backward(ribi_type(zv)))  ) {
1121 		// Try a bridge.
1122 		const sint32 cost_difference = desc->get_maintenance() > 0 ? (bridge_desc->get_maintenance() * 4l + 3l) / desc->get_maintenance() : 16;
1123 		// try eight possible lengths ..
1124 		uint32 min_length = 1;
1125 		for (uint8 i = 0; i < 8 && min_length <= welt->get_settings().way_max_bridge_len; ++i) {
1126 			sint8 bridge_height;
1127 			const char *error = NULL;
1128 			koord3d end = bridge_builder_t::find_end_pos( player_builder, from->get_pos(), zv, bridge_desc, error, bridge_height, true, min_length );
1129 			const grund_t* gr_end = welt->lookup(end);
1130 			if(  gr_end == NULL) {
1131 				// no valid end point found
1132 				min_length++;
1133 				continue;
1134 			}
1135 			uint32 length = koord_distance(from->get_pos(), end);
1136 			if(!ziel.is_contained(end)  &&  bridge_builder_t::can_place_ramp(player_builder, gr_end, desc->get_wtyp(), ribi_type(zv))) {
1137 				// If there is a slope on the starting tile, it's taken into account in is_allowed_step, but a bridge will be flat!
1138 				sint8 num_slopes = (from->get_grund_hang() == slope_t::flat) ? 1 : -1;
1139 				// On the end tile, we haven't to subtract way_count_slope, since is_allowed_step isn't called with this tile.
1140 				num_slopes += (gr_end->get_grund_hang() == slope_t::flat) ? 1 : 0;
1141 				next_gr.append(next_gr_t(welt->lookup(end), length * cost_difference + num_slopes*welt->get_settings().way_count_slope, build_straight | build_tunnel_bridge));
1142 				min_length = length+1;
1143 			}
1144 			else {
1145 				break;
1146 			}
1147 		}
1148 		return;
1149 	}
1150 
1151 	if(  tunnel_desc  &&  ribi_type(from->get_grund_hang()) == ribi_type(zv)  ) {
1152 		// uphill hang ... may be tunnel?
1153 		const sint32 cost_difference = desc->get_maintenance() > 0 ? (tunnel_desc->get_maintenance() * 4l + 3l) / desc->get_maintenance() : 16;
1154 		koord3d end = tunnel_builder_t::find_end_pos( player_builder, from->get_pos(), zv, tunnel_desc);
1155 		if(  end != koord3d::invalid  &&  !ziel.is_contained(end)  ) {
1156 			uint32 length = koord_distance(from->get_pos(), end);
1157 			next_gr.append(next_gr_t(welt->lookup(end), length * cost_difference, build_straight | build_tunnel_bridge ));
1158 			return;
1159 		}
1160 	}
1161 }
1162 
1163 
way_builder_t(player_t * player)1164 way_builder_t::way_builder_t(player_t* player) : next_gr(32)
1165 {
1166 	player_builder     = player;
1167 	bautyp = strasse;   // kann mit init_builder() gesetzt werden
1168 	maximum = 2000;// CA $ PER TILE
1169 
1170 	keep_existing_ways = false;
1171 	keep_existing_city_roads = false;
1172 	keep_existing_faster_ways = false;
1173 	build_sidewalk = false;
1174 }
1175 
1176 
1177 /**
1178  * If a way is built on top of another way, should the type
1179  * of the former way be kept or replaced (true == keep)
1180  * @author Hj. Malthaner
1181  */
set_keep_existing_ways(bool yesno)1182 void way_builder_t::set_keep_existing_ways(bool yesno)
1183 {
1184 	keep_existing_ways = yesno;
1185 	keep_existing_faster_ways = false;
1186 }
1187 
1188 
set_keep_existing_faster_ways(bool yesno)1189 void way_builder_t::set_keep_existing_faster_ways(bool yesno)
1190 {
1191 	keep_existing_ways = false;
1192 	keep_existing_faster_ways = yesno;
1193 }
1194 
1195 
init_builder(bautyp_t wt,const way_desc_t * b,const tunnel_desc_t * tunnel,const bridge_desc_t * br)1196 void way_builder_t::init_builder(bautyp_t wt, const way_desc_t *b, const tunnel_desc_t *tunnel, const bridge_desc_t *br)
1197 {
1198 	bautyp = wt;
1199 	desc = b;
1200 	bridge_desc = br;
1201 	tunnel_desc = tunnel;
1202 	if(wt&tunnel_flag  &&  tunnel==NULL) {
1203 		dbg->fatal("way_builder_t::init_builder()","needs a tunnel description for an underground route!");
1204 	}
1205 	if((wt&bautyp_mask)==luft) {
1206 		wt &= bautyp_mask | bot_flag;
1207 	}
1208 	if(player_builder==NULL) {
1209 		bridge_desc = NULL;
1210 		tunnel_desc = NULL;
1211 	}
1212 	else if(  bautyp != river  ) {
1213 #ifdef AUTOMATIC_BRIDGES
1214 		if(  bridge_desc == NULL  ) {
1215 			bridge_desc = bridge_builder_t::find_bridge(b->get_wtyp(), 25, welt->get_timeline_year_month());
1216 		}
1217 #endif
1218 #ifdef AUTOMATIC_TUNNELS
1219 		if(  tunnel_desc == NULL  ) {
1220 			tunnel_desc = tunnel_builder_t::get_tunnel_desc(b->get_wtyp(), 25, welt->get_timeline_year_month());
1221 		}
1222 #endif
1223 	}
1224   DBG_MESSAGE("way_builder_t::init_builder()",
1225          "setting way type to %d, desc=%s, bridge_desc=%s, tunnel_desc=%s",
1226          bautyp,
1227          desc ? desc->get_name() : "NULL",
1228          bridge_desc ? bridge_desc->get_name() : "NULL",
1229          tunnel_desc ? tunnel_desc->get_name() : "NULL"
1230          );
1231 }
1232 
1233 
get_mini_maxi(const vector_tpl<koord3d> & ziel,koord3d & mini,koord3d & maxi)1234 void get_mini_maxi( const vector_tpl<koord3d> &ziel, koord3d &mini, koord3d &maxi )
1235 {
1236 	mini = maxi = ziel[0];
1237 	FOR(vector_tpl<koord3d>, const& current, ziel) {
1238 		if( current.x < mini.x ) {
1239 			mini.x = current.x;
1240 		} else if( current.x > maxi.x ) {
1241 			maxi.x = current.x;
1242 		}
1243 		if( current.y < mini.y ) {
1244 			mini.y = current.y;
1245 		} else if( current.y > maxi.y ) {
1246 			maxi.y = current.y;
1247 		}
1248 		if( current.z < mini.z ) {
1249 			mini.z = current.z;
1250 		} else if( current.z > maxi.z ) {
1251 			maxi.z = current.z;
1252 		}
1253 	}
1254 }
1255 
1256 
1257 /* this routine uses A* to calculate the best route
1258  * beware: change the cost and you will mess up the system!
1259  * (but you can try, look at simuconf.tab)
1260  */
intern_calc_route(const vector_tpl<koord3d> & start,const vector_tpl<koord3d> & ziel)1261 sint32 way_builder_t::intern_calc_route(const vector_tpl<koord3d> &start, const vector_tpl<koord3d> &ziel)
1262 {
1263 	// we clear it here probably twice: does not hurt ...
1264 	route.clear();
1265 	terraform_index.clear();
1266 
1267 	// check for existing koordinates
1268 	bool has_target_ground = false;
1269 	FOR(vector_tpl<koord3d>, const& i, ziel) {
1270 		has_target_ground |= welt->lookup(i) != 0;
1271 	}
1272 	if( !has_target_ground ) {
1273 		return -1;
1274 	}
1275 
1276 	// calculate the minimal cuboid containing 'ziel'
1277 	koord3d mini, maxi;
1278 	get_mini_maxi( ziel, mini, maxi );
1279 
1280 	// memory in static list ...
1281 	if(route_t::nodes==NULL) {
1282 		route_t::MAX_STEP = welt->get_settings().get_max_route_steps(); // may need very much memory => configurable
1283 		route_t::nodes = new route_t::ANode[route_t::MAX_STEP+4+1];
1284 	}
1285 
1286 	static binary_heap_tpl <route_t::ANode *> queue;
1287 
1288 	// initialize marker field
1289 	marker_t& marker = marker_t::instance(welt->get_size().x, welt->get_size().y);
1290 
1291 	// clear the queue (should be empty anyhow)
1292 	queue.clear();
1293 
1294 	// some thing for the search
1295 	grund_t *to;
1296 	koord3d gr_pos;	// just the last valid pos ...
1297 	route_t::ANode *tmp=NULL;
1298 	uint32 step = 0;
1299 	const grund_t* gr=NULL;
1300 
1301 	FOR(vector_tpl<koord3d>, const& i, start) {
1302 		gr = welt->lookup(i);
1303 
1304 		// is valid ground?
1305 		sint32 dummy;
1306 		if( !gr || !is_allowed_step(gr,gr,&dummy) ) {
1307 			// DBG_MESSAGE("way_builder_t::intern_calc_route()","cannot start on (%i,%i,%i)",start.x,start.y,start.z);
1308 			continue;
1309 		}
1310 		tmp = &(route_t::nodes[step]);
1311 		step ++;
1312 
1313 		tmp->parent = NULL;
1314 		tmp->gr = gr;
1315 		tmp->f = calc_distance(i, mini, maxi);
1316 		tmp->g = 0;
1317 		tmp->dir = 0;
1318 		tmp->count = 0;
1319 
1320 		queue.insert(tmp);
1321 	}
1322 
1323 	if( queue.empty() ) {
1324 		// no valid ground to start.
1325 		return -1;
1326 	}
1327 
1328 	INT_CHECK("wegbauer 347");
1329 
1330 	// get exclusively the tile list
1331 	route_t::GET_NODE();
1332 
1333 	// to speed up search, but may not find all shortest ways
1334 	uint32 min_dist = 99999999;
1335 
1336 //DBG_MESSAGE("route_t::itern_calc_route()","calc route from %d,%d,%d to %d,%d,%d",ziel.x, ziel.y, ziel.z, start.x, start.y, start.z);
1337 	do {
1338 		route_t::ANode *test_tmp = queue.pop();
1339 
1340 		if(marker.test_and_mark(test_tmp->gr)) {
1341 			// we were already here on a faster route, thus ignore this branch
1342 			// (trading speed against memory consumption)
1343 			continue;
1344 		}
1345 
1346 		tmp = test_tmp;
1347 		gr = tmp->gr;
1348 		gr_pos = gr->get_pos();
1349 
1350 #ifdef DEBUG_ROUTES
1351 DBG_DEBUG("insert to close","(%i,%i,%i)  f=%i",gr->get_pos().x,gr->get_pos().y,gr->get_pos().z,tmp->f);
1352 #endif
1353 
1354 		// already there
1355 		if(  ziel.is_contained(gr_pos)  ||  tmp->g>maximum) {
1356 			// we added a target to the closed list: we are finished
1357 			break;
1358 		}
1359 
1360 		// the four possible directions plus any additional stuff due to already existing brides plus new ones ...
1361 		next_gr.clear();
1362 
1363 		// only one direction allowed ...
1364 		const ribi_t::ribi straight_dir = tmp->parent!=NULL ? ribi_type(gr->get_pos() - tmp->parent->gr->get_pos()) : (ribi_t::ribi)ribi_t::all;
1365 
1366 		// test directions
1367 		// .. use only those that are allowed by current slope
1368 		// .. do not go backward
1369 		const ribi_t::ribi slope_dir = (slope_t::is_way_ns(gr->get_weg_hang()) ? ribi_t::northsouth : ribi_t::none) | (slope_t::is_way_ew(gr->get_weg_hang()) ? ribi_t::eastwest : ribi_t::none);
1370 		const ribi_t::ribi test_dir = (tmp->count & build_straight)==0  ?  slope_dir  & ~ribi_t::backward(straight_dir)
1371 		                                                                :  straight_dir;
1372 
1373 		// testing all four possible directions
1374 		for(ribi_t::ribi r=1; (r&16)==0; r<<=1) {
1375 			if((r & test_dir)==0) {
1376 				// not allowed to go this direction
1377 				continue;
1378 			}
1379 
1380 			bool do_terraform = false;
1381 			const koord zv(r);
1382 			if(!gr->get_neighbour(to,invalid_wt,r)  ||  !check_slope(gr, to)) {
1383 				// slopes do not match
1384 				// terraforming enabled?
1385 				if (bautyp==river  ||  (bautyp & terraform_flag) == 0) {
1386 					continue;
1387 				}
1388 				// check terraforming (but not in curves)
1389 				if (gr->get_grund_hang()==0  ||  (tmp->parent!=NULL  &&  tmp->parent->parent!=NULL  &&  r==straight_dir)) {
1390 					to = welt->lookup_kartenboden(gr->get_pos().get_2d() + zv);
1391 					if (to==NULL  ||  (check_slope(gr, to)  &&  gr->get_vmove(r)!=to->get_vmove(ribi_t::backward(r)))) {
1392 						continue;
1393 					}
1394 					else {
1395 						do_terraform = true;
1396 					}
1397 				}
1398 				else {
1399 					continue;
1400 				}
1401 			}
1402 
1403 			// something valid?
1404 			if(marker.is_marked(to)) {
1405 				continue;
1406 			}
1407 
1408 			sint32 new_cost = 0;
1409 			bool is_ok = is_allowed_step(gr,to,&new_cost);
1410 
1411 			if(is_ok) {
1412 				// now add it to the array ...
1413 				next_gr.append(next_gr_t(to, new_cost, do_terraform ? build_straight | terraform : 0));
1414 			}
1415 			else if(tmp->parent!=NULL  &&  r==straight_dir  &&  (tmp->count & build_tunnel_bridge)==0) {
1416 				// try to build a bridge or tunnel here, since we cannot go here ...
1417 				check_for_bridge(tmp->parent->gr,gr,ziel);
1418 			}
1419 		}
1420 
1421 		// now check all valid ones ...
1422 		FOR(vector_tpl<next_gr_t>, const& r, next_gr) {
1423 			to = r.gr;
1424 
1425 			if(  to==NULL) {
1426 				continue;
1427 			}
1428 
1429 			// new values for cost g
1430 			uint32 new_g = tmp->g + r.cost;
1431 
1432 			settings_t const& s = welt->get_settings();
1433 			// check for curves (usually, one would need the lastlast and the last;
1434 			// if not there, then we could just take the last
1435 			uint8 current_dir;
1436 			if(tmp->parent!=NULL) {
1437 				current_dir = ribi_type( tmp->parent->gr->get_pos(), to->get_pos() );
1438 				if(tmp->dir!=current_dir) {
1439 					new_g += s.way_count_curve;
1440 					if(tmp->parent->dir!=tmp->dir) {
1441 						// discourage double turns
1442 						new_g += s.way_count_double_curve;
1443 					}
1444 					else if(ribi_t::is_perpendicular(tmp->dir,current_dir)) {
1445 						// discourage v turns heavily
1446 						new_g += s.way_count_90_curve;
1447 					}
1448 				}
1449 				else if(bautyp==leitung  &&  ribi_t::is_bend(current_dir)) {
1450 					new_g += s.way_count_double_curve;
1451 				}
1452 				// extra malus leave an existing road after only one tile
1453 				waytype_t const wt = desc->get_wtyp();
1454 				if (tmp->parent->gr->hat_weg(wt) && !gr->hat_weg(wt) && to->hat_weg(wt)) {
1455 					// but only if not straight track
1456 					if(!ribi_t::is_straight(tmp->dir)) {
1457 						new_g += s.way_count_leaving_road;
1458 					}
1459 				}
1460 			}
1461 			else {
1462 				 current_dir = ribi_type( gr->get_pos(), to->get_pos() );
1463 			}
1464 
1465 			const uint32 new_dist = calc_distance( to->get_pos(), mini, maxi );
1466 
1467 			// special check for kinks at the end
1468 			if(new_dist==0  &&  current_dir!=tmp->dir) {
1469 				// discourage turn on last tile
1470 				new_g += s.way_count_double_curve;
1471 			}
1472 
1473 			if (new_dist == 0 && r.flag & terraform) {
1474 				// no terraforming near target
1475 				continue;
1476 			}
1477 			if(new_dist<min_dist) {
1478 				min_dist = new_dist;
1479 			}
1480 			else if(new_dist>min_dist+50) {
1481 				// skip, if too far from current minimum tile
1482 				// will not find some ways, but will be much faster ...
1483 				// also it will avoid too big detours, which is probably also not the way, the builder intended
1484 				continue;
1485 			}
1486 
1487 
1488 			const uint32 new_f = new_g+new_dist;
1489 
1490 			if((step&0x03)==0) {
1491 				INT_CHECK( "wegbauer 1347" );
1492 #ifdef DEBUG_ROUTES
1493 				if((step&1023)==0) {minimap_t::get_karte()->calc_map();}
1494 #endif
1495 			}
1496 
1497 			// not in there or taken out => add new
1498 			route_t::ANode *k=&(route_t::nodes[step]);
1499 			step++;
1500 
1501 			k->parent = tmp;
1502 			k->gr = to;
1503 			k->g = new_g;
1504 			k->f = new_f;
1505 			k->dir = current_dir;
1506 			// count is unused here, use it as flag-variable instead
1507 			k->count = r.flag;
1508 
1509 			queue.insert( k );
1510 
1511 #ifdef DEBUG_ROUTES
1512 DBG_DEBUG("insert to open","(%i,%i,%i)  f=%i",to->get_pos().x,to->get_pos().y,to->get_pos().z,k->f);
1513 #endif
1514 		}
1515 
1516 	} while (!queue.empty() && step < route_t::MAX_STEP);
1517 
1518 #ifdef DEBUG_ROUTES
1519 DBG_DEBUG("way_builder_t::intern_calc_route()","steps=%i  (max %i) in route, open %i, cost %u",step,route_t::MAX_STEP,queue.get_count(),tmp->g);
1520 #endif
1521 	INT_CHECK("wegbauer 194");
1522 
1523 	route_t::RELEASE_NODE();
1524 
1525 	// target reached?
1526 	if(  !ziel.is_contained(gr->get_pos())  ||  step>=route_t::MAX_STEP  ||  tmp->parent==NULL  ||  tmp->g > maximum  ) {
1527 		if (step>=route_t::MAX_STEP) {
1528 			dbg->warning("way_builder_t::intern_calc_route()","Too many steps (%i>=max %i) in route (too long/complex)",step,route_t::MAX_STEP);
1529 		}
1530 		return -1;
1531 	}
1532 	else {
1533 		const sint32 cost = tmp->g;
1534 		// reached => construct route
1535 		while(tmp != NULL) {
1536 			route.append(tmp->gr->get_pos());
1537 			if (tmp->count & terraform) {
1538 				terraform_index.append(route.get_count()-1);
1539 			}
1540 			tmp = tmp->parent;
1541 		}
1542 		return cost;
1543 	}
1544 
1545 	return -1;
1546 }
1547 
1548 
intern_calc_straight_route(const koord3d start,const koord3d ziel)1549 void way_builder_t::intern_calc_straight_route(const koord3d start, const koord3d ziel)
1550 {
1551 	bool ok = true;
1552 	const koord3d koordup(0, 0, welt->get_settings().get_way_height_clearance());
1553 
1554 	sint32 dummy_cost;
1555 	const grund_t *test_bd = welt->lookup(start);
1556 	ok = false;
1557 	if (test_bd  &&  is_allowed_step(test_bd,test_bd,&dummy_cost)  ) {
1558 		//there is a legal ground at the start
1559 		ok = true;
1560 	}
1561 	if (ok  &&  (bautyp&tunnel_flag) && !test_bd->ist_tunnel()) {
1562 		// start tunnelbuilding in tunnels
1563 		return;
1564 	}
1565 	if (bautyp&elevated_flag) {
1566 		test_bd = welt->lookup(start + koordup);
1567 		if (test_bd  &&  is_allowed_step(test_bd,test_bd,&dummy_cost, true)  ) {
1568 			//there is a legal way at the upper layer of start
1569 			ok = true;
1570 		}
1571 	}
1572 	if (!ok) {
1573 		//target is not suitable
1574 		return;
1575 	}
1576 	test_bd = welt->lookup(ziel);
1577 	// we have to reach target height if no tunnel building or (target ground does not exists or is underground).
1578 	// in full underground mode if there is no tunnel under cursor, kartenboden gets selected
1579 	const bool target_3d = (bautyp&tunnel_flag)==0  ||  test_bd==NULL  ||  !test_bd->ist_karten_boden();
1580 	if((bautyp&tunnel_flag)==0) {
1581 		//same thing to the target point
1582 		ok = false;
1583 		if (test_bd  &&  is_allowed_step(test_bd,test_bd,&dummy_cost)  ) {
1584 			//there is a legal ground at the target
1585 			ok = true;
1586 		}
1587 		if (bautyp&elevated_flag) {
1588 			test_bd = welt->lookup(ziel + koordup);
1589 			if (test_bd  &&  is_allowed_step(test_bd,test_bd,&dummy_cost, true)  ) {
1590 				//there is a legal way at the upper layer of the target
1591 				ok = true;
1592 			}
1593 		}
1594 		if(!ok) {
1595 			return;
1596 		}
1597 	}
1598 
1599 	koord3d pos=start;
1600 
1601 	route.clear();
1602 	route.append(start);
1603 	terraform_index.clear();
1604 	bool check_terraform = start.x==ziel.x  ||  start.y==ziel.y;
1605 
1606 	while(pos.get_2d()!=ziel.get_2d()  &&  ok) {
1607 
1608 		bool do_terraform = false;
1609 		// shortest way
1610 		ribi_t::ribi diff;
1611 		if(abs(pos.x-ziel.x)>=abs(pos.y-ziel.y)) {
1612 			diff = (pos.x>ziel.x) ? ribi_t::west : ribi_t::east;
1613 		}
1614 		else {
1615 			diff = (pos.y>ziel.y) ? ribi_t::north : ribi_t::south;
1616 		}
1617 		if(bautyp&tunnel_flag) {
1618 			// create fake tunnel grounds if needed
1619 			bool bd_von_new = false, bd_nach_new = false;
1620 			grund_t *bd_von = welt->lookup(pos);
1621 			if(  bd_von == NULL ) {
1622 				bd_von = new tunnelboden_t(pos, slope_t::flat);
1623 				bd_von_new = true;
1624 			}
1625 			// take care of slopes
1626 			pos.z = bd_von->get_vmove(diff);
1627 
1628 			// check next tile
1629 			grund_t *bd_nach = welt->lookup(pos + diff);
1630 			if(  !bd_nach  ) {
1631 				// check for slope down ...
1632 				bd_nach = welt->lookup(pos + diff + koord3d(0,0,-1));
1633 				if(  !bd_nach  ) {
1634 					bd_nach = welt->lookup(pos + diff + koord3d(0,0,-2));
1635 				}
1636 				if(  bd_nach  &&  bd_nach->get_weg_hang() == slope_t::flat  ) {
1637 					// Don't care about _flat_ tunnels below.
1638 					bd_nach = NULL;
1639 				}
1640 			}
1641 			if(  bd_nach == NULL  ){
1642 				bd_nach = new tunnelboden_t(pos + diff, slope_t::flat);
1643 				bd_nach_new = true;
1644 			}
1645 			// check for tunnel and right slope
1646 			ok = ok && bd_nach->ist_tunnel() && bd_nach->get_vmove(ribi_t::backward(diff))==pos.z;
1647 			// all other checks are done here (crossings, stations etc)
1648 			ok = ok && is_allowed_step(bd_von, bd_nach, &dummy_cost);
1649 
1650 			// advance position
1651 			pos = bd_nach->get_pos();
1652 
1653 			// check new tile: ground must be above tunnel and below sea
1654 			grund_t *gr = welt->lookup_kartenboden(pos.get_2d());
1655 			ok = ok  &&  (gr->get_hoehe() > pos.z)  &&  (!gr->is_water()  ||  (welt->lookup_hgt(pos.get_2d()) > pos.z) );
1656 
1657 			if (bd_von_new) {
1658 				delete bd_von;
1659 			}
1660 			if (bd_nach_new) {
1661 				delete bd_nach;
1662 			}
1663 		}
1664 		else {
1665 			grund_t *bd_von = welt->lookup(pos);
1666 			ok = false;
1667 			grund_t *bd_nach = NULL;
1668 			if ( bd_von ) {
1669 				if (bd_von->get_neighbour(bd_nach, invalid_wt, diff) && check_slope(bd_von, bd_nach)) {
1670 					ok = true;
1671 				}
1672 				else {
1673 					// slopes do not match
1674 					// terraforming enabled?  or able to follow upper layer?
1675 					if ((bautyp==river  ||  (bautyp & terraform_flag) == 0)  &&  (bautyp&elevated_flag) == 0  ) {
1676 						break;
1677 					}
1678 					// check terraforming (but not in curves)
1679 					if (check_terraform) {
1680 						bd_nach = welt->lookup_kartenboden(bd_von->get_pos().get_2d() + diff);
1681 						if (bd_nach==NULL  ||  (check_slope(bd_von, bd_nach)  &&  bd_von->get_vmove(diff)!=bd_nach->get_vmove(ribi_t::backward(diff)))) {
1682 							ok = false;
1683 						}
1684 						else {
1685 							do_terraform = true;
1686 							ok = true;
1687 						}
1688 					}
1689 				}
1690 				// allowed ground?
1691 				ok = ok  &&  bd_nach  &&  is_allowed_step(bd_von,bd_nach,&dummy_cost);
1692 				if (ok) {
1693 					pos = bd_nach->get_pos();
1694 				}
1695 			}
1696 			// if failed
1697 			if (!ok  &&  bautyp&elevated_flag) {
1698 				//search following the upper layer
1699 				bd_von = welt->lookup(pos + koordup);
1700 				if(bd_von  &&  bd_von->get_neighbour(bd_nach, invalid_wt, diff)  &&  check_slope(bd_von, bd_nach)  &&  is_allowed_step(bd_von, bd_nach, &dummy_cost, true)  ) {
1701 					ok = true;
1702 					pos = bd_nach->get_pos() - koordup;
1703 				}
1704 			}
1705 			check_terraform = pos.x==ziel.x  ||  pos.y==ziel.y;
1706 		}
1707 
1708 		route.append(pos);
1709 		if (do_terraform) {
1710 			terraform_index.append(route.get_count()-2);
1711 		}
1712 		DBG_MESSAGE("way_builder_t::calc_straight_route()","step %s = %i",koord(diff).get_str(),ok);
1713 	}
1714 	ok = ok && ( target_3d ? pos==ziel : pos.get_2d()==ziel.get_2d() );
1715 
1716 	// we can built a straight route?
1717 	if(ok) {
1718 DBG_MESSAGE("way_builder_t::intern_calc_straight_route()","found straight route max_n=%i",get_count()-1);
1719 	}
1720 	else {
1721 		route.clear();
1722 		terraform_index.clear();
1723 	}
1724 }
1725 
1726 /* this routine uses A* to calculate the best route
1727  * beware: change the cost and you will mess up the system!
1728  * (but you can try, look at simuconf.tab)
1729  */
1730 /* It should not be river/airport/tunnel/bridge/terraformable
1731  */
intern_calc_route_elevated(const koord3d start,const koord3d ziel)1732 sint32 way_builder_t::intern_calc_route_elevated(const koord3d start, const koord3d ziel)
1733 {
1734 	// we clear it here probably twice: does not hurt ...
1735 	route.clear();
1736 	terraform_index.clear();
1737 
1738 	const koord3d koordup(0, 0, welt->get_settings().get_way_height_clearance());
1739 
1740 	// check for existing koordinates
1741 	bool has_target_ground = welt->lookup(ziel) || welt->lookup(ziel + koordup);
1742 	if( !has_target_ground ) {
1743 		return -1;
1744 	}
1745 
1746 
1747 	// memory in static list ...
1748 	if(route_t::nodes==NULL) {
1749 		route_t::MAX_STEP = welt->get_settings().get_max_route_steps(); // may need very much memory => configurable
1750 		route_t::nodes = new route_t::ANode[route_t::MAX_STEP+4+1];
1751 	}
1752 
1753 	static binary_heap_tpl <route_t::ANode *> queue;
1754 
1755 	// initialize marker field
1756 	marker_t& markerbelow = marker_t::instance(welt->get_size().x, welt->get_size().y);
1757 	marker_t& markerabove = marker_t::instance_second(welt->get_size().x, welt->get_size().y);
1758 
1759 	// clear the queue (should be empty anyhow)
1760 	queue.clear();
1761 
1762 	// some thing for the search
1763 	grund_t *to;
1764 	koord3d gr_pos;	// just the last valid pos ...
1765 	route_t::ANode *tmp=NULL;
1766 	uint32 step = 0;
1767 	const grund_t *gr=NULL, *gu = NULL;
1768 
1769 	gr = welt->lookup(start);
1770 		// is valid ground?
1771 	sint32 dummy;
1772 	if( gr && is_allowed_step(gr,gr,&dummy) ) {
1773 		// DBG_MESSAGE("way_builder_t::intern_calc_route()","cannot start on (%i,%i,%i)",start.x,start.y,start.z);
1774 		tmp = &(route_t::nodes[step]);
1775 		step ++;
1776 		tmp->parent = NULL;
1777 		tmp->gr = gr;
1778 		tmp->f = calc_distance(start, ziel, ziel);
1779 		tmp->g = 0;
1780 		tmp->dir = 0;
1781 
1782 		tmp->count = 0;
1783 
1784 		queue.insert(tmp);
1785 	}
1786 
1787 	gu = welt->lookup(start + koordup);
1788 	if( gu && is_allowed_step(gu,gu,&dummy, true) ) {
1789 		// DBG_MESSAGE("way_builder_t::intern_calc_route()","cannot start on (%i,%i,%i)",start.x,start.y,start.z);
1790 		tmp = &(route_t::nodes[step]);
1791 		step ++;
1792 		tmp->parent = NULL;
1793 		tmp->gr = gu;
1794 		tmp->f = calc_distance(start, ziel, ziel);
1795 		tmp->g = 0;
1796 		tmp->dir = 0;
1797 
1798 		tmp->count = is_upperlayer;
1799 
1800 		queue.insert(tmp);
1801 	}
1802 
1803 
1804 	if( queue.empty() ) {
1805 		// no valid ground to start.
1806 		return -1;
1807 	}
1808 
1809 	INT_CHECK("wegbauer 347");
1810 
1811 	// get exclusively the tile list
1812 	route_t::GET_NODE();
1813 
1814 	// to speed up search, but may not find all shortest ways
1815 	uint32 min_dist = 99999999;
1816 
1817 //DBG_MESSAGE("route_t::itern_calc_route()","calc route from %d,%d,%d to %d,%d,%d",ziel.x, ziel.y, ziel.z, start.x, start.y, start.z);
1818 	do {
1819 		route_t::ANode *test_tmp = queue.pop();
1820 
1821 		if(  (test_tmp->count&is_upperlayer?markerabove:markerbelow).test_and_mark(test_tmp->gr)  ) {
1822 			// we were already here on a faster route, thus ignore this branch
1823 			// (trading speed against memory consumption)
1824 			continue;
1825 		}
1826 
1827 		tmp = test_tmp;
1828 		if(test_tmp->count & is_upperlayer) {
1829 			gu = tmp->gr;
1830 			gr_pos = gu->get_pos() - koordup;
1831 			gr = welt->lookup(gr_pos);
1832 		}
1833 		else {
1834 			gr = tmp->gr;
1835 			gr_pos = gr->get_pos();
1836 			gu = welt->lookup(gr_pos + koordup);
1837 		}
1838 
1839 #ifdef DEBUG_ROUTES
1840 DBG_DEBUG("insert to close","(%i,%i,%i)  f=%i",gr->get_pos().x,gr->get_pos().y,gr->get_pos().z,tmp->f);
1841 #endif
1842 
1843 		// already there
1844 		if(  ziel == gr_pos  ||  tmp->g>maximum) {
1845 			// we added a target to the closed list: we are finished
1846 			break;
1847 		}
1848 
1849 		// the four possible directions plus any additional stuff due to already existing brides plus new ones ...
1850 		next_gr.clear();
1851 
1852 		//search following the lower layer
1853 		if(gr) {
1854 
1855 			// only one direction allowed ...
1856 			const ribi_t::ribi straight_dir = tmp->parent!=NULL ? ribi_type(gr->get_pos() - tmp->parent->gr->get_pos()) : (ribi_t::ribi)ribi_t::all;
1857 
1858 			// test directions
1859 			// .. use only those that are allowed by current slope
1860 			// .. do not go backward
1861 			const ribi_t::ribi slope_dir = (slope_t::is_way_ns(gr->get_weg_hang()) ? ribi_t::northsouth : ribi_t::none) | (slope_t::is_way_ew(gr->get_weg_hang()) ? ribi_t::eastwest : ribi_t::none);
1862 			const ribi_t::ribi test_dir = (tmp->count & build_straight)==0  ?  slope_dir  & ~ribi_t::backward(straight_dir)
1863 		                                                                :  straight_dir;
1864 
1865 			// testing all four possible directions
1866 			for(ribi_t::ribi r=1; (r&16)==0; r<<=1) {
1867 				if((r & test_dir)==0) {
1868 					// not allowed to go this direction
1869 					continue;
1870 				}
1871 
1872 				const koord zv(r);
1873 				if(!gr->get_neighbour(to,invalid_wt,r)  ||  !check_slope(gr, to)) {
1874 					// slopes do not match
1875 					continue;
1876 				}
1877 
1878 				// something valid?
1879 				if(markerbelow.is_marked(to)) {
1880 					continue;
1881 				}
1882 
1883 				sint32 new_cost = 0;
1884 				bool is_ok = is_allowed_step(gr,to,&new_cost);
1885 
1886 				if(is_ok) {
1887 					// now add it to the array ...
1888 					next_gr.append(next_gr_t(to, new_cost, 0));
1889 				}
1890 			}
1891 		}
1892 
1893 		//search following the upper layer
1894 		if(gu) {
1895 
1896 			// only one direction allowed ...
1897 			const ribi_t::ribi straight_dir = tmp->parent!=NULL ? ribi_type(gu->get_pos() - tmp->parent->gr->get_pos()) : (ribi_t::ribi)ribi_t::all;
1898 
1899 			// test directions
1900 			// .. use only those that are allowed by current slope
1901 			// .. do not go backward
1902 			const ribi_t::ribi slope_dir = (slope_t::is_way_ns(gu->get_weg_hang()) ? ribi_t::northsouth : ribi_t::none) | (slope_t::is_way_ew(gu->get_weg_hang()) ? ribi_t::eastwest : ribi_t::none);
1903 			const ribi_t::ribi test_dir = (tmp->count & build_straight)==0  ?  slope_dir  & ~ribi_t::backward(straight_dir)
1904 		                                                                :  straight_dir;
1905 
1906 			// testing all four possible directions
1907 			for(ribi_t::ribi r=1; (r&16)==0; r<<=1) {
1908 				if((r & test_dir)==0) {
1909 					// not allowed to go this direction
1910 					continue;
1911 				}
1912 
1913 				const koord zv(r);
1914 				if(!gu->get_neighbour(to,invalid_wt,r)  ||  !check_slope(gu, to)) {
1915 					// slopes do not match
1916 					continue;
1917 				}
1918 
1919 				// something valid?
1920 				if(markerabove.is_marked(to)) {
1921 					continue;
1922 				}
1923 
1924 				sint32 new_cost = 0;
1925 				bool is_ok = is_allowed_step(gu,to,&new_cost, true);
1926 
1927 				if(is_ok) {
1928 					// now add it to the array ...
1929 					next_gr.append(next_gr_t(to, new_cost, is_upperlayer));
1930 				}
1931 			}
1932 		}
1933 
1934 		// now check all valid ones ...
1935 		FOR(vector_tpl<next_gr_t>, const& r, next_gr) {
1936 			to = r.gr;
1937 
1938 			if(  to==NULL) {
1939 				continue;
1940 			}
1941 
1942 			// new values for cost g
1943 			uint32 new_g = tmp->g + r.cost;
1944 
1945 			settings_t const& s = welt->get_settings();
1946 			// check for curves (usually, one would need the lastlast and the last;
1947 			// if not there, then we could just take the last
1948 			uint8 current_dir;
1949 			if(tmp->parent!=NULL) {
1950 				current_dir = ribi_type( tmp->parent->gr->get_pos(), to->get_pos() );
1951 				if(tmp->dir!=current_dir) {
1952 					new_g += s.way_count_curve;
1953 					if(tmp->parent->dir!=tmp->dir) {
1954 						// discourage double turns
1955 						new_g += s.way_count_double_curve;
1956 					}
1957 					else if(ribi_t::is_perpendicular(tmp->dir,current_dir)) {
1958 						// discourage v turns heavily
1959 						new_g += s.way_count_90_curve;
1960 					}
1961 				}
1962 				else if(bautyp==leitung  &&  ribi_t::is_bend(current_dir)) {
1963 					new_g += s.way_count_double_curve;
1964 				}
1965 				// extra malus leave an existing road after only one tile
1966 				waytype_t const wt = desc->get_wtyp();
1967 				if (tmp->parent->gr->hat_weg(wt) && !(gr? gr: gu)->hat_weg(wt) && to->hat_weg(wt)) {
1968 					// but only if not straight track
1969 					if(!ribi_t::is_straight(tmp->dir)) {
1970 						new_g += s.way_count_leaving_road;
1971 					}
1972 				}
1973 			}
1974 			else {
1975 				 current_dir = ribi_type( gr_pos, to->get_pos() );
1976 			}
1977 
1978 			const uint32 new_dist = calc_distance( to->get_pos(), ziel, ziel );
1979 
1980 			// special check for kinks at the end
1981 			if(new_dist==0  &&  current_dir!=tmp->dir) {
1982 				// discourage turn on last tile
1983 				new_g += s.way_count_double_curve;
1984 			}
1985 
1986 			if(new_dist<min_dist) {
1987 				min_dist = new_dist;
1988 			}
1989 			else if(new_dist>min_dist+50) {
1990 				// skip, if too far from current minimum tile
1991 				// will not find some ways, but will be much faster ...
1992 				// also it will avoid too big detours, which is probably also not the way, the builder intended
1993 				continue;
1994 			}
1995 
1996 
1997 			const uint32 new_f = new_g+new_dist;
1998 
1999 			if((step&0x03)==0) {
2000 				INT_CHECK( "wegbauer 1347" );
2001 #ifdef DEBUG_ROUTES
2002 				if((step&1023)==0) {minimap_t::get_karte()->calc_map();}
2003 #endif
2004 			}
2005 
2006 			// not in there or taken out => add new
2007 			route_t::ANode *k=&(route_t::nodes[step]);
2008 			step++;
2009 
2010 			k->parent = tmp;
2011 			k->gr = to;
2012 			k->g = new_g;
2013 			k->f = new_f;
2014 			k->dir = current_dir;
2015 			// count is unused here, use it as flag-variable instead
2016 			k->count = r.flag;
2017 
2018 			queue.insert( k );
2019 
2020 #ifdef DEBUG_ROUTES
2021 DBG_DEBUG("insert to open","(%i,%i,%i)  f=%i",to->get_pos().x,to->get_pos().y,to->get_pos().z,k->f);
2022 #endif
2023 		}
2024 
2025 	} while (!queue.empty() && step < route_t::MAX_STEP);
2026 
2027 #ifdef DEBUG_ROUTES
2028 DBG_DEBUG("way_builder_t::intern_calc_route()","steps=%i  (max %i) in route, open %i, cost %u",step,route_t::MAX_STEP,queue.get_count(),tmp->g);
2029 #endif
2030 	INT_CHECK("wegbauer 194");
2031 
2032 	route_t::RELEASE_NODE();
2033 
2034 	// target reached?
2035 	if(  !(ziel == gr_pos)  ||  step>=route_t::MAX_STEP  ||  tmp->parent==NULL  ||  tmp->g > maximum  ) {
2036 		if (step>=route_t::MAX_STEP) {
2037 			dbg->warning("way_builder_t::intern_calc_route()","Too many steps (%i>=max %i) in route (too long/complex)",step,route_t::MAX_STEP);
2038 		}
2039 		return -1;
2040 	}
2041 	else {
2042 		const sint32 cost = tmp->g;
2043 		// reached => construct route
2044 		while(tmp != NULL) {
2045 			if(tmp->count & is_upperlayer) {
2046 				route.append(tmp->gr->get_pos() - koordup);
2047 			} else {
2048 				route.append(tmp->gr->get_pos() );
2049 			}
2050 			tmp = tmp->parent;
2051 		}
2052 		return cost;
2053 	}
2054 
2055 	return -1;
2056 }
2057 
2058 
2059 // special for starting/landing runways
intern_calc_route_runways(koord3d start3d,const koord3d ziel3d)2060 bool way_builder_t::intern_calc_route_runways(koord3d start3d, const koord3d ziel3d)
2061 {
2062 	route.clear();
2063 	terraform_index.clear();
2064 
2065 	const koord start=start3d.get_2d();
2066 	const koord ziel=ziel3d.get_2d();
2067 	// check for straight line!
2068 	const ribi_t::ribi ribi = ribi_type( start, ziel );
2069 	if(  !ribi_t::is_straight(ribi)  ) {
2070 		// only straight runways!
2071 		return false;
2072 	}
2073 	const ribi_t::ribi ribi_straight = ribi_t::doubles(ribi);
2074 
2075 	// not too close to the border?
2076 	if(	 !(welt->is_within_limits(start-koord(5,5))  &&  welt->is_within_limits(start+koord(5,5)))  ||
2077 		 !(welt->is_within_limits(ziel-koord(5,5))  &&  welt->is_within_limits(ziel+koord(5,5)))  ) {
2078 		if(player_builder==welt->get_active_player()) {
2079 			create_win( new news_img("Zu nah am Kartenrand"), w_time_delete, magic_none);
2080 			return false;
2081 		}
2082 	}
2083 
2084 	// now try begin and endpoint
2085 	const koord zv(ribi);
2086 	// end start
2087 	const grund_t *gr = welt->lookup_kartenboden(start);
2088 	const weg_t *weg = gr->get_weg(air_wt);
2089 	if(weg  &&  !ribi_t::is_straight(weg->get_ribi()|ribi_straight)  ) {
2090 		// cannot connect with curve at the end
2091 		return false;
2092 	}
2093 	if(  weg  &&  weg->get_desc()->get_styp()==type_flat  ) {
2094 		//  could not continue taxiway with runway
2095 		return false;
2096 	}
2097 	// check end
2098 	gr = welt->lookup_kartenboden(ziel);
2099 	weg = gr->get_weg(air_wt);
2100 	if(weg  &&  !ribi_t::is_straight(weg->get_ribi()|ribi_straight)  ) {
2101 		// cannot connect with curve at the end
2102 		return false;
2103 	}
2104 	if(  weg  &&  weg->get_desc()->get_styp()==type_flat  ) {
2105 		//  could not continue taxiway with runway
2106 		return false;
2107 	}
2108 	// now try a straight line with no crossings and no curves at the end
2109 	const int dist=koord_distance( ziel, start );
2110 	grund_t *from = welt->lookup_kartenboden(start);
2111 	for(  int i=0;  i<=dist;  i++  ) {
2112 		grund_t *to = welt->lookup_kartenboden(start+zv*i);
2113 		sint32 dummy;
2114 		if (!is_allowed_step(from, to, &dummy)) {
2115 			return false;
2116 		}
2117 		weg = to->get_weg(air_wt);
2118 		if(  weg  &&  weg->get_desc()->get_styp()==type_runway  &&  (ribi_t::is_threeway(weg->get_ribi_unmasked()|ribi_straight))  &&  (weg->get_ribi_unmasked()|ribi_straight)!=ribi_t::all  ) {
2119 			// only fourway crossings of runways allowed, no threeways => fail
2120 			return false;
2121 		}
2122 		from = to;
2123 	}
2124 	// now we can build here
2125 	route.clear();
2126 	terraform_index.clear();
2127 	route.resize(dist + 2);
2128 	for(  int i=0;  i<=dist;  i++  ) {
2129 		route.append(welt->lookup_kartenboden(start + zv * i)->get_pos());
2130 	}
2131 	return true;
2132 }
2133 
2134 
2135 /*
2136  * calc_straight_route (maximum one curve, including diagonals)
2137  */
calc_straight_route(koord3d start,const koord3d ziel)2138 void way_builder_t::calc_straight_route(koord3d start, const koord3d ziel)
2139 {
2140 	DBG_MESSAGE("way_builder_t::calc_straight_route()","from %d,%d,%d to %d,%d,%d",start.x,start.y,start.z, ziel.x,ziel.y,ziel.z );
2141 	if(bautyp==luft  &&  desc->get_styp()==type_runway) {
2142 		// these are straight anyway ...
2143 		intern_calc_route_runways(start, ziel);
2144 	}
2145 	else {
2146 		intern_calc_straight_route(start,ziel);
2147 		if (route.empty()) {
2148 			intern_calc_straight_route(ziel,start);
2149 		}
2150 	}
2151 }
2152 
2153 
calc_route(const koord3d & start,const koord3d & ziel)2154 void way_builder_t::calc_route(const koord3d &start, const koord3d &ziel)
2155 {
2156 	vector_tpl<koord3d> start_vec(1), ziel_vec(1);
2157 	start_vec.append(start);
2158 	ziel_vec.append(ziel);
2159 	calc_route(start_vec, ziel_vec);
2160 }
2161 
2162 /* calc_route
2163  *
2164  */
calc_route(const vector_tpl<koord3d> & start,const vector_tpl<koord3d> & ziel)2165 void way_builder_t::calc_route(const vector_tpl<koord3d> &start, const vector_tpl<koord3d> &ziel)
2166 {
2167 #ifdef DEBUG_ROUTES
2168 uint32 ms = dr_time();
2169 #endif
2170 	INT_CHECK("simbau 740");
2171 
2172 	if(bautyp==luft  &&  desc->get_styp()==type_runway) {
2173 		assert( start.get_count() == 1  &&  ziel.get_count() == 1 );
2174 		intern_calc_route_runways(start[0], ziel[0]);
2175 	}
2176 	else if(bautyp==river) {
2177 		assert( start.get_count() == 1  &&  ziel.get_count() == 1 );
2178 		// river only go downwards => start and end are clear ...
2179 		if(  start[0].z > ziel[0].z  ) {
2180 			intern_calc_route( start, ziel );
2181 		}
2182 		else {
2183 			intern_calc_route( ziel, start );
2184 		}
2185 		while (route.get_count()>1  &&  welt->lookup(route[0])->get_grund_hang() == slope_t::flat  &&  welt->lookup(route[1])->is_water()) {
2186 			// remove leading water ...
2187 			route.remove_at(0);
2188 		}
2189 	}
2190 	else {
2191 		keep_existing_city_roads |= (bautyp&bot_flag)!=0;
2192 		sint32 cost2;
2193 		if(desc->get_styp() == type_elevated) {
2194 			cost2 = intern_calc_route_elevated(start[0], ziel[0]);
2195 			INT_CHECK("wegbauer 1165");
2196 			if(cost2 < 0) {
2197 				intern_calc_route_elevated(ziel[0], start[0]);
2198 				return;
2199 			}
2200 		}
2201 		else {
2202 			cost2 = intern_calc_route( start, ziel );
2203 			INT_CHECK("wegbauer 1165");
2204 			if(cost2 < 0) {
2205 				intern_calc_route( ziel, start );
2206 				return;
2207 			}
2208 		}
2209 
2210 #ifdef REVERSE_CALC_ROUTE_TOO
2211 		vector_tpl<koord3d> route2(0);
2212 		vector_tpl<uint32> terraform_index2(0);
2213 		swap(route, route2);
2214 		swap(terraform_index, terraform_index2);
2215 		sint32 cost;
2216 		if(desc->get_styp() == type_elevated) {
2217 			cost = intern_calc_route_elevated(start[0], ziel[0]);
2218 		}
2219 		else {
2220 			cost = intern_calc_route( start, ziel );
2221 		}
2222 		INT_CHECK("wegbauer 1165");
2223 
2224 		// the cheaper will survive ...
2225 		if(  cost2 < cost  ||  cost < 0  ) {
2226 			swap(route, route2);
2227 			swap(terraform_index, terraform_index2);
2228 		}
2229 #endif
2230 	}
2231 	INT_CHECK("wegbauer 778");
2232 #ifdef DEBUG_ROUTES
2233 DBG_MESSAGE("calc_route::calc_route", "took %u ms", dr_time() - ms );
2234 #endif
2235 }
2236 
2237 
build_tunnel_and_bridges()2238 void way_builder_t::build_tunnel_and_bridges()
2239 {
2240 	if(bridge_desc==NULL  &&  tunnel_desc==NULL) {
2241 		return;
2242 	}
2243 	// check for bridges and tunnels (no tunnel/bridge at last/first tile)
2244 	for(uint32 i=1; i<get_count()-2; i++) {
2245 		koord d = (route[i + 1] - route[i]).get_2d();
2246 		koord zv = koord (sgn(d.x), sgn(d.y));
2247 
2248 		// ok, here is a gap ...
2249 		if(d.x > 1 || d.y > 1 || d.x < -1 || d.y < -1) {
2250 
2251 			if(d.x*d.y!=0) {
2252 				dbg->error("way_builder_t::build_tunnel_and_bridges()","cannot built a bridge between %s (n=%i, max_n=%i) and %s", route[i].get_str(),i,get_count()-1,route[i+1].get_str());
2253 				continue;
2254 			}
2255 
2256 			DBG_MESSAGE("way_builder_t::build_tunnel_and_bridges", "built bridge %p between %s and %s", bridge_desc, route[i].get_str(), route[i + 1].get_str());
2257 
2258 			const grund_t* start = welt->lookup(route[i]);
2259 			const grund_t* end   = welt->lookup(route[i + 1]);
2260 
2261 			if(start->get_weg_hang()!=start->get_grund_hang()) {
2262 				// already a bridge/tunnel there ...
2263 				continue;
2264 			}
2265 			if(end->get_weg_hang()!=end->get_grund_hang()) {
2266 				// already a bridge/tunnel there ...
2267 				continue;
2268 			}
2269 
2270 			if(start->get_grund_hang()==0  ||  start->get_grund_hang()==slope_type(zv*(-1))) {
2271 				// bridge here, since the route is saved backwards, we have to build it at the posterior end
2272 				bridge_builder_t::build( player_builder, route[i+1], bridge_desc);
2273 			}
2274 			else {
2275 				// tunnel
2276 				tunnel_builder_t::build( player_builder, route[i].get_2d(), tunnel_desc, true );
2277 			}
2278 			INT_CHECK( "wegbauer 1584" );
2279 		}
2280 		// Don't build short tunnels/bridges if they block a bridge/tunnel behind!
2281 		else if(  bautyp != leitung  &&  koord_distance(route[i + 2], route[i + 1]) == 1  ) {
2282 			grund_t *gr_i = welt->lookup(route[i]);
2283 			grund_t *gr_i1 = welt->lookup(route[i+1]);
2284 			if(  gr_i->get_weg_hang() != gr_i->get_grund_hang()  ||  gr_i1->get_weg_hang() != gr_i1->get_grund_hang()  ) {
2285 				// Here is already a tunnel or a bridge.
2286 				continue;
2287 			}
2288 			slope_t::type h = gr_i->get_weg_hang();
2289 			waytype_t const wt = desc->get_wtyp();
2290 			if(h!=slope_t::flat  &&  slope_t::opposite(h)==gr_i1->get_weg_hang()) {
2291 				// either a short mountain or a short dip ...
2292 				// now: check ownership
2293 				weg_t *wi = gr_i->get_weg(wt);
2294 				weg_t *wi1 = gr_i1->get_weg(wt);
2295 				if(wi->get_owner()==player_builder  &&  wi1->get_owner()==player_builder) {
2296 					// we are the owner
2297 					if(  h != slope_type(zv)  ) {
2298 						// its a bridge
2299 						if( bridge_desc ) {
2300 							wi->set_ribi(ribi_type(h));
2301 							wi1->set_ribi(ribi_type(slope_t::opposite(h)));
2302 							bridge_builder_t::build( player_builder, route[i], bridge_desc);
2303 						}
2304 					}
2305 					else if( tunnel_desc ) {
2306 						// make a short tunnel
2307 						wi->set_ribi(ribi_type(slope_t::opposite(h)));
2308 						wi1->set_ribi(ribi_type(h));
2309 						tunnel_builder_t::build( player_builder, route[i].get_2d(), tunnel_desc, true );
2310 					}
2311 					INT_CHECK( "wegbauer 1584" );
2312 				}
2313 			}
2314 		}
2315 	}
2316 }
2317 
2318 
2319 /*
2320  * returns the amount needed to built this way
2321  * author prissi
2322  */
calc_costs()2323 sint64 way_builder_t::calc_costs()
2324 {
2325 	sint64 costs=0;
2326 	koord3d offset = koord3d( 0, 0, bautyp & elevated_flag ? welt->get_settings().get_way_height_clearance() : 0 );
2327 
2328 	sint32 single_cost;
2329 	sint32 new_speedlimit;
2330 
2331 	if( bautyp&tunnel_flag ) {
2332 		assert( tunnel_desc );
2333 		single_cost = tunnel_desc->get_price();
2334 		new_speedlimit = tunnel_desc->get_topspeed();
2335 	}
2336 	else {
2337 		single_cost = desc->get_price();
2338 		new_speedlimit = desc->get_topspeed();
2339 	}
2340 
2341 	// calculate costs for terraforming
2342 	uint32 last_terraformed = terraform_index.get_count();
2343 
2344 	FOR(vector_tpl<uint32>, const i, terraform_index) { // index in route
2345 		grund_t *from = welt->lookup(route[i]);
2346 		uint8 from_slope = from->get_grund_hang();
2347 
2348 		grund_t *to = welt->lookup(route[i+1]);
2349 		uint8 to_slope = to->get_grund_hang();
2350 		// calculate new slopes
2351 		check_terraforming(from, to, &from_slope, &to_slope);
2352 		// change slope of from
2353 		if (from_slope != from->get_grund_hang()) {
2354 			if (last_terraformed != i) {
2355 				costs -= welt->get_settings().cst_set_slope;
2356 			}
2357 		}
2358 		// change slope of to
2359 		if (to_slope != to->get_grund_hang()) {
2360 			costs -= welt->get_settings().cst_set_slope;
2361 			last_terraformed = i+1; // do not pay twice for terraforming one tile
2362 		}
2363 	}
2364 
2365 	for(uint32 i=0; i<get_count(); i++) {
2366 		sint32 old_speedlimit = -1;
2367 		sint32 replace_cost = 0;
2368 
2369 		const grund_t* gr = welt->lookup(route[i] + offset);
2370 		if( gr ) {
2371 			if( bautyp&tunnel_flag ) {
2372 				const tunnel_t *tunnel = gr->find<tunnel_t>();
2373 				assert( tunnel );
2374 				if( tunnel->get_desc() == tunnel_desc ) {
2375 					continue; // Nothing to pay on this tile.
2376 				}
2377 				old_speedlimit = tunnel->get_desc()->get_topspeed();
2378 			}
2379 			else {
2380 				if(  desc->get_wtyp() == powerline_wt  ) {
2381 					if( leitung_t *lt=gr->get_leitung() ) {
2382 						old_speedlimit = lt->get_desc()->get_topspeed();
2383 					}
2384 				}
2385 				else {
2386 					if (weg_t const* const weg = gr->get_weg(desc->get_wtyp())) {
2387 						replace_cost = weg->get_desc()->get_price();
2388 						if( weg->get_desc() == desc ) {
2389 							continue; // Nothing to pay on this tile.
2390 						}
2391 						if(  desc->get_styp() == type_flat  &&  weg->get_desc()->get_styp() == type_tram  &&  gr->get_weg_nr(0)->get_waytype() == road_wt  ) {
2392 							// Don't replace a tram on a road with a normal track.
2393 							continue;
2394 						}
2395 						old_speedlimit = weg->get_desc()->get_topspeed();
2396 					}
2397 					else if (desc->get_wtyp()==water_wt  &&  gr->is_water()) {
2398 						old_speedlimit = new_speedlimit;
2399 					}
2400 				}
2401 			}
2402 			// eventually we have to remove trees
2403 			for(  uint8 i=0;  i<gr->get_top();  i++  ) {
2404 				obj_t *obj = gr->obj_bei(i);
2405 				switch(obj->get_typ()) {
2406 					case obj_t::baum:
2407 						costs -= welt->get_settings().cst_remove_tree;
2408 						break;
2409 					case obj_t::groundobj:
2410 						costs += ((groundobj_t *)obj)->get_desc()->get_price();
2411 						break;
2412 					default: break;
2413 				}
2414 			}
2415 		}
2416 		if(  !keep_existing_faster_ways  ||  old_speedlimit < new_speedlimit  ) {
2417 			costs += max(single_cost, replace_cost);
2418 		}
2419 
2420 		// last tile cannot be start of tunnel/bridge
2421 		if(i+1<get_count()) {
2422 			koord d = (route[i + 1] - route[i]).get_2d();
2423 			// ok, here is a gap ... => either bridge or tunnel
2424 			if(d.x > 1 || d.y > 1 || d.x < -1 || d.y < -1) {
2425 				koord zv = koord (sgn(d.x), sgn(d.y));
2426 				const grund_t* start = welt->lookup(route[i]);
2427 				const grund_t* end   = welt->lookup(route[i + 1]);
2428 				if(start->get_weg_hang()!=start->get_grund_hang()) {
2429 					// already a bridge/tunnel there ...
2430 					continue;
2431 				}
2432 				if(end->get_weg_hang()!=end->get_grund_hang()) {
2433 					// already a bridge/tunnel there ...
2434 					continue;
2435 				}
2436 				if(start->get_grund_hang()==0  ||  start->get_grund_hang()==slope_type(zv*(-1))) {
2437 					// bridge
2438 					costs += bridge_desc->get_price()*(sint64)(koord_distance(route[i], route[i+1])+1);
2439 					continue;
2440 				}
2441 				else {
2442 					// tunnel
2443 					costs += tunnel_desc->get_price()*(sint64)(koord_distance(route[i], route[i+1])+1);
2444 					continue;
2445 				}
2446 			}
2447 		}
2448 	}
2449 	DBG_MESSAGE("way_builder_t::calc_costs()","construction estimate: %f",costs/100.0);
2450 	return costs;
2451 }
2452 
2453 
2454 // adds the ground before underground construction
build_tunnel_tile()2455 bool way_builder_t::build_tunnel_tile()
2456 {
2457 	sint64 cost = 0;
2458 	for(uint32 i=0; i<get_count(); i++) {
2459 
2460 		grund_t* gr = welt->lookup(route[i]);
2461 
2462 		const way_desc_t *wb = tunnel_desc->get_way_desc();
2463 		if(wb==NULL) {
2464 			// now we search a matching way for the tunnels top speed
2465 			// ignore timeline to get consistent results
2466 			wb = way_builder_t::weg_search( tunnel_desc->get_waytype(), tunnel_desc->get_topspeed(), 0, type_flat );
2467 		}
2468 
2469 		if(gr==NULL) {
2470 			// make new tunnelboden
2471 			tunnelboden_t* tunnel = new tunnelboden_t(route[i], 0);
2472 			welt->access(route[i].get_2d())->boden_hinzufuegen(tunnel);
2473 			if(  tunnel_desc->get_waytype() != powerline_wt  ) {
2474 				weg_t *weg = weg_t::alloc(tunnel_desc->get_waytype());
2475 				weg->set_desc( wb );
2476 				tunnel->neuen_weg_bauen(weg, route.get_ribi(i), player_builder);
2477 				tunnel->obj_add(new tunnel_t(route[i], player_builder, tunnel_desc));
2478 				weg->set_max_speed(tunnel_desc->get_topspeed());
2479 				player_t::add_maintenance( player_builder, -weg->get_desc()->get_maintenance(), weg->get_desc()->get_finance_waytype());
2480 			}
2481 			else {
2482 				tunnel->obj_add(new tunnel_t(route[i], player_builder, tunnel_desc));
2483 				leitung_t *lt = new leitung_t(tunnel->get_pos(), player_builder);
2484 				lt->set_desc( wb );
2485 				tunnel->obj_add( lt );
2486 				lt->finish_rd();
2487 				player_t::add_maintenance( player_builder, -lt->get_desc()->get_maintenance(), powerline_wt);
2488 			}
2489 			tunnel->calc_image();
2490 			cost -= tunnel_desc->get_price();
2491 			player_t::add_maintenance( player_builder,  tunnel_desc->get_maintenance(), tunnel_desc->get_finance_waytype() );
2492 		}
2493 		else if(  gr->get_typ() == grund_t::tunnelboden  ) {
2494 			// check for extension only ...
2495 			if(  tunnel_desc->get_waytype() != powerline_wt  ) {
2496 				gr->weg_erweitern( tunnel_desc->get_waytype(), route.get_ribi(i) );
2497 
2498 				tunnel_t *tunnel = gr->find<tunnel_t>();
2499 				assert( tunnel );
2500 				// take the faster way
2501 				if(  !keep_existing_faster_ways  ||  (tunnel->get_desc()->get_topspeed() < tunnel_desc->get_topspeed())  ) {
2502 					player_t::add_maintenance(player_builder, -tunnel->get_desc()->get_maintenance(), tunnel->get_desc()->get_finance_waytype());
2503 					player_t::add_maintenance(player_builder,  tunnel_desc->get_maintenance(), tunnel->get_desc()->get_finance_waytype() );
2504 
2505 					tunnel->set_desc(tunnel_desc);
2506 					weg_t *weg = gr->get_weg(tunnel_desc->get_waytype());
2507 					weg->set_desc(wb);
2508 					weg->set_max_speed(tunnel_desc->get_topspeed());
2509 					// respect max speed of catenary
2510 					wayobj_t const* const wo = gr->get_wayobj(tunnel_desc->get_waytype());
2511 					if (wo  &&  wo->get_desc()->get_topspeed() < weg->get_max_speed()) {
2512 						weg->set_max_speed( wo->get_desc()->get_topspeed() );
2513 					}
2514 					gr->calc_image();
2515 					// respect speed limit of crossing
2516 					weg->count_sign();
2517 
2518 					cost -= tunnel_desc->get_price();
2519 				}
2520 			}
2521 			else {
2522 				leitung_t *lt = gr->get_leitung();
2523 				if(!lt) {
2524 					lt = new leitung_t(gr->get_pos(), player_builder);
2525 					lt->set_desc( wb );
2526 					gr->obj_add( lt );
2527 				}
2528 				else {
2529 					lt->leitung_t::finish_rd();	// only change powerline aspect
2530 					player_t::add_maintenance( player_builder, -lt->get_desc()->get_maintenance(), powerline_wt);
2531 				}
2532 			}
2533 		}
2534 	}
2535 	player_t::book_construction_costs(player_builder, cost, route[0].get_2d(), tunnel_desc->get_waytype());
2536 	return true;
2537 }
2538 
2539 
2540 
build_elevated()2541 void way_builder_t::build_elevated()
2542 {
2543 	FOR(koord3d_vector_t, & i, route) {
2544 		planquadrat_t* const plan = welt->access(i.get_2d());
2545 
2546 		grund_t* const gr0 = plan->get_boden_in_hoehe(i.z);
2547 		i.z += welt->get_settings().get_way_height_clearance();
2548 		grund_t* const gr  = plan->get_boden_in_hoehe(i.z);
2549 
2550 		if(gr==NULL) {
2551 			slope_t::type hang = gr0 ? gr0->get_grund_hang() : 0;
2552 			// add new elevated ground
2553 			monorailboden_t* const monorail = new monorailboden_t(i, hang);
2554 			plan->boden_hinzufuegen(monorail);
2555 			monorail->calc_image();
2556 		}
2557 	}
2558 }
2559 
2560 
2561 
build_road()2562 void way_builder_t::build_road()
2563 {
2564 	// only public player or cities (sp==NULL) can build cityroads with sidewalk
2565 	bool add_sidewalk = build_sidewalk  &&  (player_builder==NULL  ||  player_builder->is_public_service());
2566 
2567 	if(add_sidewalk) {
2568 		player_builder = NULL;
2569 	}
2570 
2571 	// init undo
2572 	if(player_builder!=NULL) {
2573 		// intercity roads have no owner, so we must check for an owner
2574 		player_builder->init_undo(road_wt,get_count());
2575 	}
2576 
2577 	for(  uint32 i=0;  i<get_count();  i++  ) {
2578 		if((i&3)==0) {
2579 			INT_CHECK( "wegbauer 1584" );
2580 		}
2581 
2582 		const koord k = route[i].get_2d();
2583 		grund_t* gr = welt->lookup(route[i]);
2584 		sint64 cost = 0;
2585 
2586 		bool extend = gr->weg_erweitern(road_wt, route.get_short_ribi(i));
2587 
2588 		// bridges/tunnels have their own track type and must not upgrade
2589 		if(gr->get_typ()==grund_t::brueckenboden  ||  gr->get_typ()==grund_t::tunnelboden) {
2590 			continue;
2591 		}
2592 
2593 		if(extend) {
2594 			weg_t * weg = gr->get_weg(road_wt);
2595 
2596 			// keep faster ways or if it is the same way ... (@author prissi)
2597 			if(weg->get_desc()==desc  ||  keep_existing_ways  ||  (keep_existing_city_roads  &&  weg->hat_gehweg())  ||  (keep_existing_faster_ways  &&  weg->get_desc()->get_topspeed()>desc->get_topspeed())  ||  (player_builder!=NULL  &&  weg->is_deletable(player_builder)!=NULL) || (gr->get_typ()==grund_t::monorailboden && (bautyp&elevated_flag)==0)) {
2598 				//nothing to be done
2599 //DBG_MESSAGE("way_builder_t::build_road()","nothing to do at (%i,%i)",k.x,k.y);
2600 			}
2601 			else {
2602 				// we take ownership => we take care to maintain the roads completely ...
2603 				player_t *s = weg->get_owner();
2604 				player_t::add_maintenance(s, -weg->get_desc()->get_maintenance(), weg->get_desc()->get_finance_waytype());
2605 				// cost is the more expensive one, so downgrading is between removing and new building
2606 				cost -= max( weg->get_desc()->get_price(), desc->get_price() );
2607 				weg->set_desc(desc);
2608 				// respect max speed of catenary
2609 				wayobj_t const* const wo = gr->get_wayobj(desc->get_wtyp());
2610 				if (wo  &&  wo->get_desc()->get_topspeed() < weg->get_max_speed()) {
2611 					weg->set_max_speed( wo->get_desc()->get_topspeed() );
2612 				}
2613 				weg->set_gehweg(add_sidewalk);
2614 				player_t::add_maintenance( player_builder, weg->get_desc()->get_maintenance(), weg->get_desc()->get_finance_waytype());
2615 				weg->set_owner(player_builder);
2616 				// respect speed limit of crossing
2617 				weg->count_sign();
2618 			}
2619 		}
2620 		else {
2621 			// make new way
2622 			strasse_t * str = new strasse_t();
2623 
2624 			str->set_desc(desc);
2625 			str->set_gehweg(add_sidewalk);
2626 			cost = -gr->neuen_weg_bauen(str, route.get_short_ribi(i), player_builder)-desc->get_price();
2627 
2628 			// prissi: into UNDO-list, so we can remove it later
2629 			if(player_builder!=NULL) {
2630 				// intercity roads have no owner, so we must check for an owner
2631 				player_builder->add_undo( route[i] );
2632 			}
2633 		}
2634 		gr->calc_image();	// because it may be a crossing ...
2635 		minimap_t::get_instance()->calc_map_pixel(k);
2636 		player_t::book_construction_costs(player_builder, cost, k, road_wt);
2637 	} // for
2638 }
2639 
2640 
build_track()2641 void way_builder_t::build_track()
2642 {
2643 	if(get_count() > 1) {
2644 		// init undo
2645 		player_builder->init_undo(desc->get_wtyp(), get_count());
2646 
2647 		// built tracks
2648 		for(  uint32 i=0;  i<get_count();  i++  ) {
2649 			sint64 cost = 0;
2650 			grund_t* gr = welt->lookup(route[i]);
2651 			ribi_t::ribi ribi = route.get_short_ribi(i);
2652 
2653 			if(gr->get_typ()==grund_t::wasser) {
2654 				// not building on the sea ...
2655 				continue;
2656 			}
2657 
2658 			bool const extend = gr->weg_erweitern(desc->get_wtyp(), ribi);
2659 
2660 			// bridges/tunnels have their own track type and must not upgrade
2661 			if((gr->get_typ()==grund_t::brueckenboden ||  gr->get_typ()==grund_t::tunnelboden)  &&  gr->get_weg_nr(0)->get_waytype()==desc->get_wtyp()) {
2662 				continue;
2663 			}
2664 
2665 			if(extend) {
2666 				weg_t* const weg = gr->get_weg(desc->get_wtyp());
2667 				bool change_desc = true;
2668 
2669 				// do not touch fences, tram way etc. if there is already same way with different type
2670 				// keep faster ways or if it is the same way ... (@author prissi)
2671 				if (weg->get_desc() == desc                                                               ||
2672 						(desc->get_styp() == 0 && weg->get_desc()->get_styp() == type_tram  && gr->has_two_ways())     ||
2673 						keep_existing_ways                                                                      ||
2674 						(keep_existing_faster_ways && weg->get_desc()->get_topspeed() > desc->get_topspeed()) ||
2675 						(gr->get_typ() == grund_t::monorailboden && !(bautyp & elevated_flag)  &&  gr->get_weg_nr(0)->get_waytype()==desc->get_wtyp())) {
2676 					//nothing to be done
2677 					change_desc = false;
2678 				}
2679 
2680 				// build tram track over crossing -> remove crossing
2681 				if(  gr->has_two_ways()  &&  desc->get_styp()==type_tram  &&  weg->get_desc()->get_styp() != type_tram  ) {
2682 					if(  crossing_t *cr = gr->find<crossing_t>(2)  ) {
2683 						// change to tram track
2684 						cr->mark_image_dirty( cr->get_image(), 0);
2685 						cr->cleanup(player_builder);
2686 						delete cr;
2687 						change_desc = true;
2688 						// tell way we have no crossing any more, restore speed limit
2689 						gr->get_weg_nr(0)->clear_crossing();
2690 						gr->get_weg_nr(0)->set_desc( gr->get_weg_nr(0)->get_desc() );
2691 						gr->get_weg_nr(1)->clear_crossing();
2692 					}
2693 				}
2694 
2695 				if(  change_desc  ) {
2696 					// we take ownership => we take care to maintain the roads completely ...
2697 					player_t *s = weg->get_owner();
2698 					player_t::add_maintenance( s, -weg->get_desc()->get_maintenance(), weg->get_desc()->get_finance_waytype());
2699 					// cost is the more expensive one, so downgrading is between removing and new buidling
2700 					cost -= max( weg->get_desc()->get_price(), desc->get_price() );
2701 					weg->set_desc(desc);
2702 					// respect max speed of catenary
2703 					wayobj_t const* const wo = gr->get_wayobj(desc->get_wtyp());
2704 					if (wo  &&  wo->get_desc()->get_topspeed() < weg->get_max_speed()) {
2705 						weg->set_max_speed( wo->get_desc()->get_topspeed() );
2706 					}
2707 					player_t::add_maintenance( player_builder, weg->get_desc()->get_maintenance(), weg->get_desc()->get_finance_waytype());
2708 					weg->set_owner(player_builder);
2709 					// respect speed limit of crossing
2710 					weg->count_sign();
2711 				}
2712 			}
2713 			else {
2714 				weg_t* const sch = weg_t::alloc(desc->get_wtyp());
2715 				sch->set_desc(desc);
2716 
2717 				cost = -gr->neuen_weg_bauen(sch, ribi, player_builder)-desc->get_price();
2718 
2719 				// connect canals to sea
2720 				if(  desc->get_wtyp() == water_wt  ) {
2721 					// do not connect across slopes
2722 					ribi_t::ribi slope_ribi = ribi_t::all;
2723 					if (gr->get_grund_hang()!=slope_t::flat) {
2724 						slope_ribi = ribi_t::doubles( ribi_type(gr->get_weg_hang()) );
2725 					}
2726 
2727 					for(  int j = 0;  j < 4;  j++  ) {
2728 						if (ribi_t::nsew[j] & slope_ribi) {
2729 							grund_t *sea = NULL;
2730 							if (gr->get_neighbour(sea, invalid_wt, ribi_t::nsew[j])  &&  sea->is_water()  ) {
2731 								gr->weg_erweitern( water_wt, ribi_t::nsew[j] );
2732 								sea->calc_image();
2733 							}
2734 						}
2735 					}
2736 				}
2737 
2738 				// prissi: into UNDO-list, so we can remove it later
2739 				player_builder->add_undo( route[i] );
2740 			}
2741 
2742 			gr->calc_image();
2743 			minimap_t::get_instance()->calc_map_pixel( gr->get_pos().get_2d() );
2744 			player_t::book_construction_costs(player_builder, cost, gr->get_pos().get_2d(), desc->get_finance_waytype());
2745 
2746 			if((i&3)==0) {
2747 				INT_CHECK( "wegbauer 1584" );
2748 			}
2749 		}
2750 	}
2751 }
2752 
2753 
2754 
build_powerline()2755 void way_builder_t::build_powerline()
2756 {
2757 	if(  get_count() < 1  ) {
2758 		return;
2759 	}
2760 
2761 	// no undo
2762 	player_builder->init_undo(powerline_wt,get_count());
2763 
2764 	for(  uint32 i=0;  i<get_count();  i++  ) {
2765 		grund_t* gr = welt->lookup(route[i]);
2766 
2767 		leitung_t* lt = gr->get_leitung();
2768 		bool build_powerline = false;
2769 		// ok, really no lt here ...
2770 		if(lt==NULL) {
2771 			if(gr->ist_natur()) {
2772 				// remove trees etc.
2773 				sint64 cost = gr->remove_trees();
2774 				player_t::book_construction_costs(player_builder, -cost, gr->get_pos().get_2d(), powerline_wt);
2775 			}
2776 			lt = new leitung_t(route[i], player_builder );
2777 			gr->obj_add(lt);
2778 
2779 			// prissi: into UNDO-list, so we can remove it later
2780 			player_builder->add_undo( route[i] );
2781 			build_powerline = true;
2782 		}
2783 		else {
2784 			// modernize the network
2785 			if( !keep_existing_faster_ways  ||  lt->get_desc()->get_topspeed() < desc->get_topspeed()  ) {
2786 				build_powerline = true;
2787 				player_t::add_maintenance( lt->get_owner(),  -lt->get_desc()->get_maintenance(), powerline_wt );
2788 			}
2789 		}
2790 		if (build_powerline) {
2791 			lt->set_desc(desc);
2792 			player_t::book_construction_costs(player_builder, -desc->get_price(), gr->get_pos().get_2d(), powerline_wt);
2793 			// this adds maintenance
2794 			lt->leitung_t::finish_rd();
2795 			minimap_t::get_instance()->calc_map_pixel( gr->get_pos().get_2d() );
2796 		}
2797 
2798 		if((i&3)==0) {
2799 			INT_CHECK( "wegbauer 1584" );
2800 		}
2801 	}
2802 }
2803 
2804 
2805 
2806 // this can drive any river, even a river that has max_speed=0
2807 class fluss_test_driver_t : public test_driver_t
2808 {
check_next_tile(const grund_t * gr) const2809 	bool check_next_tile(const grund_t* gr) const OVERRIDE { return gr->get_weg_ribi_unmasked(water_wt)!=0; }
get_ribi(const grund_t * gr) const2810 	ribi_t::ribi get_ribi(const grund_t* gr) const OVERRIDE { return gr->get_weg_ribi_unmasked(water_wt); }
get_waytype() const2811 	waytype_t get_waytype() const OVERRIDE { return invalid_wt; }
get_cost(const grund_t *,const weg_t *,const sint32,ribi_t::ribi) const2812 	int get_cost(const grund_t *, const weg_t *, const sint32, ribi_t::ribi) const OVERRIDE { return 1; }
is_target(const grund_t * cur,const grund_t *) const2813 	bool is_target(const grund_t *cur,const grund_t *) const OVERRIDE { return cur->is_water()  &&  cur->get_grund_hang()==slope_t::flat; }
2814 };
2815 
2816 
2817 // make a river
build_river()2818 void way_builder_t::build_river()
2819 {
2820 	/* since the constraints of the wayfinder ensures that a river flows always downwards
2821 	 * we can assume that the first tiles are the ocean.
2822 	 * Usually the wayfinder would find either direction!
2823 	 * route.front() tile at the ocean, route.back() the spring of the river
2824 	 */
2825 
2826 	// Do we join an other river?
2827 	uint32 start_n = 0;
2828 	for(  uint32 idx=start_n;  idx<get_count();  idx++  ) {
2829 		if(  welt->lookup(route[idx])->hat_weg(water_wt)  ||  welt->lookup(route[idx])->get_hoehe() == welt->get_water_hgt(route[idx].get_2d())  ) {
2830 			start_n = idx;
2831 		}
2832 	}
2833 	if(  start_n == get_count()-1  ) {
2834 		// completely joined another river => nothing to do
2835 		return;
2836 	}
2837 
2838 	// first check then lower riverbed
2839 	const sint8 start_h = route[start_n].z;
2840 	uint32 end_n = get_count();
2841 	uint32 i = start_n;
2842 	while(i<get_count()) {
2843 		// first find all tiles that are on the same level as tile i
2844 		// and check whether we can lower all of them
2845 		// if lowering fails we do not continue river building
2846 		bool ok = true;
2847 		uint32 j;
2848 		for(j=i; j<get_count() &&  ok; j++) {
2849 			// one step higher?
2850 			if (route[j].z > route[i].z) break;
2851 			// check
2852 			ok = welt->can_flatten_tile(NULL, route[j].get_2d(), max(route[j].z-1, start_h));
2853 		}
2854 		// now lower all tiles that have the same height as tile i
2855 		for(uint32 k=i; k<j; k++) {
2856 			welt->flatten_tile(NULL, route[k].get_2d(), max(route[k].z-1, start_h));
2857 		}
2858 		if (!ok) {
2859 			end_n = j;
2860 			break;
2861 		}
2862 		i = j;
2863 	}
2864 	// nothing to built ?
2865 	if (start_n >= end_n-1) {
2866 		return;
2867 	}
2868 
2869 	// now build the river
2870 	grund_t *gr_first = NULL;
2871 	for(  uint32 i=start_n;  i<end_n;  i++  ) {
2872 		grund_t* gr = welt->lookup_kartenboden(route[i].get_2d());
2873 		if(  gr_first == NULL) {
2874 			gr_first = gr;
2875 		}
2876 		if(  gr->get_typ()!=grund_t::wasser  ) {
2877 			// get direction
2878 			ribi_t::ribi ribi = i<end_n-1 ? route.get_short_ribi(i) : ribi_type(route[i-1]-route[i]);
2879 			bool extend = gr->weg_erweitern(water_wt, ribi);
2880 			if(  !extend  ) {
2881 				weg_t *sch=weg_t::alloc(water_wt);
2882 				sch->set_desc(desc);
2883 				gr->neuen_weg_bauen(sch, ribi, NULL);
2884 			}
2885 		}
2886 	}
2887 	gr_first->calc_image(); // to calculate ribi of water tiles
2888 
2889 	// we will make rivers gradually larger by stepping up their width
2890 	if(  env_t::river_types>1  &&  start_n<get_count()) {
2891 		/* since we will stop at the first crossing with an existent river,
2892 		 * we cannot make sure, we have the same destination;
2893 		 * thus we use the routefinder to find the sea
2894 		 */
2895 		route_t to_the_sea;
2896 		fluss_test_driver_t river_tester;
2897 		if (to_the_sea.find_route(welt, welt->lookup_kartenboden(route[start_n].get_2d())->get_pos(), &river_tester, 0, ribi_t::all, 0x7FFFFFFF)) {
2898 			FOR(koord3d_vector_t, const& i, to_the_sea.get_route()) {
2899 				if (weg_t* const w = welt->lookup(i)->get_weg(water_wt)) {
2900 					int type;
2901 					for(  type=env_t::river_types-1;  type>0;  type--  ) {
2902 						// lookup type
2903 						if(  w->get_desc()==desc_table.get(env_t::river_type[type])  ) {
2904 							break;
2905 						}
2906 					}
2907 					// still room to expand
2908 					if(  type>0  ) {
2909 						// thus we enlarge
2910 						w->set_desc( desc_table.get(env_t::river_type[type-1]) );
2911 						w->calc_image();
2912 					}
2913 				}
2914 			}
2915 		}
2916 	}
2917 }
2918 
2919 
2920 
build()2921 void way_builder_t::build()
2922 {
2923 	if(get_count()<2  ||  get_count() > maximum) {
2924 DBG_MESSAGE("way_builder_t::build()","called, but no valid route.");
2925 		// no valid route here ...
2926 		return;
2927 	}
2928 	DBG_MESSAGE("way_builder_t::build()", "type=%d max_n=%d start=%d,%d end=%d,%d", bautyp, get_count() - 1, route.front().x, route.front().y, route.back().x, route.back().y);
2929 
2930 #ifdef DEBUG_ROUTES
2931 uint32 ms = dr_time();
2932 #endif
2933 
2934 	if ( (bautyp&terraform_flag)!=0  &&  (bautyp&(tunnel_flag|elevated_flag))==0  &&  bautyp!=river) {
2935 		// do the terraforming
2936 		do_terraforming();
2937 	}
2938 	// first add all new underground tiles ... (and finished if successful)
2939 	if(bautyp&tunnel_flag) {
2940 		build_tunnel_tile();
2941 		return;
2942 	}
2943 
2944 	// add elevated ground for elevated tracks
2945 	if(bautyp&elevated_flag) {
2946 		build_elevated();
2947 	}
2948 
2949 
2950 INT_CHECK("simbau 1072");
2951 	switch(bautyp&bautyp_mask) {
2952 		case wasser:
2953 		case schiene:
2954 		case schiene_tram: // Dario: Tramway
2955 		case monorail:
2956 		case maglev:
2957 		case narrowgauge:
2958 		case luft:
2959 			DBG_MESSAGE("way_builder_t::build", "schiene");
2960 			build_track();
2961 			break;
2962 		case strasse:
2963 			build_road();
2964 			DBG_MESSAGE("way_builder_t::build", "strasse");
2965 			break;
2966 		case leitung:
2967 			build_powerline();
2968 			break;
2969 		case river:
2970 			build_river();
2971 			break;
2972 		default:
2973 			break;
2974 	}
2975 
2976 	INT_CHECK("simbau 1087");
2977 	build_tunnel_and_bridges();
2978 
2979 	INT_CHECK("simbau 1087");
2980 
2981 #ifdef DEBUG_ROUTES
2982 DBG_MESSAGE("way_builder_t::build", "took %u ms", dr_time() - ms );
2983 #endif
2984 }
2985 
2986 
2987 
2988 /*
2989  * This function calculates the distance of pos to the cuboid
2990  * spanned up by mini and maxi.
2991  * The result is already weighted according to
2992  * welt->get_settings().get_way_count_{straight,slope}().
2993  */
calc_distance(const koord3d & pos,const koord3d & mini,const koord3d & maxi)2994 uint32 way_builder_t::calc_distance( const koord3d &pos, const koord3d &mini, const koord3d &maxi )
2995 {
2996 	uint32 dist = 0;
2997 	if( pos.x < mini.x ) {
2998 		dist += mini.x - pos.x;
2999 	} else if( pos.x > maxi.x ) {
3000 		dist += pos.x - maxi.x;
3001 	}
3002 	if( pos.y < mini.y ) {
3003 		dist += mini.y - pos.y;
3004 	} else if( pos.y > maxi.y ) {
3005 		dist += pos.y - maxi.y;
3006 	}
3007 	settings_t const& s = welt->get_settings();
3008 	dist *= s.way_count_straight;
3009 	if( pos.z < mini.z ) {
3010 		dist += (mini.z - pos.z) * s.way_count_slope;
3011 	} else if( pos.z > maxi.z ) {
3012 		dist += (pos.z - maxi.z) * s.way_count_slope;
3013 	}
3014 	return dist;
3015 }
3016