~ubuntu-branches/debian/squeeze/openttd/squeeze

« back to all changes in this revision

Viewing changes to src/ai/trolly/trolly.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jordi Mallach, Matthijs Kooijman, Jordi Mallach
  • Date: 2009-04-15 18:22:10 UTC
  • mfrom: (1.1.6 upstream) (2.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090415182210-22ktb8kdbp2tf3bm
[ Matthijs Kooijman ]
* New upstream release.
* Remove Debian specific desktop file, upstream provides one now. 
* Add debian/watch file.

[ Jordi Mallach ]
* Bump Standards-Version to 3.8.1, with no changes required.
* Move to debhelper compat 7. Bump Build-Depends accordingly.
* Use dh_prep.
* Add "set -e" to config script.
* Remove a few extra doc files that get installed by upstream Makefile.
* Add more complete copyright information.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $Id: trolly.cpp 14267 2008-09-07 21:41:47Z rubidium $ */
2
 
 
3
 
/*
4
 
 * This AI was created as a direct reaction to the big demand for some good AIs
5
 
 * in OTTD. Too bad it never left alpha-stage, and it is considered dead in its
6
 
 * current form.
7
 
 * By the time of writing this, we, the creator of this AI and a good friend of
8
 
 * mine, are designing a whole new AI-system that allows us to create AIs
9
 
 * easier and without all the fuzz we encountered while I was working on this
10
 
 * AI. By the time that system is finished, you can expect that this AI will
11
 
 * dissapear, because it is pretty obselete and bad programmed.
12
 
 *
13
 
 * Meanwhile I wish you all much fun with this AI; if you are interested as
14
 
 * AI-developer in this AI, I advise you not stare too long to some code, some
15
 
 * things in here really are... strange ;) But in either way: enjoy :)
16
 
 *
17
 
 *  -- TrueLight :: 2005-09-01
18
 
 */
19
 
 
20
 
#include "../../stdafx.h"
21
 
#include "../../openttd.h"
22
 
#include "../../debug.h"
23
 
#include "../../road_map.h"
24
 
#include "../../station_map.h"
25
 
#include "../../command_func.h"
26
 
#include "trolly.h"
27
 
#include "../../town.h"
28
 
#include "../../industry.h"
29
 
#include "../../station.h"
30
 
#include "../../engine.h"
31
 
#include "../../gui.h"
32
 
#include "../../depot.h"
33
 
#include "../../vehicle_base.h"
34
 
#include "../../vehicle_func.h"
35
 
#include "../../date_func.h"
36
 
#include "../ai.h"
37
 
#include "../../order.h"
38
 
#include "../../player_base.h"
39
 
#include "../../player_func.h"
40
 
 
41
 
#include "table/strings.h"
42
 
 
43
 
PlayerAiNew _players_ainew[MAX_PLAYERS];
44
 
 
45
 
// This function is called after StartUp. It is the init of an AI
46
 
static void AiNew_State_FirstTime(Player *p)
47
 
{
48
 
        // This assert is used to protect those function from misuse
49
 
        //   You have quickly a small mistake in the state-array
50
 
        //   With that, everything would go wrong. Finding that, is almost impossible
51
 
        //   With this assert, that problem can never happen.
52
 
        assert(_players_ainew[p->index].state == AI_STATE_FIRST_TIME);
53
 
        // We first have to init some things
54
 
 
55
 
        if (_current_player == 1) ShowErrorMessage(INVALID_STRING_ID, TEMP_AI_IN_PROGRESS, 0, 0);
56
 
 
57
 
        // The PathFinder (AyStar)
58
 
        // TODO: Maybe when an AI goes bankrupt, this is de-init
59
 
        //  or when coming from a savegame.. should be checked out!
60
 
        _players_ainew[p->index].path_info.start_tile_tl = 0;
61
 
        _players_ainew[p->index].path_info.start_tile_br = 0;
62
 
        _players_ainew[p->index].path_info.end_tile_tl = 0;
63
 
        _players_ainew[p->index].path_info.end_tile_br = 0;
64
 
        _players_ainew[p->index].pathfinder = new_AyStar_AiPathFinder(12, &_players_ainew[p->index].path_info);
65
 
 
66
 
        _players_ainew[p->index].idle = 0;
67
 
        _players_ainew[p->index].last_vehiclecheck_date = _date;
68
 
 
69
 
        // We ALWAYS start with a bus route.. just some basic money ;)
70
 
        _players_ainew[p->index].action = AI_ACTION_BUS_ROUTE;
71
 
 
72
 
        // Let's popup the news, and after that, start building..
73
 
        _players_ainew[p->index].state = AI_STATE_WAKE_UP;
74
 
}
75
 
 
76
 
 
77
 
// This function just waste some time
78
 
//  It keeps it more real. The AI can build on such tempo no normal user
79
 
//  can ever keep up with that. The competitor_speed already delays a bit
80
 
//  but after the AI finished a track it really needs to go to sleep.
81
 
//
82
 
// Let's say, we sleep between one and three days if the AI is put on Very Fast.
83
 
//  This means that on Very Slow it will be between 16 and 48 days.. slow enough?
84
 
static void AiNew_State_Nothing(Player *p)
85
 
{
86
 
        assert(_players_ainew[p->index].state == AI_STATE_NOTHING);
87
 
        // If we are done idling, start over again
88
 
        if (_players_ainew[p->index].idle == 0) _players_ainew[p->index].idle = AI_RandomRange(DAY_TICKS * 2) + DAY_TICKS;
89
 
        if (--_players_ainew[p->index].idle == 0) {
90
 
                // We are done idling.. what you say? Let's do something!
91
 
                // I mean.. the next tick ;)
92
 
                _players_ainew[p->index].state = AI_STATE_WAKE_UP;
93
 
        }
94
 
}
95
 
 
96
 
 
97
 
// This function picks out a task we are going to do.
98
 
//  Currently supported:
99
 
//    - Make new route
100
 
//    - Check route
101
 
//    - Build HQ
102
 
static void AiNew_State_WakeUp(Player *p)
103
 
{
104
 
        int c;
105
 
        assert(_players_ainew[p->index].state == AI_STATE_WAKE_UP);
106
 
        // First, check if we have a HQ
107
 
        if (p->location_of_house == 0) {
108
 
                // We have no HQ yet, build one on a random place
109
 
                // Random till we found a place for it!
110
 
                // TODO: this should not be on a random place..
111
 
                AiNew_Build_CompanyHQ(p, AI_Random() % MapSize());
112
 
                // Enough for now, but we want to come back here the next time
113
 
                //  so we do not change any status
114
 
                return;
115
 
        }
116
 
 
117
 
        Money money = p->player_money - AI_MINIMUM_MONEY;
118
 
 
119
 
        // Let's pick an action!
120
 
        if (_players_ainew[p->index].action == AI_ACTION_NONE) {
121
 
                c = AI_Random() & 0xFF;
122
 
                if (p->current_loan > 0 &&
123
 
                                p->old_economy[1].income > AI_MINIMUM_INCOME_FOR_LOAN &&
124
 
                                c < 10) {
125
 
                        _players_ainew[p->index].action = AI_ACTION_REPAY_LOAN;
126
 
                } else if (_players_ainew[p->index].last_vehiclecheck_date + AI_DAYS_BETWEEN_VEHICLE_CHECKS < _date) {
127
 
                        // Check all vehicles once in a while
128
 
                        _players_ainew[p->index].action = AI_ACTION_CHECK_ALL_VEHICLES;
129
 
                        _players_ainew[p->index].last_vehiclecheck_date = _date;
130
 
                } else if (c < 100 && !_patches.ai_disable_veh_roadveh) {
131
 
                        // Do we have any spots for road-vehicles left open?
132
 
                        if (GetFreeUnitNumber(VEH_ROAD) <= _patches.max_roadveh) {
133
 
                                if (c < 85) {
134
 
                                        _players_ainew[p->index].action = AI_ACTION_TRUCK_ROUTE;
135
 
                                } else {
136
 
                                        _players_ainew[p->index].action = AI_ACTION_BUS_ROUTE;
137
 
                                }
138
 
                        }
139
 
#if 0
140
 
                } else if (c < 200 && !_patches.ai_disable_veh_train) {
141
 
                        if (GetFreeUnitNumber(VEH_TRAIN) <= _patches.max_trains) {
142
 
                                _players_ainew[p->index].action = AI_ACTION_TRAIN_ROUTE;
143
 
                        }
144
 
#endif
145
 
                }
146
 
 
147
 
                _players_ainew[p->index].counter = 0;
148
 
        }
149
 
 
150
 
        if (_players_ainew[p->index].counter++ > AI_MAX_TRIES_FOR_SAME_ROUTE) {
151
 
                _players_ainew[p->index].action = AI_ACTION_NONE;
152
 
                return;
153
 
        }
154
 
 
155
 
        if (_patches.ai_disable_veh_roadveh && (
156
 
                                _players_ainew[p->index].action == AI_ACTION_BUS_ROUTE ||
157
 
                                _players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE
158
 
                        )) {
159
 
                _players_ainew[p->index].action = AI_ACTION_NONE;
160
 
                return;
161
 
        }
162
 
 
163
 
        if (_players_ainew[p->index].action == AI_ACTION_REPAY_LOAN &&
164
 
                        money > AI_MINIMUM_LOAN_REPAY_MONEY) {
165
 
                // We start repaying some money..
166
 
                _players_ainew[p->index].state = AI_STATE_REPAY_MONEY;
167
 
                return;
168
 
        }
169
 
 
170
 
        if (_players_ainew[p->index].action == AI_ACTION_CHECK_ALL_VEHICLES) {
171
 
                _players_ainew[p->index].state = AI_STATE_CHECK_ALL_VEHICLES;
172
 
                return;
173
 
        }
174
 
 
175
 
        // It is useless to start finding a route if we don't have enough money
176
 
        //  to build the route anyway..
177
 
        if (_players_ainew[p->index].action == AI_ACTION_BUS_ROUTE &&
178
 
                        money > AI_MINIMUM_BUS_ROUTE_MONEY) {
179
 
                if (GetFreeUnitNumber(VEH_ROAD) > _patches.max_roadveh) {
180
 
                        _players_ainew[p->index].action = AI_ACTION_NONE;
181
 
                        return;
182
 
                }
183
 
                _players_ainew[p->index].cargo = AI_NEED_CARGO;
184
 
                _players_ainew[p->index].state = AI_STATE_LOCATE_ROUTE;
185
 
                _players_ainew[p->index].tbt = AI_BUS; // Bus-route
186
 
                return;
187
 
        }
188
 
        if (_players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE &&
189
 
                        money > AI_MINIMUM_TRUCK_ROUTE_MONEY) {
190
 
                if (GetFreeUnitNumber(VEH_ROAD) > _patches.max_roadveh) {
191
 
                        _players_ainew[p->index].action = AI_ACTION_NONE;
192
 
                        return;
193
 
                }
194
 
                _players_ainew[p->index].cargo = AI_NEED_CARGO;
195
 
                _players_ainew[p->index].last_id = 0;
196
 
                _players_ainew[p->index].state = AI_STATE_LOCATE_ROUTE;
197
 
                _players_ainew[p->index].tbt = AI_TRUCK;
198
 
                return;
199
 
        }
200
 
 
201
 
        _players_ainew[p->index].state = AI_STATE_NOTHING;
202
 
}
203
 
 
204
 
 
205
 
static void AiNew_State_ActionDone(Player *p)
206
 
{
207
 
        _players_ainew[p->index].action = AI_ACTION_NONE;
208
 
        _players_ainew[p->index].state = AI_STATE_NOTHING;
209
 
}
210
 
 
211
 
 
212
 
// Check if a city or industry is good enough to start a route there
213
 
static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type)
214
 
