Move the round strip out from under the opponent hand; let undo cross turns
Two fixes to the last change: - The round strip sat top-center, exactly where the opponent's hand is, so its cards covered it. Moved it under the rival plaque on the left, clear of the hand. - Undo/redo was capped at the current turn. When the setting is on it now walks the whole timeline -- back through committed moves, the rival's replies, and earlier rounds. The rival stays suspended whenever there are moves ahead to redo, so reviewing never makes it replay the move being looked at. Menu label updated to "전체 되감기". Verified in a browser: the strip no longer overlaps the opponent hand, and undo from mid-game walks back eight steps across a rival turn to the opening. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XBQKgvBbxbheiTF1AVy1Sh
This commit is contained in:
+8
-14
@@ -42,8 +42,8 @@ function loadMode(): Mode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Off by default: taking moves back is a training aid, not how the game is played,
|
// Off by default: taking moves back is a training aid, not how the game is played,
|
||||||
// and the default should be the honest game. When on, it is limited to the current
|
// and the default should be the honest game. When on, undo/redo walk the whole
|
||||||
// turn (see turnFloor) -- you can revise a misclick, not rewind the rival.
|
// timeline -- across the rival's moves and earlier rounds, not just your turn.
|
||||||
const UNDO_KEY = "lost-cities.undo";
|
const UNDO_KEY = "lost-cities.undo";
|
||||||
|
|
||||||
function loadUndoEnabled(): boolean {
|
function loadUndoEnabled(): boolean {
|
||||||
@@ -154,17 +154,11 @@ function App() {
|
|||||||
const { state: match, selection } = frames[cursor];
|
const { state: match, selection } = frames[cursor];
|
||||||
// The board on screen is the round in play; the match is what decides the game.
|
// The board on screen is the round in play; the match is what decides the game.
|
||||||
const state = match.round;
|
const state = match.round;
|
||||||
// The start of the current turn: the most recent committed move at or before the
|
// When enabled, undo/redo walk the whole timeline -- back through your committed
|
||||||
// cursor (a rival move, or your own draw). Undo cannot cross it, so you can take
|
// moves, the rival's replies, and earlier rounds, not just the current turn. The
|
||||||
// back a card selection or placement within your turn but never rewind into the
|
// rival is held whenever there are moves ahead to redo, so stepping back never
|
||||||
// rival's move or an earlier turn.
|
// makes it replay the move you are reviewing.
|
||||||
const turnFloor = useMemo(() => {
|
const canUndo = undoEnabled && cursor > 0;
|
||||||
for (let index = cursor; index > 0; index -= 1) {
|
|
||||||
if (frames[index].move) return index;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}, [frames, cursor]);
|
|
||||||
const canUndo = undoEnabled && cursor > turnFloor;
|
|
||||||
const canRedo = undoEnabled && cursor < frames.length - 1;
|
const canRedo = undoEnabled && cursor < frames.length - 1;
|
||||||
const latestMatch = useRef(match);
|
const latestMatch = useRef(match);
|
||||||
|
|
||||||
@@ -503,7 +497,7 @@ function App() {
|
|||||||
checked={undoEnabled}
|
checked={undoEnabled}
|
||||||
onChange={(event) => setUndoEnabled(event.target.checked)}
|
onChange={(event) => setUndoEnabled(event.target.checked)}
|
||||||
/>
|
/>
|
||||||
<span>되돌리기 / 다시 · 내 턴 안에서만</span>
|
<span>되돌리기 / 다시 · 전체 되감기</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
+6
-5
@@ -692,22 +692,23 @@ button.card:disabled { cursor: default; }
|
|||||||
/* Match mode: which round is live, and what is already banked. The board only
|
/* Match mode: which round is live, and what is already banked. The board only
|
||||||
ever shows the round in play, so without this the score plaques would be the
|
ever shows the round in play, so without this the score plaques would be the
|
||||||
only hint that two more rounds are coming. */
|
only hint that two more rounds are coming. */
|
||||||
|
/* Tucked under the rival plaque on the left, clear of the opponent hand which
|
||||||
|
sits centered along the top and would otherwise cover it. */
|
||||||
.round-strip {
|
.round-strip {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 16px;
|
top: 88px;
|
||||||
left: 50%;
|
left: 24px;
|
||||||
transform: translateX(-50%);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
padding: 6px 12px;
|
padding: 6px 14px;
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
background: rgba(18, 14, 10, 0.72);
|
background: rgba(18, 14, 10, 0.72);
|
||||||
border: 1px solid rgba(214, 188, 140, 0.22);
|
border: 1px solid rgba(214, 188, 140, 0.22);
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
letter-spacing: 0.12em;
|
letter-spacing: 0.12em;
|
||||||
color: rgba(214, 188, 140, 0.55);
|
color: rgba(214, 188, 140, 0.55);
|
||||||
z-index: 4;
|
z-index: 9;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user