Changeset - r8229:4262f8715f60
[Not reviewed]
master
0 11 0
rubidium - 16 years ago 2008-01-09 16:40:02
rubidium@openttd.org
(svn r11792) -Codechange: move some (virtually) globally included AI related structs to a place where they are only included a few times.
11 files changed with 1253 insertions and 1241 deletions:
0 comments (0 inline, 0 general)
src/ai/ai.cpp
Show inline comments
 
/* $Id$ */
 

	
 
#include "../stdafx.h"
 
#include "../openttd.h"
 
#include "../player.h"
 
#include "../variables.h"
 
#include "../command_func.h"
 
#include "../network/network.h"
 
#include "../core/alloc_func.hpp"
 
#include "ai.h"
 
#include "default/default.h"
src/ai/default/default.cpp
Show inline comments
 
@@ -24,17 +24,18 @@
 
#include "../../bridge.h"
 
#include "../../date_func.h"
 
#include "../../tunnelbridge_map.h"
 
#include "../../window_func.h"
 
#include "../../vehicle_func.h"
 
#include "../../functions.h"
 
#include "../../saveload.h"
 
#include "default.h"
 

	
 

	
 
// remove some day perhaps?
 
static uint _ai_service_interval;
 
PlayerAI _players_ai[MAX_PLAYERS];
 

	
 
typedef void AiStateAction(Player *p);
 

	
 
enum {
 
	AIS_0                            =  0,
 