{
215
 
        if (type == AI_CITY) {
216
 
                const Town* t = GetTown(ic);
217
 
                const Station* st;
218
 
                uint count = 0;
219
 
                int j = 0;
220
 
 
221
 
                // We don't like roadconstructions, don't even true such a city
222
 
                if (t->road_build_months != 0) return false;
223
 
 
224
 
                // Check if the rating in a city is high enough
225
 
                //  If not, take a chance if we want to continue
226
 
                if (t->ratings[_current_player] < 0 && AI_CHANCE16(1, 4)) return false;
227
 
 
228
 
                if (t->max_pass - t->act_pass < AI_CHECKCITY_NEEDED_CARGO && !AI_CHANCE16(1, AI_CHECKCITY_CITY_CHANCE)) return false;
229
 
 
230
 
                // Check if we have build a station in this town the last 6 months
231
 
                //  else we don't do it. This is done, because stat updates can be slow
232
 
                //  and sometimes it takes up to 4 months before the stats are corectly.
233
 
                //  This way we don't get 12 busstations in one city of 100 population ;)
234
 
                FOR_ALL_STATIONS(st) {
235
 
                        // Do we own it?
236
 
                        if (st->owner == _current_player) {
237
 
                                // Are we talking busses?
238
 
                                if (_players_ainew[p->index].tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) != FACIL_BUS_STOP) continue;
239
 
                                // Is it the same city as we are in now?
240
 
                                if (st->town != t) continue;
241
 
                                // When was this station build?
242
 
                                if (_date - st->build_date < AI_CHECKCITY_DATE_BETWEEN) return false;
243
 
                                // Cound the amount of stations in this city that we own
244
 
                                count++;
245
 
                        } else {
246
 
                                // We do not own it, request some info about the station
247
 
                                //  we want to know if this station gets the same good. If so,
248
 
                                //  we want to know its rating. If it is too high, we are not going
249
 
                                //  to build there
250
 
                                if (!st->goods[CT_PASSENGERS].last_speed) continue;
251
 
                                // Is it around our city
252
 
                                if (DistanceManhattan(st->xy, t->xy) > 10) continue;
253
 
                                // It does take this cargo.. what is his rating?
254
 
                                if (st->goods[CT_PASSENGERS].rating < AI_CHECKCITY_CARGO_RATING) continue;
255
 
                                j++;
256
 
                                // When this is the first station, we build a second with no problem ;)
257
 
                                if (j == 1) continue;
258
 
                                // The rating is high.. second station...
259
 
                                //  a little chance that we still continue
260
 
                                //  But if there are 3 stations of this size, we never go on...
261
 
                                if (j == 2 && AI_CHANCE16(1, AI_CHECKCITY_CARGO_RATING_CHANCE)) continue;
262
 
                                // We don't like this station :(
263
 
                                return false;
264
 
                        }
265
 
                }
266
 
 
267
 
                // We are about to add one...
268
 
                count++;
269
 
                // Check if we the city can provide enough cargo for this amount of stations..
270
 
                if (count * AI_CHECKCITY_CARGO_PER_STATION > t->max_pass) return false;
271
 
 
272
 
                // All check are okay, so we can build here!
273
 
                return true;
274
 
        }
275
 
        if (type == AI_INDUSTRY) {
276
 
                const Industry* i = GetIndustry(ic);
277
 
                const Station* st;
278
 
                int count = 0;
279
 
                int j = 0;
280
 
 
281
 
                if (i->town != NULL && i->town->ratings[_current_player] < 0 && AI_CHANCE16(1, 4)) return false;
282
 
 
283
 
                // No limits on delevering stations!
284
 
                //  Or for industry that does not give anything yet
285
 
                if (i->produced_cargo[0] == CT_INVALID || i->last_month_production[0] == 0) return true;
286
 
 
287
 
                if (i->last_month_production[0] - i->last_month_transported[0] < AI_CHECKCITY_NEEDED_CARGO) return false;
288
 
 
289
 
                // Check if we have build a station in this town the last 6 months
290
 
                //  else we don't do it. This is done, because stat updates can be slow
291
 
                //  and sometimes it takes up to 4 months before the stats are corectly.
292
 
                FOR_ALL_STATIONS(st) {
293
 
                        // Do we own it?
294
 
                        if (st->owner == _current_player) {
295
 
                                // Are we talking trucks?
296
 
                                if (_players_ainew[p->index].tbt == AI_TRUCK && (FACIL_TRUCK_STOP & st->facilities) != FACIL_TRUCK_STOP) continue;
297
 
                                // Is it the same city as we are in now?
298
 
                                if (st->town != i->town) continue;
299
 
                                // When was this station build?
300
 
                                if (_date - st->build_date < AI_CHECKCITY_DATE_BETWEEN) return false;
301
 
                                // Cound the amount of stations in this city that we own
302
 
                                count++;
303
 
                        } else {
304
 
                                // We do not own it, request some info about the station
305
 
                                //  we want to know if this station gets the same good. If so,
306
 
                                //  we want to know its rating. If it is too high, we are not going
307
 
                                //  to build there
308
 
                                if (i->produced_cargo[0] == CT_INVALID) continue;
309
 
                                // It does not take this cargo
310
 
                                if (!st->goods[i->produced_cargo[0]].last_speed) continue;
311
 
                                // Is it around our industry
312
 
                                if (DistanceManhattan(st->xy, i->xy) > 5) continue;
313
 
                                // It does take this cargo.. what is his rating?
314
 
                                if (st->goods[i->produced_cargo[0]].rating < AI_CHECKCITY_CARGO_RATING) continue;
315
 
                                j++;
316
 
                                // The rating is high.. a little chance that we still continue
317
 
                                //  But if there are 2 stations of this size, we never go on...
318
 
                                if (j == 1 && AI_CHANCE16(1, AI_CHECKCITY_CARGO_RATING_CHANCE)) continue;
319
 
                                // We don't like this station :(
320
 
                                return false;
321
 
                        }
322
 
                }
323
 
 
324
 
                // We are about to add one...
325
 
                count++;
326
 
                // Check if we the city can provide enough cargo for this amount of stations..
327
 
                if (count * AI_CHECKCITY_CARGO_PER_STATION > i->last_month_production[0]) return false;
328
 
 
329
 
                // All check are okay, so we can build here!
330
 
                return true;
331
 
        }
332
 
 
333
 
        return true;
334
 
}
335
 
 
336
 
 
337
 
// This functions tries to locate a good route
338
 
