diff --git a/src/core/execution/SAMLauncherExecution.ts b/src/core/execution/SAMLauncherExecution.ts index 9de53c1c6..9f42d5f31 100644 --- a/src/core/execution/SAMLauncherExecution.ts +++ b/src/core/execution/SAMLauncherExecution.ts @@ -27,7 +27,9 @@ type InterceptionTile = { class SAMTargetingSystem { // Interception tiles are computed a single time, but it may not be reachable yet. // Store the result so it can be intercepted at the proper time, rather than recomputing each tick. - private readonly precomputedNukes: Map = new Map(); + // Null interception tile means there are no interception tiles in range. Store it to + private readonly precomputedNukes: Map = + new Map(); private readonly missileSpeed: number; constructor( @@ -89,7 +91,8 @@ class SAMTargetingSystem { return ( isUnit(unit) && unit.owner() !== this.sam.owner() && - !this.sam.owner().isFriendly(unit.owner()) + !this.sam.owner().isFriendly(unit.owner()) && + !unit.targetedBySAM() ); }, ); @@ -102,6 +105,10 @@ class SAMTargetingSystem { const nukeId = nuke.unit.id(); const cached = this.precomputedNukes.get(nukeId); if (cached !== undefined) { + if (cached === null) { + // Already computed as unreachable, skip + continue; + } if (cached.tick === ticks) { // Time to shoot! targets.push({ tile: cached.tile, unit: nuke.unit }); @@ -128,16 +135,14 @@ class SAMTargetingSystem { tile: interceptionTile.tile, }); } + } else { + // Store unreachable nukes in order to prevent useless interception computation + this.precomputedNukes.set(nukeId, null); } - // Don't permanently cache unreachable nukes, the nuke moves each tick - // and may become interceptable from a different angle on a future tick } - // Filter out nukes already being targeted by another SAM - const available = targets.filter((t) => !t.unit.targetedBySAM()); - return ( - available.sort((a: Target, b: Target) => { + targets.sort((a: Target, b: Target) => { // Prioritize Hydrogen Bombs if ( a.unit.type() === UnitType.HydrogenBomb &&