17
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-11-04 14:55:52 +01:00

Keep one primary per consist and let a secondary AI claim it.

A driver without movePrimary no longer just idles. UpdateSecondary() cuts
BrakeValveActive so a secondary AI stops fighting the primary over the brake
pipe, and - as long as no driver in the consist has iEngineActive - keeps
scanning ahead of CabOccupied, so it can take movePrimary and start the engine
once a signal permits.

scan_route() orients by CabOccupied when DirActive is 0, and
ClaimConsistPrimary() clears movePrimary on every other driver in the consist,
then calls TableClear() and CheckVehicles(), so sSpeedTable is rebuilt for the
new front and ctOwner follows it.

- walk the consist with FirstFind()/Neighbour() instead of Next()/Prev(), which
  stopped at the starting vehicle and mishandled reversed members;
- ReassignConsistPrimary() picks a single driver after any coupling change,
  both from TDynamicObject::couple() and from the AI path;
- IsOccupiedByAnotherConsist() decides membership with BelongsToConsist() and
  takes a signed distance, so a consist left behind no longer cuts the scan
  short. DistanceToAnotherConsist() hands back the gap it already computes, so
  OtherConsistAtSignal() counts a foreign vehicle only while it stands closer
  than the signal itself, instead of comparing track starts;
- TSpeedPos::Set() marks an entry with spNotOurShuntSignal when a
  spShuntSemaphor was already permitting as the entry was added. A shunting
  signal does not address its permission to a particular consist, so a dormant
  driver does not wake up on a permission it did not see light up; the flag
  drops once the signal shows stop, so its own turn is never blocked. spSemaphor
  is excluded: a semaphore sets a route for us and permits us even when found
  already lit. The check reads SemPermitIndex - the entry that produced the
  permitting command - because SemNextIndex can point at an earlier signal.
  The flag is also stamped whenever the permission turns out to belong to a
  consist standing in front of us - both where TableUpdateEvent() already knows
  the signal is for the vehicle ahead, and in check_route_ahead() - so the
  addressee pulling away does not hand the still-lit signal over to whoever
  waited behind it;
- the scantable debug panel lists the flags by name (spNotOurShuntSignal shows
  as not-ours) and folds the nearest vehicle ahead into the table by its own
  distance.
This commit is contained in:
maj00r
2026-09-06 10:16:24 +02:00
parent 7a469190ca
commit aaccd7b9b7
9 changed files with 759 additions and 175 deletions

View File

@@ -4468,6 +4468,54 @@ void TMoverParameters::CompressorCheck(double dt)
}
}
double TMoverParameters::GetDPMainValve(double dt, double hp) const
{
if (!BrakeValveActive)
{
return 0.0;
}
auto const caboccupied{CabOccupied != 0};
auto const use_handle{
(BrakeOpModes & bom_PS) == 0
|| (caboccupied && BrakeOpModeFlag != bom_PS)};
if (!use_handle)
{
if (BrakeCtrlPos == Handle->GetPos(bh_EB))
{
return Handle->GetPF(BrakeCtrlPosR, PipePress, hp, dt, EqvtPipePress);
}
return 0.0;
}
auto const mhzepidle{
BrakeOpModeFlag >= bom_EP
&& BrakeCtrlPosR <= Handle->GetPos(bh_EB) - 0.5
&& (BrakeHandle == TBrakeHandle::MHZ_EN57 || BrakeHandle == TBrakeHandle::MHZ_K8P)};
if (mhzepidle)
{
return Handle->GetPF(0, PipePress, hp, dt, EqvtPipePress);
}
double pos{BrakeCtrlPosR};
if (SpeedCtrlUnit.IsActive
&& SpeedCtrlUnit.BrakeIntervention
&& !SpeedCtrlUnit.Standby
&& BrakeCtrlPos != Handle->GetPos(bh_EB))
{
pos = Handle->GetPos(bh_NP);
if (SpeedCtrlUnit.BrakeInterventionBraking)
pos = Handle->GetPos(bh_FB);
if (SpeedCtrlUnit.BrakeInterventionUnbraking)
pos = Handle->GetPos(bh_RP);
}
return Handle->GetPF(pos, PipePress, hp, dt, EqvtPipePress);
}
// *************************************************************************************************
// Q: 20160712
// aktualizacja ciśnienia w przewodzie głównym
@@ -4484,7 +4532,7 @@ void TMoverParameters::UpdatePipePressure(double dt)
const double kL = 0.5;
// double dV;
// TMoverParameters *c; // T_MoverParameters
double temp;
double hp{0.0};
// int b;
PipePress = Pipe->P();
@@ -4537,39 +4585,15 @@ void TMoverParameters::UpdatePipePressure(double dt)
if (lock_old || lock_new)
{
temp = PipePress + 0.00001;
hp = PipePress + 0.00001;
}
else
{
temp = ScndPipePress;
hp = ScndPipePress;
}
Handle->SetReductor(BrakeCtrlPos2);
if ((BrakeOpModes & bom_PS) == 0 || (CabOccupied != 0 && BrakeOpModeFlag != bom_PS))
{
if (BrakeOpModeFlag < bom_EP || Handle->GetPos(bh_EB) - 0.5 < BrakeCtrlPosR || (BrakeHandle != TBrakeHandle::MHZ_EN57 && BrakeHandle != TBrakeHandle::MHZ_K8P))
{
double pos = BrakeCtrlPosR;
if (SpeedCtrlUnit.IsActive && SpeedCtrlUnit.BrakeIntervention && !SpeedCtrlUnit.Standby && BrakeCtrlPos != Handle->GetPos(bh_EB))
{
pos = Handle->GetPos(bh_NP);
if (SpeedCtrlUnit.BrakeInterventionBraking)
pos = Handle->GetPos(bh_FB);
if (SpeedCtrlUnit.BrakeInterventionUnbraking)
pos = Handle->GetPos(bh_RP);
}
dpMainValve = Handle->GetPF(pos, PipePress, temp, dt, EqvtPipePress);
}
else
{
dpMainValve = Handle->GetPF(0, PipePress, temp, dt, EqvtPipePress);
}
}
else if (BrakeCtrlPos == Handle->GetPos(bh_EB))
{
dpMainValve = Handle->GetPF(BrakeCtrlPosR, PipePress, temp, dt, EqvtPipePress);
}
dpMainValve = GetDPMainValve(dt, hp);
if (dpMainValve < 0) // && (PipePressureVal > 0.01) //50
if (Compressor > ScndPipePress)
@@ -4740,11 +4764,9 @@ void TMoverParameters::UpdatePipePressure(double dt)
Pipe->Act();
PipePress = Pipe->P();
if ((Hamulec->GetBrakeStatus() & b_dmg) == b_dmg) // jesli hamulec wyłączony
temp = 0.0; // odetnij
else
temp = 1.0; // połącz
Pipe->Flow(temp * Hamulec->GetPF(temp * PipePress, dt, Vel) + GetDVc(dt));
// a damaged distributor cuts the car off from the pipe (as temp=0/1 used to)
auto const distributor_open{(Hamulec->GetBrakeStatus() & b_dmg) != b_dmg ? 1.0 : 0.0};
Pipe->Flow(distributor_open * Hamulec->GetPF(distributor_open * PipePress, dt, Vel) + GetDVc(dt));
if (ASBType == 128)
Hamulec->ASB(int(SlippingWheels && Vel > 1) * (1 + 2 * int(nrot_eps < -0.01)));