diff --git a/client/src/Activities.tsx b/client/src/Activities.tsx index af1834f..e155d9a 100644 --- a/client/src/Activities.tsx +++ b/client/src/Activities.tsx @@ -246,7 +246,13 @@ const Activities: React.FC = () => { {placement && (
- {who} must place a {placeRoad ? "road" : "settlement"}. + {who} must place { + (turn && (turn as any).active === "road-building" && (turn as any).freeRoads) + ? `${(turn as any).freeRoads} roads` + : placeRoad + ? "a road" + : "a settlement" + }.
)} diff --git a/server/routes/games.ts b/server/routes/games.ts index a02caac..39b5f72 100755 --- a/server/routes/games.ts +++ b/server/routes/games.ts @@ -2839,14 +2839,43 @@ const placeRoad = (game: Game, session: Session, index: number): string | undefi road.color = session.color; road.type = "road"; player.roads--; + /* Handle normal play road placement including Road Building free roads. + * If the turn is a road-building action, decrement freeRoads and + * only clear actions when no free roads remain. Otherwise, during + * initial placement we advance the initial-placement sequence. */ + if (game.state === "normal") { + addActivity(game, session, `${session.name} placed a road.`); + calculateRoadLengths(game, session); - /* During initial placement, placing a road advances the initial-placement - * sequence. In forward direction we move to the next player; when the - * last player places their road we flip to backward and begin the reverse - * settlement placements. In backward direction we move to the previous - * player and when the first player finishes, initial placement is done - * and normal play begins. */ - if (game.state === "initial-placement") { + let resetLimits = true; + if (game.turn && (game.turn as any).active === "road-building") { + if ((game.turn as any).freeRoads !== undefined) { + (game.turn as any).freeRoads = (game.turn as any).freeRoads - 1; + } + if ((game.turn as any).freeRoads === 0) { + delete (game.turn as any).free; + delete (game.turn as any).active; + delete (game.turn as any).freeRoads; + } + + const roads = getValidRoads(game, session.color as string); + if (!roads || roads.length === 0) { + delete (game.turn as any).active; + delete (game.turn as any).freeRoads; + addActivity(game, session, `${session.name} has another road to play, but there are no more valid locations.`); + } else if ((game.turn as any).freeRoads !== 0) { + (game.turn as any).free = true; + setForRoadPlacement(game, roads); + resetLimits = false; + } + } + + if (resetLimits) { + delete (game.turn as any).free; + game.turn.actions = []; + game.turn.limits = {}; + } + } else if (game.state === "initial-placement") { const order: PlayerColor[] = game.playerOrder; const idx = order.indexOf(session.color); // defensive: if player not found, just clear actions and continue