refactor: 每单元锁定一个Y车道,非轮转分配
- 单元→车道固定分配(管转向跟不上一发一个Y) - 车道需求 tracked,单元依次填满当前车道
This commit is contained in:
parent
29aa11665b
commit
4f509e5a2a
@ -145,68 +145,50 @@ namespace CounterDrone.Core.Algorithms
|
||||
}
|
||||
int totalRoundsNeeded = singleNeeded * yLanes;
|
||||
|
||||
// 计算所需齐射轮数
|
||||
int totalChannels = candidates.Sum(c => c.Unit.TotalChannels);
|
||||
int salvosNeeded = (int)Math.Ceiling((float)totalRoundsNeeded / Math.Max(1, totalChannels));
|
||||
|
||||
// 逐轮齐射分配
|
||||
// 逐单元分配:每个单元锁定一个 Y 车道
|
||||
var (effR2, _) = ComputeEffectiveRadius(threat, ammo, env);
|
||||
float spacing = effR2 * 1.5f;
|
||||
int[] laneNeeded = new int[yLanes];
|
||||
for (int l = 0; l < yLanes; l++) laneNeeded[l] = singleNeeded;
|
||||
int currentLane = 0;
|
||||
int roundsCollected = 0;
|
||||
int eventIdx = 0;
|
||||
var assignedUnits = new List<(FireUnit unit, int rounds, List<FireEvent> events)>();
|
||||
|
||||
// Y 车道间距
|
||||
var (effR2, _) = ComputeEffectiveRadius(threat, ammo, env);
|
||||
float laneSpacingY = yLanes > 1 ? formationWidth / (yLanes - 1) : 0f;
|
||||
|
||||
for (int salvo = 0; salvo < salvosNeeded; salvo++)
|
||||
foreach (var c in candidates.OrderBy(c => c.EarliestInterceptTime)
|
||||
.ThenByDescending(c => c.KillProbability))
|
||||
{
|
||||
float salvoDelay = salvo * candidates[0].Unit.Cooldown;
|
||||
if (roundsCollected >= totalRoundsNeeded) break;
|
||||
int remaining = remainingMunitions.GetValueOrDefault(c.Unit.Id, 0);
|
||||
if (remaining <= 0) continue;
|
||||
|
||||
// 车道参数
|
||||
var (laneEffR, _) = ComputeEffectiveRadius(threat, ammo, env);
|
||||
float cloudDiameter = laneEffR * 2f;
|
||||
float droneSpeed = (float)threat.Target.TypicalSpeed / 3.6f;
|
||||
float physicsInterval = Math.Max(candidates[0].Unit.ChannelInterval,
|
||||
cloudDiameter / droneSpeed);
|
||||
float spacing = laneEffR * 1.5f;
|
||||
// 找下一个有需求的车道
|
||||
while (currentLane < yLanes && laneNeeded[currentLane] <= 0) currentLane++;
|
||||
if (currentLane >= yLanes) break;
|
||||
|
||||
// 所有弹药以中点偏移=0为基准计算基础发射时间
|
||||
var refEvent = GenerateFireEventsAt(threat, candidates[0].Unit, neededAmmo, ammo, env, 0, 0, yLanes, formationWidth);
|
||||
float globalBaseFireTime = refEvent[0].FireTime;
|
||||
int toTake = Math.Min(Math.Min(c.Unit.TotalChannels, remaining), laneNeeded[currentLane]);
|
||||
if (toTake <= 0) continue;
|
||||
|
||||
foreach (var c in candidates.OrderBy(c => c.EarliestInterceptTime)
|
||||
.ThenByDescending(c => c.KillProbability))
|
||||
// 此单元的所有弹药锁定同一个 Y 车道
|
||||
int yLane = currentLane;
|
||||
var refEvt = GenerateFireEventsAt(threat, c.Unit, c.AmmoType, ammo, env, 0, yLane, yLanes, formationWidth);
|
||||
float unitBaseTime = refEvt[0].FireTime;
|
||||
|
||||
var fevents = new List<FireEvent>();
|
||||
for (int ch = 0; ch < toTake; ch++)
|
||||
{
|
||||
if (roundsCollected >= totalRoundsNeeded) break;
|
||||
int remaining = remainingMunitions.GetValueOrDefault(c.Unit.Id, 0);
|
||||
if (remaining <= 0) continue;
|
||||
|
||||
int maxSalvo = Math.Min(c.Unit.TotalChannels, remaining);
|
||||
int toTake = Math.Min(maxSalvo, totalRoundsNeeded - roundsCollected);
|
||||
if (toTake <= 0) continue;
|
||||
|
||||
// 所有单元以航路中点计算相同的基准发射时间,仅通道间隔错开
|
||||
var refEvt = GenerateFireEventsAt(threat, c.Unit, c.AmmoType, ammo, env, 0, 0, yLanes, formationWidth);
|
||||
float unitBaseTime = refEvt[0].FireTime;
|
||||
|
||||
var fevents = new List<FireEvent>();
|
||||
for (int ch = 0; ch < toTake; ch++)
|
||||
{
|
||||
float offset = (eventIdx - (totalRoundsNeeded - 1) / 2f) * spacing;
|
||||
int yLane = eventIdx % yLanes;
|
||||
var fe = GenerateFireEventsAt(threat, c.Unit, c.AmmoType, ammo, env, offset, yLane, yLanes, formationWidth);
|
||||
foreach (var e in fe)
|
||||
{
|
||||
e.FireTime = unitBaseTime + salvoDelay + ch * c.Unit.ChannelInterval;
|
||||
}
|
||||
fevents.AddRange(fe);
|
||||
eventIdx++;
|
||||
}
|
||||
|
||||
assignedUnits.Add((c.Unit, toTake, fevents));
|
||||
remainingMunitions[c.Unit.Id] -= toTake;
|
||||
roundsCollected += toTake;
|
||||
float offset = (eventIdx - (totalRoundsNeeded - 1) / 2f) * spacing;
|
||||
var fe = GenerateFireEventsAt(threat, c.Unit, c.AmmoType, ammo, env, offset, yLane, yLanes, formationWidth);
|
||||
foreach (var e in fe)
|
||||
e.FireTime = unitBaseTime + ch * c.Unit.ChannelInterval;
|
||||
fevents.AddRange(fe);
|
||||
eventIdx++;
|
||||
}
|
||||
|
||||
assignedUnits.Add((c.Unit, toTake, fevents));
|
||||
remainingMunitions[c.Unit.Id] -= toTake;
|
||||
laneNeeded[currentLane] -= toTake;
|
||||
roundsCollected += toTake;
|
||||
}
|
||||
|
||||
if (roundsCollected <= 0) { plan.ThreatsUnengaged++; continue; }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user