Skip to content

Turn the single boat into a fleet with dedicated roles - #139

Merged
dmccoystephenson merged 1 commit into
mainfrom
feature/fleet-and-boat-roles
Aug 1, 2026
Merged

Turn the single boat into a fleet with dedicated roles#139
dmccoystephenson merged 1 commit into
mainfrom
feature/fleet-and-boat-roles

Conversation

@dmccoystephenson

Copy link
Copy Markdown
Member

Summary

One boat that could only fish becomes any number of boats, each dedicated to a role. Two new modules carry it:

  • src/business/boats.py — the fleet, the four roles, and crew assignment.
  • src/business/voyages.py — the job boards for the three active roles.
Role What she does
Fishing Crew bring in a catch every morning. The only role that catches anything.
Hauling Freight contracts, and half again the export capacity of the same hull in any other role.
Piracy Raids. Pays far better than honest work, and can cost a crew member permanently.
Transport Passenger runs: less money, but guaranteed and never damages the boat.

Crew come from one shared roster. A new hire goes aboard the first boat with a free berth and can be moved between boats afterwards. Wages are owed on every hand hired whether or not they have a berth, so an idle boat is a real cost — and when payroll can't be met, the idle hands quit first. Only crew on a fishing boat bring in a catch, so where people stand is now a decision with a number attached.

Voyages cost a day, same as an export run. Pay scales with hull tier and crew size.

Piracy is the deep one, and shows its real odds before the player commits — a full-crewed Fishing Fleet is ~90% against the Saltmarsh skiffs but 47% (with a 16% disaster risk) against the escorted Thornhaven bullion run. Four outcomes: a rich take, an ordinary take (plus fish seized off their hold, straight into yours), driven off with a scratched hull, or a disaster that takes a villager the player hired by name off the boat and off the roster for good. Damage is lasting — past halfway a boat can't sail until the yard is paid.

Compatibility

player.hasBoat and player.boatTier are now read-only properties derived from the fleet, so the flag and the tier can't disagree any more (they previously could). Every read site is unchanged; write sites went through boats.addBoat.

A save written before roles existed has no boats key, so it's migrated into a single fishing boat carrying the whole crew — the exact meaning that save had. Nobody loses a boat or a hand by loading an old file, and hasBoat/boatTier are still written out so an older build can read a modern save. There are live save slots on the production box, so this path has its own tests.

business.py is now just the tier catalogue; production, crew and selling moved to boats.py, which lets boats.py depend on it without an import cycle. tests/business/test_business.py was split accordingly, with the fleet half becoming tests/business/test_boats.py.

Test plan

  • python3 -m compileall -q src tests
  • SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy python3 -m pytest --verbose -vv --cov=src --cov-report=term-missing --cov-report=xml:cov.xml594 passed, 97% total. voyages.py 100%, player.py 100%, playerJsonReaderWriter.py 100%, boats.py 96%, docks.py 93% (remaining gaps are pre-existing fish() branches).
  • black + autoflake over the changed files only.
  • Front-end parity. Everything new goes through showOptions/showInteractiveDialogue/currentPrompt — no new primitive, so console, pygame and web all get it.
  • Played it through the real console front-end: built a three-boat fleet, moved crew between boats, read the raid odds off the job board, ran a successful raid (took $1,908 and 12 fish), and forced a disaster to check it reads right and actually removes the villager.
  • The docks-menu tests now drive menus by label rather than position (fleetChooser), so adding an option no longer breaks a dozen unrelated tests.

Balance note

A raid on the top target beats a hauling contract on the same hull by a wide margin, which is the point — but it's gated behind a tier-3 boat, a real crew, and a 16% chance of losing one of them plus a repair bill. Happy to tune the loot bands or the disaster share if it plays too hot.

One boat that could only fish becomes any number of boats, each dedicated
to fishing, hauling, piracy or transport.

- Add src/business/boats.py: the fleet, the four roles, and crew drawn
  from ONE shared roster. Wages are owed on every hand hired whether or
  not they have a berth, so an idle boat is a real cost, and only crew on
  a fishing boat bring in a catch
- Add src/business/voyages.py: the active job boards. Transport always
  pays and never touches the hull; hauling pays better but heavy seas can
  batter it; piracy pays far better and can cost a villager hired by name
  plus a hull too damaged to sail until it's paid to be fixed. Raids show
  their real odds before the player commits
- player.hasBoat/boatTier become read-only properties derived from the
  fleet, so the flag and the tier can no longer disagree
- Migrate pre-roles saves into a single fishing boat carrying the whole
  crew; nobody loses a boat or a hand by loading an old file
- Hauling boats carry half again as much on an export run
- Rebuild the docks fleet menu: buy, crew, re-dedicate, repair, upgrade,
  rename and sell per boat, plus "Send Out a Boat"
- Move production/crew/selling out of business.py, which is now just the
  tier catalogue, so boats.py can depend on it without a cycle

Fixed while testing: the save loader built the fleet before reading
businessName, so a migrated boat lost the name it should have inherited.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dmccoystephenson
dmccoystephenson merged commit 4f2075e into main Aug 1, 2026
1 check passed
@dmccoystephenson
dmccoystephenson deleted the feature/fleet-and-boat-roles branch August 1, 2026 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant