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
 
@@ -2,6 +2,7 @@
 

	
 
#include "../stdafx.h"
 
#include "../openttd.h"
 
#include "../player.h"
 
#include "../variables.h"
 
#include "../command_func.h"
 
#include "../network/network.h"
src/ai/default/default.cpp
Show inline comments
 
@@ -27,11 +27,12 @@
 
#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);
 

	
 
@@ -74,14 +75,14 @@ static TrackBits GetRailTrackStatus(Tile
 

	
 
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)
 
@@ -89,7 +90,7 @@ 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;
 
@@ -101,8 +102,8 @@ static void AiStateVehLoop(Player *p)
 
			/* 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;
 
			}
 

	
 
@@ -110,9 +111,9 @@ static void AiStateVehLoop(Player *p)
 
			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;
 
			}
 

	
 
@@ -121,15 +122,15 @@ static void AiStateVehLoop(Player *p)
 
						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)
 
@@ -230,7 +231,7 @@ static Money AiGetBasePrice(const Player
 
	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;
 
@@ -277,18 +278,18 @@ static EngineID AiChooseShipToReplaceWit
 

	
 
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);
 
	}
 
}
 

	
 
@@ -304,7 +305,7 @@ static void AiRestoreVehicleOrders(Vehic
 

	
 
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;
 

	
 
@@ -334,7 +335,7 @@ 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;
 

	
 
@@ -363,7 +364,7 @@ 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;
 

	
 
@@ -414,24 +415,24 @@ static DoReplaceProc* const _veh_do_repl
 

	
 
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);
 
@@ -641,8 +642,8 @@ static bool AiCheckIfRouteIsGood(Player 
 
	/* 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;
 
	}
 
@@ -670,7 +671,7 @@ static bool AiCheckIfRouteIsGood(Player 
 
		}
 
	}
 

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

	
 
@@ -711,85 +712,85 @@ static void AiWantLongIndustryRoute(Play
 
	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)
 
@@ -814,50 +815,50 @@ static void AiWantMediumIndustryRoute(Pl
 
	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)
 
@@ -882,50 +883,50 @@ static void AiWantShortIndustryRoute(Pla
 
	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)
 
@@ -951,82 +952,82 @@ static void AiWantMailRoute(Player *p)
 
	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)
 
@@ -1052,57 +1053,57 @@ static void AiWantPassengerRoute(Player 
 
	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);
 
@@ -1139,38 +1140,38 @@ static void AiWantLongRoadIndustryRoute(
 
	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)
 
@@ -1195,38 +1196,38 @@ static void AiWantMediumRoadIndustryRout
 
	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)
 
@@ -1253,38 +1254,38 @@ static void AiWantLongRoadPassengerRoute
 
	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)
 
@@ -1309,38 +1310,38 @@ static void AiWantPassengerRouteInsideTo
 
	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)
 
@@ -1366,7 +1367,7 @@ static void AiWantPassengerAircraftRoute
 
	/* 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;
 
@@ -1422,24 +1423,24 @@ static void AiWantPassengerAircraftRoute
 

	
 

	
 
	// 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)
 
@@ -1452,14 +1453,14 @@ static void AiWantPassengerAircraftRoute
 
	 * 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)
 
@@ -1492,32 +1493,32 @@ static void AiWantOilRigAircraftRoute(Pl
 
	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)
 
@@ -1539,7 +1540,7 @@ static void AiStateWantNewRoute(Player *
 
	int i;
 

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

	
 
@@ -1568,11 +1569,11 @@ static void AiStateWantNewRoute(Player *
 
		}
 

	
 
		// 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;
 
		}
 
	}
 
@@ -1799,16 +1800,16 @@ static void AiStateBuildDefaultRailBlock
 
	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;
 
@@ -1819,22 +1820,22 @@ static void AiStateBuildDefaultRailBlock
 

	
 
			// 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.
 
@@ -1843,7 +1844,7 @@ static void AiStateBuildDefaultRailBlock
 
				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
 
				);
 
			}
 
@@ -1851,15 +1852,15 @@ static void AiStateBuildDefaultRailBlock
 
	}
 

	
 
	// 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)
 
@@ -1896,11 +1897,11 @@ static bool AiDoFollowTrack(const Player
 
{
 
	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;
 
}
 
@@ -1937,8 +1938,8 @@ static bool AiIsTileBanned(const Player*
 
{
 
	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;
 
		}
 
	}
 
@@ -1949,16 +1950,16 @@ static void AiBanTile(Player* p, TileInd
 
{
 
	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++;
 
	}
 
}
 

	
 
@@ -2025,7 +2026,7 @@ static inline void AiCheckBuildRailBridg
 
		}
 

	
 
		// 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);
 
@@ -2042,7 +2043,7 @@ static inline void AiCheckBuildRailTunne
 
	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));
 
@@ -2098,7 +2099,7 @@ static void AiBuildRailRecursive(AiRailF
 
		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]);
 
			}
 

	
 
@@ -2125,18 +2126,18 @@ static void AiBuildRailConstruct(Player 
 

	
 
	// 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;
 
@@ -2146,11 +2147,11 @@ static void AiBuildRailConstruct(Player 
 
	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;
 
	}
 

	
 
@@ -2158,24 +2159,24 @@ static void AiBuildRailConstruct(Player 
 
	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
 
@@ -2185,27 +2186,27 @@ static void AiBuildRailConstruct(Player 
 
		 */
 
		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) {
 
@@ -2220,7 +2221,7 @@ static bool AiRemoveTileAndGoForward(Pla
 
	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)) {
 
@@ -2228,26 +2229,26 @@ static bool AiRemoveTileAndGoForward(Pla
 
			// 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.
 
@@ -2264,12 +2265,12 @@ static bool AiRemoveTileAndGoForward(Pla
 
		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;
 
}
 
@@ -2278,13 +2279,13 @@ static bool AiRemoveTileAndGoForward(Pla
 
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);
 
}
 
@@ -2292,7 +2293,7 @@ static void AiBuildRailDestruct(Player *
 

	
 
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;
 
@@ -2306,12 +2307,12 @@ static void AiBuildRail(Player *p)
 

	
 
			// 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;
 
			}
 
		}
 

	
 
