game.bend fails
raw source on the hub · import 0x3b876eed3a748ea7fba8a7834d3c610b/game.bend as Game
Game: the state, the input, and the frame. ==========================================
The state is pure Data. Every click returns a new state, so a move is a value you can print, compare or replay. main.bend runs it in a window; demo.bend runs the same functions over a scripted list of events and prints the result.
The board is not laid out until the first click. That click sets the safe cell, so it can never be a mine and always opens a region.
5 imports
import Base import ./grid.bend as G import ./cell.bend as C import ./board.bend as B import ./art.bend as A
Types
type Clock source · line 22 · raw
Data
The clock the window drives, one step per frame. It is kept as whole seconds plus a frame remainder, because Base's Nat arithmetic counts up one step at a time: small numbers stay cheap, and a raw millisecond timestamp would not be.
Clock@secs:Nat -> @sub:Nat -> Clock
type Game source · line 25 · raw
Data
Game@conf:0x3b876eed3a748ea7fba8a7834d3c610b/board.Conf -> @cells:0x3b876eed3a748ea7fba8a7834d3c610b/grid.Grid<&2, 0x3b876eed3a748ea7fba8a7834d3c610b/cell.Cell> -> @phase:0x3b876eed3a748ea7fba8a7834d3c610b/board.Phase -> @live:Bool -> @bx:U32 -> @by:U32 -> @tiles:List<&2, Image> -> @scale:Nat -> @clock:Clock -> Game
type Paint source · line 38 · raw
Data
The payload of a frame pass: everything one tile needs to know.
Paint@cells:0x3b876eed3a748ea7fba8a7834d3c610b/grid.Grid<&2, 0x3b876eed3a748ea7fba8a7834d3c610b/cell.Cell> -> @tiles:List<&2, Image> -> @depth:Nat -> @lost:Bool -> @bx:U32 -> @by:U32 -> Paint
Definitions
def Game.conf source · line 47 · raw
@g:Game -> 0x3b876eed3a748ea7fba8a7834d3c610b/board.Conf
def Game.cells source · line 52 · raw
@g:Game -> 0x3b876eed3a748ea7fba8a7834d3c610b/grid.Grid<&2, 0x3b876eed3a748ea7fba8a7834d3c610b/cell.Cell>
def Game.phase source · line 57 · raw
@g:Game -> 0x3b876eed3a748ea7fba8a7834d3c610b/board.Phase
def Game.live source · line 62 · raw
@g:Game -> Bool
def Game.bx source · line 67 · raw
@g:Game -> U32
def Game.by source · line 72 · raw
@g:Game -> U32
def Game.tiles source · line 77 · raw
@g:Game -> List<&2, Image>
def Game.scale source · line 82 · raw
@g:Game -> Nat
def Paint.cells source · line 87 · raw
@pt:Paint -> 0x3b876eed3a748ea7fba8a7834d3c610b/grid.Grid<&2, 0x3b876eed3a748ea7fba8a7834d3c610b/cell.Cell>
def Paint.tiles source · line 92 · raw
@pt:Paint -> List<&2, Image>
def Paint.depth source · line 97 · raw
@pt:Paint -> Nat
def Paint.lost source · line 102 · raw
@pt:Paint -> Bool
def Paint.bx source · line 107 · raw
@pt:Paint -> U32
def Paint.by source · line 112 · raw
@pt:Paint -> U32
def Game.clock source · line 117 · raw
@g:Game -> Clock
def Clock.secs source · line 122 · raw
@c:Clock -> Nat
def Clock.roll source · line 129 · raw
@s:Nat -> @u:Nat -> @full:Bool -> Clock
The original stops counting at 999, and so does this one. That also keeps Nat.show cheap.
def Clock.bump source · line 136 · raw
@c:Clock -> Clock
def Game.is_lost source · line 142 · raw
@g:Game -> Bool
def Game.blank_cell source · line 146 · raw
@+cf:0x3b876eed3a748ea7fba8a7834d3c610b/board.Conf -> @+x:U32 -> @+y:U32 -> 0x3b876eed3a748ea7fba8a7834d3c610b/cell.Cell
An empty board, before the first click picks the safe cell.
def Game.blank source · line 149 · raw
@+cf:0x3b876eed3a748ea7fba8a7834d3c610b/board.Conf -> 0x3b876eed3a748ea7fba8a7834d3c610b/grid.Grid<&2, 0x3b876eed3a748ea7fba8a7834d3c610b/cell.Cell>
def Game.new source · line 153 · raw
@+depth:Nat -> @mines:U32 -> @seed:U32 -> @+scale:Nat -> Game
depth 4n is a 16x16 board; scale 5n is a 32x32 tile, so a 512x512 window.
def Game.reset source · line 159 · raw
@+g:Game -> Game
Restart. The seed walks on, so the next board is a different one.
def Game.wake.pick source · line 169 · raw
@+g:Game -> @x:U32 -> @y:U32 -> @live:Bool -> Game
The first click lays the board out and aims the safe block at itself.
def Game.wake source · line 178 · raw
@+g:Game -> @x:U32 -> @y:U32 -> Game
def Game.move.left source · line 182 · raw
@+g:Game -> @x:U32 -> @y:U32 -> @shown:Bool -> 0x3b876eed3a748ea7fba8a7834d3c610b/grid.Grid<&2, 0x3b876eed3a748ea7fba8a7834d3c610b/cell.Cell>
A left click opens a hidden cell and chords a shown one.
def Game.move.other source · line 189 · raw
@+g:Game -> @x:U32 -> @y:U32 -> @flagging:Bool -> 0x3b876eed3a748ea7fba8a7834d3c610b/grid.Grid<&2, 0x3b876eed3a748ea7fba8a7834d3c610b/cell.Cell>
def Game.move.pick source · line 196 · raw
@+g:Game -> @btn:U32 -> @+x:U32 -> @+y:U32 -> @left:Bool -> 0x3b876eed3a748ea7fba8a7834d3c610b/grid.Grid<&2, 0x3b876eed3a748ea7fba8a7834d3c610b/cell.Cell>
def Game.move source · line 206 · raw
@+g:Game -> @+btn:U32 -> @+x:U32 -> @+y:U32 -> 0x3b876eed3a748ea7fba8a7834d3c610b/grid.Grid<&2, 0x3b876eed3a748ea7fba8a7834d3c610b/cell.Cell>
Button 0 is the left one, 1 the right one, 2 the middle one.
def Game.settle.pick source · line 210 · raw
@+g:Game -> @cg:0x3b876eed3a748ea7fba8a7834d3c610b/grid.Grid<&2, 0x3b876eed3a748ea7fba8a7834d3c610b/cell.Cell> -> @ph:0x3b876eed3a748ea7fba8a7834d3c610b/board.Phase -> @x:U32 -> @y:U32 -> Game
A lost game turns its mines face up and remembers the one that blew.
def Game.settle source · line 222 · raw
@+g:Game -> @+cg:0x3b876eed3a748ea7fba8a7834d3c610b/grid.Grid<&2, 0x3b876eed3a748ea7fba8a7834d3c610b/cell.Cell> -> @x:U32 -> @y:U32 -> Game
def Game.press.go source · line 225 · raw
@+g:Game -> @btn:U32 -> @+x:U32 -> @+y:U32 -> Game
def Game.press.pick source · line 229 · raw
@+g:Game -> @btn:U32 -> @x:U32 -> @y:U32 -> @ph:0x3b876eed3a748ea7fba8a7834d3c610b/board.Phase -> Game
def Game.press source · line 239 · raw
@+g:Game -> @btn:U32 -> @px:U32 -> @py:U32 -> Game
A click in window pixels. A finished game ignores it.
def Game.mouse source · line 243 · raw
@+g:Game -> @btn:U32 -> @x:U32 -> @y:U32 -> @down:Bool -> Game
def Game.key.pick source · line 250 · raw
@+g:Game -> @restart:Bool -> Game
def Game.key source · line 258 · raw
@+g:Game -> @code:U32 -> @down:Bool -> Game
r starts a new board.
def Game.feed source · line 268 · raw
@es:List<&1, Event> -> @alive:Bool -> @g:Game -> Pair(Game, Bool)
Folds a frame's events into the state and reports whether the window is still open. Both come out of one walk, because the list a frame hands back is affine and cannot be walked twice.
alive is a parameter rather than a test on a computed value: a
match may only scrutinise a parameter, so the answer to this round
is carried into the next call.
def Game.tile_at source · line 283 · raw
@+pt:Paint -> @+x:U32 -> @+y:U32 -> Image
def Game.paint source · line 290 · raw
@d:Nat -> @+pt:Paint -> @+x:U32 -> @+y:U32 -> Image
Draws the board. The four quadrants run in parallel, and each leaf only copies a reference to a tile that was drawn once at startup.
def Game.image source · line 303 · raw
@+g:Game -> Image
def Game.left source · line 309 · raw
@+g:Game -> U32
Mines left to find, never below zero.
def Game.tock.pick source · line 316 · raw
@+g:Game -> @run:Bool -> Game
One frame of the clock. It runs only while a laid-out board is still in play, so it starts on the first click and stops on a win or a loss.
def Game.tock source · line 325 · raw
@+g:Game -> Game
def Game.phase.show source · line 328 · raw
@p:0x3b876eed3a748ea7fba8a7834d3c610b/board.Phase -> String
def Game.title source · line 337 · raw
@+g:Game -> String
def Game.size source · line 343 · raw
@+g:Game -> U32
The window is as wide as the board: 2^depth cells of 2^scale pixels.