static void AiNew_State_LocateRoute(Player *p)
339
 
{
340
 
        assert(_players_ainew[p->index].state == AI_STATE_LOCATE_ROUTE);
341
 
        // For now, we only support PASSENGERS, CITY and BUSSES
342
 
 
343
 
        // We don't have a route yet
344
 
        if (_players_ainew[p->index].cargo == AI_NEED_CARGO) {
345
 
                _players_ainew[p->index].new_cost = 0; // No cost yet
346
 
                _players_ainew[p->index].temp = -1;
347
 
                // Reset the counter
348
 
                _players_ainew[p->index].counter = 0;
349
 
 
350
 
                _players_ainew[p->index].from_ic = -1;
351
 
                _players_ainew[p->index].to_ic = -1;
352
 
                if (_players_ainew[p->index].tbt == AI_BUS) {
353
 
                        // For now we only have a passenger route
354
 
                        _players_ainew[p->index].cargo = CT_PASSENGERS;
355
 
 
356
 
                        // Find a route to cities
357
 
                        _players_ainew[p->index].from_type = AI_CITY;
358
 
                        _players_ainew[p->index].to_type = AI_CITY;
359
 
                } else if (_players_ainew[p->index].tbt == AI_TRUCK) {
360
 
                        _players_ainew[p->index].cargo = AI_NO_CARGO;
361
 
 
362
 
                        _players_ainew[p->index].from_type = AI_INDUSTRY;
363
 
                        _players_ainew[p->index].to_type = AI_INDUSTRY;
364
 
                }
365
 
 
366
 
                // Now we are doing initing, we wait one tick
367
 
                return;
368
 
        }
369
 
 
370
 
        // Increase the counter and abort if it is taking too long!
371
 
        _players_ainew[p->index].counter++;
372
 
        if (_players_ainew[p->index].counter > AI_LOCATE_ROUTE_MAX_COUNTER) {
373
 
                // Switch back to doing nothing!
374
 
                _players_ainew[p->index].state = AI_STATE_NOTHING;
375
 
                return;
376
 
        }
377
 
 
378
 
        // We are going to locate a city from where we are going to connect
379
 
        if (_players_ainew[p->index].from_ic == -1) {
380
 
                if (_players_ainew[p->index].temp == -1) {
381
 
                        // First, we pick a random spot to search from
382
 
                        if (_players_ainew[p->index].from_type == AI_CITY) {
383
 
                                _players_ainew[p->index].temp = AI_RandomRange(GetMaxTownIndex() + 1);
384
 
                        } else {
385
 
                                _players_ainew[p->index].temp = AI_RandomRange(GetMaxIndustryIndex() + 1);
386
 
                        }
387
 
                }
388
 
 
389
 
                if (!AiNew_Check_City_or_Industry(p, _players_ainew[p->index].temp, _players_ainew[p->index].from_type)) {
390
 
                        // It was not a valid city
391
 
                        //  increase the temp with one, and return. We will come back later here
392
 
                        //  to try again
393
 
                        _players_ainew[p->index].temp++;
394
 
                        if (_players_ainew[p->index].from_type == AI_CITY) {
395
 
                                if (_players_ainew[p->index].temp > GetMaxTownIndex()) _players_ainew[p->index].temp = 0;
396
 
                        } else {
397
 
                                if (_players_ainew[p->index].temp > GetMaxIndustryIndex()) _players_ainew[p->index].temp = 0;
398
 
                        }
399
 
 
400
 
                        // Don't do an attempt if we are trying the same id as the last time...
401
 
                        if (_players_ainew[p->index].last_id == _players_ainew[p->index].temp) return;
402
 
                        _players_ainew[p->index].last_id = _players_ainew[p->index].temp;
403
 
 
404
 
                        return;
405
 
                }
406
 
 
407
 
                // We found a good city/industry, save the data of it
408
 
                _players_ainew[p->index].from_ic = _players_ainew[p->index].temp;
409
 
 
410
 
                // Start the next tick with finding a to-city
411
 
                _players_ainew[p->index].temp = -1;
412
 
                return;
413
 
        }
414
 
 
415
 
        // Find a to-city
416
 
        if (_players_ainew[p->index].temp == -1) {
417
 
                // First, we pick a random spot to search to
418
 
                if (_players_ainew[p->index].to_type == AI_CITY) {
419
 
                        _players_ainew[p->index].temp = AI_RandomRange(GetMaxTownIndex() + 1);
420
 
                } else {
421
 
                        _players_ainew[p->index].temp = AI_RandomRange(GetMaxIndustryIndex() + 1);
422
 
                }
423
 
        }
424
 
 
425
 
        // The same city is not allowed
426
 
        // Also check if the city is valid
427
 
        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)) {
428
 
                // Maybe it is valid..
429
 
 
430
 
                /* We need to know if they are not to far apart from eachother..
431
 
                 * We do that by checking how much cargo we have to move and how long the
432
 
                 * route is.
433
 
                 */
434
 
 
435
 
                if (_players_ainew[p->index].from_type == AI_CITY && _players_ainew[p->index].tbt == AI_BUS) {
436
 
                        const Town* town_from = GetTown(_players_ainew[p->index].from_ic);
437
 
                        const Town* town_temp = GetTown(_players_ainew[p->index].temp);
438
 
                        uint distance = DistanceManhattan(town_from->xy, town_temp->xy);
439
 
                        int max_cargo;
440
 
 
441
 
                        max_cargo  = town_from->max_pass + town_temp->max_pass;
442
 
                        max_cargo -= town_from->act_pass + town_temp->act_pass;
443
 
 
444
 
                        // max_cargo is now the amount of cargo we can move between the two cities
445
 
                        // If it is more than the distance, we allow it
446
 
                        if (distance <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) {
447
 
                                // We found a good city/industry, save the data of it
448
 
                                _players_ainew[p->index].to_ic = _players_ainew[p->index].temp;
449
 
                                _players_ainew[p->index].state = AI_STATE_FIND_STATION;
450
 
 
451
 
                                DEBUG(ai, 1, "[LocateRoute] found bus-route of %d tiles long (from %d to %d)",
452
 
                                        distance,
453
 
                                        _players_ainew[p->index].from_ic,
454
 
                                        _players_ainew[p->index].temp
455
 
                                );
456
 
 
457
 
                                _players_ainew[p->index].from_tile = 0;
458
 
                                _players_ainew[p->index].to_tile = 0;
459
 
 
460
 
                                return;
461
 
                        }
462
 
                } else if (_players_ainew[p->index].tbt == AI_TRUCK) {
463
 
                        const Industry* ind_from = GetIndustry(_players_ainew[p->index].from_ic);
464
 
                        const Industry* ind_temp = GetIndustry(_players_ainew[p->index].temp);
465
 
                        bool found = false;
466
 
                        int max_cargo = 0;
467
 
                        uint i;
468
 
 
469
 
                        // TODO: in max_cargo, also check other cargo (beside [0])
470
 
                        // First we check if the from_ic produces cargo that this ic accepts
471
 
                        if (ind_from->produced_cargo[0] != CT_INVALID && ind_from->last_month_production[0] != 0) {
472
 
                                for (i = 0; i < lengthof(ind_temp->accepts_cargo); i++) {
473
 
                                        if (ind_temp->accepts_cargo[i] == CT_INVALID) break;
474
 
                                        if (ind_from->produced_cargo[0] == ind_temp->accepts_cargo[i]) {
475
 
                                                // Found a compatible industry
476
 
                                                max_cargo = ind_from->last_month_production[0] - ind_from->last_month_transported[0];
477
 
                                                found = true;
478
 
                                                _players_ainew[p->index].from_deliver = true;
479
 
                                                _players_ainew[p->index].to_deliver = false;
480
 
                                                break;
481
 
                                        }
482
 
                                }
483
 
                        }
484
 
                        if (!found && ind_temp->produced_cargo[0] != CT_INVALID && ind_temp->last_month_production[0] != 0) {
485
 
                                // If not check if the current ic produces cargo that the from_ic accepts
486
 
                                for (i = 0; i < lengthof(ind_from->accepts_cargo); i++) {
487
 
                                        if (ind_from->accepts_cargo[i] == CT_INVALID) break;
488
 
                                        if (ind_from->produced_cargo[0] == ind_from->accepts_cargo[i]) {
489
 
                                                // Found a compatbiel industry
490
 
                                                found = true;
491
 
                                                max_cargo = ind_temp->last_month_production[0] - ind_temp->last_month_transported[0];
492
 
                                                _players_ainew[p->index].from_deliver = false;
493
 
                                                _players_ainew[p->index].to_deliver = true;
494
 
                                                break;
495
 
                                        }
496
 
                                }
497
 
                        }
498
 
                        if (found) {
499
 
                                // Yeah, they are compatible!!!
500
 
                                // Check the length against the amount of goods
501
 
                                uint distance = DistanceManhattan(ind_from->xy, ind_temp->xy);
502
 
 
503
 
                                if (distance > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE &&
504
 
                                                distance <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) {
505
 
                                        _players_ainew[p->index].to_ic = _players_ainew[p->index].temp;
506
 
                                        if (_players_ainew[p->index].from_deliver) {
507
 
                                                _players_ainew[p->index].cargo = ind_from->produced_cargo[0];
508
 
                                        } else {
509
 
                                                _players_ainew[p->index].cargo = ind_temp->produced_cargo[0];
510
 
                                        }
511
 
                                        _players_ainew[p->index].state = AI_STATE_FIND_STATION;
512
 
 
513
 
                                        DEBUG(ai, 1, "[LocateRoute] found truck-route of %d tiles long (from %d to %d)",
514
 
                                                distance,
515
 
                                                _players_ainew[p->index].from_ic,
516
 
                                                _players_ainew[p->index].temp
517
 
                                        );
518
 
 
519
 
                                        _players_ainew[p->index].from_tile = 0;
520
 
                                        _players_ainew[p->index].to_tile = 0;
521
 
 
522
 
                                        return;
523
 
                                }
524
 
                        }
525
 
                }
526
 
        }
