1 /*
2  * Copyright (c) 2008 Markus Pristovsek
3  *
4  * This file is part of the Simutrans project under the artistic licence.
5  * (see licence.txt)
6  */
7 
8 /* simple passenger AI (not using trains, not pre-optimized network) */
9 
10 #include "../simcity.h"
11 #include "../simconvoi.h"
12 #include "../simfab.h"
13 #include "../simhalt.h"
14 #include "../simline.h"
15 #include "../simmenu.h"
16 #include "../simmesg.h"
17 #include "../simworld.h"
18 
19 #include "../bauer/brueckenbauer.h"
20 #include "../bauer/hausbauer.h"
21 #include "../bauer/tunnelbauer.h"
22 #include "../bauer/vehikelbauer.h"
23 #include "../bauer/wegbauer.h"
24 
25 #include "../dataobj/schedule.h"
26 #include "../dataobj/loadsave.h"
27 #include "../dataobj/marker.h"
28 
29 #include "../utils/cbuffer_t.h"
30 #include "../utils/simrandom.h"
31 #include "../utils/simstring.h"
32 
33 #include "../vehicle/simvehicle.h"
34 
35 #include "ai_passenger.h"
36 #include "finance.h"
37 
38 
ai_passenger_t(uint8 nr)39 ai_passenger_t::ai_passenger_t(uint8 nr) : ai_t( nr )
40 {
41 	state = NR_INIT;
42 
43 	road_vehicle = NULL;
44 	road_weg = NULL;
45 
46 	next_construction_steps = welt->get_steps() + 50;
47 
48 	road_transport = true;
49 	rail_transport = false;
50 	air_transport = true;
51 	ship_transport = true;
52 
53 	start_stadt = end_stadt = NULL;
54 	ziel = NULL;
55 	end_attraction = NULL;
56 }
57 
58 
59 /* Activates/deactivates a player
60  * @author prissi
61  */
set_active(bool new_state)62 bool ai_passenger_t::set_active(bool new_state)
63 {
64 	// only activate, when there are buses available!
65 	if(  new_state  ) {
66 		new_state = NULL!=vehikel_search( road_wt, 50, 80, goods_manager_t::passengers, false);
67 	}
68 	return player_t::set_active( new_state );
69 }
70 
71 
72 /* return the hub of a city (always the very first stop) or zero
73  * @author prissi
74  */
get_our_hub(const stadt_t * s) const75 halthandle_t ai_passenger_t::get_our_hub( const stadt_t *s ) const
76 {
77 	FOR(vector_tpl<halthandle_t>, const halt, haltestelle_t::get_alle_haltestellen()) {
78 		if (halt->get_owner() == sim::up_cast<player_t const*>(this)) {
79 			if(  halt->get_pax_enabled()  &&  (halt->get_station_type()&haltestelle_t::busstop)!=0  ) {
80 				koord h=halt->get_basis_pos();
81 				if(h.x>=s->get_linksoben().x  &&  h.y>=s->get_linksoben().y  &&  h.x<=s->get_rechtsunten().x  &&  h.y<=s->get_rechtsunten().y  ) {
82 					return halt;
83 				}
84 			}
85 		}
86 	}
87 	return halthandle_t();
88 }
89 
90 
find_area_for_hub(const koord lo,const koord ru,const koord basis) const91 koord ai_passenger_t::find_area_for_hub( const koord lo, const koord ru, const koord basis ) const
92 {
93 	// no found found
94 	koord best_pos = koord::invalid;
95 	// "shortest" distance
96 	int dist = 999;
97 
98 	for( sint16 x=lo.x;  x<=ru.x;  x++ ) {
99 		for( sint16 y=lo.y;  y<=ru.y;  y++ ) {
100 			const koord trypos(x,y);
101 			const grund_t * gr = welt->lookup_kartenboden(trypos);
102 			if(gr) {
103 				// flat, solid
104 				if(  gr->get_typ()==grund_t::boden  &&  gr->get_grund_hang()==slope_t::flat  ) {
105 					const obj_t* obj = gr->obj_bei(0);
106 					int test_dist = koord_distance( trypos, basis );
107 					if (!obj || !obj->get_owner() || obj->get_owner() == sim::up_cast<player_t const*>(this)) {
108 						if(  gr->is_halt()  &&  check_owner( gr->get_halt()->get_owner(), this )  &&  gr->hat_weg(road_wt)  ) {
109 							// ok, one halt belongs already to us ... (should not really happen!) but might be a public stop
110 							return trypos;
111 						} else if(  test_dist<dist  &&  gr->hat_weg(road_wt)  &&  !gr->is_halt()  ) {
112 							ribi_t::ribi  ribi = gr->get_weg_ribi_unmasked(road_wt);
113 							if(  ribi_t::is_straight(ribi)  ||  ribi_t::is_single(ribi)  ) {
114 								best_pos = trypos;
115 								dist = test_dist;
116 							}
117 						} else if(  test_dist+2<dist  &&  gr->ist_natur()  ) {
118 							// also ok for a stop, but second choice
119 							// so we gave it a malus of 2
120 							best_pos = trypos;
121 							dist = test_dist+2;
122 						}
123 					}
124 				}
125 			}
126 		}
127 	}
128 DBG_MESSAGE("ai_passenger_t::find_area_for_hub()","suggest hub at (%i,%i)",best_pos.x,best_pos.y);
129 	return best_pos;
130 }
131 
132 
133 /* tries to built a hub near the koordinate
134  * @author prissi
135  */
find_place_for_hub(const stadt_t * s) const136 koord ai_passenger_t::find_place_for_hub( const stadt_t *s ) const
137 {
138 	halthandle_t h = get_our_hub( s );
139 	if(h.is_bound()) {
140 		return h->get_basis_pos();
141 	}
142 	return find_area_for_hub( s->get_linksoben(), s->get_rechtsunten(), s->get_pos() );
143 }
144 
145 
find_harbour_pos(karte_t * welt,const stadt_t * s)146 koord ai_passenger_t::find_harbour_pos(karte_t* welt, const stadt_t *s )
147 {
148 	koord bestpos = koord::invalid, k;
149 	sint32 bestdist = 999999;
150 
151 	// try to find an airport place as close to the city as possible
152 	for(  k.y=max(6,s->get_linksoben().y-10); k.y<=min(welt->get_size().y-3-6,s->get_rechtsunten().y+10); k.y++  ) {
153 		for(  k.x=max(6,s->get_linksoben().x-25); k.x<=min(welt->get_size().x-3-6,s->get_rechtsunten().x+10); k.x++  ) {
154 			sint32 testdist = koord_distance( k, s->get_pos() );
155 			if(  testdist<bestdist  ) {
156 				if(  k.x+2<s->get_linksoben().x  ||  k.y+2<s->get_linksoben().y  ||  k.x>=s->get_rechtsunten().x  ||  k.y>=s->get_rechtsunten().y  ) {
157 					// malus for out of town
158 					testdist += 5;
159 				}
160 				if(  testdist<bestdist  ) {
161 					grund_t *gr = welt->lookup_kartenboden(k);
162 					slope_t::type hang = gr->get_grund_hang();
163 					if(  gr->ist_natur()  &&  gr->get_hoehe() == welt->get_water_hgt(k)  &&  slope_t::is_way(hang)  &&  welt->is_water( k - koord(hang), koord(hang) * 4 + koord(1, 1) )  ) {
164 						// can built busstop here?
165 						koord bushalt = k+koord(hang);
166 						gr = welt->lookup_kartenboden(bushalt);
167 						if(gr  &&  gr->ist_natur()) {
168 							bestpos = k;
169 							bestdist = testdist;
170 						}
171 					}
172 				}
173 			}
174 		}
175 	}
176 	return bestpos;
177 }
178 
179 
create_water_transport_vehikel(const stadt_t * start_stadt,const koord target_pos)180 bool ai_passenger_t::create_water_transport_vehikel(const stadt_t* start_stadt, const koord target_pos)
181 {
182 	const vehicle_desc_t *v_desc = vehikel_search(water_wt, 10, 40, goods_manager_t::passengers, false);
183 	if(v_desc==NULL  ) {
184 		// no ship there
185 		return false;
186 	}
187 
188 	if(  convoihandle_t::is_exhausted()  ) {
189 		// too many convois => cannot do anything about this ...
190 		return false;
191 	}
192 
193 	stadt_t *end_stadt = NULL;
194 	grund_t *ziel = welt->lookup_kartenboden(target_pos);
195 	gebaeude_t *gb = ziel->find<gebaeude_t>();
196 	if(gb  &&  gb->is_townhall()) {
197 		end_stadt = gb->get_stadt();
198 	}
199 	else if(!ziel->is_halt()  ||  !ziel->is_water()) {
200 		// not townhall, not factory => we will not built this line for attractions!
201 		return false;
202 	}
203 
204 	halthandle_t start_hub = get_our_hub( start_stadt );
205 	halthandle_t start_connect_hub;
206 	koord start_harbour = koord::invalid;
207 	if(start_hub.is_bound()) {
208 		if(  (start_hub->get_station_type()&haltestelle_t::dock)==0  ) {
209 			start_connect_hub = start_hub;
210 			start_hub = halthandle_t();
211 			// is there already one harbour next to this one?
212 			FOR(vector_tpl<haltestelle_t::connection_t>, const& i, start_connect_hub->get_pax_connections()) {
213 				halthandle_t const h = i.halt;
214 				if( h->get_station_type()&haltestelle_t::dock  ) {
215 					start_hub = h;
216 					break;
217 				}
218 			}
219 		}
220 		else {
221 			start_harbour = start_hub->get_basis_pos();
222 		}
223 	}
224 	// find an dock place
225 	if(!start_hub.is_bound()) {
226 		start_harbour = find_harbour_pos( welt, start_stadt );
227 	}
228 	if(start_harbour==koord::invalid) {
229 		// sorry, no suitable place
230 		return false;
231 	}
232 	// same for end
233 	halthandle_t end_hub = end_stadt ? get_our_hub( end_stadt ) : ziel->get_halt();
234 	halthandle_t end_connect_hub;
235 	koord end_harbour = koord::invalid;
236 	if(end_hub.is_bound()) {
237 		if(  (end_hub->get_station_type()&haltestelle_t::dock)==0  ) {
238 			end_connect_hub = end_hub;
239 			end_hub = halthandle_t();
240 			// is there already one harbour next to this one?
241 			FOR(vector_tpl<haltestelle_t::connection_t>, const& i, end_connect_hub->get_pax_connections()) {
242 				halthandle_t const h = i.halt;
243 				if( h->get_station_type()&haltestelle_t::dock  ) {
244 					start_hub = h;
245 					break;
246 				}
247 			}
248 		}
249 		else {
250 			end_harbour = end_hub->get_basis_pos();
251 		}
252 	}
253 	if(!end_hub.is_bound()  &&  end_stadt) {
254 		// find an dock place
255 		end_harbour = find_harbour_pos( welt, end_stadt );
256 	}
257 	if(end_harbour==koord::invalid) {
258 		// sorry, no suitable place
259 		return false;
260 	}
261 
262 	const koord start_dx(welt->lookup_kartenboden(start_harbour)->get_grund_hang());
263 	const koord end_dx(welt->lookup_kartenboden(end_harbour)->get_grund_hang());
264 
265 	// now we must check, if these two seas are connected
266 	{
267 		// we use the free own vehicle_desc_t
268 		vehicle_desc_t remover_desc( water_wt, 500, vehicle_desc_t::diesel );
269 		vehicle_t* test_driver = vehicle_builder_t::build( koord3d( start_harbour - start_dx, welt->get_water_hgt( start_harbour - start_dx ) ), this, NULL, &remover_desc );
270 		test_driver->set_flag( obj_t::not_on_map );
271 		route_t verbindung;
272 		bool connected = verbindung.calc_route( welt, koord3d( start_harbour - start_dx, welt->get_water_hgt( start_harbour - start_dx ) ), koord3d( end_harbour - end_dx, welt->get_water_hgt( end_harbour - end_dx ) ), test_driver, 0, 0 );
273 		delete test_driver;
274 		if(!connected) {
275 			return false;
276 		}
277 	}
278 
279 	// build the harbour if necessary
280 	if(!start_hub.is_bound()) {
281 		koord bushalt = start_harbour+start_dx;
282 		const koord town_road = find_place_for_hub( start_stadt );
283 		// first: built street to harbour
284 		if(town_road!=bushalt) {
285 			way_builder_t bauigel(this);
286 			// no bridges => otherwise first tile might be bridge start ...
287 			bauigel.init_builder( way_builder_t::strasse, way_builder_t::weg_search( road_wt, 25, welt->get_timeline_year_month(), type_flat ), tunnel_builder_t::get_tunnel_desc(road_wt,road_vehicle->get_topspeed(),welt->get_timeline_year_month()), NULL );
288 			bauigel.set_keep_existing_faster_ways(true);
289 			bauigel.set_keep_city_roads(true);
290 			bauigel.set_maximum(10000);
291 			bauigel.calc_route( welt->lookup_kartenboden(bushalt)->get_pos(), welt->lookup_kartenboden(town_road)->get_pos() );
292 			if(bauigel.get_count()-1 <= 1) {
293 				return false;
294 			}
295 			bauigel.build();
296 		}
297 	}
298 	if(!end_hub.is_bound()) {
299 		koord bushalt = end_harbour+end_dx;
300 		const koord town_road = find_place_for_hub( end_stadt );
301 		// first: built street to harbour
302 		if(town_road!=bushalt) {
303 			way_builder_t bauigel(this);
304 			// no bridges => otherwise first tile might be bridge start ...
305 			bauigel.init_builder( way_builder_t::strasse, way_builder_t::weg_search( road_wt, 25, welt->get_timeline_year_month(), type_flat ), tunnel_builder_t::get_tunnel_desc(road_wt,road_vehicle->get_topspeed(),welt->get_timeline_year_month()), NULL );
306 			bauigel.set_keep_existing_faster_ways(true);
307 			bauigel.set_keep_city_roads(true);
308 			bauigel.set_maximum(10000);
309 			bauigel.calc_route( welt->lookup_kartenboden(bushalt)->get_pos(), welt->lookup_kartenboden(town_road)->get_pos() );
310 			if(bauigel.get_count()-1 <= 1) {
311 				return false;
312 			}
313 			bauigel.build();
314 		}
315 	}
316 	// now built the stops ... (since the roads were ok!)
317 	if(!start_hub.is_bound()) {
318 		/* first we must built the bus stop, since this will be the default stop for all our buses
319 		 * we want to keep the name of a dock, thus we will create it beforehand
320 		 */
321 		koord bushalt = start_harbour+start_dx;
322 		const building_desc_t* busstop_desc = hausbauer_t::get_random_station(building_desc_t::generic_stop, road_wt, welt->get_timeline_year_month(), haltestelle_t::PAX );
323 		// now built the bus stop
324 		if(!call_general_tool( TOOL_BUILD_STATION, bushalt, busstop_desc->get_name() )) {
325 			return false;
326 		}
327 		// and change name to dock ...
328 		grund_t *gr = welt->lookup_kartenboden(bushalt);
329 		halthandle_t halt = gr ? gr->get_halt() : halthandle_t();
330 		if (halt.is_bound()) { // it should be, but avoid crashes
331 			char* const name = halt->create_name(bushalt, "Dock");
332 			halt->set_name( name );
333 			free(name);
334 		}
335 		// finally built the dock
336 		const building_desc_t* dock_desc = hausbauer_t::get_random_station(building_desc_t::dock, water_wt, welt->get_timeline_year_month(), 0);
337 		welt->lookup_kartenboden(start_harbour)->obj_loesche_alle(this);
338 		call_general_tool( TOOL_BUILD_STATION, start_harbour, dock_desc->get_name() );
339 		grund_t *harbour_gr = welt->lookup_kartenboden(start_harbour);
340 		start_hub = harbour_gr ? harbour_gr->get_halt() : halthandle_t();
341 		// eventually we must built a hub in the next town
342 		start_connect_hub = get_our_hub( start_stadt );
343 		if(!start_connect_hub.is_bound()) {
344 			koord sch = find_place_for_hub( start_stadt );
345 			call_general_tool( TOOL_BUILD_STATION, sch, busstop_desc->get_name() );
346 			start_connect_hub = get_our_hub( start_stadt );
347 			assert( start_connect_hub.is_bound() );
348 		}
349 	}
350 	if(!end_hub.is_bound()) {
351 		/* again we must built the bus stop first, since this will be the default stop for all our buses
352 		 * we want to keep the name of a dock, thus we will create it beforehand
353 		 */
354 		koord bushalt = end_harbour+end_dx;
355 		const building_desc_t* busstop_desc = hausbauer_t::get_random_station(building_desc_t::generic_stop, road_wt, welt->get_timeline_year_month(), haltestelle_t::PAX );
356 		// now built the bus stop
357 		if(!call_general_tool( TOOL_BUILD_STATION, bushalt, busstop_desc->get_name() )) {
358 			return false;
359 		}
360 		// and change name to dock ...
361 		grund_t *gr = welt->lookup_kartenboden(bushalt);
362 		halthandle_t halt = gr ? gr->get_halt() : halthandle_t();
363 		if (halt.is_bound()) { // it should be, but avoid crashes
364 			char* const name = halt->create_name(bushalt, "Dock");
365 			halt->set_name( name );
366 			free(name);
367 		}
368 		// finally built the dock
369 		const building_desc_t* dock_desc = hausbauer_t::get_random_station(building_desc_t::dock, water_wt, welt->get_timeline_year_month(), 0 );
370 		welt->lookup_kartenboden(end_harbour)->obj_loesche_alle(this);
371 		call_general_tool( TOOL_BUILD_STATION, end_harbour, dock_desc->get_name() );
372 		grund_t *harbour_gr = welt->lookup_kartenboden(end_harbour);
373 		end_hub = harbour_gr ? harbour_gr->get_halt() : halthandle_t();
374 		// eventually we must built a hub in the next town
375 		end_connect_hub = get_our_hub( end_stadt );
376 		if(!end_connect_hub.is_bound()) {
377 			koord ech = find_place_for_hub( end_stadt );
378 			call_general_tool( TOOL_BUILD_STATION, ech, busstop_desc->get_name() );
379 			end_connect_hub = get_our_hub( end_stadt );
380 			assert( end_connect_hub.is_bound() );
381 		}
382 	}
383 
384 	uint16 const cov = welt->get_settings().get_station_coverage();
385 	// now we have harbour => find start position for ships
386 	koord pos1 = start_harbour-start_dx;
387 	koord start_pos = pos1;
388 	for (int y = pos1.y - cov; y <= pos1.y + cov; ++y) {
389 		for (int x = pos1.x - cov; x <= pos1.x + cov; ++x) {
390 			koord p(x,y);
391 			const planquadrat_t *plan = welt->access(p);
392 			if(plan) {
393 				grund_t *gr = plan->get_kartenboden();
394 				if(  gr->is_water()  &&  !gr->get_halt().is_bound()  ) {
395 					if(plan->get_haltlist_count()>=1  &&  plan->get_haltlist()[0]==start_hub  &&  koord_distance(start_pos,end_harbour)>koord_distance(p,end_harbour)) {
396 						start_pos = p;
397 					}
398 				}
399 			}
400 		}
401 	}
402 	// now we have harbour => find start position for ships
403 	pos1 = end_harbour-end_dx;
404 	koord end_pos = pos1;
405 	for (int y = pos1.y - cov; y <= pos1.y + cov; ++y) {
406 		for (int x = pos1.x - cov; x <= pos1.x + cov; ++x) {
407 			koord p(x,y);
408 			const planquadrat_t *plan = welt->access(p);
409 			if(plan) {
410 				grund_t *gr = plan->get_kartenboden();
411 				if(  gr->is_water()  &&  !gr->get_halt().is_bound()  ) {
412 					if(plan->get_haltlist_count()>=1  &&  plan->get_haltlist()[0]==end_hub  &&  koord_distance(end_pos,start_harbour)>koord_distance(p,start_harbour)) {
413 						end_pos = p;
414 					}
415 				}
416 			}
417 		}
418 	}
419 
420 	// since 86.01 we use lines for vehicles ...
421 	schedule_t *schedule=new ship_schedule_t();
422 	schedule->append( welt->lookup_kartenboden(start_pos), 0, 0 );
423 	schedule->append( welt->lookup_kartenboden(end_pos), 90, 0 );
424 	schedule->set_current_stop( 1 );
425 	schedule->finish_editing();
426 	linehandle_t line=simlinemgmt.create_line(simline_t::shipline,this,schedule);
427 	delete schedule;
428 
429 	// now create one ship
430 	vehicle_t* v = vehicle_builder_t::build( koord3d( start_pos, welt->get_water_hgt( start_pos ) ), this, NULL, v_desc );
431 	convoi_t* cnv = new convoi_t(this);
432 	cnv->set_name(v->get_desc()->get_name());
433 	cnv->add_vehikel( v );
434 	cnv->set_line(line);
435 	cnv->start();
436 
437 	// eventually build a shuttle bus ...
438 	if(start_connect_hub.is_bound()  &&  start_connect_hub!=start_hub) {
439 		koord stops[2] = { start_harbour+start_dx, start_connect_hub->get_basis_pos() };
440 		create_bus_transport_vehikel( stops[1], 1, stops, 2, false );
441 	}
442 
443 	// eventually build a airport shuttle bus ...
444 	if(end_connect_hub.is_bound()  &&  end_connect_hub!=end_hub) {
445 		koord stops[2] = { end_harbour+end_dx, end_connect_hub->get_basis_pos() };
446 		create_bus_transport_vehikel( stops[1], 1, stops, 2, false );
447 	}
448 
449 	return true;
450 }
451 
452 
build_airport(const stadt_t * city,koord pos,int rotation)453 halthandle_t ai_passenger_t::build_airport(const stadt_t* city, koord pos, int rotation)
454 {
455 	// not too close to border?
456 	if(pos.x<6  ||  pos.y<6  ||  pos.x+3+6>=welt->get_size().x  ||  pos.y+3+6>=welt->get_size().y  ) {
457 		return halthandle_t();
458 	}
459 	// ok, not prematurely doomed
460 	// can we built airports at all?
461 	const way_desc_t *taxi_desc = way_builder_t::weg_search( air_wt, 25, welt->get_timeline_year_month(), type_flat );
462 	const way_desc_t *runway_desc = way_builder_t::weg_search( air_wt, 250, welt->get_timeline_year_month(), type_runway );
463 	if(taxi_desc==NULL  ||  runway_desc==NULL) {
464 		return halthandle_t();
465 	}
466 	// first, check if at least one tile is within city limits
467 	const koord lo = city->get_linksoben();
468 	koord size(3-1,3-1);
469 	// make sure pos is within city limits!
470 	if(pos.x<lo.x) {
471 		pos.x += size.x;
472 		size.x = -size.x;
473 	}
474 	if(pos.y<lo.y) {
475 		pos.y += size.y;
476 		size.y = -size.y;
477 	}
478 	// find coord to connect in the town
479 	halthandle_t hub = get_our_hub( city );
480 	const koord town_road = hub.is_bound() ? hub->get_basis_pos() : find_place_for_hub( city );
481 	if(  town_road==koord::invalid) {
482 		return halthandle_t();
483 	}
484 	// ok, now we could built it => flatten the land
485 	sint8 h = max( welt->get_water_hgt(pos) + 1, welt->lookup_kartenboden(pos)->get_hoehe() );
486 	const koord dx( size.x/2, size.y/2 );
487 	for(  sint16 i=0;  i!=size.y+dx.y;  i+=dx.y  ) {
488 		for( sint16 j=0;  j!=size.x+dx.x;  j+=dx.x  ) {
489 			climate c = welt->get_climate(pos+koord(j,i));
490 			if(!welt->flatten_tile(this,pos+koord(j,i),h)) {
491 				return halthandle_t();
492 			}
493 			// ensure is land
494 			grund_t* bd = welt->lookup_kartenboden(pos+koord(j,i));
495 			if (bd->get_typ() == grund_t::wasser) {
496 				welt->set_water_hgt(pos+koord(j,i), bd->get_hoehe()-1);
497 				welt->access(pos+koord(j,i))->correct_water();
498 				welt->set_climate(pos+koord(j,i), c, true);
499 			}
500 		}
501 	}
502 	// now taxiways
503 	way_builder_t bauigel(this);
504 	// 3x3 layout, first we make the taxiway cross
505 	koord center=pos+dx;
506 	bauigel.init_builder( way_builder_t::luft, taxi_desc, NULL, NULL );
507 	bauigel.calc_straight_route( welt->lookup_kartenboden(center+koord::north)->get_pos(), welt->lookup_kartenboden(center+koord::south)->get_pos() );
508 	assert(bauigel.get_count()-1 > 1);
509 	bauigel.build();
510 	bauigel.init_builder( way_builder_t::luft, taxi_desc, NULL, NULL );
511 	bauigel.calc_straight_route( welt->lookup_kartenboden(center+koord::west)->get_pos(), welt->lookup_kartenboden(center+koord::east)->get_pos() );
512 	assert(bauigel.get_count()-1 > 1);
513 	bauigel.build();
514 	// now try to connect one of the corners with a road
515 	koord bushalt = koord::invalid, runwaystart, runwayend;
516 	koord trypos[4] = { koord(0,0), koord(size.x,0), koord(0,size.y), koord(size.x,size.y) };
517 	uint32 length=9999;
518 	rotation=-1;
519 
520 	bauigel.init_builder( way_builder_t::strasse, way_builder_t::weg_search( road_wt, 25, welt->get_timeline_year_month(), type_flat ), tunnel_builder_t::get_tunnel_desc(road_wt,road_vehicle->get_topspeed(),welt->get_timeline_year_month()), bridge_builder_t::find_bridge(road_wt,road_vehicle->get_topspeed(),welt->get_timeline_year_month()) );
521 	bauigel.set_keep_existing_faster_ways(true);
522 	bauigel.set_keep_city_roads(true);
523 	bauigel.set_maximum(10000);
524 
525 	// find the closest one to town ...
526 	for(  int i=0;  i<4;  i++  ) {
527 		bushalt = pos+trypos[i];
528 		bauigel.calc_route(welt->lookup_kartenboden(bushalt)->get_pos(),welt->lookup_kartenboden(town_road)->get_pos());
529 		// no road => try next
530 		if(  bauigel.get_count() >= 2  &&   bauigel.get_count() < length+1  ) {
531 			rotation = i;
532 			length = bauigel.get_count()-1;
533 		}
534 	}
535 
536 	if(rotation==-1) {
537 		// if we every get here that means no connection road => remove airport
538 		welt->lookup_kartenboden(center+koord::north)->remove_everything_from_way( this, air_wt, ribi_t::none );
539 		welt->lookup_kartenboden(center+koord::south)->remove_everything_from_way( this, air_wt, ribi_t::none );
540 		welt->lookup_kartenboden(center+koord::west)->remove_everything_from_way( this, air_wt, ribi_t::none );
541 		welt->lookup_kartenboden(center+koord::east)->remove_everything_from_way( this, air_wt, ribi_t::none );
542 		welt->lookup_kartenboden(center)->remove_everything_from_way( this, air_wt, ribi_t::all );
543 		return halthandle_t();
544 	}
545 
546 	bushalt = pos+trypos[rotation];
547 	bauigel.calc_route(welt->lookup_kartenboden(bushalt)->get_pos(),welt->lookup_kartenboden(town_road)->get_pos());
548 	bauigel.build();
549 	// now the busstop (our next hub ... )
550 	const building_desc_t* busstop_desc = hausbauer_t::get_random_station(building_desc_t::generic_stop, road_wt, welt->get_timeline_year_month(), haltestelle_t::PAX );
551 	// get an airport name (even though the hub is the bus stop ... )
552 	// now built the bus stop
553 	if(!call_general_tool( TOOL_BUILD_STATION, bushalt, busstop_desc->get_name() )) {
554 		welt->lookup_kartenboden(center+koord::north)->remove_everything_from_way( this, air_wt, ribi_t::none );
555 		welt->lookup_kartenboden(center+koord::south)->remove_everything_from_way( this, air_wt, ribi_t::none );
556 		welt->lookup_kartenboden(center+koord::west)->remove_everything_from_way( this, air_wt, ribi_t::none );
557 		welt->lookup_kartenboden(center+koord::east)->remove_everything_from_way( this, air_wt, ribi_t::none );
558 		welt->lookup_kartenboden(center)->remove_everything_from_way( this, air_wt, ribi_t::all );
559 		return halthandle_t();
560 	}
561 	// and change name to airport ...
562 	grund_t *gr = welt->lookup_kartenboden(bushalt);
563 	halthandle_t halt = gr ? gr->get_halt() : halthandle_t();
564 	if (halt.is_bound()) { // it should be, but avoid crashes
565 		char* const name = halt->create_name(bushalt, "Airport");
566 		halt->set_name( name );
567 		free(name);
568 	}
569 	// built also runway now ...
570 	bauigel.init_builder( way_builder_t::luft, runway_desc, NULL, NULL );
571 	bauigel.calc_straight_route( welt->lookup_kartenboden(pos+trypos[rotation==0?3:0])->get_pos(), welt->lookup_kartenboden(pos+trypos[1+(rotation&1)])->get_pos() );
572 	assert(bauigel.get_count()-1 > 1);
573 	bauigel.build();
574 	// now the airstops (only on single tiles, this will always work
575 	const building_desc_t* airstop_desc = hausbauer_t::get_random_station(building_desc_t::generic_stop, air_wt, welt->get_timeline_year_month(), 0 );
576 	for(  int i=0;  i<4;  i++  ) {
577 		if(  koord_distance(center+koord::nsew[i],bushalt)==1  &&  ribi_t::is_single( welt->lookup_kartenboden(center+koord::nsew[i])->get_weg_ribi_unmasked(air_wt) )  ) {
578 			call_general_tool( TOOL_BUILD_STATION, center+koord::nsew[i], airstop_desc->get_name() );
579 		}
580 	}
581 	// and now the one far away ...
582 	for(  int i=0;  i<4;  i++  ) {
583 		if(  koord_distance(center+koord::nsew[i],bushalt)>1  &&  ribi_t::is_single( welt->lookup_kartenboden(center+koord::nsew[i])->get_weg_ribi_unmasked(air_wt) )  ) {
584 			call_general_tool( TOOL_BUILD_STATION, center+koord::nsew[i], airstop_desc->get_name() );
585 		}
586 	}
587 	// success
588 	return halt;
589 }
590 
591 
find_airport_pos(karte_t * welt,const stadt_t * s)592 static koord find_airport_pos(karte_t* welt, const stadt_t *s )
593 {
594 	koord bestpos = koord::invalid, k;
595 	sint32 bestdist = 999999;
596 
597 	// try to find an airport place as close to the city as possible
598 	for(  k.y=max(6,s->get_linksoben().y-10); k.y<=min(welt->get_size().y-3-6,s->get_rechtsunten().y+10); k.y++  ) {
599 		for(  k.x=max(6,s->get_linksoben().x-25); k.x<=min(welt->get_size().x-3-6,s->get_rechtsunten().x+10); k.x++  ) {
600 			sint32 testdist = koord_distance( k, s->get_pos() );
601 			if(  testdist<bestdist  ) {
602 				if(  k.x+2<s->get_linksoben().x  ||  k.y+2<s->get_linksoben().y  ||  k.x>=s->get_rechtsunten().x  ||  k.y>=s->get_rechtsunten().y  ) {
603 					// malus for out of town
604 					testdist += 5;
605 				}
606 				if(  testdist<bestdist  &&  welt->square_is_free( k, 3, 3, NULL, ALL_CLIMATES )  ) {
607 					bestpos = k;
608 					bestdist = testdist;
609 				}
610 			}
611 		}
612 	}
613 	return bestpos;
614 }
615 
616 
617 /* build airports and planes
618  * @author prissi
619  */
create_air_transport_vehikel(const stadt_t * start_stadt,const stadt_t * end_stadt)620 bool ai_passenger_t::create_air_transport_vehikel(const stadt_t *start_stadt, const stadt_t *end_stadt)
621 {
622 	const vehicle_desc_t *v_desc = vehikel_search(air_wt, 10, 900, goods_manager_t::passengers, false);
623 	if(v_desc==NULL) {
624 		// no aircraft there
625 		return false;
626 	}
627 
628 	if(  convoihandle_t::is_exhausted()  ) {
629 		// too many convois => cannot do anything about this ...
630 		return false;
631 	}
632 
633 	halthandle_t start_hub = get_our_hub( start_stadt );
634 	halthandle_t start_connect_hub;
635 	koord start_airport;
636 	if(start_hub.is_bound()) {
637 		if(  (start_hub->get_station_type()&haltestelle_t::airstop)==0  ) {
638 			start_connect_hub = start_hub;
639 			start_hub = halthandle_t();
640 			// is there already one airport next to this town?
641 			FOR(vector_tpl<haltestelle_t::connection_t>, const& i, start_connect_hub->get_pax_connections()) {
642 				halthandle_t const h = i.halt;
643 				if( h->get_station_type()&haltestelle_t::airstop  ) {
644 					start_hub = h;
645 					break;
646 				}
647 			}
648 		}
649 		else {
650 			start_airport = start_hub->get_basis_pos();
651 		}
652 	}
653 	// find an airport place
654 	if(!start_hub.is_bound()) {
655 		start_airport = find_airport_pos( welt, start_stadt );
656 		if(start_airport==koord::invalid) {
657 			// sorry, no suitable place
658 			return false;
659 		}
660 	}
661 	// same for end
662 	halthandle_t end_hub = get_our_hub( end_stadt );
663 	halthandle_t end_connect_hub;
664 	koord end_airport;
665 	if(end_hub.is_bound()) {
666 		if(  (end_hub->get_station_type()&haltestelle_t::airstop)==0  ) {
667 			end_connect_hub = end_hub;
668 			end_hub = halthandle_t();
669 			// is there already one airport next to this town?
670 			FOR(vector_tpl<haltestelle_t::connection_t>, const& i, end_connect_hub->get_pax_connections()) {
671 				halthandle_t const h = i.halt;
672 				if( h->get_station_type()&haltestelle_t::airstop  ) {
673 					start_hub = h;
674 					break;
675 				}
676 			}
677 		}
678 		else {
679 			end_airport = end_hub->get_basis_pos();
680 		}
681 	}
682 	if(!end_hub.is_bound()) {
683 		// find an airport place
684 		end_airport = find_airport_pos( welt, end_stadt );
685 		if(end_airport==koord::invalid) {
686 			// sorry, no suitable place
687 			return false;
688 		}
689 	}
690 	// eventually construct them
691 	if(start_airport!=koord::invalid  &&  end_airport!=koord::invalid) {
692 		// build the airport if necessary
693 		if(!start_hub.is_bound()) {
694 			start_hub = build_airport(start_stadt, start_airport, true);
695 			if(!start_hub.is_bound()) {
696 				return false;
697 			}
698 			start_connect_hub = get_our_hub( start_stadt );
699 			if(!start_connect_hub.is_bound()) {
700 				koord sch = find_place_for_hub( start_stadt );
701 				// probably we must construct a city hub, since the airport is outside of the city limits
702 				const building_desc_t* busstop_desc = hausbauer_t::get_random_station(building_desc_t::generic_stop, road_wt, welt->get_timeline_year_month(), haltestelle_t::PAX );
703 				call_general_tool( TOOL_BUILD_STATION, sch, busstop_desc->get_name() );
704 				start_connect_hub = get_our_hub( start_stadt );
705 				assert( start_connect_hub.is_bound() );
706 			}
707 		}
708 		if(!end_hub.is_bound()) {
709 			end_hub = build_airport(end_stadt, end_airport, true);
710 			if(!end_hub.is_bound()) {
711 				if (start_hub->get_pax_connections().empty()) {
712 					// remove airport busstop
713 					welt->lookup_kartenboden(start_hub->get_basis_pos())->remove_everything_from_way( this, road_wt, ribi_t::none );
714 					koord center = start_hub->get_basis_pos() + koord( welt->lookup_kartenboden(start_hub->get_basis_pos())->get_weg_ribi_unmasked( air_wt ) );
715 					// now the remaining taxi-/runways
716 					for( sint16 y=center.y-1;  y<=center.y+1;  y++  ) {
717 						for( sint16 x=center.x-1;  x<=center.x+1;  x++  ) {
718 							welt->lookup_kartenboden(koord(x,y))->remove_everything_from_way( this, air_wt, ribi_t::none );
719 						}
720 					}
721 				}
722 				return false;
723 			}
724 			end_connect_hub = get_our_hub( end_stadt );
725 			if(!end_connect_hub.is_bound()) {
726 				koord ech = find_place_for_hub( end_stadt );
727 				// probably we must construct a city hub, since the airport is outside of the city limits
728 				const building_desc_t* busstop_desc = hausbauer_t::get_random_station(building_desc_t::generic_stop, road_wt, welt->get_timeline_year_month(), haltestelle_t::PAX );
729 				call_general_tool( TOOL_BUILD_STATION, ech, busstop_desc->get_name() );
730 				end_connect_hub = get_our_hub( end_stadt );
731 				assert( end_connect_hub.is_bound() );
732 			}
733 		}
734 	}
735 	// now we have airports (albeit first tile is a bus stop)
736 	const grund_t *start = start_hub->find_matching_position(air_wt);
737 	const grund_t *end = end_hub->find_matching_position(air_wt);
738 
739 	// since 86.01 we use lines for vehicles ...
740 	schedule_t *schedule=new airplane_schedule_t();
741 	schedule->append( start, 0, 0 );
742 	schedule->append( end, 90, 0 );
743 	schedule->set_current_stop( 1 );
744 	schedule->finish_editing();
745 	linehandle_t line=simlinemgmt.create_line(simline_t::airline,this,schedule);
746 	delete schedule;
747 
748 	// now create one plane
749 	vehicle_t* v = vehicle_builder_t::build( start->get_pos(), this, NULL, v_desc);
750 	convoi_t* cnv = new convoi_t(this);
751 	cnv->set_name(v->get_desc()->get_name());
752 	cnv->add_vehikel( v );
753 	cnv->set_line(line);
754 	cnv->start();
755 
756 	// eventually build a airport shuttle bus ...
757 	if(start_connect_hub.is_bound()  &&  start_connect_hub!=start_hub) {
758 		koord stops[2] = { start_hub->get_basis_pos(), start_connect_hub->get_basis_pos() };
759 		create_bus_transport_vehikel( stops[1], 1, stops, 2, false );
760 	}
761 
762 	// eventually build a airport shuttle bus ...
763 	if(end_connect_hub.is_bound()  &&  end_connect_hub!=end_hub) {
764 		koord stops[2] = { end_hub->get_basis_pos(), end_connect_hub->get_basis_pos() };
765 		create_bus_transport_vehikel( stops[1], 1, stops, 2, false );
766 	}
767 
768 	return true;
769 }
770 
771 
772 /* creates a more general road transport
773  * @author prissi
774  */
create_bus_transport_vehikel(koord startpos2d,int anz_vehikel,koord * stops,int count,bool do_wait)775 void ai_passenger_t::create_bus_transport_vehikel(koord startpos2d,int anz_vehikel,koord *stops,int count,bool do_wait)
776 {
777 DBG_MESSAGE("ai_passenger_t::create_bus_transport_vehikel()","bus at (%i,%i)",startpos2d.x,startpos2d.y);
778 	// now start all vehicle one field before, so they load immediately
779 	koord3d startpos = welt->lookup_kartenboden(startpos2d)->get_pos();
780 
781 	// since 86.01 we use lines for road vehicles ...
782 	schedule_t *schedule=new truck_schedule_t();
783 	// do not start at current stop => wont work ...
784 	for(int j=0;  j<count;  j++) {
785 		schedule->append(welt->lookup_kartenboden(stops[j]), j == 0 || !do_wait ? 0 : 10);
786 	}
787 	schedule->set_current_stop( stops[0]==startpos2d );
788 	schedule->finish_editing();
789 	linehandle_t line=simlinemgmt.create_line(simline_t::truckline,this,schedule);
790 	delete schedule;
791 
792 	// now create all vehicles as convois
793 	for(int i=0;  i<anz_vehikel;  i++) {
794 		vehicle_t* v = vehicle_builder_t::build(startpos, this, NULL, road_vehicle);
795 		if(  convoihandle_t::is_exhausted()  ) {
796 			// too many convois => cannot do anything about this ...
797 			return;
798 		}
799 		convoi_t* cnv = new convoi_t(this);
800 		// V.Meyer: give the new convoi name from first vehicle
801 		cnv->set_name(v->get_desc()->get_name());
802 		cnv->add_vehikel( v );
803 
804 		cnv->set_line(line);
805 		cnv->start();
806 	}
807 }
808 
809 
810 /* now we follow all adjacent streets recursively and mark them
811  * if they below to this stop, then we continue
812  */
walk_city(linehandle_t const line,grund_t * const start,int const limit)813 void ai_passenger_t::walk_city(linehandle_t const line, grund_t* const start, int const limit)
814 {
815 	//maximum number of stops reached?
816 	if(line->get_schedule()->get_count()>=limit)  {
817 		return;
818 	}
819 
820 	ribi_t::ribi ribi = start->get_weg_ribi(road_wt);
821 
822 	for(int r=0; r<4; r++) {
823 
824 		// a way in our direction?
825 		if(  (ribi & ribi_t::nsew[r])==0  ) {
826 			continue;
827 		}
828 
829 		// ok, if connected, not marked, and not owner by somebody else
830 		grund_t *to;
831 		if(  start->get_neighbour(to, road_wt, ribi_t::nsew[r] )  &&  !marker->is_marked(to)  &&  check_owner(to->obj_bei(0)->get_owner(),this)  ) {
832 
833 			// ok, here is a valid street tile
834 			marker->mark(to);
835 
836 			// can built a station here
837 			if(  ribi_t::is_straight(to->get_weg_ribi(road_wt))  ) {
838 
839 				// find out how many tiles we have covered already
840 				int covered_tiles=0;
841 				int house_tiles=0;
842 				uint16 const cov = welt->get_settings().get_station_coverage();
843 				for (sint16 y = to->get_pos().y - cov; y <= to->get_pos().y + cov + 1; ++y) {
844 					for (sint16 x = to->get_pos().x - cov; x <= to->get_pos().x + cov + 1; ++x) {
845 						const planquadrat_t *pl = welt->access(koord(x,y));
846 						// check, if we have a passenger stop already here
847 						if(pl  &&  pl->get_haltlist_count()>0) {
848 							const halthandle_t *hl=pl->get_haltlist();
849 							for( uint8 own=0;  own<pl->get_haltlist_count();  own++  ) {
850 								if(  hl[own]->is_enabled(goods_manager_t::INDEX_PAS)  ) {
851 									// our stop => nothing to do
852 #if AUTOJOIN_PUBLIC
853 									// we leave also public stops alone
854 									if(  hl[own]->get_owner()==this  ||  hl[own]->get_owner()==welt->get_public_player()  ) {
855 #else
856 									if(  hl[own]->get_owner()==this  ) {
857 #endif
858 										covered_tiles ++;
859 										break;
860 									}
861 								}
862 							}
863 						}
864 						// check for houses
865 						if(pl  &&  pl->get_kartenboden()->get_typ()==grund_t::fundament) {
866 							house_tiles++;
867 						}
868 					}
869 				}
870 				// now decide, if we build here
871 				// just using the ration of covered tiles versus house tiles
872 				int const max_tiles = cov * 2 + 1;
873 				if(  covered_tiles<(max_tiles*max_tiles)/3  &&  house_tiles>=3  ) {
874 					// ok, lets do it
875 					const building_desc_t* bs = hausbauer_t::get_random_station(building_desc_t::generic_stop, road_wt, welt->get_timeline_year_month(), haltestelle_t::PAX);
876 					if(  call_general_tool( TOOL_BUILD_STATION, to->get_pos().get_2d(), bs->get_name() )  ) {
877 						//add to line
878 						line->get_schedule()->append(to,0); // no need to register it yet; done automatically, when convois will be assigned
879 					}
880 				}
881 				// start road, but no houses anywhere => stop searching
882 				if(house_tiles==0) {
883 					return;
884 				}
885 			}
886 			// now do recursion
887 			walk_city( line, to, limit );
888 		}
889 	}
890 }
891 
892 
893 /* tries to cover a city with bus stops that does not overlap much and cover as much as possible
894  * returns the line created, if successful
895  */
896 void ai_passenger_t::cover_city_with_bus_route(koord start_pos, int number_of_stops)
897 {
898 	if(  convoihandle_t::is_exhausted()  ) {
899 		// too many convois => cannot do anything about this ...
900 		return;
901 	}
902 
903 	// nothing in lists
904 	marker = &marker_t::instance(welt->get_size().x, welt->get_size().y);
905 
906 	// and init all stuff for recursion
907 	grund_t *start = welt->lookup_kartenboden(start_pos);
908 	linehandle_t line = simlinemgmt.create_line( simline_t::truckline,this, new truck_schedule_t() );
909 	line->get_schedule()->append(start,0);
910 
911 	// now create a line
912 	walk_city( line, start, number_of_stops );
913 	line->get_schedule()->finish_editing();
914 
915 	road_vehicle = vehikel_search( road_wt, 1, 50, goods_manager_t::passengers, false);
916 	if( line->get_schedule()->get_count()>1  ) {
917 		// success: add a bus to the line
918 		vehicle_t* v = vehicle_builder_t::build(start->get_pos(), this, NULL, road_vehicle);
919 		convoi_t* cnv = new convoi_t(this);
920 
921 		cnv->set_name(v->get_desc()->get_name());
922 		cnv->add_vehikel( v );
923 
924 		cnv->set_line(line);
925 		cnv->start();
926 	}
927 	else {
928 		simlinemgmt.delete_line( line );
929 	}
930 	marker = NULL;
931 }
932 
933 
934 void ai_passenger_t::step()
935 {
936 	// needed for schedule of stops ...
937 	player_t::step();
938 
939 	if(!active) {
940 		// I am off ...
941 		return;
942 	}
943 
944 	// one route per month ...
945 	if(  welt->get_steps() < next_construction_steps  ) {
946 		return;
947 	}
948 
949 	switch(state) {
950 		case NR_INIT:
951 		{
952 			// time to update hq?
953 			built_update_headquarter();
954 
955 			// assume fail
956 			state = CHECK_CONVOI;
957 
958 			/* if we have this little money, we do nothing
959 			 * The second condition may happen due to extensive replacement operations;
960 			 * in such a case it is save enough to expand anyway.
961 			 */
962 			if(!(finance->get_account_balance()>0  ||  finance->has_money_or_assets())  ) {
963 				return;
964 			}
965 
966 			const weighted_vector_tpl<stadt_t*>& staedte = welt->get_cities();
967 			int count = staedte.get_count();
968 			int offset = (count>1) ? simrand(count-1) : 0;
969 			// start with previous target
970 			const stadt_t* last_start_stadt=start_stadt;
971 			start_stadt = end_stadt;
972 			end_stadt = NULL;
973 			end_attraction = NULL;
974 			ziel = NULL;
975 			platz2 = koord::invalid;
976 			// if no previous town => find one
977 			if(start_stadt==NULL) {
978 				// larger start town preferred
979 				start_stadt = pick_any_weighted(staedte);
980 				offset = staedte.index_of(start_stadt);
981 			}
982 DBG_MESSAGE("ai_passenger_t::do_passenger_ki()","using city %s for start",start_stadt->get_name());
983 			const halthandle_t start_halt = get_our_hub(start_stadt);
984 			// find starting place
985 
986 if(!start_halt.is_bound()) {
987 	DBG_MESSAGE("ai_passenger_t::do_passenger_ki()","new_hub");
988 }
989 			platz1 = start_halt.is_bound() ? start_halt->get_basis_pos() : find_place_for_hub( start_stadt );
990 			if(platz1==koord::invalid) {
991 				return;
992 			}
993 DBG_MESSAGE("ai_passenger_t::do_passenger_ki()","using place (%i,%i) for start",platz1.x,platz1.y);
994 
995 			if(count==1  ||  simrand(3)==0) {
996 DBG_MESSAGE("ai_passenger_t::do_passenger_ki()","searching attraction");
997 				// 25 % of all connections are tourist attractions
998 				const weighted_vector_tpl<gebaeude_t*> &attractions = welt->get_attractions();
999 				// this way, we are sure, our factory is connected to this town ...
1000 				const vector_tpl<stadt_t::factory_entry_t> &fabriken = start_stadt->get_target_factories_for_pax().get_entries();
1001 				unsigned	last_dist = 0xFFFFFFFF;
1002 				bool ausflug=simrand(2)!=0;	// holidays first ...
1003 				int ziel_count=ausflug?attractions.get_count():fabriken.get_count();
1004 				for( int i=0;  i<ziel_count;  i++  ) {
1005 					unsigned	dist;
1006 					koord pos, size;
1007 					if(ausflug) {
1008 						const gebaeude_t* a = attractions[i];
1009 						if (a->get_mail_level() <= 25) {
1010 							// not a good object to go to ...
1011 							continue;
1012 						}
1013 						pos  = a->get_pos().get_2d();
1014 						size = a->get_tile()->get_desc()->get_size(a->get_tile()->get_layout());
1015 					}
1016 					else {
1017 						const fabrik_t* f = fabriken[i].factory;
1018 						const factory_desc_t *const desc = f->get_desc();
1019 						if (( desc->get_pax_demand()==65535 ? desc->get_pax_level() : desc->get_pax_demand() ) <= 10) {
1020 							// not a good object to go to ... we want more action ...
1021 							continue;
1022 						}
1023 						pos  = f->get_pos().get_2d();
1024 						size = f->get_desc()->get_building()->get_size(f->get_rotate());
1025 					}
1026 					const stadt_t *next_town = welt->find_nearest_city(pos);
1027 					if(next_town==NULL  ||  start_stadt==next_town) {
1028 						// this is either a town already served (so we do not create a new hub)
1029 						// or a lonely point somewhere
1030 						// in any case we do not want to serve this location already
1031 						uint16 const c   = welt->get_settings().get_station_coverage();
1032 						koord  const cov = koord(c, c);
1033 						koord test_platz=find_area_for_hub(pos-cov,pos+size+cov,pos);
1034 						if(  !get_halt(test_platz).is_bound()  ) {
1035 							// not served
1036 							dist = koord_distance(platz1,test_platz);
1037 							if(dist+simrand(50)<last_dist  &&   dist>3) {
1038 								// but closer than the others
1039 								if(ausflug) {
1040 									end_attraction = attractions[i];
1041 								}
1042 								else {
1043 									ziel = fabriken[i].factory;
1044 								}
1045 								last_dist = dist;
1046 								platz2 = test_platz;
1047 							}
1048 						}
1049 					}
1050 				}
1051 				// test for success
1052 				if(platz2!=koord::invalid) {
1053 					// found something
1054 					state = NR_SAMMLE_ROUTEN;
1055 DBG_MESSAGE("ai_passenger_t::do_passenger_ki()","decision: %s wants to built network between %s and %s",get_name(),start_stadt->get_name(),ausflug?end_attraction->get_tile()->get_desc()->get_name():ziel->get_name());
1056 				}
1057 			}
1058 			else {
1059 DBG_MESSAGE("ai_passenger_t::do_passenger_ki()","searching town");
1060 				int last_dist = 9999999;
1061 				// find a good route
1062 				for( int i=0;  i<count;  i++  ) {
1063 					const int nr = (i+offset)%count;
1064 					const stadt_t* cur = staedte[nr];
1065 					if(cur!=last_start_stadt  &&  cur!=start_stadt) {
1066 						halthandle_t end_halt = get_our_hub(cur);
1067 						int dist = koord_distance(platz1,cur->get_pos());
1068 						if(  end_halt.is_bound()  &&  is_connected(platz1,end_halt->get_basis_pos(),goods_manager_t::passengers) ) {
1069 							// already connected
1070 							continue;
1071 						}
1072 						// check if more close
1073 						if(  dist<last_dist  ) {
1074 							end_stadt = cur;
1075 							last_dist = dist;
1076 						}
1077 					}
1078 				}
1079 				// ok, found two cities
1080 				if(start_stadt!=NULL  &&  end_stadt!=NULL) {
1081 					state = NR_SAMMLE_ROUTEN;
1082 DBG_MESSAGE("ai_passenger_t::do_passenger_ki()","%s wants to built network between %s and %s",get_name(),start_stadt->get_name(),end_stadt->get_name());
1083 				}
1084 			}
1085 		}
1086 		break;
1087 
1088 		// so far only busses
1089 		case NR_SAMMLE_ROUTEN:
1090 		{
1091 			//
1092 			koord end_hub_pos = koord::invalid;
1093 DBG_MESSAGE("ai_passenger_t::do_passenger_ki()","Find hub");
1094 			// also for target (if not tourist attraction!)
1095 			if(end_stadt!=NULL) {
1096 DBG_MESSAGE("ai_passenger_t::do_passenger_ki()","try to built connect to city %p", end_stadt );
1097 				// target is town
1098 				halthandle_t h = get_our_hub(end_stadt);
1099 				if(h.is_bound()) {
1100 					end_hub_pos = h->get_basis_pos();
1101 				}
1102 				else {
1103 					end_hub_pos = find_place_for_hub( end_stadt );
1104 				}
1105 			}
1106 			else {
1107 				// already found place
1108 				end_hub_pos = platz2;
1109 			}
1110 			// was successful?
1111 			if(end_hub_pos!=koord::invalid) {
1112 				// ok, now we check the vehicle
1113 				platz2 = end_hub_pos;
1114 DBG_MESSAGE("ai_passenger_t::do_passenger_ki()","hub found -> NR_BAUE_ROUTE1");
1115 				state = NR_BAUE_ROUTE1;
1116 			}
1117 			else {
1118 				// no success
1119 DBG_MESSAGE("ai_passenger_t::do_passenger_ki()","no suitable hub found");
1120 				end_stadt = NULL;
1121 				state = CHECK_CONVOI;
1122 			}
1123 		}
1124 		break;
1125 
1126 		// get a suitable vehicle
1127 		case NR_BAUE_ROUTE1:
1128 		// wait for construction semaphore
1129 		{
1130 			// we want the fastest we can get!
1131 			road_vehicle = vehikel_search( road_wt, 50, 80, goods_manager_t::passengers, false);
1132 			if(road_vehicle!=NULL) {
1133 				// find the best => AI will never survive
1134 //				road_weg = way_builder_t::weg_search( road_wt, road_vehicle->get_topspeed(), welt->get_timeline_year_month(),type_flat );
1135 				// find the really cheapest road
1136 				road_weg = way_builder_t::weg_search( road_wt, 10, welt->get_timeline_year_month(), type_flat );
1137 				state = NR_BAUE_STRASSEN_ROUTE;
1138 DBG_MESSAGE("ai_passenger_t::do_passenger_ki()","using %s on %s",road_vehicle->get_name(),road_weg->get_name());
1139 			}
1140 			else {
1141 				// no success
1142 				end_stadt = NULL;
1143 				state = CHECK_CONVOI;
1144 			}
1145 		}
1146 		break;
1147 
1148 		// built a simple road (no bridges, no tunnels)
1149 		case NR_BAUE_STRASSEN_ROUTE:
1150 		{
1151 			state = NR_BAUE_WATER_ROUTE;	// assume failure
1152 			if(  !ai_t::road_transport  ) {
1153 				// no overland bus lines
1154 				break;
1155 			}
1156 			const building_desc_t* bs = hausbauer_t::get_random_station(building_desc_t::generic_stop, road_wt, welt->get_timeline_year_month(), haltestelle_t::PAX);
1157 			if(bs  &&  create_simple_road_transport(platz1, koord(1,1),platz2,koord(1,1),road_weg)  ) {
1158 				// since the road may have led to a crossing at the intended stop position ...
1159 				bool ok = true;
1160 				if(  !get_halt(platz1).is_bound()  ) {
1161 					if(  !call_general_tool( TOOL_BUILD_STATION, platz1, bs->get_name() )  ) {
1162 						platz1 = find_area_for_hub( platz1-koord(2,2), platz1+koord(2,2), platz1 );
1163 						ok = call_general_tool( TOOL_BUILD_STATION, platz1, bs->get_name() );
1164 					}
1165 				}
1166 				if(  ok  ) {
1167 					if(  !get_halt(platz2).is_bound()  ) {
1168 						if(  !call_general_tool( TOOL_BUILD_STATION, platz2, bs->get_name() )  ) {
1169 							platz2 = find_area_for_hub( platz2-koord(2,2), platz2+koord(2,2), platz2 );
1170 							ok = call_general_tool( TOOL_BUILD_STATION, platz2, bs->get_name() );
1171 						}
1172 					}
1173 				}
1174 				// still continue?
1175 				if(ok) {
1176 					koord list[2]={ platz1, platz2 };
1177 					// wait only, if target is not a hub but an attraction/factory
1178 					create_bus_transport_vehikel(platz1,1,list,2,end_stadt==NULL);
1179 					state = NR_SUCCESS;
1180 					// tell the player
1181 					cbuffer_t buf;
1182 					if(end_attraction!=NULL) {
1183 						platz1 = end_attraction->get_pos().get_2d();
1184 						buf.printf(translator::translate("%s now\noffers bus services\nbetween %s\nand attraction\n%s\nat (%i,%i).\n"), get_name(), start_stadt->get_name(), make_single_line_string(translator::translate(end_attraction->get_tile()->get_desc()->get_name()),2), platz1.x, platz1.y );
1185 						end_stadt = start_stadt;
1186 					}
1187 					else if(ziel!=NULL) {
1188 						platz1 = ziel->get_pos().get_2d();
1189 						buf.printf( translator::translate("%s now\noffers bus services\nbetween %s\nand factory\n%s\nat (%i,%i).\n"), get_name(), start_stadt->get_name(), make_single_line_string(translator::translate(ziel->get_name()),2), platz1.x, platz1.y );
1190 						end_stadt = start_stadt;
1191 					}
1192 					else {
1193 						buf.printf( translator::translate("Travellers now\nuse %s's\nbusses between\n%s \nand %s.\n"), get_name(), start_stadt->get_name(), end_stadt->get_name() );
1194 						// add two intown routes
1195 						cover_city_with_bus_route(platz1, 6);
1196 						cover_city_with_bus_route(platz2, 6);
1197 					}
1198 					welt->get_message()->add_message(buf, platz1, message_t::ai, PLAYER_FLAG|player_nr, road_vehicle->get_base_image());
1199 				}
1200 			}
1201 		}
1202 		break;
1203 
1204 		case NR_BAUE_WATER_ROUTE:
1205 			if(  !ai_t::ship_transport  ) {
1206 				// no overland bus lines
1207 				state = NR_BAUE_AIRPORT_ROUTE;
1208 				break;
1209 			}
1210 			if(  end_attraction == NULL  &&  ship_transport  &&
1211 					create_water_transport_vehikel(start_stadt, end_stadt ? end_stadt->get_pos() : ziel->get_pos().get_2d())) {
1212 				// add two intown routes
1213 				cover_city_with_bus_route( get_our_hub(start_stadt)->get_basis_pos(), 6);
1214 				if(end_stadt!=NULL) {
1215 					cover_city_with_bus_route( get_our_hub(end_stadt)->get_basis_pos(), 6);
1216 				}
1217 				else {
1218 					// start again with same town
1219 					end_stadt = start_stadt;
1220 				}
1221 				cbuffer_t buf;
1222 				buf.printf( translator::translate("Ferry service by\n%s\nnow between\n%s \nand %s.\n"), get_name(), start_stadt->get_name(), end_stadt->get_name() );
1223 				welt->get_message()->add_message(buf, end_stadt->get_pos(), message_t::ai, PLAYER_FLAG | player_nr, road_vehicle->get_base_image());
1224 				state = NR_SUCCESS;
1225 			}
1226 			else {
1227 				if(  end_attraction==NULL  &&  ziel==NULL  ) {
1228 					state = NR_BAUE_AIRPORT_ROUTE;
1229 				}
1230 				else {
1231 					state = NR_BAUE_CLEAN_UP;
1232 				}
1233 			}
1234 		break;
1235 
1236 		// despite its name: try airplane
1237 		case NR_BAUE_AIRPORT_ROUTE:
1238 			// try airline (if we are wealthy enough) ...
1239 			if(  !air_transport  ||  finance->get_history_com_month(1, ATC_CASH) < finance->get_starting_money()  ||
1240 			     !end_stadt  ||  !create_air_transport_vehikel( start_stadt, end_stadt )  ) {
1241 				state = NR_BAUE_CLEAN_UP;
1242 			}
1243 			else {
1244 				// add two intown routes
1245 				cover_city_with_bus_route( get_our_hub(start_stadt)->get_basis_pos(), 6);
1246 				cover_city_with_bus_route( get_our_hub(end_stadt)->get_basis_pos(), 6);
1247 				cbuffer_t buf;
1248 				buf.printf( translator::translate("Airline service by\n%s\nnow between\n%s \nand %s.\n"), get_name(), start_stadt->get_name(), end_stadt->get_name() );
1249 				welt->get_message()->add_message(buf, end_stadt->get_pos(), message_t::ai, PLAYER_FLAG | player_nr, road_vehicle->get_base_image());
1250 				state = NR_SUCCESS;
1251 			}
1252 		break;
1253 
1254 		// remove marker etc.
1255 		case NR_BAUE_CLEAN_UP:
1256 			state = CHECK_CONVOI;
1257 			end_stadt = NULL; // otherwise it may always try to built the same route!
1258 		break;
1259 
1260 		// successful construction
1261 		case NR_SUCCESS:
1262 		{
1263 			state = CHECK_CONVOI;
1264 			next_construction_steps = welt->get_steps() + simrand( construction_speed/16 );
1265 		}
1266 		break;
1267 
1268 
1269 		// add vehicles to crowded lines
1270 		case CHECK_CONVOI:
1271 		{
1272 			// next time: do something different
1273 			state = NR_INIT;
1274 			next_construction_steps = welt->get_steps() + simrand( ai_t::construction_speed ) + 25;
1275 
1276 			vector_tpl<linehandle_t> lines(0);
1277 			simlinemgmt.get_lines( simline_t::line, &lines);
1278 			const uint32 offset = simrand(lines.get_count());
1279 			for (uint32 i = 0;  i<lines.get_count();  i++  ) {
1280 				linehandle_t line = lines[(i+offset)%lines.get_count()];
1281 				if(line->get_linetype()!=simline_t::airline  &&  line->get_linetype()!=simline_t::truckline) {
1282 					continue;
1283 				}
1284 
1285 				// remove empty lines
1286 				if(line->count_convoys()==0) {
1287 					simlinemgmt.delete_line(line);
1288 					break;
1289 				}
1290 
1291 				// avoid empty schedule ?!?
1292 				assert(!line->get_schedule()->empty());
1293 
1294 				// made loss with this line
1295 				if(line->get_finance_history(0,LINE_PROFIT)<0) {
1296 					// try to update the vehicles
1297 					if(welt->use_timeline()  &&  line->count_convoys()>1) {
1298 						// do not update unimportant lines with single vehicles
1299 						slist_tpl <convoihandle_t> obsolete;
1300 						uint32 capacity = 0;
1301 						for(  uint i=0;  i<line->count_convoys();  i++  ) {
1302 							convoihandle_t cnv = line->get_convoy(i);
1303 							if(cnv->has_obsolete_vehicles()) {
1304 								obsolete.append(cnv);
1305 								capacity += cnv->front()->get_desc()->get_capacity();
1306 							}
1307 						}
1308 						if(capacity>0) {
1309 							// now try to find new vehicle
1310 							vehicle_t              const& v       = *line->get_convoy(0)->front();
1311 							waytype_t              const  wt      = v.get_waytype();
1312 							vehicle_desc_t const* const  v_desc = vehicle_builder_t::vehikel_search(wt, welt->get_current_month(), 50, welt->get_average_speed(wt), goods_manager_t::passengers, false, true);
1313 							if (!v_desc->is_retired(welt->get_current_month()) && v_desc != v.get_desc()) {
1314 								// there is a newer one ...
1315 								for(  uint32 new_capacity=0;  capacity>new_capacity;  new_capacity+=v_desc->get_capacity()) {
1316 									if(  convoihandle_t::is_exhausted()  ) {
1317 										// too many convois => cannot do anything about this ...
1318 										break;
1319 									}
1320 									vehicle_t* v = vehicle_builder_t::build( line->get_schedule()->entries[0].pos, this, NULL, v_desc  );
1321 									convoi_t* new_cnv = new convoi_t(this);
1322 									new_cnv->set_name( v->get_desc()->get_name() );
1323 									new_cnv->add_vehikel( v );
1324 									new_cnv->set_line(line);
1325 									new_cnv->start();
1326 								}
1327 								// delete all old convois
1328 								while(!obsolete.empty()) {
1329 									obsolete.remove_first()->self_destruct();
1330 								}
1331 								return;
1332 							}
1333 						}
1334 					}
1335 				}
1336 				// next: check for stuck convois ...
1337 
1338 				sint64	free_cap = line->get_finance_history(0,LINE_CAPACITY);
1339 				sint64	used_cap = line->get_finance_history(0,LINE_TRANSPORTED_GOODS);
1340 
1341 				if(free_cap+used_cap==0) {
1342 					continue;
1343 				}
1344 
1345 				sint32 ratio = (sint32)((free_cap*100l)/(free_cap+used_cap));
1346 
1347 				// next: check for overflowing lines, i.e. running with 3/4 of the capacity
1348 				if(  ratio<10  &&  !convoihandle_t::is_exhausted()  ) {
1349 					// else add the first convoi again
1350 					vehicle_t* const v = vehicle_builder_t::build(line->get_schedule()->entries[0].pos, this, NULL, line->get_convoy(0)->front()->get_desc());
1351 					convoi_t* new_cnv = new convoi_t(this);
1352 					new_cnv->set_name( v->get_desc()->get_name() );
1353 					new_cnv->add_vehikel( v );
1354 					new_cnv->set_line( line );
1355 					// on waiting line, wait at alternating stations for load balancing
1356 					if(  line->get_schedule()->entries[1].minimum_loading==90  &&  line->get_linetype()!=simline_t::truckline  &&  (line->count_convoys()&1)==0  ) {
1357 						new_cnv->get_schedule()->entries[0].minimum_loading = 90;
1358 						new_cnv->get_schedule()->entries[1].minimum_loading = 0;
1359 					}
1360 					new_cnv->start();
1361 					return;
1362 				}
1363 
1364 				// next: check for too many cars, i.e. running with too many cars
1365 				if(  ratio>40  &&  line->count_convoys()>1) {
1366 					// remove one convoi
1367 					line->get_convoy(0)->self_destruct();
1368 					return;
1369 				}
1370 			}
1371 		}
1372 		break;
1373 
1374 		default:
1375 			DBG_MESSAGE("ai_passenger_t::do_passenger_ki()",	"Illegal state %d!", state );
1376 			end_stadt = NULL;
1377 			state = NR_INIT;
1378 	}
1379 }
1380 
1381 
1382 
1383 void ai_passenger_t::rdwr(loadsave_t *file)
1384 {
1385 	if(  file->is_version_less(102, 2)  ) {
1386 		// due to an error the player was never saved correctly
1387 		player_t::rdwr(file);
1388 		return;
1389 	}
1390 
1391 	xml_tag_t t( file, "ai_passenger_t" );
1392 
1393 	ai_t::rdwr(file);
1394 
1395 	// then check, if we have to do something or the game is too old ...
1396 	if(file->is_version_less(101, 0)) {
1397 		// ignore saving, reinit on loading
1398 		if(  file->is_loading()  ) {
1399 			next_construction_steps = welt->get_steps()+simrand(ai_t::construction_speed);
1400 		}
1401 		return;
1402 	}
1403 
1404 	// now save current state ...
1405 	file->rdwr_enum(state);
1406 	if(  file->is_version_less(111, 1)  ) {
1407 		file->rdwr_long(ai_t::construction_speed);
1408 		file->rdwr_bool(air_transport);
1409 		file->rdwr_bool(ship_transport);
1410 		road_transport = true;
1411 		rail_transport = false;
1412 	}
1413 	platz1.rdwr( file );
1414 	platz2.rdwr( file );
1415 
1416 	if(file->is_saving()) {
1417 		// save current pointers
1418 		sint32 delta_steps = next_construction_steps-welt->get_steps();
1419 		file->rdwr_long(delta_steps);
1420 		koord k = start_stadt ? start_stadt->get_pos() : koord::invalid;
1421 		k.rdwr(file);
1422 		k = end_stadt ? end_stadt->get_pos() : koord::invalid;
1423 		k.rdwr(file);
1424 		koord3d k3d = end_attraction ? end_attraction->get_pos() : koord3d::invalid;
1425 		k3d.rdwr(file);
1426 		k3d = ziel ? ziel->get_pos() : koord3d::invalid;
1427 		k3d.rdwr(file);
1428 	}
1429 	else {
1430 		// since steps in loaded game == 0
1431 		file->rdwr_long(next_construction_steps);
1432 		next_construction_steps += welt->get_steps();
1433 		// reinit current pointers
1434 		koord k;
1435 		k.rdwr(file);
1436 		start_stadt = welt->find_nearest_city(k);
1437 		k.rdwr(file);
1438 		end_stadt = welt->find_nearest_city(k);
1439 		koord3d k3d;
1440 		k3d.rdwr(file);
1441 		end_attraction = welt->lookup(k3d) ? welt->lookup(k3d)->find<gebaeude_t>() : NULL;
1442 		k3d.rdwr(file);
1443 		ziel = fabrik_t::get_fab(k3d.get_2d() );
1444 	}
1445 }
1446 
1447 
1448 
1449 /**
1450  * Dealing with stuck  or lost vehicles:
1451  * - delete lost ones
1452  * - ignore stuck ones
1453  * @author prissi
1454  * @date 30-Dec-2008
1455  */
1456 void ai_passenger_t::report_vehicle_problem(convoihandle_t cnv,const koord3d ziel)
1457 {
1458 	if(  cnv->get_state() == convoi_t::NO_ROUTE  &&  this!=welt->get_active_player()  ) {
1459 			DBG_MESSAGE("ai_passenger_t::report_vehicle_problem","Vehicle %s can't find a route to (%i,%i)!", cnv->get_name(),ziel.x,ziel.y);
1460 			cnv->self_destruct();
1461 			return;
1462 	}
1463 	player_t::report_vehicle_problem( cnv, ziel );
1464 }
1465 
1466 
1467 void ai_passenger_t::finish_rd()
1468 {
1469 	road_vehicle = vehikel_search( road_wt, 50, 80, goods_manager_t::passengers, false);
1470 	if (road_vehicle == NULL) {
1471 		// reset state
1472 		end_stadt = NULL;
1473 		state = CHECK_CONVOI;
1474 	}
1475 }
1476