Play now against the bot opens a room the server keeps
Every duel then leaves a ledger and shows in the visitors digest; the offline duel in the browser remains as a fallback. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0141G6xqLeNRYEtviLWSB5Up
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
098dadf482
commit
885dcf56e6
@@ -32,6 +32,20 @@
|
||||
});
|
||||
|
||||
async function playBot() {
|
||||
busy = true;
|
||||
error = '';
|
||||
try {
|
||||
rememberName(name);
|
||||
const remote = await Duel.createBotRoom(name.trim());
|
||||
await goto(`/join/${remote.roomId}`);
|
||||
} catch (e) {
|
||||
error = e instanceof Error ? e.message : 'The duel could not be opened.';
|
||||
} finally {
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function playOffline() {
|
||||
rememberName(name);
|
||||
await goto('/play');
|
||||
}
|
||||
@@ -66,7 +80,7 @@
|
||||
const g = games[held.roomId];
|
||||
if (g === undefined) return 'looking';
|
||||
if (g === null) return 'unreachable';
|
||||
const others = g.seats.filter((s) => s.id !== held.seat).map((s) => s.name);
|
||||
const others = g.seats.filter((s) => s.id !== held.seat).map((s) => (s.bot ? `${s.name} (the bot)` : s.name));
|
||||
if (!g.state) return `waiting to start${g.seats.length ? ` · ${g.seats.map((s) => s.name).join(', ')}` : ''}`;
|
||||
if (g.state.over) {
|
||||
if (g.state.over.winner === held.seat) return 'you won';
|
||||
@@ -105,12 +119,14 @@
|
||||
<span>Your wizard's name</span>
|
||||
<input type="text" bind:value={name} maxlength={NAME_MAX} placeholder="e.g. Morwenna" autocomplete="nickname" />
|
||||
</label>
|
||||
<button type="button" class="reveal primary" disabled={!ready} onclick={playBot}>
|
||||
{local ? `Continue against ${local.foe.name} (turn ${local.turnNumber})` : 'Play now against the bot'}
|
||||
</button>
|
||||
{#if local}
|
||||
<p class="muted small">Or start afresh from the board's "New duel".</p>
|
||||
{/if}
|
||||
<button type="button" class="reveal primary" disabled={!ready || busy} onclick={playBot}>Play now against the bot</button>
|
||||
<p class="muted small">
|
||||
{#if local}
|
||||
<button type="button" class="link" onclick={playOffline}>Continue your offline duel against {local.foe.name} (turn {local.turnNumber})</button>
|
||||
{:else}
|
||||
<button type="button" class="link" onclick={playOffline}>Or play offline, in this browser only</button>
|
||||
{/if}
|
||||
</p>
|
||||
<div class="ways">
|
||||
<button type="button" class="quiet" disabled={!ready || busy} onclick={create}>Create a duel</button>
|
||||
<form class="joinform" onsubmit={join}>
|
||||
@@ -149,8 +165,8 @@
|
||||
{#if local}
|
||||
<div class="ledger-row your-move">
|
||||
<a class="ledger-resume" href="/play">
|
||||
<span class="ledger-code">bot</span>
|
||||
<span class="ledger-info">your move · turn {local.turnNumber} · against {local.foe.name}</span>
|
||||
<span class="ledger-code">here</span>
|
||||
<span class="ledger-info">offline · your move · turn {local.turnNumber} · against {local.foe.name}</span>
|
||||
</a>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -794,6 +794,13 @@ export class Duel {
|
||||
return remoteFrom(seated.view, seated.token);
|
||||
}
|
||||
|
||||
/** A room with the bot already seated: a duel the server keeps, so it can be replayed and seen. */
|
||||
static async createBotRoom(name: string): Promise<Remote> {
|
||||
const seated = await api.create(name, 2);
|
||||
rememberSeat(seated.view.roomId, { seat: seated.seat, token: seated.token });
|
||||
return remoteFrom(await api.addBot(seated.view.roomId, seated.token), seated.token);
|
||||
}
|
||||
|
||||
static async joinRoom(roomId: string, name: string): Promise<Remote> {
|
||||
const seated = await api.join(roomId, name);
|
||||
rememberSeat(roomId, { seat: seated.seat, token: seated.token });
|
||||
|
||||
Reference in New Issue
Block a user