1
0
Fork 0

(svn r10098) -Codechange: bilbo cared about the performance of the AI with respect to the airport placement, so he rewrote the aircraft handling of the AI; now it can actually make lots of money again :)

release/0.6
rubidium 2007-06-11 14:23:04 +00:00
parent 3e326085fa
commit cc4d18ecc4
2 changed files with 92 additions and 5 deletions

View File

@ -622,7 +622,6 @@ static bool AiCheckIfRouteIsGood(Player *p, FoundRoute *fr, byte bitmask)
int dist;
uint same_station = 0;
// Make sure distance to closest station is < 37 pixels.
from_tile = GET_TOWN_OR_INDUSTRY_TILE(fr->from);
to_tile = GET_TOWN_OR_INDUSTRY_TILE(fr->to);
@ -646,7 +645,19 @@ static bool AiCheckIfRouteIsGood(Player *p, FoundRoute *fr, byte bitmask)
return false;
}
if (dist != 0xFFFF && dist > 37) return false;
/* Requiring distance to nearest station to be always under 37 tiles may be suboptimal,
* Especially for longer aircraft routes that start and end pretty at any arbitrary place on map
* While it may be nice for AI to cluster their creations together, hardcoded limit is not ideal.
* If AI will randomly start on some isolated spot, it will never get out of there.
* AI will have chance of randomly rejecting routes further than 37 tiles from their network,
* so there will be some attempt to cluster the network together */
/* Random value between 37 and 292. Low values are exponentially more likely
* With 50% chance the value will be under 52 tiles */
int min_distance = 36 + 1 << (Random() % 9); // 0..8
/* Make sure distance to closest station is < min_distance tiles. */
if (dist != 0xFFFF && dist > min_distance) return false;
if (p->ai.route_type_mask != 0 &&
!(p->ai.route_type_mask & bitmask) &&
@ -1371,15 +1382,55 @@ static void AiWantPassengerAircraftRoute(Player *p)
FoundRoute fr;
int i;
/* Get aircraft that would be bought for this route
* (probably, as conditions may change before the route is fully built,
* like running out of money and having to select different aircraft, etc ...) */
EngineID veh = AiChooseAircraftToBuild(p->player_money, p->ai.build_kind != 0 ? 0 : AIR_CTOL);
/* No aircraft buildable mean no aircraft route */
if (veh == INVALID_ENGINE) return;
const AircraftVehicleInfo *avi = AircraftVehInfo(veh);
/* For passengers, "optimal" number of days in transit is about 80 to 100
* Calculate "maximum optimal number of squares" from speed for 80 days
* 20 days should be enough for takeoff, land, taxi, etc ...
*
* "A vehicle traveling at 100kph will cross 5.6 tiles per day" ->
* Since in table aircraft speeds are in "real km/h", this should be accurate
* We get max_squares = avi->max_speed * 5.6 / 100.0 * 80 */
int max_squares = avi->max_speed * 448 / 100;
/* For example this will be 10456 tiles for 2334 km/h aircrafts with realistic aircraft speeds
* and 836 with "unrealistic" speeds, much more than the original 95 squares limit
*
* Size of the map, if not rectangular, it is the larger dimension of it
*/
int map_size = max(MapSizeX(), MapSizeY());
/* Minimum distance between airports is half of map size, clamped between 1% and 20% of optimum.
* May prevent building plane routes at all on small maps, but they will be ineffective there, so
* it is feature, not a bug.
* On smaller distances, buses or trains are usually more effective approach anyway.
* Additional safeguard is needing at least 20 squares,
* which may trigger in highly unusual configurations */
int min_squares = max(20, max(max_squares / 100, min(max_squares / 5, map_size / 2)));
/* Should not happen, unless aircraft with real speed under approx. 5 km/h is selected.
* No such exist, unless using some NewGRF with ballons, zeppelins or similar
* slow-moving stuff. In that case, bail out, it is faster to walk by foot anyway :). */
if (max_squares < min_squares) return;
i = 60;
for (;;) {
// look for one from the subsidy list
AiFindSubsidyPassengerRoute(&fr);
if (IS_INT_INSIDE(fr.distance, 0, 95 + 1)) break;
if (IS_INT_INSIDE(fr.distance, min_squares, max_squares + 1)) break;
// try a random one
AiFindRandomPassengerRoute(&fr);
if (IS_INT_INSIDE(fr.distance, 0, 95 + 1)) break;
if (IS_INT_INSIDE(fr.distance, min_squares, max_squares + 1)) break;
// only test 60 times
if (--i == 0) return;
@ -1408,7 +1459,19 @@ static void AiWantPassengerAircraftRoute(Player *p)
p->ai.build_kind = 0;
p->ai.num_build_rec = 2;
p->ai.num_loco_to_build = 1;
p->ai.num_want_fullload = 1;
/* Using full load always may not be the best.
* Pick random value and rely on selling the vehicle & route
* afterwards if the choice was utterly wrong (or maybe altering the value if AI is improved)
* When traffic is very low or very assymetric, is is better not to full load
* When traffic is high, full/non-full make no difference
* It should be better to run with aircraft only one way full 6 times per year,
* rather than two way full 1 times.
* Practical experiments with AI show that the non-full-load aircrafts are usually
* those that survive
* Also, non-full load is more resistant against starving (by building better stations
* or using exclusive rights)
*/
p->ai.num_want_fullload = CHANCE16(1, 5); // 20% chance
// p->ai.loco_id = INVALID_VEHICLE;
p->ai.order_list_blocks[0] = 0;
p->ai.order_list_blocks[1] = 1;

View File

@ -567,8 +567,32 @@ static const AiDefaultBlockData _airportdata_ai_1[] = {
{1, 0, {0, 0}}
};
static const AiDefaultBlockData _airportdata_ai_3[] = {
MKAIR(3, 0, 0),
{1, 0, {0, 0}},
};
static const AiDefaultBlockData _airportdata_ai_4[] = {
MKAIR(4, 0, 0),
{1, 0, {0, 0}},
};
static const AiDefaultBlockData _airportdata_ai_5[] = {
MKAIR(5, 0, 0),
{1, 0, {0, 0}},
};
static const AiDefaultBlockData _airportdata_ai_7[] = {
MKAIR(7, 0, 0),
{1, 0, {0, 0}}
};
static const AiDefaultBlockData * const _airport_default_block_data[] = {
_airportdata_ai_7, // intercontinental airport
_airportdata_ai_4, // international airport
_airportdata_ai_3, // metropolitan airport
_airportdata_ai_0, // city airport
_airportdata_ai_5, // commuter airport
_airportdata_ai_1, // country airport
NULL
};