UPDATED DAILY FROM GITHUB RELEASES
Follow the latest changes across the Simulation Engine, Game API, Injury Engine, and Web App.
Clamped 0-yard sacks — where the pass-protection clamp caps YardsGained at 0 to prevent a safety when the offense is backed up to its own 1-yard line — were previously inferred as "not a sack" by YardsGained < 0 heuristics. This corrupted validator aggregate stats, engine player-stat attribution, and play result logging.
PassPlay.IsSack => SackResult != null — a single reliable sack signal (SackResult is only ever assigned on the genuine pass-protection sack path, never on completions, incompletions, spikes, scrambles, or interceptions).AggregateStats.cs): sack classification and the sack-yards matrix now key off IsSack instead of YardsGained < 0, so clamped 0-yard sacks are counted as sacks and no longer leak into incompletions.StatsAccumulator.cs): a clamped 0-yard sack no longer credits the QB a passing attempt or the receiver a target, and now correctly credits DL Sacks/Tackles and OL SacksAllowed.PassResult.cs): clamped 0-yard sacks log as "Sacked" rather than "Incomplete".12345, TestFluentSeedableRandom fluent methods including the new SackYardsBucketRoll).dotnet build && dotnet test: 0 warnings / 0 errors, 1982 passed, 6 skipped, 0 failed.GameProbabilities.cs, SackMatrix.cs) and the clamp logic itself are intentionally unchanged.This PR was generated with Release Please. See documentation.
Fixes a play-by-play logging regression introduced by #300. When PR #300 replaced the YardsGained < 0 sack heuristic with the new PassPlay.IsSack discriminator, the incomplete-vs-sack branch in PassResult.cs (!lastSegment.IsComplete && !play.IsSack) stopped excluding interceptions. As a result, a negative-yard interception return logged a spurious "Incomplete pass." line in addition to the correct interception log. The old YardsGained >= 0 predicate had accidentally suppressed this.
This is log-cosmetic only — no stat/aggregate corruption — but it produced contradictory play narration.
PassResult.cs: incomplete-pass branch now also guards && !play.Interception, so interception returns (including negative-yard returns) no longer emit an "Incomplete pass." log.AggregateStats.cs: simplified the hoisted isSack to passPlay?.IsSack ?? false. The earlier if (play.Interception) branch already classifies interceptions before the sack else if, so the removed !Interception/!IsTouchdown/!isComplete guards are behavior-preserving for all currently-modeled plays (verified against the full suite). This also avoids masking a future strip-sack defensive TD from sack totals.12345, fluent RNG): PassPlay_NegativeYardInterceptionReturn_LogsInterceptionNotIncompletePass — asserts a non-pick-six interception with negative net yards logs the interception and does not log "Incomplete pass".dotnet build && dotnet test: 1983 passed / 6 skipped / 0 failed (baseline 1982 + 1 new test), 0 warnings.play.Fumbles entry/recovery; and PassProtectionSkillsCheckResult logs the raw unclamped sack loss.Restores reliable Gridiron Engine package release automation so published engine releases can reach consumers through the NuGet feed once the required automation token is configured.
This uses the Release Please generic extra-files updater with the x-release-please-version annotation because the csproj version is an arbitrary metadata field rather than a standard manifest file. The publish workflow itself is unchanged.