summaryrefslogtreecommitdiff
path: root/src/ai/trolly/trolly.h
blob: a1d8e0cd93ad0527de4c1705b6ef00920e061a45 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
/* $Id$ */

/** @file trolly.h Functions/defines related to the trolly AI. */

#ifndef AI_TROLLY_H
#define AI_TROLLY_H

#include "../../aystar.h"
#include "../../company_type.h"
#include "../../vehicle_type.h"
#include "../../date_type.h"
#include "../../engine_type.h"

/*
 * These defines can be altered to change the behavoir of the AI
 *
 * WARNING:
 *   This can also alter the AI in a negative way. I will never claim these settings
 *   are perfect, but don't change them if you don't know what the effect is.
 */

// How many times it the H multiplied. The higher, the more it will go straight to the
//   end point. The lower, how more it will find the route with the lowest cost.
//   also: the lower, the longer it takes before route is calculated..
#define AI_PATHFINDER_H_MULTIPLER 100

// How many loops may AyStar do before it stops
//   0 = infinite
#define AI_PATHFINDER_LOOPS_PER_TICK 5

// How long may the AI search for one route?
//   0 = infinite
// This number is the number of tiles tested.
//  It takes (AI_PATHFINDER_MAX_SEARCH_NODES / AI_PATHFINDER_LOOPS_PER_TICK) ticks
//  to get here.. with 5000 / 10 = 500. 500 / 74 (one day) = 8 days till it aborts
//   (that is: if the AI is on VERY FAST! :p
#define AI_PATHFINDER_MAX_SEARCH_NODES 5000

// If you enable this, the AI is not allowed to make 90degree turns
#define AI_PATHFINDER_NO_90DEGREES_TURN

// Below are defines for the g-calculation

// Standard penalty given to a tile
#define AI_PATHFINDER_PENALTY 150
// The penalty given to a tile that is going up
#define AI_PATHFINDER_TILE_GOES_UP_PENALTY 450
// The penalty given to a tile which would have to use fundation
#define AI_PATHFINDER_FOUNDATION_PENALTY 100
// Changing direction is a penalty, to prevent curved ways (with that: slow ways)
#define AI_PATHFINDER_DIRECTION_CHANGE_PENALTY 200
// Same penalty, only for when road already exists
#define AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY 50
// A diagonal track cost the same as a straigh, but a diagonal is faster... so give
//  a bonus for using diagonal track
#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
#define AI_PATHFINDER_DIAGONAL_BONUS 95
#else
#define AI_PATHFINDER_DIAGONAL_BONUS 75
#endif
// If a roadblock already exists, it gets a bonus
#define AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS 140
// To prevent 3 direction changes in 3 tiles, this penalty is given in such situation
#define AI_PATHFINDER_CURVE_PENALTY 200

// Penalty a bridge gets per length
#define AI_PATHFINDER_BRIDGE_PENALTY 180
// The penalty for a bridge going up
#define AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY 1000

// Tunnels are expensive...
//  Because of that, every tile the cost is increased with 1/8th of his value
//  This is also true if you are building a tunnel yourself
#define AI_PATHFINDER_TUNNEL_PENALTY 350

/*
 * Ai_New defines
 */

// How long may we search cities and industry for a new route?
#define AI_LOCATE_ROUTE_MAX_COUNTER 200

// How many days must there be between building the first station and the second station
//  within one city. This number is in days and should be more than 4 months.
#define AI_CHECKCITY_DATE_BETWEEN 180

// How many cargo is needed for one station in a city?
#define AI_CHECKCITY_CARGO_PER_STATION 60
// How much cargo must there not be used in a city before we can build a new station?
#define AI_CHECKCITY_NEEDED_CARGO 50
// When there is already a station which takes the same good and the rating of that
//  city is higher than this numer, we are not going to attempt to build anything
//  there
#define AI_CHECKCITY_CARGO_RATING 50
// But, there is a chance of 1 out of this number, that we do ;)
#define AI_CHECKCITY_CARGO_RATING_CHANCE 5
// If a city is too small to contain a station, there is a small chance
//  that we still do so.. just to make the city bigger!
#define AI_CHECKCITY_CITY_CHANCE 5

// This number indicates for every unit of cargo, how many tiles two stations maybe be away
//  from eachother. In other words: if we have 120 units of cargo in one station, and 120 units
//  of the cargo in the other station, both stations can be 96 units away from eachother, if the
//  next number is 0.4.
#define AI_LOCATEROUTE_BUS_CARGO_DISTANCE 0.4
#define AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE 0.7
// In whole tiles, the minimum distance for a truck route
#define AI_LOCATEROUTE_TRUCK_MIN_DISTANCE 30

// The amount of tiles in a square from -X to +X that is scanned for a station spot
//  (so if this number is 10, 20x20 = 400 tiles are scanned for _the_ perfect spot
// Safe values are between 15 and 5
#define AI_FINDSTATION_TILE_RANGE 10

// Building on normal speed goes very fast. Idle this amount of ticks between every
//  building part. It is calculated like this: (4 - competitor_speed) * num + 1
//  where competitor_speed is between 0 (very slow) to 4 (very fast)
#define AI_BUILDPATH_PAUSE 10

// Minimum % of reliabilty a vehicle has to have before the AI buys it
#define AI_VEHICLE_MIN_RELIABILTY 60

// The minimum amount of money a company should always have
#define AI_MINIMUM_MONEY 15000

// If the most cheap route is build, how much is it going to cost..
// This is to prevent the AI from trying to build a route which can not be paid for
#define AI_MINIMUM_BUS_ROUTE_MONEY 25000
#define AI_MINIMUM_TRUCK_ROUTE_MONEY 35000