527
 
 
528
 
        // It was not a valid city
529
 
        //  increase the temp with one, and return. We will come back later here
530
 
        //  to try again
531
 
        _players_ainew[p->index].temp++;
532
 
        if (_players_ainew[p->index].to_type == AI_CITY) {
533
 
                if (_players_ainew[p->index].temp > GetMaxTownIndex()) _players_ainew[p->index].temp = 0;
534
 
        } else {
535
 
                if (_players_ainew[p->index].temp > GetMaxIndustryIndex()) _players_ainew[p->index].temp = 0;
536
 
        }
537
 
 
538
 
        // Don't do an attempt if we are trying the same id as the last time...
539
 
        if (_players_ainew[p->index].last_id == _players_ainew[p->index].temp) return;
540
 
        _players_ainew[p->index].last_id = _players_ainew[p->index].temp;
541
 
}
542
 
 
543
 
 
544
 
// Check if there are not more than a certain amount of vehicles pointed to a certain
545
 
//  station. This to prevent 10 busses going to one station, which gives... problems ;)
546
 
static bool AiNew_CheckVehicleStation(Player *p, Station *st)
547
 
{
548
 
        int count = 0;
549
 
        Vehicle *v;
550
 
 
551
 
        // Also check if we don't have already a lot of busses to this city...
552
 
        FOR_ALL_VEHICLES(v) {
553
 
                if (v->owner == _current_player) {
554
 
                        const Order *order;
555
 
 
556
 
                        FOR_VEHICLE_ORDERS(v, order) {
557
 
                                if (order->type == OT_GOTO_STATION && GetStation(order->dest) == st) {
558
 
                                        // This vehicle has this city in its list
559
 
                                        count++;
560
 
                                }
561
 
                        }
562
 
                }
563
 
        }
564
 
 
565
 
        if (count > AI_CHECK_MAX_VEHICLE_PER_STATION) return false;
566
 
        return true;
567
 
}
568
 
 
569
 
// This function finds a good spot for a station
570
 
static void AiNew_State_FindStation(Player *p)
571
 
{
572
 
        TileIndex tile;
573
 
        Station *st;
574
 
        int count = 0;
575
 
        EngineID i;
576
 
        TileIndex new_tile = 0;
577
 
        DiagDirection direction = DIAGDIR_NE;
578
 
        Town *town = NULL;
579
 
        assert(_players_ainew[p->index].state == AI_STATE_FIND_STATION);
580
 
 
581
 
        if (_players_ainew[p->index].from_tile == 0) {
582
 
                // First we scan for a station in the from-city
583
 
                if (_players_ainew[p->index].from_type == AI_CITY) {
584
 
                        town = GetTown(_players_ainew[p->index].from_ic);
585
 
                        tile = town->xy;
586
 
                } else {
587
 
                        tile = GetIndustry(_players_ainew[p->index].from_ic)->xy;
588
 
                }
589
 
        } else if (_players_ainew[p->index].to_tile == 0) {
590
 
                // Second we scan for a station in the to-city
591
 
                if (_players_ainew[p->index].to_type == AI_CITY) {
592
 
                        town = GetTown(_players_ainew[p->index].to_ic);
593
 
                        tile = town->xy;
594
 
                } else {
595
 
                        tile = GetIndustry(_players_ainew[p->index].to_ic)->xy;
596
 
                }
597
 
        } else {
598
 
                // Unsupported request
599
 
                // Go to FIND_PATH
600
 
                _players_ainew[p->index].temp = -1;
601
 
                _players_ainew[p->index].state = AI_STATE_FIND_PATH;
602
 
                return;
603
 
        }
604
 
 
605
 
        // First, we are going to look at the stations that already exist inside the city
606
 
        //  If there is enough cargo left in the station, we take that station
607
 
        //  If that is not possible, and there are more than 2 stations in the city, abort
608
 
        i = AiNew_PickVehicle(p);
609
 
        // Euhmz, this should not happen _EVER_
610
 
        // Quit finding a route...
611
 
        if (i == INVALID_ENGINE) {
612
 
                _players_ainew[p->index].state = AI_STATE_NOTHING;
613
 
                return;
614
 
        }
615
 
 
616
 
        FOR_ALL_STATIONS(st) {
617
 
                if (st->owner == _current_player) {
618
 
                        if (_players_ainew[p->index].tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) == FACIL_BUS_STOP) {
619
 
                                if (st->town == town) {
620
 
                                        // Check how much cargo there is left in the station
621
 
                                        if ((int)st->goods[_players_ainew[p->index].cargo].cargo.Count() > RoadVehInfo(i)->capacity * AI_STATION_REUSE_MULTIPLER) {
622
 
                                                if (AiNew_CheckVehicleStation(p, st)) {
623
 
                                                        // We did found a station that was good enough!
624
 
                                                        new_tile = st->xy;
625
 
                                                        direction = GetRoadStopDir(st->xy);
626
 
                                                        break;
627
 
                                                }
628
 
                                        }
629
 
                                        count++;
630
 
                                }
631
 
                        }
632
 
                }
633
 
        }
634
 
        // We are going to add a new station...
635
 
        if (new_tile == 0) count++;
636
 
        // No more than 2 stations allowed in a city
637
 
        //  This is because only the best 2 stations of one cargo do get any cargo
638
 
        if (count > 2) {
639
 
                _players_ainew[p->index].state = AI_STATE_NOTHING;
640
 
                return;
641
 
        }
642
 
 
643
 
        if (new_tile == 0 && _players_ainew[p->index].tbt == AI_BUS) {
644
 
                uint x, y, i = 0;
645
 
                CommandCost r;
646
 
                uint best;
647
 
                uint accepts[NUM_CARGO];
648
 
                TileIndex found_spot[AI_FINDSTATION_TILE_RANGE*AI_FINDSTATION_TILE_RANGE * 4];
649
 
                uint found_best[AI_FINDSTATION_TILE_RANGE*AI_FINDSTATION_TILE_RANGE * 4];
650
 
                // To find a good spot we scan a range from the center, a get the point
651
 
                //  where we get the most cargo and where it is buildable.
652
 
                // TODO: also check for station of myself and make sure we are not
653
 
                //   taking eachothers passengers away (bad result when it does not)
654
 
                for (x = TileX(tile) - AI_FINDSTATION_TILE_RANGE; x <= TileX(tile) + AI_FINDSTATION_TILE_RANGE; x++) {
655
 
                        for (y = TileY(tile) - AI_FINDSTATION_TILE_RANGE; y <= TileY(tile) + AI_FINDSTATION_TILE_RANGE; y++) {
656
 
                                new_tile = TileXY(x, y);
657
 
                                if (IsTileType(new_tile, MP_CLEAR) || IsTileType(new_tile, MP_TREES)) {
658
 
                                        // This tile we can build on!
659
 
                                        // Check acceptance
660
 
                                        // XXX - Get the catchment area
661
 
                                        GetAcceptanceAroundTiles(accepts, new_tile, 1, 1, 4);
662
 
                                        // >> 3 == 0 means no cargo
663
 
                                        if (accepts[_players_ainew[p->index].cargo] >> 3 == 0) continue;
664
 
                                        // See if we can build the station
665
 
                                        r = AiNew_Build_Station(p, _players_ainew[p->index].tbt, new_tile, 0, 0, 0, DC_QUERY_COST);
666
 
                                        if (CmdFailed(r)) continue;
667
 
                                        // We can build it, so add it to found_spot
668
 
                                        found_spot[i] = new_tile;
669
 
                                        found_best[i++] = accepts[_players_ainew[p->index].cargo];
670
 
                                }
671
 
                        }
672
 
                }
673
 
 
674
 
                // If i is still zero, we did not find anything
675
 
                if (i == 0) {
676
 
                        _players_ainew[p->index].state = AI_STATE_NOTHING;
677
 
                        return;
678
 
                }
679
 
 
680
 
                // Go through all the found_best and check which has the highest value
681
 
                best = 0;
682
 
                new_tile = 0;
683
 
 
684
 
                for (x = 0; x < i; x++) {
685
 
                        if (found_best[x] > best ||
686
 
                                        (found_best[x] == best && DistanceManhattan(tile, new_tile) > DistanceManhattan(tile, found_spot[x]))) {
687
 
                                new_tile = found_spot[x];
688
 
                                best = found_best[x];
689
 
                        }
690
 
                }
691
 
 
692
 
                // See how much it is going to cost us...
693
 
                r = AiNew_Build_Station(p, _players_ainew[p->index].tbt, new_tile, 0, 0, 0, DC_QUERY_COST);
694
 
                _players_ainew[p->index].new_cost += r.GetCost();
695
 
 
696
 
                direction = (DiagDirection)AI_PATHFINDER_NO_DIRECTION;
697
 
        } else if (new_tile == 0 && _players_ainew[p->index].tbt == AI_TRUCK) {
698
 
                // Truck station locater works differently.. a station can be on any place
699
 
                //  as long as it is in range. So we give back code AI_STATION_RANGE
700
 
                //  so the pathfinder routine can work it out!
701
 
                new_tile = AI_STATION_RANGE;
702
 
                direction = (DiagDirection)AI_PATHFINDER_NO_DIRECTION;
703
 
        }