@@ -2328,26 +2329,26 @@ static void AiStateBuildRail(Player *p)
 
	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;
 
@@ -2360,37 +2361,37 @@ static void AiStateBuildRail(Player *p)
 

	
 
		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)
 
@@ -2444,40 +2445,40 @@ static void AiStateBuildRailVeh(Player *
 
	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;
 
	}
 
@@ -2490,22 +2491,22 @@ handle_nocash:
 
	// 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;
 

	
 
@@ -2514,7 +2515,7 @@ handle_nocash:
 
		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);
 
@@ -2524,20 +2525,20 @@ handle_nocash:
 

	
 
	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;
 
@@ -2548,7 +2549,7 @@ static void AiStateDeleteRailBlocks(Play
 
		}
 
	} 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)
 
@@ -2677,8 +2678,8 @@ clear_town_stuff:;
 
// 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) {
 
@@ -2699,16 +2700,16 @@ static void AiStateBuildDefaultRoadBlock
 
	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;
 
@@ -2724,13 +2725,13 @@ static void AiStateBuildDefaultRoadBlock
 

	
 
			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;
 
@@ -2749,15 +2750,15 @@ static void AiStateBuildDefaultRoadBlock
 
	}
 

	
 
	// 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 {
 
@@ -2854,11 +2855,11 @@ static bool AiCheckRoadFinished(Player *
 
{
 
	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];
 
@@ -2875,8 +2876,8 @@ static bool AiCheckRoadFinished(Player *
 

	
 
	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;
 
}
 

	
 
@@ -3019,14 +3020,14 @@ static void AiBuildRoadConstruct(Player 
 

	
 
	// 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;
 
@@ -3036,11 +3037,11 @@ static void AiBuildRoadConstruct(Player 
 
	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;
 
	}
 

	
 
@@ -3049,25 +3050,25 @@ static void AiBuildRoadConstruct(Player 
 
		// 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
 
@@ -3076,28 +3077,28 @@ do_some_terraform:
 
		 */
 
		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) {
 
@@ -3109,24 +3110,24 @@ do_some_terraform:
 

	
 
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;
 
		}
 
	}
 
}
 
