|
|
@ -34,7 +34,8 @@
|
|
|
|
#include "depot.h"
|
|
|
|
#include "depot.h"
|
|
|
|
|
|
|
|
|
|
|
|
// This function is called after StartUp. It is the init of an AI
|
|
|
|
// This function is called after StartUp. It is the init of an AI
|
|
|
|
static void AiNew_State_FirstTime(Player *p) {
|
|
|
|
static void AiNew_State_FirstTime(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
// This assert is used to protect those function from misuse
|
|
|
|
// This assert is used to protect those function from misuse
|
|
|
|
// You have quickly a small mistake in the state-array
|
|
|
|
// You have quickly a small mistake in the state-array
|
|
|
|
// With that, everything would go wrong. Finding that, is almost impossible
|
|
|
|
// With that, everything would go wrong. Finding that, is almost impossible
|
|
|
@ -65,6 +66,7 @@ static void AiNew_State_FirstTime(Player *p) {
|
|
|
|
p->ainew.state = AI_STATE_WAKE_UP;
|
|
|
|
p->ainew.state = AI_STATE_WAKE_UP;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This function just waste some time
|
|
|
|
// This function just waste some time
|
|
|
|
// It keeps it more real. The AI can build on such tempo no normal user
|
|
|
|
// It keeps it more real. The AI can build on such tempo no normal user
|
|
|
|
// can ever keep up with that. The competitor_speed already delays a bit
|
|
|
|
// can ever keep up with that. The competitor_speed already delays a bit
|
|
|
@ -72,7 +74,8 @@ static void AiNew_State_FirstTime(Player *p) {
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Let's say, we sleep between one and three days if the AI is put on Very Fast.
|
|
|
|
// Let's say, we sleep between one and three days if the AI is put on Very Fast.
|
|
|
|
// This means that on Very Slow it will be between 16 and 48 days.. slow enough?
|
|
|
|
// This means that on Very Slow it will be between 16 and 48 days.. slow enough?
|
|
|
|
static void AiNew_State_Nothing(Player *p) {
|
|
|
|
static void AiNew_State_Nothing(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
assert(p->ainew.state == AI_STATE_NOTHING);
|
|
|
|
assert(p->ainew.state == AI_STATE_NOTHING);
|
|
|
|
// If we are done idling, start over again
|
|
|
|
// If we are done idling, start over again
|
|
|
|
if (p->ainew.idle == 0) p->ainew.idle = RandomRange(DAY_TICKS * 2) + DAY_TICKS;
|
|
|
|
if (p->ainew.idle == 0) p->ainew.idle = RandomRange(DAY_TICKS * 2) + DAY_TICKS;
|
|
|
@ -83,12 +86,14 @@ static void AiNew_State_Nothing(Player *p) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This function picks out a task we are going to do.
|
|
|
|
// This function picks out a task we are going to do.
|
|
|
|
// Currently supported:
|
|
|
|
// Currently supported:
|
|
|
|
// - Make new route
|
|
|
|
// - Make new route
|
|
|
|
// - Check route
|
|
|
|
// - Check route
|
|
|
|
// - Build HQ
|
|
|
|
// - Build HQ
|
|
|
|
static void AiNew_State_WakeUp(Player *p) {
|
|
|
|
static void AiNew_State_WakeUp(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
int32 money;
|
|
|
|
int32 money;
|
|
|
|
int c;
|
|
|
|
int c;
|
|
|
|
assert(p->ainew.state == AI_STATE_WAKE_UP);
|
|
|
|
assert(p->ainew.state == AI_STATE_WAKE_UP);
|
|
|
@ -108,7 +113,8 @@ static void AiNew_State_WakeUp(Player *p) {
|
|
|
|
// Let's pick an action!
|
|
|
|
// Let's pick an action!
|
|
|
|
if (p->ainew.action == AI_ACTION_NONE) {
|
|
|
|
if (p->ainew.action == AI_ACTION_NONE) {
|
|
|
|
c = Random() & 0xFF;
|
|
|
|
c = Random() & 0xFF;
|
|
|
|
if (p->current_loan > 0 && p->old_economy[1].income > AI_MINIMUM_INCOME_FOR_LOAN &&
|
|
|
|
if (p->current_loan > 0 &&
|
|
|
|
|
|
|
|
p->old_economy[1].income > AI_MINIMUM_INCOME_FOR_LOAN &&
|
|
|
|
c < 10) {
|
|
|
|
c < 10) {
|
|
|
|
p->ainew.action = AI_ACTION_REPAY_LOAN;
|
|
|
|
p->ainew.action = AI_ACTION_REPAY_LOAN;
|
|
|
|
} else if (p->ainew.last_vehiclecheck_date + AI_DAYS_BETWEEN_VEHICLE_CHECKS < _date) {
|
|
|
|
} else if (p->ainew.last_vehiclecheck_date + AI_DAYS_BETWEEN_VEHICLE_CHECKS < _date) {
|
|
|
@ -118,8 +124,10 @@ static void AiNew_State_WakeUp(Player *p) {
|
|
|
|
} else if (c < 100 && !_patches.ai_disable_veh_roadveh) {
|
|
|
|
} else if (c < 100 && !_patches.ai_disable_veh_roadveh) {
|
|
|
|
// Do we have any spots for road-vehicles left open?
|
|
|
|
// Do we have any spots for road-vehicles left open?
|
|
|
|
if (GetFreeUnitNumber(VEH_Road) <= _patches.max_roadveh) {
|
|
|
|
if (GetFreeUnitNumber(VEH_Road) <= _patches.max_roadveh) {
|
|
|
|
if (c < 85) p->ainew.action = AI_ACTION_TRUCK_ROUTE;
|
|
|
|
if (c < 85)
|
|
|
|
else p->ainew.action = AI_ACTION_BUS_ROUTE;
|
|
|
|
p->ainew.action = AI_ACTION_TRUCK_ROUTE;
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
p->ainew.action = AI_ACTION_BUS_ROUTE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}/* else if (c < 200 && !_patches.ai_disable_veh_train) {
|
|
|
|
}/* else if (c < 200 && !_patches.ai_disable_veh_train) {
|
|
|
|
if (GetFreeUnitNumber(VEH_Train) <= _patches.max_trains) {
|
|
|
|
if (GetFreeUnitNumber(VEH_Train) <= _patches.max_trains) {
|
|
|
@ -136,18 +144,23 @@ static void AiNew_State_WakeUp(Player *p) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (_patches.ai_disable_veh_roadveh && (
|
|
|
|
if (_patches.ai_disable_veh_roadveh && (
|
|
|
|
p->ainew.action == AI_ACTION_BUS_ROUTE || p->ainew.action == AI_ACTION_TRUCK_ROUTE)) {
|
|
|
|
p->ainew.action == AI_ACTION_BUS_ROUTE ||
|
|
|
|
|
|
|
|
p->ainew.action == AI_ACTION_TRUCK_ROUTE
|
|
|
|
|
|
|
|
)) {
|
|
|
|
p->ainew.action = AI_ACTION_NONE;
|
|
|
|
p->ainew.action = AI_ACTION_NONE;
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (_patches.ai_disable_veh_roadveh && (
|
|
|
|
if (_patches.ai_disable_veh_roadveh && (
|
|
|
|
p->ainew.action == AI_ACTION_BUS_ROUTE || p->ainew.action == AI_ACTION_TRUCK_ROUTE)) {
|
|
|
|
p->ainew.action == AI_ACTION_BUS_ROUTE ||
|
|
|
|
|
|
|
|
p->ainew.action == AI_ACTION_TRUCK_ROUTE
|
|
|
|
|
|
|
|
)) {
|
|
|
|
p->ainew.action = AI_ACTION_NONE;
|
|
|
|
p->ainew.action = AI_ACTION_NONE;
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (p->ainew.action == AI_ACTION_REPAY_LOAN && money > AI_MINIMUM_LOAN_REPAY_MONEY) {
|
|
|
|
if (p->ainew.action == AI_ACTION_REPAY_LOAN &&
|
|
|
|
|
|
|
|
money > AI_MINIMUM_LOAN_REPAY_MONEY) {
|
|
|
|
// We start repaying some money..
|
|
|
|
// We start repaying some money..
|
|
|
|
p->ainew.state = AI_STATE_REPAY_MONEY;
|
|
|
|
p->ainew.state = AI_STATE_REPAY_MONEY;
|
|
|
|
return;
|
|
|
|
return;
|
|
|
@ -160,7 +173,8 @@ static void AiNew_State_WakeUp(Player *p) {
|
|
|
|
|
|
|
|
|
|
|
|
// It is useless to start finding a route if we don't have enough money
|
|
|
|
// It is useless to start finding a route if we don't have enough money
|
|
|
|
// to build the route anyway..
|
|
|
|
// to build the route anyway..
|
|
|
|
if (p->ainew.action == AI_ACTION_BUS_ROUTE && money > AI_MINIMUM_BUS_ROUTE_MONEY) {
|
|
|
|
if (p->ainew.action == AI_ACTION_BUS_ROUTE &&
|
|
|
|
|
|
|
|
money > AI_MINIMUM_BUS_ROUTE_MONEY) {
|
|
|
|
if (GetFreeUnitNumber(VEH_Road) > _patches.max_roadveh) {
|
|
|
|
if (GetFreeUnitNumber(VEH_Road) > _patches.max_roadveh) {
|
|
|
|
p->ainew.action = AI_ACTION_NONE;
|
|
|
|
p->ainew.action = AI_ACTION_NONE;
|
|
|
|
return;
|
|
|
|
return;
|
|
|
@ -170,7 +184,8 @@ static void AiNew_State_WakeUp(Player *p) {
|
|
|
|
p->ainew.tbt = AI_BUS; // Bus-route
|
|
|
|
p->ainew.tbt = AI_BUS; // Bus-route
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (p->ainew.action == AI_ACTION_TRUCK_ROUTE && money > AI_MINIMUM_TRUCK_ROUTE_MONEY) {
|
|
|
|
if (p->ainew.action == AI_ACTION_TRUCK_ROUTE &&
|
|
|
|
|
|
|
|
money > AI_MINIMUM_TRUCK_ROUTE_MONEY) {
|
|
|
|
if (GetFreeUnitNumber(VEH_Road) > _patches.max_roadveh) {
|
|
|
|
if (GetFreeUnitNumber(VEH_Road) > _patches.max_roadveh) {
|
|
|
|
p->ainew.action = AI_ACTION_NONE;
|
|
|
|
p->ainew.action = AI_ACTION_NONE;
|
|
|
|
return;
|
|
|
|
return;
|
|
|
@ -185,13 +200,17 @@ static void AiNew_State_WakeUp(Player *p) {
|
|
|
|
p->ainew.state = AI_STATE_NOTHING;
|
|
|
|
p->ainew.state = AI_STATE_NOTHING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void AiNew_State_ActionDone(Player *p) {
|
|
|
|
|
|
|
|
|
|
|
|
static void AiNew_State_ActionDone(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
p->ainew.action = AI_ACTION_NONE;
|
|
|
|
p->ainew.action = AI_ACTION_NONE;
|
|
|
|
p->ainew.state = AI_STATE_NOTHING;
|
|
|
|
p->ainew.state = AI_STATE_NOTHING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check if a city or industry is good enough to start a route there
|
|
|
|
// Check if a city or industry is good enough to start a route there
|
|
|
|
static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) {
|
|
|
|
static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (type == AI_CITY) {
|
|
|
|
if (type == AI_CITY) {
|
|
|
|
Town *t = GetTown(ic);
|
|
|
|
Town *t = GetTown(ic);
|
|
|
|
Station *st;
|
|
|
|
Station *st;
|
|
|
@ -318,8 +337,10 @@ static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type) {
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This functions tries to locate a good route
|
|
|
|
// This functions tries to locate a good route
|
|
|
|
static void AiNew_State_LocateRoute(Player *p) {
|
|
|
|
static void AiNew_State_LocateRoute(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
assert(p->ainew.state == AI_STATE_LOCATE_ROUTE);
|
|
|
|
assert(p->ainew.state == AI_STATE_LOCATE_ROUTE);
|
|
|
|
// For now, we only support PASSENGERS, CITY and BUSSES
|
|
|
|
// For now, we only support PASSENGERS, CITY and BUSSES
|
|
|
|
|
|
|
|
|
|
|
@ -511,9 +532,11 @@ static void AiNew_State_LocateRoute(Player *p) {
|
|
|
|
p->ainew.last_id = p->ainew.temp;
|
|
|
|
p->ainew.last_id = p->ainew.temp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check if there are not more than a certain amount of vehicles pointed to a certain
|
|
|
|
// Check if there are not more than a certain amount of vehicles pointed to a certain
|
|
|
|
// station. This to prevent 10 busses going to one station, which gives... problems ;)
|
|
|
|
// station. This to prevent 10 busses going to one station, which gives... problems ;)
|
|
|
|
static bool AiNew_CheckVehicleStation(Player *p, Station *st) {
|
|
|
|
static bool AiNew_CheckVehicleStation(Player *p, Station *st)
|
|
|
|
|
|
|
|
{
|
|
|
|
int count = 0;
|
|
|
|
int count = 0;
|
|
|
|
Vehicle *v;
|
|
|
|
Vehicle *v;
|
|
|
|
|
|
|
|
|
|
|
@ -536,7 +559,8 @@ static bool AiNew_CheckVehicleStation(Player *p, Station *st) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// This function finds a good spot for a station
|
|
|
|
// This function finds a good spot for a station
|
|
|
|
static void AiNew_State_FindStation(Player *p) {
|
|
|
|
static void AiNew_State_FindStation(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
TileIndex tile;
|
|
|
|
TileIndex tile;
|
|
|
|
Station *st;
|
|
|
|
Station *st;
|
|
|
|
int i, count = 0;
|
|
|
|
int i, count = 0;
|
|
|
@ -688,8 +712,10 @@ static void AiNew_State_FindStation(Player *p) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// We try to find a path between 2 points
|
|
|
|
// We try to find a path between 2 points
|
|
|
|
static void AiNew_State_FindPath(Player *p) {
|
|
|
|
static void AiNew_State_FindPath(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
int r;
|
|
|
|
assert(p->ainew.state == AI_STATE_FIND_PATH);
|
|
|
|
assert(p->ainew.state == AI_STATE_FIND_PATH);
|
|
|
|
|
|
|
|
|
|
|
@ -746,8 +772,10 @@ static void AiNew_State_FindPath(Player *p) {
|
|
|
|
// In any other case, we are still busy finding the route...
|
|
|
|
// In any other case, we are still busy finding the route...
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// This function tries to locate a good place for a depot!
|
|
|
|
// This function tries to locate a good place for a depot!
|
|
|
|
static void AiNew_State_FindDepot(Player *p) {
|
|
|
|
static void AiNew_State_FindDepot(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
// To place the depot, we walk through the route, and if we find a lovely spot (MP_CLEAR, MP_TREES), we place it there..
|
|
|
|
// To place the depot, we walk through the route, and if we find a lovely spot (MP_CLEAR, MP_TREES), we place it there..
|
|
|
|
// Simple, easy, works!
|
|
|
|
// Simple, easy, works!
|
|
|
|
// To make the depot stand in the middle of the route, we start from the center..
|
|
|
|
// To make the depot stand in the middle of the route, we start from the center..
|
|
|
@ -802,7 +830,8 @@ static void AiNew_State_FindDepot(Player *p) {
|
|
|
|
// And because it is not build yet, we can't see it on the tile..
|
|
|
|
// And because it is not build yet, we can't see it on the tile..
|
|
|
|
// So check the surrounding tiles :)
|
|
|
|
// So check the surrounding tiles :)
|
|
|
|
if (tile + TileOffsByDir(j) == p->ainew.path_info.route[i-1] ||
|
|
|
|
if (tile + TileOffsByDir(j) == p->ainew.path_info.route[i-1] ||
|
|
|
|
tile + TileOffsByDir(j) == p->ainew.path_info.route[i+1]) continue;
|
|
|
|
tile + TileOffsByDir(j) == p->ainew.path_info.route[i+1])
|
|
|
|
|
|
|
|
continue;
|
|
|
|
// Not around a bridge?
|
|
|
|
// Not around a bridge?
|
|
|
|
if (p->ainew.path_info.route_extra[i] != 0) continue;
|
|
|
|
if (p->ainew.path_info.route_extra[i] != 0) continue;
|
|
|
|
if (IsTileType(tile, MP_TUNNELBRIDGE)) continue;
|
|
|
|
if (IsTileType(tile, MP_TUNNELBRIDGE)) continue;
|
|
|
@ -836,7 +865,8 @@ static void AiNew_State_FindDepot(Player *p) {
|
|
|
|
// It works pretty simple: get the length, see how much we move around
|
|
|
|
// It works pretty simple: get the length, see how much we move around
|
|
|
|
// and hussle that, and you know how many vehicles there are needed.
|
|
|
|
// and hussle that, and you know how many vehicles there are needed.
|
|
|
|
// It returns the cost for the vehicles
|
|
|
|
// It returns the cost for the vehicles
|
|
|
|
static int AiNew_HowManyVehicles(Player *p) {
|
|
|
|
static int AiNew_HowManyVehicles(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (p->ainew.tbt == AI_BUS) {
|
|
|
|
if (p->ainew.tbt == AI_BUS) {
|
|
|
|
// For bus-routes we look at the time before we are back in the station
|
|
|
|
// For bus-routes we look at the time before we are back in the station
|
|
|
|
int i, length, tiles_a_day;
|
|
|
|
int i, length, tiles_a_day;
|
|
|
@ -886,7 +916,8 @@ static int AiNew_HowManyVehicles(Player *p) {
|
|
|
|
// - If the route went okay
|
|
|
|
// - If the route went okay
|
|
|
|
// - Calculates the amount of money needed to build the route
|
|
|
|
// - Calculates the amount of money needed to build the route
|
|
|
|
// - Calculates how much vehicles needed for the route
|
|
|
|
// - Calculates how much vehicles needed for the route
|
|
|
|
static void AiNew_State_VerifyRoute(Player *p) {
|
|
|
|
static void AiNew_State_VerifyRoute(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
int res, i;
|
|
|
|
int res, i;
|
|
|
|
assert(p->ainew.state == AI_STATE_VERIFY_ROUTE);
|
|
|
|
assert(p->ainew.state == AI_STATE_VERIFY_ROUTE);
|
|
|
|
|
|
|
|
|
|
|
@ -942,15 +973,16 @@ static void AiNew_State_VerifyRoute(Player *p) {
|
|
|
|
DEBUG(ai,1)("[AiNew] The route is set and buildable.. going to build it!");
|
|
|
|
DEBUG(ai,1)("[AiNew] The route is set and buildable.. going to build it!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Build the stations
|
|
|
|
// Build the stations
|
|
|
|
static void AiNew_State_BuildStation(Player *p) {
|
|
|
|
static void AiNew_State_BuildStation(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
int res = 0;
|
|
|
|
int res = 0;
|
|
|
|
assert(p->ainew.state == AI_STATE_BUILD_STATION);
|
|
|
|
assert(p->ainew.state == AI_STATE_BUILD_STATION);
|
|
|
|
if (p->ainew.temp == 0) {
|
|
|
|
if (p->ainew.temp == 0) {
|
|
|
|
if (!IsTileType(p->ainew.from_tile, MP_STATION))
|
|
|
|
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);
|
|
|
|
res = AiNew_Build_Station(p, p->ainew.tbt, p->ainew.from_tile, 0, 0, p->ainew.from_direction, DC_EXEC);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
else {
|
|
|
|
|
|
|
|
if (!IsTileType(p->ainew.to_tile, MP_STATION))
|
|
|
|
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);
|
|
|
|
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;
|
|
|
|
p->ainew.state = AI_STATE_BUILD_PATH;
|
|
|
@ -966,8 +998,10 @@ static void AiNew_State_BuildStation(Player *p) {
|
|
|
|
p->ainew.temp++;
|
|
|
|
p->ainew.temp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Build the path
|
|
|
|
// Build the path
|
|
|
|
static void AiNew_State_BuildPath(Player *p) {
|
|
|
|
static void AiNew_State_BuildPath(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
assert(p->ainew.state == AI_STATE_BUILD_PATH);
|
|
|
|
assert(p->ainew.state == AI_STATE_BUILD_PATH);
|
|
|
|
// p->ainew.temp is set to -1 when this function is called for the first time
|
|
|
|
// p->ainew.temp is set to -1 when this function is called for the first time
|
|
|
|
if (p->ainew.temp == -1) {
|
|
|
|
if (p->ainew.temp == -1) {
|
|
|
@ -1059,8 +1093,10 @@ static void AiNew_State_BuildPath(Player *p) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Builds the depot
|
|
|
|
// Builds the depot
|
|
|
|
static void AiNew_State_BuildDepot(Player *p) {
|
|
|
|
static void AiNew_State_BuildDepot(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
int res = 0;
|
|
|
|
int res = 0;
|
|
|
|
assert(p->ainew.state == AI_STATE_BUILD_DEPOT);
|
|
|
|
assert(p->ainew.state == AI_STATE_BUILD_DEPOT);
|
|
|
|
|
|
|
|
|
|
|
@ -1092,8 +1128,10 @@ static void AiNew_State_BuildDepot(Player *p) {
|
|
|
|
p->ainew.veh_main_id = (VehicleID)-1;
|
|
|
|
p->ainew.veh_main_id = (VehicleID)-1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Build vehicles
|
|
|
|
// Build vehicles
|
|
|
|
static void AiNew_State_BuildVehicle(Player *p) {
|
|
|
|
static void AiNew_State_BuildVehicle(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
int res;
|
|
|
|
int res;
|
|
|
|
assert(p->ainew.state == AI_STATE_BUILD_VEHICLE);
|
|
|
|
assert(p->ainew.state == AI_STATE_BUILD_VEHICLE);
|
|
|
|
|
|
|
|
|
|
|
@ -1130,8 +1168,10 @@ static void AiNew_State_BuildVehicle(Player *p) {
|
|
|
|
p->ainew.state = AI_STATE_GIVE_ORDERS;
|
|
|
|
p->ainew.state = AI_STATE_GIVE_ORDERS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Put the stations in the order list
|
|
|
|
// Put the stations in the order list
|
|
|
|
static void AiNew_State_GiveOrders(Player *p) {
|
|
|
|
static void AiNew_State_GiveOrders(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
int idx;
|
|
|
|
int idx;
|
|
|
|
Order order;
|
|
|
|
Order order;
|
|
|
|
|
|
|
|
|
|
|
@ -1180,8 +1220,10 @@ static void AiNew_State_GiveOrders(Player *p) {
|
|
|
|
p->ainew.state = AI_STATE_START_VEHICLE;
|
|
|
|
p->ainew.state = AI_STATE_START_VEHICLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Start the vehicle
|
|
|
|
// Start the vehicle
|
|
|
|
static void AiNew_State_StartVehicle(Player *p) {
|
|
|
|
static void AiNew_State_StartVehicle(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
assert(p->ainew.state == AI_STATE_START_VEHICLE);
|
|
|
|
assert(p->ainew.state == AI_STATE_START_VEHICLE);
|
|
|
|
|
|
|
|
|
|
|
|
// 3, 2, 1... go! (give START_STOP command ;))
|
|
|
|
// 3, 2, 1... go! (give START_STOP command ;))
|
|
|
@ -1190,15 +1232,19 @@ static void AiNew_State_StartVehicle(Player *p) {
|
|
|
|
p->ainew.state = AI_STATE_BUILD_VEHICLE;
|
|
|
|
p->ainew.state = AI_STATE_BUILD_VEHICLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Repays money
|
|
|
|
// Repays money
|
|
|
|
static void AiNew_State_RepayMoney(Player *p) {
|
|
|
|
static void AiNew_State_RepayMoney(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int i;
|
|
|
|
for (i=0;i<AI_LOAN_REPAY;i++)
|
|
|
|
for (i=0;i<AI_LOAN_REPAY;i++)
|
|
|
|
DoCommandByTile(0, 0, 0, DC_EXEC, CMD_DECREASE_LOAN);
|
|
|
|
DoCommandByTile(0, 0, 0, DC_EXEC, CMD_DECREASE_LOAN);
|
|
|
|
p->ainew.state = AI_STATE_ACTION_DONE;
|
|
|
|
p->ainew.state = AI_STATE_ACTION_DONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void AiNew_CheckVehicle(Player *p, Vehicle *v) {
|
|
|
|
|
|
|
|
|
|
|
|
static void AiNew_CheckVehicle(Player *p, Vehicle *v)
|
|
|
|
|
|
|
|
{
|
|
|
|
// When a vehicle is under the 6 months, we don't check for anything
|
|
|
|
// When a vehicle is under the 6 months, we don't check for anything
|
|
|
|
if (v->age < 180) return;
|
|
|
|
if (v->age < 180) return;
|
|
|
|
|
|
|
|
|
|
|
@ -1238,8 +1284,10 @@ static void AiNew_CheckVehicle(Player *p, Vehicle *v) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Checks all vehicles if they are still valid and make money and stuff
|
|
|
|
// Checks all vehicles if they are still valid and make money and stuff
|
|
|
|
static void AiNew_State_CheckAllVehicles(Player *p) {
|
|
|
|
static void AiNew_State_CheckAllVehicles(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
Vehicle *v;
|
|
|
|
Vehicle *v;
|
|
|
|
|
|
|
|
|
|
|
|
FOR_ALL_VEHICLES(v) {
|
|
|
|
FOR_ALL_VEHICLES(v) {
|
|
|
@ -1254,6 +1302,7 @@ static void AiNew_State_CheckAllVehicles(Player *p) {
|
|
|
|
p->ainew.state = AI_STATE_ACTION_DONE;
|
|
|
|
p->ainew.state = AI_STATE_ACTION_DONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Using the technique simular to the original AI
|
|
|
|
// Using the technique simular to the original AI
|
|
|
|
// Keeps things logical
|
|
|
|
// Keeps things logical
|
|
|
|
// It really should be in the same order as the AI_STATE's are!
|
|
|
|
// It really should be in the same order as the AI_STATE's are!
|
|
|
@ -1279,15 +1328,17 @@ static AiNew_StateFunction* const _ainew_state[] = {
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static void AiNew_OnTick(Player *p) {
|
|
|
|
static void AiNew_OnTick(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
if (_ainew_state[p->ainew.state] != NULL)
|
|
|
|
if (_ainew_state[p->ainew.state] != NULL)
|
|
|
|
_ainew_state[p->ainew.state](p);
|
|
|
|
_ainew_state[p->ainew.state](p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AiNewDoGameLoop(Player *p) {
|
|
|
|
|
|
|
|
|
|
|
|
void AiNewDoGameLoop(Player *p)
|
|
|
|
|
|
|
|
{
|
|
|
|
// If it is a human player, it is not an AI, so bubye!
|
|
|
|
// If it is a human player, it is not an AI, so bubye!
|
|
|
|
if (IS_HUMAN_PLAYER(_current_player))
|
|
|
|
if (IS_HUMAN_PLAYER(_current_player)) return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (p->ainew.state == AI_STATE_STARTUP) {
|
|
|
|
if (p->ainew.state == AI_STATE_STARTUP) {
|
|
|
|
// The AI just got alive!
|
|
|
|
// The AI just got alive!
|
|
|
@ -1306,15 +1357,19 @@ void AiNewDoGameLoop(Player *p) {
|
|
|
|
case 0: // Very slow
|
|
|
|
case 0: // Very slow
|
|
|
|
if (!(p->ainew.tick&8)) return;
|
|
|
|
if (!(p->ainew.tick&8)) return;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 1: // Slow
|
|
|
|
case 1: // Slow
|
|
|
|
if (!(p->ainew.tick&4)) return;
|
|
|
|
if (!(p->ainew.tick&4)) return;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
case 2:
|
|
|
|
if (!(p->ainew.tick&2)) return;
|
|
|
|
if (!(p->ainew.tick&2)) return;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
case 3:
|
|
|
|
if (!(p->ainew.tick&1)) return;
|
|
|
|
if (!(p->ainew.tick&1)) return;
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case 4: // Very fast
|
|
|
|
case 4: // Very fast
|
|
|
|
default: // Cool, a new speed setting.. ;) VERY fast ;)
|
|
|
|
default: // Cool, a new speed setting.. ;) VERY fast ;)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|