truelight@9711: /* $Id$ */ truelight@9711: truebrain@9833: /** @file ai_engine.cpp Implementation of AIEngine. */ truelight@9711: truelight@9711: #include "ai_engine.hpp" truelight@9711: #include "ai_cargo.hpp" rubidium@9724: #include "../../player_func.h" rubidium@9723: #include "../../strings_func.h" truebrain@9733: #include "../../roadveh.h" truebrain@9733: #include "../../train.h" truebrain@9733: #include "../../ship.h" truebrain@9733: #include "../../aircraft.h" truebrain@9809: #include "../../cargotype.h" truebrain@9809: #include "../../vehicle_func.h" rubidium@9723: #include "../../core/alloc_func.hpp" rubidium@9723: #include "../../economy_func.h" rubidium@9724: #include "../../core/bitmath_func.hpp" truebrain@9804: #include "../../settings_type.h" rubidium@10190: #include "../../articulated_vehicles.h" rubidium@9724: #include "table/strings.h" truelight@9711: truelight@9711: /* static */ bool AIEngine::IsValidEngine(EngineID engine_id) truelight@9711: { truebrain@9736: return ::IsEngineIndex(engine_id) && HasBit(::GetEngine(engine_id)->player_avail, _current_player); truelight@9711: } truelight@9711: truelight@9713: /* static */ char *AIEngine::GetName(EngineID engine_id) truelight@9713: { truebrain@9736: if (!IsValidEngine(engine_id)) return NULL; truelight@9713: truelight@9713: static const int len = 64; truelight@9713: char *engine_name = MallocT(len); truelight@9713: rubidium@9724: ::SetDParam(0, engine_id); rubidium@9724: ::GetString(engine_name, STR_ENGINE_NAME, &engine_name[len - 1]); truelight@9713: return engine_name; truelight@9713: } truelight@9713: truelight@9713: /* static */ CargoID AIEngine::GetCargoType(EngineID engine_id) truelight@9713: { truebrain@10197: if (!IsValidEngine(engine_id)) return CT_INVALID; truelight@9713: truelight@9713: switch (::GetEngine(engine_id)->type) { truelight@9713: case VEH_ROAD: { truebrain@9736: const RoadVehicleInfo *vi = ::RoadVehInfo(engine_id); truelight@9713: return vi->cargo_type; truelight@9713: } break; truelight@9713: truelight@9713: case VEH_TRAIN: { truebrain@9736: const RailVehicleInfo *vi = ::RailVehInfo(engine_id); truelight@9713: return vi->cargo_type; truelight@9713: } break; truelight@9713: truelight@9713: case VEH_SHIP: { truebrain@9736: const ShipVehicleInfo *vi = ::ShipVehInfo(engine_id); truelight@9713: return vi->cargo_type; truelight@9713: } break; truelight@9713: truelight@9713: case VEH_AIRCRAFT: { truelight@9713: return CT_PASSENGERS; truelight@9713: } break; truelight@9713: truelight@9713: default: NOT_REACHED(); truelight@9713: } truelight@9713: } truelight@9713: truebrain@9809: /* static */ bool AIEngine::CanRefitCargo(EngineID engine_id, CargoID cargo_id) truebrain@9809: { truebrain@9809: if (!IsValidEngine(engine_id)) return false; truebrain@9809: if (!AICargo::IsValidCargo(cargo_id)) return false; truebrain@9809: truebrain@9809: if (GetCargoType(engine_id) == cargo_id) return true; truebrain@9809: if (cargo_id == CT_MAIL && ::GetEngine(engine_id)->type == VEH_AIRCRAFT) return true; truebrain@9809: return ::CanRefitTo(engine_id, cargo_id); truebrain@9809: } truebrain@9809: truebrain@10194: /* static */ int32 AIEngine::GetCapacity(EngineID engine_id) truelight@9713: { truebrain@10194: if (!IsValidEngine(engine_id)) return -1; truelight@9713: truelight@9713: switch (::GetEngine(engine_id)->type) { rubidium@10190: case VEH_ROAD: truelight@9713: case VEH_TRAIN: { rubidium@10190: uint16 *capacities = GetCapacityOfArticulatedParts(engine_id, ::GetEngine(engine_id)->type); rubidium@10190: for (CargoID c = 0; c < NUM_CARGO; c++) { rubidium@10190: if (capacities[c] == 0) continue; rubidium@10190: return capacities[c]; rubidium@10190: } truebrain@10194: return -1; truelight@9713: } break; truelight@9713: truelight@9713: case VEH_SHIP: { truebrain@9736: const ShipVehicleInfo *vi = ::ShipVehInfo(engine_id); truelight@9713: return vi->capacity; truelight@9713: } break; truelight@9713: truelight@9713: case VEH_AIRCRAFT: { truebrain@9736: const AircraftVehicleInfo *vi = ::AircraftVehInfo(engine_id); truelight@9713: return vi->passenger_capacity; truelight@9713: } break; truelight@9713: truelight@9713: default: NOT_REACHED(); truelight@9713: } truelight@9713: } truelight@9713: truebrain@10194: /* static */ int32 AIEngine::GetReliability(EngineID engine_id) truelight@9713: { truebrain@10194: if (!IsValidEngine(engine_id)) return -1; truelight@9713: truelight@9713: return (::GetEngine(engine_id)->reliability * 100 >> 16); truelight@9713: } truelight@9713: truebrain@10194: /* static */ int32 AIEngine::GetMaxSpeed(EngineID engine_id) truelight@9713: { truebrain@10194: if (!IsValidEngine(engine_id)) return -1; truelight@9713: truelight@9713: switch (::GetEngine(engine_id)->type) { truelight@9713: case VEH_ROAD: { truebrain@9736: const RoadVehicleInfo *vi = ::RoadVehInfo(engine_id); truebrain@9734: /* Internal speeds are km/h * 2 */ truebrain@9734: return vi->max_speed / 2; truelight@9713: } break; truelight@9713: truelight@9713: case VEH_TRAIN: { truebrain@9736: const RailVehicleInfo *vi = ::RailVehInfo(engine_id); truelight@9713: return vi->max_speed; truelight@9713: } break; truelight@9713: truelight@9713: case VEH_SHIP: { truebrain@9736: const ShipVehicleInfo *vi = ::ShipVehInfo(engine_id); truebrain@9734: /* Internal speeds are km/h * 2 */ truebrain@9734: return vi->max_speed / 2; truelight@9713: } break; truelight@9713: truelight@9713: case VEH_AIRCRAFT: { truebrain@9736: const AircraftVehicleInfo *vi = ::AircraftVehInfo(engine_id); truebrain@9804: return vi->max_speed / _patches.plane_speed; truelight@9713: } break; truelight@9713: truelight@9713: default: NOT_REACHED(); truelight@9713: } truelight@9713: } truelight@9713: rubidium@10196: /* static */ Money AIEngine::GetPrice(EngineID engine_id) truelight@9713: { truebrain@10194: if (!IsValidEngine(engine_id)) return -1; truelight@9713: truelight@9713: switch (::GetEngine(engine_id)->type) { truelight@9713: case VEH_ROAD: { truebrain@9736: const RoadVehicleInfo *vi = ::RoadVehInfo(engine_id); truelight@9713: return (_price.roadveh_base >> 3) * vi->base_cost >> 5; truelight@9713: } break; truelight@9713: truelight@9713: case VEH_TRAIN: { truebrain@9736: const RailVehicleInfo *vi = ::RailVehInfo(engine_id); truelight@9713: return (_price.build_railvehicle >> 3) * vi->base_cost >> 5; truelight@9713: } break; truelight@9713: truelight@9713: case VEH_SHIP: { truebrain@9736: const ShipVehicleInfo *vi = ::ShipVehInfo(engine_id); truelight@9713: return (_price.ship_base >> 3) * vi->base_cost >> 5; truelight@9713: } break; truelight@9713: truelight@9713: case VEH_AIRCRAFT: { truebrain@9736: const AircraftVehicleInfo *vi = ::AircraftVehInfo(engine_id); truelight@9713: return (_price.aircraft_base >> 3) * vi->base_cost >> 5; truelight@9713: } break; truelight@9713: truelight@9713: default: NOT_REACHED(); truelight@9713: } truelight@9713: } truelight@9713: truebrain@10194: /* static */ int32 AIEngine::GetMaxAge(EngineID engine_id) truebrain@9733: { truebrain@10194: if (!IsValidEngine(engine_id)) return -1; truebrain@9733: truebrain@9733: return ::GetEngine(engine_id)->lifelength * 366; truebrain@9733: } truebrain@9733: truebrain@9733: /* static */ Money AIEngine::GetRunningCost(EngineID engine_id) truebrain@9733: { truebrain@10194: if (!IsValidEngine(engine_id)) return -1; truebrain@9733: truebrain@9733: /* We need to create an instance in order to obtain GetRunningCost. truebrain@9733: * This means we temporary allocate a vehicle in the pool, but truebrain@9733: * there is no other way.. */ truebrain@9733: Vehicle *vehicle; truebrain@9733: switch (::GetEngine(engine_id)->type) { truebrain@9733: case VEH_ROAD: { truebrain@9733: vehicle = new RoadVehicle(); truebrain@9733: } break; truebrain@9733: truebrain@9733: case VEH_TRAIN: { truebrain@9733: vehicle = new Train(); truebrain@9733: } break; truebrain@9733: truebrain@9733: case VEH_SHIP: { truebrain@9733: vehicle = new Ship(); truebrain@9733: } break; truebrain@9733: truebrain@9733: case VEH_AIRCRAFT: { truebrain@9733: vehicle = new Aircraft(); truebrain@9733: } break; truebrain@9733: truebrain@9733: default: NOT_REACHED(); truebrain@9733: } truebrain@9733: truebrain@9733: vehicle->engine_type = engine_id; truebrain@9733: Money runningCost = vehicle->GetRunningCost(); truebrain@9733: delete vehicle; truebrain@9733: return runningCost >> 8; truebrain@9733: } truebrain@9733: truelight@9713: /* static */ AIVehicle::VehicleType AIEngine::GetVehicleType(EngineID engine_id) truelight@9713: { truebrain@9736: if (!IsValidEngine(engine_id)) return AIVehicle::VEHICLE_INVALID; truelight@9713: truelight@9713: switch (::GetEngine(engine_id)->type) { truelight@9713: case VEH_ROAD: return AIVehicle::VEHICLE_ROAD; truelight@9713: case VEH_TRAIN: return AIVehicle::VEHICLE_RAIL; truelight@9713: case VEH_SHIP: return AIVehicle::VEHICLE_WATER; truelight@9713: case VEH_AIRCRAFT: return AIVehicle::VEHICLE_AIR; truelight@9713: default: NOT_REACHED(); truelight@9713: } truelight@9713: }