@@ -3149,27 +3150,27 @@ static void AiStateBuildRoad(Player *p)
 
	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;
 
@@ -3178,30 +3179,30 @@ static void AiStateBuildRoad(Player *p)
 

	
 
		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)
 
@@ -3219,13 +3220,13 @@ static void AiStateBuildRoadVehicles(Pla
 
	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;
 
	}
 

	
 
@@ -3233,21 +3234,21 @@ static void AiStateBuildRoadVehicles(Pla
 

	
 
	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;
 

	
 
@@ -3256,7 +3257,7 @@ static void AiStateBuildRoadVehicles(Pla
 
		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);
 
@@ -3265,14 +3266,14 @@ static void AiStateBuildRoadVehicles(Pla
 
	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;
 
@@ -3284,7 +3285,7 @@ static void AiStateDeleteRoadBlocks(Play
 
		}
 
	} while (++aib, --num);
 

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

	
 

	
 
@@ -3305,7 +3306,7 @@ static void AiStateAirportStuff(Player *
 
		// 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?
 
@@ -3316,7 +3317,7 @@ static void AiStateAirportStuff(Player *
 

	
 
			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;
 
			}
 

	
 
@@ -3355,11 +3356,11 @@ static void AiStateAirportStuff(Player *
 
			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)
 
@@ -3424,8 +3425,8 @@ static void AiStateBuildDefaultAirportBl
 
	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;
 
	}
 

	
 
@@ -3433,8 +3434,8 @@ static void AiStateBuildDefaultAirportBl
 
	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;
 
@@ -3444,19 +3445,19 @@ static void AiStateBuildDefaultAirportBl
 
			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.
 
@@ -3475,14 +3476,14 @@ static void AiStateBuildDefaultAirportBl
 
	} 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)
 
@@ -3500,12 +3501,12 @@ static void AiStateBuildAircraftVehicles
 
	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
 
@@ -3514,9 +3515,9 @@ static void AiStateBuildAircraftVehicles
 
	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;
 
@@ -3524,7 +3525,7 @@ static void AiStateBuildAircraftVehicles
 
		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);
 
@@ -3534,9 +3535,9 @@ static void AiStateBuildAircraftVehicles
 

	
 
	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)
 
@@ -3556,7 +3557,7 @@ static void AiStateDoShipStuff(Player *p
 

	
 
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) {
 
@@ -3593,7 +3594,7 @@ static void AiStateSellVeh(Player *p)
 

	
 
	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;
 
@@ -3601,7 +3602,7 @@ going_to_depot:;
 
		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)
 
@@ -3612,7 +3613,7 @@ static void AiStateRemoveStation(Player 
 
	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);
 
@@ -3652,9 +3653,9 @@ is_rail_crossing:;
 
			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;
 
				}
 
			}
 
@@ -3662,9 +3663,9 @@ pos_0:
 
			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;
 
				}
 
			}
 
@@ -3672,9 +3673,9 @@ pos_1:
 
			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;
 
				}
 
			}
 
@@ -3682,9 +3683,9 @@ pos_2:
 
			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;
 
				}
 
			}
 