704
 
 
705
 
        if (_players_ainew[p->index].from_tile == 0) {
706
 
                _players_ainew[p->index].from_tile = new_tile;
707
 
                _players_ainew[p->index].from_direction = direction;
708
 
                // Now we found thisone, go in for to_tile
709
 
                return;
710
 
        } else if (_players_ainew[p->index].to_tile == 0) {
711
 
                _players_ainew[p->index].to_tile = new_tile;
712
 
                _players_ainew[p->index].to_direction = direction;
713
 
                // K, done placing stations!
714
 
                _players_ainew[p->index].temp = -1;
715
 
                _players_ainew[p->index].state = AI_STATE_FIND_PATH;
716
 
                return;
717
 
        }
718
 
}
719
 
 
720
 
 
721
 
// We try to find a path between 2 points
722
 
static void AiNew_State_FindPath(Player *p)
723
 
{
724
 
        int r;
725
 
        assert(_players_ainew[p->index].state == AI_STATE_FIND_PATH);
726
 
 
727
 
        // First time, init some data
728
 
        if (_players_ainew[p->index].temp == -1) {
729
 
                // Init path_info
730
 
                if (_players_ainew[p->index].from_tile == AI_STATION_RANGE) {
731
 
                        const Industry* i = GetIndustry(_players_ainew[p->index].from_ic);
732
 
 
733
 
                        // For truck routes we take a range around the industry
734
 
                        _players_ainew[p->index].path_info.start_tile_tl = i->xy - TileDiffXY(1, 1);
735
 
                        _players_ainew[p->index].path_info.start_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1);
736
 
                        _players_ainew[p->index].path_info.start_direction = _players_ainew[p->index].from_direction;
737
 
                } else {
738
 
                        _players_ainew[p->index].path_info.start_tile_tl = _players_ainew[p->index].from_tile;
739
 
                        _players_ainew[p->index].path_info.start_tile_br = _players_ainew[p->index].from_tile;
740
 
                        _players_ainew[p->index].path_info.start_direction = _players_ainew[p->index].from_direction;
741
 
                }
742
 
 
743
 
                if (_players_ainew[p->index].to_tile == AI_STATION_RANGE) {
744
 
                        const Industry* i = GetIndustry(_players_ainew[p->index].to_ic);
745
 
 
746
 
                        _players_ainew[p->index].path_info.end_tile_tl = i->xy - TileDiffXY(1, 1);
747
 
                        _players_ainew[p->index].path_info.end_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1);
748
 
                        _players_ainew[p->index].path_info.end_direction = _players_ainew[p->index].to_direction;
749
 
                } else {
750
 
                        _players_ainew[p->index].path_info.end_tile_tl = _players_ainew[p->index].to_tile;
751
 
                        _players_ainew[p->index].path_info.end_tile_br = _players_ainew[p->index].to_tile;
752
 
                        _players_ainew[p->index].path_info.end_direction = _players_ainew[p->index].to_direction;
753
 
                }
754
 
 
755
 
                _players_ainew[p->index].path_info.rail_or_road = (_players_ainew[p->index].tbt == AI_TRAIN);
756
 
 
757
 
                // First, clean the pathfinder with our new begin and endpoints
758
 
                clean_AyStar_AiPathFinder(_players_ainew[p->index].pathfinder, &_players_ainew[p->index].path_info);
759
 
 
760
 
                _players_ainew[p->index].temp = 0;
761
 
        }
762
 
 
763
 
        // Start the pathfinder
764
 
        r = _players_ainew[p->index].pathfinder->main(_players_ainew[p->index].pathfinder);
765
 
        switch (r) {
766
 
                case AYSTAR_NO_PATH:
767
 
                        DEBUG(ai, 1, "No route found by pathfinder");
768
 
                        // Start all over again
769
 
                        _players_ainew[p->index].state = AI_STATE_NOTHING;
770
 
                        break;
771
 
 
772
 
                case AYSTAR_FOUND_END_NODE: // We found the end-point
773
 
                        _players_ainew[p->index].temp = -1;
774
 
                        _players_ainew[p->index].state = AI_STATE_FIND_DEPOT;
775
 
                        break;
776
 
 
777
 
                // In any other case, we are still busy finding the route
778
 
                default: break;
779
 
        }
780
 
}
781
 
 
782
 
 
783
 
// This function tries to locate a good place for a depot!
784
 
static void AiNew_State_FindDepot(Player *p)
785
 
{
786
 
        // To place the depot, we walk through the route, and if we find a lovely spot (MP_CLEAR, MP_TREES), we place it there..
787
 
        // Simple, easy, works!
788
 
        // To make the depot stand in the middle of the route, we start from the center..
789
 
        // But first we walk through the route see if we can find a depot that is ours
790
 
        //  this keeps things nice ;)
791
 
        int g, i;
792
 
        CommandCost r;
793
 
        DiagDirection j;
794
 
        TileIndex tile;
795
 
        assert(_players_ainew[p->index].state == AI_STATE_FIND_DEPOT);
796
 
 
797
 
        _players_ainew[p->index].depot_tile = 0;
798
 
 
799
 
        for (i=2;i<_players_ainew[p->index].path_info.route_length-2;i++) {
800
 
                tile = _players_ainew[p->index].path_info.route[i];
801
 
                for (j = DIAGDIR_BEGIN; j < DIAGDIR_END; j++) {
802
 
                        TileIndex t = tile + TileOffsByDiagDir(j);
803
 
 
804
 
                        if (IsRoadDepotTile(t) &&
805
 
                                        IsTileOwner(t, _current_player) &&
806
 
                                        GetRoadDepotDirection(t) == ReverseDiagDir(j)) {
807
 
                                _players_ainew[p->index].depot_tile = t;
808
 
                                _players_ainew[p->index].depot_direction = ReverseDiagDir(j);
809
 
                                _players_ainew[p->index].state = AI_STATE_VERIFY_ROUTE;
810
 
                                return;
811
 
                        }
812
 
                }
813
 
        }
814
 
 
815
 
        // This routine let depot finding start in the middle, and work his way to the stations
816
 
        // It makes depot placing nicer :)
817
 
        i = _players_ainew[p->index].path_info.route_length / 2;
818
 
        g = 1;
819
 
        while (i > 1 && i < _players_ainew[p->index].path_info.route_length - 2) {
820
 
                i += g;
821
 
                g *= -1;
822
 
                (g < 0?g--:g++);
823
 
 
824
 
                if (_players_ainew[p->index].path_info.route_extra[i] != 0 || _players_ainew[p->index].path_info.route_extra[i+1] != 0) {
825
 
                        // Bridge or tunnel.. we can't place a depot there
826
 
                        continue;
827
 
                }
828
 
 
829
 
                tile = _players_ainew[p->index].path_info.route[i];
830
 
 
831
 
                for (j = DIAGDIR_BEGIN; j < DIAGDIR_END; j++) {
832
 
                        TileIndex t = tile + TileOffsByDiagDir(j);
833
 
 
834
 
                        // It may not be placed on the road/rail itself
835
 
                        // And because it is not build yet, we can't see it on the tile..
836
 
                        // So check the surrounding tiles :)
837
 
                        if (t == _players_ainew[p->index].path_info.route[i - 1] ||
838
 
                                        t == _players_ainew[p->index].path_info.route[i + 1]) {
839
 
                                continue;
840
 
                        }
841
 
                        // Not around a bridge?
842
 
                        if (_players_ainew[p->index].path_info.route_extra[i] != 0) continue;
843
 
                        if (IsTileType(tile, MP_TUNNELBRIDGE)) continue;
844
 
                        // Is the terrain clear?
845
 
                        if (IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)) {
846
 
                                // If the current tile is on a slope then we do not allow this
847
 
                                if (GetTileSlope(tile, NULL) != SLOPE_FLAT) continue;
848
 
                                // Check if everything went okay..
849
 
                                r = AiNew_Build_Depot(p, t, ReverseDiagDir(j), 0);
850
 
                                if (CmdFailed(r)) continue;
851
 
                                // Found a spot!
852
 
                                _players_ainew[p->index].new_cost += r.GetCost();
853
 
                                _players_ainew[p->index].depot_tile = t;
854
 
                                _players_ainew[p->index].depot_direction = ReverseDiagDir(j); // Reverse direction
855
 
                                _players_ainew[p->index].state = AI_STATE_VERIFY_ROUTE;
856
 
                                return;
857
 
                        }
858
 
                }
859
 
        }
