# Raclette Footy Cup — Game Mechanics & Formulas

> **For players:** paste this whole file into your favourite AI and ask it to design a
> team for you. It contains the exact formulas the match engine uses, so the AI can
> reason about real trade-offs. A starter prompt is at the bottom.
>
> This document is **generated live from the running game engine** — every number
> below is the real value currently in play, so it is always up to date.

---

## 1. The game in one minute

- You are a **manager**. You build a **team of 6 footballers** — **exactly 1 goalkeeper** + 5 outfield (defenders / midfielders / forwards, your choice of mix).
- Each footballer has **7 stats**, each **1–10**: `speed, strength, size, shooting, passing, stamina, intelligence`.
- Each footballer starts at 1 in every stat (a base of 7 points) and you get **25 extra points** to spend, up to **10 per stat**. So a single footballer's 7 stats can total at most **32**.
- Matches are **6-a-side**, played by an AI on a top-down 2D pitch. You don't control players live — your **stats and positions ARE your strategy**.
- A match lasts **240 real seconds** at 1× speed, simulating a **90-minute** game (time compression ≈ **22.5×**). The host can change playback speed; it doesn't change the result.
- Everything is **deterministic** given the team stats + a seed: the same teams always play out the same match.

### Positions matter
- **GK** — stays on its line, saves shots, distributes. Goalkeeping quality comes from **size** (coverage) and **speed** (reaction).
- **DEF / MID / FWD** — start deep / central / high. Defenders sit back, forwards push up. 1 GK + 5 FWD = all-out attack (and concedes a lot); 1 GK + 5 DEF parks the bus.

---

## 2. The 7 stats → what they actually do

Every stat maps through `deriveBody()` into concrete physical properties. The tables below are the **real derived values** at stat levels 1/3/5/7/10.

### ⚡ Speed — pace, acceleration, evasion
- `maxSpeed = 58 + speed × 18` (px/s) — top running speed.
- `accel = 300 + speed × 120` (px/s²) — how fast they reach top speed.
- `evade = speed × 0.025` — resistance to being dispossessed.
- Faster top speed **costs more stamina**: `speedFactor = maxSpeed / 150`.

| speed | maxSpeed (px/s) | accel (px/s²) | evade | stamina cost × |
| --- | --- | --- | --- | --- |
| 1 | 76 | 420 | 0.025 | 0.51 |
| 3 | 112 | 660 | 0.075 | 0.75 |
| 5 | 148 | 900 | 0.125 | 0.99 |
| 7 | 184 | 1140 | 0.175 | 1.23 |
| 10 | 238 | 1500 | 0.25 | 1.59 |

### 💪 Strength — winning the ball by force
- `push = 0.4 + strength × 0.22` — knockback you **deal** (the "boop").
- `brace = 0.45 + strength × 0.13` — knockback you **resist** (incoming impulse ÷ brace).
- `shield = clamp(0.10 + strength × 0.085, 0.1, 0.9)` — chance to **keep the ball** when booped.

| strength | push (deal) | brace (resist) | shield (keep ball) |
| --- | --- | --- | --- |
| 1 | 0.62 | 0.58 | 0.19 |
| 3 | 1.06 | 0.84 | 0.36 |
| 5 | 1.5 | 1.1 | 0.53 |
| 7 | 1.94 | 1.36 | 0.7 |
| 10 | 2.6 | 1.75 | 0.9 |

### 📏 Size — a literally bigger body
- `radius = 10 + size × 1.2` (px) — a bigger circle.
- `mass = 0.5 + size × 0.2` — harder to knock back.
- `reach = radius + 7` — ball-winning / contact distance.
- Bigger keepers cover more goal. Size adds **no speed**.

| size | radius (px) | mass | reach (px) |
| --- | --- | --- | --- |
| 1 | 11.2 | 0.7 | 18.2 |
| 3 | 13.6 | 1.1 | 20.6 |
| 5 | 16 | 1.5 | 23 |
| 7 | 18.4 | 1.9 | 25.4 |
| 10 | 22 | 2.5 | 29 |

### 🎯 Shooting — power & accuracy (especially from range)
- `shotPower = 350 + shooting × 100` (px/s) — harder shots are tougher to save.
- On-target chance & placement depend on **shooting AND distance** (see §3).

| shooting | shotPower (px/s) |
| --- | --- |
| 1 | 450 |
| 3 | 650 |
| 5 | 850 |
| 7 | 1050 |
| 10 | 1350 |

### 🎩 Passing — crisp vs wobbly distribution
- `passAcc = clamp(0.22 + passing × 0.085, 0.22, 1)`.
- `wobble = (1 − passAcc) × 110` (px/s) — low passing sprays it.
- Pass speed `= 320 + passing × 18` (px/s), before fatigue.