@@ -3755,24 +3756,24 @@ static void AiStateRemoveTrack(Player *p
 
	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[] = {
 
@@ -3949,11 +3950,11 @@ void AiDoGameLoop(Player *p)
 
			"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;
 
@@ -3961,5 +3962,76 @@ void AiDoGameLoop(Player *p)
 
	}
 
#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
 
@@ -4,5 +4,61 @@
 
#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
 
@@ -70,7 +70,7 @@ CommandCost AiNew_Build_Bridge(Player *p
 
	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);
 
@@ -144,7 +144,7 @@ CommandCost AiNew_Build_RoutePart(Player
 
				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);
 
@@ -200,7 +200,7 @@ CommandCost AiNew_Build_RoutePart(Player
 
					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();
 
					}
 

	
 
@@ -226,7 +226,7 @@ CommandCost AiNew_Build_RoutePart(Player
 
// 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 {
 
@@ -244,7 +244,7 @@ EngineID AiNew_PickVehicle(Player *p)
 
			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
 
@@ -272,20 +272,20 @@ void CcAI(bool success, TileIndex tile, 
 
	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;
 
	}
 
}
 

	
 
@@ -296,7 +296,7 @@ CommandCost AiNew_Build_Vehicle(Player *
 
	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);
 
@@ -308,7 +308,7 @@ CommandCost AiNew_Build_Vehicle(Player *
 
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);
src/ai/trolly/pathfinder.cpp
Show inline comments
 
@@ -27,14 +27,14 @@ static bool TestCanBuildStationHere(Tile
 
		// 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));
 
}
 

	
 

	
src/ai/trolly/shared.cpp
Show inline comments
 
@@ -80,8 +80,8 @@ uint AiNew_GetSpecialVehicleFlag(Player*
 
	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;
 
		}
 
	}
 

	
 
@@ -96,13 +96,13 @@ bool AiNew_SetSpecialVehicleFlag(Player*
 
	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;
 
		}
 
	}
 