// The minimum amount of money before we are going to repay any money
#define AI_MINIMUM_LOAN_REPAY_MONEY 40000
// How many repays do we do if we have enough money to do so?
//  Every repay is 10000
#define AI_LOAN_REPAY 2
// How much income must we have before paying back a loan? Month-based (and looked at the last month)
#define AI_MINIMUM_INCOME_FOR_LOAN 7000

// If there is <num> time as much cargo in the station then the vehicle can handle
//  reuse the station instead of building a new one!
#define AI_STATION_REUSE_MULTIPLER 2

// No more than this amount of vehicles per station..
#define AI_CHECK_MAX_VEHICLE_PER_STATION 10

// How many thick between building 2 vehicles
#define AI_BUILD_VEHICLE_TIME_BETWEEN DAY_TICKS

// How many days must there between vehicle checks
//  The more often, the less non-money-making lines there will be
//   but the unfair it may seem to a human company
#define AI_DAYS_BETWEEN_VEHICLE_CHECKS 30

// How money profit does a vehicle needs to make to stay in order
//  This is the profit of this year + profit of last year
//  But also for vehicles that are just one year old. In other words:
//   Vehicles of 2 years do easier meet this setting than vehicles
//   of one year. This is a very good thing. New vehicles are filtered,
//   while old vehicles stay longer, because we do get less in return.
#define AI_MINIMUM_ROUTE_PROFIT 1000

// A vehicle is considered lost when he his cargo is more than 180 days old
#define AI_VEHICLE_LOST_DAYS 180

// How many times may the AI try to find a route before it gives up
#define AI_MAX_TRIES_FOR_SAME_ROUTE 8

/*
 * End of defines
 */

// This stops 90degrees curves
static const byte _illegal_curves[6] = {
	255, 255, // Horz and vert, don't have the effect
	5, // upleft and upright are not valid
	4, // downright and downleft are not valid
	2, // downleft and upleft are not valid
	3, // upright and downright are not valid
};

enum {
	AI_STATE_STARTUP = 0,
	AI_STATE_FIRST_TIME,
	AI_STATE_NOTHING,
	AI_STATE_WAKE_UP,
	AI_STATE_LOCATE_ROUTE,
	AI_STATE_FIND_STATION,
	AI_STATE_FIND_PATH,
	AI_STATE_FIND_DEPOT,
	AI_STATE_VERIFY_ROUTE,
	AI_STATE_BUILD_STATION,
	AI_STATE_BUILD_PATH,
	AI_STATE_BUILD_DEPOT,
	AI_STATE_BUILD_VEHICLE,
	AI_STATE_WAIT_FOR_BUILD,
	AI_STATE_GIVE_ORDERS,
	AI_STATE_START_VEHICLE,
	AI_STATE_REPAY_MONEY,
	AI_STATE_CHECK_ALL_VEHICLES,
	AI_STATE_ACTION_DONE,
	AI_STATE_STOP, // Temporary function to stop the AI
};

// Used for tbt (train/bus/truck)
enum {
	AI_TRAIN = 0,
	AI_BUS,
	AI_TRUCK,
};

enum {
	AI_ACTION_NONE = 0,
	AI_ACTION_BUS_ROUTE,
	AI_ACTION_TRUCK_ROUTE,
	AI_ACTION_REPAY_LOAN,
	AI_ACTION_CHECK_ALL_VEHICLES,
};

// Used for from_type/to_type
enum {
	AI_NO_TYPE = 0,
	AI_CITY,
	AI_INDUSTRY,
};

// Flags for in the vehicle
enum {
	AI_VEHICLEFLAG_SELL = 1,
	// Remember, flags must be in power of 2
};

#define AI_NO_CARGO 0xFF // Means that there is no cargo defined yet (used for industry)
#define AI_NEED_CARGO 0xFE // Used when the AI needs to find out a cargo for the route
#define AI_STATION_RANGE TileXY(MapMaxX(), MapMaxY())

#define AI_PATHFINDER_NO_DIRECTION (byte)-1

// Flags used in user_data
#define AI_PATHFINDER_FLAG_BRIDGE 1
#define AI_PATHFINDER_FLAG_TUNNEL 2

typedef void AiNew_StateFunction(Company *c);

// ai_new.c
void AiNewDoGameLoop(Company *c);

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

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

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

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

// ai_shared.c
int AiNew_GetRailDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c);
int AiNew_GetRoadDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c);
DiagDirection AiNew_GetDirection(TileIndex tile_a, TileIndex tile_b);
bool AiNew_SetSpecialVehicleFlag(Company *c, Vehicle *v, uint flag);
uint AiNew_GetSpecialVehicleFlag(Company *c, Vehicle *v);

// ai_build.c
bool AiNew_Build_CompanyHQ(Company *c, TileIndex tile);
CommandCost AiNew_Build_Station(Company *c, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag);
CommandCost AiNew_Build_Bridge(Company *c, TileIndex tile_a, TileIndex tile_b, byte flag);
CommandCost AiNew_Build_RoutePart(Company *c, Ai_PathFinderInfo *PathFinderInfo, byte flag);
EngineID AiNew_PickVehicle(Company *c);
CommandCost AiNew_Build_Vehicle(Company *c, TileIndex tile, byte flag);
CommandCost AiNew_Build_Depot(Company *c, 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 CompanyAiNew {
	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 CompanyAiNew _companies_ainew[MAX_COMPANIES];

#endif /* AI_TROLLY_H */