| passing | passAcc | wobble (px/s) | pass speed (px/s) |
| --- | --- | --- | --- |
| 1 | 0.305 | 76.5 | 338 |
| 3 | 0.475 | 57.8 | 374 |
| 5 | 0.645 | 39.1 | 410 |
| 7 | 0.815 | 20.3 | 446 |
| 10 | 1 | 0 | 500 |

### 🔋 Stamina — keep your level for 90 minutes
- `staminaPool = 0.3 + stamina × 0.11` — a bigger pool drains slower (see §5).

| stamina | staminaPool |
| --- | --- |
| 1 | 0.41 |
| 3 | 0.63 |
| 5 | 0.85 |
| 7 | 1.07 |
| 10 | 1.4 |

### 🧠 Intelligence — anticipation, dribbling & shot selection
Intelligence adds no raw pace or power — it makes a footballer *think*. It sets a hidden `vision = (intelligence − 1) / 9` (0 at int 1, 1 at int 10) that drives:
- **Reading loose balls & passes:** smart players spot a free ball from further away (detection radius `250 + vision × 170` px) and run onto **where it's going** (anticipating by `leadTime = vision × 0.4` of the ball's flight) instead of chasing where it is.
- **Dribbling:** intelligent carriers **weave around** the nearest defender in their path; dumb ones (int 1) beeline straight into contact.
- **Shot selection:** smart shooters lean *off* low-percentage shots toward better chances — shot willingness is scaled by `1 − vision × 0.55 × (1 − onTargetChance)`, so a clever player wastes far fewer hopeless efforts but still buries good ones.

| intelligence | vision | leadTime (s of flight) | loose-ball radius (px) |
| --- | --- | --- | --- |
| 1 | 0 | 0 | 250 |
| 3 | 0.15 | 0.08 | 276 |
| 5 | 0.3 | 0.15 | 301 |
| 7 | 0.3 | 0.15 | 301 |
| 10 | 0.3 | 0.15 | 301 |

> Takeaway: intelligence is an **off-ball and decision** stat — great for intercepting, beating defenders, and not wasting shots. It won't help you out-run or out-muscle anyone.

---

## 3. Shooting, on target, and saves

When a carrier shoots, the engine rolls **on target?** then **saved?**

**On target** (`onTargetChance`): `clamp(0.32 + shooting × 0.085 − (dist/700) × 0.45, 0.05, 0.96)` (dist to goal in px, capped 700).

| shooting \\ dist→ | 100px | 250px | 400px | 550px | 700px |
| --- | --- | --- | --- | --- | --- |
| 1 | 0.34 | 0.24 | 0.15 | 0.05 | 0.05 |
| 3 | 0.51 | 0.41 | 0.32 | 0.22 | 0.12 |
| 5 | 0.68 | 0.58 | 0.49 | 0.39 | 0.3 |
| 7 | 0.85 | 0.75 | 0.66 | 0.56 | 0.47 |
| 10 | 0.96 | 0.96 | 0.91 | 0.82 | 0.72 |

> **Shooting is worth far more from range.** Close in, even weak shooters hit the target; from distance only snipers do.

**Saved** (`saveChance`): `clamp(0.16 + gkReflex × 0.45 × reactFrac − shooterShooting × 0.04, 0.04, 0.85)`, where `gkReflex = 0.45 × size/10 + 0.55 × speed/10` and `reactFrac` rises the longer the ball takes to arrive. Harder `shotPower` arrives sooner → lower save chance.

Save chance for a keeper (its **size & speed** both at the listed level) facing a shooting-5 shot:

| GK size&speed | point-blank (60px) | box edge (200px) | long (400px) |
| --- | --- | --- | --- |
| 1 | 0.04 | 0.04 | 0.04 |
| 3 | 0.04 | 0.05 | 0.1 |
| 5 | 0.05 | 0.11 | 0.19 |
| 7 | 0.09 | 0.17 | 0.27 |
| 10 | 0.14 | 0.26 | 0.41 |

> A good keeper needs **both size and speed**. Nobody saves everything point-blank (0.85 cap) — defend the shot at source.

---

## 4. Winning the ball: collisions & tackling

Players are circles with mass. When two overlap, `resolveCollision` separates them and, if closing, applies the **"boop"**:
- `jBase = −(1 + 0.35) × closingSpeed / (1/massA + 1/massB)`, scaled by `(their push / your brace) × 0.9`.
- Lighter bodies get shoved more; knockback excess is capped at **320 px/s**.

A boop on the **carrier** by an opponent can **dislodge the ball** (`dislodgeChance`):
`clamp(0.10 + (impactSpeed/300) × 0.45 + attacker.strength × 0.07 − owner.shield − owner.evade × 0.5, 0.02, 0.95)`

