Wiz-War
sixth edition
{#if local.active}
hotseat
local.leave()}>set the game aside
local.abandon()}>abandon game
{:else if net.roomId}
room
{net.roomId}
net.requestTransferCode()}>transfer seat
net.leave()}>leave table
{/if}
(showHelp = true)}> help & rules
{net.status === "connected" ? "" : "reconnecting…"}
{#if showHelp}
(showHelp = false)} /> {/if} {#if net.error}
{net.error}
{/if} {#if net.transferCode}
Speak this phrase into your other device (good for 10 minutes, one use):
{net.transferCode.code}
(net.transferCode = null)}>dismiss
{/if} {#if local.handoffTo}
local.takeSeat()} onkeydown={(e) => e.key === "Enter" && local.takeSeat()}>
pass the device to
{local.handoffTo}
tap when only they can see the screen
{/if} {#if !net.roomId && !local.active}
Wiz-War
A game of magical combat in a stone labyrinth
Your wizard's name
net.create(name)}> Create a game
or join one
net.join(joinCode, name)}> Join
n.trim()).length < 2} onclick={() => { const err = local.start(hotseatNames.split(","), withExpansion); if (err) net.error = err; }}> Play here
{#if local.hasSave()}
local.resume()}>Resume hotseat
{/if}
with Expansion Set #1
{ net.claimTransfer(claimPhrase); claimPhrase = ""; }}> Claim a transferred seat
{#if net.seats.length > 0}
your games
{#if !net.notificationsEnabled}
net.enableNotifications()}> notify me on my turn
{/if}
{#each net.seats as seat (seat.roomId + seat.name)} {@const g = net.games.find((x) => x.roomId === seat.roomId && x.name === seat.name)}
net.resume(seat)}>
{seat.roomId}
{#if !g} as {seat.name} — unreachable {:else if g.finished} {g.winner === seat.name ? "you won! 🏆" : `${g.winner} won`} {:else if !g.started} waiting to start · {g.players.join(", ")} {:else if g.yourTurn} YOUR TURN · round {g.round} · {timeAgo(g.lastMoveAt)} {:else} {g.activePlayerId}'s turn · round {g.round} · {timeAgo(g.lastMoveAt)} {/if}
net.forgetSeat(seat.roomId)}>×
{/each}
{/if}
{:else if !local.active && !net.started}
Room {net.roomId}
Share the code. Two to six wizards enter the maze.
{#each net.players as p (p)}
{p}{p === net.hostId ? " — host" : ""}
{/each}
{#if net.you === net.hostId}
Include Expansion Set #1 — monsters & wands
6} onclick={() => net.start(withExpansion)} > Flip the boards ({net.players.length} wizard{net.players.length === 1 ? "" : "s"})
{:else}
Waiting for {net.hostId} to flip the boards…
{/if}
{:else if view}
{#if selectedDef || youMustDiscard || discardMode || discardSelection.size > 0}
{#if youMustDiscard}
Hand over the limit — mark cards and discard.
{:else if discardMode && discardSelection.size === 0}
Mark the cards to throw away, then confirm.
{/if} {#if discardSelection.size > 0}
Discard {discardSelection.size} marked
{/if} {#if discardMode || (discardSelection.size > 0 && !youMustDiscard)}
never mind
{/if} {#if selectedDef}
{selectedDef.name}
{#if edgeSelectMode}
— click a wall line
{/if} {#if selectedDef.cardType === "attack" && !edgeSelectMode && !cellSelectMode}
— click a target{attachedNumber ? ` (powered by a ${numberTotal})` : " (tap a number card to power it)"}
{/if} {#if attachedMods.length > 0}
[+ {attachedMods.map((m) => cardDef(m.cardId).name).join(", ")}]
{/if} {#if selectedCard?.cardId === "boobytrap"}
— place 4 tokens ({trapCells.length}/4; the first is real)
{/if} {#if selectedCard && TWO_CELL_CARDS.has(selectedCard.cardId)}
{tradeFrom ? "— now the second square" : "— click the first square"}
{/if} {#if selectedCard?.cardId === "rotate-sector"}
clockwise
— click the sector
{/if} {#if selectedCard?.cardId === "relocate-sector"}
{pendingSectorFrom ? "— now the destination area" : "— click the sector to move"}
{/if} {#if selectedCard && NAMED_CARDS.has(selectedCard.cardId)}
name
{#if selectedCard.cardId === "deja-vu"}
{ const id = nameToCardId(nameInput); if (id && selectedCard) { dispatch({ type: "cast", instanceId: selectedCard.instanceId, params: { cardId: id } }); clearSelection(); } }}>Retrieve
{:else}
— then click the target
{/if} {/if} {#if selectedCard?.cardId === "waterbolt"}
damage
(knockback {numberTotal - wbDamage})
{/if} {#if selectedCard?.cardId === "power-run"}
life to trade
Run!
{/if} {#if selectedCard && CONFIRM_CAST.has(selectedCard.cardId)}
Cast{attachedNumber ? ` with the ${numberTotal}` : ""}
{/if} {#if selectedCard && isNumberCard(selectedCard.cardId)}
Play for +{cardDef(selectedCard.cardId).value} movement{view.turn.numberPlayedForMovement ? " (uses your Add)" : ""}
{/if}
cancel
{/if}
{/if}
{#if isYourTurn && onWarpToken}
dispatch({ type: "warpStep" })}>Step through the warp
{/if} {#if isYourTurn}
Pick up treasure
Drop treasure
Discard cards…
draw
0
1
2
End turn
{/if}
{#if selectedCard && !inspectorHidden}
(inspectorHidden = true)} aria-label="hide enlarged card">×
{/if}
{#each view.yourHand as card (card.instanceId)}
m.instanceId === card.instanceId)} marked={discardSelection.has(card.instanceId)} displayed={view.players.find((p) => p.id === view.you)?.displayed.some((c) => c.instanceId === card.instanceId) ?? false} charges={view.wandCharges[card.instanceId] ?? null} onclick={() => selectCard(card)} /> {/each}
{/if}