"A naive demonstration of Conway's Game of Life, using terminal graphics." 'src/init.slate' fileIn. 'src/vt220.slate' fileIn. lobby addSlot: #LifeGame valued: Cloneable derive. LifeGame addSlot: #screen. LifeGame addSlot: #height. LifeGame addSlot: #width. LifeGame addSlot: #cells valued: {}. "Array of size H * W." LifeGame addSlot: #newCells valued: {}. "Array of size H * W." LifeGame addSlot: #randomStream. ConsoleOutput addSlotsFrom: VT220. g@(LifeGame traits) random: max [ g randomStream next mod: max ]. g@(LifeGame traits) init "Load up #cells to be randomized." [ g cells doWithIndex: [| :each :index | g cells at: index put: 0]. g cells size / 4 timesRepeat: [g cells at: (g random: g cells size) put: 1]. g ]. g@(LifeGame traits) new "Target stdout and set up the game for it." [| newG scr | newG: g clone. scr: (newG screen: ConsoleOutput). newG height: 24. newG width: 40. "Play it safe with the size, since we can't read it yet." newG cells: (g cells newSize: (newG height * newG width)). newG newCells: newG cells. newG randomStream: (RandomStream newSeed: 4357). newG init. newG ]. g@(LifeGame traits) at: array [ g cells at: (array at: 0) + ((array at: 1) * g width) ]. g@(LifeGame traits) at: x at: y [ g cells at: x + (y * g width) ]. g@(LifeGame traits) neighborsOf: array [| index n atTop atBottom atLeft atRight | n: 0. index: (array at: 0) + ((array at: 1) * g width). atTop: (array at: 1) = 0. atBottom: (array at: 1) = (g height - 1). atLeft: (array at: 0) = 0. atRight: (array at: 0) = (g width - 1). atTop ifFalse: [ n: n + (g cells at: index - g width). atLeft ifFalse: [n: n + (g cells at: index - g width - 1)]. atRight ifFalse: [n: n + (g cells at: index - g width + 1)]]. atLeft ifFalse: [n: n + (g cells at: index - 1)]. atRight ifFalse: [n: n + (g cells at: index + 1)]. atBottom ifFalse: [ n: n + (g cells at: index + g width). atLeft ifFalse: [n: n + (g cells at: index + g width - 1)]. atRight ifFalse: [n: n + (g cells at: index + g width + 1)]]. n ]. g@(LifeGame traits) calcNewState "The core life rules." [ 0 below: g height do: [| :y | 0 below: g width do: [| :x n index | n: (g neighborsOf: {x. y}). index: x + (y * g width). (n > 3 or: [n < 2]) ifTrue: [g newCells at: index put: 0] ifFalse: [n = 3 ifTrue: [g newCells at: index put: 1] ifFalse: [g newCells at: index put: (g at: x at: y)]]]]. g ]. g@(LifeGame traits) step "Iterate: swap new with old arrays, and display the new one." [| temp | g calcNewState. temp: g newCells. g newCells: g cells. g cells: temp. g redraw ]. LifeGame addSlot: #oncolor valued: VT220 colorBG green. LifeGame addSlot: #offcolor valued: VT220 colorBG blue. g@(LifeGame traits) redraw [ 0 below: g height do: [| :y | g screen cursorToX: 1 y: y + 1. 0 below: g width do: [| :x | (g at: x at: y) = 0 ifTrue: [g screen formatFrom: {g offcolor}] ifFalse: [g screen formatFrom: {g oncolor}]. g screen nextPut: $\s]] ]. g@(LifeGame) run [ [g step] loop ]. ConsoleOutput ; 'Type "LifeGame new run." to see Life unfold.\n'.