feat: implement Phase 1b — Bi-Planetary game engine#5
Merged
Conversation
- movement.ts: pure helpers (getValidDestinations, resolveMovement, checkLanding) + 33-test suite covering coasting, thrust, gravity, win detection, and multi-turn integration - types/game.ts: expand Ship (maxFuel, cs, pendingGravity), add PlotEntry, flesh out TriplanetaryState (plots, turnNumber, winner, mapSnapshot, scenarioId) - TriplanetaryGame.ts: astrogation phase with simultaneous plotCourse / lockIn moves; onEnd calls resolveMovement; endIf detects winner - shared/index.ts: export movement lib - LobbyPage.tsx: fetch canonical map, create match with setupData, join endpoint, store playerID+credentials in sessionStorage - HexGrid.tsx: add overlays?: ReactNode prop for ship/vector overlays - GameRoom.tsx: wire boardgame.io/react Client with SocketIO transport - Board.tsx: game board with ship counters, vector arrows, valid-dest highlights, plot lines, and hex-click course-plotting flow - HUD.tsx: turn/fuel/phase display, Lock In button, win/loss banner - vite.config.ts: optimizeDeps for boardgame.io CJS modules https://claude.ai/code/session_01DeLbhCjrgM6A71jTPZCrsn
Contributor
There was a problem hiding this comment.
Pull request overview
Implements “Phase 1b” of the Bi-Planetary Triplanetary engine by adding shared movement resolution + win detection, integrating those rules into a boardgame.io game phase, and wiring a playable client UI (lobby → join/create → game room → board/HUD rendering).
Changes:
- Expanded shared game state/types and introduced movement helpers (
getValidDestinations,resolveMovement,checkLanding) with a dedicated test suite. - Implemented an astrogation phase in
TriplanetaryGame(simultaneous plotting + lock-in) and exported the new movement library from shared. - Built client flow for match creation/joining + session credential storage, and added board/HUD rendering with hex overlays.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/shared/src/types/game.ts | Extends Ship and TriplanetaryState to support plotting, turn tracking, winner state, and map snapshots. |
| packages/shared/src/lib/movement.ts | Adds core movement/landing resolution logic for Bi-Planetary. |
| packages/shared/src/lib/tests/movement.test.ts | Adds Vitest coverage for movement rules, gravity, and win/draw detection. |
| packages/shared/src/index.ts | Re-exports movement library from shared package entrypoint. |
| packages/shared/src/game/TriplanetaryGame.ts | Adds boardgame.io phase + moves for simultaneous plotting/locking and movement resolution. |
| packages/client/vite.config.ts | Adds optimizeDeps includes to improve boardgame.io module handling in Vite. |
| packages/client/src/pages/lobby/LobbyPage.tsx | Fetches canonical map, creates + joins matches, stores credentials, and joins existing matches. |
| packages/client/src/pages/lobby/GameRoom.tsx | Wires boardgame.io React client with SocketIO transport using stored seat credentials. |
| packages/client/src/pages/game/HUD.tsx | Adds a HUD with turn/phase/fuel display and lock-in/win/loss UI. |
| packages/client/src/pages/game/Board.tsx | Renders the hex board with overlays (ships, vectors, valid destinations, plot lines) and click-to-plot interaction. |
| packages/client/src/components/map/HexGrid.tsx | Adds overlays prop to render SVG overlays above the hex layer. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+85
to
+88
| players: Array<{ id: number; name?: string }>; | ||
| }; | ||
|
|
||
| const freeSeat = matchData.players.find((p) => !p.name); |
Comment on lines
+47
to
+55
| const ProtoHex = defineHex({ | ||
| dimensions: hexSize, | ||
| orientation: Orientation.POINTY, | ||
| origin: 'topLeft', | ||
| }); | ||
| const grid = new Grid( | ||
| ProtoHex, | ||
| rectangle({ width: qMax - qMin + 1, height: rMax - rMin + 1, start: { q: qMin, r: rMin } }), | ||
| ); |
Comment on lines
+47
to
+61
| plotCourse: ({ G, ctx }, destination: [number, number]) => { | ||
| const ship = G.ships[Number(ctx.currentPlayer)]; | ||
| if (!ship) return INVALID_MOVE; | ||
| const valid = getValidDestinations(ship, G.mapSnapshot?.hexes ?? {}); | ||
| if (!valid.has(`${destination[0]},${destination[1]}`)) return INVALID_MOVE; | ||
| G.plots[ctx.currentPlayer] = { destination, locked: false }; | ||
| }, | ||
|
|
||
| lockIn: ({ G, ctx, events }) => { | ||
| const plot = G.plots[ctx.currentPlayer]; | ||
| if (!plot) return INVALID_MOVE; | ||
| plot.locked = true; | ||
| const allLocked = Object.keys(ctx.activePlayers ?? {}) | ||
| .every(pid => G.plots[pid]?.locked === true); | ||
| if (allLocked) events.endPhase(); |
Comment on lines
+122
to
+139
| // Step 2 — cost: coast (no thrust) is free; any other destination costs 1 fuel | ||
| const coastQ = ship.position[0] + ship.vector[0]; | ||
| const coastR = ship.position[1] + ship.vector[1]; | ||
| const [destQ, destR] = plot.destination; | ||
| const isCoasting = destQ === coastQ && destR === coastR; | ||
| const fuelCost = isCoasting ? 0 : 1; | ||
|
|
||
| // Step 3 — new velocity = destination − current position | ||
| ship.vector[0] = destQ - ship.position[0]; | ||
| ship.vector[1] = destR - ship.position[1]; | ||
|
|
||
| // Step 4 — move | ||
| ship.position[0] = destQ; | ||
| ship.position[1] = destR; | ||
|
|
||
| // Step 5 — consume fuel | ||
| ship.fuel = Math.max(0, ship.fuel - fuelCost); | ||
|
|
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.
https://claude.ai/code/session_01DeLbhCjrgM6A71jTPZCrsn