summaryrefslogtreecommitdiff
path: root/src/ai
diff options
context:
space:
mode:
Diffstat (limited to 'src/ai')
-rw-r--r--src/ai/ai.cpp1
-rw-r--r--src/ai/default/default.cpp1422
-rw-r--r--src/ai/default/default.h56
-rw-r--r--src/ai/trolly/build.cpp28
-rw-r--r--src/ai/trolly/pathfinder.cpp4
-rw-r--r--src/ai/trolly/shared.cpp16
-rw-r--r--src/ai/trolly/trolly.cpp614
-rw-r--r--src/ai/trolly/trolly.h76
8 files changed, 1212 insertions, 1005 deletions
diff --git a/src/ai/ai.cpp b/src/ai/ai.cpp
index 4a075b3ad..0654fcaa1 100644
--- a/src/ai/ai.cpp
+++ b/src/ai/ai.cpp
@@ -2,6 +2,7 @@
#include "../stdafx.h"
#include "../openttd.h"
+#include "../player.h"
#include "../variables.h"
#include "../command_func.h"
#include "../network/network.h"
diff --git a/src/ai/default/default.cpp b/src/ai/default/default.cpp
index 71c12c664..51cb9729e 100644
--- a/src/ai/default/default.cpp
+++ b/src/ai/default/default.cpp
@@ -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(TileIndex 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* p)
Money base = _price.station_value;
// adjust base price when more expensive vehicles are available
- switch (p->ai.railtype_to_use) {
+ switch (_players_ai[p->index].railtype_to_use) {
default: NOT_REACHED();
case RAILTYPE_RAIL: break;
case RAILTYPE_ELECTRIC: break;
@@ -277,18 +278,18 @@ static EngineID AiChooseShipToReplaceWith(const Player* p, const Vehicle* v)
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 (_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 (++p->ai.state_counter <= 1387) {
- p->ai.state = AIS_VEH_DO_REPLACE_VEHICLE;
+ 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(Vehicle *v, BackuppedOrders *bak)
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 *p)
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(Player *p)
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_replace_proc[] = {
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;
+ const Vehicle* v = _players_ai[p->index].cur_veh;
- p->ai.state = AIS_VEH_LOOP;
+ _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 *p, FoundRoute *fr, byte bitmask)
/* 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, FoundRoute *fr, byte bitmask)
}
}
- p->ai.route_type_mask |= bitmask;
+ _players_ai[p->index].route_type_mask |= bitmask;
return true;
}
@@ -711,85 +712,85 @@ static void AiWantLongIndustryRoute(Player *p)
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(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 = 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(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 = 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 *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 = 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(Player *p)
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;
+ _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;
-// 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;
+// _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;
- 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].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 AiWantMediumRoadIndustryRoute(Player *p)
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;
+ _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;
-// 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;
+// _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;
- 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].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(Player *p)
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;
+ _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;
-// 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;
+// _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;
- 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].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 AiWantPassengerRouteInsideTown(Player *p)
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;
+ _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;
-// 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;
+// _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;
- 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].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(Player *p)
/* 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(Player *p)
// 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(Player *p)
* 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;
+ _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;
- p->ai.state = AIS_AIRPORT_STUFF;
- p->ai.timeout_counter = 0;
+ _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(Player *p)
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;
+ _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;
- p->ai.state = AIS_AIRPORT_STUFF;
- p->ai.timeout_counter = 0;
+ _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 *p)
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 *p)
}
// 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 AiStateBuildDefaultRailBlocks(Player *p)
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 AiStateBuildDefaultRailBlocks(Player *p)
// 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 AiStateBuildDefaultRailBlocks(Player *p)
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 AiStateBuildDefaultRailBlocks(Player *p)
}
// 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* p)
{
AiRailPathFindData arpfd;
- arpfd.tile = p->ai.start_tile_a;
- arpfd.tile2 = p->ai.cur_tile_a;
+ arpfd.tile = _players_ai[p->index].start_tile_a;
+ arpfd.tile2 = _players_ai[p->index].cur_tile_a;
arpfd.flag = false;
arpfd.count = 0;
- FollowTrack(p->ai.cur_tile_a + TileOffsByDiagDir(p->ai.cur_dir_a), 0x2000 | TRANSPORT_RAIL, 0, ReverseDiagDir(p->ai.cur_dir_a),
+ FollowTrack(_players_ai[p->index].cur_tile_a + TileOffsByDiagDir(_players_ai[p->index].cur_dir_a), 0x2000 | TRANSPORT_RAIL, 0, ReverseDiagDir(_players_ai[p->index].cur_dir_a),
(TPFEnumProc*)AiEnumFollowTrack, NULL, &arpfd);
return arpfd.count > 8;
}
@@ -1937,8 +1938,8 @@ static bool AiIsTileBanned(const Player* p, TileIndex tile, byte val)
{
int i;
- for (i = 0; i != p->ai.banned_tile_count; i++) {
- if (p->ai.banned_tiles[i] == tile && p->ai.banned_val[i] == val) {
+ for (i = 0; i != _players_ai[p->index].banned_tile_count; i++) {
+ if (_players_ai[p->index].banned_tiles[i] == tile && _players_ai[p->index].banned_val[i] == val) {
return true;
}
}
@@ -1949,16 +1950,16 @@ static void AiBanTile(Player* p, TileIndex tile, byte val)
{
uint i;
- for (i = lengthof(p->ai.banned_tiles) - 1; i != 0; i--) {
- p->ai.banned_tiles[i] = p->ai.banned_tiles[i - 1];
- p->ai.banned_val[i] = p->ai.banned_val[i - 1];
+ for (i = lengthof(_players_ai[p->index].banned_tiles) - 1; i != 0; i--) {
+ _players_ai[p->index].banned_tiles[i] = _players_ai[p->index].banned_tiles[i - 1];
+ _players_ai[p->index].banned_val[i] = _players_ai[p->index].banned_val[i - 1];
}
- p->ai.banned_tiles[0] = tile;
- p->ai.banned_val[0] = val;
+ _players_ai[p->index].banned_tiles[0] = tile;
+ _players_ai[p->index].banned_val[0] = val;
- if (p->ai.banned_tile_count != lengthof(p->ai.banned_tiles)) {
- p->ai.banned_tile_count++;
+ 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 AiCheckBuildRailBridgeHere(AiRailFinder *arf, TileIndex tile,
}
// 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 AiCheckBuildRailTunnelHere(AiRailFinder *arf, TileIndex tile,
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(AiRailFinder *arf, TileIndex tile, DiagDirectio
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 *p)
// 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 *p)
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 *p)
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 *p)
*/
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);
+ 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);
- p->ai.cur_tile_a = arf.bridge_end_tile;
- p->ai.state_counter = 0;
+ _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(Player *p)
byte b;
int bit;
const byte *ptr;
- TileIndex tile = p->ai.cur_tile_a;
+ TileIndex tile = _players_ai[p->index].cur_tile_a;
TileIndex tilenew;
if (IsTileType(tile, MP_TUNNELBRIDGE)) {
@@ -2228,26 +2229,26 @@ static bool AiRemoveTileAndGoForward(Player *p)
// 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(Player *p)
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(Player *p)
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 *p)
static void AiBuildRail(Player *p)
{
- switch (p->ai.state_mode) {
+ switch (_players_ai[p->index].state_mode) {
case 0: // Construct mode, build new rail.
AiBuildRailConstruct(p);
break;
@@ -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 *p)
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));
+ tile = TILE_ADD(_players_ai[p->index].src.use_tile, ToTileIndexDiff(ptr->tileoffs));
- cargo = p->ai.cargo_type;
+ 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 (_players_ai[p->index].num_want_fullload != 0) _players_ai[p->index].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_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(Player *p)
}
} 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 AiStateBuildDefaultRoadBlocks(Player *p)
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 AiStateBuildDefaultRoadBlocks(Player *p)
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 AiStateBuildDefaultRoadBlocks(Player *p)
}
// 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 *p)
{
AiRoadEnum are;
TileIndex tile;
- DiagDirection dir = p->ai.cur_dir_a;
+ DiagDirection dir = _players_ai[p->index].cur_dir_a;
uint32 bits;
- are.dest = p->ai.cur_tile_b;
- tile = TILE_MASK(p->ai.cur_tile_a + TileOffsByDiagDir(dir));
+ are.dest = _players_ai[p->index].cur_tile_b;
+ tile = TILE_MASK(_players_ai[p->index].cur_tile_a + TileOffsByDiagDir(dir));
if (IsRoadStopTile(tile) || IsTileDepotType(tile, TRANSPORT_ROAD)) return false;
bits = GetTileTrackStatus(tile, TRANSPORT_ROAD, ROADTYPES_ROAD) & _ai_road_table_and[dir];
@@ -2875,8 +2876,8 @@ static bool AiCheckRoadFinished(Player *p)
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 *p)
// 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 *p)
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 *p)
// Terraform some
do_some_terraform:
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_mode = 1;
+ if (++_players_ai[p->index].state_counter == 21) {
+ _players_ai[p->index].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;
+ _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);
+ DoCommand(tile, _players_ai[p->index].cur_tile_a, i + ((0x80 | ROADTYPES_ROAD) << 8), DC_AUTO | DC_EXEC, CMD_BUILD_BRIDGE);
- p->ai.state_counter = 0;
+ _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(Player *p)
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));
+ tile = TILE_ADD(_players_ai[p->index].src.use_tile, ToTileIndexDiff(ptr->tileoffs));
- veh = AiChooseRoadVehToBuild(p->ai.cargo_type, p->player_money, tile);
+ 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(Player *p)
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(Player *p)
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(Player *p)
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(Player *p)
}
} while (++aib, --num);
- p->ai.state = AIS_0;
+ _players_ai[p->index].state = AIS_0;
}
@@ -3305,7 +3306,7 @@ static void AiStateAirportStuff(Player *p)
// 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 *p)
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 *p)
aib->use_tile = st->airport_tile;
break;
}
- } while (++i != p->ai.num_build_rec);
+ } while (++i != _players_ai[p->index].num_build_rec);
- p->ai.state = AIS_BUILD_DEFAULT_AIRPORT_BLOCKS;
- p->ai.state_mode = 255;
- p->ai.state_counter = 0;
+ _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 AiStateBuildDefaultAirportBlocks(Player *p)
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 AiStateBuildDefaultAirportBlocks(Player *p)
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 AiStateBuildDefaultAirportBlocks(Player *p)
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 AiStateBuildDefaultAirportBlocks(Player *p)
} 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(Player *p)
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));
+ tile = TILE_ADD(_players_ai[p->index].src.use_tile, ToTileIndexDiff(ptr->tileoffs));
- veh = AiChooseAircraftToBuild(p->player_money, p->ai.build_kind != 0 ? 0 : AIR_CTOL);
+ 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(Player *p)
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(Player *p)
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(Player *p)
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 (_players_ai[p->index].num_want_fullload != 0) _players_ai[p->index].num_want_fullload--;
- if (--p->ai.num_loco_to_build == 0) p->ai.state = AIS_0;
+ 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 *p)
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
diff --git a/src/ai/default/default.h b/src/ai/default/default.h
index d367d4a72..9c45d0945 100644
--- a/src/ai/default/default.h
+++ b/src/ai/default/default.h
@@ -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
diff --git a/src/ai/trolly/build.cpp b/src/ai/trolly/build.cpp
index d54575666..388a40b66 100644
--- a/src/ai/trolly/build.cpp
+++ b/src/ai/trolly/build.cpp
@@ -70,7 +70,7 @@ CommandCost AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, by
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 *p, Ai_PathFinderInfo *PathFinderInfo,
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 *p, Ai_PathFinderInfo *PathFinderInfo,
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 *p, Ai_PathFinderInfo *PathFinderInfo,
// 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, uint32 p1, uint32 p2)
Player* p = GetPlayer(_current_player);
if (success) {
- p->ainew.state = AI_STATE_GIVE_ORDERS;
- p->ainew.veh_id = _new_vehicle_id;
+ _players_ainew[p->index].state = AI_STATE_GIVE_ORDERS;
+ _players_ainew[p->index].veh_id = _new_vehicle_id;
- if (GetVehicle(p->ainew.veh_id)->cargo_type != p->ainew.cargo) {
+ if (GetVehicle(_players_ainew[p->index].veh_id)->cargo_type != _players_ainew[p->index].cargo) {
/* Cargo type doesn't match, so refit it */
- if (CmdFailed(DoCommand(tile, p->ainew.veh_id, p->ainew.cargo, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
+ if (CmdFailed(DoCommand(tile, _players_ainew[p->index].veh_id, _players_ainew[p->index].cargo, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
/* Refit failed, so sell the vehicle */
- DoCommand(tile, p->ainew.veh_id, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
- p->ainew.state = AI_STATE_NOTHING;
+ DoCommand(tile, _players_ainew[p->index].veh_id, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
+ _players_ainew[p->index].state = AI_STATE_NOTHING;
}
}
} else {
/* XXX this should be handled more gracefully */
- p->ainew.state = AI_STATE_NOTHING;
+ _players_ainew[p->index].state = AI_STATE_NOTHING;
}
}
@@ -296,7 +296,7 @@ CommandCost AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
EngineID i = AiNew_PickVehicle(p);
if (i == INVALID_ENGINE) return CMD_ERROR;
- if (p->ainew.tbt == AI_TRAIN) return CMD_ERROR;
+ if (_players_ainew[p->index].tbt == AI_TRAIN) return CMD_ERROR;
if (flag & DC_EXEC) {
return AI_DoCommandCc(tile, i, 0, flag, CMD_BUILD_ROAD_VEH, CcAI);
@@ -308,7 +308,7 @@ CommandCost AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
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);
diff --git a/src/ai/trolly/pathfinder.cpp b/src/ai/trolly/pathfinder.cpp
index c670c0eae..945691675 100644
--- a/src/ai/trolly/pathfinder.cpp
+++ b/src/ai/trolly/pathfinder.cpp
@@ -27,14 +27,14 @@ static bool TestCanBuildStationHere(TileIndex tile, byte dir)
// 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));
}
diff --git a/src/ai/trolly/shared.cpp b/src/ai/trolly/shared.cpp
index 2b80021fa..8e0860432 100644
--- a/src/ai/trolly/shared.cpp
+++ b/src/ai/trolly/shared.cpp
@@ -80,8 +80,8 @@ uint AiNew_GetSpecialVehicleFlag(Player* p, Vehicle* v)
uint i;
for (i = 0; i < AI_MAX_SPECIAL_VEHICLES; i++) {
- if (p->ainew.special_vehicles[i].veh_id == v->index) {
- return p->ainew.special_vehicles[i].flag;
+ if (_players_ainew[p->index].special_vehicles[i].veh_id == v->index) {
+ return _players_ainew[p->index].special_vehicles[i].flag;
}
}
@@ -96,13 +96,13 @@ bool AiNew_SetSpecialVehicleFlag(Player* p, Vehicle* v, uint flag)
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* p, Vehicle* v, uint flag)
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;
}
diff --git a/src/ai/trolly/trolly.cpp b/src/ai/trolly/trolly.cpp
index 9ca8988b6..3f0cf58ba 100644
--- a/src/ai/trolly/trolly.cpp
+++ b/src/ai/trolly/trolly.cpp
@@ -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 *p)
// 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 *p)
// 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 *p)
// 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 *p)
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(Player *p, int ic, byte type)
// 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(Player *p, int ic, byte type)
// 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(Player *p, int ic, byte type)
// 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(Player *p)
}
// 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(Player *p)
* 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(Player *p)
// 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(Player *p)
// 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(Player *p)
// 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(Player *p)
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(Player *p)
// 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(Player *p)
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(Player *p)
// Euhmz, this should not happen _EVER_
// Quit finding a route...
if (i == INVALID_ENGINE) {
- p->ainew.state = AI_STATE_NOTHING;
+ _players_ainew[p->index].state = AI_STATE_NOTHING;
return;
}
FOR_ALL_STATIONS(st) {
if (st->owner == _current_player) {
- if (p->ainew.tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) == FACIL_BUS_STOP) {
+ if (_players_ainew[p->index].tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) == FACIL_BUS_STOP) {
if (st->town == town) {
// Check how much cargo there is left in the station
- if ((int)st->goods[p->ainew.cargo].cargo.Count() > RoadVehInfo(i)->capacity * AI_STATION_REUSE_MULTIPLER) {
+ if ((int)st->goods[_players_ainew[p->index].cargo].cargo.Count() > RoadVehInfo(i)->capacity * AI_STATION_REUSE_MULTIPLER) {
if (AiNew_CheckVehicleStation(p, st)) {
// We did found a station that was good enough!
new_tile = st->xy;
@@ -631,11 +633,11 @@ static void AiNew_State_FindStation(Player *p)
// 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(Player *p)
// 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(Player *p)
}
// 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(Player *p)
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(Player *p)
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 *p)
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 *p)
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 *p)
// 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 *p)
// 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 *p)
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 *p)
// 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 *p)
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 *p)
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 *p)
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 *p)
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(Player *p)
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 *p)
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 *p)
}
}
- 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 *p)
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(Player *p)
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(Player *p)
int idx;
Order order;
- assert(p->ainew.state == AI_STATE_GIVE_ORDERS);
+ assert(_players_ainew[p->index].state == AI_STATE_GIVE_ORDERS);
- if (p->ainew.veh_main_id != INVALID_VEHICLE) {
- AI_DoCommand(0, p->ainew.veh_id + (p->ainew.veh_main_id << 16), CO_SHARE, DC_EXEC, CMD_CLONE_ORDER);
+ if (_players_ainew[p->index].veh_main_id != INVALID_VEHICLE) {
+ AI_DoCommand(0, _players_ainew[p->index].veh_id + (_players_ainew[p->index].veh_main_id << 16), CO_SHARE, DC_EXEC, CMD_CLONE_ORDER);
- p->ainew.state = AI_STATE_START_VEHICLE;
+ _players_ainew[p->index].state = AI_STATE_START_VEHICLE;
return;
} else {
- p->ainew.veh_main_id = p->ainew.veh_id;
+ _players_ainew[p->index].veh_main_id = _players_ainew[p->index].veh_id;
}
// Very handy for AI, goto depot.. but yeah, it needs to be activated ;)
@@ -1183,46 +1185,46 @@ static void AiNew_State_GiveOrders(Player *p)
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(Player *p)
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(Player *p)
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_state[] = {
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);
diff --git a/src/ai/trolly/trolly.h b/src/ai/trolly/trolly.h
index 52bad9aa1..c367867f5 100644
--- a/src/ai/trolly/trolly.h
+++ b/src/ai/trolly/trolly.h
@@ -239,6 +239,22 @@ typedef void AiNew_StateFunction(Player *p);
// ai_new.c
void AiNewDoGameLoop(Player *p);
+struct Ai_PathFinderInfo {
+ TileIndex start_tile_tl; ///< tl = top-left
+ TileIndex start_tile_br; ///< br = bottom-right
+ TileIndex end_tile_tl; ///< tl = top-left
+ TileIndex end_tile_br; ///< br = bottom-right
+ DiagDirection start_direction; ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION
+ DiagDirection end_direction; ///< 0 to 3 or AI_PATHFINDER_NO_DIRECTION
+
+ TileIndex route[500];
+ byte route_extra[500]; ///< Some extra information about the route like bridge/tunnel
+ int route_length;
+ int position; ///< Current position in the build-path, needed to build the path
+
+ bool rail_or_road; ///< true = rail, false = road
+};
+
// ai_pathfinder.c
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo);
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo);
@@ -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 */