@@ -112,7 +112,7 @@ bool AiNew_SetSpecialVehicleFlag(Player*
 
		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
 
@@ -37,6 +37,8 @@
 
#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)
 
{
 
@@ -44,7 +46,7 @@ static void AiNew_State_FirstTime(Player
 
	//   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);
 
@@ -52,20 +54,20 @@ static void AiNew_State_FirstTime(Player
 
	// 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;
 
}
 

	
 

	
 
@@ -78,13 +80,13 @@ static void AiNew_State_FirstTime(Player
 
//  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;
 
	}
 
}
 

	
 
@@ -97,7 +99,7 @@ static void AiNew_State_Nothing(Player *
 
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
 
@@ -112,95 +114,95 @@ static void AiNew_State_WakeUp(Player *p
 
	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;
 
}
 

	
 

	
 
@@ -230,7 +232,7 @@ static bool AiNew_Check_City_or_Industry
 
			// 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?
 
@@ -288,7 +290,7 @@ static bool AiNew_Check_City_or_Industry
 
			// 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?
 
@@ -332,30 +334,30 @@ 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
 
@@ -363,63 +365,63 @@ static void AiNew_State_LocateRoute(Play
 
	}
 

	
 
	// 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..
 
@@ -427,9 +429,9 @@ static void AiNew_State_LocateRoute(Play
 
		 * 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;
 

	
 
@@ -440,23 +442,23 @@ static void AiNew_State_LocateRoute(Play
 
			// 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;
 
@@ -470,8 +472,8 @@ static void AiNew_State_LocateRoute(Play
 
						// 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;
 
					}
 
				}
 
@@ -484,8 +486,8 @@ static void AiNew_State_LocateRoute(Play
 
						// 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;
 
					}
 
				}
 
@@ -497,22 +499,22 @@ static void AiNew_State_LocateRoute(Play
 

	
 
				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;
 
				}
 
@@ -523,16 +525,16 @@ static void AiNew_State_LocateRoute(Play
 
	// 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;
 
}
 

	
 

	
 
@@ -571,29 +573,29 @@ static void AiNew_State_FindStation(Play
 
	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;
 
	}
 

	
 
@@ -604,16 +606,16 @@ static void AiNew_State_FindStation(Play
 
	// 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;
 
@@ -631,11 +633,11 @@ static void AiNew_State_FindStation(Play
 
	// 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;
 
@@ -655,20 +657,20 @@ static void AiNew_State_FindStation(Play
 
					// 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;
 
		}
 

	
 
@@ -685,11 +687,11 @@ static void AiNew_State_FindStation(Play
 
		}
 

	
 
		// 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!
 
@@ -697,17 +699,17 @@ static void AiNew_State_FindStation(Play
 
		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;
 
	}
 
}
 
@@ -717,56 +719,56 @@ static void AiNew_State_FindStation(Play
 
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
 
@@ -787,12 +789,12 @@ static void AiNew_State_FindDepot(Player
 
	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);
 

	
 
@@ -800,9 +802,9 @@ static void AiNew_State_FindDepot(Player
 
					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;
 
			}
 
		}
 
@@ -810,19 +812,19 @@ static void AiNew_State_FindDepot(Player
 

	
 
	// 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);
 
@@ -830,12 +832,12 @@ static void AiNew_State_FindDepot(Player
 
			// 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)) {
 
@@ -845,17 +847,17 @@ static void AiNew_State_FindDepot(Player
 
				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;
 
}
 

	
 

	
 
@@ -866,7 +868,7 @@ static void AiNew_State_FindDepot(Player
 
// 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;
 
@@ -874,7 +876,7 @@ static int AiNew_HowManyVehicles(Player 
 
		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!
 
@@ -882,7 +884,7 @@ static int AiNew_HowManyVehicles(Player 
 
		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;
 
@@ -890,13 +892,13 @@ static int AiNew_HowManyVehicles(Player 
 
		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!
 
@@ -922,58 +924,58 @@ static int AiNew_HowManyVehicles(Player 
 
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);
 
}
 

	
 

	
 
@@ -981,54 +983,54 @@ static void AiNew_State_VerifyRoute(Play
 
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;
 
@@ -1036,15 +1038,15 @@ static void AiNew_State_BuildPath(Player
 
			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);
 
@@ -1085,8 +1087,8 @@ 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;
 
	}
 
}
 

	
 
@@ -1095,34 +1097,34 @@ static void AiNew_State_BuildPath(Player
 
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;
 
}
 

	
 

	
 
@@ -1130,34 +1132,34 @@ static void AiNew_State_BuildDepot(Playe
 
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;
 
}
 

	
 

	
 
@@ -1167,15 +1169,15 @@ static void AiNew_State_GiveOrders(Playe
 
	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 ;)
 
@@ -1183,46 +1185,46 @@ static void AiNew_State_GiveOrders(Playe
 
		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;
 
}
 

	
 

	
 
@@ -1234,7 +1236,7 @@ static void AiNew_State_RepayMoney(Playe
 
	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;
 
}
 

	
 

	
 
@@ -1293,7 +1295,7 @@ static void AiNew_State_CheckAllVehicles
 
		AiNew_CheckVehicle(p, v);
 
	}
 

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

	
 

	
 
@@ -1325,24 +1327,24 @@ static AiNew_StateFunction* const _ainew
 

	
 
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
 
@@ -239,6 +239,22 @@ typedef void AiNew_StateFunction(Player 
 
// 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);
 
@@ -259,4 +275,64 @@ 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
 
@@ -20,6 +20,7 @@
 
#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"
 
@@ -811,10 +812,10 @@ static bool OldLoadAIBuildRec(LoadgameSt
 
	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;
 
@@ -924,11 +925,10 @@ static const OldChunks player_ai_chunk[]
 

	
 
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 ),
 
@@ -958,7 +958,7 @@ static const OldChunks player_chunk[] = 
 
	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] ),
 
@@ -982,6 +982,7 @@ static bool LoadOldPlayer(LoadgameState 
 
	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 */
 
@@ -1007,10 +1008,10 @@ static bool LoadOldPlayer(LoadgameState 
 
		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);
src/player.h
Show inline comments
 
@@ -5,12 +5,7 @@
 
#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"
 
@@ -25,136 +20,6 @@ struct PlayerEconomyEntry {
 
	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,
 
@@ -198,8 +63,6 @@ struct Player {
 

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

	
 
	Money yearly_expenses[3][13];
 
	PlayerEconomyEntry cur_economy;
src/players.cpp
Show inline comments
 
@@ -30,6 +30,8 @@
 
#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
 
@@ -441,6 +443,8 @@ static Player *AllocatePlayer()
 
		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;
 
		}
 
@@ -480,7 +484,7 @@ Player *DoStartupNewPlayer(bool is_ai)
 
	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);
 
@@ -1193,66 +1197,6 @@ static const SaveLoad _player_economy_de
 
	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),
 
@@ -1268,10 +1212,7 @@ static void SaveLoad_PLYR(Player* p)
 

	
 
	/* 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 */
0 comments (0 inline, 0 general)