Make the fleet passive and put the player at the helm - #140
Merged
Conversation
The fleet becomes the background economy; captaining a boat yourself becomes the game. Passive fleet: - Every role now earns each morning, not just fishing. Hauling and transport bring in money, piracy brings in the most plus seized fish - and a bad day of piracy damages the hull and can cost a villager - Add an overnight report surfaced wherever a day passes (sleeping, a night at the tavern, an export run, a voyage), so losing a named crew member is news the player is told rather than a roster they notice changed later Captained voyages (src/business/adventures.py): - Take the Helm at the docks: pick a boat, pick how far out, provision her, then sail her a leg at a time. Each leg is a day at sea and puts a situation in front of you - Hull, supplies and crew only get scarcer unless a decision is spent on them, and the hold is only yours if you get home - The crew you brought unlock choices nobody else can offer - Iris Dunmore reads the weather, Cormac Ide patches a hull at sea, Sena Vale works out where a merchantman will anchor. Crewing becomes casting - A voyage that founders is cut short: the hold goes over the side and she comes back a wreck, but the boat is still yours - A boat at sea earns nothing at home; that's the cost of taking the helm Removes src/business/voyages.py: the one-shot job runs are superseded, and leaving them alongside passive income would have paid twice for the same day. totalRaids/totalPlunder now count days of passive piracy so existing saves keep their numbers. Found by playing it: one event ate half a full stores load on a short voyage, which made "full stores" a lie. Halved that cost and added a deep-stores option so insuring against a bad week is the player's call. Also fixed two tests that assumed every voyage runs its full length - they were flaky about 1 run in 6, because a foundering voyage correctly ends early. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI caught what ten local runs did not: pinning random.randint alone isn't enough to guarantee a voyage completes. Events that consume stores don't use randint at all, so a full load can still empty out, and the starvation roll is random.random - which on a two-hand crew can take both of them and founder her on the last leg. Pin both dice in the two tests that need a completed voyage. Verified with 25 consecutive runs of the docks suite. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI caught what ten local runs did not: pinning random.randint alone isn't enough to guarantee a voyage completes. Events that consume stores don't use randint at all, so a full load can still empty out, and the starvation roll is random.random - which on a two-hand crew can take both of them and founder her on the last leg. Pin both dice in the two tests that need a completed voyage. Verified with 25 consecutive runs of the docks suite and 10 of the whole one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reviewed and played each round, against Nielsen's heuristics and Krug's "don't make me think". 1. Visibility of system status. Every boat's line now says what she earns a day, and the fleet header leads with income against payroll and the net. There was no way to tell a boat that paid her wages from one that didn't. Also fixed a label that read as a stutter - "Fishing Fleet, Fishing" - by leading with the role and labelling the hull. 2. Don't make me think. The plan menu quoted "x1.6 the pickings" against a per-leg value the player couldn't see; it now quotes what the voyage is worth in money. The boat picker says what taking her out gives up. The standing village prompt no longer follows you out to sea. 3. Error prevention. Half rations on a long voyage was certain starvation presented as a neutral option; every provisioning option now says which day it runs out on. Sailing a half-wrecked hull on an eleven-day voyage now warns first, with the repair cost. The repair refusal says how to raise the money. 4. User control and freedom. You can break off and run for home from any leg, keeping the hold - being committed to every leg made a thinning hull a slow walk to the bottom rather than a decision. The hold is now on the status line; the only numbers moving on screen were the money and fish at home, which climb from the rest of the fleet and read as progress when they weren't. 5. Recognition over recall. The docks screen names anything wrong with the fleet - a boat idle, a hull that can't sail, hands ashore on full wages - instead of leaving it to be found by opening the fleet screen. The overnight report puts the wages next to the takings so a day reads as a profit or a loss, and says where to repair a damaged boat. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
startVoyage marks a boat atSea and the flag gets serialized, so a save written with it set would otherwise strand her out of the fleet economy with no way back. The loader already rebuilds boats without it; this holds that behaviour down. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The fleet becomes the background economy, and captaining a boat yourself becomes the game. Two halves, landed together because either alone leaves the game worse: passive-only removes the interactive content, and voyages-only would pay twice for the same day.
The fleet runs itself
Every role earns each morning now, not just fishing — hauling and transport bring in money, piracy brings in the most plus seized fish. A bad day of piracy damages the hull and, rarely, costs a villager.
That last part needed a way to tell the player, so
increaseDaynow returns an overnight report surfaced everywhere a day passes (sleeping, a night at the tavern, an export run, a voyage). Losing someone you hired by name should never be something you only notice because the roster got shorter.Taking the helm —
src/business/adventures.pyTake the Helm at the docks. Pick a boat, pick how far out (short run / middle grounds / far water — longer, richer, less forgiving), provision her, then sail her a leg at a time. Each leg is a day at sea and puts a situation in front of you:
That third option exists only because Iris Dunmore is aboard. Choices are gated on the specialties of the villagers you actually brought — Cormac Ide finds the seam in a leaking hull, Junia Marsh goes over the side after what sank, Bastian Roe nurses a sick crew through the night, Sena Vale works out where a merchantman will anchor so you take her asleep. Crewing a boat stops being a headcount and becomes casting, which is what makes the villager roster pay off.
Hull, supplies and crew only ever get scarcer unless a decision is spent on them, and the hold is only yours if you get home. If the hull gives out or the crew starve the voyage is cut short — everything aboard is lost and she comes back a wreck, but the boat is still yours, so a bad run is a setback rather than a save-wrecker. A boat at sea earns nothing at home; that's what taking the helm costs.
Nine events across four role-filtered pools, with the shared ones (squall, wreckage, a leak, sickness, becalmed) reachable by any role and the rest specific — a fishing voyage never meets a patrol cutter, and a raid never frets about its passengers.
Removals
src/business/voyages.pyis deleted. The one-shot job runs it added this morning are superseded by captained voyages, and keeping them alongside passive income would have paid twice for the same day.totalRaids/totalPlundernow count days of passive piracy, so the counts already in live saves stay meaningful instead of being stranded.Test plan
python3 -m compileall -q src testsSDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy python3 -m pytest --verbose -vv --cov=src --cov-report=term-missing --cov-report=xml:cov.xml— 606 passed, 96% total;adventures.pyandboats.pyboth 97%.black+autoflakeover the changed files only.showOptions/showDialogue/currentPrompt— no new primitive, so console, pygame and web all get voyages.Two things playing it caught
crew × 2supplies, which on a short voyage is half a full load — so a fully-provisioned 4-leg run starved on leg 3. Halved that cost, and added a deep stores option so insuring against a bad week is a decision the player gets to make rather than a trap.Balance note
A captained leg is worth several times what the same boat earns passively in a day, which is the point — but the numbers are first-pass.
ROLE_LEG_VALUE,VOYAGE_PLANS' multipliers andROLE_DAILY_PER_CREWare each a single table if it plays too hot or too cold.