At a firm 150 px/s impact, vs a weak carrier (str 1) and a strong+fast carrier (str 10, spd 10):

| attacker strength | vs weak carrier | vs strong+fast carrier |
| --- | --- | --- |
| 1 | 0.15 | 0.02 |
| 3 | 0.29 | 0.02 |
| 5 | 0.43 | 0.02 |
| 7 | 0.57 | 0.02 |
| 10 | 0.78 | 0.02 |

- A failed tackle = **0.9 s cooldown**. Very hard hits can draw a card (foul chance `clamp(impactSpeed/900, 0, 0.12)`, ~6% red).

> **strength + size win the ball**; the carrier's **strength (shield) + speed (evade)** protect it. Pace also gets you there first.

---

## 5. Fatigue — why stamina is a real choice

Per game-second: `drain = effort × 0.0080 × speedFactor × dtGame / staminaPool`; `recover = (1 − effort) × 0.022 × dtGame`.
A tired player's effectiveness is `freshness = 1 − 0.5 × fatigue` — a fully-gassed player floors at **0.5×**. Freshness scales **top speed, shot power & accuracy, pass zip & accuracy, barging, and keeper reflexes**.

One game-minute of full sprinting (a speed-10 runner), from fresh:
- **stamina 1** → fatigue **1**, effectiveness **0.5×**
- **stamina 10** → fatigue **0.54**, effectiveness **0.73×**

> Low stamina on a **fast, busy** player is punished late. Slow players burn less.

---

## 6. Team-wide swings: momentum & rubber-band

Each team has **momentum** in [−1, 1], decaying toward 0: `m × exp(−0.12 × dt) + events`. Events: **score +0.35** (concede −0.25), shot on target +0.03, save +0.03, win a tackle +0.06 (lose it −0.04). Positive momentum → ~+10% speed, ~+25% press, a bit more aggression. A **rubber-band** lifts the trailing team: pride floor `clamp(deficit × 0.12, 0, 0.4)`.

> Matches swing; falling behind is partly self-correcting (good comebacks, no snowball).

---

## 7. How the AI decides on the ball

The carrier re-decides ≤ every **0.15 s**, computing a **shoot** and a **pass** probability, then one roll (leftover = dribble at goal).
- **Shoot** (outfield, within ~480px of goal): `clamp((0.03 + (shooting/10) × 0.22) × agg × max(0.35, 1 − shotDist/820) × smartShot, 0, 0.55)`, `agg = 1 + 0.25 × max(0, momentum)`, `smartShot` from intelligence (§2). Keepers never shoot.
- **Pass** (outfield): `clamp((passing/10) × 0.30 × bestOptionScore × agg (+0.07 if pressed), 0, 0.55)`. Keepers: `clamp(0.45 + (passing/10) × 0.4, 0.3, 0.95)`.
- **Best pass option** (`teammateScore`) blends how **open** a teammate is (200px clear = wide open) with how **forward** they are.

> **High shooting → shoots more & from further. High passing → keeps it moving to open, forward teammates.** A team of lone wolves wastes passing; a team with no shooters rarely scores.

---

## 8. Quick strategic implications

- **Pace** wins loose balls/races, feeds keeper reactions, and lets you make tackling contact.
- **Strength + size** = a ball-winning, ball-keeping spine; size costs no stamina but adds no speed.
- **Shooting is range-dependent** — a long-range sniper ≠ a get-close poacher.
- **Passing pays only with good options** (open, forward mates).
- **Stamina** is insurance on your fastest, busiest players.
- **Intelligence** wins the off-ball game (interceptions, beating defenders, shot discipline) but never out-runs or out-muscles.
- **Formation (position mix)** sets your risk: more forwards = more shots both ways.
- **Cap is 32 per footballer** (1 base in each of 7 stats + 25 to spend) — don't leave points unspent.

---

## 9. Starter prompt for your AI

> "You're my assistant manager in a football sim. Attached are the exact game
> mechanics and formulas. I have a team of **6 footballers** (exactly 1 goalkeeper +
> 5 outfield). Each footballer has 7 stats (speed, strength, size, shooting, passing, stamina, intelligence), each 1–10, and the
> 7 stats of any one footballer can total at most **32** (so 25 points to spend over a
> base of 1 each). Using the formulas, propose a full 6-footballer team (positions +
> every stat), explain the strategy, and name the main weakness an opponent could
> exploit. Optimise for [your goal here]."

---

*Mechanics live in `public/js/physics.js` (formulas/constants) and `public/js/engine.js` (AI decisions). This file is generated from them on every download, so it always matches the live game.*
