# Deep Hook Fishing > A free, no-install, browser-based Three.js fishing game. Cast a hook > into a 100-ft underwater column. Phase 1: descend while dodging fish > (collisions slow you down; descent timer caps depth). Phase 2: the > line retracts; catch ten of the best fish on the way up. Score = sum > of caught-fish points × depth bonus. Replay-validated leaderboard. Tagline: Cast Deep. Dodge Down. Catch Up. Site: https://tglgames.com/ Play: https://tglgames.com/deep-hook-fishing/ About: https://tglgames.com/deep-hook-fishing/about/ Leaderboard: https://tglgames.com/deep-hook-fishing/leaders/ ## What it is Single-player browser fishing game with a two-phase loop (descent + retract). Real-time 3D rendered with Three.js (importmap → unpkg CDN, no build step). Mobile-first: portrait stage, drag-to-steer, on-screen d-pad for one-thumb play, plus keyboard arrows for desktop. Same self-hosted gamehub backend as the rest of tglgames.com: guest session cookie, signed run tokens, replay-validated leaderboard. ## The two phases 1. **Cast** (~1.4 s cinematic) — hook drops from above the surface. 2. **Descend** — base velocity 30 ft/s downward. Player steers the hook left/right. Hitting a fish or a column wall stuns the hook for 800 ms (velocity clamps to 6 ft/s). A 6-second descent timer caps reachable depth — too many bumps means the hook does not reach the 100-ft bottom. 3. **Retract** — line rises at 25 ft/s. Player steers to *touch* fish; the first 10 touches are caught. After 10, additional touches are ignored. If the hook reaches the surface before 10 catches, retract ends with however many were caught. 4. **Score** — server submit, leaderboard + per-user stats update. ## Scoring ``` descent_bonus = clamp(depth_reached_ft / 100, 0.3, 1.5) score = round(sum(caught_fish.base_pts) * descent_bonus) ``` Deeper casts multiply the catch ceiling; a max-depth (100 ft) run multiplies by 1.5. A shallow run is capped to 0.3. ## Fish catalog Ten species. Each fish has weight (lb), spawn rarity (higher = more common at its depth band), point value, and a depth band where it can appear. The spawn picker uses weighted random per the current depth. | Fish | Weight (lb) | Rarity | Points | Depth band | | --- | --: | --: | --: | --- | | Minnow | 0.2 | 30 | 1 | 0–40 ft | | Sunfish | 0.7 | 25 | 2 | 0–60 ft | | Bass | 3.0 | 18 | 5 | 20–80 ft | | Trout | 4.5 | 14 | 7 | 30–80 ft | | Catfish | 12.0 | 8 | 12 | 50–100 ft | | Pike | 18.0 | 6 | 15 | 60–100 ft | | Sturgeon | 60.0 | 3 | 25 | 80–100 ft | | Tuna | 120.0 | 2 | 30 | 80–100 ft | | Marlin | 250.0 | 1 | 50 | 90–100 ft | | Golden Bass | 5.0 | 0.2 | 100 | 70–100 ft (mythic) | ## Anti-cheat Every run is *capable* of being replay-validated: spawn order is seeded by the server's `run_token` seed using the same Mulberry32 PRNG as other tglgames.com games. The first release uses a sanity-cap validator (depth ≤ 100 ft, catches ≤ 10, score consistent with the recorded catalog of caught fish). Full deterministic spawn-order replay is a follow-up — flagged in the project plan. ## Logging policy Every fish spawn, collision, near-miss (within ~1.5 hook radii), catch, phase transition, and final score is appended to a `move_log` JSON array, posted to `/api/run/submit`, and kept on the server forever. No opt-out toggle. ## Files - `/deep-hook-fishing/index.html` — game shell (HUD, drawer, importmap) - `/deep-hook-fishing/js/main.js` — composition root, render loop, phases - `/deep-hook-fishing/js/scene.js` — Three.js scene (camera, fog, walls, seabed) - `/deep-hook-fishing/js/hook.js` — hook mesh + descent/retract physics - `/deep-hook-fishing/js/fish.js` — fish actors (stretched ellipsoid + tail) - `/deep-hook-fishing/js/fish-catalog.js` — pure data table of 10 species - `/deep-hook-fishing/js/spawner.js` — seeded weighted spawn by depth band - `/deep-hook-fishing/js/input.js` — keyboard, pointer, d-pad routing - `/deep-hook-fishing/js/hud.js` — depth/timer/catch ledger - `/deep-hook-fishing/js/state.js` — mutable singleton + TUNING constants - `/deep-hook-fishing/js/rng.js` — Mulberry32 (matches `api/lib/rng.php`) - `/deep-hook-fishing/js/log.js` — event recorder for `move_log` - `/deep-hook-fishing/js/api.js` — `/api/run/start` and `/api/run/submit` wrappers - `/api/games/deep-hook-fishing.php` — `DeepHookFishingValidator::validate()` ## Schema Standard runs lifecycle. Per-game stats in `deep_hook_fishing_runs` (1:1 with `runs.id`): `depth_reached_ft`, `collisions_descent`, `dodge_streak_best`, `fish_caught_count`, `heaviest_lb`, `rarest_fish_id`, `descent_ms`, `retract_ms`, `input_key/pointer/dpad`, and `move_log` LONGTEXT. ## Author Made by mgwalk at https://tglgames.com/