	AIS_1                            =  1,
 
@@ -71,68 +72,68 @@ static TrackBits GetRailTrackStatus(Tile
 
	return (TrackBits)(byte) (r | r >> 8);
 
}
 

	
 

	
 
static void AiCase0(Player *p)
 
{
 
	p->ai.state = AIS_REMOVE_TRACK;
 
	p->ai.state_counter = 0;
 
	_players_ai[p->index].state = AIS_REMOVE_TRACK;
 
	_players_ai[p->index].state_counter = 0;
 
}
 

	
 
static void AiCase1(Player *p)
 
{
 
	p->ai.cur_veh = NULL;
 
	p->ai.state = AIS_VEH_LOOP;
 
	_players_ai[p->index].cur_veh = NULL;
 
	_players_ai[p->index].state = AIS_VEH_LOOP;
 
}
 

	
 
static void AiStateVehLoop(Player *p)
 
{
 
	Vehicle *v;
 
	uint index;
 

	
 
	index = (p->ai.cur_veh == NULL) ? 0 : p->ai.cur_veh->index + 1;
 
	index = (_players_ai[p->index].cur_veh == NULL) ? 0 : _players_ai[p->index].cur_veh->index + 1;
 

	
 
	FOR_ALL_VEHICLES_FROM(v, index) {
 
		if (v->owner != _current_player) continue;
 

	
 
		if ((v->type == VEH_TRAIN && v->subtype == 0) ||
 
				v->type == VEH_ROAD ||
 
				(v->type == VEH_AIRCRAFT && IsNormalAircraft(v)) ||
 
				v->type == VEH_SHIP) {
 
			/* replace engine? */
 
			if (v->type == VEH_TRAIN && v->engine_type < 3 &&
 
					(_price.build_railvehicle >> 3) < p->player_money) {
 
				p->ai.state = AIS_VEH_CHECK_REPLACE_VEHICLE;
 
				p->ai.cur_veh = v;
 
				_players_ai[p->index].state = AIS_VEH_CHECK_REPLACE_VEHICLE;
 
				_players_ai[p->index].cur_veh = v;
 
				return;
 
			}
 

	
 
			/* not profitable? */
 
			if (v->age >= 730 &&
 
					v->profit_last_year < _price.station_value * 5 &&
 
					v->profit_this_year < _price.station_value * 5) {
 
				p->ai.state_counter = 0;
 
				p->ai.state = AIS_SELL_VEHICLE;
 
				p->ai.cur_veh = v;
 
				_players_ai[p->index].state_counter = 0;
 
				_players_ai[p->index].state = AIS_SELL_VEHICLE;
 
				_players_ai[p->index].cur_veh = v;
 
				return;
 
			}
 

	
 
			/* not reliable? */
 
			if (v->age >= v->max_age || (
 
						v->age != 0 &&
 
						GetEngine(v->engine_type)->reliability < 35389
 
					)) {
 
				p->ai.state = AIS_VEH_CHECK_REPLACE_VEHICLE;
 
				p->ai.cur_veh = v;
 
				_players_ai[p->index].state = AIS_VEH_CHECK_REPLACE_VEHICLE;
 
				_players_ai[p->index].cur_veh = v;
 
				return;
 
			}
 
		}
 
	}
 

	
 
	p->ai.state = AIS_WANT_NEW_ROUTE;
 
	p->ai.state_counter = 0;
 
	_players_ai[p->index].state = AIS_WANT_NEW_ROUTE;
 
	_players_ai[p->index].state_counter = 0;
 
}
 

	
 
static EngineID AiChooseTrainToBuild(RailType railtype, Money money, byte flag, TileIndex tile)
 
{
 
	EngineID best_veh_index = INVALID_ENGINE;
 
	byte best_veh_score = 0;
 
@@ -227,13 +228,13 @@ static EngineID AiChooseAircraftToBuild(
 

	
 
static Money AiGetBasePrice(const Player* p)
 
{
 
	Money base = _price.station_value;
 

	
 
	// adjust base price when more expensive vehicles are available
 
	switch (p->ai.railtype_to_use) {
 
	switch (_players_ai[p->index].railtype_to_use) {
 
		default: NOT_REACHED();
 
		case RAILTYPE_RAIL:     break;
 
		case RAILTYPE_ELECTRIC: break;
 
		case RAILTYPE_MONO:     base = (base * 3) >> 1; break;
 
		case RAILTYPE_MAGLEV:   base *= 2; break;
 
	}
 
@@ -274,24 +275,24 @@ static EngineID AiChooseShipToReplaceWit
 
	/* Ships are not implemented in this (broken) AI */
 
	return INVALID_ENGINE;
 
}
 

	
 
static void AiHandleGotoDepot(Player *p, int cmd)
 
{
 
	if (p->ai.cur_veh->current_order.type != OT_GOTO_DEPOT)
 
		DoCommand(0, p->ai.cur_veh->index, 0, DC_EXEC, cmd);
 

	
 
	if (++p->ai.state_counter <= 1387) {
 
		p->ai.state = AIS_VEH_DO_REPLACE_VEHICLE;
 
	if (_players_ai[p->index].cur_veh->current_order.type != OT_GOTO_DEPOT)
 
		DoCommand(0, _players_ai[p->index].cur_veh->index, 0, DC_EXEC, cmd);
 

	
 
	if (++_players_ai[p->index].state_counter <= 1387) {
 
		_players_ai[p->index].state = AIS_VEH_DO_REPLACE_VEHICLE;
 
		return;
 
	}
 

	
 
	if (p->ai.cur_veh->current_order.type == OT_GOTO_DEPOT) {
 
		p->ai.cur_veh->current_order.type = OT_DUMMY;
 
		p->ai.cur_veh->current_order.flags = 0;
 
		InvalidateWindow(WC_VEHICLE_VIEW, p->ai.cur_veh->index);
 
	if (_players_ai[p->index].cur_veh->current_order.type == OT_GOTO_DEPOT) {
 
		_players_ai[p->index].cur_veh->current_order.type = OT_DUMMY;
 
		_players_ai[p->index].cur_veh->current_order.flags = 0;
 
		InvalidateWindow(WC_VEHICLE_VIEW, _players_ai[p->index].cur_veh->index);
 
	}
 
}
 

	
 
static void AiRestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak)
 
{
 
	uint i;
 
@@ -301,13 +302,13 @@ static void AiRestoreVehicleOrders(Vehic
 
			break;
 
	}
 
}
 

	
 
static void AiHandleReplaceTrain(Player *p)
 
{
 
	const Vehicle* v = p->ai.cur_veh;
 
	const Vehicle* v = _players_ai[p->index].cur_veh;
 
	BackuppedOrders orderbak;
 
	EngineID veh;
 

	
 
	// wait until the vehicle reaches the depot.
 
	if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
 
		AiHandleGotoDepot(p, CMD_SEND_TRAIN_TO_DEPOT);
 
@@ -331,13 +332,13 @@ static void AiHandleReplaceTrain(Player 
 
		}
 
	}
 
}
 

	
 
static void AiHandleReplaceRoadVeh(Player *p)
 
{
 
	const Vehicle* v = p->ai.cur_veh;
 
	const Vehicle* v = _players_ai[p->index].cur_veh;
 
	BackuppedOrders orderbak[1];
 
	EngineID veh;
 

	
 
	if (!v->IsStoppedInDepot()) {
 
		AiHandleGotoDepot(p, CMD_SEND_ROADVEH_TO_DEPOT);
 
		return;
 
@@ -360,13 +361,13 @@ static void AiHandleReplaceRoadVeh(Playe
 
		}
 
	}
 
}
 

	
 
static void AiHandleReplaceAircraft(Player *p)
 
{
 
	const Vehicle* v = p->ai.cur_veh;
 
	const Vehicle* v = _players_ai[p->index].cur_veh;
 
	BackuppedOrders orderbak[1];
 
	EngineID veh;
 

	
 
	if (!v->IsStoppedInDepot()) {
 
		AiHandleGotoDepot(p, CMD_SEND_AIRCRAFT_TO_HANGAR);
 
		return;
 
@@ -411,30 +412,30 @@ static DoReplaceProc* const _veh_do_repl
 
	AiHandleReplaceShip,
 
	AiHandleReplaceAircraft
 
};
 

	
 
static void AiStateCheckReplaceVehicle(Player *p)
 
{
 
	const Vehicle* v = p->ai.cur_veh;
 
	const Vehicle* v = _players_ai[p->index].cur_veh;
 

	
 
	if (!v->IsValid() ||
 
			v->owner != _current_player ||
 
			v->type > VEH_SHIP ||
 
			_veh_check_replace_proc[v->type - VEH_TRAIN](p, v) == INVALID_ENGINE) {
 
		p->ai.state = AIS_VEH_LOOP;
 
		_players_ai[p->index].state = AIS_VEH_LOOP;
 
	} else {
 
		p->ai.state_counter = 0;
 
		p->ai.state = AIS_VEH_DO_REPLACE_VEHICLE;
 
		_players_ai[p->index].state_counter = 0;
 
		_players_ai[p->index].state = AIS_VEH_DO_REPLACE_VEHICLE;
 
	}
 
}
 

	
 
static void AiStateDoReplaceVehicle(Player *p)
 
{
 
	const Vehicle* v = p->ai.cur_veh;
 

	
 
	p->ai.state = AIS_VEH_LOOP;
 
	const Vehicle* v = _players_ai[p->index].cur_veh;
 

	
 
	_players_ai[p->index].state = AIS_VEH_LOOP;
 
	// vehicle is not owned by the player anymore, something went very wrong.
 
	if (!v->IsValid() || v->owner != _current_player) return;
 
	_veh_do_replace_proc[v->type - VEH_TRAIN](p);
 
}
 

	
 
struct FoundRoute {
 
@@ -638,14 +639,14 @@ static bool AiCheckIfRouteIsGood(Player 
 
	 * With 50% chance the value will be under 52 tiles */
 
	int min_distance = 36 + (1 << (Random() % 9)); // 0..8
 

	
 
	/* Make sure distance to closest station is < min_distance tiles. */
 
	if (dist != 0xFFFF && dist > min_distance) return false;
 

	
 
	if (p->ai.route_type_mask != 0 &&
 
			!(p->ai.route_type_mask & bitmask) &&
 
	if (_players_ai[p->index].route_type_mask != 0 &&
 
			!(_players_ai[p->index].route_type_mask & bitmask) &&
 
			!Chance16(1, 5)) {
 
		return false;
 
	}
 

	
 
	if (fr->cargo == CT_PASSENGERS || fr->cargo == CT_MAIL) {
 
		const Town* from = (const Town*)fr->from;
 
@@ -667,13 +668,13 @@ static bool AiCheckIfRouteIsGood(Player 
 
		if (i->last_month_pct_transported[fr->cargo != i->produced_cargo[0]] > 0x99 ||
 
				i->last_month_production[fr->cargo != i->produced_cargo[0]] == 0) {
 
			return false;
 
		}
 
	}
 

	
 
	p->ai.route_type_mask |= bitmask;
 
	_players_ai[p->index].route_type_mask |= bitmask;
 
	return true;
 
}
 

	
 
static byte AiGetDirectionBetweenTiles(TileIndex a, TileIndex b)
 
{
 
	byte i = (TileX(a) < TileX(b)) ? 1 : 0;
 
@@ -708,91 +709,91 @@ static void AiWantLongIndustryRoute(Play
 
		if (--i == 0) return;
 
	}
 

	
 
	if (!AiCheckIfRouteIsGood(p, &fr, 1)) return;
 

	
 
	// Fill the source field
 
	p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 

	
 
	p->ai.src.use_tile = 0;
 
	p->ai.src.rand_rng = 9;
 
	p->ai.src.cur_building_rule = 0xFF;
 
	p->ai.src.unk6 = 1;
 
	p->ai.src.unk7 = 0;
 
	p->ai.src.buildcmd_a = 0x24;
 
	p->ai.src.buildcmd_b = 0xFF;
 
	p->ai.src.direction = AiGetDirectionBetweenTiles(
 
		p->ai.src.spec_tile,
 
		p->ai.dst.spec_tile
 
	_players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	_players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 

	
 
	_players_ai[p->index].src.use_tile = 0;
 
	_players_ai[p->index].src.rand_rng = 9;
 
	_players_ai[p->index].src.cur_building_rule = 0xFF;
 
	_players_ai[p->index].src.unk6 = 1;
 
	_players_ai[p->index].src.unk7 = 0;
 
	_players_ai[p->index].src.buildcmd_a = 0x24;
 
	_players_ai[p->index].src.buildcmd_b = 0xFF;
 
	_players_ai[p->index].src.direction = AiGetDirectionBetweenTiles(
 
		_players_ai[p->index].src.spec_tile,
 
		_players_ai[p->index].dst.spec_tile
 
	);
 
	p->ai.src.cargo = fr.cargo | 0x80;
 
	_players_ai[p->index].src.cargo = fr.cargo | 0x80;
 

	
 
	// Fill the dest field
 

	
 
	p->ai.dst.use_tile = 0;
 
	p->ai.dst.rand_rng = 9;
 
	p->ai.dst.cur_building_rule = 0xFF;
 
	p->ai.dst.unk6 = 1;
 
	p->ai.dst.unk7 = 0;
 
	p->ai.dst.buildcmd_a = 0x34;
 
	p->ai.dst.buildcmd_b = 0xFF;
 
	p->ai.dst.direction = AiGetDirectionBetweenTiles(
 
		p->ai.dst.spec_tile,
 
		p->ai.src.spec_tile
 
	_players_ai[p->index].dst.use_tile = 0;
 
	_players_ai[p->index].dst.rand_rng = 9;
 
	_players_ai[p->index].dst.cur_building_rule = 0xFF;
 
	_players_ai[p->index].dst.unk6 = 1;
 
	_players_ai[p->index].dst.unk7 = 0;
 
	_players_ai[p->index].dst.buildcmd_a = 0x34;
 
	_players_ai[p->index].dst.buildcmd_b = 0xFF;
 
	_players_ai[p->index].dst.direction = AiGetDirectionBetweenTiles(
 
		_players_ai[p->index].dst.spec_tile,
 
		_players_ai[p->index].src.spec_tile
 
	);
 
	p->ai.dst.cargo = fr.cargo;
 
	_players_ai[p->index].dst.cargo = fr.cargo;
 

	
 
	// Fill middle field 1
 
	p->ai.mid1.spec_tile = AiGetPctTileBetween(
 
		p->ai.src.spec_tile,
 
		p->ai.dst.spec_tile,
 
	_players_ai[p->index].mid1.spec_tile = AiGetPctTileBetween(
 
		_players_ai[p->index].src.spec_tile,
 
		_players_ai[p->index].dst.spec_tile,
 
		0x55
 
	);
 
	p->ai.mid1.use_tile = 0;
 
	p->ai.mid1.rand_rng = 6;
 
	p->ai.mid1.cur_building_rule = 0xFF;
 
	p->ai.mid1.unk6 = 2;
 
	p->ai.mid1.unk7 = 1;
 
	p->ai.mid1.buildcmd_a = 0x30;
 
	p->ai.mid1.buildcmd_b = 0xFF;
 
	p->ai.mid1.direction = p->ai.src.direction;
 
	p->ai.mid1.cargo = fr.cargo;
 
	_players_ai[p->index].mid1.use_tile = 0;
 
	_players_ai[p->index].mid1.rand_rng = 6;
 
	_players_ai[p->index].mid1.cur_building_rule = 0xFF;
 
	_players_ai[p->index].mid1.unk6 = 2;
 
	_players_ai[p->index].mid1.unk7 = 1;
 
	_players_ai[p->index].mid1.buildcmd_a = 0x30;
 
	_players_ai[p->index].mid1.buildcmd_b = 0xFF;
 
	_players_ai[p->index].mid1.direction = _players_ai[p->index].src.direction;
 
	_players_ai[p->index].mid1.cargo = fr.cargo;
 

	
 
	// Fill middle field 2
 
	p->ai.mid2.spec_tile = AiGetPctTileBetween(
 
		p->ai.src.spec_tile,
 
		p->ai.dst.spec_tile,
 
	_players_ai[p->index].mid2.spec_tile = AiGetPctTileBetween(
 
		_players_ai[p->index].src.spec_tile,
 
		_players_ai[p->index].dst.spec_tile,
 
		0xAA
 
	);
 
	p->ai.mid2.use_tile = 0;
 
	p->ai.mid2.rand_rng = 6;
 
	p->ai.mid2.cur_building_rule = 0xFF;
 
	p->ai.mid2.unk6 = 2;
 
	p->ai.mid2.unk7 = 1;
 
	p->ai.mid2.buildcmd_a = 0xFF;
 
	p->ai.mid2.buildcmd_b = 0xFF;
 
	p->ai.mid2.direction = p->ai.dst.direction;
 
	p->ai.mid2.cargo = fr.cargo;
 
	_players_ai[p->index].mid2.use_tile = 0;
 
	_players_ai[p->index].mid2.rand_rng = 6;
 
	_players_ai[p->index].mid2.cur_building_rule = 0xFF;
 
	_players_ai[p->index].mid2.unk6 = 2;
 
	_players_ai[p->index].mid2.unk7 = 1;
 
	_players_ai[p->index].mid2.buildcmd_a = 0xFF;
 
	_players_ai[p->index].mid2.buildcmd_b = 0xFF;
 
	_players_ai[p->index].mid2.direction = _players_ai[p->index].dst.direction;
 
	_players_ai[p->index].mid2.cargo = fr.cargo;
 

	
 
	// Fill common fields
 
	p->ai.cargo_type = fr.cargo;
 
	p->ai.num_wagons = 3;
 
	p->ai.build_kind = 2;
 
	p->ai.num_build_rec = 4;
 
	p->ai.num_loco_to_build = 2;
 
	p->ai.num_want_fullload = 2;
 
	p->ai.wagon_list[0] = INVALID_VEHICLE;
 
	p->ai.order_list_blocks[0] = 0;
 
	p->ai.order_list_blocks[1] = 1;
 
	p->ai.order_list_blocks[2] = 255;
 

	
 
	p->ai.state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
 
	p->ai.state_mode = UCHAR_MAX;
 
	p->ai.state_counter = 0;
 
	p->ai.timeout_counter = 0;
 
	_players_ai[p->index].cargo_type = fr.cargo;
 
	_players_ai[p->index].num_wagons = 3;
 
	_players_ai[p->index].build_kind = 2;
 
	_players_ai[p->index].num_build_rec = 4;
 
	_players_ai[p->index].num_loco_to_build = 2;
 
	_players_ai[p->index].num_want_fullload = 2;
 
	_players_ai[p->index].wagon_list[0] = INVALID_VEHICLE;
 
	_players_ai[p->index].order_list_blocks[0] = 0;
 
	_players_ai[p->index].order_list_blocks[1] = 1;
 
	_players_ai[p->index].order_list_blocks[2] = 255;
 

	
 
	_players_ai[p->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
 
	_players_ai[p->index].state_mode = UCHAR_MAX;
 
	_players_ai[p->index].state_counter = 0;
 
	_players_ai[p->index].timeout_counter = 0;
 
}
 

	
 
static void AiWantMediumIndustryRoute(Player *p)
 
{
 
	int i;
 
	FoundRoute fr;
 
@@ -811,56 +812,56 @@ static void AiWantMediumIndustryRoute(Pl
 
		if (--i == 0) return;
 
	}
 

	
 
	if (!AiCheckIfRouteIsGood(p, &fr, 1)) return;
 

	
 
	// Fill the source field
 
	p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	p->ai.src.use_tile = 0;
 
	p->ai.src.rand_rng = 9;
 
	p->ai.src.cur_building_rule = 0xFF;
 
	p->ai.src.unk6 = 1;
 
	p->ai.src.unk7 = 0;
 
	p->ai.src.buildcmd_a = 0x10;
 
	p->ai.src.buildcmd_b = 0xFF;
 
	p->ai.src.direction = AiGetDirectionBetweenTiles(
 
	_players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	_players_ai[p->index].src.use_tile = 0;
 
	_players_ai[p->index].src.rand_rng = 9;
 
	_players_ai[p->index].src.cur_building_rule = 0xFF;
 
	_players_ai[p->index].src.unk6 = 1;
 
	_players_ai[p->index].src.unk7 = 0;
 
	_players_ai[p->index].src.buildcmd_a = 0x10;
 
	_players_ai[p->index].src.buildcmd_b = 0xFF;
 
	_players_ai[p->index].src.direction = AiGetDirectionBetweenTiles(
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.from),
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.to)
 
	);
 
	p->ai.src.cargo = fr.cargo | 0x80;
 
	_players_ai[p->index].src.cargo = fr.cargo | 0x80;
 

	
 
	// Fill the dest field
 
	p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	p->ai.dst.use_tile = 0;
 
	p->ai.dst.rand_rng = 9;
 
	p->ai.dst.cur_building_rule = 0xFF;
 
	p->ai.dst.unk6 = 1;
 
	p->ai.dst.unk7 = 0;
 
	p->ai.dst.buildcmd_a = 0xFF;
 
	p->ai.dst.buildcmd_b = 0xFF;
 
	p->ai.dst.direction = AiGetDirectionBetweenTiles(
 
	_players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	_players_ai[p->index].dst.use_tile = 0;
 
	_players_ai[p->index].dst.rand_rng = 9;
 
	_players_ai[p->index].dst.cur_building_rule = 0xFF;
 
	_players_ai[p->index].dst.unk6 = 1;
 
	_players_ai[p->index].dst.unk7 = 0;
 
	_players_ai[p->index].dst.buildcmd_a = 0xFF;
 
	_players_ai[p->index].dst.buildcmd_b = 0xFF;
 
	_players_ai[p->index].dst.direction = AiGetDirectionBetweenTiles(
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.to),
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.from)
 
	);
 
	p->ai.dst.cargo = fr.cargo;
 
	_players_ai[p->index].dst.cargo = fr.cargo;
 

	
 
	// Fill common fields
 
	p->ai.cargo_type = fr.cargo;
 
	p->ai.num_wagons = 3;
 
	p->ai.build_kind = 1;
 
	p->ai.num_build_rec = 2;
 
	p->ai.num_loco_to_build = 1;
 
	p->ai.num_want_fullload = 1;
 
	p->ai.wagon_list[0] = INVALID_VEHICLE;
 
	p->ai.order_list_blocks[0] = 0;
 
	p->ai.order_list_blocks[1] = 1;
 
	p->ai.order_list_blocks[2] = 255;
 
	p->ai.state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
 
	p->ai.state_mode = UCHAR_MAX;
 
	p->ai.state_counter = 0;
 
	p->ai.timeout_counter = 0;
 
	_players_ai[p->index].cargo_type = fr.cargo;
 
	_players_ai[p->index].num_wagons = 3;
 
	_players_ai[p->index].build_kind = 1;
 
	_players_ai[p->index].num_build_rec = 2;
 
	_players_ai[p->index].num_loco_to_build = 1;
 
	_players_ai[p->index].num_want_fullload = 1;
 
	_players_ai[p->index].wagon_list[0] = INVALID_VEHICLE;
 
	_players_ai[p->index].order_list_blocks[0] = 0;
 
	_players_ai[p->index].order_list_blocks[1] = 1;
 
	_players_ai[p->index].order_list_blocks[2] = 255;
 
	_players_ai[p->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
 
	_players_ai[p->index].state_mode = UCHAR_MAX;
 
	_players_ai[p->index].state_counter = 0;
 
	_players_ai[p->index].timeout_counter = 0;
 
}
 

	
 
static void AiWantShortIndustryRoute(Player *p)
 
{
 
	int i;
 
	FoundRoute fr;
 
@@ -879,56 +880,56 @@ static void AiWantShortIndustryRoute(Pla
 
		if (--i == 0) return;
 
	}
 

	
 
	if (!AiCheckIfRouteIsGood(p, &fr, 1)) return;
 

	
 
	// Fill the source field
 
	p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	p->ai.src.use_tile = 0;
 
	p->ai.src.rand_rng = 9;
 
	p->ai.src.cur_building_rule = 0xFF;
 
	p->ai.src.unk6 = 1;
 
	p->ai.src.unk7 = 0;
 
	p->ai.src.buildcmd_a = 0x10;
 
	p->ai.src.buildcmd_b = 0xFF;
 
	p->ai.src.direction = AiGetDirectionBetweenTiles(
 
	_players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	_players_ai[p->index].src.use_tile = 0;
 
	_players_ai[p->index].src.rand_rng = 9;
 
	_players_ai[p->index].src.cur_building_rule = 0xFF;
 
	_players_ai[p->index].src.unk6 = 1;
 
	_players_ai[p->index].src.unk7 = 0;
 
	_players_ai[p->index].src.buildcmd_a = 0x10;
 
	_players_ai[p->index].src.buildcmd_b = 0xFF;
 
	_players_ai[p->index].src.direction = AiGetDirectionBetweenTiles(
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.from),
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.to)
 
	);
 
	p->ai.src.cargo = fr.cargo | 0x80;
 
	_players_ai[p->index].src.cargo = fr.cargo | 0x80;
 

	
 
	// Fill the dest field
 
	p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	p->ai.dst.use_tile = 0;
 
	p->ai.dst.rand_rng = 9;
 
	p->ai.dst.cur_building_rule = 0xFF;
 
	p->ai.dst.unk6 = 1;
 
	p->ai.dst.unk7 = 0;
 
	p->ai.dst.buildcmd_a = 0xFF;
 
	p->ai.dst.buildcmd_b = 0xFF;
 
	p->ai.dst.direction = AiGetDirectionBetweenTiles(
 
	_players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	_players_ai[p->index].dst.use_tile = 0;
 
	_players_ai[p->index].dst.rand_rng = 9;
 
	_players_ai[p->index].dst.cur_building_rule = 0xFF;
 
	_players_ai[p->index].dst.unk6 = 1;
 
	_players_ai[p->index].dst.unk7 = 0;
 
	_players_ai[p->index].dst.buildcmd_a = 0xFF;
 
	_players_ai[p->index].dst.buildcmd_b = 0xFF;
 
	_players_ai[p->index].dst.direction = AiGetDirectionBetweenTiles(
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.to),
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.from)
 
	);
 
	p->ai.dst.cargo = fr.cargo;
 
	_players_ai[p->index].dst.cargo = fr.cargo;
 

	
 
	// Fill common fields
 
	p->ai.cargo_type = fr.cargo;
 
	p->ai.num_wagons = 2;
 
	p->ai.build_kind = 1;
 
	p->ai.num_build_rec = 2;
 
	p->ai.num_loco_to_build = 1;
 
	p->ai.num_want_fullload = 1;
 
	p->ai.wagon_list[0] = INVALID_VEHICLE;
 
	p->ai.order_list_blocks[0] = 0;
 
	p->ai.order_list_blocks[1] = 1;
 
	p->ai.order_list_blocks[2] = 255;
 
	p->ai.state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
 
	p->ai.state_mode = UCHAR_MAX;
 
	p->ai.state_counter = 0;
 
	p->ai.timeout_counter = 0;
 
	_players_ai[p->index].cargo_type = fr.cargo;
 
	_players_ai[p->index].num_wagons = 2;
 
	_players_ai[p->index].build_kind = 1;
 
	_players_ai[p->index].num_build_rec = 2;
 
	_players_ai[p->index].num_loco_to_build = 1;
 
	_players_ai[p->index].num_want_fullload = 1;
 
	_players_ai[p->index].wagon_list[0] = INVALID_VEHICLE;
 
	_players_ai[p->index].order_list_blocks[0] = 0;
 
	_players_ai[p->index].order_list_blocks[1] = 1;
 
	_players_ai[p->index].order_list_blocks[2] = 255;
 
	_players_ai[p->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
 
	_players_ai[p->index].state_mode = UCHAR_MAX;
 
	_players_ai[p->index].state_counter = 0;
 
	_players_ai[p->index].timeout_counter = 0;
 
}
 

	
 
static void AiWantMailRoute(Player *p)
 
{
 
	int i;
 
	FoundRoute fr;
 
@@ -948,88 +949,88 @@ static void AiWantMailRoute(Player *p)
 
	}
 

	
 
	fr.cargo = CT_MAIL;
 
	if (!AiCheckIfRouteIsGood(p, &fr, 1)) return;
 

	
 
	// Fill the source field
 
	p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	p->ai.src.use_tile = 0;
 
	p->ai.src.rand_rng = 7;
 
	p->ai.src.cur_building_rule = 0xFF;
 
	p->ai.src.unk6 = 1;
 
	p->ai.src.unk7 = 0;
 
	p->ai.src.buildcmd_a = 0x24;
 
	p->ai.src.buildcmd_b = 0xFF;
 
	p->ai.src.direction = AiGetDirectionBetweenTiles(
 
	_players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	_players_ai[p->index].src.use_tile = 0;
 
	_players_ai[p->index].src.rand_rng = 7;
 
	_players_ai[p->index].src.cur_building_rule = 0xFF;
 
	_players_ai[p->index].src.unk6 = 1;
 
	_players_ai[p->index].src.unk7 = 0;
 
	_players_ai[p->index].src.buildcmd_a = 0x24;
 
	_players_ai[p->index].src.buildcmd_b = 0xFF;
 
	_players_ai[p->index].src.direction = AiGetDirectionBetweenTiles(
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.from),
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.to)
 
	);
 
	p->ai.src.cargo = fr.cargo;
 
	_players_ai[p->index].src.cargo = fr.cargo;
 

	
 
	// Fill the dest field
 
	p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	p->ai.dst.use_tile = 0;
 
	p->ai.dst.rand_rng = 7;
 
	p->ai.dst.cur_building_rule = 0xFF;
 
	p->ai.dst.unk6 = 1;
 
	p->ai.dst.unk7 = 0;
 
	p->ai.dst.buildcmd_a = 0x34;
 
	p->ai.dst.buildcmd_b = 0xFF;
 
	p->ai.dst.direction = AiGetDirectionBetweenTiles(
 
	_players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	_players_ai[p->index].dst.use_tile = 0;
 
	_players_ai[p->index].dst.rand_rng = 7;
 
	_players_ai[p->index].dst.cur_building_rule = 0xFF;
 
	_players_ai[p->index].dst.unk6 = 1;
 
	_players_ai[p->index].dst.unk7 = 0;
 
	_players_ai[p->index].dst.buildcmd_a = 0x34;
 
	_players_ai[p->index].dst.buildcmd_b = 0xFF;
 
	_players_ai[p->index].dst.direction = AiGetDirectionBetweenTiles(
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.to),
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.from)
 
	);
 
	p->ai.dst.cargo = fr.cargo;
 
	_players_ai[p->index].dst.cargo = fr.cargo;
 

	
 
	// Fill middle field 1
 
	p->ai.mid1.spec_tile = AiGetPctTileBetween(
 
	_players_ai[p->index].mid1.spec_tile = AiGetPctTileBetween(
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.from),
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.to),
 
		0x55
 
	);
 
	p->ai.mid1.use_tile = 0;
 
	p->ai.mid1.rand_rng = 6;
 
	p->ai.mid1.cur_building_rule = 0xFF;
 
	p->ai.mid1.unk6 = 2;
 
	p->ai.mid1.unk7 = 1;
 
	p->ai.mid1.buildcmd_a = 0x30;
 
	p->ai.mid1.buildcmd_b = 0xFF;
 
	p->ai.mid1.direction = p->ai.src.direction;
 
	p->ai.mid1.cargo = fr.cargo;
 
	_players_ai[p->index].mid1.use_tile = 0;
 
	_players_ai[p->index].mid1.rand_rng = 6;
 
	_players_ai[p->index].mid1.cur_building_rule = 0xFF;
 
	_players_ai[p->index].mid1.unk6 = 2;
 
	_players_ai[p->index].mid1.unk7 = 1;
 
	_players_ai[p->index].mid1.buildcmd_a = 0x30;
 
	_players_ai[p->index].mid1.buildcmd_b = 0xFF;
 
	_players_ai[p->index].mid1.direction = _players_ai[p->index].src.direction;
 
	_players_ai[p->index].mid1.cargo = fr.cargo;
 

	
 
	// Fill middle field 2
 
	p->ai.mid2.spec_tile = AiGetPctTileBetween(
 
	_players_ai[p->index].mid2.spec_tile = AiGetPctTileBetween(
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.from),
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.to),
 
		0xAA
 
	);
 
	p->ai.mid2.use_tile = 0;
 
	p->ai.mid2.rand_rng = 6;
 
	p->ai.mid2.cur_building_rule = 0xFF;
 
	p->ai.mid2.unk6 = 2;
 
	p->ai.mid2.unk7 = 1;
 
	p->ai.mid2.buildcmd_a = 0xFF;
 
	p->ai.mid2.buildcmd_b = 0xFF;
 
	p->ai.mid2.direction = p->ai.dst.direction;
 
	p->ai.mid2.cargo = fr.cargo;
 
	_players_ai[p->index].mid2.use_tile = 0;
 
	_players_ai[p->index].mid2.rand_rng = 6;
 
	_players_ai[p->index].mid2.cur_building_rule = 0xFF;
 
	_players_ai[p->index].mid2.unk6 = 2;
 
	_players_ai[p->index].mid2.unk7 = 1;
 
	_players_ai[p->index].mid2.buildcmd_a = 0xFF;
 
	_players_ai[p->index].mid2.buildcmd_b = 0xFF;
 
	_players_ai[p->index].mid2.direction = _players_ai[p->index].dst.direction;
 
	_players_ai[p->index].mid2.cargo = fr.cargo;
 

	
 
	// Fill common fields
 
	p->ai.cargo_type = fr.cargo;
 
	p->ai.num_wagons = 3;
 
	p->ai.build_kind = 2;
 
	p->ai.num_build_rec = 4;
 
	p->ai.num_loco_to_build = 2;
 
	p->ai.num_want_fullload = 0;
 
	p->ai.wagon_list[0] = INVALID_VEHICLE;
 
	p->ai.order_list_blocks[0] = 0;
 
	p->ai.order_list_blocks[1] = 1;
 
	p->ai.order_list_blocks[2] = 255;
 
	p->ai.state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
 
	p->ai.state_mode = UCHAR_MAX;
 
	p->ai.state_counter = 0;
 
	p->ai.timeout_counter = 0;
 
	_players_ai[p->index].cargo_type = fr.cargo;
 
	_players_ai[p->index].num_wagons = 3;
 
	_players_ai[p->index].build_kind = 2;
 
	_players_ai[p->index].num_build_rec = 4;
 
	_players_ai[p->index].num_loco_to_build = 2;
 
	_players_ai[p->index].num_want_fullload = 0;
 
	_players_ai[p->index].wagon_list[0] = INVALID_VEHICLE;
 
	_players_ai[p->index].order_list_blocks[0] = 0;
 
	_players_ai[p->index].order_list_blocks[1] = 1;
 
	_players_ai[p->index].order_list_blocks[2] = 255;
 
	_players_ai[p->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
 
	_players_ai[p->index].state_mode = UCHAR_MAX;
 
	_players_ai[p->index].state_counter = 0;
 
	_players_ai[p->index].timeout_counter = 0;
 
}
 

	
 
static void AiWantPassengerRoute(Player *p)
 
{
 
	int i;
 
	FoundRoute fr;
 
@@ -1049,63 +1050,63 @@ static void AiWantPassengerRoute(Player 
 
	}
 

	
 
	fr.cargo = CT_PASSENGERS;
 
	if (!AiCheckIfRouteIsGood(p, &fr, 1)) return;
 

	
 
	// Fill the source field
 
	p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	p->ai.src.use_tile = 0;
 
	p->ai.src.rand_rng = 7;
 
	p->ai.src.cur_building_rule = 0xFF;
 
	p->ai.src.unk6 = 1;
 
	p->ai.src.unk7 = 0;
 
	p->ai.src.buildcmd_a = 0x10;
 
	p->ai.src.buildcmd_b = 0xFF;
 
	p->ai.src.direction = AiGetDirectionBetweenTiles(
 
	_players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	_players_ai[p->index].src.use_tile = 0;
 
	_players_ai[p->index].src.rand_rng = 7;
 
	_players_ai[p->index].src.cur_building_rule = 0xFF;
 
	_players_ai[p->index].src.unk6 = 1;
 
	_players_ai[p->index].src.unk7 = 0;
 
	_players_ai[p->index].src.buildcmd_a = 0x10;
 
	_players_ai[p->index].src.buildcmd_b = 0xFF;
 
	_players_ai[p->index].src.direction = AiGetDirectionBetweenTiles(
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.from),
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.to)
 
	);
 
	p->ai.src.cargo = fr.cargo;
 
	_players_ai[p->index].src.cargo = fr.cargo;
 

	
 
	// Fill the dest field
 
	p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	p->ai.dst.use_tile = 0;
 
	p->ai.dst.rand_rng = 7;
 
	p->ai.dst.cur_building_rule = 0xFF;
 
	p->ai.dst.unk6 = 1;
 
	p->ai.dst.unk7 = 0;
 
	p->ai.dst.buildcmd_a = 0xFF;
 
	p->ai.dst.buildcmd_b = 0xFF;
 
	p->ai.dst.direction = AiGetDirectionBetweenTiles(
 
	_players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	_players_ai[p->index].dst.use_tile = 0;
 
	_players_ai[p->index].dst.rand_rng = 7;
 
	_players_ai[p->index].dst.cur_building_rule = 0xFF;
 
	_players_ai[p->index].dst.unk6 = 1;
 
	_players_ai[p->index].dst.unk7 = 0;
 
	_players_ai[p->index].dst.buildcmd_a = 0xFF;
 
	_players_ai[p->index].dst.buildcmd_b = 0xFF;
 
	_players_ai[p->index].dst.direction = AiGetDirectionBetweenTiles(
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.to),
 
		GET_TOWN_OR_INDUSTRY_TILE(fr.from)
 
	);
 
	p->ai.dst.cargo = fr.cargo;
 
	_players_ai[p->index].dst.cargo = fr.cargo;
 

	
 
	// Fill common fields
 
	p->ai.cargo_type = fr.cargo;
 
	p->ai.num_wagons = 2;
 
	p->ai.build_kind = 1;
 
	p->ai.num_build_rec = 2;
 
	p->ai.num_loco_to_build = 1;
 
	p->ai.num_want_fullload = 0;
 
	p->ai.wagon_list[0] = INVALID_VEHICLE;
 
	p->ai.order_list_blocks[0] = 0;
 
	p->ai.order_list_blocks[1] = 1;
 
	p->ai.order_list_blocks[2] = 255;
 
	p->ai.state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
 
	p->ai.state_mode = UCHAR_MAX;
 
	p->ai.state_counter = 0;
 
	p->ai.timeout_counter = 0;
 
	_players_ai[p->index].cargo_type = fr.cargo;
 
	_players_ai[p->index].num_wagons = 2;
 
	_players_ai[p->index].build_kind = 1;
 
	_players_ai[p->index].num_build_rec = 2;
 
	_players_ai[p->index].num_loco_to_build = 1;
 
	_players_ai[p->index].num_want_fullload = 0;
 
	_players_ai[p->index].wagon_list[0] = INVALID_VEHICLE;
 
	_players_ai[p->index].order_list_blocks[0] = 0;
 
	_players_ai[p->index].order_list_blocks[1] = 1;
 
	_players_ai[p->index].order_list_blocks[2] = 255;
 
	_players_ai[p->index].state = AIS_BUILD_DEFAULT_RAIL_BLOCKS;
 
	_players_ai[p->index].state_mode = UCHAR_MAX;
 
	_players_ai[p->index].state_counter = 0;
 
	_players_ai[p->index].timeout_counter = 0;
 
}
 

	
 
static void AiWantTrainRoute(Player *p)
 
{
 
	uint16 r = GB(Random(), 0, 16);
 

	
 
	p->ai.railtype_to_use = GetBestRailtype(p);
 
	_players_ai[p->index].railtype_to_use = GetBestRailtype(p);
 

	
 
	if (r > 0xD000) {
 
		AiWantLongIndustryRoute(p);
 
	} else if (r > 0x6000) {
 
		AiWantMediumIndustryRoute(p);
 
	} else if (r > 0x1000) {
 
@@ -1136,44 +1137,44 @@ static void AiWantLongRoadIndustryRoute(
 
		if (--i == 0) return;
 
	}
 

	
 
	if (!AiCheckIfRouteIsGood(p, &fr, 2)) return;
 

	
 
	// Fill the source field
 
	p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	p->ai.src.use_tile = 0;
 
	p->ai.src.rand_rng = 9;
 
	p->ai.src.cur_building_rule = 0xFF;
 
	p->ai.src.buildcmd_a = 1;
 
	p->ai.src.direction = 0;
 
	p->ai.src.cargo = fr.cargo | 0x80;
 
	_players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	_players_ai[p->index].src.use_tile = 0;
 
	_players_ai[p->index].src.rand_rng = 9;
 
	_players_ai[p->index].src.cur_building_rule = 0xFF;
 
	_players_ai[p->index].src.buildcmd_a = 1;
 
	_players_ai[p->index].src.direction = 0;
 
	_players_ai[p->index].src.cargo = fr.cargo | 0x80;
 

	
 
	// Fill the dest field
 
	p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	p->ai.dst.use_tile = 0;
 
	p->ai.dst.rand_rng = 9;
 
	p->ai.dst.cur_building_rule = 0xFF;
 
	p->ai.dst.buildcmd_a = 0xFF;
 
	p->ai.dst.direction = 0;
 
	p->ai.dst.cargo = fr.cargo;
 
	_players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	_players_ai[p->index].dst.use_tile = 0;
 
	_players_ai[p->index].dst.rand_rng = 9;
 
	_players_ai[p->index].dst.cur_building_rule = 0xFF;
 
	_players_ai[p->index].dst.buildcmd_a = 0xFF;
 
	_players_ai[p->index].dst.direction = 0;
 
	_players_ai[p->index].dst.cargo = fr.cargo;
 

	
 
	// Fill common fields
 
	p->ai.cargo_type = fr.cargo;
 
	p->ai.num_build_rec = 2;
 
	p->ai.num_loco_to_build = 5;
 
	p->ai.num_want_fullload = 5;
 

	
 
//	p->ai.loco_id = INVALID_VEHICLE;
 
	p->ai.order_list_blocks[0] = 0;
 
	p->ai.order_list_blocks[1] = 1;
 
	p->ai.order_list_blocks[2] = 255;
 

	
 
	p->ai.state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
 
	p->ai.state_mode = UCHAR_MAX;
 
	p->ai.state_counter = 0;
 
	p->ai.timeout_counter = 0;
 
	_players_ai[p->index].cargo_type = fr.cargo;
 
	_players_ai[p->index].num_build_rec = 2;
 
	_players_ai[p->index].num_loco_to_build = 5;
 
	_players_ai[p->index].num_want_fullload = 5;
 

	
 
//	_players_ai[p->index].loco_id = INVALID_VEHICLE;
 
	_players_ai[p->index].order_list_blocks[0] = 0;
 
	_players_ai[p->index].order_list_blocks[1] = 1;
 
	_players_ai[p->index].order_list_blocks[2] = 255;
 

	
 
	_players_ai[p->index].state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
 
	_players_ai[p->index].state_mode = UCHAR_MAX;
 
	_players_ai[p->index].state_counter = 0;
 
	_players_ai[p->index].timeout_counter = 0;
 
}
 

	
 
static void AiWantMediumRoadIndustryRoute(Player *p)
 
{
 
	int i;
 
	FoundRoute fr;
 
@@ -1192,44 +1193,44 @@ static void AiWantMediumRoadIndustryRout
 
		if (--i == 0) return;
 
	}
 

	
 
	if (!AiCheckIfRouteIsGood(p, &fr, 2)) return;
 

	
 
	// Fill the source field
 
	p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	p->ai.src.use_tile = 0;
 
	p->ai.src.rand_rng = 9;
 
	p->ai.src.cur_building_rule = 0xFF;
 
	p->ai.src.buildcmd_a = 1;
 
	p->ai.src.direction = 0;
 
	p->ai.src.cargo = fr.cargo | 0x80;
 
	_players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	_players_ai[p->index].src.use_tile = 0;
 
	_players_ai[p->index].src.rand_rng = 9;
 
	_players_ai[p->index].src.cur_building_rule = 0xFF;
 
	_players_ai[p->index].src.buildcmd_a = 1;
 
	_players_ai[p->index].src.direction = 0;
 
	_players_ai[p->index].src.cargo = fr.cargo | 0x80;
 

	
 
	// Fill the dest field
 
	p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	p->ai.dst.use_tile = 0;
 
	p->ai.dst.rand_rng = 9;
 
	p->ai.dst.cur_building_rule = 0xFF;
 
	p->ai.dst.buildcmd_a = 0xFF;
 
	p->ai.dst.direction = 0;
 
	p->ai.dst.cargo = fr.cargo;
 
	_players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	_players_ai[p->index].dst.use_tile = 0;
 
	_players_ai[p->index].dst.rand_rng = 9;
 
	_players_ai[p->index].dst.cur_building_rule = 0xFF;
 
	_players_ai[p->index].dst.buildcmd_a = 0xFF;
 
	_players_ai[p->index].dst.direction = 0;
 
	_players_ai[p->index].dst.cargo = fr.cargo;
 

	
 
	// Fill common fields
 
	p->ai.cargo_type = fr.cargo;
 
	p->ai.num_build_rec = 2;
 
	p->ai.num_loco_to_build = 3;
 
	p->ai.num_want_fullload = 3;
 

	
 
//	p->ai.loco_id = INVALID_VEHICLE;
 
	p->ai.order_list_blocks[0] = 0;
 
	p->ai.order_list_blocks[1] = 1;
 
	p->ai.order_list_blocks[2] = 255;
 

	
 
	p->ai.state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
 
	p->ai.state_mode = UCHAR_MAX;
 
	p->ai.state_counter = 0;
 
	p->ai.timeout_counter = 0;
 
	_players_ai[p->index].cargo_type = fr.cargo;
 
	_players_ai[p->index].num_build_rec = 2;
 
	_players_ai[p->index].num_loco_to_build = 3;
 
	_players_ai[p->index].num_want_fullload = 3;
 

	
 
//	_players_ai[p->index].loco_id = INVALID_VEHICLE;
 
	_players_ai[p->index].order_list_blocks[0] = 0;
 
	_players_ai[p->index].order_list_blocks[1] = 1;
 
	_players_ai[p->index].order_list_blocks[2] = 255;
 

	
 
	_players_ai[p->index].state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
 
	_players_ai[p->index].state_mode = UCHAR_MAX;
 
	_players_ai[p->index].state_counter = 0;
 
	_players_ai[p->index].timeout_counter = 0;
 
}
 

	
 
static void AiWantLongRoadPassengerRoute(Player *p)
 
{
 
	int i;
 
	FoundRoute fr;
 
@@ -1250,44 +1251,44 @@ static void AiWantLongRoadPassengerRoute
 

	
 
	fr.cargo = CT_PASSENGERS;
 

	
 
	if (!AiCheckIfRouteIsGood(p, &fr, 2)) return;
 

	
 
	// Fill the source field
 
	p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	p->ai.src.use_tile = 0;
 
	p->ai.src.rand_rng = 10;
 
	p->ai.src.cur_building_rule = 0xFF;
 
	p->ai.src.buildcmd_a = 1;
 
	p->ai.src.direction = 0;
 
	p->ai.src.cargo = CT_PASSENGERS;
 
	_players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	_players_ai[p->index].src.use_tile = 0;
 
	_players_ai[p->index].src.rand_rng = 10;
 
	_players_ai[p->index].src.cur_building_rule = 0xFF;
 
	_players_ai[p->index].src.buildcmd_a = 1;
 
	_players_ai[p->index].src.direction = 0;
 
	_players_ai[p->index].src.cargo = CT_PASSENGERS;
 

	
 
	// Fill the dest field
 
	p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	p->ai.dst.use_tile = 0;
 
	p->ai.dst.rand_rng = 10;
 
	p->ai.dst.cur_building_rule = 0xFF;
 
	p->ai.dst.buildcmd_a = 0xFF;
 
	p->ai.dst.direction = 0;
 
	p->ai.dst.cargo = CT_PASSENGERS;
 
	_players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	_players_ai[p->index].dst.use_tile = 0;
 
	_players_ai[p->index].dst.rand_rng = 10;
 
	_players_ai[p->index].dst.cur_building_rule = 0xFF;
 
	_players_ai[p->index].dst.buildcmd_a = 0xFF;
 
	_players_ai[p->index].dst.direction = 0;
 
	_players_ai[p->index].dst.cargo = CT_PASSENGERS;
 

	
 
	// Fill common fields
 
	p->ai.cargo_type = CT_PASSENGERS;
 
	p->ai.num_build_rec = 2;
 
	p->ai.num_loco_to_build = 4;
 
	p->ai.num_want_fullload = 0;
 

	
 
//	p->ai.loco_id = INVALID_VEHICLE;
 
	p->ai.order_list_blocks[0] = 0;
 
	p->ai.order_list_blocks[1] = 1;
 
	p->ai.order_list_blocks[2] = 255;
 

	
 
	p->ai.state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
 
	p->ai.state_mode = UCHAR_MAX;
 
	p->ai.state_counter = 0;
 
	p->ai.timeout_counter = 0;
 
	_players_ai[p->index].cargo_type = CT_PASSENGERS;
 
	_players_ai[p->index].num_build_rec = 2;
 
	_players_ai[p->index].num_loco_to_build = 4;
 
	_players_ai[p->index].num_want_fullload = 0;
 

	
 
//	_players_ai[p->index].loco_id = INVALID_VEHICLE;
 
	_players_ai[p->index].order_list_blocks[0] = 0;
 
	_players_ai[p->index].order_list_blocks[1] = 1;
 
	_players_ai[p->index].order_list_blocks[2] = 255;
 

	
 
	_players_ai[p->index].state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
 
	_players_ai[p->index].state_mode = UCHAR_MAX;
 
	_players_ai[p->index].state_counter = 0;
 
	_players_ai[p->index].timeout_counter = 0;
 
}
 

	
 
static void AiWantPassengerRouteInsideTown(Player *p)
 
{
 
	int i;
 
	FoundRoute fr;
 
@@ -1306,44 +1307,44 @@ static void AiWantPassengerRouteInsideTo
 
	fr.cargo = CT_PASSENGERS;
 
	fr.from = fr.to = t;
 

	
 
	if (!AiCheckIfRouteIsGood(p, &fr, 2)) return;
 

	
 
	// Fill the source field
 
	p->ai.src.spec_tile = t->xy;
 
	p->ai.src.use_tile = 0;
 
	p->ai.src.rand_rng = 10;
 
	p->ai.src.cur_building_rule = 0xFF;
 
	p->ai.src.buildcmd_a = 1;
 
	p->ai.src.direction = 0;
 
	p->ai.src.cargo = CT_PASSENGERS;
 
	_players_ai[p->index].src.spec_tile = t->xy;
 
	_players_ai[p->index].src.use_tile = 0;
 
	_players_ai[p->index].src.rand_rng = 10;
 
	_players_ai[p->index].src.cur_building_rule = 0xFF;
 
	_players_ai[p->index].src.buildcmd_a = 1;
 
	_players_ai[p->index].src.direction = 0;
 
	_players_ai[p->index].src.cargo = CT_PASSENGERS;
 

	
 
	// Fill the dest field
 
	p->ai.dst.spec_tile = t->xy;
 
	p->ai.dst.use_tile = 0;
 
	p->ai.dst.rand_rng = 10;
 
	p->ai.dst.cur_building_rule = 0xFF;
 
	p->ai.dst.buildcmd_a = 0xFF;
 
	p->ai.dst.direction = 0;
 
	p->ai.dst.cargo = CT_PASSENGERS;
 
	_players_ai[p->index].dst.spec_tile = t->xy;
 
	_players_ai[p->index].dst.use_tile = 0;
 
	_players_ai[p->index].dst.rand_rng = 10;
 
	_players_ai[p->index].dst.cur_building_rule = 0xFF;
 
	_players_ai[p->index].dst.buildcmd_a = 0xFF;
 
	_players_ai[p->index].dst.direction = 0;
 
	_players_ai[p->index].dst.cargo = CT_PASSENGERS;
 

	
 
	// Fill common fields
 
	p->ai.cargo_type = CT_PASSENGERS;
 
	p->ai.num_build_rec = 2;
 
	p->ai.num_loco_to_build = 2;
 
	p->ai.num_want_fullload = 0;
 

	
 
//	p->ai.loco_id = INVALID_VEHICLE;
 
	p->ai.order_list_blocks[0] = 0;
 
	p->ai.order_list_blocks[1] = 1;
 
	p->ai.order_list_blocks[2] = 255;
 

	
 
	p->ai.state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
 
	p->ai.state_mode = UCHAR_MAX;
 
	p->ai.state_counter = 0;
 
	p->ai.timeout_counter = 0;
 
	_players_ai[p->index].cargo_type = CT_PASSENGERS;
 
	_players_ai[p->index].num_build_rec = 2;
 
	_players_ai[p->index].num_loco_to_build = 2;
 
	_players_ai[p->index].num_want_fullload = 0;
 

	
 
//	_players_ai[p->index].loco_id = INVALID_VEHICLE;
 
	_players_ai[p->index].order_list_blocks[0] = 0;
 
	_players_ai[p->index].order_list_blocks[1] = 1;
 
	_players_ai[p->index].order_list_blocks[2] = 255;
 

	
 
	_players_ai[p->index].state = AIS_BUILD_DEFAULT_ROAD_BLOCKS;
 
	_players_ai[p->index].state_mode = UCHAR_MAX;
 
	_players_ai[p->index].state_counter = 0;
 
	_players_ai[p->index].timeout_counter = 0;
 
}
 

	
 
static void AiWantRoadRoute(Player *p)
 
{
 
	uint16 r = GB(Random(), 0, 16);
 

	
 
@@ -1363,13 +1364,13 @@ static void AiWantPassengerAircraftRoute
 
	FoundRoute fr;
 
	int i;
 

	
 
	/* Get aircraft that would be bought for this route
 
	 * (probably, as conditions may change before the route is fully built,
 
	 * like running out of money and having to select different aircraft, etc ...) */
 
	EngineID veh = AiChooseAircraftToBuild(p->player_money, p->ai.build_kind != 0 ? 0 : AIR_CTOL);
 
	EngineID veh = AiChooseAircraftToBuild(p->player_money, _players_ai[p->index].build_kind != 0 ? 0 : AIR_CTOL);
 

	
 
	/* No aircraft buildable mean no aircraft route */
 
	if (veh == INVALID_ENGINE) return;
 

	
 
	const AircraftVehicleInfo *avi = AircraftVehInfo(veh);
 

	
 
@@ -1419,50 +1420,50 @@ static void AiWantPassengerAircraftRoute
 

	
 
	fr.cargo = CT_PASSENGERS;
 
	if (!AiCheckIfRouteIsGood(p, &fr, 4)) return;
 

	
 

	
 
	// Fill the source field
 
	p->ai.src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	p->ai.src.use_tile = 0;
 
	p->ai.src.rand_rng = 12;
 
	p->ai.src.cur_building_rule = 0xFF;
 
	p->ai.src.cargo = fr.cargo;
 
	_players_ai[p->index].src.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.to);
 
	_players_ai[p->index].src.use_tile = 0;
 
	_players_ai[p->index].src.rand_rng = 12;
 
	_players_ai[p->index].src.cur_building_rule = 0xFF;
 
	_players_ai[p->index].src.cargo = fr.cargo;
 

	
 
	// Fill the dest field
 
	p->ai.dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	p->ai.dst.use_tile = 0;
 
	p->ai.dst.rand_rng = 12;
 
	p->ai.dst.cur_building_rule = 0xFF;
 
	p->ai.dst.cargo = fr.cargo;
 
	_players_ai[p->index].dst.spec_tile = GET_TOWN_OR_INDUSTRY_TILE(fr.from);
 
	_players_ai[p->index].dst.use_tile = 0;
 
	_players_ai[p->index].dst.rand_rng = 12;
 
	_players_ai[p->index].dst.cur_building_rule = 0xFF;
 
	_players_ai[p->index].dst.cargo = fr.cargo;
 

	
 
	// Fill common fields
 
	p->ai.cargo_type = fr.cargo;
 
	p->ai.build_kind = 0;
 
	p->ai.num_build_rec = 2;
 
	p->ai.num_loco_to_build = 1;
 
	_players_ai[p->index].cargo_type = fr.cargo;
 
	_players_ai[p->index].build_kind = 0;
 
	_players_ai[p->index].num_build_rec = 2;
 
	_players_ai[p->index].num_loco_to_build = 1;
 
	/* Using full load always may not be the best.
 
	 * Pick random value and rely on selling the vehicle & route
 
	 * afterwards if the choice was utterly wrong (or maybe altering the value if AI is improved)
 
	 * When traffic is very low or very assymetric, is is better not to full load
 
	 * When traffic is high, full/non-full make no difference
 
	 * It should be better to run with aircraft only one way full 6 times per year,
 
	 * rather than two way full 1 times.
 
	 * Practical experiments with AI show that the non-full-load aircrafts are usually
 
	 * those that survive
 
	 * Also, non-full load is more resistant against starving (by building better stations
 
	 * or using exclusive rights)
 
	 */
 
	p->ai.num_want_fullload = Chance16(1, 5); // 20% chance
 
//	p->ai.loco_id = INVALID_VEHICLE;
 
	p->ai.order_list_blocks[0] = 0;
 
	p->ai.order_list_blocks[1] = 1;
 
	p->ai.order_list_blocks[2] = 255;
 

	
 
	p->ai.state = AIS_AIRPORT_STUFF;
 
	p->ai.timeout_counter = 0;
 
	_players_ai[p->index].num_want_fullload = Chance16(1, 5); // 20% chance
 
//	_players_ai[p->index].loco_id = INVALID_VEHICLE;
 
	_players_ai[p->index].order_list_blocks[0] = 0;
 
	_players_ai[p->index].order_list_blocks[1] = 1;
 
	_players_ai[p->index].order_list_blocks[2] = 255;
 

	
 
	_players_ai[p->index].state = AIS_AIRPORT_STUFF;
 
	_players_ai[p->index].timeout_counter = 0;
 
}
 

	
 
static void AiWantOilRigAircraftRoute(Player *p)
 
{
 
	int i;
 
	FoundRoute fr;
 
@@ -1489,38 +1490,38 @@ static void AiWantOilRigAircraftRoute(Pl
 
	fr.cargo = CT_PASSENGERS;
 
	fr.from = fr.to = t;
 

	
 
	if (!AiCheckIfRouteIsGood(p, &fr, 4)) return;
 

	
 
	// Fill the source field
 
	p->ai.src.spec_tile = t->xy;
 
	p->ai.src.use_tile = 0;
 
	p->ai.src.rand_rng = 12;
 
	p->ai.src.cur_building_rule = 0xFF;
 
	p->ai.src.cargo = CT_PASSENGERS;
 
	_players_ai[p->index].src.spec_tile = t->xy;
 
	_players_ai[p->index].src.use_tile = 0;
 
	_players_ai[p->index].src.rand_rng = 12;
 
	_players_ai[p->index].src.cur_building_rule = 0xFF;
 
	_players_ai[p->index].src.cargo = CT_PASSENGERS;
 

	
 
	// Fill the dest field
 
	p->ai.dst.spec_tile = in->xy;
 
	p->ai.dst.use_tile = 0;
 
	p->ai.dst.rand_rng = 5;
 
	p->ai.dst.cur_building_rule = 0xFF;
 
	p->ai.dst.cargo = CT_PASSENGERS;
 
	_players_ai[p->index].dst.spec_tile = in->xy;
 
	_players_ai[p->index].dst.use_tile = 0;
 
	_players_ai[p->index].dst.rand_rng = 5;
 
	_players_ai[p->index].dst.cur_building_rule = 0xFF;
 
	_players_ai[p->index].dst.cargo = CT_PASSENGERS;
 

	
 
	// Fill common fields
 
	p->ai.cargo_type = CT_PASSENGERS;
 
	p->ai.build_kind = 1;
 
	p->ai.num_build_rec = 2;
 
	p->ai.num_loco_to_build = 1;
 
	p->ai.num_want_fullload = 0;
 
//	p->ai.loco_id = INVALID_VEHICLE;
 
	p->ai.order_list_blocks[0] = 0;
 
	p->ai.order_list_blocks[1] = 1;
 
	p->ai.order_list_blocks[2] = 255;
 

	
 
	p->ai.state = AIS_AIRPORT_STUFF;
 
	p->ai.timeout_counter = 0;
 
	_players_ai[p->index].cargo_type = CT_PASSENGERS;
 
	_players_ai[p->index].build_kind = 1;
 
	_players_ai[p->index].num_build_rec = 2;
 
	_players_ai[p->index].num_loco_to_build = 1;
 
	_players_ai[p->index].num_want_fullload = 0;
 
//	_players_ai[p->index].loco_id = INVALID_VEHICLE;
 
	_players_ai[p->index].order_list_blocks[0] = 0;
 
	_players_ai[p->index].order_list_blocks[1] = 1;
 
	_players_ai[p->index].order_list_blocks[2] = 255;
 

	
 
	_players_ai[p->index].state = AIS_AIRPORT_STUFF;
 
	_players_ai[p->index].timeout_counter = 0;
 
}
 

	
 
static void AiWantAircraftRoute(Player *p)
 
{
 
	uint16 r = (uint16)Random();
 

	
 
@@ -1536,13 +1537,13 @@ static void AiWantAircraftRoute(Player *
 
static void AiStateWantNewRoute(Player *p)
 
{
 
	uint16 r;
 
	int i;
 

	
 
	if (p->player_money < AiGetBasePrice(p) * 500) {
 
		p->ai.state = AIS_0;
 
		_players_ai[p->index].state = AIS_0;
 
		return;
 
	}
 

	
 
	i = 200;
 
	for (;;) {
 
		r = (uint16)Random();
 
@@ -1565,17 +1566,17 @@ static void AiStateWantNewRoute(Player *
 
			AiWantAircraftRoute(p);
 
		} else {
 
			/* Ships are not implemented in this (broken) AI */
 
		}
 

	
 
		// got a route?
 
		if (p->ai.state != AIS_WANT_NEW_ROUTE) break;
 
		if (_players_ai[p->index].state != AIS_WANT_NEW_ROUTE) break;
 

	
 
		// time out?
 
		if (--i == 0) {
 
			if (++p->ai.state_counter == 556) p->ai.state = AIS_0;
 
			if (++_players_ai[p->index].state_counter == 556) _players_ai[p->index].state = AIS_0;
 
			break;
 
		}
 
	}
 
}
 

	
 
static bool AiCheckTrackResources(TileIndex tile, const AiDefaultBlockData *p, byte cargo)
 
@@ -1796,73 +1797,73 @@ static void AiStateBuildDefaultRailBlock
 
	int j;
 
	AiBuildRec *aib;
 
	int rule;
 
	CommandCost cost;
 

	
 
	// time out?
 
	if (++p->ai.timeout_counter == 1388) {
 
		p->ai.state = AIS_DELETE_RAIL_BLOCKS;
 
	if (++_players_ai[p->index].timeout_counter == 1388) {
 
		_players_ai[p->index].state = AIS_DELETE_RAIL_BLOCKS;
 
		return;
 
	}
 

	
 
	// do the following 8 times
 
	for (i = 0; i < 8; i++) {
 
		// check if we can build the default track
 
		aib = &p->ai.src;
 
		j = p->ai.num_build_rec;
 
		aib = &_players_ai[p->index].src;
 
		j = _players_ai[p->index].num_build_rec;
 
		do {
 
			// this item has already been built?
 
			if (aib->cur_building_rule != 255) continue;
 

	
 
			// adjust the coordinate randomly,
 
			// to make sure that we find a position.
 
			aib->use_tile = AdjustTileCoordRandomly(aib->spec_tile, aib->rand_rng);
 

	
 
			// check if the track can be build there.
 
			rule = AiBuildDefaultRailTrack(aib->use_tile,
 
				p->ai.build_kind, p->ai.num_wagons,
 
				_players_ai[p->index].build_kind, _players_ai[p->index].num_wagons,
 
				aib->unk6, aib->unk7,
 
				aib->direction, aib->cargo,
 
				p->ai.railtype_to_use,
 
				_players_ai[p->index].railtype_to_use,
 
				&cost
 
			);
 

	
 
			if (rule == -1) {
 
				// cannot build, terraform after a while
 
				if (p->ai.state_counter >= 600) {
 
					AiDoTerraformLand(aib->use_tile, (DiagDirection)(Random() & 3), 3, (int8)p->ai.state_mode);
 
				if (_players_ai[p->index].state_counter >= 600) {
 
					AiDoTerraformLand(aib->use_tile, (DiagDirection)(Random() & 3), 3, (int8)_players_ai[p->index].state_mode);
 
				}
 
				// also try the other terraform direction
 
				if (++p->ai.state_counter >= 1000) {
 
					p->ai.state_counter = 0;
 
					p->ai.state_mode = -p->ai.state_mode;
 
				if (++_players_ai[p->index].state_counter >= 1000) {
 
					_players_ai[p->index].state_counter = 0;
 
					_players_ai[p->index].state_mode = -_players_ai[p->index].state_mode;
 
				}
 
			} else if (CheckPlayerHasMoney(cost)) {
 
				// player has money, build it.
 
				aib->cur_building_rule = rule;
 

	
 
				AiDoBuildDefaultRailTrack(
 
					aib->use_tile,
 
					_default_rail_track_data[rule]->data,
 
					p->ai.railtype_to_use,
 
					_players_ai[p->index].railtype_to_use,
 
					DC_EXEC | DC_NO_TOWN_RATING
 
				);
 
			}
 
		} while (++aib, --j);
 
	}
 

	
 
	// check if we're done with all of them
 
	aib = &p->ai.src;
 
	j = p->ai.num_build_rec;
 
	aib = &_players_ai[p->index].src;
 
	j = _players_ai[p->index].num_build_rec;
 
	do {
 
		if (aib->cur_building_rule == 255) return;
 
	} while (++aib, --j);
 

	
 
	// yep, all are done. switch state to the rail building state.
 
	p->ai.state = AIS_BUILD_RAIL;
 
	p->ai.state_mode = 255;
 
	_players_ai[p->index].state = AIS_BUILD_RAIL;
 
	_players_ai[p->index].state_mode = 255;
 
}
 

	
 
static TileIndex AiGetEdgeOfDefaultRailBlock(byte rule, TileIndex tile, byte cmd, DiagDirection *dir)
 
{
 
	const AiDefaultBlockData *p = _default_rail_track_data[rule]->data;
 

	
 
@@ -1893,17 +1894,17 @@ static bool AiEnumFollowTrack(TileIndex 
 
}
 

	
 
static bool AiDoFollowTrack(const Player* p)
 
{
 
	AiRailPathFindData arpfd;
 

	
 
	arpfd.tile = p->ai.start_tile_a;
 
	arpfd.tile2 = p->ai.cur_tile_a;
 
	arpfd.tile = _players_ai[p->index].start_tile_a;
 
	arpfd.tile2 = _players_ai[p->index].cur_tile_a;
 
	arpfd.flag = false;
 
	arpfd.count = 0;
 
	FollowTrack(p->ai.cur_tile_a + TileOffsByDiagDir(p->ai.cur_dir_a), 0x2000 | TRANSPORT_RAIL, 0, ReverseDiagDir(p->ai.cur_dir_a),
 
	FollowTrack(_players_ai[p->index].cur_tile_a + TileOffsByDiagDir(_players_ai[p->index].cur_dir_a), 0x2000 | TRANSPORT_RAIL, 0, ReverseDiagDir(_players_ai[p->index].cur_dir_a),
 
		(TPFEnumProc*)AiEnumFollowTrack, NULL, &arpfd);
 
	return arpfd.count > 8;
 
}
 

	
 
struct AiRailFinder {
 
	TileIndex final_tile;
 
@@ -1934,34 +1935,34 @@ static const byte _dir_table_2[] = {12, 
 

	
 

	
 
static bool AiIsTileBanned(const Player* p, TileIndex tile, byte val)
 
{
 
	int i;
 

	
 
	for (i = 0; i != p->ai.banned_tile_count; i++) {
 
		if (p->ai.banned_tiles[i] == tile && p->ai.banned_val[i] == val) {
 
	for (i = 0; i != _players_ai[p->index].banned_tile_count; i++) {
 
		if (_players_ai[p->index].banned_tiles[i] == tile && _players_ai[p->index].banned_val[i] == val) {
 
			return true;
 
		}
 
	}
 
	return false;
 
}
 

	
 
static void AiBanTile(Player* p, TileIndex tile, byte val)
 
{
 
	uint i;
 

	
 
	for (i = lengthof(p->ai.banned_tiles) - 1; i != 0; i--) {
 
		p->ai.banned_tiles[i] = p->ai.banned_tiles[i - 1];
 
		p->ai.banned_val[i] = p->ai.banned_val[i - 1];
 
	for (i = lengthof(_players_ai[p->index].banned_tiles) - 1; i != 0; i--) {
 
		_players_ai[p->index].banned_tiles[i] = _players_ai[p->index].banned_tiles[i - 1];
 
		_players_ai[p->index].banned_val[i] = _players_ai[p->index].banned_val[i - 1];
 
	}
 

	
 
	p->ai.banned_tiles[0] = tile;
 
	p->ai.banned_val[0] = val;
 

	
 
	if (p->ai.banned_tile_count != lengthof(p->ai.banned_tiles)) {
 
		p->ai.banned_tile_count++;
 
	_players_ai[p->index].banned_tiles[0] = tile;
 
	_players_ai[p->index].banned_val[0] = val;
 

	
 
	if (_players_ai[p->index].banned_tile_count != lengthof(_players_ai[p->index].banned_tiles)) {
 
		_players_ai[p->index].banned_tile_count++;
 
	}
 
}
 

	
 
static void AiBuildRailRecursive(AiRailFinder *arf, TileIndex tile, DiagDirection dir);
 

	
 
static bool AiCheckRailPathBetter(AiRailFinder *arf, const byte *p)
 
@@ -2022,13 +2023,13 @@ static inline void AiCheckBuildRailBridg
 
			}
 
			if (type != MP_WATER && type != MP_RAILWAY && type != MP_ROAD) return;
 
			flag = true;
 
		}
 

	
 
		// Is building a (rail)bridge possible at this place (type doesn't matter)?
 
		if (CmdFailed(DoCommand(tile_new, tile, 0 | arf->player->ai.railtype_to_use << 8, DC_AUTO, CMD_BUILD_BRIDGE))) {
 
		if (CmdFailed(DoCommand(tile_new, tile, 0 | _players_ai[arf->player->index].railtype_to_use << 8, DC_AUTO, CMD_BUILD_BRIDGE))) {
 
			return;
 
		}
 
		AiBuildRailRecursive(arf, tile_new, dir2);
 

	
 
		// At the bottom depth, check if the new path is better than the old one.
 
		if (arf->depth == 1) {
 
@@ -2039,13 +2040,13 @@ static inline void AiCheckBuildRailBridg
 

	
 
static inline void AiCheckBuildRailTunnelHere(AiRailFinder *arf, TileIndex tile, const byte *p)
 
{
 
	uint z;
 

	
 
	if (GetTileSlope(tile, &z) == _dir_table_2[p[0] & 3] && z != 0) {
 
		CommandCost cost = DoCommand(tile, arf->player->ai.railtype_to_use, 0, DC_AUTO, CMD_BUILD_TUNNEL);
 
		CommandCost cost = DoCommand(tile, _players_ai[arf->player->index].railtype_to_use, 0, DC_AUTO, CMD_BUILD_TUNNEL);
 

	
 
		if (CmdSucceeded(cost) && cost.GetCost() <= (arf->player->player_money >> 4)) {
 
			AiBuildRailRecursive(arf, _build_tunnel_endtile, (DiagDirection)(p[0] & 3));
 
			if (arf->depth == 1) AiCheckRailPathBetter(arf, p);
 
		}
 
	}
 
@@ -2095,13 +2096,13 @@ static void AiBuildRailRecursive(AiRailF
 
	if (GetTileZ(tile) == 0) {
 
		p += 6;
 
	} else {
 
		do {
 
			// Make sure the tile is not in the list of banned tiles and that a rail can be built here.
 
			if (!AiIsTileBanned(arf->player, tile, p[0]) &&
 
					CmdSucceeded(DoCommand(tile, arf->player->ai.railtype_to_use, p[0], DC_AUTO | DC_NO_WATER | DC_NO_RAIL_OVERLAP, CMD_BUILD_SINGLE_RAIL))) {
 
					CmdSucceeded(DoCommand(tile, _players_ai[arf->player->index].railtype_to_use, p[0], DC_AUTO | DC_NO_WATER | DC_NO_RAIL_OVERLAP, CMD_BUILD_SINGLE_RAIL))) {
 
				AiBuildRailRecursive(arf, tile, (DiagDirection)p[1]);
 
			}
 

	
 
			// At the bottom depth?
 
			if (arf->depth == 1) AiCheckRailPathBetter(arf, p);
 

	
 
@@ -2122,93 +2123,93 @@ static void AiBuildRailConstruct(Player 
 
{
 
	AiRailFinder arf;
 
	int i;
 

	
 
	// Check too much lookahead?
 
	if (AiDoFollowTrack(p)) {
 
		p->ai.state_counter = (Random()&0xE)+6; // Destruct this amount of blocks
 
		p->ai.state_mode = 1; // Start destruct
 
		_players_ai[p->index].state_counter = (Random()&0xE)+6; // Destruct this amount of blocks
 
		_players_ai[p->index].state_mode = 1; // Start destruct
 

	
 
		// Ban this tile and don't reach it for a while.
 
		AiBanTile(p, p->ai.cur_tile_a, FindFirstBit(GetRailTrackStatus(p->ai.cur_tile_a)));
 
		AiBanTile(p, _players_ai[p->index].cur_tile_a, FindFirstBit(GetRailTrackStatus(_players_ai[p->index].cur_tile_a)));
 
		return;
 
	}
 

	
 
	// Setup recursive finder and call it.
 
	arf.player = p;
 
	arf.final_tile = p->ai.cur_tile_b;
 
	arf.final_dir = p->ai.cur_dir_b;
 
	arf.final_tile = _players_ai[p->index].cur_tile_b;
 
	arf.final_dir = _players_ai[p->index].cur_dir_b;
 
	arf.depth = 0;
 
	arf.recursive_mode = 0;
 
	arf.best_ptr = NULL;
 
	arf.cur_best_dist = (uint)-1;
 
	arf.cur_best_depth = 0xff;
 
	arf.best_dist = (uint)-1;
 
	arf.best_depth = 0xff;
 
	arf.cur_best_tile = 0;
 
	arf.best_tile = 0;
 
	AiBuildRailRecursive(&arf, p->ai.cur_tile_a, p->ai.cur_dir_a);
 
	AiBuildRailRecursive(&arf, _players_ai[p->index].cur_tile_a, _players_ai[p->index].cur_dir_a);
 

	
 
	// Reached destination?
 
	if (arf.recursive_mode == 2 && arf.cur_best_depth == 0) {
 
		p->ai.state_mode = 255;
 
		_players_ai[p->index].state_mode = 255;
 
		return;
 
	}
 

	
 
	// Didn't find anything to build?
 
	if (arf.best_ptr == NULL) {
 
		// Terraform some
 
		for (i = 0; i != 5; i++) {
 
			AiDoTerraformLand(p->ai.cur_tile_a, p->ai.cur_dir_a, 3, 0);
 
			AiDoTerraformLand(_players_ai[p->index].cur_tile_a, _players_ai[p->index].cur_dir_a, 3, 0);
 
		}
 

	
 
		if (++p->ai.state_counter == 21) {
 
			p->ai.state_counter = 40;
 
			p->ai.state_mode = 1;
 
		if (++_players_ai[p->index].state_counter == 21) {
 
			_players_ai[p->index].state_counter = 40;
 
			_players_ai[p->index].state_mode = 1;
 

	
 
			// Ban this tile
 
			AiBanTile(p, p->ai.cur_tile_a, FindFirstBit(GetRailTrackStatus(p->ai.cur_tile_a)));
 
			AiBanTile(p, _players_ai[p->index].cur_tile_a, FindFirstBit(GetRailTrackStatus(_players_ai[p->index].cur_tile_a)));
 
		}
 
		return;
 
	}
 

	
 
	p->ai.cur_tile_a += TileOffsByDiagDir(p->ai.cur_dir_a);
 
	_players_ai[p->index].cur_tile_a += TileOffsByDiagDir(_players_ai[p->index].cur_dir_a);
 

	
 
	if (arf.best_ptr[0] & 0x80) {
 
		int i;
 
		int32 bridge_len = GetBridgeLength(arf.bridge_end_tile, p->ai.cur_tile_a);
 
		int32 bridge_len = GetBridgeLength(arf.bridge_end_tile, _players_ai[p->index].cur_tile_a);
 

	
 
		/* Figure out which (rail)bridge type to build
 
		 * start with best bridge, then go down to worse and worse bridges
 
		 * unnecessary to check for worst bridge (i=0), since AI will always build
 
		 * that. AI is so fucked up that fixing this small thing will probably not
 
		 * solve a thing
 
		 */
 
		for (i = MAX_BRIDGES - 1; i != 0; i--) {
 
			if (CheckBridge_Stuff(i, bridge_len)) {
 
				CommandCost cost = DoCommand(arf.bridge_end_tile, p->ai.cur_tile_a, i | (p->ai.railtype_to_use << 8), DC_AUTO, CMD_BUILD_BRIDGE);
 
				CommandCost cost = DoCommand(arf.bridge_end_tile, _players_ai[p->index].cur_tile_a, i | (_players_ai[p->index].railtype_to_use << 8), DC_AUTO, CMD_BUILD_BRIDGE);
 
				if (CmdSucceeded(cost) && cost.GetCost() < (p->player_money >> 5)) break;
 
			}
 
		}
 

	
 
		// Build it
 
		DoCommand(arf.bridge_end_tile, p->ai.cur_tile_a, i | (p->ai.railtype_to_use << 8), DC_AUTO | DC_EXEC, CMD_BUILD_BRIDGE);
 

	
 
		p->ai.cur_tile_a = arf.bridge_end_tile;
 
		p->ai.state_counter = 0;
 
		DoCommand(arf.bridge_end_tile, _players_ai[p->index].cur_tile_a, i | (_players_ai[p->index].railtype_to_use << 8), DC_AUTO | DC_EXEC, CMD_BUILD_BRIDGE);
 

	
 
		_players_ai[p->index].cur_tile_a = arf.bridge_end_tile;
 
		_players_ai[p->index].state_counter = 0;
 
	} else if (arf.best_ptr[0] & 0x40) {
 
		// tunnel
 
		DoCommand(p->ai.cur_tile_a, p->ai.railtype_to_use, 0, DC_AUTO | DC_EXEC, CMD_BUILD_TUNNEL);
 
		p->ai.cur_tile_a = _build_tunnel_endtile;
 
		p->ai.state_counter = 0;
 
		DoCommand(_players_ai[p->index].cur_tile_a, _players_ai[p->index].railtype_to_use, 0, DC_AUTO | DC_EXEC, CMD_BUILD_TUNNEL);
 
		_players_ai[p->index].cur_tile_a = _build_tunnel_endtile;
 
		_players_ai[p->index].state_counter = 0;
 
	} else {
 
		// rail
 
		p->ai.cur_dir_a = (DiagDirection)(arf.best_ptr[1] & 3);
 
		DoCommand(p->ai.cur_tile_a, p->ai.railtype_to_use, arf.best_ptr[0],
 
		_players_ai[p->index].cur_dir_a = (DiagDirection)(arf.best_ptr[1] & 3);
 
		DoCommand(_players_ai[p->index].cur_tile_a, _players_ai[p->index].railtype_to_use, arf.best_ptr[0],
 
			DC_EXEC | DC_AUTO | DC_NO_WATER | DC_NO_RAIL_OVERLAP, CMD_BUILD_SINGLE_RAIL);
 
		p->ai.state_counter = 0;
 
		_players_ai[p->index].state_counter = 0;
 
	}
 

	
 
	if (arf.best_tile != 0) {
 
		for (i = 0; i != 2; i++) {
 
			AiDoTerraformLand(arf.best_tile, arf.best_dir, 3, 0);
 
		}
 
@@ -2217,40 +2218,40 @@ static void AiBuildRailConstruct(Player 
 

	
 
static bool AiRemoveTileAndGoForward(Player *p)
 
{
 
	byte b;
 
	int bit;
 
	const byte *ptr;
 
	TileIndex tile = p->ai.cur_tile_a;
 
	TileIndex tile = _players_ai[p->index].cur_tile_a;
 
	TileIndex tilenew;
 

	
 
	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
 
		if (IsTunnel(tile)) {
 
			// Clear the tunnel and continue at the other side of it.
 
			if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR)))
 
				return false;
 
			p->ai.cur_tile_a = TILE_MASK(_build_tunnel_endtile - TileOffsByDiagDir(p->ai.cur_dir_a));
 
			_players_ai[p->index].cur_tile_a = TILE_MASK(_build_tunnel_endtile - TileOffsByDiagDir(_players_ai[p->index].cur_dir_a));
 
			return true;
 
		} else {
 
			// Check if the bridge points in the right direction.
 
			// This is not really needed the first place AiRemoveTileAndGoForward is called.
 
			if (DiagDirToAxis(GetTunnelBridgeDirection(tile)) != (p->ai.cur_dir_a & 1)) return false;
 
			if (DiagDirToAxis(GetTunnelBridgeDirection(tile)) != (_players_ai[p->index].cur_dir_a & 1)) return false;
 

	
 
			tile = GetOtherBridgeEnd(tile);
 

	
 
			tilenew = TILE_MASK(tile - TileOffsByDiagDir(p->ai.cur_dir_a));
 
			tilenew = TILE_MASK(tile - TileOffsByDiagDir(_players_ai[p->index].cur_dir_a));
 
			// And clear the bridge.
 
			if (CmdFailed(DoCommand(tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR)))
 
				return false;
 
			p->ai.cur_tile_a = tilenew;
 
			_players_ai[p->index].cur_tile_a = tilenew;
 
			return true;
 
		}
 
	}
 

	
 
	// Find the railtype at the position. Quit if no rail there.
 
	b = GetRailTrackStatus(tile) & _dir_table_3[p->ai.cur_dir_a];
 
	b = GetRailTrackStatus(tile) & _dir_table_3[_players_ai[p->index].cur_dir_a];
 
	if (b == 0) return false;
 

	
 
	// Convert into a bit position that CMD_REMOVE_SINGLE_RAIL expects.
 
	bit = FindFirstBit(b);
 

	
 
	// Then remove and signals if there are any.
 
@@ -2261,41 +2262,41 @@ static bool AiRemoveTileAndGoForward(Pla
 

	
 
	// And also remove the rail.
 
	if (CmdFailed(DoCommand(tile, 0, bit, DC_EXEC, CMD_REMOVE_SINGLE_RAIL)))
 
		return false;
 

	
 
	// Find the direction at the other edge of the rail.
 
	ptr = _ai_table_15[ReverseDiagDir(p->ai.cur_dir_a)];
 
	ptr = _ai_table_15[ReverseDiagDir(_players_ai[p->index].cur_dir_a)];
 
	while (ptr[0] != bit) ptr += 2;
 
	p->ai.cur_dir_a = ReverseDiagDir((DiagDirection)ptr[1]);
 
	_players_ai[p->index].cur_dir_a = ReverseDiagDir((DiagDirection)ptr[1]);
 

	
 
	// And then also switch tile.
 
	p->ai.cur_tile_a = TILE_MASK(p->ai.cur_tile_a - TileOffsByDiagDir(p->ai.cur_dir_a));
 
	_players_ai[p->index].cur_tile_a = TILE_MASK(_players_ai[p->index].cur_tile_a - TileOffsByDiagDir(_players_ai[p->index].cur_dir_a));
 

	
 
	return true;
 
}
 

	
 

	
 
static void AiBuildRailDestruct(Player *p)
 
{
 
	// Decrease timeout.
 
	if (!--p->ai.state_counter) {
 
		p->ai.state_mode = 2;
 
		p->ai.state_counter = 0;
 
	if (!--_players_ai[p->index].state_counter) {
 
		_players_ai[p->index].state_mode = 2;
 
		_players_ai[p->index].state_counter = 0;
 
	}
 

	
 
	// Don't do anything if the destination is already reached.
 
	if (p->ai.cur_tile_a == p->ai.start_tile_a) return;
 
	if (_players_ai[p->index].cur_tile_a == _players_ai[p->index].start_tile_a) return;
 

	
 
	AiRemoveTileAndGoForward(p);
 
}
 

	
 

	
 
static void AiBuildRail(Player *p)
 
{
 
	switch (p->ai.state_mode) {
 
	switch (_players_ai[p->index].state_mode) {
 
		case 0: // Construct mode, build new rail.
 
			AiBuildRailConstruct(p);
 
			break;
 

	
 
		case 1: // Destruct mode, destroy the rail currently built.
 
			AiBuildRailDestruct(p);
 
@@ -2303,18 +2304,18 @@ static void AiBuildRail(Player *p)
 

	
 
		case 2: {
 
			uint i;
 

	
 
			// Terraform some and then try building again.
 
			for (i = 0; i != 4; i++) {
 
				AiDoTerraformLand(p->ai.cur_tile_a, p->ai.cur_dir_a, 3, 0);
 
				AiDoTerraformLand(_players_ai[p->index].cur_tile_a, _players_ai[p->index].cur_dir_a, 3, 0);
 
			}
 

	
 
			if (++p->ai.state_counter == 4) {
 
				p->ai.state_counter = 0;
 
				p->ai.state_mode = 0;
 
			if (++_players_ai[p->index].state_counter == 4) {
 
				_players_ai[p->index].state_counter = 0;
 
				_players_ai[p->index].state_mode = 0;
 
			}
 
		}
 

	
 
		default: break;
 
	}
 
}
 
@@ -2325,75 +2326,75 @@ static void AiStateBuildRail(Player *p)
 
	AiBuildRec *aib;
 
	byte cmd;
 
	TileIndex tile;
 
	DiagDirection dir;
 

	
 
	// time out?
 
	if (++p->ai.timeout_counter == 1388) {
 
		p->ai.state = AIS_DELETE_RAIL_BLOCKS;
 
	if (++_players_ai[p->index].timeout_counter == 1388) {
 
		_players_ai[p->index].state = AIS_DELETE_RAIL_BLOCKS;
 
		return;
 
	}
 

	
 
	// Currently building a rail between two points?
 
	if (p->ai.state_mode != 255) {
 
	if (_players_ai[p->index].state_mode != 255) {
 
		AiBuildRail(p);
 

	
 
		// Alternate between edges
 
		Swap(p->ai.start_tile_a, p->ai.start_tile_b);
 
		Swap(p->ai.cur_tile_a,   p->ai.cur_tile_b);
 
		Swap(p->ai.start_dir_a,  p->ai.start_dir_b);
 
		Swap(p->ai.cur_dir_a,    p->ai.cur_dir_b);
 
		Swap(_players_ai[p->index].start_tile_a, _players_ai[p->index].start_tile_b);
 
		Swap(_players_ai[p->index].cur_tile_a,   _players_ai[p->index].cur_tile_b);
 
		Swap(_players_ai[p->index].start_dir_a,  _players_ai[p->index].start_dir_b);
 
		Swap(_players_ai[p->index].cur_dir_a,    _players_ai[p->index].cur_dir_b);
 
		return;
 
	}
 

	
 
	// Now, find two new points to build between
 
	num = p->ai.num_build_rec;
 
	aib = &p->ai.src;
 
	num = _players_ai[p->index].num_build_rec;
 
	aib = &_players_ai[p->index].src;
 

	
 
	for (;;) {
 
		cmd = aib->buildcmd_a;
 
		aib->buildcmd_a = 255;
 
		if (cmd != 255) break;
 

	
 
		cmd = aib->buildcmd_b;
 
		aib->buildcmd_b = 255;
 
		if (cmd != 255) break;
 

	
 
		aib++;
 
		if (--num == 0) {
 
			p->ai.state = AIS_BUILD_RAIL_VEH;
 
			p->ai.state_counter = 0; // timeout
 
			_players_ai[p->index].state = AIS_BUILD_RAIL_VEH;
 
			_players_ai[p->index].state_counter = 0; // timeout
 
			return;
 
		}
 
	}
 

	
 
	// Find first edge to build from.
 
	tile = AiGetEdgeOfDefaultRailBlock(aib->cur_building_rule, aib->use_tile, cmd & 3, &dir);
 
	p->ai.start_tile_a = tile;
 
	p->ai.cur_tile_a = tile;
 
	p->ai.start_dir_a = dir;
 
	p->ai.cur_dir_a = dir;
 
	_players_ai[p->index].start_tile_a = tile;
 
	_players_ai[p->index].cur_tile_a = tile;
 
	_players_ai[p->index].start_dir_a = dir;
 
	_players_ai[p->index].cur_dir_a = dir;
 
	DoCommand(TILE_MASK(tile + TileOffsByDiagDir(dir)), 0, (dir & 1) ? 1 : 0, DC_EXEC, CMD_REMOVE_SINGLE_RAIL);
 

	
 
	assert(TILE_MASK(tile) != 0xFF00);
 

	
 
	// Find second edge to build to
 
	aib = (&p->ai.src) + ((cmd >> 4) & 0xF);
 
	aib = (&_players_ai[p->index].src) + ((cmd >> 4) & 0xF);
 
	tile = AiGetEdgeOfDefaultRailBlock(aib->cur_building_rule, aib->use_tile, (cmd >> 2) & 3, &dir);
 
	p->ai.start_tile_b = tile;
 
	p->ai.cur_tile_b = tile;
 
	p->ai.start_dir_b = dir;
 
	p->ai.cur_dir_b = dir;
 
	_players_ai[p->index].start_tile_b = tile;
 
	_players_ai[p->index].cur_tile_b = tile;
 
	_players_ai[p->index].start_dir_b = dir;
 
	_players_ai[p->index].cur_dir_b = dir;
 
	DoCommand(TILE_MASK(tile + TileOffsByDiagDir(dir)), 0, (dir & 1) ? 1 : 0, DC_EXEC, CMD_REMOVE_SINGLE_RAIL);
 

	
 
	assert(TILE_MASK(tile) != 0xFF00);
 

	
 
	// And setup state.
 
	p->ai.state_mode = 2;
 
	p->ai.state_counter = 0;
 
	p->ai.banned_tile_count = 0;
 
	_players_ai[p->index].state_mode = 2;
 
	_players_ai[p->index].state_counter = 0;
 
	_players_ai[p->index].banned_tile_count = 0;
 
}
 

	
 
static StationID AiGetStationIdByDef(TileIndex tile, int id)
 
{
 
	const AiDefaultBlockData *p = _default_rail_track_data[id]->data;
 
	while (p->mode != 1) p++;
 
@@ -2441,117 +2442,117 @@ static void AiStateBuildRailVeh(Player *
 
	int i;
 
	CargoID cargo;
 
	CommandCost cost;
 
	Vehicle *v;
 
	VehicleID loco_id;
 

	
 
	ptr = _default_rail_track_data[p->ai.src.cur_building_rule]->data;
 
	ptr = _default_rail_track_data[_players_ai[p->index].src.cur_building_rule]->data;
 
	while (ptr->mode != 0) ptr++;
 

	
 
	tile = TILE_ADD(p->ai.src.use_tile, ToTileIndexDiff(ptr->tileoffs));
 

	
 

	
 
	cargo = p->ai.cargo_type;
 
	tile = TILE_ADD(_players_ai[p->index].src.use_tile, ToTileIndexDiff(ptr->tileoffs));
 

	
 

	
 
	cargo = _players_ai[p->index].cargo_type;
 
	for (i = 0;;) {
 
		if (p->ai.wagon_list[i] == INVALID_VEHICLE) {
 
			veh = AiFindBestWagon(cargo, p->ai.railtype_to_use);
 
		if (_players_ai[p->index].wagon_list[i] == INVALID_VEHICLE) {
 
			veh = AiFindBestWagon(cargo, _players_ai[p->index].railtype_to_use);
 
			/* veh will return INVALID_ENGINE if no suitable wagon is available.
 
			 * We shall treat this in the same way as having no money */
 
			if (veh == INVALID_ENGINE) goto handle_nocash;
 
			cost = DoCommand(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE);
 
			if (CmdFailed(cost)) goto handle_nocash;
 
			p->ai.wagon_list[i] = _new_vehicle_id;
 
			p->ai.wagon_list[i + 1] = INVALID_VEHICLE;
 
			_players_ai[p->index].wagon_list[i] = _new_vehicle_id;
 
			_players_ai[p->index].wagon_list[i + 1] = INVALID_VEHICLE;
 
			return;
 
		}
 
		if (cargo == CT_MAIL) cargo = CT_PASSENGERS;
 
		if (++i == p->ai.num_wagons * 2 - 1) break;
 
		if (++i == _players_ai[p->index].num_wagons * 2 - 1) break;
 
	}
 

	
 
	// Which locomotive to build?
 
	veh = AiChooseTrainToBuild(p->ai.railtype_to_use, p->player_money, cargo != CT_PASSENGERS ? 1 : 0, tile);
 
	veh = AiChooseTrainToBuild(_players_ai[p->index].railtype_to_use, p->player_money, cargo != CT_PASSENGERS ? 1 : 0, tile);
 
	if (veh == INVALID_ENGINE) {
 
handle_nocash:
 
		// after a while, if AI still doesn't have cash, get out of this block by selling the wagons.
 
		if (++p->ai.state_counter == 1000) {
 
			for (i = 0; p->ai.wagon_list[i] != INVALID_VEHICLE; i++) {
 
				cost = DoCommand(tile, p->ai.wagon_list[i], 0, DC_EXEC, CMD_SELL_RAIL_WAGON);
 
		if (++_players_ai[p->index].state_counter == 1000) {
 
			for (i = 0; _players_ai[p->index].wagon_list[i] != INVALID_VEHICLE; i++) {
 
				cost = DoCommand(tile, _players_ai[p->index].wagon_list[i], 0, DC_EXEC, CMD_SELL_RAIL_WAGON);
 
				assert(CmdSucceeded(cost));
 
			}
 
			p->ai.state = AIS_0;
 
			_players_ai[p->index].state = AIS_0;
 
		}
 
		return;
 
	}
 

	
 
	// Try to build the locomotive
 
	cost = DoCommand(tile, veh, 0, DC_EXEC, CMD_BUILD_RAIL_VEHICLE);
 
	assert(CmdSucceeded(cost));
 
	loco_id = _new_vehicle_id;
 

	
 
	// Sell a vehicle if the train is double headed.
 
	v = GetVehicle(loco_id);
 
	if (v->Next() != NULL) {
 
		i = p->ai.wagon_list[p->ai.num_wagons * 2 - 2];
 
		p->ai.wagon_list[p->ai.num_wagons * 2 - 2] = INVALID_VEHICLE;
 
		i = _players_ai[p->index].wagon_list[_players_ai[p->index].num_wagons * 2 - 2];
 
		_players_ai[p->index].wagon_list[_players_ai[p->index].num_wagons * 2 - 2] = INVALID_VEHICLE;
 
		DoCommand(tile, i, 0, DC_EXEC, CMD_SELL_RAIL_WAGON);
 
	}
 

	
 
	// Move the wagons onto the train
 
	for (i = 0; p->ai.wagon_list[i] != INVALID_VEHICLE; i++) {
 
		DoCommand(tile, p->ai.wagon_list[i] | (loco_id << 16), 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
 
	for (i = 0; _players_ai[p->index].wagon_list[i] != INVALID_VEHICLE; i++) {
 
		DoCommand(tile, _players_ai[p->index].wagon_list[i] | (loco_id << 16), 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
 
	}
 

	
 
	for (i = 0; p->ai.order_list_blocks[i] != 0xFF; i++) {
 
		const AiBuildRec* aib = &p->ai.src + p->ai.order_list_blocks[i];
 
	for (i = 0; _players_ai[p->index].order_list_blocks[i] != 0xFF; i++) {
 
		const AiBuildRec* aib = &_players_ai[p->index].src + _players_ai[p->index].order_list_blocks[i];
 
		bool is_pass = (
 
			p->ai.cargo_type == CT_PASSENGERS ||
 
			p->ai.cargo_type == CT_MAIL ||
 
			(_opt.landscape == LT_TEMPERATE && p->ai.cargo_type == CT_VALUABLES)
 
			_players_ai[p->index].cargo_type == CT_PASSENGERS ||
 
			_players_ai[p->index].cargo_type == CT_MAIL ||
 
			(_opt.landscape == LT_TEMPERATE && _players_ai[p->index].cargo_type == CT_VALUABLES)
 
		);
 
		Order order;
 

	
 
		order.type = OT_GOTO_STATION;
 
		order.flags = 0;
 
		order.dest = AiGetStationIdByDef(aib->use_tile, aib->cur_building_rule);
 

	
 
		if (!is_pass && i == 1) order.flags |= OF_UNLOAD;
 
		if (p->ai.num_want_fullload != 0 && (is_pass || i == 0))
 
		if (_players_ai[p->index].num_want_fullload != 0 && (is_pass || i == 0))
 
			order.flags |= OF_FULL_LOAD;
 

	
 
		DoCommand(0, loco_id + (i << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
 
	}
 

	
 
	DoCommand(0, loco_id, 0, DC_EXEC, CMD_START_STOP_TRAIN);
 

	
 
	DoCommand(0, loco_id, _ai_service_interval, DC_EXEC, CMD_CHANGE_SERVICE_INT);
 

	
 
	if (p->ai.num_want_fullload != 0) p->ai.num_want_fullload--;
 

	
 
	if (--p->ai.num_loco_to_build != 0) {
 
//		p->ai.loco_id = INVALID_VEHICLE;
 
		p->ai.wagon_list[0] = INVALID_VEHICLE;
 
	if (_players_ai[p->index].num_want_fullload != 0) _players_ai[p->index].num_want_fullload--;
 

	
 
	if (--_players_ai[p->index].num_loco_to_build != 0) {
 
//		_players_ai[p->index].loco_id = INVALID_VEHICLE;
 
		_players_ai[p->index].wagon_list[0] = INVALID_VEHICLE;
 
	} else {
 
		p->ai.state = AIS_0;
 
		_players_ai[p->index].state = AIS_0;
 
	}
 
}
 

	
 
static void AiStateDeleteRailBlocks(Player *p)
 
{
 
	const AiBuildRec* aib = &p->ai.src;
 
	uint num = p->ai.num_build_rec;
 
	const AiBuildRec* aib = &_players_ai[p->index].src;
 
	uint num = _players_ai[p->index].num_build_rec;
 

	
 
	do {
 
		const AiDefaultBlockData* b;
 

	
 
		if (aib->cur_building_rule == 255) continue;
 
		for (b = _default_rail_track_data[aib->cur_building_rule]->data; b->mode != 4; b++) {
 
			DoCommand(TILE_ADD(aib->use_tile, ToTileIndexDiff(b->tileoffs)), 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
		}
 
	} while (++aib, --num);
 

	
 
	p->ai.state = AIS_0;
 
	_players_ai[p->index].state = AIS_0;
 
}
 

	
 
static bool AiCheckRoadResources(TileIndex tile, const AiDefaultBlockData *p, byte cargo)
 
{
 
	uint values[NUM_CARGO];
 
	int rad;
 
@@ -2674,14 +2675,14 @@ clear_town_stuff:;
 
	return total_cost;
 
}
 

	
 
// Make sure the blocks are not too close to each other
 
static bool AiCheckBlockDistances(Player *p, TileIndex tile)
 
{
 
	const AiBuildRec* aib = &p->ai.src;
 
	uint num = p->ai.num_build_rec;
 
	const AiBuildRec* aib = &_players_ai[p->index].src;
 
	uint num = _players_ai[p->index].num_build_rec;
 

	
 
	do {
 
		if (aib->cur_building_rule != 255) {
 
			if (DistanceManhattan(aib->use_tile, tile) < 9) return false;
 
		}
 
	} while (++aib, --num);
 
@@ -2696,22 +2697,22 @@ static void AiStateBuildDefaultRoadBlock
 
	int j;
 
	AiBuildRec *aib;
 
	int rule;
 
	CommandCost cost;
 

	
 
	// time out?
 
	if (++p->ai.timeout_counter == 1388) {
 
		p->ai.state = AIS_DELETE_RAIL_BLOCKS;
 
	if (++_players_ai[p->index].timeout_counter == 1388) {
 
		_players_ai[p->index].state = AIS_DELETE_RAIL_BLOCKS;
 
		return;
 
	}
 

	
 
	// do the following 8 times
 
	for (i = 0; i != 8; i++) {
 
		// check if we can build the default track
 
		aib = &p->ai.src;
 
		j = p->ai.num_build_rec;
 
		aib = &_players_ai[p->index].src;
 
		j = _players_ai[p->index].num_build_rec;
 
		do {
 
			// this item has already been built?
 
			if (aib->cur_building_rule != 255) continue;
 

	
 
			// adjust the coordinate randomly,
 
			// to make sure that we find a position.
 
@@ -2721,19 +2722,19 @@ static void AiStateBuildDefaultRoadBlock
 
			rule = AiFindBestDefaultRoadBlock(
 
				aib->use_tile, aib->direction, aib->cargo, &cost
 
			);
 

	
 
			if (rule == -1) {
 
				// cannot build, terraform after a while
 
				if (p->ai.state_counter >= 600) {
 
					AiDoTerraformLand(aib->use_tile, (DiagDirection)(Random() & 3), 3, (int8)p->ai.state_mode);
 
				if (_players_ai[p->index].state_counter >= 600) {
 
					AiDoTerraformLand(aib->use_tile, (DiagDirection)(Random() & 3), 3, (int8)_players_ai[p->index].state_mode);
 
				}
 
				// also try the other terraform direction
 
				if (++p->ai.state_counter >= 1000) {
 
					p->ai.state_counter = 0;
 
					p->ai.state_mode = -p->ai.state_mode;
 
				if (++_players_ai[p->index].state_counter >= 1000) {
 
					_players_ai[p->index].state_counter = 0;
 
					_players_ai[p->index].state_mode = -_players_ai[p->index].state_mode;
 
				}
 
			} else if (CheckPlayerHasMoney(cost) && AiCheckBlockDistances(p, aib->use_tile)) {
 
				CommandCost r;
 

	
 
				// player has money, build it.
 
				aib->cur_building_rule = rule;
 
@@ -2746,21 +2747,21 @@ static void AiStateBuildDefaultRoadBlock
 
				assert(CmdSucceeded(r));
 
			}
 
		} while (++aib, --j);
 
	}
 

	
 
	// check if we're done with all of them
 
	aib = &p->ai.src;
 
	j = p->ai.num_build_rec;
 
	aib = &_players_ai[p->index].src;
 
	j = _players_ai[p->index].num_build_rec;
 
	do {
 
		if (aib->cur_building_rule == 255) return;
 
	} while (++aib, --j);
 

	
 
	// yep, all are done. switch state to the rail building state.
 
	p->ai.state = AIS_BUILD_ROAD;
 
	p->ai.state_mode = 255;
 
	_players_ai[p->index].state = AIS_BUILD_ROAD;
 
	_players_ai[p->index].state_mode = 255;
 
}
 

	
 
struct AiRoadFinder {
 
	TileIndex final_tile;
 
	DiagDirection final_dir;
 
	byte depth;
 
@@ -2851,17 +2852,17 @@ static const uint16 _ai_road_table_and[4
 
};
 

	
 
static bool AiCheckRoadFinished(Player *p)
 
{
 
	AiRoadEnum are;
 
	TileIndex tile;
 
	DiagDirection dir = p->ai.cur_dir_a;
 
	DiagDirection dir = _players_ai[p->index].cur_dir_a;
 
	uint32 bits;
 

	
 
	are.dest = p->ai.cur_tile_b;
 
	tile = TILE_MASK(p->ai.cur_tile_a + TileOffsByDiagDir(dir));
 
	are.dest = _players_ai[p->index].cur_tile_b;
 
	tile = TILE_MASK(_players_ai[p->index].cur_tile_a + TileOffsByDiagDir(dir));
 

	
 
	if (IsRoadStopTile(tile) || IsTileDepotType(tile, TRANSPORT_ROAD)) return false;
 
	bits = GetTileTrackStatus(tile, TRANSPORT_ROAD, ROADTYPES_ROAD) & _ai_road_table_and[dir];
 
	if (bits == 0) return false;
 

	
 
	are.best_dist = (uint)-1;
 
@@ -2872,14 +2873,14 @@ static bool AiCheckRoadFinished(Player *
 
	}
 

	
 
	if (DistanceManhattan(tile, are.dest) <= are.best_dist) return false;
 

	
 
	if (are.best_dist == 0) return true;
 

	
 
	p->ai.cur_tile_a = are.best_tile;
 
	p->ai.cur_dir_a = _dir_by_track[are.best_track];
 
	_players_ai[p->index].cur_tile_a = are.best_tile;
 
	_players_ai[p->index].cur_dir_a = _dir_by_track[are.best_track];
 
	return false;
 
}
 

	
 

	
 
static bool AiBuildRoadHelper(TileIndex tile, int flags, int type)
 
{
 
@@ -3016,120 +3017,120 @@ static void AiBuildRoadConstruct(Player 
 
	AiRoadFinder arf;
 
	int i;
 
	TileIndex tile;
 

	
 
	// Reached destination?
 
	if (AiCheckRoadFinished(p)) {
 
		p->ai.state_mode = 255;
 
		_players_ai[p->index].state_mode = 255;
 
		return;
 
	}
 

	
 
	// Setup recursive finder and call it.
 
	arf.player = p;
 
	arf.final_tile = p->ai.cur_tile_b;
 
	arf.final_dir = p->ai.cur_dir_b;
 
	arf.final_tile = _players_ai[p->index].cur_tile_b;
 
	arf.final_dir = _players_ai[p->index].cur_dir_b;
 
	arf.depth = 0;
 
	arf.recursive_mode = 0;
 
	arf.best_ptr = NULL;
 
	arf.cur_best_dist = (uint)-1;
 
	arf.cur_best_depth = 0xff;
 
	arf.best_dist = (uint)-1;
 
	arf.best_depth =  0xff;
 
	arf.cur_best_tile = 0;
 
	arf.best_tile = 0;
 
	AiBuildRoadRecursive(&arf, p->ai.cur_tile_a, p->ai.cur_dir_a);
 
	AiBuildRoadRecursive(&arf, _players_ai[p->index].cur_tile_a, _players_ai[p->index].cur_dir_a);
 

	
 
	// Reached destination?
 
	if (arf.recursive_mode == 2 && arf.cur_best_depth == 0) {
 
		p->ai.state_mode = 255;
 
		_players_ai[p->index].state_mode = 255;
 
		return;
 
	}
 

	
 
	// Didn't find anything to build?
 
	if (arf.best_ptr == NULL) {
 
		// Terraform some
 
do_some_terraform:
 
		for (i = 0; i != 5; i++)
 
			AiDoTerraformLand(p->ai.cur_tile_a, p->ai.cur_dir_a, 3, 0);
 

	
 
		if (++p->ai.state_counter == 21) {
 
			p->ai.state_mode = 1;
 

	
 
			p->ai.cur_tile_a = TILE_MASK(p->ai.cur_tile_a + TileOffsByDiagDir(p->ai.cur_dir_a));
 
			p->ai.cur_dir_a = ReverseDiagDir(p->ai.cur_dir_a);
 
			p->ai.state_counter = 0;
 
			AiDoTerraformLand(_players_ai[p->index].cur_tile_a, _players_ai[p->index].cur_dir_a, 3, 0);
 

	
 
		if (++_players_ai[p->index].state_counter == 21) {
 
			_players_ai[p->index].state_mode = 1;
 

	
 
			_players_ai[p->index].cur_tile_a = TILE_MASK(_players_ai[p->index].cur_tile_a + TileOffsByDiagDir(_players_ai[p->index].cur_dir_a));
 
			_players_ai[p->index].cur_dir_a = ReverseDiagDir(_players_ai[p->index].cur_dir_a);
 
			_players_ai[p->index].state_counter = 0;
 
		}
 
		return;
 
	}
 

	
 
	tile = TILE_MASK(p->ai.cur_tile_a + TileOffsByDiagDir(p->ai.cur_dir_a));
 
	tile = TILE_MASK(_players_ai[p->index].cur_tile_a + TileOffsByDiagDir(_players_ai[p->index].cur_dir_a));
 

	
 
	if (arf.best_ptr[0] & 0x80) {
 
		int i;
 
		int32 bridge_len;
 
		p->ai.cur_tile_a = arf.bridge_end_tile;
 
		bridge_len = GetBridgeLength(tile, p->ai.cur_tile_a); // tile
 
		_players_ai[p->index].cur_tile_a = arf.bridge_end_tile;
 
		bridge_len = GetBridgeLength(tile, _players_ai[p->index].cur_tile_a); // tile
 

	
 
		/* Figure out what (road)bridge type to build
 
		 * start with best bridge, then go down to worse and worse bridges
 
		 * unnecessary to check for worse bridge (i=0), since AI will always build that.
 
		 *AI is so fucked up that fixing this small thing will probably not solve a thing
 
		 */
 
		for (i = 10; i != 0; i--) {
 
			if (CheckBridge_Stuff(i, bridge_len)) {
 
				CommandCost cost = DoCommand(tile, p->ai.cur_tile_a, i + ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO, CMD_BUILD_BRIDGE);
 
				CommandCost cost = DoCommand(tile, _players_ai[p->index].cur_tile_a, i + ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO, CMD_BUILD_BRIDGE);
 
				if (CmdSucceeded(cost) && cost.GetCost() < (p->player_money >> 5)) break;
 
			}
 
		}
 

	
 
		// Build it
 
		DoCommand(tile, p->ai.cur_tile_a, i + ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO | DC_EXEC, CMD_BUILD_BRIDGE);
 

	
 
		p->ai.state_counter = 0;
 
		DoCommand(tile, _players_ai[p->index].cur_tile_a, i + ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO | DC_EXEC, CMD_BUILD_BRIDGE);
 

	
 
		_players_ai[p->index].state_counter = 0;
 
	} else if (arf.best_ptr[0] & 0x40) {
 
		// tunnel
 
		DoCommand(tile, 0x200, 0, DC_AUTO | DC_EXEC, CMD_BUILD_TUNNEL);
 
		p->ai.cur_tile_a = _build_tunnel_endtile;
 
		p->ai.state_counter = 0;
 
		_players_ai[p->index].cur_tile_a = _build_tunnel_endtile;
 
		_players_ai[p->index].state_counter = 0;
 
	} else {
 
		// road
 
		if (!AiBuildRoadHelper(tile, DC_EXEC | DC_AUTO | DC_NO_WATER | DC_AI_BUILDING, arf.best_ptr[0]))
 
			goto do_some_terraform;
 

	
 
		p->ai.cur_dir_a = (DiagDirection)(arf.best_ptr[1] & 3);
 
		p->ai.cur_tile_a = tile;
 
		p->ai.state_counter = 0;
 
		_players_ai[p->index].cur_dir_a = (DiagDirection)(arf.best_ptr[1] & 3);
 
		_players_ai[p->index].cur_tile_a = tile;
 
		_players_ai[p->index].state_counter = 0;
 
	}
 

	
 
	if (arf.best_tile != 0) {
 
		for (i = 0; i != 2; i++)
 
			AiDoTerraformLand(arf.best_tile, arf.best_dir, 3, 0);
 
	}
 
}
 

	
 

	
 
static void AiBuildRoad(Player *p)
 
{
 
	if (p->ai.state_mode < 1) {
 
	if (_players_ai[p->index].state_mode < 1) {
 
		// Construct mode, build new road.
 
		AiBuildRoadConstruct(p);
 
	} else if (p->ai.state_mode == 1) {
 
	} else if (_players_ai[p->index].state_mode == 1) {
 
		// Destruct mode, not implemented for roads.
 
		p->ai.state_mode = 2;
 
		p->ai.state_counter = 0;
 
	} else if (p->ai.state_mode == 2) {
 
		_players_ai[p->index].state_mode = 2;
 
		_players_ai[p->index].state_counter = 0;
 
	} else if (_players_ai[p->index].state_mode == 2) {
 
		uint i;
 

	
 
		// Terraform some and then try building again.
 
		for (i = 0; i != 4; i++) {
 
			AiDoTerraformLand(p->ai.cur_tile_a, p->ai.cur_dir_a, 3, 0);
 
			AiDoTerraformLand(_players_ai[p->index].cur_tile_a, _players_ai[p->index].cur_dir_a, 3, 0);
 
		}
 

	
 
		if (++p->ai.state_counter == 4) {
 
			p->ai.state_counter = 0;
 
			p->ai.state_mode = 0;
 
		if (++_players_ai[p->index].state_counter == 4) {
 
			_players_ai[p->index].state_counter = 0;
 
			_players_ai[p->index].state_mode = 0;
 
		}
 
	}
 
}
 

	
 
static TileIndex AiGetRoadBlockEdge(byte rule, TileIndex tile, DiagDirection *dir)
 
{
 
@@ -3146,65 +3147,65 @@ static void AiStateBuildRoad(Player *p)
 
	AiBuildRec *aib;
 
	byte cmd;
 
	TileIndex tile;
 
	DiagDirection dir;
 

	
 
	// time out?
 
	if (++p->ai.timeout_counter == 1388) {
 
		p->ai.state = AIS_DELETE_ROAD_BLOCKS;
 
	if (++_players_ai[p->index].timeout_counter == 1388) {
 
		_players_ai[p->index].state = AIS_DELETE_ROAD_BLOCKS;
 
		return;
 
	}
 

	
 
	// Currently building a road between two points?
 
	if (p->ai.state_mode != 255) {
 
	if (_players_ai[p->index].state_mode != 255) {
 
		AiBuildRoad(p);
 

	
 
		// Alternate between edges
 
		Swap(p->ai.start_tile_a, p->ai.start_tile_b);
 
		Swap(p->ai.cur_tile_a,   p->ai.cur_tile_b);
 
		Swap(p->ai.start_dir_a,  p->ai.start_dir_b);
 
		Swap(p->ai.cur_dir_a,    p->ai.cur_dir_b);
 
		Swap(_players_ai[p->index].start_tile_a, _players_ai[p->index].start_tile_b);
 
		Swap(_players_ai[p->index].cur_tile_a,   _players_ai[p->index].cur_tile_b);
 
		Swap(_players_ai[p->index].start_dir_a,  _players_ai[p->index].start_dir_b);
 
		Swap(_players_ai[p->index].cur_dir_a,    _players_ai[p->index].cur_dir_b);
 

	
 
		return;
 
	}
 

	
 
	// Now, find two new points to build between
 
	num = p->ai.num_build_rec;
 
	aib = &p->ai.src;
 
	num = _players_ai[p->index].num_build_rec;
 
	aib = &_players_ai[p->index].src;
 

	
 
	for (;;) {
 
		cmd = aib->buildcmd_a;
 
		aib->buildcmd_a = 255;
 
		if (cmd != 255) break;
 

	
 
		aib++;
 
		if (--num == 0) {
 
			p->ai.state = AIS_BUILD_ROAD_VEHICLES;
 
			_players_ai[p->index].state = AIS_BUILD_ROAD_VEHICLES;
 
			return;
 
		}
 
	}
 

	
 
	// Find first edge to build from.
 
	tile = AiGetRoadBlockEdge(aib->cur_building_rule, aib->use_tile, &dir);
 
	p->ai.start_tile_a = tile;
 
	p->ai.cur_tile_a = tile;
 
	p->ai.start_dir_a = dir;
 
	p->ai.cur_dir_a = dir;
 
	_players_ai[p->index].start_tile_a = tile;
 
	_players_ai[p->index].cur_tile_a = tile;
 
	_players_ai[p->index].start_dir_a = dir;
 
	_players_ai[p->index].cur_dir_a = dir;
 

	
 
	// Find second edge to build to
 
	aib = (&p->ai.src) + (cmd & 0xF);
 
	aib = (&_players_ai[p->index].src) + (cmd & 0xF);
 
	tile = AiGetRoadBlockEdge(aib->cur_building_rule, aib->use_tile, &dir);
 
	p->ai.start_tile_b = tile;
 
	p->ai.cur_tile_b = tile;
 
	p->ai.start_dir_b = dir;
 
	p->ai.cur_dir_b = dir;
 
	_players_ai[p->index].start_tile_b = tile;
 
	_players_ai[p->index].cur_tile_b = tile;
 
	_players_ai[p->index].start_dir_b = dir;
 
	_players_ai[p->index].cur_dir_b = dir;
 

	
 
	// And setup state.
 
	p->ai.state_mode = 2;
 
	p->ai.state_counter = 0;
 
	p->ai.banned_tile_count = 0;
 
	_players_ai[p->index].state_mode = 2;
 
	_players_ai[p->index].state_counter = 0;
 
	_players_ai[p->index].banned_tile_count = 0;
 
}
 

	
 
static StationID AiGetStationIdFromRoadBlock(TileIndex tile, int id)
 
{
 
	const AiDefaultBlockData *p = _road_default_block_data[id]->data;
 
	while (p->mode != 1) p++;
 
@@ -3216,78 +3217,78 @@ static void AiStateBuildRoadVehicles(Pla
 
	const AiDefaultBlockData *ptr;
 
	TileIndex tile;
 
	VehicleID loco_id;
 
	EngineID veh;
 
	uint i;
 

	
 
	ptr = _road_default_block_data[p->ai.src.cur_building_rule]->data;
 
	ptr = _road_default_block_data[_players_ai[p->index].src.cur_building_rule]->data;
 
	for (; ptr->mode != 0; ptr++) {}
 
	tile = TILE_ADD(p->ai.src.use_tile, ToTileIndexDiff(ptr->tileoffs));
 

	
 
	veh = AiChooseRoadVehToBuild(p->ai.cargo_type, p->player_money, tile);
 
	tile = TILE_ADD(_players_ai[p->index].src.use_tile, ToTileIndexDiff(ptr->tileoffs));
 

	
 
	veh = AiChooseRoadVehToBuild(_players_ai[p->index].cargo_type, p->player_money, tile);
 
	if (veh == INVALID_ENGINE) {
 
		p->ai.state = AIS_0;
 
		_players_ai[p->index].state = AIS_0;
 
		return;
 
	}
 

	
 
	if (CmdFailed(DoCommand(tile, veh, 0, DC_EXEC, CMD_BUILD_ROAD_VEH))) return;
 

	
 
	loco_id = _new_vehicle_id;
 

	
 
	if (GetVehicle(loco_id)->cargo_type != p->ai.cargo_type) {
 
	if (GetVehicle(loco_id)->cargo_type != _players_ai[p->index].cargo_type) {
 
		/* Cargo type doesn't match, so refit it */
 
		if (CmdFailed(DoCommand(tile, loco_id, p->ai.cargo_type, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
 
		if (CmdFailed(DoCommand(tile, loco_id, _players_ai[p->index].cargo_type, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
 
			/* Refit failed... sell the vehicle */
 
			DoCommand(tile, loco_id, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
 
			return;
 
		}
 
	}
 

	
 
	for (i = 0; p->ai.order_list_blocks[i] != 0xFF; i++) {
 
		const AiBuildRec* aib = &p->ai.src + p->ai.order_list_blocks[i];
 
	for (i = 0; _players_ai[p->index].order_list_blocks[i] != 0xFF; i++) {
 
		const AiBuildRec* aib = &_players_ai[p->index].src + _players_ai[p->index].order_list_blocks[i];
 
		bool is_pass = (
 
			p->ai.cargo_type == CT_PASSENGERS ||
 
			p->ai.cargo_type == CT_MAIL ||
 
			(_opt.landscape == LT_TEMPERATE && p->ai.cargo_type == CT_VALUABLES)
 
			_players_ai[p->index].cargo_type == CT_PASSENGERS ||
 
			_players_ai[p->index].cargo_type == CT_MAIL ||
 
			(_opt.landscape == LT_TEMPERATE && _players_ai[p->index].cargo_type == CT_VALUABLES)
 
		);
 
		Order order;
 

	
 
		order.type = OT_GOTO_STATION;
 
		order.flags = 0;
 
		order.dest = AiGetStationIdFromRoadBlock(aib->use_tile, aib->cur_building_rule);
 

	
 
		if (!is_pass && i == 1) order.flags |= OF_UNLOAD;
 
		if (p->ai.num_want_fullload != 0 && (is_pass || i == 0))
 
		if (_players_ai[p->index].num_want_fullload != 0 && (is_pass || i == 0))
 
			order.flags |= OF_FULL_LOAD;
 

	
 
		DoCommand(0, loco_id + (i << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
 
	}
 

	
 
	DoCommand(0, loco_id, 0, DC_EXEC, CMD_START_STOP_ROADVEH);
 
	DoCommand(0, loco_id, _ai_service_interval, DC_EXEC, CMD_CHANGE_SERVICE_INT);
 

	
 
	if (p->ai.num_want_fullload != 0) p->ai.num_want_fullload--;
 
	if (--p->ai.num_loco_to_build == 0) p->ai.state = AIS_0;
 
	if (_players_ai[p->index].num_want_fullload != 0) _players_ai[p->index].num_want_fullload--;
 
	if (--_players_ai[p->index].num_loco_to_build == 0) _players_ai[p->index].state = AIS_0;
 
}
 

	
 
static void AiStateDeleteRoadBlocks(Player *p)
 
{
 
	const AiBuildRec* aib = &p->ai.src;
 
	uint num = p->ai.num_build_rec;
 
	const AiBuildRec* aib = &_players_ai[p->index].src;
 
	uint num = _players_ai[p->index].num_build_rec;
 

	
 
	do {
 
		const AiDefaultBlockData* b;
 

	
 
		if (aib->cur_building_rule == 255) continue;
 
		for (b = _road_default_block_data[aib->cur_building_rule]->data; b->mode != 4; b++) {
 
			if (b->mode > 1) continue;
 
			DoCommand(TILE_ADD(aib->use_tile, ToTileIndexDiff(b->tileoffs)), 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
		}
 
	} while (++aib, --num);
 

	
 
	p->ai.state = AIS_0;
 
	_players_ai[p->index].state = AIS_0;
 
}
 

	
 

	
 
static void AiStateAirportStuff(Player *p)
 
{
 
	const Station* st;
 
@@ -3302,24 +3303,24 @@ static void AiStateAirportStuff(Player *
 

	
 
	i = 0;
 
	do {
 
		// We do this all twice - once for the source (town in the case
 
		// of oilrig route) and then for the destination (oilrig in the
 
		// case of oilrig route).
 
		aib = &p->ai.src + i;
 
		aib = &_players_ai[p->index].src + i;
 

	
 
		FOR_ALL_STATIONS(st) {
 
			// Is this an airport?
 
			if (!(st->facilities & FACIL_AIRPORT)) continue;
 

	
 
			// Do we own the airport? (Oilrigs aren't owned, though.)
 
			if (st->owner != OWNER_NONE && st->owner != _current_player) continue;
 

	
 
			AirportFTAClass::Flags flags = st->Airport()->flags;
 

	
 
			if (!(flags & (p->ai.build_kind == 1 && i == 0 ? AirportFTAClass::HELICOPTERS : AirportFTAClass::AIRPLANES))) {
 
			if (!(flags & (_players_ai[p->index].build_kind == 1 && i == 0 ? AirportFTAClass::HELICOPTERS : AirportFTAClass::AIRPLANES))) {
 
				continue;
 
			}
 

	
 
			// Dismiss airports too far away.
 
			if (DistanceMax(st->airport_tile, aib->spec_tile) > aib->rand_rng)
 
				continue;
 
@@ -3352,17 +3353,17 @@ static void AiStateAirportStuff(Player *
 
			}
 

	
 
			aib->cur_building_rule = rule;
 
			aib->use_tile = st->airport_tile;
 
			break;
 
		}
 
	} while (++i != p->ai.num_build_rec);
 

	
 
	p->ai.state = AIS_BUILD_DEFAULT_AIRPORT_BLOCKS;
 
	p->ai.state_mode = 255;
 
	p->ai.state_counter = 0;
 
	} while (++i != _players_ai[p->index].num_build_rec);
 

	
 
	_players_ai[p->index].state = AIS_BUILD_DEFAULT_AIRPORT_BLOCKS;
 
	_players_ai[p->index].state_mode = 255;
 
	_players_ai[p->index].state_counter = 0;
 
}
 

	
 
static CommandCost AiDoBuildDefaultAirportBlock(TileIndex tile, const AiDefaultBlockData *p, byte flag)
 
{
 
	uint32 avail_airports = GetValidAirports();
 
	CommandCost total_cost, ret;
 
@@ -3421,45 +3422,45 @@ static void AiStateBuildDefaultAirportBl
 
	int i, j;
 
	AiBuildRec *aib;
 
	int rule;
 
	CommandCost cost;
 

	
 
	// time out?
 
	if (++p->ai.timeout_counter == 1388) {
 
		p->ai.state = AIS_0;
 
	if (++_players_ai[p->index].timeout_counter == 1388) {
 
		_players_ai[p->index].state = AIS_0;
 
		return;
 
	}
 

	
 
	// do the following 8 times
 
	i = 8;
 
	do {
 
		// check if we can build the default
 
		aib = &p->ai.src;
 
		j = p->ai.num_build_rec;
 
		aib = &_players_ai[p->index].src;
 
		j = _players_ai[p->index].num_build_rec;
 
		do {
 
			// this item has already been built?
 
			if (aib->cur_building_rule != 255) continue;
 

	
 
			// adjust the coordinate randomly,
 
			// to make sure that we find a position.
 
			aib->use_tile = AdjustTileCoordRandomly(aib->spec_tile, aib->rand_rng);
 

	
 
			// check if the aircraft stuff can be built there.
 
			rule = AiFindBestDefaultAirportBlock(aib->use_tile, aib->cargo, p->ai.build_kind, &cost);
 
			rule = AiFindBestDefaultAirportBlock(aib->use_tile, aib->cargo, _players_ai[p->index].build_kind, &cost);
 

	
 
//			SetRedErrorSquare(aib->use_tile);
 

	
 
			if (rule == -1) {
 
				// cannot build, terraform after a while
 
				if (p->ai.state_counter >= 600) {
 
					AiDoTerraformLand(aib->use_tile, (DiagDirection)(Random() & 3), 3, (int8)p->ai.state_mode);
 
				if (_players_ai[p->index].state_counter >= 600) {
 
					AiDoTerraformLand(aib->use_tile, (DiagDirection)(Random() & 3), 3, (int8)_players_ai[p->index].state_mode);
 
				}
 
				// also try the other terraform direction
 
				if (++p->ai.state_counter >= 1000) {
 
					p->ai.state_counter = 0;
 
					p->ai.state_mode = -p->ai.state_mode;
 
				if (++_players_ai[p->index].state_counter >= 1000) {
 
					_players_ai[p->index].state_counter = 0;
 
					_players_ai[p->index].state_mode = -_players_ai[p->index].state_mode;
 
				}
 
			} else if (CheckPlayerHasMoney(cost) && AiCheckBlockDistances(p, aib->use_tile)) {
 
				// player has money, build it.
 
				CommandCost r;
 

	
 
				aib->cur_building_rule = rule;
 
@@ -3472,20 +3473,20 @@ static void AiStateBuildDefaultAirportBl
 
				assert(CmdSucceeded(r));
 
			}
 
		} while (++aib, --j);
 
	} while (--i);
 

	
 
	// check if we're done with all of them
 
	aib = &p->ai.src;
 
	j = p->ai.num_build_rec;
 
	aib = &_players_ai[p->index].src;
 
	j = _players_ai[p->index].num_build_rec;
 
	do {
 
		if (aib->cur_building_rule == 255) return;
 
	} while (++aib, --j);
 

	
 
	// yep, all are done. switch state.
 
	p->ai.state = AIS_BUILD_AIRCRAFT_VEHICLES;
 
	_players_ai[p->index].state = AIS_BUILD_AIRCRAFT_VEHICLES;
 
}
 

	
 
static StationID AiGetStationIdFromAircraftBlock(TileIndex tile, int id)
 
{
 
	const AiDefaultBlockData *p = _airport_default_block_data[id];
 
	while (p->mode != 1) p++;
 
@@ -3497,49 +3498,49 @@ static void AiStateBuildAircraftVehicles
 
	const AiDefaultBlockData *ptr;
 
	TileIndex tile;
 
	EngineID veh;
 
	int i;
 
	VehicleID loco_id;
 

	
 
	ptr = _airport_default_block_data[p->ai.src.cur_building_rule];
 
	ptr = _airport_default_block_data[_players_ai[p->index].src.cur_building_rule];
 
	for (; ptr->mode != 0; ptr++) {}
 

	
 
	tile = TILE_ADD(p->ai.src.use_tile, ToTileIndexDiff(ptr->tileoffs));
 

	
 
	veh = AiChooseAircraftToBuild(p->player_money, p->ai.build_kind != 0 ? 0 : AIR_CTOL);
 
	tile = TILE_ADD(_players_ai[p->index].src.use_tile, ToTileIndexDiff(ptr->tileoffs));
 

	
 
	veh = AiChooseAircraftToBuild(p->player_money, _players_ai[p->index].build_kind != 0 ? 0 : AIR_CTOL);
 
	if (veh == INVALID_ENGINE) return;
 

	
 
	/* XXX - Have the AI pick the hangar terminal in an airport. Eg get airport-type
 
	 * and offset to the FIRST depot because the AI picks the st->xy tile */
 
	tile += ToTileIndexDiff(GetStationByTile(tile)->Airport()->airport_depots[0]);
 
	if (CmdFailed(DoCommand(tile, veh, 0, DC_EXEC, CMD_BUILD_AIRCRAFT))) return;
 
	loco_id = _new_vehicle_id;
 

	
 
	for (i = 0; p->ai.order_list_blocks[i] != 0xFF; i++) {
 
		AiBuildRec *aib = (&p->ai.src) + p->ai.order_list_blocks[i];
 
		bool is_pass = (p->ai.cargo_type == CT_PASSENGERS || p->ai.cargo_type == CT_MAIL);
 
	for (i = 0; _players_ai[p->index].order_list_blocks[i] != 0xFF; i++) {
 
		AiBuildRec *aib = (&_players_ai[p->index].src) + _players_ai[p->index].order_list_blocks[i];
 
		bool is_pass = (_players_ai[p->index].cargo_type == CT_PASSENGERS || _players_ai[p->index].cargo_type == CT_MAIL);
 
		Order order;
 

	
 
		order.type = OT_GOTO_STATION;
 
		order.flags = 0;
 
		order.dest = AiGetStationIdFromAircraftBlock(aib->use_tile, aib->cur_building_rule);
 

	
 
		if (!is_pass && i == 1) order.flags |= OF_UNLOAD;
 
		if (p->ai.num_want_fullload != 0 && (is_pass || i == 0))
 
		if (_players_ai[p->index].num_want_fullload != 0 && (is_pass || i == 0))
 
			order.flags |= OF_FULL_LOAD;
 

	
 
		DoCommand(0, loco_id + (i << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
 
	}
 

	
 
	DoCommand(0, loco_id, 0, DC_EXEC, CMD_START_STOP_AIRCRAFT);
 

	
 
	DoCommand(0, loco_id, _ai_service_interval, DC_EXEC, CMD_CHANGE_SERVICE_INT);
 

	
 
	if (p->ai.num_want_fullload != 0) p->ai.num_want_fullload--;
 

	
 
	if (--p->ai.num_loco_to_build == 0) p->ai.state = AIS_0;
 
	if (_players_ai[p->index].num_want_fullload != 0) _players_ai[p->index].num_want_fullload--;
 

	
 
	if (--_players_ai[p->index].num_loco_to_build == 0) _players_ai[p->index].state = AIS_0;
 
}
 

	
 
static void AiStateCheckShipStuff(Player *p)
 
{
 
	/* Ships are not implemented in this (broken) AI */
 
}
 
@@ -3553,13 +3554,13 @@ static void AiStateDoShipStuff(Player *p
 
{
 
	/* Ships are not implemented in this (broken) AI */
 
}
 

	
 
static void AiStateSellVeh(Player *p)
 
{
 
	Vehicle *v = p->ai.cur_veh;
 
	Vehicle *v = _players_ai[p->index].cur_veh;
 

	
 
	if (v->owner == _current_player) {
 
		if (v->type == VEH_TRAIN) {
 

	
 
			if (!IsTileDepotType(v->tile, TRANSPORT_RAIL) || v->u.rail.track != 0x80 || !(v->vehstatus&VS_STOPPED)) {
 
				if (v->current_order.type != OT_GOTO_DEPOT)
 
@@ -3590,32 +3591,32 @@ static void AiStateSellVeh(Player *p)
 
			/* Ships are not implemented in this (broken) AI */
 
		}
 
	}
 

	
 
	goto return_to_loop;
 
going_to_depot:;
 
	if (++p->ai.state_counter <= 832) return;
 
	if (++_players_ai[p->index].state_counter <= 832) return;
 

	
 
	if (v->current_order.type == OT_GOTO_DEPOT) {
 
		v->current_order.type = OT_DUMMY;
 
		v->current_order.flags = 0;
 
		InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 
	}
 
return_to_loop:;
 
	p->ai.state = AIS_VEH_LOOP;
 
	_players_ai[p->index].state = AIS_VEH_LOOP;
 
}
 

	
 
static void AiStateRemoveStation(Player *p)
 
{
 
	// Remove stations that aren't in use by any vehicle
 
	const Order *ord;
 
	const Station *st;
 
	TileIndex tile;
 

	
 
	// Go to this state when we're done.
 
	p->ai.state = AIS_1;
 
	_players_ai[p->index].state = AIS_1;
 

	
 
	// Get a list of all stations that are in use by a vehicle
 
	byte *in_use = MallocT<byte>(GetMaxStationIndex() + 1);
 
	memset(in_use, 0, GetMaxStationIndex() + 1);
 
	FOR_ALL_ORDERS(ord) {
 
		if (ord->type == OT_GOTO_STATION) in_use[ord->dest] = 1;
 
@@ -3649,45 +3650,45 @@ is_rail_crossing:;
 

	
 
			if (rails == TRACK_BIT_HORZ || rails == TRACK_BIT_VERT) return;
 

	
 
			if (rails & TRACK_BIT_3WAY_NE) {
 
pos_0:
 
				if ((GetRailTrackStatus(TILE_MASK(tile - TileDiffXY(1, 0))) & TRACK_BIT_3WAY_SW) == 0) {
 
					p->ai.cur_dir_a = DIAGDIR_NE;
 
					p->ai.cur_tile_a = tile;
 
					p->ai.state = AIS_REMOVE_SINGLE_RAIL_TILE;
 
					_players_ai[p->index].cur_dir_a = DIAGDIR_NE;
 
					_players_ai[p->index].cur_tile_a = tile;
 
					_players_ai[p->index].state = AIS_REMOVE_SINGLE_RAIL_TILE;
 
					return;
 
				}
 
			}
 

	
 
			if (rails & TRACK_BIT_3WAY_SE) {
 
pos_1:
 
				if ((GetRailTrackStatus(TILE_MASK(tile + TileDiffXY(0, 1))) & TRACK_BIT_3WAY_NW) == 0) {
 
					p->ai.cur_dir_a = DIAGDIR_SE;
 
					p->ai.cur_tile_a = tile;
 
					p->ai.state = AIS_REMOVE_SINGLE_RAIL_TILE;
 
					_players_ai[p->index].cur_dir_a = DIAGDIR_SE;
 
					_players_ai[p->index].cur_tile_a = tile;
 
					_players_ai[p->index].state = AIS_REMOVE_SINGLE_RAIL_TILE;
 
					return;
 
				}
 
			}
 

	
 
			if (rails & TRACK_BIT_3WAY_SW) {
 
pos_2:
 
				if ((GetRailTrackStatus(TILE_MASK(tile + TileDiffXY(1, 0))) & TRACK_BIT_3WAY_NE) == 0) {
 
					p->ai.cur_dir_a = DIAGDIR_SW;
 
					p->ai.cur_tile_a = tile;
 
					p->ai.state = AIS_REMOVE_SINGLE_RAIL_TILE;
 
					_players_ai[p->index].cur_dir_a = DIAGDIR_SW;
 
					_players_ai[p->index].cur_tile_a = tile;
 
					_players_ai[p->index].state = AIS_REMOVE_SINGLE_RAIL_TILE;
 
					return;
 
				}
 
			}
 

	
 
			if (rails & TRACK_BIT_3WAY_NW) {
 
pos_3:
 
				if ((GetRailTrackStatus(TILE_MASK(tile - TileDiffXY(0, 1))) & TRACK_BIT_3WAY_SE) == 0) {
 
					p->ai.cur_dir_a = DIAGDIR_NW;
 
					p->ai.cur_tile_a = tile;
 
					p->ai.state = AIS_REMOVE_SINGLE_RAIL_TILE;
 
					_players_ai[p->index].cur_dir_a = DIAGDIR_NW;
 
					_players_ai[p->index].cur_tile_a = tile;
 
					_players_ai[p->index].state = AIS_REMOVE_SINGLE_RAIL_TILE;
 
					return;
 
				}
 
			}
 
		} else {
 
			static const byte _depot_bits[] = {0x19, 0x16, 0x25, 0x2A};
 

	
 
@@ -3752,30 +3753,30 @@ pos_3:
 
static void AiStateRemoveTrack(Player *p)
 
{
 
	/* Was 1000 for standard 8x8 maps. */
 
	int num = MapSizeX() * 4;
 

	
 
	do {
 
		TileIndex tile = ++p->ai.state_counter;
 
		TileIndex tile = ++_players_ai[p->index].state_counter;
 

	
 
		// Iterated all tiles?
 
		if (tile >= MapSize()) {
 
			p->ai.state = AIS_REMOVE_STATION;
 
			_players_ai[p->index].state = AIS_REMOVE_STATION;
 
			return;
 
		}
 

	
 
		// Remove player stuff in that tile
 
		AiRemovePlayerRailOrRoad(p, tile);
 
		if (p->ai.state != AIS_REMOVE_TRACK) return;
 
		if (_players_ai[p->index].state != AIS_REMOVE_TRACK) return;
 
	} while (--num);
 
}
 

	
 
static void AiStateRemoveSingleRailTile(Player *p)
 
{
 
	// Remove until we can't remove more.
 
	if (!AiRemoveTileAndGoForward(p)) p->ai.state = AIS_REMOVE_TRACK;
 
	if (!AiRemoveTileAndGoForward(p)) _players_ai[p->index].state = AIS_REMOVE_TRACK;
 
}
 

	
 
static AiStateAction * const _ai_actions[] = {
 
	AiCase0,
 
	AiCase1,
 
	AiStateVehLoop,
 
@@ -3946,20 +3947,91 @@ void AiDoGameLoop(Player *p)
 
			"AiStateSellVeh",
 
			"AiStateRemoveStation",
 
			"AiStateRemoveTrack",
 
			"AiStateRemoveSingleRailTile"
 
		};
 

	
 
		if (p->ai.state != old_state) {
 
		if (_players_ai[p->index].state != old_state) {
 
			if (hasdots)
 
				printf("\n");
 
			hasdots=false;
 
			printf("AiState: %s\n", _ai_state_names[old_state=p->ai.state]);
 
			printf("AiState: %s\n", _ai_state_names[old_state=_players_ai[p->index].state]);
 
		} else {
 
			printf(".");
 
			hasdots=true;
 
		}
 
	}
 
#endif
 

	
 
	_ai_actions[p->ai.state](p);
 
	_ai_actions[_players_ai[p->index].state](p);
 
}
 

	
 

	
 
static const SaveLoad _player_ai_desc[] = {
 
	    SLE_VAR(PlayerAI, state,             SLE_UINT8),
 
	    SLE_VAR(PlayerAI, tick,              SLE_UINT8),
 
	SLE_CONDVAR(PlayerAI, state_counter,     SLE_FILE_U16 | SLE_VAR_U32,  0, 12),
 
	SLE_CONDVAR(PlayerAI, state_counter,     SLE_UINT32,                 13, SL_MAX_VERSION),
 
	    SLE_VAR(PlayerAI, timeout_counter,   SLE_UINT16),
 

	
 
	    SLE_VAR(PlayerAI, state_mode,        SLE_UINT8),
 
	    SLE_VAR(PlayerAI, banned_tile_count, SLE_UINT8),
 
	    SLE_VAR(PlayerAI, railtype_to_use,   SLE_UINT8),
 

	
 
	    SLE_VAR(PlayerAI, cargo_type,        SLE_UINT8),
 
	    SLE_VAR(PlayerAI, num_wagons,        SLE_UINT8),
 
	    SLE_VAR(PlayerAI, build_kind,        SLE_UINT8),
 
	    SLE_VAR(PlayerAI, num_build_rec,     SLE_UINT8),
 
	    SLE_VAR(PlayerAI, num_loco_to_build, SLE_UINT8),
 
	    SLE_VAR(PlayerAI, num_want_fullload, SLE_UINT8),
 

	
 
	    SLE_VAR(PlayerAI, route_type_mask,   SLE_UINT8),
 

	
 
	SLE_CONDVAR(PlayerAI, start_tile_a,      SLE_FILE_U16 | SLE_VAR_U32,  0,  5),
 
	SLE_CONDVAR(PlayerAI, start_tile_a,      SLE_UINT32,                  6, SL_MAX_VERSION),
 
	SLE_CONDVAR(PlayerAI, cur_tile_a,        SLE_FILE_U16 | SLE_VAR_U32,  0,  5),
 
	SLE_CONDVAR(PlayerAI, cur_tile_a,        SLE_UINT32,                  6, SL_MAX_VERSION),
 
	    SLE_VAR(PlayerAI, start_dir_a,       SLE_UINT8),
 
	    SLE_VAR(PlayerAI, cur_dir_a,         SLE_UINT8),
 

	
 
	SLE_CONDVAR(PlayerAI, start_tile_b,      SLE_FILE_U16 | SLE_VAR_U32,  0,  5),
 
	SLE_CONDVAR(PlayerAI, start_tile_b,      SLE_UINT32,                  6, SL_MAX_VERSION),
 
	SLE_CONDVAR(PlayerAI, cur_tile_b,        SLE_FILE_U16 | SLE_VAR_U32,  0,  5),
 
	SLE_CONDVAR(PlayerAI, cur_tile_b,        SLE_UINT32,                  6, SL_MAX_VERSION),
 
	    SLE_VAR(PlayerAI, start_dir_b,       SLE_UINT8),
 
	    SLE_VAR(PlayerAI, cur_dir_b,         SLE_UINT8),
 

	
 
	    SLE_REF(PlayerAI, cur_veh,           REF_VEHICLE),
 

	
 
	    SLE_ARR(PlayerAI, wagon_list,        SLE_UINT16, 9),
 
	    SLE_ARR(PlayerAI, order_list_blocks, SLE_UINT8, 20),
 
	    SLE_ARR(PlayerAI, banned_tiles,      SLE_UINT16, 16),
 

	
 
	SLE_CONDNULL(64, 2, SL_MAX_VERSION),
 
	SLE_END()
 
};
 

	
 
static const SaveLoad _player_ai_build_rec_desc[] = {
 
	SLE_CONDVAR(AiBuildRec, spec_tile,         SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
 
	SLE_CONDVAR(AiBuildRec, spec_tile,         SLE_UINT32,                 6, SL_MAX_VERSION),
 
	SLE_CONDVAR(AiBuildRec, use_tile,          SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
 
	SLE_CONDVAR(AiBuildRec, use_tile,          SLE_UINT32,                 6, SL_MAX_VERSION),
 
	    SLE_VAR(AiBuildRec, rand_rng,          SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, cur_building_rule, SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, unk6,              SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, unk7,              SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, buildcmd_a,        SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, buildcmd_b,        SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, direction,         SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, cargo,             SLE_UINT8),
 
	SLE_END()
 
};
 

	
 

	
 
void SaveLoad_AI(PlayerID id)
 
{
 
	PlayerAI *pai = &_players_ai[id];
 
	SlObject(pai, _player_ai_desc);
 
	for (int i = 0; i != pai->num_build_rec; i++) {
 
		SlObject(&pai->src + i, _player_ai_build_rec_desc);
 
	}
 
}
 
\ No newline at end of file
src/ai/default/default.h
Show inline comments
 
/* $Id$ */
 

	
 
#ifndef DEFAULT_H
 
#define DEFAULT_H
 

	
 
void AiDoGameLoop(Player*);
 
void SaveLoad_AI(PlayerID id);
 

	
 
struct AiBuildRec {
 
	TileIndex spec_tile;
 
	TileIndex use_tile;
 
	byte rand_rng;
 
	byte cur_building_rule;
 
	byte unk6;
 
	byte unk7;
 
	byte buildcmd_a;
 
	byte buildcmd_b;
 
	byte direction;
 
	CargoID cargo;
 
};
 

	
 
struct PlayerAI {
 
	byte state;
 
	byte tick;            ///< Used to determine how often to move
 
	uint32 state_counter; ///< Can hold tile index!
 
	uint16 timeout_counter;
 

	
 
	byte state_mode;
 
	byte banned_tile_count;
 
	RailTypeByte railtype_to_use;
 

	
 
	CargoID cargo_type;
 
	byte num_wagons;
 
	byte build_kind;
 
	byte num_build_rec;
 
	byte num_loco_to_build;
 
	byte num_want_fullload;
 

	
 
	byte route_type_mask;
 

	
 
	TileIndex start_tile_a;
 
	TileIndex cur_tile_a;
 
	DiagDirectionByte cur_dir_a;
 
	DiagDirectionByte start_dir_a;
 

	
 
	TileIndex start_tile_b;
 
	TileIndex cur_tile_b;
 
	DiagDirectionByte cur_dir_b;
 
	DiagDirectionByte start_dir_b;
 

	
 
	Vehicle *cur_veh; ///< only used by some states
 

	
 
	AiBuildRec src, dst, mid1, mid2;
 

	
 
	VehicleID wagon_list[9];
 
	byte order_list_blocks[20];
 

	
 
	TileIndex banned_tiles[16];
 
	byte banned_val[16];
 
};
 

	
 
extern PlayerAI _players_ai[MAX_PLAYERS];
 

	
 
#endif
src/ai/trolly/build.cpp
Show inline comments
 
@@ -67,13 +67,13 @@ CommandCost AiNew_Build_Bridge(Player *p
 
		}
 
	}
 
	// There is only one bridge that can be built
 
	if (type2 == 0 && type != 0) type2 = type;
 

	
 
	// Now, simply, build the bridge!
 
	if (p->ainew.tbt == AI_TRAIN) {
 
	if (_players_ainew[p->index].tbt == AI_TRAIN) {
 
		return AI_DoCommand(tile_a, tile_b, (0x00 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
 
	} else {
 
		return AI_DoCommand(tile_a, tile_b, ((0x80 | ROADTYPES_ROAD) << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
 
	}
 
}
 

	
 
@@ -141,13 +141,13 @@ CommandCost AiNew_Build_RoutePart(Player
 
				if (old_dir != -1 && old_dir != dir) break;
 
				old_dir = dir;
 
				// Build the tile
 
				res = AI_DoCommand(route[part], 0, dir, flag, CMD_BUILD_SINGLE_RAIL);
 
				if (CmdFailed(res)) {
 
					// Problem.. let's just abort it all!
 
					p->ainew.state = AI_STATE_NOTHING;
 
					_players_ainew[p->index].state = AI_STATE_NOTHING;
 
					return CommandCost();
 
				}
 
				cost.AddCost(res);
 
				// Go to the next tile
 
				part++;
 
				// Check if it is still in range..
 
@@ -197,13 +197,13 @@ CommandCost AiNew_Build_RoutePart(Player
 
					// Build the tile
 
					res = AI_DoCommand(route[part], dir, 0, flag | DC_NO_WATER, CMD_BUILD_ROAD);
 
					// Currently, we ignore CMD_ERRORs!
 
					if (CmdFailed(res) && flag == DC_EXEC && !IsTileType(route[part], MP_ROAD) && !EnsureNoVehicleOnGround(route[part])) {
 
						// Problem.. let's just abort it all!
 
						DEBUG(ai, 0, "[BuidPath] route building failed at tile 0x%X, aborting", route[part]);
 
						p->ainew.state = AI_STATE_NOTHING;
 
						_players_ainew[p->index].state = AI_STATE_NOTHING;
 
						return CommandCost();
 
					}
 

	
 
					if (CmdSucceeded(res)) cost.AddCost(res);
 
				}
 
				// Go to the next tile
 
@@ -223,13 +223,13 @@ CommandCost AiNew_Build_RoutePart(Player
 

	
 

	
 
// This functions tries to find the best vehicle for this type of cargo
 
// It returns INVALID_ENGINE if not suitable engine is found
 
EngineID AiNew_PickVehicle(Player *p)
 
{
 
	if (p->ainew.tbt == AI_TRAIN) {
 
	if (_players_ainew[p->index].tbt == AI_TRAIN) {
 
		// Not supported yet
 
		return INVALID_ENGINE;
 
	} else {
 
		EngineID best_veh_index = INVALID_ENGINE;
 
		int32 best_veh_rating = 0;
 
		EngineID start = ROAD_ENGINES_INDEX;
 
@@ -241,13 +241,13 @@ EngineID AiNew_PickVehicle(Player *p)
 
			const RoadVehicleInfo *rvi = RoadVehInfo(i);
 
			const Engine* e = GetEngine(i);
 
			int32 rating;
 
			CommandCost ret;
 

	
 
			/* Skip vehicles which can't take our cargo type */
 
			if (rvi->cargo_type != p->ainew.cargo && !CanRefitTo(i, p->ainew.cargo)) continue;
 
			if (rvi->cargo_type != _players_ainew[p->index].cargo && !CanRefitTo(i, _players_ainew[p->index].cargo)) continue;
 

	
 
			// Is it availiable?
 
			// Also, check if the reliability of the vehicle is above the AI_VEHICLE_MIN_RELIABILTY
 
			if (!HasBit(e->player_avail, _current_player) || e->reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
 

	
 
			/* Rate and compare the engine by speed & capacity */
 
@@ -269,49 +269,49 @@ EngineID AiNew_PickVehicle(Player *p)
 

	
 
void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
 
{
 
	Player* p = GetPlayer(_current_player);
 

	
 
	if (success) {
 
		p->ainew.state = AI_STATE_GIVE_ORDERS;
 
		p->ainew.veh_id = _new_vehicle_id;
 
		_players_ainew[p->index].state = AI_STATE_GIVE_ORDERS;
 
		_players_ainew[p->index].veh_id = _new_vehicle_id;
 

	
 
		if (GetVehicle(p->ainew.veh_id)->cargo_type != p->ainew.cargo) {
 
		if (GetVehicle(_players_ainew[p->index].veh_id)->cargo_type != _players_ainew[p->index].cargo) {
 
			/* Cargo type doesn't match, so refit it */
 
			if (CmdFailed(DoCommand(tile, p->ainew.veh_id, p->ainew.cargo, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
 
			if (CmdFailed(DoCommand(tile, _players_ainew[p->index].veh_id, _players_ainew[p->index].cargo, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
 
				/* Refit failed, so sell the vehicle */
 
				DoCommand(tile, p->ainew.veh_id, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
 
				p->ainew.state = AI_STATE_NOTHING;
 
				DoCommand(tile, _players_ainew[p->index].veh_id, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
 
				_players_ainew[p->index].state = AI_STATE_NOTHING;
 
			}
 
		}
 
	} else {
 
		/* XXX this should be handled more gracefully */
 
		p->ainew.state = AI_STATE_NOTHING;
 
		_players_ainew[p->index].state = AI_STATE_NOTHING;
 
	}
 
}
 

	
 

	
 
// Builds the best vehicle possible
 
CommandCost AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
 
{
 
	EngineID i = AiNew_PickVehicle(p);
 

	
 
	if (i == INVALID_ENGINE) return CMD_ERROR;
 
	if (p->ainew.tbt == AI_TRAIN) return CMD_ERROR;
 
	if (_players_ainew[p->index].tbt == AI_TRAIN) return CMD_ERROR;
 

	
 
	if (flag & DC_EXEC) {
 
		return AI_DoCommandCc(tile, i, 0, flag, CMD_BUILD_ROAD_VEH, CcAI);
 
	} else {
 
		return AI_DoCommand(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
 
	}
 
}
 

	
 
CommandCost AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag)
 
{
 
	CommandCost ret, ret2;
 
	if (p->ainew.tbt == AI_TRAIN) {
 
	if (_players_ainew[p->index].tbt == AI_TRAIN) {
 
		return AI_DoCommand(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
 
	} else {
 
		ret = AI_DoCommand(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
 
		if (CmdFailed(ret2)) return ret;
 
		// Try to build the road from the depot
 
		ret2 = AI_DoCommand(tile + TileOffsByDiagDir(direction), DiagDirToRoadBits(ReverseDiagDir(direction)), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
src/ai/trolly/pathfinder.cpp
Show inline comments
 
@@ -24,20 +24,20 @@ static bool TestCanBuildStationHere(Tile
 

	
 
	if (dir == TEST_STATION_NO_DIR) {
 
		CommandCost ret;
 
		// TODO: currently we only allow spots that can be access from al 4 directions...
 
		//  should be fixed!!!
 
		for (dir = 0; dir < 4; dir++) {
 
			ret = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
 
			ret = AiNew_Build_Station(p, _players_ainew[p->index].tbt, tile, 1, 1, dir, DC_QUERY_COST);
 
			if (CmdSucceeded(ret)) return true;
 
		}
 
		return false;
 
	}
 

	
 
	// return true if command succeeded, so the inverse of CmdFailed()
 
	return CmdSucceeded(AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST));
 
	return CmdSucceeded(AiNew_Build_Station(p, _players_ainew[p->index].tbt, tile, 1, 1, dir, DC_QUERY_COST));
 
}
 

	
 

	
 
static bool IsRoad(TileIndex tile)
 
{
 
	return
src/ai/trolly/shared.cpp
Show inline comments
 
@@ -77,14 +77,14 @@ DiagDirection AiNew_GetDirection(TileInd
 
//  and returns his flag
 
uint AiNew_GetSpecialVehicleFlag(Player* p, Vehicle* v)
 
{
 
	uint i;
 

	
 
	for (i = 0; i < AI_MAX_SPECIAL_VEHICLES; i++) {
 
		if (p->ainew.special_vehicles[i].veh_id == v->index) {
 
			return p->ainew.special_vehicles[i].flag;
 
		if (_players_ainew[p->index].special_vehicles[i].veh_id == v->index) {
 
			return _players_ainew[p->index].special_vehicles[i].flag;
 
		}
 
	}
 

	
 
	// Not found :(
 
	return 0;
 
}
 
@@ -93,26 +93,26 @@ uint AiNew_GetSpecialVehicleFlag(Player*
 
bool AiNew_SetSpecialVehicleFlag(Player* p, Vehicle* v, uint flag)
 
{
 
	int new_id = -1;
 
	uint i;
 

	
 
	for (i = 0; i < AI_MAX_SPECIAL_VEHICLES; i++) {
 
		if (p->ainew.special_vehicles[i].veh_id == v->index) {
 
			p->ainew.special_vehicles[i].flag |= flag;
 
		if (_players_ainew[p->index].special_vehicles[i].veh_id == v->index) {
 
			_players_ainew[p->index].special_vehicles[i].flag |= flag;
 
			return true;
 
		}
 
		if (new_id == -1 &&
 
				p->ainew.special_vehicles[i].veh_id == 0 &&
 
				p->ainew.special_vehicles[i].flag == 0) {
 
				_players_ainew[p->index].special_vehicles[i].veh_id == 0 &&
 
				_players_ainew[p->index].special_vehicles[i].flag == 0) {
 
			new_id = i;
 
		}
 
	}
 

	
 
	// Out of special_vehicle spots :s
 
	if (new_id == -1) {
 
		DEBUG(ai, 1, "special_vehicles list is too small");
 
		return false;
 
	}
 
	p->ainew.special_vehicles[new_id].veh_id = v->index;
 
	p->ainew.special_vehicles[new_id].flag = flag;
 
	_players_ainew[p->index].special_vehicles[new_id].veh_id = v->index;
 
	_players_ainew[p->index].special_vehicles[new_id].flag = flag;
 
	return true;
 
}
src/ai/trolly/trolly.cpp
Show inline comments
 
@@ -34,73 +34,75 @@
 
#include "../../vehicle_base.h"
 
#include "../../vehicle_func.h"
 
#include "../../date_func.h"
 
#include "../ai.h"
 
#include "../../order.h"
 

	
 
PlayerAiNew _players_ainew[MAX_PLAYERS];
 

	
 
// This function is called after StartUp. It is the init of an AI
 
static void AiNew_State_FirstTime(Player *p)
 
{
 
	// This assert is used to protect those function from misuse
 
	//   You have quickly a small mistake in the state-array
 
	//   With that, everything would go wrong. Finding that, is almost impossible
 
	//   With this assert, that problem can never happen.
 
	assert(p->ainew.state == AI_STATE_FIRST_TIME);
 
	assert(_players_ainew[p->index].state == AI_STATE_FIRST_TIME);
 
	// We first have to init some things
 

	
 
	if (_current_player == 1) ShowErrorMessage(INVALID_STRING_ID, TEMP_AI_IN_PROGRESS, 0, 0);
 

	
 
	// The PathFinder (AyStar)
 
	// TODO: Maybe when an AI goes bankrupt, this is de-init
 
	//  or when coming from a savegame.. should be checked out!
 
	p->ainew.path_info.start_tile_tl = 0;
 
	p->ainew.path_info.start_tile_br = 0;
 
	p->ainew.path_info.end_tile_tl = 0;
 
	p->ainew.path_info.end_tile_br = 0;
 
	p->ainew.pathfinder = new_AyStar_AiPathFinder(12, &p->ainew.path_info);
 
	_players_ainew[p->index].path_info.start_tile_tl = 0;
 
	_players_ainew[p->index].path_info.start_tile_br = 0;
 
	_players_ainew[p->index].path_info.end_tile_tl = 0;
 
	_players_ainew[p->index].path_info.end_tile_br = 0;
 
	_players_ainew[p->index].pathfinder = new_AyStar_AiPathFinder(12, &_players_ainew[p->index].path_info);
 

	
 
	p->ainew.idle = 0;
 
	p->ainew.last_vehiclecheck_date = _date;
 
	_players_ainew[p->index].idle = 0;
 
	_players_ainew[p->index].last_vehiclecheck_date = _date;
 

	
 
	// We ALWAYS start with a bus route.. just some basic money ;)
 
	p->ainew.action = AI_ACTION_BUS_ROUTE;
 
	_players_ainew[p->index].action = AI_ACTION_BUS_ROUTE;
 

	
 
	// Let's popup the news, and after that, start building..
 
	p->ainew.state = AI_STATE_WAKE_UP;
 
	_players_ainew[p->index].state = AI_STATE_WAKE_UP;
 
}
 

	
 

	
 
// This function just waste some time
 
//  It keeps it more real. The AI can build on such tempo no normal user
 
//  can ever keep up with that. The competitor_speed already delays a bit
 
//  but after the AI finished a track it really needs to go to sleep.
 
//
 
// Let's say, we sleep between one and three days if the AI is put on Very Fast.
 
//  This means that on Very Slow it will be between 16 and 48 days.. slow enough?
 
static void AiNew_State_Nothing(Player *p)
 
{
 
	assert(p->ainew.state == AI_STATE_NOTHING);
 
	assert(_players_ainew[p->index].state == AI_STATE_NOTHING);
 
	// If we are done idling, start over again
 
	if (p->ainew.idle == 0) p->ainew.idle = AI_RandomRange(DAY_TICKS * 2) + DAY_TICKS;
 
	if (--p->ainew.idle == 0) {
 
	if (_players_ainew[p->index].idle == 0) _players_ainew[p->index].idle = AI_RandomRange(DAY_TICKS * 2) + DAY_TICKS;
 
	if (--_players_ainew[p->index].idle == 0) {
 
		// We are done idling.. what you say? Let's do something!
 
		// I mean.. the next tick ;)
 
		p->ainew.state = AI_STATE_WAKE_UP;
 
		_players_ainew[p->index].state = AI_STATE_WAKE_UP;
 
	}
 
}
 

	
 

	
 
// This function picks out a task we are going to do.
 
//  Currently supported:
 
//    - Make new route
 
//    - Check route
 
//    - Build HQ
 
static void AiNew_State_WakeUp(Player *p)
 
{
 
	int c;
 
	assert(p->ainew.state == AI_STATE_WAKE_UP);
 
	assert(_players_ainew[p->index].state == AI_STATE_WAKE_UP);
 
	// First, check if we have a HQ
 
	if (p->location_of_house == 0) {
 
		// We have no HQ yet, build one on a random place
 
		// Random till we found a place for it!
 
		// TODO: this should not be on a random place..
 
		AiNew_Build_CompanyHQ(p, AI_Random() % MapSize());
 
@@ -109,101 +111,101 @@ static void AiNew_State_WakeUp(Player *p
 
		return;
 
	}
 

	
 
	Money money = p->player_money - AI_MINIMUM_MONEY;
 

	
 
	// Let's pick an action!
 
	if (p->ainew.action == AI_ACTION_NONE) {
 
	if (_players_ainew[p->index].action == AI_ACTION_NONE) {
 
		c = AI_Random() & 0xFF;
 
		if (p->current_loan > 0 &&
 
				p->old_economy[1].income > AI_MINIMUM_INCOME_FOR_LOAN &&
 
				c < 10) {
 
			p->ainew.action = AI_ACTION_REPAY_LOAN;
 
		} else if (p->ainew.last_vehiclecheck_date + AI_DAYS_BETWEEN_VEHICLE_CHECKS < _date) {
 
			_players_ainew[p->index].action = AI_ACTION_REPAY_LOAN;
 
		} else if (_players_ainew[p->index].last_vehiclecheck_date + AI_DAYS_BETWEEN_VEHICLE_CHECKS < _date) {
 
			// Check all vehicles once in a while
 
			p->ainew.action = AI_ACTION_CHECK_ALL_VEHICLES;
 
			p->ainew.last_vehiclecheck_date = _date;
 
			_players_ainew[p->index].action = AI_ACTION_CHECK_ALL_VEHICLES;
 
			_players_ainew[p->index].last_vehiclecheck_date = _date;
 
		} else if (c < 100 && !_patches.ai_disable_veh_roadveh) {
 
			// Do we have any spots for road-vehicles left open?
 
			if (GetFreeUnitNumber(VEH_ROAD) <= _patches.max_roadveh) {
 
				if (c < 85) {
 
					p->ainew.action = AI_ACTION_TRUCK_ROUTE;
 
					_players_ainew[p->index].action = AI_ACTION_TRUCK_ROUTE;
 
				} else {
 
					p->ainew.action = AI_ACTION_BUS_ROUTE;
 
					_players_ainew[p->index].action = AI_ACTION_BUS_ROUTE;
 
				}
 
			}
 
#if 0
 
		} else if (c < 200 && !_patches.ai_disable_veh_train) {
 
			if (GetFreeUnitNumber(VEH_TRAIN) <= _patches.max_trains) {
 
				p->ainew.action = AI_ACTION_TRAIN_ROUTE;
 
				_players_ainew[p->index].action = AI_ACTION_TRAIN_ROUTE;
 
			}
 
#endif
 
		}
 

	
 
		p->ainew.counter = 0;
 
		_players_ainew[p->index].counter = 0;
 
	}
 

	
 
	if (p->ainew.counter++ > AI_MAX_TRIES_FOR_SAME_ROUTE) {
 
		p->ainew.action = AI_ACTION_NONE;
 
	if (_players_ainew[p->index].counter++ > AI_MAX_TRIES_FOR_SAME_ROUTE) {
 
		_players_ainew[p->index].action = AI_ACTION_NONE;
 
		return;
 
	}
 

	
 
	if (_patches.ai_disable_veh_roadveh && (
 
				p->ainew.action == AI_ACTION_BUS_ROUTE ||
 
				p->ainew.action == AI_ACTION_TRUCK_ROUTE
 
				_players_ainew[p->index].action == AI_ACTION_BUS_ROUTE ||
 
				_players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE
 
			)) {
 
		p->ainew.action = AI_ACTION_NONE;
 
		_players_ainew[p->index].action = AI_ACTION_NONE;
 
		return;
 
	}
 

	
 
	if (p->ainew.action == AI_ACTION_REPAY_LOAN &&
 
	if (_players_ainew[p->index].action == AI_ACTION_REPAY_LOAN &&
 
			money > AI_MINIMUM_LOAN_REPAY_MONEY) {
 
		// We start repaying some money..
 
		p->ainew.state = AI_STATE_REPAY_MONEY;
 
		_players_ainew[p->index].state = AI_STATE_REPAY_MONEY;
 
		return;
 
	}
 

	
 
	if (p->ainew.action == AI_ACTION_CHECK_ALL_VEHICLES) {
 
		p->ainew.state = AI_STATE_CHECK_ALL_VEHICLES;
 
	if (_players_ainew[p->index].action == AI_ACTION_CHECK_ALL_VEHICLES) {
 
		_players_ainew[p->index].state = AI_STATE_CHECK_ALL_VEHICLES;
 
		return;
 
	}
 

	
 
	// It is useless to start finding a route if we don't have enough money
 
	//  to build the route anyway..
 
	if (p->ainew.action == AI_ACTION_BUS_ROUTE &&
 
	if (_players_ainew[p->index].action == AI_ACTION_BUS_ROUTE &&
 
			money > AI_MINIMUM_BUS_ROUTE_MONEY) {
 
		if (GetFreeUnitNumber(VEH_ROAD) > _patches.max_roadveh) {
 
			p->ainew.action = AI_ACTION_NONE;
 
			_players_ainew[p->index].action = AI_ACTION_NONE;
 
			return;
 
		}
 
		p->ainew.cargo = AI_NEED_CARGO;
 
		p->ainew.state = AI_STATE_LOCATE_ROUTE;
 
		p->ainew.tbt = AI_BUS; // Bus-route
 
		_players_ainew[p->index].cargo = AI_NEED_CARGO;
 
		_players_ainew[p->index].state = AI_STATE_LOCATE_ROUTE;
 
		_players_ainew[p->index].tbt = AI_BUS; // Bus-route
 
		return;
 
	}
 
	if (p->ainew.action == AI_ACTION_TRUCK_ROUTE &&
 
	if (_players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE &&
 
			money > AI_MINIMUM_TRUCK_ROUTE_MONEY) {
 
		if (GetFreeUnitNumber(VEH_ROAD) > _patches.max_roadveh) {
 
			p->ainew.action = AI_ACTION_NONE;
 
			_players_ainew[p->index].action = AI_ACTION_NONE;
 
			return;
 
		}
 
		p->ainew.cargo = AI_NEED_CARGO;
 
		p->ainew.last_id = 0;
 
		p->ainew.state = AI_STATE_LOCATE_ROUTE;
 
		p->ainew.tbt = AI_TRUCK;
 
		_players_ainew[p->index].cargo = AI_NEED_CARGO;
 
		_players_ainew[p->index].last_id = 0;
 
		_players_ainew[p->index].state = AI_STATE_LOCATE_ROUTE;
 
		_players_ainew[p->index].tbt = AI_TRUCK;
 
		return;
 
	}
 

	
 
	p->ainew.state = AI_STATE_NOTHING;
 
	_players_ainew[p->index].state = AI_STATE_NOTHING;
 
}
 

	
 

	
 
static void AiNew_State_ActionDone(Player *p)
 
{
 
	p->ainew.action = AI_ACTION_NONE;
 
	p->ainew.state = AI_STATE_NOTHING;
 
	_players_ainew[p->index].action = AI_ACTION_NONE;
 
	_players_ainew[p->index].state = AI_STATE_NOTHING;
 
}
 

	
 

	
 
// Check if a city or industry is good enough to start a route there
 
static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type)
 
{
 
@@ -227,13 +229,13 @@ static bool AiNew_Check_City_or_Industry
 
		//  and sometimes it takes up to 4 months before the stats are corectly.
 
		//  This way we don't get 12 busstations in one city of 100 population ;)
 
		FOR_ALL_STATIONS(st) {
 
			// Do we own it?
 
			if (st->owner == _current_player) {
 
				// Are we talking busses?
 
				if (p->ainew.tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) != FACIL_BUS_STOP) continue;
 
				if (_players_ainew[p->index].tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) != FACIL_BUS_STOP) continue;
 
				// Is it the same city as we are in now?
 
				if (st->town != t) continue;
 
				// When was this station build?
 
				if (_date - st->build_date < AI_CHECKCITY_DATE_BETWEEN) return false;
 
				// Cound the amount of stations in this city that we own
 
				count++;
 
@@ -285,13 +287,13 @@ static bool AiNew_Check_City_or_Industry
 
		//  else we don't do it. This is done, because stat updates can be slow
 
		//  and sometimes it takes up to 4 months before the stats are corectly.
 
		FOR_ALL_STATIONS(st) {
 
			// Do we own it?
 
			if (st->owner == _current_player) {
 
				// Are we talking trucks?
 
				if (p->ainew.tbt == AI_TRUCK && (FACIL_TRUCK_STOP & st->facilities) != FACIL_TRUCK_STOP) continue;
 
				if (_players_ainew[p->index].tbt == AI_TRUCK && (FACIL_TRUCK_STOP & st->facilities) != FACIL_TRUCK_STOP) continue;
 
				// Is it the same city as we are in now?
 
				if (st->town != i->town) continue;
 
				// When was this station build?
 
				if (_date - st->build_date < AI_CHECKCITY_DATE_BETWEEN) return false;
 
				// Cound the amount of stations in this city that we own
 
				count++;
 
@@ -329,137 +331,137 @@ static bool AiNew_Check_City_or_Industry
 
}
 

	
 

	
 
// This functions tries to locate a good route
 
static void AiNew_State_LocateRoute(Player *p)
 
{
 
	assert(p->ainew.state == AI_STATE_LOCATE_ROUTE);
 
	assert(_players_ainew[p->index].state == AI_STATE_LOCATE_ROUTE);
 
	// For now, we only support PASSENGERS, CITY and BUSSES
 

	
 
	// We don't have a route yet
 
	if (p->ainew.cargo == AI_NEED_CARGO) {
 
		p->ainew.new_cost = 0; // No cost yet
 
		p->ainew.temp = -1;
 
	if (_players_ainew[p->index].cargo == AI_NEED_CARGO) {
 
		_players_ainew[p->index].new_cost = 0; // No cost yet
 
		_players_ainew[p->index].temp = -1;
 
		// Reset the counter
 
		p->ainew.counter = 0;
 
		_players_ainew[p->index].counter = 0;
 

	
 
		p->ainew.from_ic = -1;
 
		p->ainew.to_ic = -1;
 
		if (p->ainew.tbt == AI_BUS) {
 
		_players_ainew[p->index].from_ic = -1;
 
		_players_ainew[p->index].to_ic = -1;
 
		if (_players_ainew[p->index].tbt == AI_BUS) {
 
			// For now we only have a passenger route
 
			p->ainew.cargo = CT_PASSENGERS;
 
			_players_ainew[p->index].cargo = CT_PASSENGERS;
 

	
 
			// Find a route to cities
 
			p->ainew.from_type = AI_CITY;
 
			p->ainew.to_type = AI_CITY;
 
		} else if (p->ainew.tbt == AI_TRUCK) {
 
			p->ainew.cargo = AI_NO_CARGO;
 
			_players_ainew[p->index].from_type = AI_CITY;
 
			_players_ainew[p->index].to_type = AI_CITY;
 
		} else if (_players_ainew[p->index].tbt == AI_TRUCK) {
 
			_players_ainew[p->index].cargo = AI_NO_CARGO;
 

	
 
			p->ainew.from_type = AI_INDUSTRY;
 
			p->ainew.to_type = AI_INDUSTRY;
 
			_players_ainew[p->index].from_type = AI_INDUSTRY;
 
			_players_ainew[p->index].to_type = AI_INDUSTRY;
 
		}
 

	
 
		// Now we are doing initing, we wait one tick
 
		return;
 
	}
 

	
 
	// Increase the counter and abort if it is taking too long!
 
	p->ainew.counter++;
 
	if (p->ainew.counter > AI_LOCATE_ROUTE_MAX_COUNTER) {
 
	_players_ainew[p->index].counter++;
 
	if (_players_ainew[p->index].counter > AI_LOCATE_ROUTE_MAX_COUNTER) {
 
		// Switch back to doing nothing!
 
		p->ainew.state = AI_STATE_NOTHING;
 
		_players_ainew[p->index].state = AI_STATE_NOTHING;
 
		return;
 
	}
 

	
 
	// We are going to locate a city from where we are going to connect
 
	if (p->ainew.from_ic == -1) {
 
		if (p->ainew.temp == -1) {
 
	if (_players_ainew[p->index].from_ic == -1) {
 
		if (_players_ainew[p->index].temp == -1) {
 
			// First, we pick a random spot to search from
 
			if (p->ainew.from_type == AI_CITY) {
 
				p->ainew.temp = AI_RandomRange(GetMaxTownIndex() + 1);
 
			if (_players_ainew[p->index].from_type == AI_CITY) {
 
				_players_ainew[p->index].temp = AI_RandomRange(GetMaxTownIndex() + 1);
 
			} else {
 
				p->ainew.temp = AI_RandomRange(GetMaxIndustryIndex() + 1);
 
				_players_ainew[p->index].temp = AI_RandomRange(GetMaxIndustryIndex() + 1);
 
			}
 
		}
 

	
 
		if (!AiNew_Check_City_or_Industry(p, p->ainew.temp, p->ainew.from_type)) {
 
		if (!AiNew_Check_City_or_Industry(p, _players_ainew[p->index].temp, _players_ainew[p->index].from_type)) {
 
			// It was not a valid city
 
			//  increase the temp with one, and return. We will come back later here
 
			//  to try again
 
			p->ainew.temp++;
 
			if (p->ainew.from_type == AI_CITY) {
 
				if (p->ainew.temp > GetMaxTownIndex()) p->ainew.temp = 0;
 
			_players_ainew[p->index].temp++;
 
			if (_players_ainew[p->index].from_type == AI_CITY) {
 
				if (_players_ainew[p->index].temp > GetMaxTownIndex()) _players_ainew[p->index].temp = 0;
 
			} else {
 
				if (p->ainew.temp > GetMaxIndustryIndex()) p->ainew.temp = 0;
 
				if (_players_ainew[p->index].temp > GetMaxIndustryIndex()) _players_ainew[p->index].temp = 0;
 
			}
 

	
 
			// Don't do an attempt if we are trying the same id as the last time...
 
			if (p->ainew.last_id == p->ainew.temp) return;
 
			p->ainew.last_id = p->ainew.temp;
 
			if (_players_ainew[p->index].last_id == _players_ainew[p->index].temp) return;
 
			_players_ainew[p->index].last_id = _players_ainew[p->index].temp;
 

	
 
			return;
 
		}
 

	
 
		// We found a good city/industry, save the data of it
 
		p->ainew.from_ic = p->ainew.temp;
 
		_players_ainew[p->index].from_ic = _players_ainew[p->index].temp;
 

	
 
		// Start the next tick with finding a to-city
 
		p->ainew.temp = -1;
 
		_players_ainew[p->index].temp = -1;
 
		return;
 
	}
 

	
 
	// Find a to-city
 
	if (p->ainew.temp == -1) {
 
	if (_players_ainew[p->index].temp == -1) {
 
		// First, we pick a random spot to search to
 
		if (p->ainew.to_type == AI_CITY) {
 
			p->ainew.temp = AI_RandomRange(GetMaxTownIndex() + 1);
 
		if (_players_ainew[p->index].to_type == AI_CITY) {
 
			_players_ainew[p->index].temp = AI_RandomRange(GetMaxTownIndex() + 1);
 
		} else {
 
			p->ainew.temp = AI_RandomRange(GetMaxIndustryIndex() + 1);
 
			_players_ainew[p->index].temp = AI_RandomRange(GetMaxIndustryIndex() + 1);
 
		}
 
	}
 

	
 
	// The same city is not allowed
 
	// Also check if the city is valid
 
	if (p->ainew.temp != p->ainew.from_ic && AiNew_Check_City_or_Industry(p, p->ainew.temp, p->ainew.to_type)) {
 
	if (_players_ainew[p->index].temp != _players_ainew[p->index].from_ic && AiNew_Check_City_or_Industry(p, _players_ainew[p->index].temp, _players_ainew[p->index].to_type)) {
 
		// Maybe it is valid..
 

	
 
		/* We need to know if they are not to far apart from eachother..
 
		 * We do that by checking how much cargo we have to move and how long the
 
		 * route is.
 
		 */
 

	
 
		if (p->ainew.from_type == AI_CITY && p->ainew.tbt == AI_BUS) {
 
			const Town* town_from = GetTown(p->ainew.from_ic);
 
			const Town* town_temp = GetTown(p->ainew.temp);
 
		if (_players_ainew[p->index].from_type == AI_CITY && _players_ainew[p->index].tbt == AI_BUS) {
 
			const Town* town_from = GetTown(_players_ainew[p->index].from_ic);
 
			const Town* town_temp = GetTown(_players_ainew[p->index].temp);
 
			uint distance = DistanceManhattan(town_from->xy, town_temp->xy);
 
			int max_cargo;
 

	
 
			max_cargo  = town_from->max_pass + town_temp->max_pass;
 
			max_cargo -= town_from->act_pass + town_temp->act_pass;
 

	
 
			// max_cargo is now the amount of cargo we can move between the two cities
 
			// If it is more than the distance, we allow it
 
			if (distance <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) {
 
				// We found a good city/industry, save the data of it
 
				p->ainew.to_ic = p->ainew.temp;
 
				p->ainew.state = AI_STATE_FIND_STATION;
 
				_players_ainew[p->index].to_ic = _players_ainew[p->index].temp;
 
				_players_ainew[p->index].state = AI_STATE_FIND_STATION;
 

	
 
				DEBUG(ai, 1, "[LocateRoute] found bus-route of %d tiles long (from %d to %d)",
 
					distance,
 
					p->ainew.from_ic,
 
					p->ainew.temp
 
					_players_ainew[p->index].from_ic,
 
					_players_ainew[p->index].temp
 
				);
 

	
 
				p->ainew.from_tile = 0;
 
				p->ainew.to_tile = 0;
 
				_players_ainew[p->index].from_tile = 0;
 
				_players_ainew[p->index].to_tile = 0;
 

	
 
				return;
 
			}
 
		} else if (p->ainew.tbt == AI_TRUCK) {
 
			const Industry* ind_from = GetIndustry(p->ainew.from_ic);
 
			const Industry* ind_temp = GetIndustry(p->ainew.temp);
 
		} else if (_players_ainew[p->index].tbt == AI_TRUCK) {
 
			const Industry* ind_from = GetIndustry(_players_ainew[p->index].from_ic);
 
			const Industry* ind_temp = GetIndustry(_players_ainew[p->index].temp);
 
			bool found = false;
 
			int max_cargo = 0;
 
			uint i;
 

	
 
			// TODO: in max_cargo, also check other cargo (beside [0])
 
			// First we check if the from_ic produces cargo that this ic accepts
 
@@ -467,75 +469,75 @@ static void AiNew_State_LocateRoute(Play
 
				for (i = 0; i < lengthof(ind_temp->accepts_cargo); i++) {
 
					if (ind_temp->accepts_cargo[i] == CT_INVALID) break;
 
					if (ind_from->produced_cargo[0] == ind_temp->accepts_cargo[i]) {
 
						// Found a compatible industry
 
						max_cargo = ind_from->last_month_production[0] - ind_from->last_month_transported[0];
 
						found = true;
 
						p->ainew.from_deliver = true;
 
						p->ainew.to_deliver = false;
 
						_players_ainew[p->index].from_deliver = true;
 
						_players_ainew[p->index].to_deliver = false;
 
						break;
 
					}
 
				}
 
			}
 
			if (!found && ind_temp->produced_cargo[0] != CT_INVALID && ind_temp->last_month_production[0] != 0) {
 
				// If not check if the current ic produces cargo that the from_ic accepts
 
				for (i = 0; i < lengthof(ind_from->accepts_cargo); i++) {
 
					if (ind_from->accepts_cargo[i] == CT_INVALID) break;
 
					if (ind_from->produced_cargo[0] == ind_from->accepts_cargo[i]) {
 
						// Found a compatbiel industry
 
						found = true;
 
						max_cargo = ind_temp->last_month_production[0] - ind_temp->last_month_transported[0];
 
						p->ainew.from_deliver = false;
 
						p->ainew.to_deliver = true;
 
						_players_ainew[p->index].from_deliver = false;
 
						_players_ainew[p->index].to_deliver = true;
 
						break;
 
					}
 
				}
 
			}
 
			if (found) {
 
				// Yeah, they are compatible!!!
 
				// Check the length against the amount of goods
 
				uint distance = DistanceManhattan(ind_from->xy, ind_temp->xy);
 

	
 
				if (distance > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE &&
 
						distance <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) {
 
					p->ainew.to_ic = p->ainew.temp;
 
					if (p->ainew.from_deliver) {
 
						p->ainew.cargo = ind_from->produced_cargo[0];
 
					_players_ainew[p->index].to_ic = _players_ainew[p->index].temp;
 
					if (_players_ainew[p->index].from_deliver) {
 
						_players_ainew[p->index].cargo = ind_from->produced_cargo[0];
 
					} else {
 
						p->ainew.cargo = ind_temp->produced_cargo[0];
 
						_players_ainew[p->index].cargo = ind_temp->produced_cargo[0];
 
					}
 
					p->ainew.state = AI_STATE_FIND_STATION;
 
					_players_ainew[p->index].state = AI_STATE_FIND_STATION;
 

	
 
					DEBUG(ai, 1, "[LocateRoute] found truck-route of %d tiles long (from %d to %d)",
 
						distance,
 
						p->ainew.from_ic,
 
						p->ainew.temp
 
						_players_ainew[p->index].from_ic,
 
						_players_ainew[p->index].temp
 
					);
 

	
 
					p->ainew.from_tile = 0;
 
					p->ainew.to_tile = 0;
 
					_players_ainew[p->index].from_tile = 0;
 
					_players_ainew[p->index].to_tile = 0;
 

	
 
					return;
 
				}
 
			}
 
		}
 
	}
 

	
 
	// It was not a valid city
 
	//  increase the temp with one, and return. We will come back later here
 
	//  to try again
 
	p->ainew.temp++;
 
	if (p->ainew.to_type == AI_CITY) {
 
		if (p->ainew.temp > GetMaxTownIndex()) p->ainew.temp = 0;
 
	_players_ainew[p->index].temp++;
 
	if (_players_ainew[p->index].to_type == AI_CITY) {
 
		if (_players_ainew[p->index].temp > GetMaxTownIndex()) _players_ainew[p->index].temp = 0;
 
	} else {
 
		if (p->ainew.temp > GetMaxIndustryIndex()) p->ainew.temp = 0;
 
		if (_players_ainew[p->index].temp > GetMaxIndustryIndex()) _players_ainew[p->index].temp = 0;
 
	}
 

	
 
	// Don't do an attempt if we are trying the same id as the last time...
 
	if (p->ainew.last_id == p->ainew.temp) return;
 
	p->ainew.last_id = p->ainew.temp;
 
	if (_players_ainew[p->index].last_id == _players_ainew[p->index].temp) return;
 
	_players_ainew[p->index].last_id = _players_ainew[p->index].temp;
 
}
 

	
 

	
 
// Check if there are not more than a certain amount of vehicles pointed to a certain
 
//  station. This to prevent 10 busses going to one station, which gives... problems ;)
 
static bool AiNew_CheckVehicleStation(Player *p, Station *st)
 
@@ -568,55 +570,55 @@ static void AiNew_State_FindStation(Play
 
	Station *st;
 
	int count = 0;
 
	EngineID i;
 
	TileIndex new_tile = 0;
 
	DiagDirection direction = DIAGDIR_NE;
 
	Town *town = NULL;
 
	assert(p->ainew.state == AI_STATE_FIND_STATION);
 
	assert(_players_ainew[p->index].state == AI_STATE_FIND_STATION);
 

	
 
	if (p->ainew.from_tile == 0) {
 
	if (_players_ainew[p->index].from_tile == 0) {
 
		// First we scan for a station in the from-city
 
		if (p->ainew.from_type == AI_CITY) {
 
			town = GetTown(p->ainew.from_ic);
 
		if (_players_ainew[p->index].from_type == AI_CITY) {
 
			town = GetTown(_players_ainew[p->index].from_ic);
 
			tile = town->xy;
 
		} else {
 
			tile = GetIndustry(p->ainew.from_ic)->xy;
 
			tile = GetIndustry(_players_ainew[p->index].from_ic)->xy;
 
		}
 
	} else if (p->ainew.to_tile == 0) {
 
	} else if (_players_ainew[p->index].to_tile == 0) {
 
		// Second we scan for a station in the to-city
 
		if (p->ainew.to_type == AI_CITY) {
 
			town = GetTown(p->ainew.to_ic);
 
		if (_players_ainew[p->index].to_type == AI_CITY) {
 
			town = GetTown(_players_ainew[p->index].to_ic);
 
			tile = town->xy;
 
		} else {
 
			tile = GetIndustry(p->ainew.to_ic)->xy;
 
			tile = GetIndustry(_players_ainew[p->index].to_ic)->xy;
 
		}
 
	} else {
 
		// Unsupported request
 
		// Go to FIND_PATH
 
		p->ainew.temp = -1;
 
		p->ainew.state = AI_STATE_FIND_PATH;
 
		_players_ainew[p->index].temp = -1;
 
		_players_ainew[p->index].state = AI_STATE_FIND_PATH;
 
		return;
 
	}
 

	
 
	// First, we are going to look at the stations that already exist inside the city
 
	//  If there is enough cargo left in the station, we take that station
 
	//  If that is not possible, and there are more than 2 stations in the city, abort
 
	i = AiNew_PickVehicle(p);
 
	// Euhmz, this should not happen _EVER_
 
	// Quit finding a route...
 
	if (i == INVALID_ENGINE) {
 
		p->ainew.state = AI_STATE_NOTHING;
 
		_players_ainew[p->index].state = AI_STATE_NOTHING;
 
		return;
 
	}
 

	
 
	FOR_ALL_STATIONS(st) {
 
		if (st->owner == _current_player) {
 
			if (p->ainew.tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) == FACIL_BUS_STOP) {
 
			if (_players_ainew[p->index].tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) == FACIL_BUS_STOP) {
 
				if (st->town == town) {
 
					// Check how much cargo there is left in the station
 
					if ((int)st->goods[p->ainew.cargo].cargo.Count() > RoadVehInfo(i)->capacity * AI_STATION_REUSE_MULTIPLER) {
 
					if ((int)st->goods[_players_ainew[p->index].cargo].cargo.Count() > RoadVehInfo(i)->capacity * AI_STATION_REUSE_MULTIPLER) {
 
						if (AiNew_CheckVehicleStation(p, st)) {
 
							// We did found a station that was good enough!
 
							new_tile = st->xy;
 
							direction = GetRoadStopDir(st->xy);
 
							break;
 
						}
 
@@ -628,17 +630,17 @@ static void AiNew_State_FindStation(Play
 
	}
 
	// We are going to add a new station...
 
	if (new_tile == 0) count++;
 
	// No more than 2 stations allowed in a city
 
	//  This is because only the best 2 stations of one cargo do get any cargo
 
	if (count > 2) {
 
		p->ainew.state = AI_STATE_NOTHING;
 
		_players_ainew[p->index].state = AI_STATE_NOTHING;
 
		return;
 
	}
 

	
 
	if (new_tile == 0 && p->ainew.tbt == AI_BUS) {
 
	if (new_tile == 0 && _players_ainew[p->index].tbt == AI_BUS) {
 
		uint x, y, i = 0;
 
		CommandCost r;
 
		uint best;
 
		uint accepts[NUM_CARGO];
 
		TileIndex found_spot[AI_FINDSTATION_TILE_RANGE*AI_FINDSTATION_TILE_RANGE * 4];
 
		uint found_best[AI_FINDSTATION_TILE_RANGE*AI_FINDSTATION_TILE_RANGE * 4];
 
@@ -652,26 +654,26 @@ static void AiNew_State_FindStation(Play
 
				if (IsTileType(new_tile, MP_CLEAR) || IsTileType(new_tile, MP_TREES)) {
 
					// This tile we can build on!
 
					// Check acceptance
 
					// XXX - Get the catchment area
 
					GetAcceptanceAroundTiles(accepts, new_tile, 1, 1, 4);
 
					// >> 3 == 0 means no cargo
 
					if (accepts[p->ainew.cargo] >> 3 == 0) continue;
 
					if (accepts[_players_ainew[p->index].cargo] >> 3 == 0) continue;
 
					// See if we can build the station
 
					r = AiNew_Build_Station(p, p->ainew.tbt, new_tile, 0, 0, 0, DC_QUERY_COST);
 
					r = AiNew_Build_Station(p, _players_ainew[p->index].tbt, new_tile, 0, 0, 0, DC_QUERY_COST);
 
					if (CmdFailed(r)) continue;
 
					// We can build it, so add it to found_spot
 
					found_spot[i] = new_tile;
 
					found_best[i++] = accepts[p->ainew.cargo];
 
					found_best[i++] = accepts[_players_ainew[p->index].cargo];
 
				}
 
			}
 
		}
 

	
 
		// If i is still zero, we did not find anything
 
		if (i == 0) {
 
			p->ainew.state = AI_STATE_NOTHING;
 
			_players_ainew[p->index].state = AI_STATE_NOTHING;
 
			return;
 
		}
 

	
 
		// Go through all the found_best and check which has the highest value
 
		best = 0;
 
		new_tile = 0;
 
@@ -682,94 +684,94 @@ static void AiNew_State_FindStation(Play
 
				new_tile = found_spot[x];
 
				best = found_best[x];
 
			}
 
		}
 

	
 
		// See how much it is going to cost us...
 
		r = AiNew_Build_Station(p, p->ainew.tbt, new_tile, 0, 0, 0, DC_QUERY_COST);
 
		p->ainew.new_cost += r.GetCost();
 
		r = AiNew_Build_Station(p, _players_ainew[p->index].tbt, new_tile, 0, 0, 0, DC_QUERY_COST);
 
		_players_ainew[p->index].new_cost += r.GetCost();
 

	
 
		direction = (DiagDirection)AI_PATHFINDER_NO_DIRECTION;
 
	} else if (new_tile == 0 && p->ainew.tbt == AI_TRUCK) {
 
	} else if (new_tile == 0 && _players_ainew[p->index].tbt == AI_TRUCK) {
 
		// Truck station locater works differently.. a station can be on any place
 
		//  as long as it is in range. So we give back code AI_STATION_RANGE
 
		//  so the pathfinder routine can work it out!
 
		new_tile = AI_STATION_RANGE;
 
		direction = (DiagDirection)AI_PATHFINDER_NO_DIRECTION;
 
	}
 

	
 
	if (p->ainew.from_tile == 0) {
 
		p->ainew.from_tile = new_tile;
 
		p->ainew.from_direction = direction;
 
	if (_players_ainew[p->index].from_tile == 0) {
 
		_players_ainew[p->index].from_tile = new_tile;
 
		_players_ainew[p->index].from_direction = direction;
 
		// Now we found thisone, go in for to_tile
 
		return;
 
	} else if (p->ainew.to_tile == 0) {
 
		p->ainew.to_tile = new_tile;
 
		p->ainew.to_direction = direction;
 
	} else if (_players_ainew[p->index].to_tile == 0) {
 
		_players_ainew[p->index].to_tile = new_tile;
 
		_players_ainew[p->index].to_direction = direction;
 
		// K, done placing stations!
 
		p->ainew.temp = -1;
 
		p->ainew.state = AI_STATE_FIND_PATH;
 
		_players_ainew[p->index].temp = -1;
 
		_players_ainew[p->index].state = AI_STATE_FIND_PATH;
 
		return;
 
	}
 
}
 

	
 

	
 
// We try to find a path between 2 points
 
static void AiNew_State_FindPath(Player *p)
 
{
 
	int r;
 
	assert(p->ainew.state == AI_STATE_FIND_PATH);
 
	assert(_players_ainew[p->index].state == AI_STATE_FIND_PATH);
 

	
 
	// First time, init some data
 
	if (p->ainew.temp == -1) {
 
	if (_players_ainew[p->index].temp == -1) {
 
		// Init path_info
 
		if (p->ainew.from_tile == AI_STATION_RANGE) {
 
			const Industry* i = GetIndustry(p->ainew.from_ic);
 
		if (_players_ainew[p->index].from_tile == AI_STATION_RANGE) {
 
			const Industry* i = GetIndustry(_players_ainew[p->index].from_ic);
 

	
 
			// For truck routes we take a range around the industry
 
			p->ainew.path_info.start_tile_tl = i->xy - TileDiffXY(1, 1);
 
			p->ainew.path_info.start_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1);
 
			p->ainew.path_info.start_direction = p->ainew.from_direction;
 
			_players_ainew[p->index].path_info.start_tile_tl = i->xy - TileDiffXY(1, 1);
 
			_players_ainew[p->index].path_info.start_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1);
 
			_players_ainew[p->index].path_info.start_direction = _players_ainew[p->index].from_direction;
 
		} else {
 
			p->ainew.path_info.start_tile_tl = p->ainew.from_tile;
 
			p->ainew.path_info.start_tile_br = p->ainew.from_tile;
 
			p->ainew.path_info.start_direction = p->ainew.from_direction;
 
			_players_ainew[p->index].path_info.start_tile_tl = _players_ainew[p->index].from_tile;
 
			_players_ainew[p->index].path_info.start_tile_br = _players_ainew[p->index].from_tile;
 
			_players_ainew[p->index].path_info.start_direction = _players_ainew[p->index].from_direction;
 
		}
 

	
 
		if (p->ainew.to_tile == AI_STATION_RANGE) {
 
			const Industry* i = GetIndustry(p->ainew.to_ic);
 
		if (_players_ainew[p->index].to_tile == AI_STATION_RANGE) {
 
			const Industry* i = GetIndustry(_players_ainew[p->index].to_ic);
 

	
 
			p->ainew.path_info.end_tile_tl = i->xy - TileDiffXY(1, 1);
 
			p->ainew.path_info.end_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1);
 
			p->ainew.path_info.end_direction = p->ainew.to_direction;
 
			_players_ainew[p->index].path_info.end_tile_tl = i->xy - TileDiffXY(1, 1);
 
			_players_ainew[p->index].path_info.end_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1);
 
			_players_ainew[p->index].path_info.end_direction = _players_ainew[p->index].to_direction;
 
		} else {
 
			p->ainew.path_info.end_tile_tl = p->ainew.to_tile;
 
			p->ainew.path_info.end_tile_br = p->ainew.to_tile;
 
			p->ainew.path_info.end_direction = p->ainew.to_direction;
 
			_players_ainew[p->index].path_info.end_tile_tl = _players_ainew[p->index].to_tile;
 
			_players_ainew[p->index].path_info.end_tile_br = _players_ainew[p->index].to_tile;
 
			_players_ainew[p->index].path_info.end_direction = _players_ainew[p->index].to_direction;
 
		}
 

	
 
		p->ainew.path_info.rail_or_road = (p->ainew.tbt == AI_TRAIN);
 
		_players_ainew[p->index].path_info.rail_or_road = (_players_ainew[p->index].tbt == AI_TRAIN);
 

	
 
		// First, clean the pathfinder with our new begin and endpoints
 
		clean_AyStar_AiPathFinder(p->ainew.pathfinder, &p->ainew.path_info);
 
		clean_AyStar_AiPathFinder(_players_ainew[p->index].pathfinder, &_players_ainew[p->index].path_info);
 

	
 
		p->ainew.temp = 0;
 
		_players_ainew[p->index].temp = 0;
 
	}
 

	
 
	// Start the pathfinder
 
	r = p->ainew.pathfinder->main(p->ainew.pathfinder);
 
	r = _players_ainew[p->index].pathfinder->main(_players_ainew[p->index].pathfinder);
 
	switch (r) {
 
		case AYSTAR_NO_PATH:
 
			DEBUG(ai, 1, "No route found by pathfinder");
 
			// Start all over again
 
			p->ainew.state = AI_STATE_NOTHING;
 
			_players_ainew[p->index].state = AI_STATE_NOTHING;
 
			break;
 

	
 
		case AYSTAR_FOUND_END_NODE: // We found the end-point
 
			p->ainew.temp = -1;
 
			p->ainew.state = AI_STATE_FIND_DEPOT;
 
			_players_ainew[p->index].temp = -1;
 
			_players_ainew[p->index].state = AI_STATE_FIND_DEPOT;
 
			break;
 

	
 
		// In any other case, we are still busy finding the route
 
		default: break;
 
	}
 
}
 
@@ -784,122 +786,122 @@ static void AiNew_State_FindDepot(Player
 
	// But first we walk through the route see if we can find a depot that is ours
 
	//  this keeps things nice ;)
 
	int g, i;
 
	CommandCost r;
 
	DiagDirection j;
 
	TileIndex tile;
 
	assert(p->ainew.state == AI_STATE_FIND_DEPOT);
 
	assert(_players_ainew[p->index].state == AI_STATE_FIND_DEPOT);
 

	
 
	p->ainew.depot_tile = 0;
 
	_players_ainew[p->index].depot_tile = 0;
 

	
 
	for (i=2;i<p->ainew.path_info.route_length-2;i++) {
 
		tile = p->ainew.path_info.route[i];
 
	for (i=2;i<_players_ainew[p->index].path_info.route_length-2;i++) {
 
		tile = _players_ainew[p->index].path_info.route[i];
 
		for (j = DIAGDIR_BEGIN; j < DIAGDIR_END; j++) {
 
			TileIndex t = tile + TileOffsByDiagDir(j);
 

	
 
			if (IsTileType(t, MP_ROAD) &&
 
					GetRoadTileType(t) == ROAD_TILE_DEPOT &&
 
					IsTileOwner(t, _current_player) &&
 
					GetRoadDepotDirection(t) == ReverseDiagDir(j)) {
 
				p->ainew.depot_tile = t;
 
				p->ainew.depot_direction = ReverseDiagDir(j);
 
				p->ainew.state = AI_STATE_VERIFY_ROUTE;
 
				_players_ainew[p->index].depot_tile = t;
 
				_players_ainew[p->index].depot_direction = ReverseDiagDir(j);
 
				_players_ainew[p->index].state = AI_STATE_VERIFY_ROUTE;
 
				return;
 
			}
 
		}
 
	}
 

	
 
	// This routine let depot finding start in the middle, and work his way to the stations
 
	// It makes depot placing nicer :)
 
	i = p->ainew.path_info.route_length / 2;
 
	i = _players_ainew[p->index].path_info.route_length / 2;
 
	g = 1;
 
	while (i > 1 && i < p->ainew.path_info.route_length - 2) {
 
	while (i > 1 && i < _players_ainew[p->index].path_info.route_length - 2) {
 
		i += g;
 
		g *= -1;
 
		(g < 0?g--:g++);
 

	
 
		if (p->ainew.path_info.route_extra[i] != 0 || p->ainew.path_info.route_extra[i+1] != 0) {
 
		if (_players_ainew[p->index].path_info.route_extra[i] != 0 || _players_ainew[p->index].path_info.route_extra[i+1] != 0) {
 
			// Bridge or tunnel.. we can't place a depot there
 
			continue;
 
		}
 

	
 
		tile = p->ainew.path_info.route[i];
 
		tile = _players_ainew[p->index].path_info.route[i];
 

	
 
		for (j = DIAGDIR_BEGIN; j < DIAGDIR_END; j++) {
 
			TileIndex t = tile + TileOffsByDiagDir(j);
 

	
 
			// It may not be placed on the road/rail itself
 
			// And because it is not build yet, we can't see it on the tile..
 
			// So check the surrounding tiles :)
 
			if (t == p->ainew.path_info.route[i - 1] ||
 
					t == p->ainew.path_info.route[i + 1]) {
 
			if (t == _players_ainew[p->index].path_info.route[i - 1] ||
 
					t == _players_ainew[p->index].path_info.route[i + 1]) {
 
				continue;
 
			}
 
			// Not around a bridge?
 
			if (p->ainew.path_info.route_extra[i] != 0) continue;
 
			if (_players_ainew[p->index].path_info.route_extra[i] != 0) continue;
 
			if (IsTileType(tile, MP_TUNNELBRIDGE)) continue;
 
			// Is the terrain clear?
 
			if (IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)) {
 
				// If the current tile is on a slope then we do not allow this
 
				if (GetTileSlope(tile, NULL) != SLOPE_FLAT) continue;
 
				// Check if everything went okay..
 
				r = AiNew_Build_Depot(p, t, ReverseDiagDir(j), 0);
 
				if (CmdFailed(r)) continue;
 
				// Found a spot!
 
				p->ainew.new_cost += r.GetCost();
 
				p->ainew.depot_tile = t;
 
				p->ainew.depot_direction = ReverseDiagDir(j); // Reverse direction
 
				p->ainew.state = AI_STATE_VERIFY_ROUTE;
 
				_players_ainew[p->index].new_cost += r.GetCost();
 
				_players_ainew[p->index].depot_tile = t;
 
				_players_ainew[p->index].depot_direction = ReverseDiagDir(j); // Reverse direction
 
				_players_ainew[p->index].state = AI_STATE_VERIFY_ROUTE;
 
				return;
 
			}
 
		}
 
	}
 

	
 
	// Failed to find a depot?
 
	p->ainew.state = AI_STATE_NOTHING;
 
	_players_ainew[p->index].state = AI_STATE_NOTHING;
 
}
 

	
 

	
 
// This function calculates how many vehicles there are needed on this
 
//  traject.
 
// It works pretty simple: get the length, see how much we move around
 
//  and hussle that, and you know how many vehicles there are needed.
 
// It returns the cost for the vehicles
 
static int AiNew_HowManyVehicles(Player *p)
 
{
 
	if (p->ainew.tbt == AI_BUS) {
 
	if (_players_ainew[p->index].tbt == AI_BUS) {
 
		// For bus-routes we look at the time before we are back in the station
 
		EngineID i;
 
		int length, tiles_a_day;
 
		int amount;
 
		i = AiNew_PickVehicle(p);
 
		if (i == INVALID_ENGINE) return 0;
 
		// Passenger run.. how long is the route?
 
		length = p->ainew.path_info.route_length;
 
		length = _players_ainew[p->index].path_info.route_length;
 
		// Calculating tiles a day a vehicle moves is not easy.. this is how it must be done!
 
		tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16;
 
		// We want a vehicle in a station once a month at least, so, calculate it!
 
		// (the * 2 is because we have 2 stations ;))
 
		amount = length * 2 * 2 / tiles_a_day / 30;
 
		if (amount == 0) amount = 1;
 
		return amount;
 
	} else if (p->ainew.tbt == AI_TRUCK) {
 
	} else if (_players_ainew[p->index].tbt == AI_TRUCK) {
 
		// For truck-routes we look at the cargo
 
		EngineID i;
 
		int length, amount, tiles_a_day;
 
		int max_cargo;
 
		i = AiNew_PickVehicle(p);
 
		if (i == INVALID_ENGINE) return 0;
 
		// Passenger run.. how long is the route?
 
		length = p->ainew.path_info.route_length;
 
		length = _players_ainew[p->index].path_info.route_length;
 
		// Calculating tiles a day a vehicle moves is not easy.. this is how it must be done!
 
		tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16;
 
		if (p->ainew.from_deliver) {
 
			max_cargo = GetIndustry(p->ainew.from_ic)->last_month_production[0];
 
		if (_players_ainew[p->index].from_deliver) {
 
			max_cargo = GetIndustry(_players_ainew[p->index].from_ic)->last_month_production[0];
 
		} else {
 
			max_cargo = GetIndustry(p->ainew.to_ic)->last_month_production[0];
 
			max_cargo = GetIndustry(_players_ainew[p->index].to_ic)->last_month_production[0];
 
		}
 

	
 
		// This is because moving 60% is more than we can dream of!
 
		max_cargo *= 6;
 
		max_cargo /= 10;
 
		// We want all the cargo to be gone in a month.. so, we know the cargo it delivers
 
@@ -919,135 +921,135 @@ static int AiNew_HowManyVehicles(Player 
 
//   - If the route went okay
 
//   - Calculates the amount of money needed to build the route
 
//   - Calculates how much vehicles needed for the route
 
static void AiNew_State_VerifyRoute(Player *p)
 
{
 
	int res, i;
 
	assert(p->ainew.state == AI_STATE_VERIFY_ROUTE);
 
	assert(_players_ainew[p->index].state == AI_STATE_VERIFY_ROUTE);
 

	
 
	// Let's calculate the cost of the path..
 
	//  new_cost already contains the cost of the stations
 
	p->ainew.path_info.position = -1;
 
	_players_ainew[p->index].path_info.position = -1;
 

	
 
	do {
 
		p->ainew.path_info.position++;
 
		p->ainew.new_cost += AiNew_Build_RoutePart(p, &p->ainew.path_info, DC_QUERY_COST).GetCost();
 
	} while (p->ainew.path_info.position != -2);
 
		_players_ainew[p->index].path_info.position++;
 
		_players_ainew[p->index].new_cost += AiNew_Build_RoutePart(p, &_players_ainew[p->index].path_info, DC_QUERY_COST).GetCost();
 
	} while (_players_ainew[p->index].path_info.position != -2);
 

	
 
	// Now we know the price of build station + path. Now check how many vehicles
 
	//  we need and what the price for that will be
 
	res = AiNew_HowManyVehicles(p);
 
	// If res == 0, no vehicle was found, or an other problem did occour
 
	if (res == 0) {
 
		p->ainew.state = AI_STATE_NOTHING;
 
		_players_ainew[p->index].state = AI_STATE_NOTHING;
 
		return;
 
	}
 
	p->ainew.amount_veh = res;
 
	p->ainew.cur_veh = 0;
 
	_players_ainew[p->index].amount_veh = res;
 
	_players_ainew[p->index].cur_veh = 0;
 

	
 
	// Check how much it it going to cost us..
 
	for (i=0;i<res;i++) {
 
		p->ainew.new_cost += AiNew_Build_Vehicle(p, 0, DC_QUERY_COST).GetCost();
 
		_players_ainew[p->index].new_cost += AiNew_Build_Vehicle(p, 0, DC_QUERY_COST).GetCost();
 
	}
 

	
 
	// Now we know how much the route is going to cost us
 
	//  Check if we have enough money for it!
 
	if (p->ainew.new_cost > p->player_money - AI_MINIMUM_MONEY) {
 
	if (_players_ainew[p->index].new_cost > p->player_money - AI_MINIMUM_MONEY) {
 
		// Too bad..
 
		DEBUG(ai, 1, "Insufficient funds to build route (%" OTTD_PRINTF64 "d)", (int64)p->ainew.new_cost);
 
		p->ainew.state = AI_STATE_NOTHING;
 
		DEBUG(ai, 1, "Insufficient funds to build route (%" OTTD_PRINTF64 "d)", (int64)_players_ainew[p->index].new_cost);
 
		_players_ainew[p->index].state = AI_STATE_NOTHING;
 
		return;
 
	}
 

	
 
	// Now we can build the route, check the direction of the stations!
 
	if (p->ainew.from_direction == AI_PATHFINDER_NO_DIRECTION) {
 
		p->ainew.from_direction = AiNew_GetDirection(p->ainew.path_info.route[p->ainew.path_info.route_length - 1], p->ainew.path_info.route[p->ainew.path_info.route_length - 2]);
 
	if (_players_ainew[p->index].from_direction == AI_PATHFINDER_NO_DIRECTION) {
 
		_players_ainew[p->index].from_direction = AiNew_GetDirection(_players_ainew[p->index].path_info.route[_players_ainew[p->index].path_info.route_length - 1], _players_ainew[p->index].path_info.route[_players_ainew[p->index].path_info.route_length - 2]);
 
	}
 
	if (p->ainew.to_direction == AI_PATHFINDER_NO_DIRECTION) {
 
		p->ainew.to_direction = AiNew_GetDirection(p->ainew.path_info.route[0], p->ainew.path_info.route[1]);
 
	if (_players_ainew[p->index].to_direction == AI_PATHFINDER_NO_DIRECTION) {
 
		_players_ainew[p->index].to_direction = AiNew_GetDirection(_players_ainew[p->index].path_info.route[0], _players_ainew[p->index].path_info.route[1]);
 
	}
 
	if (p->ainew.from_tile == AI_STATION_RANGE)
 
		p->ainew.from_tile = p->ainew.path_info.route[p->ainew.path_info.route_length - 1];
 
	if (p->ainew.to_tile == AI_STATION_RANGE)
 
		p->ainew.to_tile = p->ainew.path_info.route[0];
 
	if (_players_ainew[p->index].from_tile == AI_STATION_RANGE)
 
		_players_ainew[p->index].from_tile = _players_ainew[p->index].path_info.route[_players_ainew[p->index].path_info.route_length - 1];
 
	if (_players_ainew[p->index].to_tile == AI_STATION_RANGE)
 
		_players_ainew[p->index].to_tile = _players_ainew[p->index].path_info.route[0];
 

	
 
	p->ainew.state = AI_STATE_BUILD_STATION;
 
	p->ainew.temp = 0;
 
	_players_ainew[p->index].state = AI_STATE_BUILD_STATION;
 
	_players_ainew[p->index].temp = 0;
 

	
 
	DEBUG(ai, 1, "The route is set and buildable, building 0x%X to 0x%X...", p->ainew.from_tile, p->ainew.to_tile);
 
	DEBUG(ai, 1, "The route is set and buildable, building 0x%X to 0x%X...", _players_ainew[p->index].from_tile, _players_ainew[p->index].to_tile);
 
}
 

	
 

	
 
// Build the stations
 
static void AiNew_State_BuildStation(Player *p)
 
{
 
	CommandCost res;
 
	assert(p->ainew.state == AI_STATE_BUILD_STATION);
 
	if (p->ainew.temp == 0) {
 
		if (!IsTileType(p->ainew.from_tile, MP_STATION))
 
			res = AiNew_Build_Station(p, p->ainew.tbt, p->ainew.from_tile, 0, 0, p->ainew.from_direction, DC_EXEC);
 
	assert(_players_ainew[p->index].state == AI_STATE_BUILD_STATION);
 
	if (_players_ainew[p->index].temp == 0) {
 
		if (!IsTileType(_players_ainew[p->index].from_tile, MP_STATION))
 
			res = AiNew_Build_Station(p, _players_ainew[p->index].tbt, _players_ainew[p->index].from_tile, 0, 0, _players_ainew[p->index].from_direction, DC_EXEC);
 
	} else {
 
		if (!IsTileType(p->ainew.to_tile, MP_STATION))
 
			res = AiNew_Build_Station(p, p->ainew.tbt, p->ainew.to_tile, 0, 0, p->ainew.to_direction, DC_EXEC);
 
		p->ainew.state = AI_STATE_BUILD_PATH;
 
		if (!IsTileType(_players_ainew[p->index].to_tile, MP_STATION))
 
			res = AiNew_Build_Station(p, _players_ainew[p->index].tbt, _players_ainew[p->index].to_tile, 0, 0, _players_ainew[p->index].to_direction, DC_EXEC);
 
		_players_ainew[p->index].state = AI_STATE_BUILD_PATH;
 
	}
 
	if (CmdFailed(res)) {
 
		DEBUG(ai, 0, "[BuildStation] station could not be built (0x%X)", p->ainew.to_tile);
 
		p->ainew.state = AI_STATE_NOTHING;
 
		DEBUG(ai, 0, "[BuildStation] station could not be built (0x%X)", _players_ainew[p->index].to_tile);
 
		_players_ainew[p->index].state = AI_STATE_NOTHING;
 
		// If the first station _was_ build, destroy it
 
		if (p->ainew.temp != 0)
 
			AI_DoCommand(p->ainew.from_tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
		if (_players_ainew[p->index].temp != 0)
 
			AI_DoCommand(_players_ainew[p->index].from_tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
 
		return;
 
	}
 
	p->ainew.temp++;
 
	_players_ainew[p->index].temp++;
 
}
 

	
 

	
 
// Build the path
 
static void AiNew_State_BuildPath(Player *p)
 
{
 
	assert(p->ainew.state == AI_STATE_BUILD_PATH);
 
	// p->ainew.temp is set to -1 when this function is called for the first time
 
	if (p->ainew.temp == -1) {
 
	assert(_players_ainew[p->index].state == AI_STATE_BUILD_PATH);
 
	// _players_ainew[p->index].temp is set to -1 when this function is called for the first time
 
	if (_players_ainew[p->index].temp == -1) {
 
		DEBUG(ai, 1, "Starting to build new path");
 
		// Init the counter
 
		p->ainew.counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
 
		_players_ainew[p->index].counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
 
		// Set the position to the startingplace (-1 because in a minute we do ++)
 
		p->ainew.path_info.position = -1;
 
		_players_ainew[p->index].path_info.position = -1;
 
		// And don't do this again
 
		p->ainew.temp = 0;
 
		_players_ainew[p->index].temp = 0;
 
	}
 
	// Building goes very fast on normal rate, so we are going to slow it down..
 
	//  By let the counter count from AI_BUILDPATH_PAUSE to 0, we have a nice way :)
 
	if (--p->ainew.counter != 0) return;
 
	p->ainew.counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
 
	if (--_players_ainew[p->index].counter != 0) return;
 
	_players_ainew[p->index].counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
 

	
 
	// Increase the building position
 
	p->ainew.path_info.position++;
 
	_players_ainew[p->index].path_info.position++;
 
	// Build route
 
	AiNew_Build_RoutePart(p, &p->ainew.path_info, DC_EXEC);
 
	if (p->ainew.path_info.position == -2) {
 
	AiNew_Build_RoutePart(p, &_players_ainew[p->index].path_info, DC_EXEC);
 
	if (_players_ainew[p->index].path_info.position == -2) {
 
		// This means we are done building!
 

	
 
		if (p->ainew.tbt == AI_TRUCK && !_patches.roadveh_queue) {
 
		if (_players_ainew[p->index].tbt == AI_TRUCK && !_patches.roadveh_queue) {
 
			// If they not queue, they have to go up and down to try again at a station...
 
			// We don't want that, so try building some road left or right of the station
 
			DiagDirection dir1, dir2, dir3;
 
			TileIndex tile;
 
			CommandCost ret;
 
			for (int i = 0; i < 2; i++) {
 
				if (i == 0) {
 
					tile = p->ainew.from_tile + TileOffsByDiagDir(p->ainew.from_direction);
 
					dir1 = ChangeDiagDir(p->ainew.from_direction, DIAGDIRDIFF_90LEFT);
 
					dir2 = ChangeDiagDir(p->ainew.from_direction, DIAGDIRDIFF_90RIGHT);
 
					dir3 = p->ainew.from_direction;
 
					tile = _players_ainew[p->index].from_tile + TileOffsByDiagDir(_players_ainew[p->index].from_direction);
 
					dir1 = ChangeDiagDir(_players_ainew[p->index].from_direction, DIAGDIRDIFF_90LEFT);
 
					dir2 = ChangeDiagDir(_players_ainew[p->index].from_direction, DIAGDIRDIFF_90RIGHT);
 
					dir3 = _players_ainew[p->index].from_direction;
 
				} else {
 
					tile = p->ainew.to_tile + TileOffsByDiagDir(p->ainew.to_direction);
 
					dir1 = ChangeDiagDir(p->ainew.to_direction, DIAGDIRDIFF_90LEFT);
 
					dir2 = ChangeDiagDir(p->ainew.to_direction, DIAGDIRDIFF_90RIGHT);
 
					dir3 = p->ainew.to_direction;
 
					tile = _players_ainew[p->index].to_tile + TileOffsByDiagDir(_players_ainew[p->index].to_direction);
 
					dir1 = ChangeDiagDir(_players_ainew[p->index].to_direction, DIAGDIRDIFF_90LEFT);
 
					dir2 = ChangeDiagDir(_players_ainew[p->index].to_direction, DIAGDIRDIFF_90RIGHT);
 
					dir3 = _players_ainew[p->index].to_direction;
 
				}
 

	
 
				ret = AI_DoCommand(tile, DiagDirToRoadBits(ReverseDiagDir(dir1)), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
 
				if (CmdSucceeded(ret)) {
 
					TileIndex offset = TileOffsByDiagDir(dir1);
 
					if (IsTileType(tile + offset, MP_CLEAR) || IsTileType(tile + offset, MP_TREES)) {
 
@@ -1082,162 +1084,162 @@ static void AiNew_State_BuildPath(Player
 
						}
 
					}
 
				}
 
			}
 
		}
 

	
 
		DEBUG(ai, 1, "Finished building path, cost: %" OTTD_PRINTF64 "d", (int64)p->ainew.new_cost);
 
		p->ainew.state = AI_STATE_BUILD_DEPOT;
 
		DEBUG(ai, 1, "Finished building path, cost: %" OTTD_PRINTF64 "d", (int64)_players_ainew[p->index].new_cost);
 
		_players_ainew[p->index].state = AI_STATE_BUILD_DEPOT;
 
	}
 
}
 

	
 

	
 
// Builds the depot
 
static void AiNew_State_BuildDepot(Player *p)
 
{
 
	CommandCost res;
 
	assert(p->ainew.state == AI_STATE_BUILD_DEPOT);
 
	assert(_players_ainew[p->index].state == AI_STATE_BUILD_DEPOT);
 

	
 
	if (IsTileType(p->ainew.depot_tile, MP_ROAD) && GetRoadTileType(p->ainew.depot_tile) == ROAD_TILE_DEPOT) {
 
		if (IsTileOwner(p->ainew.depot_tile, _current_player)) {
 
	if (IsTileType(_players_ainew[p->index].depot_tile, MP_ROAD) && GetRoadTileType(_players_ainew[p->index].depot_tile) == ROAD_TILE_DEPOT) {
 
		if (IsTileOwner(_players_ainew[p->index].depot_tile, _current_player)) {
 
			// The depot is already built
 
			p->ainew.state = AI_STATE_BUILD_VEHICLE;
 
			_players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE;
 
			return;
 
		} else {
 
			// There is a depot, but not of our team! :(
 
			p->ainew.state = AI_STATE_NOTHING;
 
			_players_ainew[p->index].state = AI_STATE_NOTHING;
 
			return;
 
		}
 
	}
 

	
 
	// There is a bus on the tile we want to build road on... idle till he is gone! (BAD PERSON! :p)
 
	if (!EnsureNoVehicleOnGround(p->ainew.depot_tile + TileOffsByDiagDir(p->ainew.depot_direction)))
 
	if (!EnsureNoVehicleOnGround(_players_ainew[p->index].depot_tile + TileOffsByDiagDir(_players_ainew[p->index].depot_direction)))
 
		return;
 

	
 
	res = AiNew_Build_Depot(p, p->ainew.depot_tile, p->ainew.depot_direction, DC_EXEC);
 
	res = AiNew_Build_Depot(p, _players_ainew[p->index].depot_tile, _players_ainew[p->index].depot_direction, DC_EXEC);
 
	if (CmdFailed(res)) {
 
		DEBUG(ai, 0, "[BuildDepot] depot could not be built (0x%X)", p->ainew.depot_tile);
 
		p->ainew.state = AI_STATE_NOTHING;
 
		DEBUG(ai, 0, "[BuildDepot] depot could not be built (0x%X)", _players_ainew[p->index].depot_tile);
 
		_players_ainew[p->index].state = AI_STATE_NOTHING;
 
		return;
 
	}
 

	
 
	p->ainew.state = AI_STATE_BUILD_VEHICLE;
 
	p->ainew.idle = 10;
 
	p->ainew.veh_main_id = INVALID_VEHICLE;
 
	_players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE;
 
	_players_ainew[p->index].idle = 10;
 
	_players_ainew[p->index].veh_main_id = INVALID_VEHICLE;
 
}
 

	
 

	
 
// Build vehicles
 
static void AiNew_State_BuildVehicle(Player *p)
 
{
 
	CommandCost res;
 
	assert(p->ainew.state == AI_STATE_BUILD_VEHICLE);
 
	assert(_players_ainew[p->index].state == AI_STATE_BUILD_VEHICLE);
 

	
 
	// Check if we need to build a vehicle
 
	if (p->ainew.amount_veh == 0) {
 
	if (_players_ainew[p->index].amount_veh == 0) {
 
		// Nope, we are done!
 
		// This means: we are all done! The route is open.. go back to NOTHING
 
		//  He will idle some time and it will all start over again.. :)
 
		p->ainew.state = AI_STATE_ACTION_DONE;
 
		_players_ainew[p->index].state = AI_STATE_ACTION_DONE;
 
		return;
 
	}
 
	if (--p->ainew.idle != 0) return;
 
	if (--_players_ainew[p->index].idle != 0) return;
 
	// It is realistic that the AI can only build 1 vehicle a day..
 
	// This makes sure of that!
 
	p->ainew.idle = AI_BUILD_VEHICLE_TIME_BETWEEN;
 
	_players_ainew[p->index].idle = AI_BUILD_VEHICLE_TIME_BETWEEN;
 

	
 
	// Build the vehicle
 
	res = AiNew_Build_Vehicle(p, p->ainew.depot_tile, DC_EXEC);
 
	res = AiNew_Build_Vehicle(p, _players_ainew[p->index].depot_tile, DC_EXEC);
 
	if (CmdFailed(res)) {
 
		// This happens when the AI can't build any more vehicles!
 
		p->ainew.state = AI_STATE_NOTHING;
 
		_players_ainew[p->index].state = AI_STATE_NOTHING;
 
		return;
 
	}
 
	// Increase the current counter
 
	p->ainew.cur_veh++;
 
	_players_ainew[p->index].cur_veh++;
 
	// Decrease the total counter
 
	p->ainew.amount_veh--;
 
	_players_ainew[p->index].amount_veh--;
 
	// Go give some orders!
 
	p->ainew.state = AI_STATE_WAIT_FOR_BUILD;
 
	_players_ainew[p->index].state = AI_STATE_WAIT_FOR_BUILD;
 
}
 

	
 

	
 
// Put the stations in the order list
 
static void AiNew_State_GiveOrders(Player *p)
 
{
 
	int idx;
 
	Order order;
 

	
 
	assert(p->ainew.state == AI_STATE_GIVE_ORDERS);
 
	assert(_players_ainew[p->index].state == AI_STATE_GIVE_ORDERS);
 

	
 
	if (p->ainew.veh_main_id != INVALID_VEHICLE) {
 
		AI_DoCommand(0, p->ainew.veh_id + (p->ainew.veh_main_id << 16), CO_SHARE, DC_EXEC, CMD_CLONE_ORDER);
 
	if (_players_ainew[p->index].veh_main_id != INVALID_VEHICLE) {
 
		AI_DoCommand(0, _players_ainew[p->index].veh_id + (_players_ainew[p->index].veh_main_id << 16), CO_SHARE, DC_EXEC, CMD_CLONE_ORDER);
 

	
 
		p->ainew.state = AI_STATE_START_VEHICLE;
 
		_players_ainew[p->index].state = AI_STATE_START_VEHICLE;
 
		return;
 
	} else {
 
		p->ainew.veh_main_id = p->ainew.veh_id;
 
		_players_ainew[p->index].veh_main_id = _players_ainew[p->index].veh_id;
 
	}
 

	
 
	// Very handy for AI, goto depot.. but yeah, it needs to be activated ;)
 
	if (_patches.gotodepot) {
 
		idx = 0;
 
		order.type = OT_GOTO_DEPOT;
 
		order.flags = OF_UNLOAD;
 
		order.dest = GetDepotByTile(p->ainew.depot_tile)->index;
 
		AI_DoCommand(0, p->ainew.veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
 
		order.dest = GetDepotByTile(_players_ainew[p->index].depot_tile)->index;
 
		AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
 
	}
 

	
 
	idx = 0;
 
	order.type = OT_GOTO_STATION;
 
	order.flags = 0;
 
	order.dest = GetStationIndex(p->ainew.to_tile);
 
	if (p->ainew.tbt == AI_TRUCK && p->ainew.to_deliver)
 
	order.dest = GetStationIndex(_players_ainew[p->index].to_tile);
 
	if (_players_ainew[p->index].tbt == AI_TRUCK && _players_ainew[p->index].to_deliver)
 
		order.flags |= OF_FULL_LOAD;
 
	AI_DoCommand(0, p->ainew.veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
 
	AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
 

	
 
	idx = 0;
 
	order.type = OT_GOTO_STATION;
 
	order.flags = 0;
 
	order.dest = GetStationIndex(p->ainew.from_tile);
 
	if (p->ainew.tbt == AI_TRUCK && p->ainew.from_deliver)
 
	order.dest = GetStationIndex(_players_ainew[p->index].from_tile);
 
	if (_players_ainew[p->index].tbt == AI_TRUCK && _players_ainew[p->index].from_deliver)
 
		order.flags |= OF_FULL_LOAD;
 
	AI_DoCommand(0, p->ainew.veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
 
	AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
 

	
 
	// Start the engines!
 
	p->ainew.state = AI_STATE_START_VEHICLE;
 
	_players_ainew[p->index].state = AI_STATE_START_VEHICLE;
 
}
 

	
 

	
 
// Start the vehicle
 
static void AiNew_State_StartVehicle(Player *p)
 
{
 
	assert(p->ainew.state == AI_STATE_START_VEHICLE);
 
	assert(_players_ainew[p->index].state == AI_STATE_START_VEHICLE);
 

	
 
	// Skip the first order if it is a second vehicle
 
	//  This to make vehicles go different ways..
 
	if (p->ainew.cur_veh & 1)
 
		AI_DoCommand(0, p->ainew.veh_id, 1, DC_EXEC, CMD_SKIP_TO_ORDER);
 
	if (_players_ainew[p->index].cur_veh & 1)
 
		AI_DoCommand(0, _players_ainew[p->index].veh_id, 1, DC_EXEC, CMD_SKIP_TO_ORDER);
 

	
 
	// 3, 2, 1... go! (give START_STOP command ;))
 
	AI_DoCommand(0, p->ainew.veh_id, 0, DC_EXEC, CMD_START_STOP_ROADVEH);
 
	AI_DoCommand(0, _players_ainew[p->index].veh_id, 0, DC_EXEC, CMD_START_STOP_ROADVEH);
 
	// Try to build an other vehicle (that function will stop building when needed)
 
	p->ainew.idle  = 10;
 
	p->ainew.state = AI_STATE_BUILD_VEHICLE;
 
	_players_ainew[p->index].idle  = 10;
 
	_players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE;
 
}
 

	
 

	
 
// Repays money
 
static void AiNew_State_RepayMoney(Player *p)
 
{
 
	uint i;
 

	
 
	for (i = 0; i < AI_LOAN_REPAY; i++) {
 
		AI_DoCommand(0, 0, 0, DC_EXEC, CMD_DECREASE_LOAN);
 
	}
 
	p->ainew.state = AI_STATE_ACTION_DONE;
 
	_players_ainew[p->index].state = AI_STATE_ACTION_DONE;
 
}
 

	
 

	
 
static void AiNew_CheckVehicle(Player *p, Vehicle *v)
 
{
 
	// When a vehicle is under the 6 months, we don't check for anything
 
@@ -1290,13 +1292,13 @@ static void AiNew_State_CheckAllVehicles
 
		// Currently, we only know how to handle road-vehicles
 
		if (v->type != VEH_ROAD) continue;
 

	
 
		AiNew_CheckVehicle(p, v);
 
	}
 

	
 
	p->ainew.state = AI_STATE_ACTION_DONE;
 
	_players_ainew[p->index].state = AI_STATE_ACTION_DONE;
 
}
 

	
 

	
 
// Using the technique simular to the original AI
 
//   Keeps things logical
 
// It really should be in the same order as the AI_STATE's are!
 
@@ -1322,28 +1324,28 @@ static AiNew_StateFunction* const _ainew
 
	AiNew_State_ActionDone,
 
	NULL,
 
};
 

	
 
static void AiNew_OnTick(Player *p)
 
{
 
	if (_ainew_state[p->ainew.state] != NULL)
 
		_ainew_state[p->ainew.state](p);
 
	if (_ainew_state[_players_ainew[p->index].state] != NULL)
 
		_ainew_state[_players_ainew[p->index].state](p);
 
}
 

	
 

	
 
void AiNewDoGameLoop(Player *p)
 
{
 
	if (p->ainew.state == AI_STATE_STARTUP) {
 
	if (_players_ainew[p->index].state == AI_STATE_STARTUP) {
 
		// The AI just got alive!
 
		p->ainew.state = AI_STATE_FIRST_TIME;
 
		p->ainew.tick = 0;
 
		_players_ainew[p->index].state = AI_STATE_FIRST_TIME;
 
		_players_ainew[p->index].tick = 0;
 

	
 
		// Only startup the AI
 
		return;
 
	}
 

	
 
	// We keep a ticker. We use it for competitor_speed
 
	p->ainew.tick++;
 
	_players_ainew[p->index].tick++;
 

	
 
	// If we come here, we can do a tick.. do so!
 
	AiNew_OnTick(p);
 
}
src/ai/trolly/trolly.h
Show inline comments
 
@@ -236,12 +236,28 @@ enum {
 

	
 
typedef void AiNew_StateFunction(Player *p);
 

	
 
// ai_new.c
 
void AiNewDoGameLoop(Player *p);
 

	
 
struct Ai_PathFinderInfo {
 
	TileIndex start_tile_tl; ///< tl = top-left
 
	TileIndex start_tile_br; ///< br = bottom-right
 
	TileIndex end_tile_tl;   ///< tl = top-left
 
	TileIndex end_tile_br;   ///< br = bottom-right
 
	DiagDirection start_direction; ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION
 
	DiagDirection end_direction;   ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION
 

	
 
	TileIndex route[500];
 
	byte route_extra[500];   ///< Some extra information about the route like bridge/tunnel
 
	int route_length;
 
	int position;            ///< Current position in the build-path, needed to build the path
 

	
 
	bool rail_or_road;       ///< true = rail, false = road
 
};
 

	
 
// ai_pathfinder.c
 
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo);
 
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo);
 

	
 
// ai_shared.c
 
int AiNew_GetRailDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c);
 
@@ -256,7 +272,67 @@ CommandCost AiNew_Build_Station(Player *
 
CommandCost AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag);
 
CommandCost AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag);
 
EngineID AiNew_PickVehicle(Player *p);
 
CommandCost AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag);
 
CommandCost AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag);
 

	
 
/* The amount of memory reserved for the AI-special-vehicles */
 
#define AI_MAX_SPECIAL_VEHICLES 100
 

	
 
struct Ai_SpecialVehicle {
 
	VehicleID veh_id;
 
	uint32 flag;
 
};
 

	
 
struct PlayerAiNew {
 
	uint8 state;
 
	uint tick;
 
	uint idle;
 

	
 
	int temp;    ///< A value used in more than one function, but it just temporary
 
	             ///< The use is pretty simple: with this we can 'think' about stuff
 
	             ///<   in more than one tick, and more than one AI. A static will not
 
	             ///<   do, because they are not saved. This way, the AI is almost human ;)
 
	int counter; ///< For the same reason as temp, we have counter. It can count how
 
	             ///<  long we are trying something, and just abort if it takes too long
 

	
 
	/* Pathfinder stuff */
 
	Ai_PathFinderInfo path_info;
 
	AyStar *pathfinder;
 

	
 
	/* Route stuff */
 

	
 
	CargoID cargo;
 
	byte tbt;    ///< train/bus/truck 0/1/2 AI_TRAIN/AI_BUS/AI_TRUCK
 
	Money new_cost;
 

	
 
	byte action;
 

	
 
	int last_id; ///< here is stored the last id of the searched city/industry
 
	Date last_vehiclecheck_date; // Used in CheckVehicle
 
	Ai_SpecialVehicle special_vehicles[AI_MAX_SPECIAL_VEHICLES]; ///< Some vehicles have some special flags
 

	
 
	TileIndex from_tile;
 
	TileIndex to_tile;
 

	
 
	DiagDirectionByte from_direction;
 
	DiagDirectionByte to_direction;
 

	
 
	bool from_deliver; ///< True if this is the station that GIVES cargo
 
	bool to_deliver;
 

	
 
	TileIndex depot_tile;
 
	DiagDirectionByte depot_direction;
 

	
 
	byte amount_veh;       ///< How many vehicles we are going to build in this route
 
	byte cur_veh;          ///< How many vehicles did we bought?
 
	VehicleID veh_id;      ///< Used when bought a vehicle
 
	VehicleID veh_main_id; ///< The ID of the first vehicle, for shared copy
 

	
 
	int from_ic;           ///< ic = industry/city. This is the ID of them
 
	byte from_type;        ///< AI_NO_TYPE/AI_CITY/AI_INDUSTRY
 
	int to_ic;
 
	byte to_type;
 
};
 
extern PlayerAiNew _players_ainew[MAX_PLAYERS];
 

	
 
#endif /* AI_TROLLY_H */
src/oldloader.cpp
Show inline comments
 
@@ -17,12 +17,13 @@
 
#include "train.h"
 
#include "signs.h"
 
#include "debug.h"
 
#include "depot.h"
 
#include "newgrf_config.h"
 
#include "ai/ai.h"
 
#include "ai/default/default.h"
 
#include "zoom_func.h"
 
#include "functions.h"
 
#include "date_func.h"
 
#include "vehicle_func.h"
 
#include "variables.h"
 

	
 
@@ -808,16 +809,16 @@ static const OldChunks player_ai_build_r
 

	
 
static bool OldLoadAIBuildRec(LoadgameState *ls, int num)
 
{
 
	Player *p = GetPlayer(_current_player_id);
 

	
 
	switch (num) {
 
		case 0: return LoadChunk(ls, &p->ai.src, player_ai_build_rec_chunk);
 
		case 1: return LoadChunk(ls, &p->ai.dst, player_ai_build_rec_chunk);
 
		case 2: return LoadChunk(ls, &p->ai.mid1, player_ai_build_rec_chunk);
 
		case 3: return LoadChunk(ls, &p->ai.mid2, player_ai_build_rec_chunk);
 
		case 0: return LoadChunk(ls, &_players_ai[p->index].src, player_ai_build_rec_chunk);
 
		case 1: return LoadChunk(ls, &_players_ai[p->index].dst, player_ai_build_rec_chunk);
 
		case 2: return LoadChunk(ls, &_players_ai[p->index].mid1, player_ai_build_rec_chunk);
 
		case 3: return LoadChunk(ls, &_players_ai[p->index].mid2, player_ai_build_rec_chunk);
 
	}
 

	
 
	return false;
 
}
 
static const OldChunks player_ai_chunk[] = {
 
	OCL_SVAR(  OC_UINT8, PlayerAI, state ),
 
@@ -921,17 +922,16 @@ static const OldChunks player_ai_chunk[]
 

	
 
	OCL_END()
 
};
 

	
 
static bool OldPlayerAI(LoadgameState *ls, int num)
 
{
 
	Player *p = GetPlayer(_current_player_id);
 

	
 
	return LoadChunk(ls, &p->ai, player_ai_chunk);
 
	return LoadChunk(ls, &_players_ai[_current_player_id], player_ai_chunk);
 
}
 

	
 
uint8 ai_tick;
 
static const OldChunks player_chunk[] = {
 
	OCL_VAR ( OC_UINT16,   1, &_old_string_id ),
 
	OCL_SVAR( OC_UINT32, Player, name_2 ),
 
	OCL_SVAR( OC_UINT32, Player, face ),
 
	OCL_VAR ( OC_UINT16,   1, &_old_string_id_2 ),
 
	OCL_SVAR( OC_UINT32, Player, president_name_2 ),
 
@@ -955,13 +955,13 @@ static const OldChunks player_chunk[] = 
 
	OCL_SVAR(                  OC_TILE, Player, last_build_coordinate ),
 
	OCL_SVAR(                 OC_UINT8, Player, num_valid_stat_ent ),
 

	
 
	OCL_CHUNK( 1, OldPlayerAI ),
 

	
 
	OCL_SVAR(  OC_UINT8, Player, block_preview ),
 
	OCL_SVAR(  OC_UINT8, Player, ai.tick ),
 
	 OCL_VAR(  OC_UINT8,   1, &ai_tick ),
 
	OCL_SVAR(  OC_UINT8, Player, avail_railtypes ),
 
	OCL_SVAR(   OC_TILE, Player, location_of_house ),
 
	OCL_SVAR(  OC_UINT8, Player, share_owners[0] ),
 
	OCL_SVAR(  OC_UINT8, Player, share_owners[1] ),
 
	OCL_SVAR(  OC_UINT8, Player, share_owners[2] ),
 
	OCL_SVAR(  OC_UINT8, Player, share_owners[3] ),
 
@@ -979,12 +979,13 @@ static bool LoadOldPlayer(LoadgameState 
 

	
 
	if (!LoadChunk(ls, p, player_chunk)) return false;
 

	
 
	p->name_1 = RemapOldStringID(_old_string_id);
 
	p->president_name_1 = RemapOldStringID(_old_string_id_2);
 
	p->player_money = p->player_money;
 
	_players_ai[_current_player_id].tick = ai_tick;
 

	
 
	if (num == 0) {
 
		/* If the first player has no name, make sure we call it UNNAMED */
 
		if (p->name_1 == 0)
 
			p->name_1 = STR_SV_UNNAMED;
 
	} else {
 
@@ -1004,16 +1005,16 @@ static bool LoadOldPlayer(LoadgameState 
 
	_player_colors[num] = p->player_color;
 
	p->inaugurated_year -= ORIGINAL_BASE_YEAR;
 
	if (p->location_of_house == 0xFFFF)
 
		p->location_of_house = 0;
 

	
 
	/* State 20 for AI players is sell vehicle. Since the AI struct is not
 
	 * really figured out as of now, p->ai.cur_veh; needed for 'sell vehicle'
 
	 * really figured out as of now, _players_ai[p->index].cur_veh; needed for 'sell vehicle'
 
	 * is NULL and the function will crash. To fix this, just change the state
 
	 * to some harmless state, like 'loop vehicle'; 1 */
 
	if (!IsHumanPlayer((PlayerID)num) && p->ai.state == 20) p->ai.state = 1;
 
	if (!IsHumanPlayer((PlayerID)num) && _players_ai[p->index].state == 20) _players_ai[p->index].state = 1;
 

	
 
	if (p->is_ai && (!_networking || _network_server) && _ai.enabled)
 
		AI_StartNewAI(p->index);
 

	
 
	return true;
 
}
src/player.h
Show inline comments
 
@@ -2,18 +2,13 @@
 

	
 
/** @file player.h */
 

	
 
#ifndef PLAYER_H
 
#define PLAYER_H
 

	
 
#include "oldpool.h"
 
#include "aystar.h"
 
#include "rail_type.h"
 
#include "road_func.h"
 
#include "cargo_type.h"
 
#include "command_type.h"
 
#include "date_type.h"
 
#include "engine.h"
 
#include "livery.h"
 
#include "genworld.h"
 
#include "autoreplace_type.h"
 

	
 
@@ -22,142 +17,12 @@ struct PlayerEconomyEntry {
 
	Money expenses;
 
	int32 delivered_cargo;
 
	int32 performance_history; ///< player score (scale 0-1000)
 
	Money company_value;
 
};
 

	
 
struct AiBuildRec {
 
	TileIndex spec_tile;
 
	TileIndex use_tile;
 
	byte rand_rng;
 
	byte cur_building_rule;
 
	byte unk6;
 
	byte unk7;
 
	byte buildcmd_a;
 
	byte buildcmd_b;
 
	byte direction;
 
	CargoID cargo;
 
};
 

	
 
struct PlayerAI {
 
	byte state;
 
	byte tick;            ///< Used to determine how often to move
 
	uint32 state_counter; ///< Can hold tile index!
 
	uint16 timeout_counter;
 

	
 
	byte state_mode;
 
	byte banned_tile_count;
 
	RailTypeByte railtype_to_use;
 

	
 
	CargoID cargo_type;
 
	byte num_wagons;
 
	byte build_kind;
 
	byte num_build_rec;
 
	byte num_loco_to_build;
 
	byte num_want_fullload;
 

	
 
	byte route_type_mask;
 

	
 
	TileIndex start_tile_a;
 
	TileIndex cur_tile_a;
 
	DiagDirectionByte cur_dir_a;
 
	DiagDirectionByte start_dir_a;
 

	
 
	TileIndex start_tile_b;
 
	TileIndex cur_tile_b;
 
	DiagDirectionByte cur_dir_b;
 
	DiagDirectionByte start_dir_b;
 

	
 
	Vehicle *cur_veh; ///< only used by some states
 

	
 
	AiBuildRec src, dst, mid1, mid2;
 

	
 
	VehicleID wagon_list[9];
 
	byte order_list_blocks[20];
 

	
 
	TileIndex banned_tiles[16];
 
	byte banned_val[16];
 
};
 

	
 
struct Ai_PathFinderInfo {
 
	TileIndex start_tile_tl; ///< tl = top-left
 
	TileIndex start_tile_br; ///< br = bottom-right
 
	TileIndex end_tile_tl;   ///< tl = top-left
 
	TileIndex end_tile_br;   ///< br = bottom-right
 
	DiagDirection start_direction; ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION
 
	DiagDirection end_direction;   ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION
 

	
 
	TileIndex route[500];
 
	byte route_extra[500];   ///< Some extra information about the route like bridge/tunnel
 
	int route_length;
 
	int position;            ///< Current position in the build-path, needed to build the path
 

	
 
	bool rail_or_road;       ///< true = rail, false = road
 
};
 

	
 
/* The amount of memory reserved for the AI-special-vehicles */
 
#define AI_MAX_SPECIAL_VEHICLES 100
 

	
 
struct Ai_SpecialVehicle {
 
	VehicleID veh_id;
 
	uint32 flag;
 
};
 

	
 
struct PlayerAiNew {
 
	uint8 state;
 
	uint tick;
 
	uint idle;
 

	
 
	int temp;    ///< A value used in more than one function, but it just temporary
 
	             ///< The use is pretty simple: with this we can 'think' about stuff
 
	             ///<   in more than one tick, and more than one AI. A static will not
 
	             ///<   do, because they are not saved. This way, the AI is almost human ;)
 
	int counter; ///< For the same reason as temp, we have counter. It can count how
 
	             ///<  long we are trying something, and just abort if it takes too long
 

	
 
	/* Pathfinder stuff */
 
	Ai_PathFinderInfo path_info;
 
	AyStar *pathfinder;
 

	
 
	/* Route stuff */
 

	
 
	CargoID cargo;
 
	byte tbt;    ///< train/bus/truck 0/1/2 AI_TRAIN/AI_BUS/AI_TRUCK
 
	Money new_cost;
 

	
 
	byte action;
 

	
 
	int last_id; ///< here is stored the last id of the searched city/industry
 
	Date last_vehiclecheck_date; // Used in CheckVehicle
 
	Ai_SpecialVehicle special_vehicles[AI_MAX_SPECIAL_VEHICLES]; ///< Some vehicles have some special flags
 

	
 
	TileIndex from_tile;
 
	TileIndex to_tile;
 

	
 
	DiagDirectionByte from_direction;
 
	DiagDirectionByte to_direction;
 

	
 
	bool from_deliver; ///< True if this is the station that GIVES cargo
 
	bool to_deliver;
 

	
 
	TileIndex depot_tile;
 
	DiagDirectionByte depot_direction;
 

	
 
	byte amount_veh;       ///< How many vehicles we are going to build in this route
 
	byte cur_veh;          ///< How many vehicles did we bought?
 
	VehicleID veh_id;      ///< Used when bought a vehicle
 
	VehicleID veh_main_id; ///< The ID of the first vehicle, for shared copy
 

	
 
	int from_ic;           ///< ic = industry/city. This is the ID of them
 
	byte from_type;        ///< AI_NO_TYPE/AI_CITY/AI_INDUSTRY
 
	int to_ic;
 
	byte to_type;
 

	
 
};
 

	
 

	
 
/* The "steps" in loan size, in British Pounds! */
 
enum {
 
	LOAN_INTERVAL        = 10000,
 
	LOAN_INTERVAL_OLD_AI = 50000,
 
};
 

	
 
@@ -195,14 +60,12 @@ struct Player {
 
	byte bankrupt_asked; ///< which players were asked about buying it?
 
	int16 bankrupt_timeout;
 
	Money bankrupt_value;
 

	
 
	bool is_active;
 
	bool is_ai;
 
	PlayerAI ai;
 
	PlayerAiNew ainew;
 

	
 
	Money yearly_expenses[3][13];
 
	PlayerEconomyEntry cur_economy;
 
	PlayerEconomyEntry old_economy[24];
 
	EngineRenewList engine_renew_list; ///< Defined later
 
	bool engine_renew;
src/players.cpp
Show inline comments
 
@@ -27,12 +27,14 @@
 
#include "date_func.h"
 
#include "vehicle_func.h"
 
#include "sound_func.h"
 
#include "autoreplace_func.h"
 
#include "autoreplace_gui.h"
 
#include "string_func.h"
 
#include "ai/default/default.h"
 
#include "ai/trolly/trolly.h"
 

	
 
/**
 
 * Sets the local player and updates the patch settings that are set on a
 
 * per-company (player) basis to reflect the core's state in the GUI.
 
 * @param new_player the new player
 
 * @pre IsValidPlayer(new_player) || new_player == PLAYER_SPECTATOR || new_player == OWNER_NONE
 
@@ -438,12 +440,14 @@ static Player *AllocatePlayer()
 
	Player *p;
 
	/* Find a free slot */
 
	FOR_ALL_PLAYERS(p) {
 
		if (!p->is_active) {
 
			PlayerID i = p->index;
 
			memset(p, 0, sizeof(Player));
 
			memset(&_players_ai[i], 0, sizeof(PlayerAI));
 
			memset(&_players_ainew[i], 0, sizeof(PlayerAiNew));
 
			p->index = i;
 
			return p;
 
		}
 
	}
 
	return NULL;
 
}
 
@@ -477,13 +481,13 @@ Player *DoStartupNewPlayer(bool is_ai)
 
	p->name_1 = STR_SV_UNNAMED;
 
	p->is_active = true;
 

	
 
	p->player_money = p->current_loan = 100000;
 

	
 
	p->is_ai = is_ai;
 
	p->ai.state = 5; // AIS_WANT_NEW_ROUTE
 
	_players_ai[p->index].state = 5; // AIS_WANT_NEW_ROUTE
 
	p->share_owners[0] = p->share_owners[1] = p->share_owners[2] = p->share_owners[3] = PLAYER_SPECTATOR;
 

	
 
	p->avail_railtypes = GetPlayerRailtypes(p->index);
 
	p->avail_roadtypes = GetPlayerRoadtypes(p->index);
 
	p->inaugurated_year = _cur_year;
 
	RandomPlayerFaceBits(p->face, (GenderEthnicity)Random(), false); // create a random player face
 
@@ -1190,72 +1194,12 @@ static const SaveLoad _player_economy_de
 
	    SLE_VAR(PlayerEconomyEntry, delivered_cargo,     SLE_INT32),
 
	    SLE_VAR(PlayerEconomyEntry, performance_history, SLE_INT32),
 

	
 
	SLE_END()
 
};
 

	
 
static const SaveLoad _player_ai_desc[] = {
 
	    SLE_VAR(PlayerAI, state,             SLE_UINT8),
 
	    SLE_VAR(PlayerAI, tick,              SLE_UINT8),
 
	SLE_CONDVAR(PlayerAI, state_counter,     SLE_FILE_U16 | SLE_VAR_U32,  0, 12),
 
	SLE_CONDVAR(PlayerAI, state_counter,     SLE_UINT32,                 13, SL_MAX_VERSION),
 
	    SLE_VAR(PlayerAI, timeout_counter,   SLE_UINT16),
 

	
 
	    SLE_VAR(PlayerAI, state_mode,        SLE_UINT8),
 
	    SLE_VAR(PlayerAI, banned_tile_count, SLE_UINT8),
 
	    SLE_VAR(PlayerAI, railtype_to_use,   SLE_UINT8),
 

	
 
	    SLE_VAR(PlayerAI, cargo_type,        SLE_UINT8),
 
	    SLE_VAR(PlayerAI, num_wagons,        SLE_UINT8),
 
	    SLE_VAR(PlayerAI, build_kind,        SLE_UINT8),
 
	    SLE_VAR(PlayerAI, num_build_rec,     SLE_UINT8),
 
	    SLE_VAR(PlayerAI, num_loco_to_build, SLE_UINT8),
 
	    SLE_VAR(PlayerAI, num_want_fullload, SLE_UINT8),
 

	
 
	    SLE_VAR(PlayerAI, route_type_mask,   SLE_UINT8),
 

	
 
	SLE_CONDVAR(PlayerAI, start_tile_a,      SLE_FILE_U16 | SLE_VAR_U32,  0,  5),
 
	SLE_CONDVAR(PlayerAI, start_tile_a,      SLE_UINT32,                  6, SL_MAX_VERSION),
 
	SLE_CONDVAR(PlayerAI, cur_tile_a,        SLE_FILE_U16 | SLE_VAR_U32,  0,  5),
 
	SLE_CONDVAR(PlayerAI, cur_tile_a,        SLE_UINT32,                  6, SL_MAX_VERSION),
 
	    SLE_VAR(PlayerAI, start_dir_a,       SLE_UINT8),
 
	    SLE_VAR(PlayerAI, cur_dir_a,         SLE_UINT8),
 

	
 
	SLE_CONDVAR(PlayerAI, start_tile_b,      SLE_FILE_U16 | SLE_VAR_U32,  0,  5),
 
	SLE_CONDVAR(PlayerAI, start_tile_b,      SLE_UINT32,                  6, SL_MAX_VERSION),
 
	SLE_CONDVAR(PlayerAI, cur_tile_b,        SLE_FILE_U16 | SLE_VAR_U32,  0,  5),
 
	SLE_CONDVAR(PlayerAI, cur_tile_b,        SLE_UINT32,                  6, SL_MAX_VERSION),
 
	    SLE_VAR(PlayerAI, start_dir_b,       SLE_UINT8),
 
	    SLE_VAR(PlayerAI, cur_dir_b,         SLE_UINT8),
 

	
 
	    SLE_REF(PlayerAI, cur_veh,           REF_VEHICLE),
 

	
 
	    SLE_ARR(PlayerAI, wagon_list,        SLE_UINT16, 9),
 
	    SLE_ARR(PlayerAI, order_list_blocks, SLE_UINT8, 20),
 
	    SLE_ARR(PlayerAI, banned_tiles,      SLE_UINT16, 16),
 

	
 
	SLE_CONDNULL(64, 2, SL_MAX_VERSION),
 
	SLE_END()
 
};
 

	
 
static const SaveLoad _player_ai_build_rec_desc[] = {
 
	SLE_CONDVAR(AiBuildRec, spec_tile,         SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
 
	SLE_CONDVAR(AiBuildRec, spec_tile,         SLE_UINT32,                 6, SL_MAX_VERSION),
 
	SLE_CONDVAR(AiBuildRec, use_tile,          SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
 
	SLE_CONDVAR(AiBuildRec, use_tile,          SLE_UINT32,                 6, SL_MAX_VERSION),
 
	    SLE_VAR(AiBuildRec, rand_rng,          SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, cur_building_rule, SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, unk6,              SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, unk7,              SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, buildcmd_a,        SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, buildcmd_b,        SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, direction,         SLE_UINT8),
 
	    SLE_VAR(AiBuildRec, cargo,             SLE_UINT8),
 
	SLE_END()
 
};
 

	
 
static const SaveLoad _player_livery_desc[] = {
 
	SLE_CONDVAR(Livery, in_use,  SLE_BOOL,  34, SL_MAX_VERSION),
 
	SLE_CONDVAR(Livery, colour1, SLE_UINT8, 34, SL_MAX_VERSION),
 
	SLE_CONDVAR(Livery, colour2, SLE_UINT8, 34, SL_MAX_VERSION),
 
	SLE_END()
 
};
 
@@ -1265,16 +1209,13 @@ static void SaveLoad_PLYR(Player* p)
 
	int i;
 

	
 
	SlObject(p, _player_desc);
 

	
 
	/* Write AI? */
 
	if (!IsHumanPlayer(p->index)) {
 
		SlObject(&p->ai, _player_ai_desc);
 
		for (i = 0; i != p->ai.num_build_rec; i++) {
 
			SlObject(&p->ai.src + i, _player_ai_build_rec_desc);
 
		}
 
		SaveLoad_AI(p->index);
 
	}
 

	
 
	/* Write economy */
 
	SlObject(&p->cur_economy, _player_economy_desc);
 

	
 
	/* Write old economy entries. */
0 comments (0 inline, 0 general)