Hnefatafl

The Viking board game. One king, one throne, four corners, and a ring of attackers closing in.

Hnefatafl was played across the Norse world for a thousand years before chess. Every piece moves like a rook and is taken by being sandwiched; the attackers must capture the king, the king must reach safety. Play a housecarl, or open a table for a friend and play by turns. Copenhagen rules on the big board, or Tablut, the older game Linnaeus wrote down in 1732.

{#if game.options?.length}
{#each game.options as o (o.key)} {@const chosen = o.choices.find((c) => c.value === options[o.key])}
{#if chosen?.note}

{chosen.note}

{/if}
{/each}
{/if}
or join one

A code opens the door either way: take a seat if one is free, or watch from the Peanut Gallery.

or bring a seat from another device
{#if error}

{error}

{/if}
{#if seats.length}
your games
{#each seats as held (held.roomId)} {/each} {#if reports.length}
your reports to the keeper
{#each reports as r (r.id)} {@const last = r.thread[r.thread.length - 1]}
{r.roomId}

“{r.happened}”{#if r.image} (with a picture){/if}

{#each r.thread as line, j (j)} {#if line.from === 'player'}

you: {line.text}

{:else}

{line.status} {line.text}

{/if} {/each} {#if !last}

the keeper is studying the moment

{:else if last.from === 'player'}

your word is with the keeper

{/if} {#if r.thread.some((l) => l.from === 'desk')}
{ e.preventDefault(); void answer(r); }}>
{/if}
{/each} {#if answerError}

{answerError}

{/if} {/if}
{/if}
about this game

Hnefatafl is the tafl game of the Vikings, carried by them from Scandinavia to Britain, Ireland, Iceland and beyond, and played until chess arrived in the eleventh and twelfth centuries. No rules from that age survive; the game was reconstructed in modern times from a Sámi cousin, Tablut, whose rules the botanist Carl Linnaeus jotted down on his journey through Lapland in 1732.

This table plays Copenhagen, the modern tournament ruleset, on the eleven-by-eleven board, and Tablut on the nine-by-nine one, with the older board showing its age. The rules it follows are on the rules page. The game is in the public domain; the board and pieces here are drawn, not borrowed.

It is free and keeps no accounts. A game between people lives on a small server as an append-only ledger of moves, so it can be replayed from its first move, and each player is shown only what the rules let them see.

Send word

A rule read wrong, a bug, a game you would like to tell of: write to eric@ericwagoner.com, @kestrelsnest.social on Bluesky, or @eric@toots.kestrelsnest.social on Mastodon. The keeper of this hall roosts at kestrelsnest.social.

{#if tally}

The tally

{tally.gamesFinished}
{tally.gamesFinished === 1 ? 'game' : 'games'} played to a finish, of {tally.gamesBegun} begun at {tally.tablesOpened} {tally.tablesOpened === 1 ? 'table' : 'tables'}
{tally.namesSeated}
{tally.namesSeated === 1 ? 'name has' : 'names have'} taken a seat
{tally.turnsPlayed}
turns recorded; {tally.longestGameTurns} in the longest game
{hours(tally.minutesAtTable)}
at the table, by the clock between moves
{tally.gamesWithBot}
{tally.gamesWithBot === 1 ? 'game' : 'games'} with a housecarl seated; {tally.talkLines} {tally.talkLines === 1 ? 'line' : 'lines'} of table talk
{#each Object.entries(tally.byGame) as [label, n] (label)}
{n}
{label}
{/each}

{#if tally.firstGameAt}The first game began {new Date(tally.firstGameAt).toLocaleDateString(undefined, { year: 'numeric', month: 'long', day: 'numeric' })}.{/if} Names are counted, not people: one player under two names is two here. Table time counts only the minutes between moves, so a game left open overnight adds nothing for the night.

{/if} {#if family.length}

More games at the Kestrel's Nest

    {#each family as g (g.slug)}
  • {g.name}: {g.pitch} {g.players} players; {g.origin}.
  • {/each}
{/if}

Hnefatafl belongs to everyone; it is a thousand years old. This page was made by Eric and a very enthusiastic AI, 2026.