summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2007-06-11 14:23:04 +0000
committerrubidium <rubidium@openttd.org>2007-06-11 14:23:04 +0000
commitcc4d18ecc440aea0ecb9f754fcc90803c9050d2b (patch)
tree280395be4dfbadd6c99f6d11e10796c05b05ea17
parent3e326085fa69da20e0a81182cbea4466016eb566 (diff)
downloadopenttd-cc4d18ecc440aea0ecb9f754fcc90803c9050d2b.tar.xz
(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 :)
-rw-r--r--src/ai/default/default.cpp73
-rw-r--r--src/table/ai_rail.h24
2 files changed, 92 insertions, 5 deletions
diff --git a/src/ai/default/default.cpp b/src/ai/default/default.cpp
index 3dca2825b..1394158e6 100644
--- a/src/ai/default/default.cpp
+++ b/src/ai/default/default.cpp
@@ -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;
diff --git a/src/table/ai_rail.h b/src/table/ai_rail.h
index 2b9602abd..7fe518968 100644
--- a/src/table/ai_rail.h
+++ b/src/table/ai_rail.h
@@ -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
};