fix draft ui

This commit is contained in:
2026-04-10 15:49:51 -04:00
parent 30e3f88b21
commit 856f0049b7

View File

@@ -1,11 +1,11 @@
import "./styles.css"; import "./styles/globals.css";
import { import {
ROOT_SHIFT_COST, ROOT_SHIFT_COST,
ROUND_ANIMATION_BONUS_MS, ROUND_ANIMATION_BONUS_MS,
ROUND_ANIMATION_BRANCH_MS, ROUND_ANIMATION_BRANCH_MS,
ROUND_ANIMATION_SUN_MS, ROUND_ANIMATION_SUN_MS,
} from "./constants"; } from "./engine/constants";
import { import {
buildChildrenMap as buildChildrenMapForState, buildChildrenMap as buildChildrenMapForState,
buildParentMap as buildParentMapForState, buildParentMap as buildParentMapForState,
@@ -14,18 +14,18 @@ import {
getNodeOwner as getNodeOwnerForState, getNodeOwner as getNodeOwnerForState,
getRootShiftMove as getRootShiftMoveForState, getRootShiftMove as getRootShiftMoveForState,
playerHasLegalMove as playerHasLegalMoveForState, playerHasLegalMove as playerHasLegalMoveForState,
} from "./rules-board"; } from "./engine/rules-board";
import { import {
buildEnergySimulation, buildEnergySimulation,
buildRoundAnimation as buildRoundAnimationForState, buildRoundAnimation as buildRoundAnimationForState,
maybeRollDisease as maybeRollDiseaseForState, maybeRollDisease as maybeRollDiseaseForState,
maybeRollSunbeam as maybeRollSunbeamForState, maybeRollSunbeam as maybeRollSunbeamForState,
scoreColumns as scoreColumnsForState, scoreColumns as scoreColumnsForState,
} from "./rules-scoring"; } from "./engine/rules-scoring";
import { import {
createInitiativeDraft, createInitiativeDraft,
getInitiativeGraceRounds, getInitiativeGraceRounds,
} from "./rules-initiative"; } from "./engine/rules-initiative";
import { import {
WEATHER_OFFER_PAIRS, WEATHER_OFFER_PAIRS,
createWeatherDraft, createWeatherDraft,
@@ -33,7 +33,7 @@ import {
getWeatherCard, getWeatherCard,
isWeatherCardAvailable, isWeatherCardAvailable,
isWeatherOfferResolved, isWeatherOfferResolved,
} from "./rules-weather"; } from "./engine/rules-weather";
import { import {
createInitialState, createInitialState,
createPlayers, createPlayers,
@@ -41,7 +41,7 @@ import {
createSetupState, createSetupState,
getMaxStartingNodesPerPlayer, getMaxStartingNodesPerPlayer,
normalizeSeedInputs, normalizeSeedInputs,
} from "./state"; } from "./engine/state";
import type { import type {
GameState, GameState,
GrowTarget, GrowTarget,
@@ -52,8 +52,8 @@ import type {
ShiftMove, ShiftMove,
TurnMove, TurnMove,
WeatherCardId, WeatherCardId,
} from "./types"; } from "./engine/types";
import { keyFor, parseKey, tint, wait } from "./utils"; import { keyFor, parseKey, tint, wait } from "./engine/utils";
const app = document.querySelector("#app"); const app = document.querySelector("#app");
@@ -520,6 +520,9 @@ function chooseWeatherAction(offerId: string, cardId: WeatherCardId, action: "dr
return; return;
} }
const offer = draft.offers.find((entry) => entry.id === offerId);
const otherCardId = offer?.options.find((option) => option !== cardId) ?? null;
const playerId = getCurrentWeatherPlayerId(draft); const playerId = getCurrentWeatherPlayerId(draft);
if (action === "draft") { if (action === "draft") {
const card = getWeatherCard(cardId); const card = getWeatherCard(cardId);
@@ -531,6 +534,10 @@ function chooseWeatherAction(offerId: string, cardId: WeatherCardId, action: "dr
state.history.unshift(`${state.players[playerId].name} banned ${card?.title ?? cardId}.`); state.history.unshift(`${state.players[playerId].name} banned ${card?.title ?? cardId}.`);
} }
if (otherCardId && !draft.locked.includes(otherCardId)) {
draft.locked.push(otherCardId);
}
if (draft.draftIndex >= draft.playerOrder.length - 1) { if (draft.draftIndex >= draft.playerOrder.length - 1) {
finalizeWeatherDraft(); finalizeWeatherDraft();
render(); render();
@@ -1077,7 +1084,7 @@ function renderWeatherDraftModal() {
</div> </div>
</div> </div>
<div class="seed-editor"> <div class="seed-editor">
<p class="seed-help">${currentPlayer?.name ?? "A player"} can draft or ban either card in each offer.</p> <p class="seed-help">${currentPlayer?.name ?? "A player"} can draft or ban 1 card. Offered in pairs.</p>
<div class="weather-key" aria-label="Weather action key"> <div class="weather-key" aria-label="Weather action key">
<span><strong>☀ Draft</strong>: take that card for 1 round</span> <span><strong>☀ Draft</strong>: take that card for 1 round</span>
<span><strong>✕ Ban</strong>: remove just that card</span> <span><strong>✕ Ban</strong>: remove just that card</span>
@@ -1094,13 +1101,14 @@ function renderWeatherDraftModal() {
<div> <div>
<p class="eyebrow">Offer</p> <p class="eyebrow">Offer</p>
<div class="weather-pair"> <div class="weather-pair">
${offer.options.map((cardId) => { ${offer.options.map((cardId, optionIndex) => {
const card = getWeatherCard(cardId); const card = getWeatherCard(cardId);
const drafted = draft.drafted.includes(cardId); const drafted = draft.drafted.includes(cardId);
const banned = draft.banned.includes(cardId); const banned = draft.banned.includes(cardId);
const locked = draft.locked.includes(cardId);
const available = isWeatherCardAvailable(draft, offer.id, cardId); const available = isWeatherCardAvailable(draft, offer.id, cardId);
return ` return `${optionIndex === 1 ? `<div class="weather-pair__divider">-- OR --</div>` : ""}
<div class="weather-pair__option${drafted ? " weather-pair__option--drafted" : ""}${banned ? " weather-pair__option--banned" : ""}"> <div class="weather-pair__option${drafted ? " weather-pair__option--drafted" : ""}${banned ? " weather-pair__option--banned" : ""}${locked ? " weather-pair__option--locked" : ""}">
<h2>${card?.title ?? cardId}</h2> <h2>${card?.title ?? cardId}</h2>
<p>${card?.description ?? ""}</p> <p>${card?.description ?? ""}</p>
${available ? ` ${available ? `
@@ -1114,7 +1122,7 @@ function renderWeatherDraftModal() {
<span><strong>Ban</strong></span> <span><strong>Ban</strong></span>
</button> </button>
</div> </div>
` : `<p class="weather-card__status">${drafted ? "Drafted" : "Banned"}</p>`} ` : `<p class="weather-card__status">${drafted ? "Drafted" : banned ? "Banned" : "Locked"}</p>`}
</div> </div>
`; `;
}).join("")} }).join("")}
@@ -1396,7 +1404,6 @@ function renderSidebar() {
return ` return `
<aside class="sidebar"> <aside class="sidebar">
<button class="ghost-button new-game-launch" id="new-game">New Game</button>
<section class="panel status-panel status-panel--weather"> <section class="panel status-panel status-panel--weather">
<h2>In Effect</h2> <h2>In Effect</h2>
${activeEffectsMarkup} ${activeEffectsMarkup}
@@ -1455,7 +1462,10 @@ function renderSidebar() {
</section> </section>
<section class="panel finish-panel"> <section class="panel finish-panel">
<button id="finish-game" class="ghost-button finish-game-button" ${boardLocked ? "disabled" : ""}>End Game / Score Now</button> <div class="button-row finish-panel__actions">
<button id="new-game" class="ghost-button finish-game-button">New Game</button>
<button id="finish-game" class="ghost-button finish-game-button" ${boardLocked ? "disabled" : ""}>End Game / Score Now</button>
</div>
</section> </section>
</aside> </aside>
`; `;