644 same_station > 2 && |
643 same_station > 2 && |
645 ((Town*)fr->from)->population < same_station * 350) { |
644 ((Town*)fr->from)->population < same_station * 350) { |
646 return false; |
645 return false; |
647 } |
646 } |
648 |
647 |
649 if (dist != 0xFFFF && dist > 37) return false; |
648 /* Requiring distance to nearest station to be always under 37 tiles may be suboptimal, |
|
649 * Especially for longer aircraft routes that start and end pretty at any arbitrary place on map |
|
650 * While it may be nice for AI to cluster their creations together, hardcoded limit is not ideal. |
|
651 * If AI will randomly start on some isolated spot, it will never get out of there. |
|
652 * AI will have chance of randomly rejecting routes further than 37 tiles from their network, |
|
653 * so there will be some attempt to cluster the network together */ |
|
654 |
|
655 /* Random value between 37 and 292. Low values are exponentially more likely |
|
656 * With 50% chance the value will be under 52 tiles */ |
|
657 int min_distance = 36 + 1 << (Random() % 9); // 0..8 |
|
658 |
|
659 /* Make sure distance to closest station is < min_distance tiles. */ |
|
660 if (dist != 0xFFFF && dist > min_distance) return false; |
650 |
661 |
651 if (p->ai.route_type_mask != 0 && |
662 if (p->ai.route_type_mask != 0 && |
652 !(p->ai.route_type_mask & bitmask) && |
663 !(p->ai.route_type_mask & bitmask) && |
653 !CHANCE16(1, 5)) { |
664 !CHANCE16(1, 5)) { |
654 return false; |
665 return false; |
1369 static void AiWantPassengerAircraftRoute(Player *p) |
1380 static void AiWantPassengerAircraftRoute(Player *p) |
1370 { |
1381 { |
1371 FoundRoute fr; |
1382 FoundRoute fr; |
1372 int i; |
1383 int i; |
1373 |
1384 |
|
1385 /* Get aircraft that would be bought for this route |
|
1386 * (probably, as conditions may change before the route is fully built, |
|
1387 * like running out of money and having to select different aircraft, etc ...) */ |
|
1388 EngineID veh = AiChooseAircraftToBuild(p->player_money, p->ai.build_kind != 0 ? 0 : AIR_CTOL); |
|
1389 |
|
1390 /* No aircraft buildable mean no aircraft route */ |
|
1391 if (veh == INVALID_ENGINE) return; |
|
1392 |
|
1393 const AircraftVehicleInfo *avi = AircraftVehInfo(veh); |
|
1394 |
|
1395 /* For passengers, "optimal" number of days in transit is about 80 to 100 |
|
1396 * Calculate "maximum optimal number of squares" from speed for 80 days |
|
1397 * 20 days should be enough for takeoff, land, taxi, etc ... |
|
1398 * |
|
1399 * "A vehicle traveling at 100kph will cross 5.6 tiles per day" -> |
|
1400 * Since in table aircraft speeds are in "real km/h", this should be accurate |
|
1401 * We get max_squares = avi->max_speed * 5.6 / 100.0 * 80 */ |
|
1402 int max_squares = avi->max_speed * 448 / 100; |
|
1403 |
|
1404 /* For example this will be 10456 tiles for 2334 km/h aircrafts with realistic aircraft speeds |
|
1405 * and 836 with "unrealistic" speeds, much more than the original 95 squares limit |
|
1406 * |
|
1407 * Size of the map, if not rectangular, it is the larger dimension of it |
|
1408 */ |
|
1409 int map_size = max(MapSizeX(), MapSizeY()); |
|
1410 |
|
1411 /* Minimum distance between airports is half of map size, clamped between 1% and 20% of optimum. |
|
1412 * May prevent building plane routes at all on small maps, but they will be ineffective there, so |
|
1413 * it is feature, not a bug. |
|
1414 * On smaller distances, buses or trains are usually more effective approach anyway. |
|
1415 * Additional safeguard is needing at least 20 squares, |
|
1416 * which may trigger in highly unusual configurations */ |
|
1417 int min_squares = max(20, max(max_squares / 100, min(max_squares / 5, map_size / 2))); |
|
1418 |
|
1419 /* Should not happen, unless aircraft with real speed under approx. 5 km/h is selected. |
|
1420 * No such exist, unless using some NewGRF with ballons, zeppelins or similar |
|
1421 * slow-moving stuff. In that case, bail out, it is faster to walk by foot anyway :). */ |
|
1422 if (max_squares < min_squares) return; |
|
1423 |
1374 i = 60; |
1424 i = 60; |
1375 for (;;) { |
1425 for (;;) { |
|
1426 |
1376 // look for one from the subsidy list |
1427 // look for one from the subsidy list |
1377 AiFindSubsidyPassengerRoute(&fr); |
1428 AiFindSubsidyPassengerRoute(&fr); |
1378 if (IS_INT_INSIDE(fr.distance, 0, 95 + 1)) break; |
1429 if (IS_INT_INSIDE(fr.distance, min_squares, max_squares + 1)) break; |
1379 |
1430 |
1380 // try a random one |
1431 // try a random one |
1381 AiFindRandomPassengerRoute(&fr); |
1432 AiFindRandomPassengerRoute(&fr); |
1382 if (IS_INT_INSIDE(fr.distance, 0, 95 + 1)) break; |
1433 if (IS_INT_INSIDE(fr.distance, min_squares, max_squares + 1)) break; |
1383 |
1434 |
1384 // only test 60 times |
1435 // only test 60 times |
1385 if (--i == 0) return; |
1436 if (--i == 0) return; |
1386 } |
1437 } |
1387 |
1438 |
1406 // Fill common fields |
1457 // Fill common fields |
1407 p->ai.cargo_type = fr.cargo; |
1458 p->ai.cargo_type = fr.cargo; |
1408 p->ai.build_kind = 0; |
1459 p->ai.build_kind = 0; |
1409 p->ai.num_build_rec = 2; |
1460 p->ai.num_build_rec = 2; |
1410 p->ai.num_loco_to_build = 1; |
1461 p->ai.num_loco_to_build = 1; |
1411 p->ai.num_want_fullload = 1; |
1462 /* Using full load always may not be the best. |
|
1463 * Pick random value and rely on selling the vehicle & route |
|
1464 * afterwards if the choice was utterly wrong (or maybe altering the value if AI is improved) |
|
1465 * When traffic is very low or very assymetric, is is better not to full load |
|
1466 * When traffic is high, full/non-full make no difference |
|
1467 * It should be better to run with aircraft only one way full 6 times per year, |
|
1468 * rather than two way full 1 times. |
|
1469 * Practical experiments with AI show that the non-full-load aircrafts are usually |
|
1470 * those that survive |
|
1471 * Also, non-full load is more resistant against starving (by building better stations |
|
1472 * or using exclusive rights) |
|
1473 */ |
|
1474 p->ai.num_want_fullload = CHANCE16(1, 5); // 20% chance |
1412 // p->ai.loco_id = INVALID_VEHICLE; |
1475 // p->ai.loco_id = INVALID_VEHICLE; |
1413 p->ai.order_list_blocks[0] = 0; |
1476 p->ai.order_list_blocks[0] = 0; |
1414 p->ai.order_list_blocks[1] = 1; |
1477 p->ai.order_list_blocks[1] = 1; |
1415 p->ai.order_list_blocks[2] = 255; |
1478 p->ai.order_list_blocks[2] = 255; |
1416 |
1479 |