librarygames/shut-the-box/ShutTheBox.xtl

Shut the box's rules, a library: shut-the-box.xtl (scripted), play.xtl (at the terminal) and the web page all use these. Tiles 1 to 9 start open. Each turn roll two dice (one die once the open tiles add up to 6 or less) and shut open tiles adding up to the roll. When no set of open tiles makes the roll, the game is over and the open tiles are the score; shut them all to win.

The state is the open tiles as a 0/1 vector of 9.

source · imports b: lib/Board.xtl

ˡn̲ew : (Any a, Num b) => a -> b

function · line 14

A new box: all nine tiles open (1).

ˡn̲ew ← { x → 9 r̲eshape 1 }

ˡs̲core : Int -> Int

function · line 17

The open tiles' sum: the tiles times the 0/1 vector, an inner product.

ˡs̲core ← { s → s '+ '× i̲nner r̲ange 9 }

ˡs̲ubsets : Unit -> Int

function · line 23

Every set of tiles at once: the 512 subsets of 1 to 9 as the columns of a 9 by 512 matrix of bits (the binary digits of 0 to 511), and all their sums by one inner product.

ˡs̲ubsets ← { @ → 2 2 2 2 2 2 2 2 2 e̲ncode o̲ffsets 512 }
Used in: ˡs̲ums, ˡm̲oves, M

ˡs̲ums : Unit -> Int

function · line 26

Every subset's sum: the tiles' numbers against the 512 subsets, one inner product.

ˡs̲ums ← { @ → (r̲ange 9) '+ '× i̲nner ˡs̲ubsets @ }

ˡr̲oll : Int -> Int

function · line 30

The roll: two dice, or one when the open tiles add up to 6 or less.

ˡr̲oll ← { s → r̲oll! (1 + 6 < ˡs̲core s) r̲eshape 6 }

ˡm̲oves : Int -> Int -> Int

function · line 35

The moves for roll r: the subsets that use only open tiles (every bit at most the tile's 0 or 1) and add up to r, one per row.

ˡm̲oves ← { s r →
  M ← ˡs̲ubsets @
  fits ← '∧ r̲/ M ≤ s 'l̲eft t̲able o̲ffsets 512
  o̲\ (w̲here fits ∧ r = ˡs̲ums @) s̲elect₂ M
}

ˡs̲hut : (Num a, Truthy a, Truthy b) => a -> b -> a

function · line 42

Shut the tiles of a move (a 0/1 vector of 9).

ˡs̲hut ← { s m → s × n̲ot m }
Used in: ᵘt̲urn, t, ᵘg̲ame

ˡs̲tatus : Num a => Int -> Int -> a

function · line 45

0 playing, 1 the box shut, 2 stuck (the score stands).

ˡs̲tatus ← { s r → f̲irst (((0 = ˡs̲core s) c̲at 0 = t̲ally s ˡm̲oves r) r̲eplicate 1 2) c̲at 0 }

ˡv̲iew : Int -> Char

function · line 50

The tiles as the box shows them: open ones by number, shut ones as ., spaced (lib/Board).

ˡv̲iew ← { s → r̲avel ᵇs̲paced (1 9 r̲eshape 1 + s × r̲ange 9) s̲elect ".123456789" }

ˡt̲iles : Truthy a => a -> Char

function · line 53

A move as its tiles, "1 2 4".

ˡt̲iles ← { m → f̲ormat w̲here m }
Used in: ˡl̲isted

ˡl̲isted : Truthy a => a -> Box Char

function · line 57

The moves as a strand of lines, " 1 2 4", one per move (a function mapped over the moves' row numbers).

ˡl̲isted ← { m → '{ "  " c̲at ˡt̲iles ⍵ s̲elect m } m̲ap r̲ange t̲ally m }
Used in: ᵘt̲urn

ˡh̲igh : Int -> Int -> Int

function · line 62

A player that shuts the highest tiles it can: of the moves, the one whose tiles, read as a number from 9 down, is largest.

ˡh̲igh ← { s r →
  m ← s ˡm̲oves r
  key ← m '+ '× i̲nner 2 ^ o̲ffsets 9
  (f̲irst w̲here key = 'm̲ax r̲/ key) s̲elect m
}
Used in: ᵘg̲ame