860
 
 
861
 
        // Failed to find a depot?
862
 
        _players_ainew[p->index].state = AI_STATE_NOTHING;
863
 
}
864
 
 
865
 
 
866
 
// This function calculates how many vehicles there are needed on this
867
 
//  traject.
868
 
// It works pretty simple: get the length, see how much we move around
869
 
//  and hussle that, and you know how many vehicles there are needed.
870
 
// It returns the cost for the vehicles
871
 
static int AiNew_HowManyVehicles(Player *p)
872
 
{
873
 
        if (_players_ainew[p->index].tbt == AI_BUS) {
874
 
                // For bus-routes we look at the time before we are back in the station
875
 
                EngineID i;
876
 
                int length, tiles_a_day;
877
 
                int amount;
878
 
                i = AiNew_PickVehicle(p);
879
 
                if (i == INVALID_ENGINE) return 0;
880
 
                // Passenger run.. how long is the route?
881
 
                length = _players_ainew[p->index].path_info.route_length;
882
 
                // Calculating tiles a day a vehicle moves is not easy.. this is how it must be done!
883
 
                tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16;
884
 
                if (tiles_a_day == 0) tiles_a_day = 1;
885
 
                // We want a vehicle in a station once a month at least, so, calculate it!
886
 
                // (the * 2 is because we have 2 stations ;))
887
 
                amount = length * 2 * 2 / tiles_a_day / 30;
888
 
                if (amount == 0) amount = 1;
889
 
                return amount;
890
 
        } else if (_players_ainew[p->index].tbt == AI_TRUCK) {
891
 
                // For truck-routes we look at the cargo
892
 
                EngineID i;
893
 
                int length, amount, tiles_a_day;
894
 
                int max_cargo;
895
 
                i = AiNew_PickVehicle(p);
896
 
                if (i == INVALID_ENGINE) return 0;
897
 
                // Passenger run.. how long is the route?
898
 
                length = _players_ainew[p->index].path_info.route_length;
899
 
                // Calculating tiles a day a vehicle moves is not easy.. this is how it must be done!
900
 
                tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16;
901
 
                if (tiles_a_day == 0) tiles_a_day = 1;
902
 
                if (_players_ainew[p->index].from_deliver) {
903
 
                        max_cargo = GetIndustry(_players_ainew[p->index].from_ic)->last_month_production[0];
904
 
                } else {
905
 
                        max_cargo = GetIndustry(_players_ainew[p->index].to_ic)->last_month_production[0];
906
 
                }
907
 
 
908
 
                // This is because moving 60% is more than we can dream of!
909
 
                max_cargo *= 6;
910
 
                max_cargo /= 10;
911
 
                // We want all the cargo to be gone in a month.. so, we know the cargo it delivers
912
 
                //  we know what the vehicle takes with him, and we know the time it takes him
913
 
                //  to get back here.. now let's do some math!
914
 
                amount = 2 * length * max_cargo / tiles_a_day / 30 / RoadVehInfo(i)->capacity;
915
 
                amount += 1;
916
 
                return amount;
917
 
        } else {
918
 
                // Currently not supported
919
 
                return 0;
920
 
        }
921
 
}
922
 
 
923
 
 
924
 
// This function checks:
925
 
//   - If the route went okay
926
 
//   - Calculates the amount of money needed to build the route
927
 
//   - Calculates how much vehicles needed for the route
928
 
static void AiNew_State_VerifyRoute(Player *p)
929
 
{
930
 
        int res, i;
931
 
        assert(_players_ainew[p->index].state == AI_STATE_VERIFY_ROUTE);
932
 
 
933
 
        // Let's calculate the cost of the path..
934
 
        //  new_cost already contains the cost of the stations
935
 
        _players_ainew[p->index].path_info.position = -1;
936
 
 
937
 
        do {
938
 
                _players_ainew[p->index].path_info.position++;
939
 
                _players_ainew[p->index].new_cost += AiNew_Build_RoutePart(p, &_players_ainew[p->index].path_info, DC_QUERY_COST).GetCost();
940
 
        } while (_players_ainew[p->index].path_info.position != -2);
941
 
 
942
 
        // Now we know the price of build station + path. Now check how many vehicles
943
 
        //  we need and what the price for that will be
944
 
        res = AiNew_HowManyVehicles(p);
945
 
        // If res == 0, no vehicle was found, or an other problem did occour
946
 
        if (res == 0) {
947
 
                _players_ainew[p->index].state = AI_STATE_NOTHING;
948
 
                return;
949
 
        }
950
 
        _players_ainew[p->index].amount_veh = res;
951
 
        _players_ainew[p->index].cur_veh = 0;
952
 
 
953
 
        // Check how much it it going to cost us..
954
 
        for (i=0;i<res;i++) {
955
 
                _players_ainew[p->index].new_cost += AiNew_Build_Vehicle(p, 0, DC_QUERY_COST).GetCost();
956
 
        }
957
 
 
958
 
        // Now we know how much the route is going to cost us
959
 
        //  Check if we have enough money for it!
960
 
        if (_players_ainew[p->index].new_cost > p->player_money - AI_MINIMUM_MONEY) {
961
 
                // Too bad..
962
 
                DEBUG(ai, 1, "Insufficient funds to build route (%" OTTD_PRINTF64 "d)", (int64)_players_ainew[p->index].new_cost);
963
 
                _players_ainew[p->index].state = AI_STATE_NOTHING;
964
 
                return;
965
 
        }
966
 
 
967
 
        // Now we can build the route, check the direction of the stations!
968
 
        if (_players_ainew[p->index].from_direction == AI_PATHFINDER_NO_DIRECTION) {
969
 
                _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]);
970
 
        }
971
 
        if (_players_ainew[p->index].to_direction == AI_PATHFINDER_NO_DIRECTION) {
972
 
                _players_ainew[p->index].to_direction = AiNew_GetDirection(_players_ainew[p->index].path_info.route[0], _players_ainew[p->index].path_info.route[1]);
973
 
        }
974
 
        if (_players_ainew[p->index].from_tile == AI_STATION_RANGE)
975
 
                _players_ainew[p->index].from_tile = _players_ainew[p->index].path_info.route[_players_ainew[p->index].path_info.route_length - 1];
976
 
        if (_players_ainew[p->index].to_tile == AI_STATION_RANGE)
977
 
                _players_ainew[p->index].to_tile = _players_ainew[p->index].path_info.route[0];
978
 
 
979
 
        _players_ainew[p->index].state = AI_STATE_BUILD_STATION;
980
 
        _players_ainew[p->index].temp = 0;
981
 
 
982
 
        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);
983
 
}
984
 
 
985
 
 
986
 
// Build the stations
987
 
static void AiNew_State_BuildStation(Player *p)
988
 
{
989
 
        CommandCost res;
990
 
        assert(_players_ainew[p->index].state == AI_STATE_BUILD_STATION);
991
 
        if (_players_ainew[p->index].temp == 0) {
992
 
                if (!IsTileType(_players_ainew[p->index].from_tile, MP_STATION))
993
 
                        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);
994
 
        } else {
995
 
                if (!IsTileType(_players_ainew[p->index].to_tile, MP_STATION))
996
 
                        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);
997
 
                _players_ainew[p->index].state = AI_STATE_BUILD_PATH;
998
 
        }
999
 
        if (CmdFailed(res)) {
1000
 
                DEBUG(ai, 0, "[BuildStation] station could not be built (0x%X)", _players_ainew[p->index].to_tile);
1001
 
                _players_ainew[p->index].state = AI_STATE_NOTHING;
1002
 
                // If the first station _was_ build, destroy it
1003
 
                if (_players_ainew[p->index].temp != 0)
1004
 
                        AI_DoCommand(_players_ainew[p->index].from_tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
1005
 
                return;
1006
 
        }
1007
 
        _players_ainew[p->index].temp++;
1008
 
}
1009
 
 
1010
 
 
1011
 
// Build the path
1012
 
static void AiNew_State_BuildPath(Player *p)
1013
 
