Skip to content

Instantly share code, notes, and snippets.

@akkartik
Last active September 24, 2021 20:14
Show Gist options
  • Save akkartik/5bd19488bfb59b6615fe13e5ee482af7 to your computer and use it in GitHub Desktop.
Save akkartik/5bd19488bfb59b6615fe13e5ee482af7 to your computer and use it in GitHub Desktop.
Conway's Game of Life in Smalltalk (Glamorous Toolkit)
"Hopefully I copied it correctly from my image and CodeChanges."
Object subclass: #GameOfLife
instanceVariableNames: 'grid grid1 grid2 side'
classVariableNames: ''
package: 'KartikAgaram'.
GameOfLife >> initialize
side := 10.
grid1 := (Array2D rows: side columns: side element: 0).
grid2 := (Array2D rows: side columns: side element: 0).
grid := grid1.
"step"
GameOfLife >> step
grid = grid1 ifTrue: [ self step12] ifFalse: [self step21]
GameOfLife >> step12
1 to: side do: [ :x |
1 to: side do: [ :y |
self step12: x@y.
]
]
grid := grid2.
GameOfLife >> step21
1 to: side do: [ :x |
1 to: side do: [ :y |
self step21: x@y.
]
].
grid := grid1.
GameOfLife >> step12: aPoint
| x y neighbors count oldState newState |
x := aPoint x.
y := aPoint y.
"obtain neighbors without going out of bounds"
neighbors := grid1 atRows: y-1 to: y+1 columns: x-1 to: x+1 ifInvalid: 0.
neighbors at: 2 at: 2 put: 0. "a cell isn't its own neighbor"
"count neighbors"
count := neighbors occurrencesOf: 1.
"compute new state"
oldState := grid1 at: y at: x.
newState := count = 2 ifTrue: [grid1 at: y at: x] ifFalse: [count = 3 ifTrue: [1] ifFalse: [0]].
"save new state"
grid2 at: y at: x put: newState.
GameOfLife >> step21: aPoint
| x y neighbors count oldState newState |
x := aPoint x.
y := aPoint y.
"obtain neighbors without going out of bounds"
neighbors := grid2 atRows: y-1 to: y+1 columns: x-1 to: x+1 ifInvalid: 0.
neighbors at: 2 at: 2 put: 0. "a cell isn't its own neighbor"
"count neighbors"
count := neighbors occurrencesOf: 1.
"compute new state"
oldState := grid2 at: y at: x.
newState := count = 2 ifTrue: [oldState] ifFalse: [count = 3 ifTrue: [1] ifFalse: [0]].
"save new state"
grid1 at: y at: x put: newState.
GameOfLifeTestExamples >> singleLiveCellDies
<gtExample>
|x|
x := GameOfLife new.
x set: 5@5.
x step.
self assert: x isEmpty.
^ x
GameOfLifeTestExamples >> block2x2Lives
"https://www.conwaylife.com/wiki/Block"
<gtExample>
|x|
x := GameOfLife new.
x set: 2@2; set: 2@3; set: 3@2; set: 3@3.
x step.
self assert: x isEmpty not.
^ x
GameOfLifeTestExamples >> block2x2LivesAtCorner
"https://www.conwaylife.com/wiki/Block"
<gtExample>
|x|
x := GameOfLife new.
x set: 1@1; set: 1@2; set: 2@1; set: 2@2.
x step.
self assert: x isEmpty not.
^ x
GameOfLifeTestExamples >> block2x2LivesAtEdge
"https://www.conwaylife.com/wiki/Block"
<gtExample>
|x|
x := GameOfLife new.
x set: 1@2; set: 1@3; set: 2@2; set: 2@3.
x step.
self assert: x isEmpty not.
^ x
GameOfLifeTestExamples >> loafLives
"https://www.conwaylife.com/wiki/Loaf remains unchanging"
<gtExample>
|x expected|
x := GameOfLife new.
x set: 2@4; set: 3@3; set: 4@2; set: 5@3; set: 5@4; set: 4@5; set: 3@5.
expected := x grid copy.
x step.
self assert: (x grid) = expected.
^ x
GameOfLifeTestExamples >> trafficLight
"https://www.conwaylife.com/wiki/Blinker returns to original shape after 2 steps"
<gtExample>
|x expected|
x := GameOfLife new.
x set: 2@3; set: 3@3; set: 4@3.
expected := x grid copy.
x step.
self assert: (x grid) ~= expected.
x step.
self assert: (x grid) = expected.
^ x
"some helpers for the tests"
GameOfLife >> grid
^ grid
GameOfLife >> isEmpty
^ grid allEqual: 0
Array2D >> allEqual: exemplar
^ contents allEqual: exemplar
Array >> allEqual: exemplar
^ self inject: true into: [:result :x| result and: (x = exemplar)]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment