diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index aedfcff..2e0a916 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -1,7 +1,76 @@
# Copilot Instructions
+---
+name: karpathy-guidelines
+description: Behavioral guidelines to reduce common LLM coding mistakes. Use when writing, reviewing, or refactoring code to avoid overcomplication, make surgical changes, surface assumptions, and define verifiable success criteria.
+license: MIT
+---
+
+# Karpathy Guidelines
+
+Behavioral guidelines to reduce common LLM coding mistakes, derived from [Andrej Karpathy's observations](https://x.com/karpathy/status/2015883857489522876) on LLM coding pitfalls.
+
+**Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment.
+
+## 1. Think Before Coding
+
+**Don't assume. Don't hide confusion. Surface tradeoffs.**
+
+Before implementing:
+- State your assumptions explicitly. If uncertain, ask.
+- If multiple interpretations exist, present them - don't pick silently.
+- If a simpler approach exists, say so. Push back when warranted.
+- If something is unclear, stop. Name what's confusing. Ask.
+
+## 2. Simplicity First
+
+**Minimum code that solves the problem. Nothing speculative.**
+
+- No features beyond what was asked.
+- No abstractions for single-use code.
+- No "flexibility" or "configurability" that wasn't requested.
+- No error handling for impossible scenarios.
+- If you write 200 lines and it could be 50, rewrite it.
+
+Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
+
+## 3. Surgical Changes
+
+**Touch only what you must. Clean up only your own mess.**
+
+When editing existing code:
+- Don't "improve" adjacent code, comments, or formatting.
+- Don't refactor things that aren't broken.
+- Match existing style, even if you'd do it differently.
+- If you notice unrelated dead code, mention it - don't delete it.
+
+When your changes create orphans:
+- Remove imports/variables/functions that YOUR changes made unused.
+- Don't remove pre-existing dead code unless asked.
+
+The test: Every changed line should trace directly to the user's request.
+
+## 4. Goal-Driven Execution
+
+**Define success criteria. Loop until verified.**
+
+Transform tasks into verifiable goals:
+- "Add validation" → "Write tests for invalid inputs, then make them pass"
+- "Fix the bug" → "Write a test that reproduces it, then make it pass"
+- "Refactor X" → "Ensure tests pass before and after"
+
+For multi-step tasks, state a brief plan:
+```
+1. [Step] → verify: [check]
+2. [Step] → verify: [check]
+3. [Step] → verify: [check]
+```
+
+Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
+
+
## Project Guidelines
-- For this G-effects model, the desired behavior is that a 1→5 Gz+ ramp over 5 seconds should not reach full unconsciousness in ~10 seconds; target loss-of-consciousness timing should be closer to 20–30 seconds (without fatigue modeled yet).
+- For this G-effects model, the desired behavior is that a 1→5 Gz+ ramp over 5 seconds should reach loss-of-consciousness between 25 and 35 seconds.
## Visibility Semantics
- TunnelVisionLevel semantics: 1 means no visibility left, and 0.5 means half of the field of view is still free. TunnelVisionLevel should reach 1 when ConsciousnessLevel is close to 0, and tunnel vision should not be driven too directly by short perfusion recovery dips.
diff --git a/.github/skills/andrej-karpathy-skills/SKILL.md b/.github/skills/andrej-karpathy-skills/SKILL.md
new file mode 100644
index 0000000..6a62d04
--- /dev/null
+++ b/.github/skills/andrej-karpathy-skills/SKILL.md
@@ -0,0 +1,67 @@
+---
+name: karpathy-guidelines
+description: Behavioral guidelines to reduce common LLM coding mistakes. Use when writing, reviewing, or refactoring code to avoid overcomplication, make surgical changes, surface assumptions, and define verifiable success criteria.
+license: MIT
+---
+
+# Karpathy Guidelines
+
+Behavioral guidelines to reduce common LLM coding mistakes, derived from [Andrej Karpathy's observations](https://x.com/karpathy/status/2015883857489522876) on LLM coding pitfalls.
+
+**Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment.
+
+## 1. Think Before Coding
+
+**Don't assume. Don't hide confusion. Surface tradeoffs.**
+
+Before implementing:
+- State your assumptions explicitly. If uncertain, ask.
+- If multiple interpretations exist, present them - don't pick silently.
+- If a simpler approach exists, say so. Push back when warranted.
+- If something is unclear, stop. Name what's confusing. Ask.
+
+## 2. Simplicity First
+
+**Minimum code that solves the problem. Nothing speculative.**
+
+- No features beyond what was asked.
+- No abstractions for single-use code.
+- No "flexibility" or "configurability" that wasn't requested.
+- No error handling for impossible scenarios.
+- If you write 200 lines and it could be 50, rewrite it.
+
+Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
+
+## 3. Surgical Changes
+
+**Touch only what you must. Clean up only your own mess.**
+
+When editing existing code:
+- Don't "improve" adjacent code, comments, or formatting.
+- Don't refactor things that aren't broken.
+- Match existing style, even if you'd do it differently.
+- If you notice unrelated dead code, mention it - don't delete it.
+
+When your changes create orphans:
+- Remove imports/variables/functions that YOUR changes made unused.
+- Don't remove pre-existing dead code unless asked.
+
+The test: Every changed line should trace directly to the user's request.
+
+## 4. Goal-Driven Execution
+
+**Define success criteria. Loop until verified.**
+
+Transform tasks into verifiable goals:
+- "Add validation" → "Write tests for invalid inputs, then make them pass"
+- "Fix the bug" → "Write a test that reproduces it, then make it pass"
+- "Refactor X" → "Ensure tests pass before and after"
+
+For multi-step tasks, state a brief plan:
+```
+1. [Step] → verify: [check]
+2. [Step] → verify: [check]
+3. [Step] → verify: [check]
+```
+
+Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
diff --git a/GEffectsLogic/GEffectsLogic.csproj b/GEffectsLogic/GEffectsLogic.csproj
index 89add90..4c70a85 100644
--- a/GEffectsLogic/GEffectsLogic.csproj
+++ b/GEffectsLogic/GEffectsLogic.csproj
@@ -8,9 +8,9 @@
Debug;Release;PerfDebug
False
- 0.4.0
+ 0.5.0
$(VersionPrefix)
- 0.4.0.0
+ 0.5.0.0
$(VersionPrefix).0
nogit
diff --git a/GEffectsLogic/PhysiologicalModel.cs b/GEffectsLogic/PhysiologicalModel.cs
index e761124..476fadf 100644
--- a/GEffectsLogic/PhysiologicalModel.cs
+++ b/GEffectsLogic/PhysiologicalModel.cs
@@ -61,7 +61,7 @@ protected double
//protected double confusionLevel = 0.0;
protected double greyScaleLevel;
protected double tunnelVisionLevel;
- protected double blurLevel; // Higher than tunnelvision, matches at 0.85
+ protected double blurLevel; // Rises early, then slowly approaches greyscale
protected double filmgrainLevel; // 25% influence on filmgrain, 75% from vignette alpha
protected bool primaryColor = true; // true = normal (blackout), false = inverted (redout)
@@ -421,12 +421,12 @@ public virtual void Update(double dt, double gz, double gx = 0.0, double gy = 0.
var visualReserve = 0.7 * visualPerf + 0.3 * visualO2;
var visualDeficit = 1.0 - visualReserve;
- #region Tunnelvision
// Early/mid-visual impairment path.
// Keeps onset before LOC, but avoids saturating too early.
var physiologicalVisualTarget = Clamp((visualDeficit - 0.18) / 0.82, 0.0, 1.0);
physiologicalVisualTarget = Math.Pow(physiologicalVisualTarget, 2.2);
+ #region Tunnelvision
// Blackout path: if consciousness gets close to zero, tunnel vision must approach 1.
// This also reduces sensitivity to short perfusion recoveries.
var blackoutTunnelTarget = Clamp(1.0 - consciousnessLevel, 0.0, 1.0);
@@ -450,9 +450,21 @@ public virtual void Update(double dt, double gz, double gx = 0.0, double gy = 0.
tunnelVisionLevel = Clamp(tunnelVisionLevel, 0.0, 1.0);
#endregion
+ #region Greyscale
+ // physiologicalVisualTarget produces good enough curve, no extra target needed
+ var greyTau = physiologicalVisualTarget > greyScaleLevel
+ ? LogicSettings.GreyscaleVisualInTau
+ : LogicSettings.GreyscaleVisualOutTau;
+ greyScaleLevel = StepTowardsLinear(greyScaleLevel, physiologicalVisualTarget, greyTau, dt);
+ greyScaleLevel = Clamp(greyScaleLevel, 0.0, 1.0);
+ #endregion
+
#region Blur
- blurLevel = Clamp(Math.Pow(TunnelVisionLevel, 0.5), 0.0, 1.0);
+ var earlyBlurTarget = 0.23 * (1.0 - Math.Exp(-8.0 * physiologicalVisualTarget));
+ var earlyBlurInfluence = 1.0 - SmoothStep(Clamp((greyScaleLevel - 0.2) / 0.3, 0.0, 1.0));
+ var earlyBlurBoost = Math.Max(earlyBlurTarget - greyScaleLevel * 0.5, 0.0) * earlyBlurInfluence;
+ blurLevel = Clamp(greyScaleLevel + earlyBlurBoost, 0.0, 1.0);
#endregion
@@ -461,15 +473,6 @@ public virtual void Update(double dt, double gz, double gx = 0.0, double gy = 0.
filmgrainLevel = Clamp(Math.Pow(TunnelVisionLevel, 1.5), 0.0, 1.0);
#endregion
-
- #region Greyscale
- // physiologicalVisualTarget produces good enough curve, no extra target needed
- var greyTau = physiologicalVisualTarget > greyScaleLevel
- ? LogicSettings.GreyscaleVisualInTau
- : LogicSettings.GreyscaleVisualOutTau;
- greyScaleLevel = StepTowardsLinear(greyScaleLevel, physiologicalVisualTarget, greyTau, dt);
- greyScaleLevel = Clamp(greyScaleLevel, 0.0, 1.0);
- #endregion
// Hard guarantee: only enforce near total visual loss when consciousness is very close to zero.
var nearLoc = Clamp((0.12 - consciousnessLevel) / 0.12, 0.0, 1.0);