{
1014
 
        assert(_players_ainew[p->index].state == AI_STATE_BUILD_PATH);
1015
 
        // _players_ainew[p->index].temp is set to -1 when this function is called for the first time
1016
 
        if (_players_ainew[p->index].temp == -1) {
1017
 
                DEBUG(ai, 1, "Starting to build new path");
1018
 
                // Init the counter
1019
 
                _players_ainew[p->index].counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
1020
 
                // Set the position to the startingplace (-1 because in a minute we do ++)
1021
 
                _players_ainew[p->index].path_info.position = -1;
1022
 
                // And don't do this again
1023
 
                _players_ainew[p->index].temp = 0;
1024
 
        }
1025
 
        // Building goes very fast on normal rate, so we are going to slow it down..
1026
 
        //  By let the counter count from AI_BUILDPATH_PAUSE to 0, we have a nice way :)
1027
 
        if (--_players_ainew[p->index].counter != 0) return;
1028
 
        _players_ainew[p->index].counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
1029
 
 
1030
 
        // Increase the building position
1031
 
        _players_ainew[p->index].path_info.position++;
1032
 
        // Build route
1033
 
        AiNew_Build_RoutePart(p, &_players_ainew[p->index].path_info, DC_EXEC);
1034
 
        if (_players_ainew[p->index].path_info.position == -2) {
1035
 
                // This means we are done building!
1036
 
 
1037
 
                if (_players_ainew[p->index].tbt == AI_TRUCK && !_patches.roadveh_queue) {
1038
 
                        // If they not queue, they have to go up and down to try again at a station...
1039
 
                        // We don't want that, so try building some road left or right of the station
1040
 
                        DiagDirection dir1, dir2, dir3;
1041
 
                        TileIndex tile;
1042
 
                        CommandCost ret;
1043
 
                        for (int i = 0; i < 2; i++) {
1044
 
                                if (i == 0) {
1045
 
                                        tile = _players_ainew[p->index].from_tile + TileOffsByDiagDir(_players_ainew[p->index].from_direction);
1046
 
                                        dir1 = ChangeDiagDir(_players_ainew[p->index].from_direction, DIAGDIRDIFF_90LEFT);
1047
 
                                        dir2 = ChangeDiagDir(_players_ainew[p->index].from_direction, DIAGDIRDIFF_90RIGHT);
1048
 
                                        dir3 = _players_ainew[p->index].from_direction;
1049
 
                                } else {
1050
 
                                        tile = _players_ainew[p->index].to_tile + TileOffsByDiagDir(_players_ainew[p->index].to_direction);
1051
 
                                        dir1 = ChangeDiagDir(_players_ainew[p->index].to_direction, DIAGDIRDIFF_90LEFT);
1052
 
                                        dir2 = ChangeDiagDir(_players_ainew[p->index].to_direction, DIAGDIRDIFF_90RIGHT);
1053
 
                                        dir3 = _players_ainew[p->index].to_direction;
1054
 
                                }
1055
 
 
1056
 
                                ret = AI_DoCommand(tile, DiagDirToRoadBits(ReverseDiagDir(dir1)), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
1057
 
                                if (CmdSucceeded(ret)) {
1058
 
                                        TileIndex offset = TileOffsByDiagDir(dir1);
1059
 
                                        if (IsTileType(tile + offset, MP_CLEAR) || IsTileType(tile + offset, MP_TREES)) {
1060
 
                                                ret = AI_DoCommand(tile + offset, AiNew_GetRoadDirection(tile, tile + offset, tile + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
1061
 
                                                if (CmdSucceeded(ret)) {
1062
 
                                                        if (IsTileType(tile + offset + offset, MP_CLEAR) || IsTileType(tile + offset + offset, MP_TREES))
1063
 
                                                                AI_DoCommand(tile + offset + offset, AiNew_GetRoadDirection(tile + offset, tile + offset + offset, tile + offset + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
1064
 
                                                }
1065
 
                                        }
1066
 
                                }
1067
 
 
1068
 
                                ret = AI_DoCommand(tile, DiagDirToRoadBits(ReverseDiagDir(dir2)), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
1069
 
                                if (CmdSucceeded(ret)) {
1070
 
                                        TileIndex offset = TileOffsByDiagDir(dir2);
1071
 
                                        if (IsTileType(tile + offset, MP_CLEAR) || IsTileType(tile + offset, MP_TREES)) {
1072
 
                                                ret = AI_DoCommand(tile + offset, AiNew_GetRoadDirection(tile, tile + offset, tile + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
1073
 
                                                if (CmdSucceeded(ret)) {
1074
 
                                                        if (IsTileType(tile + offset + offset, MP_CLEAR) || IsTileType(tile + offset + offset, MP_TREES))
1075
 
                                                                AI_DoCommand(tile + offset + offset, AiNew_GetRoadDirection(tile + offset, tile + offset + offset, tile + offset + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
1076
 
                                                }
1077
 
                                        }
1078
 
                                }
1079
 
 
1080
 
                                ret = AI_DoCommand(tile, DiagDirToRoadBits(dir3), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
1081
 
                                if (CmdSucceeded(ret)) {
1082
 
                                        TileIndex offset = TileOffsByDiagDir(dir3);
1083
 
                                        if (IsTileType(tile + offset, MP_CLEAR) || IsTileType(tile + offset, MP_TREES)) {
1084
 
                                                ret = AI_DoCommand(tile + offset, AiNew_GetRoadDirection(tile, tile + offset, tile + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
1085
 
                                                if (CmdSucceeded(ret)) {
1086
 
                                                        if (IsTileType(tile + offset + offset, MP_CLEAR) || IsTileType(tile + offset + offset, MP_TREES))
1087
 
                                                                AI_DoCommand(tile + offset + offset, AiNew_GetRoadDirection(tile + offset, tile + offset + offset, tile + offset + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
1088
 
                                                }
1089
 
                                        }
1090
 
                                }
1091
 
                        }
1092
 
                }
1093
 
 
1094
 
                DEBUG(ai, 1, "Finished building path, cost: %" OTTD_PRINTF64 "d", (int64)_players_ainew[p->index].new_cost);
1095
 
                _players_ainew[p->index].state = AI_STATE_BUILD_DEPOT;
1096
 
        }
1097
 
}
1098
 
 
1099
 
 
1100
 
// Builds the depot
1101
 
static void AiNew_State_BuildDepot(Player *p)
1102
 
{
1103
 
        CommandCost res;
1104
 
        assert(_players_ainew[p->index].state == AI_STATE_BUILD_DEPOT);
1105
 
 
1106
 
        if (IsRoadDepotTile(_players_ainew[p->index].depot_tile)) {
1107
 
                if (IsTileOwner(_players_ainew[p->index].depot_tile, _current_player)) {
1108
 
                        // The depot is already built
1109
 
                        _players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE;
1110
 
                        return;
1111
 
                } else {
1112
 
                        // There is a depot, but not of our team! :(
1113
 
                        _players_ainew[p->index].state = AI_STATE_NOTHING;
1114
 
                        return;
1115
 
                }
1116
 
        }
1117
 
 
1118
 
        // There is a bus on the tile we want to build road on... idle till he is gone! (BAD PERSON! :p)
1119
 
        if (!EnsureNoVehicleOnGround(_players_ainew[p->index].depot_tile + TileOffsByDiagDir(_players_ainew[p->index].depot_direction)))
1120
 
                return;
1121
 
 
1122
 
        res = AiNew_Build_Depot(p, _players_ainew[p->index].depot_tile, _players_ainew[p->index].depot_direction, DC_EXEC);
1123
 
        if (CmdFailed(res)) {
1124
 
                DEBUG(ai, 0, "[BuildDepot] depot could not be built (0x%X)", _players_ainew[p->index].depot_tile);
1125
 
                _players_ainew[p->index].state = AI_STATE_NOTHING;
1126
 
                return;
1127
 
        }
1128
 
 
1129
 
        _players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE;
1130
 
        _players_ainew[p->index].idle = 10;
1131
 
        _players_ainew[p->index].veh_main_id = INVALID_VEHICLE;
1132
 
}
1133
 
 
1134
 
 
1135
 
// Build vehicles
1136
 
static void AiNew_State_BuildVehicle(Player *p)
1137
 
{
1138
 
        CommandCost res;
1139
 
        assert(_players_ainew[p->index].state == AI_STATE_BUILD_VEHICLE);
1140
 
 
1141
 
        // Check if we need to build a vehicle
1142
 
        if (_players_ainew[p->index].amount_veh == 0) {
1143
 
                // Nope, we are done!
1144
 
                // This means: we are all done! The route is open.. go back to NOTHING
1145
 
                //  He will idle some time and it will all start over again.. :)
1146
 
                _players_ainew[p->index].state = AI_STATE_ACTION_DONE;
1147
 
                return;
1148
 
        }
1149
 
        if (--_players_ainew[p->index].idle != 0) return;
1150
 
        // It is realistic that the AI can only build 1 vehicle a day..
1151
 
        // This makes sure of that!
1152
 
        _players_ainew[p->index].idle = AI_BUILD_VEHICLE_TIME_BETWEEN;
1153
 
 
1154
 
        // Build the vehicle
1155
 
        res = AiNew_Build_Vehicle(p, _players_ainew[p->index].depot_tile, DC_EXEC);
1156
 
        if (CmdFailed(res)) {
1157
 
                // This happens when the AI can't build any more vehicles!
1158
 
                _players_ainew[p->index].state = AI_STATE_NOTHING;
1159
 
                return;
1160
 
        }
1161
 
        // Increase the current counter
1162
 
        _players_ainew[p->index].cur_veh++;
1163
 
        // Decrease the total counter
1164
 
        _players_ainew[p->index].amount_veh--;
1165
 
        // Go give some orders!
1166
 
        _players_ainew[p->index].state = AI_STATE_WAIT_FOR_BUILD;
1167
 
}
1168
 
 
1169
 
 
1170
 
// Put the stations in the order list
1171
 
static void AiNew_State_GiveOrders(Player *p)
1172
 
{
1173
 
        int idx;
1174
 
        Order order;
1175
 
 
1176
 
        assert(_players_ainew[p->index].state == AI_STATE_GIVE_ORDERS);
1177
 
 
1178
 
        if (_players_ainew[p->index].veh_main_id != INVALID_VEHICLE) {
1179
 
                AI_DoCommand(0, _players_ainew[p->index].veh_id + (_players_ainew[p->index].veh_main_id << 16), CO_SHARE, DC_EXEC, CMD_CLONE_ORDER);
1180
 
 
1181
 
                _players_ainew[p->index].state = AI_STATE_START_VEHICLE;
1182
 
                return;
1183
 
        } else {
1184
 
                _players_ainew[p->index].veh_main_id = _players_ainew[p->index].veh_id;
1185
 
        }
1186
 
 
1187
 
        // Very handy for AI, goto depot.. but yeah, it needs to be activated ;)
1188
 
        if (_patches.gotodepot) {
1189
 
                idx = 0;
1190
 
                order.type = OT_GOTO_DEPOT;
1191
 
                order.flags = OFB_UNLOAD;
1192
 
                order.dest = GetDepotByTile(_players_ainew[p->index].depot_tile)->index;
1193
 
                AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
1194
 
        }
1195
 
 
1196
 
        idx = 0;
1197
 
        order.type = OT_GOTO_STATION;
1198
 
        order.flags = 0;
1199
 
        order.dest = GetStationIndex(_players_ainew[p->index].to_tile);
1200
 
        if (_players_ainew[p->index].tbt == AI_TRUCK && _players_ainew[p->index].to_deliver)
1201
 
                order.flags |= OFB_FULL_LOAD;
1202
 
        AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
1203
 
 
1204
 
        idx = 0;
1205
 
        order.type = OT_GOTO_STATION;
1206
 
        order.flags = 0;
1207
 
        order.dest = GetStationIndex(_players_ainew[p->index].from_tile);
1208
 
        if (_players_ainew[p->index].tbt == AI_TRUCK && _players_ainew[p->index].from_deliver)
1209
 
                order.flags |= OFB_FULL_LOAD;
1210
 
        AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
1211
 
 
1212
 
        // Start the engines!
1213
 
        _players_ainew[p->index].state = AI_STATE_START_VEHICLE;
1214
 
}
1215
 
 
1216
 
 
1217
 
// Start the vehicle
1218
 
static void AiNew_State_StartVehicle(Player *p)
1219
 
{
1220
 
        assert(_players_ainew[p->index].state == AI_STATE_START_VEHICLE);
1221
 
 
1222
 
        // Skip the first order if it is a second vehicle
1223
 
        //  This to make vehicles go different ways..
1224
 
        if (_players_ainew[p->index].cur_veh & 1)
1225
 
                AI_DoCommand(0, _players_ainew[p->index].veh_id, 1, DC_EXEC, CMD_SKIP_TO_ORDER);
1226
 
 
1227
 
        // 3, 2, 1... go! (give START_STOP command ;))
1228
 
        AI_DoCommand(0, _players_ainew[p->index].veh_id, 0, DC_EXEC, CMD_START_STOP_ROADVEH);
1229
 
        // Try to build an other vehicle (that function will stop building when needed)
1230
 
        _players_ainew[p->index].idle  = 10;
1231
 
        _players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE;
1232
 
}
1233
 
 
1234
 
 
1235
 
// Repays money
1236
 
static void AiNew_State_RepayMoney(Player *p)
1237
 
{
1238
 
        uint i;
1239
 
 
1240
 
        for (i = 0; i < AI_LOAN_REPAY; i++) {
1241
 
                AI_DoCommand(0, 0, 0, DC_EXEC, CMD_DECREASE_LOAN);
1242
 
        }
1243
 
        _players_ainew[p->index].state = AI_STATE_ACTION_DONE;
1244
 
}
1245
 
 
1246
 
 
1247
 
static void AiNew_CheckVehicle(Player *p, Vehicle *v)
1248
 
{
1249
 
        // When a vehicle is under the 6 months, we don't check for anything
1250
 
        if (v->age < 180) return;
1251
 
 
1252
 
        // When a vehicle is older then 1 year, it should make money...
1253
 
        if (v->age > 360) {
1254
 
                // If both years together are not more than AI_MINIMUM_ROUTE_PROFIT,
1255
 
                //  it is not worth the line I guess...
1256
 
                if (v->profit_last_year + v->profit_this_year < (Money)256 * AI_MINIMUM_ROUTE_PROFIT ||
1257
 
                                (v->reliability * 100 >> 16) < 40) {
1258
 
                        // There is a possibility that the route is fucked up...
1259
 
                        if (v->cargo.DaysInTransit() > AI_VEHICLE_LOST_DAYS) {
1260
 
                                // The vehicle is lost.. check the route, or else, get the vehicle
1261
 
                                //  back to a depot
1262
 
                                // TODO: make this piece of code
1263
 
                        }
1264
 
 
1265
 
 
1266
 
                        // We are already sending him back
1267
 
                        if (AiNew_GetSpecialVehicleFlag(p, v) & AI_VEHICLEFLAG_SELL) {
1268
 
                                if (v->type == VEH_ROAD && IsTileDepotType(v->tile, TRANSPORT_ROAD) &&
1269
 
                                                (v->vehstatus&VS_STOPPED)) {
1270
 
                                        // We are at the depot, sell the vehicle
1271
 
                                        AI_DoCommand(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
1272
 
                                }
1273
 
                                return;
1274
 
                        }
1275
 
 
1276
 
                        if (!AiNew_SetSpecialVehicleFlag(p, v, AI_VEHICLEFLAG_SELL)) return;
1277
 
                        {
1278
 
                                CommandCost ret;
1279
 
                                if (v->type == VEH_ROAD)
1280
 
                                        ret = AI_DoCommand(0, v->index, 0, DC_EXEC, CMD_SEND_ROADVEH_TO_DEPOT);
1281
 
                                // This means we can not find a depot :s
1282
 
                                //                              if (CmdFailed(ret))
1283
 
                        }
1284
 
                }
1285
 
        }
1286
 
}
1287
 
 
1288
 
 
1289
 
// Checks all vehicles if they are still valid and make money and stuff
1290
 
static void AiNew_State_CheckAllVehicles(Player *p)
1291
 
{
1292
 
        Vehicle *v;
1293
 
 
1294
 
        FOR_ALL_VEHICLES(v) {
1295
 
                if (v->owner != p->index) continue;
1296
 
                // Currently, we only know how to handle road-vehicles
1297
 
                if (v->type != VEH_ROAD) continue;
1298
 
 
1299
 
                AiNew_CheckVehicle(p, v);
1300
 
        }
1301
 
 
1302
 
        _players_ainew[p->index].state = AI_STATE_ACTION_DONE;
1303
 
}
1304
 
 
1305
 
 
1306
 
// Using the technique simular to the original AI
1307
 
//   Keeps things logical
1308
 
// It really should be in the same order as the AI_STATE's are!
1309
 
static AiNew_StateFunction* const _ainew_state[] = {
1310
 
        NULL,
1311
 
        AiNew_State_FirstTime,
1312
 
        AiNew_State_Nothing,
1313
 
        AiNew_State_WakeUp,
1314
 
        AiNew_State_LocateRoute,
1315
 
        AiNew_State_FindStation,
1316
 
        AiNew_State_FindPath,
1317
 
        AiNew_State_FindDepot,
1318
 
        AiNew_State_VerifyRoute,
1319
 
        AiNew_State_BuildStation,
1320
 
        AiNew_State_BuildPath,
1321
 
        AiNew_State_BuildDepot,
1322
 
        AiNew_State_BuildVehicle,
1323
 
        NULL,
1324
 
        AiNew_State_GiveOrders,
1325
 
        AiNew_State_StartVehicle,
1326
 
        AiNew_State_RepayMoney,
1327
 
        AiNew_State_CheckAllVehicles,
1328
 
        AiNew_State_ActionDone,
1329
 
        NULL,
1330
 
};
1331
 
 
1332
 
static void AiNew_OnTick(Player *p)
1333
 
{
1334
 
        if (_ainew_state[_players_ainew[p->index].state] != NULL)
1335
 
                _ainew_state[_players_ainew[p->index].state](p);
1336
 
}
1337
 
 
1338
 
 
1339
 
void AiNewDoGameLoop(Player *p)
1340
 
{
1341
 
        if (_players_ainew[p->index].state == AI_STATE_STARTUP) {
1342
 
                // The AI just got alive!
1343
 
                _players_ainew[p->index].state = AI_STATE_FIRST_TIME;
1344
 
                _players_ainew[p->index].tick = 0;
1345
 
 
1346
 
                // Only startup the AI
1347
 
                return;
1348
 
        }
1349
 
 
1350
 
        // We keep a ticker. We use it for competitor_speed
1351
 
        _players_ainew[p->index].tick++;
1352
 
 
1353
 
        // If we come here, we can do a tick.. do so!
1354
 
        AiNew_OnTick(p);
1355
 
}