summaryrefslogtreecommitdiff
path: root/roadveh_cmd.c
diff options
context:
space:
mode:
authorcelestar <celestar@openttd.org>2006-04-03 14:25:32 +0000
committercelestar <celestar@openttd.org>2006-04-03 14:25:32 +0000
commit8cbe98a3fdb0e8d4a6743c00712cedfa33979a0d (patch)
tree93820da9b941ae74b1d1ae37cd47bc46b37c3434 /roadveh_cmd.c
parent369ad5a573cfe7d4ccb130981517dd6ef3d3e9c7 (diff)
downloadopenttd-8cbe98a3fdb0e8d4a6743c00712cedfa33979a0d.tar.xz
(svn r4259) -[multistop] Fix/Feature/Codechange:
1) Improved the road vehicle allocation (aka slotting) for multistop. Stops can now accept unlimited, er... 256, vehicles. 2) Removed the "wait for stop" feature, because it did not work in practise. 3) Slotting now ignores unreachable stations. Uses NPF at the moment because the old pathfinder cannot do it (yet) 4) Now matter how many vehicles approach a station, they will always be distributed evenly over existing stops. 5) Hopefully the last fundamental change to multistop
Diffstat (limited to 'roadveh_cmd.c')
-rw-r--r--roadveh_cmd.c107
1 files changed, 36 insertions, 71 deletions
diff --git a/roadveh_cmd.c b/roadveh_cmd.c
index 33473f517..f552136ad 100644
--- a/roadveh_cmd.c
+++ b/roadveh_cmd.c
@@ -1,5 +1,6 @@
/* $Id$ */
+#include <limits.h>
#include "stdafx.h"
#include "openttd.h"
#include "debug.h"
@@ -164,10 +165,6 @@ int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
// v->u.road.unk2 = 0;
// v->u.road.overtaking = 0;
- v->u.road.slot = NULL;
- v->u.road.slotindex = 0;
- v->u.road.slot_age = 0;
-
v->last_station_visited = INVALID_STATION;
v->max_speed = rvi->max_speed;
v->engine_type = (byte)p1;
@@ -238,10 +235,10 @@ void ClearSlot(Vehicle *v)
v->u.road.slot = NULL;
v->u.road.slot_age = 0;
- // check that the slot is indeed assigned to the same vehicle
- assert(rs->slot[v->u.road.slotindex] == v->index);
- rs->slot[v->u.road.slotindex] = INVALID_VEHICLE;
- DEBUG(ms, 3) ("Multistop: Clearing slot %d at 0x%x", v->u.road.slotindex, rs->xy);
+ assert(rs->num_vehicles != 0);
+ rs->num_vehicles--;
+
+ DEBUG(ms, 3) ("Multistop: Clearing slot at 0x%x", rs->xy);
}
/** Sell a road vehicle.
@@ -382,7 +379,6 @@ int32 CmdSendRoadVehToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2)
if (flags & DC_EXEC) {
ClearSlot(v);
- v->vehstatus &= ~VS_WAIT_FOR_SLOT;
v->current_order.type = OT_GOTO_DEPOT;
v->current_order.flags = OF_NON_STOP | OF_HALT_IN_DEPOT;
v->current_order.station = dep->index;
@@ -408,7 +404,7 @@ int32 CmdTurnRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
if (v->type != VEH_Road || !CheckOwnership(v->owner)) return CMD_ERROR;
- if (v->vehstatus & (VS_HIDDEN | VS_STOPPED | VS_WAIT_FOR_SLOT) ||
+ if (v->vehstatus & (VS_HIDDEN | VS_STOPPED) ||
v->u.road.crashed_ctr != 0 ||
v->breakdown_ctr != 0 ||
v->u.road.overtaking != 0 ||
@@ -633,7 +629,6 @@ static void ProcessRoadVehOrder(Vehicle *v)
v->current_order.flags = 0;
v->dest_tile = 0;
ClearSlot(v);
- v->vehstatus &= ~VS_WAIT_FOR_SLOT;
return;
}
@@ -645,8 +640,6 @@ static void ProcessRoadVehOrder(Vehicle *v)
v->current_order = *order;
v->dest_tile = 0;
- /* We have changed the destination STATION, so resume movement */
- v->vehstatus &= ~VS_WAIT_FOR_SLOT;
if (order->type == OT_GOTO_STATION) {
const Station* st = GetStation(order->station);
@@ -907,7 +900,7 @@ static void RoadVehCheckOvertake(Vehicle *v, Vehicle *u)
od.u = u;
if (u->max_speed >= v->max_speed &&
- !(u->vehstatus & (VS_STOPPED | VS_WAIT_FOR_SLOT)) &&
+ !(u->vehstatus & VS_STOPPED) &&
u->cur_speed != 0) {
return;
}
@@ -929,7 +922,7 @@ static void RoadVehCheckOvertake(Vehicle *v, Vehicle *u)
od.tile = v->tile + TileOffsByDir(DirToDiagDir(v->direction));
if (FindRoadVehToOvertake(&od)) return;
- if (od.u->cur_speed == 0 || od.u->vehstatus& (VS_STOPPED | VS_WAIT_FOR_SLOT)) {
+ if (od.u->cur_speed == 0 || od.u->vehstatus& VS_STOPPED) {
v->u.road.overtaking_ctr = 0x11;
v->u.road.overtaking = 0x10;
} else {
@@ -1133,7 +1126,6 @@ found_best_track:;
return best_track;
}
-#if 0 /* Commented out until NPF works properly here */
static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile)
{
NPFFindStationOrTileData fstd;
@@ -1145,7 +1137,6 @@ static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile)
return NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE).best_path_dist;
}
-#endif
typedef struct RoadDriveEntry {
byte x,y;
@@ -1191,7 +1182,7 @@ static void RoadVehController(Vehicle *v)
v->breakdown_ctr--;
}
- if (v->vehstatus & (VS_STOPPED | VS_WAIT_FOR_SLOT)) return;
+ if (v->vehstatus & VS_STOPPED) return;
ProcessRoadVehOrder(v);
HandleRoadVehLoading(v);
@@ -1454,7 +1445,6 @@ again:
v->current_order.type = OT_NOTHING;
v->current_order.flags = 0;
ClearSlot(v);
- v->vehstatus &= ~VS_WAIT_FOR_SLOT;
}
SETBIT(rs->status, 7);
@@ -1560,7 +1550,7 @@ static void CheckIfRoadVehNeedsService(Vehicle *v)
if (_patches.servint_roadveh == 0) return;
if (!VehicleNeedsService(v)) return;
- if (v->vehstatus & (VS_STOPPED | VS_WAIT_FOR_SLOT)) return;
+ if (v->vehstatus & VS_STOPPED) return;
if (_patches.gotodepot && VehicleHasDepotOrders(v)) return;
// Don't interfere with a depot visit scheduled by the user, or a
@@ -1610,82 +1600,57 @@ void OnNewDay_RoadVeh(Vehicle *v)
CheckOrders(v);
//Current slot has expired
- if (v->u.road.slot_age-- == 0 && v->u.road.slot != NULL) {
- DEBUG(ms, 2) ("Multistop: Slot %d expired for vehicle %d (index %d) at stop 0x%x",
- v->u.road.slotindex, v->unitnumber, v->index, v->u.road.slot->xy
- );
+ if (v->current_order.type == OT_GOTO_STATION && v->u.road.slot_age-- == 0 && v->u.road.slot != NULL) {
+ DEBUG(ms, 2) ("Multistop: Slot expired for vehicle %d (index %d) at stop 0x%x",
+ v->unitnumber, v->index, v->u.road.slot->xy);
ClearSlot(v);
}
if (v->vehstatus & VS_STOPPED) return;
/* update destination */
- if (v->current_order.type == OT_GOTO_STATION &&
- v->u.road.slot == NULL &&
- !IsLevelCrossing(v->tile) &&
- v->u.road.overtaking == 0 &&
- !(v->vehstatus & VS_CRASHED)) {
- RoadStopType type = (v->cargo_type == CT_PASSENGERS) ? RS_BUS : RS_TRUCK;
+ if (v->current_order.type == OT_GOTO_STATION && v->u.road.slot == NULL && !(v->vehstatus & VS_CRASHED)) {
RoadStop *rs;
- uint mindist = 0xFFFFFFFF;
- int i;
- RoadStop *nearest = NULL;
+ RoadStop *best = NULL;
st = GetStation(v->current_order.station);
- rs = GetPrimaryRoadStop(st, type);
+ rs = GetPrimaryRoadStop(st, v->cargo_type == CT_PASSENGERS ? RS_BUS : RS_TRUCK);
if (rs != NULL) {
if (DistanceManhattan(v->tile, st->xy) < 16) {
- int new_slot = -1;
+ uint dist, badness;
+ uint minbadness = UINT_MAX;
DEBUG(ms, 2) ("Multistop: Attempting to obtain a slot for vehicle %d (index %d) at station %d (0x%x)", v->unitnumber,
v->index, st->index, st->xy);
/* Now we find the nearest road stop that has a free slot */
- for (i = 0; rs != NULL; rs = rs->next, i++) {
- uint dist = 0xFFFFFFFF;
- bool is_slot_free = false;
- int k;
- int last_free = -1;
-
- for (k = 0; k < NUM_SLOTS; k++)
- if (rs->slot[k] == INVALID_VEHICLE) {
- is_slot_free = true;
- last_free = k;
- dist = DistanceManhattan(v->tile, st->xy);
- break;
- }
-
- if (!is_slot_free) {
- DEBUG(ms, 4) ("Multistop: ---- stop %d is full", i);
+ for (; rs != NULL; rs = rs->next) {
+ dist = RoadFindPathToStop(v, rs->xy);
+ if (dist == UINT_MAX) {
+ DEBUG(ms, 4) (" ---- stop 0x%x is not reachable, not treating further", rs->xy);
continue;
}
+ badness = (rs->num_vehicles + 1) * (rs->num_vehicles + 1) + dist / NPF_TILE_LENGTH;
+
+ DEBUG(ms, 4) (" ---- stop 0x%x has %d vehicle%s waiting", rs->xy, rs->num_vehicles, rs->num_vehicles == 1 ? "":"s");
+ DEBUG(ms, 4) (" ---- Distance is %u", dist);
+ DEBUG(ms, 4) (" -- Badness %u", badness);
- DEBUG(ms, 4) ("Multistop: ---- distance to stop %d is %d", i, dist);
- if (dist < mindist) {
- nearest = rs;
- mindist = dist;
- new_slot = last_free;
+ if (badness < minbadness) {
+ best = rs;
+ minbadness = badness;
}
}
- if (nearest != NULL) { /* We have a suitable stop */
- DEBUG(ms, 3) ("Multistop: -- Slot %d of stop at 0x%x assinged.", new_slot, nearest->xy);
- nearest->slot[new_slot] = v->index;
+ if (best != NULL) {
+ best->num_vehicles++;
+ DEBUG(ms, 3) (" -- Assigned to stop 0x%x", best->xy);
- v->u.road.slot = nearest;
- v->dest_tile = nearest->xy;
+ v->u.road.slot = best;
+ v->dest_tile = best->xy;
v->u.road.slot_age = 14;
- v->u.road.slotindex = new_slot;
-
- if (v->vehstatus & VS_WAIT_FOR_SLOT) {
- DEBUG(ms, 4) ("Multistop: ---- stopped vehicle got a slot. resuming movement");
- v->vehstatus &= ~VS_WAIT_FOR_SLOT;
- InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
- }
} else {
- DEBUG(ms, 2) ("Multistop -- No free slot at station. Waiting");
- v->vehstatus |= VS_WAIT_FOR_SLOT;
- InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
+ DEBUG(ms, 3) (" -- Could not find a suitable stop");
}
} else {
DEBUG(ms, 5) ("Multistop: --- Distance from station too far. Postponing slotting for vehicle %d (index %d) at station %d, (0x%x)",