Skip to the content

Tsunagi繋ぎ

Join each pair with a separate line and fill the board, through fixed levels or seeded puzzles.

Tsunagi means joining in Japanese. About the name

Contents

Reference

Rules, solvers and generation

import { … } from "@johnmorrisdotca/tsunagi";

22.4 kB minified and gzipped, with everything it imports (measured with esbuild)

Tsunagi: join each pair of marbles with a line, every line its own, filling the board. The layouts and answers as codes, the rules a line must keep, a solver that counts answers, a generator, the twists (walls, bridges, waypoints, hexagons), the difficulty measure, and the level ladder. The levels themselves are data, imported a size at a time (@johnmorrisdotca/tsunagi/levels-7) or all through @johnmorrisdotca/tsunagi/levels.

Exports

NameKindWhat it is
allJoinedfunctionSolved: every pair joined, every open cell on a line, and every bridge gone over both ways.
answerOffunctionThe answer the lines make, in the answer's spelling (encodeAnswer).
blockOffunctionThe block a level is in, from 1.
blockRangefunctionA block's first and last level, the last no further than the size has.
blocksInfunctionHow many blocks a size of count levels has.
bridgeAndWallCandidatefunctionA board with bridges and the walls it needs besides: both twists at once, for the blocks after both are taught.
bridgeCandidatefunctionA board with want bridges, or null where this filling offers no place for them or the board has more than one answer.
bridgesOffunctionThe bridges of a board.
candidatefunctionOne candidate level, or null: a filling, its layout, and the solver's proof that the layout has exactly one answer — the filling's own.
CAPITAL_PAIRSconstantHow many of PAIR_LETTERS are not small letters: a board that uses all of them has small letters for stones.
CELL_BLOCKEDconstantThe decoded blocked-cell sentinel.
CELL_BRIDGEconstantThe decoded bridge-cell sentinel.
CELL_EMPTYconstantA cell in a decoded layout: an empty cell, a blocked one, or a stone of pair n (0 for A).
ChallengetypeA challenge a board can have.
CHALLENGESconstantWHAT A TSUNAGI LEVEL ASKS OF A PLAYER, read from its board: the challenges on it, where it sits in its block's lesson, and how hard it measured.
challengesOffunctionThe challenges on a board, in the order the ladder teaches them.
cheatGamefunctionCheat: one unfinished line drawn as the answer has it, anything in its way cut back.
cheatLinefunctionCHEAT: one unfinished line drawn for the player, correctly.
checkGamefunctionCheck: the pairs not joined yet are flagged, and how many cells are still empty is said.
checkTsunagiAnswerfunctionValidate that an answer fills this board with legal, separate lines connecting every pair.
compareEdgesfunctionEdges in the one order a layout writes them: by their first cell, then their second.
countSolutionsfunctionCount valid complete answers up to a limit within a bounded search budget.
countSolutionsOfLevelfunctionHow a level is proved and measured: countSolutions for a board the search of this file has always counted (4×4 to 15×15, no portals), and for a bigger one, or one with portals, the SAT search started from the level's own answer (countSolutionsSat, binary pairs).
countSolutionsSatfunctionCounts a layout's answers by SAT, up to limit.
dailyTsunagiLevelfunctionThe level of the day at a size: a whole number from 1 to that size's count of levels, or null for a size there are no levels of.
decodeLayoutfunctionA layout read from its code, or null for a string that is not one: the wrong length, a stray character, a letter used other than twice, or letters not named in reading order.
decodeLinesfunctionLines read back from a progress code against the layout they were drawn on, or null for a code that does not describe lines on it: a start that is not a stone, a step from nowhere, a line through another pair's stone, a cell two lines claim.
DIFFICULTY_WEIGHTSconstantThe weights of the four measures in the score.
difficultyScoresfunctionEach level's score, 0 (easiest) to 100 (hardest), as the blend of its four percentiles among measures — one size's levels.
dragFingerfunctionA finger over finger, drawing the line of pair, with the reach it had: the lines after it and the reach now.
dragGamefunctionThe finger carried into a cell: the line grows, shortens or cuts another back, as the rules say.
dragThroughfunctionA drag that jumped several cells between two pointer events (a quick flick): walked one cell at a time along the row, then the column, so a fast finger draws what a slow one would.
dragTofunctionA drag of the pair being drawn into cell: one step, as the finger enters a cell.
edgeKeyfunctionAn edge between two neighbouring cells, the same whichever way round they are named.
edgeModelfunctionA layout written down as clauses (see the top of this file), or null where it cannot be solved at all: a stone its pair does not name, or a cell with too few ways in and out to hold a line.
EdgeModeltypeThe clauses a layout comes to, ready to be searched.
edgeOpenfunctionWhether a line may step from cell a to its neighbour b: no wall between them.
encodeAnswerfunctionA finished grid's code: the letter of the line through each cell, # where blocked, + on a bridge.
encodeLayoutfunctionA layout's code, from its cells, walls, waypoints and whether it wraps: the inverse of decodeLayout.
encodeLinesfunctionEncode current lines as native resumable progress for this layout.
encodePortalsfunctionThe portals as a layout writes them, after wrap: each pair as its smaller cell and its larger, the pairs in order; nothing where there are none.
encodeWallsfunctionThe walls as a layout writes them, after the cells: nothing where there are none.
ExplosiontypeEXPLOSIONS: every so many strokes, a drawn line is broken.
explosionAfterfunctionWhat the stroke-th stroke sets off, from the lines as it left them; null when it sets nothing off: a board without explosions, a stroke between them, or no line drawn to break.
explosionsAsChosenfunctionA level's explosions as the player chose to play them at set-up: as made, SOFTENED — a boom in place of a blast, and half as often — or OFF.
filledfunctionHow many open cells have a line through them or a stone on them, and how many there are: a bridge counts twice, once each way over it.
FillingStyletypeHow a filling is laid, where it need not be the way it always was: how often a line takes its tightest way on, and whether it may start beside the tightest cell as well as on it.
firstUnsolvedTsunagiLevelfunctionThe lowest level not yet solved, or null when every level of the size is.
forcedSharefunctionThe share of a layout's empty cells filled by forced moves alone: each line's two ends are grown while one of them has exactly one empty neighbour to go to, until a pair's ends meet or no end has only one way on.
gameOverfunctionWhether the game takes no more strokes: solved, or out of strokes.
helpOffunctionThe help a game has used so far, the one that costs more where it used two; null for none.
helpOpensNextfunctionWhether a solve with this help (or none) opens what a solve opens: every help but explosions off, whose block's lesson was not played.
hexCandidatefunctionA HEXAGON: the board as Hexversi's honeycomb, the square's corners off the board, filled with lines that may step along either slant as well as the four ways a square allows (hexNeighboursOf).
hexNeighboursOffunctionThe six neighbours of a cell on the hexagon lattice, as indexes; fewer at an edge of the square (the hexagon's own edge is its # cells).
hexNeighbourTablefunctionEvery cell's six neighbours on the hexagon lattice, worked out once for a size.
hexRadiusfunctionThe hexagon's radius on a board of this side: R, for a side of 2R + 1.
inHexfunctionWhether a cell of the square is inside the hexagon: at most R lattice steps from the middle.
isTsunagiDayfunctionWhether a text is a real date written YYYY-MM-DD: 2026-02-30 is not.
isTsunagiLevelfunctionWhether a number is a level this size has.
isTwistfunctionWhether a board is a twist: any challenge on it.
joinedfunctionWhether a pair's line runs from one of its stones to the other.
layoutCellsfunctionA layout's cells without its walls or wrap: the part of the code one character a cell.
layoutNeighboursfunctionEach cell's neighbours a line may step to on this board: the four around it, less any across a wall.
layoutOffunctionThe layout and answer the lines leave: their ends as stones, lettered in reading order, with whatever else the board has — blocked cells, bridges (in two lines' paths, drawn +) and walls.
layoutStepfunctionA layout's step from a to its neighbour b (stepBetween on its own kind of board), or 0.
letGofunctionLetting go: a line of only its stone is no line (a tap on a stone clears it), and a line ends before a bridge it stopped on.
levelCountOffunctionHow many levels a size has in a set; zero for a size the set has none at.
LevelMeasuretypeWhat is measured of one level.
LevelRowtypeOne level: its layout and its one answer, each a code (code.ts).
levelSeedfunctionThe number a record keeps a level by: its own for the first set, TSUNAGI_PORTAL_SEED and its number for the portals.
liftGamefunctionThe finger lifted: the stroke is counted if it changed the board, the board may be solved, and an explosion may go off.
LinestypeTHE LINES A PLAYER HAS DRAWN, and what a press and a drag do to them.
linesCodeFitsfunctionWhether a progress code has the shape of one: a size's cells in the progress alphabet.
linesOfAnswerfunctionA level's answer drawn back as lines: each pair's cells, in order, from its first marble to its second.
LINK_BLOCKEDconstantThe blocked-cell marker in a layout code.
LINK_BRIDGEconstantThe bridge-cell marker in a layout code.
LINK_EMPTYconstantTSUNAGI, WRITTEN DOWN: a level's layout and a finished grid, as the strings every puzzle travels as (puzzleCode.ts is the spelling of the number grids; this is the spelling of this one).
LINK_HEXconstantThe segment after the cells that makes a board a hexagon of hexagons.
LINK_PORTALSconstantThe word after the cells that begins a list of portals, each as its two cells.
LINK_SPARSEconstantThe segment after the cells that says a board has few, long lines.
LINK_WALLSconstantWhere the walls start, after the cells.
LINK_WRAPconstantThe segment after the cells that makes a board wrap.
LinkCandidatetypeOne candidate: its layout and answer codes, and what the solver said about it.
LinkExtrastypeWhat a board has besides its lines: the cells no line enters, the bridges two lines cross, and the walls between cells.
LinkLayouttypeA decoded board with pairs, cells, walls, waypoints, wrapping, portals and optional limits.
measureLevelfunctionEvery measure of one level, from its layout and answer; null for a layout that does not read as one of this size.
measureSolvedfunctionThe same measures from a solve already made — how many positions and branches the solver took — so a caller that has just proved a level (the level tests) does not solve it a second time to measure it.
MOST_PAIRSconstantThe most lines a board can have: as many as there are characters to name them.
neighboursOffunctionThe four neighbours of a cell on a square grid, as indexes; fewer at an edge.
neighbourTablefunctionEvery cell's neighbours, worked out once for a size.
newTsunagiGamefunctionA game on a layout code, or null for a code that is no layout at that size.
nextTsunagiLevelfunctionThe level to open on: the first open one not yet solved, or the last open one when every open level is solved.
NO_REACHconstantNo distance: the finger draws toward the cell it is over.
noLinesfunctionThe initial lines rooted at each pair’s first endpoint.
openTsunagiLevelsfunctionThe levels that are open, given the ones solved: the first block of sixteen always, and each block after it once every level of the block before is solved.
orderByDifficultyfunctionThe order to play a size's levels in: easiest first, by score, and among equal scores by their order in levels so the ranking is the same every time it is made.
outOfStrokesfunctionWhether the game is out of strokes before it is solved: it takes nothing more until restartGame.
overBridgefunctionThe pair going over a bridge each way, or -1: across (left to right) and down.
ownersOffunctionThe pair whose line (or stone) holds each cell, CELL_EMPTY for none, CELL_BLOCKED where blocked, CELL_BRIDGE on a bridge (two lines may be there).
PAIR_LETTERSconstantThe characters a pair may be named by, in order: the capital letters, the digits, the small letters, then twenty punctuation marks, eighty-two in all, enough for a 30×30 board with as many lines to the cell as a 15×15 has.
portalExitfunctionThe cell a line comes out at after stepping from from into portal cell into: beyond the other portal, the same way on; -1 where there is none (off the board, or across a wall).
portalsAreAmbiguousfunctionWhether two ways for a line to go from one cell to another exist on a board with portals (a portal and a step beside it, or two portals, or one in two directions), which an answer's cells could not tell apart.
pressAtfunctionA press: the lines after it, and the pair now being drawn, or null where the press draws nothing.
pressGamefunctionA finger down on a cell: starts a line from a marble, or carries on from a line's cell.
RandomtypeA number in [0, 1), like Math.random, from a stream a seed fixes.
randomFillingfunctionGrid lines that fill every cell, as lists of cells; null when this attempt painted itself into a corner.
ReachtypeHOW FAR A FINGER IS FROM THE END OF THE LINE IT DRAWS, in rows and columns, once that line has been through a portal.
reducedCandidatefunctionOne board made by taking clues away, or null.
ReducedCandidatetypeWhat a made board has besides its lines.
ReduceOptionstypeBudgets and geometry choices for generating a puzzle by reducing clues.
reletteredfunctionA code's letters renamed in reading order of first appearance: the one spelling of a layout or answer.
renumberedRecordfunctionA RECORD KEPT BY LEVEL NUMBER, MOVED TO THE NUMBERS THE LEVELS HAVE NOW.
repairedCandidatefunctionOne candidate level made by MENDING rather than by luck, for boards too big for luck (12×12): a filling whose layout has a second answer is mended where the two answers differ — the line through a cell they disagree on is cut in two there, which adds a pair of stones the second answer cannot honour — and solved again, until it has exactly one answer, its own.
restartGamefunctionRestart: every line cleared and the strokes counted again (Undo can bring the lines back).
SAT_BINARY_FROM_SIZEconstantFrom which side the SAT solver writes a cell's pair as a binary number rather than a variable for each pair, which a board of dozens of pairs needs: every level to 15×15 was proved the first way and keeps its counts.
SAT_FROM_SIZEconstantFrom which side of the board a layout is counted by solveSat.ts rather than by the search below.
SatColourstypeHow a cell's pair is written as variables: a variable for each pair (the way every level to 15×15 was proved), or a binary number, which a board of many pairs can afford.
seededRandomfunctionA stream of numbers in [0, 1) fixed by a seed.
setOfSeedfunctionThe set and the number in it a record's number names.
shuffledfunctionA copy of the list in a random order (Fisher–Yates); the list given is left alone.
SolveCounttypeTHE TSUNAGI SOLVER: how many ways a layout can be joined, up to a limit, and how much trying it took.
sparseCandidatefunctionOne sparse candidate level, or null.
sparseMostfunctionThe most lines a sparse board of this side has: two thirds of the side — six on a 9×9, where nine is usual.
SteptypeWHERE A LINE MAY GO NEXT, on one board: the rules of a single step, which the solver, the check, the drawing and the answer's lines all read, so a bridge or a wall means the same thing everywhere.
stepBetweenfunctionThe way from a to its neighbour b as a step (-1, +1, -size, +size), counting a step across a wrapped edge as the step it is — right off the right edge is +1, though the cells' numbers differ by size - 1.
stepTablefunctionEvery cell's steps on a board, worked out once.
stoneLettersfunctionThe characters that name pairs in a layout's cells: the first thirty-six (capitals and digits), or all eighty-two where the board uses every one of the thirty-six, which is when its small letters are stones and not waypoints.
strokesToExplosionfunctionStrokes left before the next explosion: 1 means the next stroke sets one off.
strongestTsunagiHelpfunctionOf several helps, the one a solve is kept with: explosions off, then Cheat, then explosions softened.
symmetryKeyfunctionThe least spelling of a layout over its eight turns and mirrors: equal keys are the same board.
tailWordfunctionWhich of the tail's words a segment is, and what it says; null for none of them (the walls list).
transformedfunctionA layout code turned or mirrored: turn quarter turns, then a mirror across the vertical when mirror.
TSUNAGI_BLOCKconstantTSUNAGI'S BLOCKS: its levels come sixteen at a time.
TSUNAGI_DAILY_STRIDEconstantEach day moves this many levels along a size's ladder, round to the start when it runs out.
TSUNAGI_LEVEL_COUNTSconstantHow many levels each size has, read without loading the size.
TSUNAGI_PORTAL_COUNTSconstantThe number of portal levels available at each supported size.
TSUNAGI_PORTAL_SEEDconstantA portal level's number in a record that keeps a level by one number: this and its number in its own set, past every level of the first.
TSUNAGI_PORTAL_SIZESconstantA second set of levels, boards with portals (code.ts): a line goes in at one ring and out of the other.
TSUNAGI_SIZESconstantTSUNAGI'S LEVELS, COUNTED: which sizes there are, how many levels each has, and which of them a player has opened.
tsunagiBandfunctionWhich third of a size a level sits in: its first third easy, its middle medium, its last hard.
TsunagiBandtypeThe third of a size a level sits in.
TsunagiChecktypeWhat a check says: joined, or the first reason it is not.
tsunagiDayfunctionThe day a moment falls on, in UTC, or the same day if it is already written as one.
TsunagiDaytypeA calendar date, YYYY-MM-DD.
TsunagiExplosionChoicetypeHow a board's explosions are played: as made, softened (a boom for a blast, half as often) or not at all.
TsunagiGametypeThe complete immutable puzzle state, current stroke, undo history and assistance flags.
TsunagiGameOptionstypeWhat a game is told when it starts.
TsunagiHelptypeThe help a solve used: Cheat drew a line, or explosions were softened or turned off.
tsunagiMarksfunctionA level's measured difficulty, 1 (easiest) to 5, or null for a level the marks do not have.
tsunagiProgressfunctionRead the native completion, strokes, explosions and help status of a game.
TsunagiProgresstypeWhat a game stands at: for a status line under the board.
tsunagiRolefunctionA level's part in its block's lesson, from the data the level script wrote (marks.data.ts), without its size's boards; null for none.
TsunagiSettypeWhich set of levels: the ones from 4×4 up, or the ones with portals.
turnsInfunctionHow many times an answer's lines turn a corner, over all of them: a line going straight over a bridge turns nowhere on it.
TwistCandidatetypeMAKING TSUNAGI'S TWISTS, on a desk: boards with bridges, and boards with walls and blocked cells (John, 2026-09-26, both chosen from the brainstorm; bridges first).
twistRolefunctionA level's part in its block's lesson, or null for a level that has none (1 to 14, or a 15th or 16th left plain because somebody had played it).
TwistRoletypeWhere a level sits in its block's lesson: its 15th teaches the block's twist, its 16th tests it.
undoGamefunctionUndo: the lines as they were before the last stroke.
unjoinedPairsfunctionThe pairs not joined yet, for Check: every pair whose line does not run from one of its marbles to the other — a line stopped beside its partner looks joined and is not.
VERSIONconstantThe package's version.
wallCandidatefunctionA board with blockedWanted blocked cells and as many walls as it needs (at most mostWalls) to have one answer, or null.
WAYPOINT_LETTERSconstantThe waypoints a layout may carry: a pair's capital in lower case, so only the first twenty-six pairs can have one.
waypointCandidatefunctionWAYPOINTS.
withoutPortalTailfunctionA line with the portal cells taken off its end, if it ends on any: a line is never left inside a portal.
withPortalsfunctionA filling with portals put in: each portal is made by joining two lines into one that goes into a ring and out of another, and the two cells it takes are the portal.
wrapCandidatefunctionWRAP.
wrappedStepfunctionThe cell beside at one step by (-1, +1, -size, +size) on a board that wraps: off one edge and in at the other.

View sourceEdit on GitHubMade from the source of @johnmorrisdotca/tsunagi 1.7.0.