# Conway's Game of Life

(Redirected from Life in two dimensions)
Conway's Game of Life
You are encouraged to solve this task according to the task description, using any language you may know.

The Game of Life is a   cellular automaton   devised by the British mathematician   John Horton Conway   in 1970.   It is the best-known example of a cellular automaton.

Conway's game of life is described   here:

A cell   C   is represented by a   1   when alive,   or   0   when dead,   in an   m-by-m   (or m×m)   square array of cells.

We calculate   N   - the sum of live cells in C's   eight-location neighbourhood,   then cell   C   is alive or dead in the next generation based on the following table:

```   C   N                 new C
1   0,1             ->  0  # Lonely
1   4,5,6,7,8       ->  0  # Overcrowded
1   2,3             ->  1  # Lives
0   3               ->  1  # It takes three to give birth!
0   0,1,2,4,5,6,7,8 ->  0  # Barren
```

Assume cells beyond the boundary are always dead.

The "game" is actually a zero-player game, meaning that its evolution is determined by its initial state, needing no input from human players.   One interacts with the Game of Life by creating an initial configuration and observing how it evolves.

Although you should test your implementation on more complex examples such as the   glider   in a larger universe,   show the action of the blinker   (three adjoining cells in a row all alive),   over three generations, in a 3 by 3 grid.

References

## 11l

Translation of: Python
```V cellcountx = 6
V cellcounty = 5
V celltable = [(1, 2) = 1,
(1, 3) = 1,
(0, 3) = 1]
DefaultDict[(Int, Int), Int] universe
universe[(1, 1)] = 1
universe[(2, 1)] = 1
universe[(3, 1)] = 1
universe[(1, 4)] = 1
universe[(2, 4)] = 1
universe[(3, 4)] = 1

L(i) 4
print("\nGeneration "i‘:’)
L(row) 0 .< cellcounty
print(‘  ’(0 .< cellcountx).map(col -> [‘. ’, ‘O ’][:universe[(@row, col)]]).join(‘’))

DefaultDict[(Int, Int), Int] nextgeneration
L(row) 0 .< cellcounty
L(col) 0 .< cellcountx
nextgeneration[(row, col)] = celltable.get(
(universe[(row, col)],
-universe[(row, col)] + sum(multiloop(row-1..row+1,
col-1..col+1, (r, c) -> :universe[(r, c)]))
), 0)
universe = nextgeneration```

### More optimal solution

```V cellcountx = 6
V cellcounty = 5
V universe = [[0B] * cellcountx] * cellcounty
universe[1][1] = 1B
universe[2][1] = 1B
universe[3][1] = 1B
universe[1][4] = 1B
universe[2][4] = 1B
universe[3][4] = 1B
V nextgeneration = [[0B] * cellcountx] * cellcounty

L(i) 4
print("\nGeneration "i‘:’)
L(row) 0 .< cellcounty
print(‘  ’, end' ‘’)
L(col) 0 .< cellcountx
print(I universe[row][col] {‘O ’} E ‘. ’, end' ‘’)
print()

L(row) 0 .< cellcounty
L(col) 0 .< cellcountx
V s = 0
I row > 0
s = universe[row-1][col]
I col > 0
s += universe[row-1][col-1]
I col < cellcountx-1
s += universe[row-1][col+1]
I col > 0
s += universe[row][col-1]
I col < cellcountx-1
s += universe[row][col+1]
I row < cellcounty-1
s += universe[row+1][col]
I col > 0
s += universe[row+1][col-1]
I col < cellcountx-1
s += universe[row+1][col+1]
nextgeneration[row][col] = I universe[row][col] {s C 2..3} E s == 3
universe = nextgeneration```
Output:
```Generation 0:
. . . . . .
. O . . O .
. O . . O .
. O . . O .
. . . . . .

Generation 1:
. . . . . .
. . . . . .
O O O O O O
. . . . . .
. . . . . .

Generation 2:
. . . . . .
. O O O O .
. O O O O .
. O O O O .
. . . . . .

Generation 3:
. . O O . .
. O . . O .
O . . . . O
. O . . O .
. . O O . .
```

## 6502 Assembly

Works with: [6502asm.com] version 1.2
```randfill:   stx \$01          ;\$200 for indirect
stx \$02
randloop:   lda \$fe          ;generate random
and #\$01         ;pixels on the
sta (\$01),Y      ;screen
jsr inc0103
cmp #\$00
bne randloop
lda \$02
cmp #\$06
bne randloop

clearmem:   lda #\$df         ;set \$07df-\$0a20
sta \$01          ;to \$#00
lda #\$07
sta \$02
clearbyte:  lda #\$00
sta (\$01),Y
jsr inc0103
cmp #\$20
bne clearbyte
lda \$02
cmp #\$0a
bne clearbyte

starttick:
copyscreen: lda #\$00         ;set up source
sta \$01          ;pointer at
sta \$03          ;\$01/\$02 and
lda #\$02         ;dest pointer
sta \$02          ;at \$03/\$04
lda #\$08
sta \$04
ldy #\$00
copybyte:   lda (\$01),Y      ;copy pixel to
sta (\$03),Y      ;back buffer
jsr inc0103      ;increment pointers
cmp #\$00         ;check to see
bne copybyte     ;if we're at \$600
lda \$02          ;if so, we've
cmp #\$06         ;copied the
bne copybyte     ;entire screen

conway:     lda #\$df         ;apply conway rules
sta \$01          ;reset the pointer
sta \$03          ;to \$#01df/\$#07df
lda #\$01         ;(\$200 - \$21)
sta \$02          ;(\$800 - \$21)
lda #\$07
sta \$04
onecell:    lda #\$00         ;process one cell
ldy #\$01         ;upper cell
clc
ldy #\$41         ;lower cell
clc
chkleft:    tax              ;check to see
lda \$01          ;if we're at the
and #\$1f         ;left edge
tay
txa
cpy #\$1f
beq rightcells
leftcells:  ldy #\$00         ;upper-left cell
clc
ldy #\$20         ;left cell
clc
ldy #\$40         ;lower-left cell
clc
chkright:   tax              ;check to see
lda \$01          ;if we're at the
and #\$1f         ;right edge
tay
txa
cpy #\$1e
beq evaluate
rightcells: ldy #\$02         ;upper-right cell
clc
ldy #\$22         ;right cell
clc
ldy #\$42         ;lower-right cell
clc
evaluate:   ldx #\$01         ;evaluate total
ldy #\$21         ;for current cell
cmp #\$03         ;3 = alive
beq storex
ldx #\$00
cmp #\$02         ;2 = alive if
bne storex       ;c = alive
lda (\$03),Y
and #\$01
tax
storex:     txa              ;store to screen
sta (\$01),Y
jsr inc0103      ;move to next cell
conwayloop: cmp #\$e0         ;if not last cell,
bne onecell      ;process next cell
lda \$02
cmp #\$05
bne onecell
jmp starttick    ;run next tick

inc0103:    lda \$01          ;increment \$01
cmp #\$ff         ;and \$03 as 16-bit
bne onlyinc01    ;pointers
inc \$02
inc \$04
onlyinc01:  inc \$01
lda \$01
sta \$03
rts```

## 68000 Assembly

I went a little further and created a 40x30 grid, but this implementation is accurate and does have a blinker in it. As always, thanks to Keith of Chibiakumas for the cartridge header and hardware routines. This is the source code for a Sega Genesis game that you can compile with VASM. (It was tested in the Fusion emulator but it should work anywhere.)

Explanation of the implementation:

• I'm using the Genesis's foreground tilemap to create the graphics.
• Grid boundaries are handled by using the classic trick of padding all sides with a value that's not used in the "real" grid, and always counts as a dead cell.
• Every iteration of the main loop does the same thing: check neighbors of each cell in the grid, write the next generation to a buffer, copy that buffer over the original, and display the output. This way, updates don't impact the outcome of the rest of the cells down the line (which would go against the rules of the game, as all cell births/deaths happen simultaneously.)

Explanation of macros:

• pushRegs = MOVEM.L ___,-(SP)
• popRegs = MOVEM.L (SP)+,___
• pushLong = MOVE.L ___,-(SP)
• popLong = MOVE.L (SP)+,___
```include "\SrcALL\68000_Macros.asm"
;Ram Variables
Cursor_X equ \$00FF0000		;Ram for Cursor Xpos
Cursor_Y equ \$00FF0000+1	;Ram for Cursor Ypos

conwayTilemapRam equ \$00FF1000
conwayBackupTilemapRam equ \$00FF2000
;Video Ports
VDP_data	EQU	\$C00000	; VDP data, R/W word or longword access only
VDP_ctrl	EQU	\$C00004	; VDP control, word or longword writes only

;constants
ROWLENGTH equ 40

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 					Traps
DC.L	\$FFFFFE00		;SP register value
DC.L	ProgramStart	;Start of Program Code
DS.L	7,IntReturn		; bus err,addr err,illegal inst,divzero,CHK,TRAPV,priv viol
DC.L	IntReturn		; TRACE
DC.L	IntReturn		; Line A (1010) emulator
DC.L	IntReturn		; Line F (1111) emulator
DS.L	4,IntReturn		; Reserverd /Coprocessor/Format err/ Uninit Interrupt
DS.L	8,IntReturn		; Reserved
DC.L	IntReturn		; spurious interrupt
DC.L	IntReturn		; IRQ level 1
DC.L	IntReturn		; IRQ level 2 EXT
DC.L	IntReturn		; IRQ level 3
DC.L	IntReturn		; IRQ level 4 Hsync
DC.L	IntReturn		; IRQ level 5
DC.L	IntReturn		; IRQ level 6 Vsync
DC.L	IntReturn		; IRQ level 7
DS.L	16,IntReturn	; TRAPs
DS.L	16,IntReturn	; Misc (FP/MMU)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DC.B	"SEGA GENESIS    "	;System Name
DC.B	"2019.JAN"			;Date
DC.B	"ChibiAkumas.com                                 " ; Cart Name
DC.B	"ChibiAkumas.com                                 " ; Cart Name (Alt)
DC.B	"GM CHIBI001-00"	;TT NNNNNNNN-RR T=Type (GM=Game) N=game Num  R=Revision
DC.W	\$0000				;16-bit Checksum (Address \$000200+)
DC.B	"J               "	;Control Data (J=3button K=Keyboard 6=6button C=cdrom)
DC.L	\$00000000			;ROM Start
DC.L	\$003FFFFF			;ROM Length
DC.L	\$00FF0000,\$00FFFFFF	;RAM start/end (fixed)
DC.B	"            "		;External RAM Data
DC.B	"            "		;Modem Data
DC.B	"                                        " ;MEMO
DC.B	"JUE             "	;Regions Allowed

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;					Generic Interrupt Handler
IntReturn:
rte
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;					Program Start
ProgramStart:
move.b (\$A10001),D0		;A10001 test the hardware version
and.b #\$0F,D0
beq	NoTmss				;branch if no TMSS chip
move.l #'SEGA',(\$A14000);A14000 disable TMSS
NoTmss:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;					Set Up Graphics

lea VDPSettings,A5		;Initialize Screen Registers
move.l #VDPSettingsEnd-VDPSettings,D1 ;length of Settings

move.w (VDP_ctrl),D0	;C00004 read VDP status (interrupt acknowledge?)
move.l #\$00008000,d5	;VDP Reg command (%8rvv)

NextInitByte:
move.b (A5)+,D5			;get next video control byte
move.w D5,(VDP_ctrl)	;C00004 send write register command to VDP
;   8RVV - R=Reg V=Value
add.w #\$0100,D5			;point to next VDP register
dbra D1,NextInitByte	;loop for rest of block

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;					Set up palette and graphics

move.l #\$C0000000,d0	;Color 0
move.l d0,VDP_Ctrl
MOVE.W #\$0A00,VDP_Data		;BLUE

move.l #\$C01E0000,d0	;Color 0
move.l d0,VDP_Ctrl
MOVE.W #\$00EE,VDP_Data		;YELLOW

lea Graphics,a0						;background tiles
move.w #(GraphicsEnd-Graphics)-1,d1	;data size
jsr DefineTiles

clr.b Cursor_X			;Clear Cursor XY
clr.b Cursor_Y

;Turn on screen
move.w	#\$8144,(VDP_Ctrl);C00004 reg 1 = 0x44 unblank display

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; TESTING AREA

LEA Conway_Tilemap,a3
LEA ConwayTilemapRam,A2
move.l #(Conway_Backup_Tilemap-Conway_Tilemap),d1
JSR LDIR

LEA Conway_Backup_Tilemap,a3
LEA conwayBackupTilemapRam,A2
move.l #(Conway_Backup_Tilemap-Conway_Tilemap),d1
JSR LDIR

CLR.B Cursor_X
CLR.B Cursor_Y
;print the tilemap once
LEA ConwayTilemapRam,A3
JSR Conway_Print

main:

;do the behavior
jsr Conway_CheckTilemap

;copy the tilemap
lea conwayBackupTilemapRam,A3
LEA ConwayTilemapRam,A2
move.l #(Conway_Backup_Tilemap-Conway_Tilemap),d1
jsr LDIR

CLR.B Cursor_X
CLR.B Cursor_Y
;print the tilemap
LEA ConwayTilemapRam,A3
JSR Conway_Print

;repeat
JMP main

Conway_CheckTilemap:

;since we don't want the partial results of the checks to mess with later ones, we'll copy the changes to a buffer, and then
;have that buffer clobber the original. That way, all changes to the ecosystem are effectively atomic.

LEA ConwayTilemapRam,A0
LEA conwayBackupTilemapRam,A6
LEA (ROWLENGTH+3,A0),A0	;actual data starts here
LEA (ROWLENGTH+3,A6),A6	;actual data starts here
.loop:
MOVE.B (A0),D2
CMP.B #255,D2
BEQ .done
CMP.B #2,D2
JSR Conway_CheckNeighbors

pushLong D0
JSR popcnt_8
MOVE.B D0,D3
popLong D0

;now implement the table here.
;neighbor bits in D0
;current state in D2
;popcnt in D3
;pointer to where we are in A0

;the only time the current state is relevant to the output, is when popcnt = 2. Otherwise, it's entirely determined by popcnt.
CMP.B #4,D3
CMP.B #1,D3
CMP.B #3,D3
BEQ .LiveCell
;else, must be 2.
MOVE.B D2,(A6)	;store current value into backup table.
.LiveCell:
MOVE.B #1,(A6)
MOVE.B #0,(A6)	;store in backup table.
JMP .loop
.done:
RTS

popcnt_8:
pushRegs D2-D5
MOVEQ #8-1,D5
MOVEQ #0,D3
.loop:
ROR.B #1,D0
dbra d5,.loop
MOVE.B D3,D0
popRegs D2-D5
RTS

Conway_CheckNeighbors:
;A0 = pointer to where we are in the tilemap.
;returns: D0.B = uUrRdDlL
;u = top left
;U = top
;r = top Right
;R = Right
;d = bottom right
;D = bottom
;l = bottom Left
;L = Left
pushRegs D2-D5/A0
MOVEQ #0,D0
MOVE.L A0,A1
MOVE.L A1,A2
SUBA.L #ROWLENGTH+2,A1		;POINTS ABOVE

MOVE.B (A1),D1
MOVE.B (A2),D2

CMP.B #1,D1
BNE .noUpper
BSET #6,D0
bra .next
.noUpper:
BCLR #6,D0
.next:
CheckLower:
CMP.B #1,D2
BNE .noLower
BSET #2,D0
bra .next
.noLower:
BCLR #2,D0
.next:

SUBA.L #1,A0	;left
SUBA.L #1,A1	;upper-left
SUBA.L #1,A2	;lower-left

MOVE.B (A1),D1
MOVE.B (A2),D2
MOVE.B (A0),D3
CheckUpperLeft:
CMP.B #1,D1
BNE .noUpperLeft
BSET #7,D0
bra .next
.noUpperLeft:
BCLR #7,D0
.next:

CheckLowerLeft:
CMP.B #1,D2
BNE .noLowerLeft
BSET #1,D0
bra .next
.noLowerLeft:
BCLR #1,D0
.next:

CheckLeft:
CMP.B #1,D3
BNE .noLeft
BSET #0,D0
bra .next
.noLeft:
BCLR #0,D0
.next:

MOVE.B (A1),D1
MOVE.B (A2),D2
MOVE.B (A0),D3

CheckUpperRight:
CMP.B #1,D1
BNE .noUpperRight
BSET #5,D0
bra .next
.noUpperRight:
BCLR #5,D0
.next:

CheckLowerRight:
CMP.B #1,D2
BNE .noLowerRight
BSET #3,D0
bra .next
.noLowerRight:
BCLR #3,D0
.next:

CheckRight:
CMP.B #1,D3
BNE .noRight
BSET #4,D0
bra .next
.noRight:
BCLR #4,D0
.next:
popRegs D2-D5/A0
rts

Conway_Print:
;input: A3 = base address of tilemap
MOVE.B (A3)+,D0
CMP.B #255,D0
BEQ .done
CMP.B #2,D0
BEQ .skip
;else, print
JSR Conway_PrintChar
.skip
BRA Conway_Print
.done
rts

Conway_PrintChar:				;Show D0 to screen
moveM.l d0-d7/a0-a7,-(sp)
and.l #\$FF,d0			;Keep only 1 byte
Move.L  #\$40000003,d5	;top 4=write, bottom \$3=Cxxx range
MOVEQ #0,D4				;Tilemap at \$C000+

Move.B (Cursor_Y),D4
rol.L #8,D4				;move \$-FFF to \$-FFF----
rol.L #8,D4
rol.L #7,D4				;2 bytes per tile * 64 tiles per line

Move.B (Cursor_X),D4
rol.L #8,D4				;move \$-FFF to \$-FFF----
rol.L #8,D4
rol.L #1,D4				;2 bytes per tile

MOVE.L	D5,(VDP_ctrl)	; C00004 write next character to VDP
MOVE.W	D0,(VDP_data)	; C00000 store next word of name data

move.b (Cursor_X),d0
cmp.b #39,d0
bls .nextpixel_Xok
jsr NewLine			;If we're at end of line, start newline
.nextpixel_Xok:
moveM.l (sp)+,d0-d7/a0-a7
rts

;don't forget, these are in ROM so we can't write to them directly.
;instead, they will be copied to ram and worked with from there.
Conway_Tilemap:	;(screenwidth + 2) by (screenheight+2)
DC.B \$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$01,\$01,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$01,\$01,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$01,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$01,\$00,\$00,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$01,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$01,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$01,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$01,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
DC.B \$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02
DC.B 255
EVEN
Conway_Backup_Tilemap:	;(screenwidth + 2) by (screenheight+2)
DC.B \$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02
rept 30
DC.B \$02,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$00,\$02
endr
DC.B \$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02,\$02
DC.B 255
EVEN
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
NewLine:
clr.b (Cursor_X)			;Zero X
rts

LDIR:	;COPY D1 BYTES FROM A3 TO A2
move.b (a3)+,(a2)+
DBRA D1,LDIR
rts

DefineTiles:						;Copy D1 bytes of data from A0 to VDP memory D2
jsr prepareVram					;Calculate the memory location we want to write
.again:								; the tile pattern definitions to
move.l (a0)+,(VDP_data)
dbra d1,.again
rts

prepareVram:							;To select a memory location D2 we need to calculate
;the command byte... depending on the memory location
pushall								;\$7FFF0003 = Vram \$FFFF.... \$40000000=Vram \$0000
move.l d2,d0
and.w #%1100000000000000,d0		;Shift the top two bits to the far right
rol.w #2,d0

and.l #%0011111111111111,d2	    ; shift all the other bits left two bytes
rol.l #8,d2
rol.l #8,d2

or.l d0,d2
or.l #\$40000000,d2				;Set the second bit from the top to 1
;#%01000000 00000000 00000000 00000000
move.l d2,(VDP_ctrl)
popallRTS:
popall
rts

Graphics:
DC.L \$0000000F,\$0000000F,\$0000000F,\$0000000F,\$0000000F,\$0000000F,\$0000000F,\$FFFFFFFF
DC.L \$FFFFFFFF,\$FFFFFFFF,\$FFFFFFFF,\$FFFFFFFF,\$FFFFFFFF,\$FFFFFFFF,\$FFFFFFFF,\$FFFFFFFF
GraphicsEnd:

VDPSettings:
DC.B \$04 ; 0 mode register 1											---H-1M-
DC.B \$04 ; 1 mode register 2											-DVdP---
DC.B \$30 ; 2 name table base for scroll A (A=top 3 bits)				--AAA--- = \$C000
DC.B \$3C ; 3 name table base for window (A=top 4 bits / 5 in H40 Mode)	--AAAAA- = \$F000
DC.B \$07 ; 4 name table base for scroll B (A=top 3 bits)				-----AAA = \$E000
DC.B \$6C ; 5 sprite attribute table base (A=top 7 bits / 6 in H40)		-AAAAAAA = \$D800
DC.B \$00 ; 6 unused register											--------
DC.B \$00 ; 7 background color (P=Palette C=Color)						--PPCCCC
DC.B \$00 ; 8 unused register											--------
DC.B \$00 ; 9 unused register											--------
DC.B \$FF ;10 H interrupt register (L=Number of lines)					LLLLLLLL
DC.B \$00 ;11 mode register 3											----IVHL
DC.B \$81 ;12 mode register 4 (C bits both1 = H40 Cell)					C---SIIC
DC.B \$37 ;13 H scroll table base (A=Top 6 bits)							--AAAAAA = \$FC00
DC.B \$00 ;14 unused register											--------
DC.B \$02 ;15 auto increment (After each Read/Write)						NNNNNNNN
DC.B \$01 ;16 scroll size (Horiz & Vert size of ScrollA & B)				--VV--HH = 64x32 tiles
DC.B \$00 ;17 window H position (D=Direction C=Cells)					D--CCCCC
DC.B \$00 ;18 window V position (D=Direction C=Cells)					D--CCCCC
DC.B \$FF ;19 DMA length count low										LLLLLLLL
DC.B \$FF ;20 DMA length count high										HHHHHHHH
DC.B \$00 ;21 DMA source address low										LLLLLLLL
DC.B \$00 ;22 DMA source address mid										MMMMMMMM
DC.B \$80 ;23 DMA source address high (C=CMD)							CCHHHHHH
VDPSettingsEnd:
even```
Output:

## ABAP

Works with: ABAP version 7.4 SP05 or Above only

For the proposed task use 10,9;10,10;10,11 on screen field P_POS. Can be left blank for random filling

```*&---------------------------------------------------------------------*
*& Report ZCONWAYS_GAME_OF_LIFE
*&---------------------------------------------------------------------*
*& by Marcelo Bovo
*&---------------------------------------------------------------------*
report zconways_game_of_life line-size 174 no standard page heading
line-count 40.

parameters: p_char type c default '#',
p_pos  type string.

class lcl_game_of_life definition.

public section.

data: x_max      type i value 174,
y_max      type i value 40,
character  type c value abap_true,
x          type i,
y          type i,
pos        type string,
offlimits  type i value 9998,
grid(9999) type c. " every X_MAX characters on grid equals one line on screen

data: o_random_y type ref to cl_abap_random_int,
o_random_x type ref to cl_abap_random_int.

methods: constructor,
play,
initial_position,
initial_grid,
write,
change_grid.

endclass.

class lcl_game_of_life implementation.
method constructor.
o_random_y = cl_abap_random_int=>create( seed = cl_abap_random=>create( conv i( sy-uzeit ) )->intinrange( low = 1 high = 999999 )
min  = 1
max = y_max ).

o_random_x = cl_abap_random_int=>create( seed = cl_abap_random=>create( conv i( |{ sy-datum(4) }{ sy-uzeit }| ) )->intinrange( low = 1 high = 999999 )
min  = 1
max = x_max ).

endmethod.

method play.

"fill initial data ramdonly if user hasnt typed any coordenates
if pos is initial.
initial_position( ).
endif.

initial_grid( ).

write( ).

endmethod.

method initial_position.
do cl_abap_random_int=>create( "seed = conv i( sy-uzeit )
min  = 50
max = 800 )->get_next( ) times.
data(lv_index) = sy-index.

x = o_random_x->get_next( ).
y = o_random_y->get_next( ).

p_pos = |{ p_pos }{ switch char1( lv_index when '1' then space else ';' ) }{ y },{ x }|.
enddo.
endmethod.

method initial_grid.

"Split coordenates
split p_pos at ';' into table data(lt_pos_inicial) .

sort lt_pos_inicial.

loop at lt_pos_inicial assigning field-symbol(<pos_inicial>).

split <pos_inicial> at ',' into data(y_char) data(x_char).

x = x_char.
y = y_char.

"Ensure maximum coordenates are not surpassed
x = cond #( when x <= x_max then x
else o_random_x->get_next( ) ).

y = cond #( when y <= y_max then y
else o_random_y->get_next( ) ).

"Write on string grid
"Every x_max lines represent one line(Y) on the grid
data(grid_xy) = ( x_max * y ) + x - x_max - 1.
grid+grid_xy(1) = character.

endloop.

endmethod.

method write.

"Write every line on screen
do y_max times.
data(lv_index) = sy-index - 1.

"Write whole line(current line plus number of maximum X characters)
data(grid_xy) = ( lv_index * x_max ).

write / grid+grid_xy(x_max) no-gap.

if grid+grid_xy(x_max) is initial.
skip.
endif.

enddo.

change_grid( ).

endmethod.

method change_grid.

data(grid_aux) = grid.
clear grid_aux.
data(grid_size) = strlen( grid ).

"Validate neighbours based on previous written grid
"ABC
"D.F
"GHI
do grid_size + x_max times.

"Doens't write anything beyond borders
check sy-index <= x_max * y_max.

data(grid_xy) = sy-index - 1.

data(neighbours) = 0.

"Current Line neighbours
data(d) = grid_xy - 1.
data(f) = grid_xy + 1.

"Line above neighbours
data(b) = grid_xy - x_max.
data(a) = b - 1.
data(c) = b + 1.

"Line Bellow neighbours
data(h) = grid_xy + x_max.
data(g) = h - 1.
data(i) = h + 1.

"Previous Neighbours
neighbours += cond #( when a < 0 then 0 else cond #( when grid+a(1) is not initial then 1 else 0 )   ).
neighbours += cond #( when b < 0 then 0 else cond #( when grid+b(1) is not initial then 1 else 0 )   ).
neighbours += cond #( when c < 0 then 0 else cond #( when grid+c(1) is not initial then 1 else 0 )   ).
neighbours += cond #( when d < 0 then 0 else cond #( when grid+d(1) is not initial then 1 else 0 )   ).

"Next Neighbours
neighbours += cond #( when f > grid_size then 0 else cond #( when grid+f(1) is not initial then 1 else 0 )   ).
neighbours += cond #( when g > grid_size then 0 else cond #( when grid+g(1) is not initial then 1 else 0 )   ).
neighbours += cond #( when h > grid_size then 0 else cond #( when grid+h(1) is not initial then 1 else 0 )   ).
neighbours += cond #( when i > grid_size then 0 else cond #( when grid+i(1) is not initial then 1 else 0 )   ).

grid_aux+grid_xy(1) = cond #( when  neighbours = 3 or (  neighbours = 2  and grid+grid_xy(1) = character )
then character
else space ).

enddo.

grid = grid_aux.

endmethod.
endclass.

start-of-selection.

set pf-status 'STANDARD_FULLSCREEN'. "Use &REFRESH button with F8 Shortcut to go to next generation

data(lo_prog) = new lcl_game_of_life( ).
lo_prog->character = p_char.
lo_prog->pos = p_pos.
lo_prog->play( ).

at user-command.

case sy-ucomm.
when 'REFR' or '&REFRESH'.
sy-lsind = 1. "Prevents LIST_TOO_MANY_LEVELS DUMP
lo_prog->write( ).
when others.
leave list-processing.
endcase.
```

## ACL2

```(defun print-row (row)
(if (endp row)
nil
(prog2\$ (if (first row)
(cw "[]")
(cw "  "))
(print-row (rest row)))))

(defun print-grid-r (grid)
(if (endp grid)
nil
(progn\$ (cw "|")
(print-row (first grid))
(cw "|~%")
(print-grid-r (rest grid)))))

(defun print-line (l)
(if (zp l)
nil
(prog2\$ (cw "-")
(print-line (1- l)))))

(defun print-grid (grid)
(progn\$ (cw "+")
(print-line (* 2 (len (first grid))))
(cw "+~%")
(print-grid-r grid)
(cw "+")
(print-line (* 2 (len (first grid))))
(cw "+~%")))

(defun neighbors-row-r (row)
(if (endp (rest (rest row)))
(list (if (first row) 1 0))
(cons (+ (if (first row) 1 0)
(if (third row) 1 0))
(neighbors-row-r (rest row)))))

(defun neighbors-row (row)
(cons (if (second row) 1 0)
(neighbors-row-r row)))

(defun zip+ (xs ys)
(if (or (endp xs) (endp ys))
(append xs ys)
(cons (+ (first xs) (first ys))
(zip+ (rest xs) (rest ys)))))

(defun counts-row (row)
(if (endp row)
nil
(cons (if (first row) 1 0)
(counts-row (rest row)))))

(defun neighbors-r (grid prev-counts curr-counts next-counts
prev-neighbors curr-neighbors
next-neighbors)
(if (endp (rest grid))
(list (zip+ (zip+ prev-counts
prev-neighbors)
(neighbors-row (first grid))))
(cons (zip+ (zip+ (zip+ prev-counts next-counts)
(zip+ prev-neighbors next-neighbors))
curr-neighbors)
(neighbors-r (rest grid)
curr-counts
next-counts
(counts-row (third grid))
curr-neighbors
next-neighbors
(neighbors-row (third grid))))))

(defun neighbors (grid)
(neighbors-r grid
nil
(counts-row (first grid))
(counts-row (second grid))
nil
(neighbors-row (first grid))
(neighbors-row (second grid))))

(defun life-rules-row (life neighbors)
(if (or (endp life) (endp neighbors))
nil
(cons (or (and (first life)
(or (= (first neighbors) 2)
(= (first neighbors) 3)))
(and (not (first life))
(= (first neighbors) 3)))
(life-rules-row (rest life) (rest neighbors)))))

(defun life-rules-r (grid neighbors)
(if (or (endp grid) (endp neighbors))
nil
(cons (life-rules-row (first grid) (first neighbors))
(life-rules-r (rest grid) (rest neighbors)))))

(defun conway-step (grid)
(life-rules-r grid (neighbors grid)))

(defun conway (grid steps)
(if (zp steps)
nil
(progn\$ (print-grid grid)
(conway (conway-step grid) (1- steps)))))
```
Output:
```+------+
|  []  |
|  []  |
|  []  |
+------+
+------+
|      |
|[][][]|
|      |
+------+
+------+
|  []  |
|  []  |
|  []  |
+------+```

```WITH Ada.Text_IO;  USE Ada.Text_IO;

PROCEDURE Life IS
SUBTYPE Cell IS Natural RANGE 0 .. 1;

TYPE Petri_Dish IS ARRAY (Positive RANGE <>, Positive RANGE <>) OF Cell;

PROCEDURE Step (Gen : IN OUT Petri_Dish) IS
Above       : ARRAY (Gen'Range (2)) OF Cell := (OTHERS => 0);
Left, This  : Cell;
BEGIN
FOR I IN Gen'First (1) + 1 .. Gen'Last (1) - 1 LOOP
Left := 0;
FOR J IN Gen'First (2) + 1 .. Gen'Last (2) - 1 LOOP
This := (CASE Above (J - 1) + Above (J) + Above (J + 1) +
Left			    + Gen (I, J + 1) +
Gen (I + 1, J - 1) + Gen (I + 1, J) 	+ Gen (I + 1, J + 1) IS
WHEN 2      => Gen (I, J),
WHEN 3      => 1,
WHEN OTHERS => 0);
Above (J - 1):= Left;
Left         := Gen (I, J);
Gen (I, J) 	 := This;
END LOOP;
Above (Above'Last - 1) := Left;
END LOOP;
END Step;

PROCEDURE Put (Gen : Petri_Dish) IS
BEGIN
FOR I IN Gen'Range (1) LOOP
FOR J IN Gen'Range (2) LOOP
Put ( if Gen (I, J) = 0 then " " else "#");
END LOOP;
New_Line;
END LOOP;
END Put;

Blinker : Petri_Dish := (2 .. 4 => (0, 0, 1, 0, 0), 1 | 5 => (0, 0, 0, 0, 0));
Glider  : Petri_Dish (1..6,1..11):= (2 => (3 => 1, others => 0),
3 => (4 => 1, others => 0),
4 => (2|3|4=>1, others => 0),
others => (others => 0));
PROCEDURE Put_And_Step_Generation (N : Positive; Name : String; P : IN OUT Petri_Dish) IS
BEGIN
FOR Generation IN 1 .. N LOOP
Put_Line (Name & Generation'Img);
Put (P);
Step (P);
END LOOP;
END Put_And_Step_Generation;

BEGIN
Put_And_Step_Generation (5, "Glider", Glider);
END Life;
```

The solution uses one cell thick border around square Petri dish as uninhabited dire land. This simplifies computations of neighborhood. Sample output contains 3 generations of the blinker and 5 of the glider:

Output:
```Blinker 1

#
#
#

###

#
#
#

Glider 1

#
#
###

Glider 2

# #
##
#

Glider 3

#
# #
##

Glider 4

#
##
##

Glider 5

#
#
###

```

## Amazing Hopper

El programa genera el algoritmo en modo texto.

Adaptado del programa "Conway's Game of Life" de Vishal Nagda, en Hithub

https://github.com/vishalnagda1/CONWAYs-Game-of-Life-C/blob/master/game_of_life.c

```#include <jambo.h>

#define SIZER   90
#define SIZEC   120

Main

Dim (SIZER, SIZEC) as zeros 'grid, neighbour_count'
Dim (SIZER, SIZEC) as fill '" ",disp grid'

c=0, Let( c := Utf8(Chr(254)))

moi=0, moj=0, poi=0, poj=0

m={}
Set ' 0,1,1 ' Apnd row 'm'
Set ' 1,1,0 ' Apnd row 'm'
Set ' 0,1,0 ' Apnd row 'm'
[44:46, 59:61] Set 'm', Put 'grid'
Clr all marks

i=0, j=0
Tok sep '""'
Locate (1,1)
Loop
i=1
Iterator ( ++i, Less equal(i,SIZER),\
j=1, Iterator ( ++j, Less equal(j,SIZEC), \
Set 'i,j', Gosub 'Count NBR', [i,j], Put 'neighbour_count' ) )

i=1
Loop if( Less equal(i,SIZER) )
j=1
Loop if( Less equal(j,SIZEC) )
[i,j]
If ( Get 'grid' )
Get 'neighbour_count'
When ( Out of range including '1,4' ) {
Set '0," "', Put 'disp grid', Put 'grid'
}
Else
Get 'neighbour_count'
When ( Is equal to '3' ) {
Set '1,c', Put 'disp grid', Put 'grid'
}
End If
++j
Back
++i
Back

Clr all marks
Print table 'disp grid'
Break if ( Key pressed )

Back
Pause
End

Subrutines

Define 'Count NBR, i, j'
n_count = 0

When ( Must be( Minus one 'i' ---Backup to 'moi'---, Minus one 'j' ---Backup to 'moj'--- ) ) {

When ( [moi,moj]Get 'grid' ) {
++n_count
}
}

Plus one 'j', Move to 'poj'

When ( moi ) {
When ( [ moi, j ] Get 'grid' ) {
++n_count
}
When ( Less equal( poj, SIZEC )) {
When ( [ moi, poj] Get 'grid' ) {
++n_count
}
}
}

When ( moj ) {
When( [i, moj] Get 'grid' )  {
++n_count
}
}

When ( Less equal ( poj, SIZEC ) ){

When( [i, poj] Get 'grid' ) {
++n_count
}
}

When ( Less equal (Plus one 'i' ---Backup to 'poi'---, SIZER ) ) {

When ( [ poi, j] Get 'grid' ) {
++n_count
}

When ( Less equal ( poj, SIZEC) ) {
When ( [poi, poj] Get 'grid' ) {
++n_count
}
}

When ( moj ){
When ([poi, moj] Get 'grid' ){
++n_count
}
}
}
Return 'n_count'
```
Output:
```La llamada se realiza desde terminal, con el programa "rxvt" de Linux, para adaptar la terminal a los pixeles y dimensiones adecuados.

rxvt -g 270x100 -fn "xft:FantasqueSansMono-Regular:pixelsize=3" -e hopper jm/gamelife.jambo
```

Version 2

Me di cuenta de que la subrutina "Count NBR" era un poco lenta, y además, una función que cuente los vecinos en un radio dado, me es útil para hacer juegos, por lo que incluí esa función dentro de las funciones de HOPPER.

Además, reescribí el programa "a la Hopper", como debió ser desde un principio.

```#include <jambo.h>
#define SIZER   90
#define SIZEC   120

Main
Cls
Hide cursor

Dim (SIZER, SIZEC), as zeros 'grid, neighbour_count'
Dim (SIZER, SIZEC), as fill '" ",disp grid'

c=0 , Let( c := Utf8(Chr(254)))

m={}
Set ' 0,1,1 ' Apend row to 'm'
Set ' 1,1,0 ' Apend row to 'm'
Set ' 0,1,0 ' Apend row to 'm'

[44:46, 59:61] Set 'm', Put 'grid'

Clr all marks

Tok sep '""'

Locate (1,1)
Loop
i=1
Iterator ( ++i, Less equal(i,SIZER),\
j=1, Iterator ( ++j, Less equal(j,SIZEC), \
[i,j], Neighbour count (grid,radio), Put 'neighbour_count' ) )

Cartesian ( Greater equal(grid, 1)---Back up to 'r'--- Mul by 'neighbour_count';\
Out of range including '1,4' )
Get range, Set '0," "', Put 'disp grid', Put 'grid', Forget

Cartesian ( Not( r ); Mul by 'neighbour_count'; Is equal to '3' )
Get range, Set '1,c', Put 'disp grid', Put 'grid', Forget
Clr range

Clr all marks
Print table 'disp grid'

Break if ( Key pressed )
Back
Pause
Show cursor
End
```
Output:

La salida es la misma, pero ahora va mucho más rápido... parecen estrellitas explotando :D

## APL

APL \ 1130 example (very old APL dialect via simulator)

From: APL \ 1130 Samples

The following APL \ 1130 code will need APL385 font installed to display correctly.

```      ∇LIFE[⎕]∇
[0]   NG←LIFE CG;W
[1]   W←CG+(¯1⊖CG)+(1⊖CG)+(¯1⌽CG)+(1⌽CG)
[2]   W←W+(1⊖1⌽CG)+(¯1⊖1⌽CG)+(1⊖¯1⌽CG)+(¯1⊖¯1⌽CG)
[3]   NG←(3=W)+(CG∧4=W)
∇
RP←5 5⍴0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 1 0 0
RP
0 0 0 0 0
0 0 1 1 0
0 1 1 0 0
0 0 1 0 0
0 0 0 0 0
LIFE RP
0 0 0 0 0
0 1 1 1 0
0 1 0 0 0
0 1 1 0 0
0 0 0 0 0
LIFE LIFE RP
0 0 1 0 0
0 1 1 0 0
1 0 0 1 0
0 1 1 0 0
0 0 0 0 0
```

## AppleScript

This handler creates and returns a "universe" script object initialised with given "seed" text and dimensions. For convenience, the seed text's visible characters can be anything, the set-up code itself replacing them with "■" characters. The use of the returned universe is demo'd later.

```use AppleScript version "2.4" -- OS X 10.10 (Yosemite) or later
use framework "Foundation" -- For the regex at the top of newUniverse()

-- The characters to represent the live and dead cells.
property live : "■" -- character id 9632 (U+25A0).
-- Infinite universes are expensive to maintain, so only a local region of universe is represented here.
-- Its invisible border is a wall of "dead" cells one cell deep, lined with a two-cell buffer layer into which
-- objects nominally leaving the region can disappear without being seen to hit the wall or bouncing back.
property borderThickness : 3

on newUniverse(seed, {w, h})
-- Replace every visible character in the seed text with "■" and every horizontal space with a space.
set seed to current application's class "NSMutableString"'s stringWithString:(seed)
set regex to current application's NSRegularExpressionSearch
tell seed to replaceOccurrencesOfString:("\\S") withString:(live) options:(regex) range:({0, its |length|()})
tell seed to replaceOccurrencesOfString:("\\h") withString:(dead) options:(regex) range:({0, its |length|()})
-- Ensure the universe dimensions are at least equal to the number of lines and the length of the longest.
set seedLines to paragraphs of (seed as text)
set lineCount to (count seedLines)
if (lineCount > h) then set h to lineCount
set seedWidth to 0
repeat with thisLine in seedLines
set lineLength to (count thisLine)
if (lineLength > seedWidth) then set seedWidth to lineLength
end repeat
if (seedWidth > w) then set w to seedWidth

-- Get a new universe.
script universe
-- State lists. These will contain or be lists of 0s and 1s and will include the border cells.
property newState : {}
property previousState : {}
property currentRow : {}
property rowAbove : {}
property rowBelow : {}
property replacementRow : {}
-- Equivalent text lists. These will only cover what's in the bounded region.
property lineList : {}
property characterGrid : {}
property currentLineCharacters : {}
-- Precalculated border cell indices.
property rightInnerBuffer : borderThickness + w + 1
property rightOuterBuffer : rightInnerBuffer + borderThickness - 2
property bottomInnerBuffer : borderThickness + h + 1
property bottomOuterBuffer : bottomInnerBuffer + borderThickness - 2
-- Generation counter.
property counter : 0
-- Temporary lists used in the set-up.
property rowTemplate : {}
property lineCharacterTemplate : {}

-- Built-in handlers. Both return text representing a universe state and
-- a boolean indicating whether or not the state's the same as the previous one.
on nextState()
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ""
copy newState to previousState
set currentRow to beginning of my previousState
set rowBelow to item 2 of my previousState
-- Check each occupiable cell in each occupiable row of the 'previousState' grid, including the buffer cells.
-- If warranted by the number of live neighbours, edit the equivalent cell in 'newState' and,
-- if within the region's bounds, change the corresponding text character too.
repeat with r from 2 to bottomOuterBuffer
set rowAbove to currentRow
set currentRow to rowBelow
set rowBelow to item (r + 1) of my previousState
set replacementRow to item r of my newState
set rowCrossesRegion to ((r comes after borderThickness) and (r comes before bottomInnerBuffer))
if (rowCrossesRegion) then set currentLineCharacters to item (r - borderThickness) of my characterGrid
set lineChanged to false
repeat with c from 2 to rightOuterBuffer
set liveNeighbours to ¬
(item (c - 1) of my rowAbove) + (item c of my rowAbove) + (item (c + 1) of my rowAbove) + ¬
(item (c - 1) of my currentRow) + (item (c + 1) of my currentRow) + ¬
(item (c - 1) of my rowBelow) + (item c of my rowBelow) + (item (c + 1) of my rowBelow)
if (item c of my currentRow is 1) then
if ((liveNeighbours < 2) or (liveNeighbours > 3)) then
set item c of my replacementRow to 0
if ((c comes after borderThickness) and (c comes before rightInnerBuffer) and (rowCrossesRegion)) then
set item (c - borderThickness) of my currentLineCharacters to dead
set lineChanged to true
else if ((c is 3) or (c is rightOuterBuffer) or (r is 3) or (r is bottomOuterBuffer)) then
-- This is a fudge to dissolve "bombers" entering the buffer zone.
set item (c - 1) of my replacementRow to -1
set item c of item (r - 1) of my newState to -1
end if
end if
else if (liveNeighbours is 3) then
set item c of my replacementRow to 1
if ((c comes after borderThickness) and (c comes before rightInnerBuffer) and (rowCrossesRegion)) then
set item (c - borderThickness) of my currentLineCharacters to live
set lineChanged to true
end if
end if
end repeat
if (lineChanged) then set item (r - borderThickness) of my lineList to currentLineCharacters as text
end repeat
set AppleScript's text item delimiters to astid
set counter to counter + 1
set last item of my lineList to "Generation " & counter

return currentState()
end nextState

on currentState()
set noChanges to (newState = previousState)
if (noChanges) then ¬
set last item of my lineList to (last item of my lineList) & " (all dead, still lifes, or left the universe)"
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to return
set stateText to lineList as text
set AppleScript's text item delimiters to astid

return {stateText, noChanges}
end currentState
end script

-- Set the universe's start conditions.
-- Build a row template list containing w + 2 * borderThickness zeros
-- and a line character template list containing w 'dead' characters.
repeat (borderThickness * 2) times
set end of universe's rowTemplate to 0
end repeat
repeat w times
set end of universe's rowTemplate to 0
set end of universe's lineCharacterTemplate to dead
end repeat
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ""
set blankLine to universe's lineCharacterTemplate as text

-- Use the templates to populate lists representing the universe's conditions.
-- Firstly the top border rows ('newState' list only).
repeat borderThickness times
copy universe's rowTemplate to end of universe's newState
end repeat
-- Then enough rows and text lines to centre the input roughly halfway down the grid.
set headroom to (h - lineCount) div 2
copy universe's rowTemplate to end of universe's newState
copy universe's lineCharacterTemplate to end of universe's characterGrid
set end of universe's lineList to blankLine
end repeat
-- Then the rows and lines representing the input itself, centring it roughly halfway across the grid.
set textInset to (w - seedWidth) div 2
set stateInset to textInset + borderThickness
repeat with thisLine in seedLines
copy universe's rowTemplate to universe's currentRow
copy universe's lineCharacterTemplate to universe's currentLineCharacters
repeat with c from 1 to (count thisLine)
set thisCharacter to character c of thisLine
set item (textInset + c) of universe's currentLineCharacters to thisCharacter
set item (stateInset + c) of universe's currentRow to (thisCharacter is live) as integer
end repeat
set end of universe's newState to universe's currentRow
set end of universe's characterGrid to universe's currentLineCharacters
set end of universe's lineList to universe's currentLineCharacters as text
end repeat
set AppleScript's text item delimiters to astid
-- Then the rows and lines beneath and the bottom border.
repeat (h - (headroom + lineCount)) times
copy universe's rowTemplate to end of universe's newState
copy universe's lineCharacterTemplate to end of universe's characterGrid
set end of universe's lineList to blankLine
end repeat
repeat borderThickness times
copy universe's rowTemplate to end of universe's newState
end repeat
-- Add a generation counter display line to the end of the line list.
set end of universe's lineList to "Generation 0"
-- Lose the no-longer-needed template lists.
set universe's rowTemplate to missing value
set universe's lineCharacterTemplate to universe's rowTemplate

return universe
end newUniverse
```

In conjunction with the above, this fulfills the task as set:

```on RCTask(seed, dimensions, maxGenerations)
-- Create a universe and start a list with its initial state.
set universe to newUniverse(seed, dimensions)
set {stateText} to universe's currentState()
set output to {stateText}
-- Add successive states to the list.
repeat maxGenerations times
set {stateText, noChanges} to universe's nextState()
set end of output to stateText
if (noChanges) then exit repeat
end repeat
-- Coerce the states to a single text, each followed by a short line of dashes.
set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to linefeed & "-----" & linefeed & linefeed
set output to (output as text) & linefeed & "-----"
set AppleScript's text item delimiters to astid

return output

-- Return text containing the original and three generations of a "blinker" in a 3 x 3 grid.
```
Output:
```"
■■■

Generation 0
-----

■
■
■
Generation 1
-----

■■■

Generation 2
-----

■
■
■
Generation 3
-----"
```

This alternative to the task code runs an animation of a "Gosper glider gun" in TextEdit, the AppleScriptable text editor included with macOS. The animation's achieved by replacing the entire text of a document with successive universe states. It's faster than it sounds, but the universe size specified shouldn't be much greater than 150 x 150 with current machines.

```on runGame(seed, dimensions, maxGenerations)
-- Create an RTF file set up for Menlo-Regular 12pt, half spacing, and a reasonable window size.
set fontName to "Menlo-Regular"
set fontSize to 12
set viewScale to fontSize * 12.4 -- Seems to work well.
set {w, h} to dimensions

{\\fonttbl\\f0\\fnil\\fcharset0 " & fontName & ";}
{\\colortbl;\\red255\\green255\\blue255;}
{\\*\\expandedcolortbl;;}
\\margl1440\\margr1440\\vieww" & (w * viewScale as integer) & "\\viewh" & ((h + 1) * viewScale as integer) & "\\viewkind0
\\pard\\sl120\\slmult1\\pardirnatural\\partightenfactor0
\\f0\\fs" & (fontSize * 2) & " \\cf0  }" -- Contains a space as body text for TextEdit to see as an 'attribute run'.
set RTFFile to ((path to temporary items as text) & "Conway's Game of Life.rtf") as «class furl»
set fRef to (open for access RTFFile with write permission)
try
set eof fRef to 0
write RTFHeaders as «class utf8» to fRef
close access fRef
on error errMsg number errNum
close access fRef
error errMsg number errNum
end try
-- Open the file as a document in TextEdit.
tell application "TextEdit"
activate
tell document "Conway's Game of Life.rtf" to if (it exists) then close saving no
set CGoLDoc to (open RTFFile)
end tell

-- Create a universe and display its initial state in the document window.
set universe to newUniverse(seed, dimensions)
set {stateText} to universe's currentState()
tell application "TextEdit" to set CGoLDoc's first attribute run to stateText
-- Get and display successive states.
repeat maxGenerations times
set {stateText, noChanges} to universe's nextState()
tell application "TextEdit" to set CGoLDoc's first attribute run to stateText
if (noChanges) then exit repeat
end repeat
end runGame

set GosperGliderGun to "                        *
* *
**      **            **
*   *    **            **
**        *     *   **
**        *   * **    * *
*     *       *
*   *
**"
-- Run for 500 generations in a 100 x 100 universe.
runGame(GosperGliderGun, {100, 100}, 500)
```

## ARM Assembly

Works with: TI-Nspire
```	.string "PRG"

lcd_ptr .req r4
active_fb .req r5
inactive_fb .req r6
offset_r .req r7
backup_fb .req r8

@ start
push {r4-r10, r12, lr}

ldr lcd_ptr, =0xC0000000 @ address of the LCD controller
ldrh r0, [offset_r, #6] @ 0xffff is already in memory because -1 is in the offsets table
str r0, [lcd_ptr, #0x200] @ set up paletted colors: 1 is black, 0 is white

ldr r2, [lcd_ptr, #0x18] @ load lcd configuration
bic r2, #14
orr r2, #6 @ Set color mode to 8 bpp, paletted
str r2, [lcd_ptr, #0x18]

ldr backup_fb, [lcd_ptr, #0x10] @ Save address of OS framebuffer

@ allocate a buffer for game state / framebuffer
ldr r0, =153600 @ 320 * 240 * 2
svc #5 @ malloc
push {r0}
orr inactive_fb, r0, #7

@ fill buffer with random ones and zeroes
ldr r10, =76800
mov r9, #0
1:	subs r10, r10, #1
strb r9, [active_fb, r10] @ zero other framebuffer
svc #206 @ rand syscall
and r0, r0, #1
strb r0, [inactive_fb, r10]
bne 1b

@ set first and last rows to zero
mov r2, #320
mov r1, #0
mov r0, inactive_fb
push {r1,r2}
svc #7 @ memset
pop {r1,r2}
ldr r3, =76480
svc #7

@ beginning of main loop, swap framebuffers
3:	ldr r0, =76480 @ 320 * 239
str inactive_fb, [lcd_ptr, #0x10]
mov inactive_fb, active_fb
ldr active_fb, [lcd_ptr, #0x10]

@ per-pixel loop
2:	mov r1, #16 @ 8 * 2
mov r2, #0
sub r0, #1

@ loop to count up neighboring living cells
1:	subs r1, #2
ldrsh r3, [offset_r, r1] @ cant use lsl #1
ldrb r3, [active_fb, r3]
bne 1b @ at end of loop, r1 and r3 can be discarded

@ decides whether the cell should live or die based on neighbors
ldrb r1, [active_fb, r0]
teq r2, #3
moveq r1, #1
teqne r2, #4
movne r1, #0
strb r1, [inactive_fb, r0]
teq r0, #320
bne 2b

@ checks if the escape key is pressed
ldr r0, =0x900E001C
ldr r1, [r0]
tst r1, #0x80
beq 3b

str backup_fb, [lcd_ptr, #0x10] @ restores OS framebuffer

pop {r0}
svc #6 @ free buffer
pop {r4-r10, r12, pc}
offsets:
.hword -321, -320, -319, -1, 1, 319, 320, 321```

## AutoHotkey

ahk discussion

```rows := cols := 10                               ; set grid dimensions
i = -1,0,1, -1,1, -1,0,1                         ; neighbors' x-offsets
j = -1,-1,-1, 0,0, 1,1,1                         ; neighbors' y-offsets
StringSplit i, i, `,                             ; make arrays
StringSplit j, j, `,

Loop % rows {                                    ; setup grid of checkboxes
r := A_Index, y := r*17-8                     ; looks good in VISTA
Loop % cols {
c := A_Index, x := c*17-5
Gui Add, CheckBox, x%x% y%y% w17 h17 vv%c%_%r% gCheck
}
}
Gui Add, Button, % "x12 w" x+2, step             ; button to step to next generation
Gui Show
Return

Check:
GuiControlGet %A_GuiControl%                  ; manual set of cells
Return

ButtonStep:                                      ; move to next generation
Loop % rows {
r := A_Index
Loop % cols {
c := A_Index, n := 0
Loop 8                                  ; w[x,y] <- new states
x := c+i%A_Index%, y := r+j%A_Index%, n += 1=v%x%_%y%
GuiControl,,v%c%_%r%,% w%c%_%r% := v%c%_%r% ? n=2 || n=3 : n=3
}
}
Loop % rows {                                 ; update v[x,y] = states
r := A_Index
Loop % cols
v%A_Index%_%r% := w%A_Index%_%r%
}
Return

GuiClose:                                        ; exit when GUI is closed
ExitApp
```

## AWK

50x20 grid (hardcoded) with empty border, filled with random cells, running for 220 generations, using ANSI escape-codes for output to terminal:

```BEGIN {
c=220; d=619; i=10000;
printf("\033[2J");      # Clear screen
while(i--) m[i]=0;
while(d--) m[int(rand()*1000)]=1;

while(c--){
for(i=52; i<=949; i++){
d=m[i-1]+m[i+1]+m[i-51]+m[i-50]+m[i-49]+m[i+49]+m[i+50]+m[i+51];
n[i]=m[i];
if(m[i]==0 && d==3) n[i]=1;
else if(m[i]==1 && d<2) n[i]=0;
else if(m[i]==1 && d>3) n[i]=0;
}
printf("\033[1;1H");   # Home cursor
for(i=1;i<=1000;i++)   # gridsize 50x20
{
if(n[i]) printf("O"); else printf(".");
m[i]=n[i];
if(!(i%50)) printf("\n");
}
printf("%3d\n",c);     # Countdown
x=30000; while(x--) ;  # Delay
}
}
```
Output:
Finally
```..................................................
..........................................OO......
..........................................O.O.....
...........................................O......
......................................OOO.......OO
................................................OO
....................................O.....O.......
....................................O.....O.......
....................................O.....O.......
..................................................
......................................OOO.........
..................................................
..................................................
..................................................
..O...............................................
.O.O..............................................
O.O...........OO...........OO.....................
.O............OO.........O..O.....................
.........................OOO......................
..................................................
0
```

## Axe

 This example is in need of improvement: Improve performance and add a way to interactively seed the map.

This implementation uses the full screen buffer instead of a 3x3 grid. This naive, unoptimized version gets less than 1 FPS.

```Full

While getKey(0)
End

ClrDraw
Pxl-On(45,45)
Pxl-On(46,45)
Pxl-On(47,45)

.GLIDER
Pxl-On(1,1)
Pxl-On(2,2)
Pxl-On(2,3)
Pxl-On(3,1)
Pxl-On(3,2)

Repeat getKey(0)
DispGraph
EVOLVE()
RecallPic
ClrDrawʳ
End
Return

Lbl EVOLVE
For(Y,0,63)
For(X,0,95)
0→N
For(B,Y-1,Y+1)
For(A,X-1,X+1)
pxl-Test(A,B)?N++
End
End
pxl_Test(X,Y)?N--
If N=3??(N=2?pxl-Test(X,Y))
Pxl-On(X,Y)ʳ
Else
Pxl-Off(X,Y)ʳ
End
End
End
Return```

## BASIC

### BASIC256

Saving to PNG files function is omited. You can find it in the Galton box animation example.

```# Conway's_Game_of_Life

X = 59 : Y = 35 : H = 4

fastgraphics
graphsize X*H,Y*H

dim c(X,Y) : dim cn(X,Y) : dim cl(X,Y)```
```# Thunderbird methuselah
c[X/2-1,Y/3+1] = 1 : c[X/2,Y/3+1] = 1 : c[X/2+1,Y/3+1] = 1
c[X/2,Y/3+3] = 1 : c[X/2,Y/3+4] = 1 : c[X/2,Y/3+5] = 1

s = 0
do
color black
rect 0,0,graphwidth,graphheight
alive = 0 : stable = 1
s = s + 1
for y = 0 to Y-1
for x = 0 to X-1
xm1 = (x-1+X)%X : xp1 = (x+1+X)%X
ym1 = (y-1+Y)%Y : yp1 = (y+1+Y)%Y
cn[x,y] = c[xm1,y] + c[xp1,y]
cn[x,y] = c[xm1,ym1] + c[x,ym1] + c[xp1,ym1] + cn[x,y]
cn[x,y] = c[xm1,yp1] + c[x,yp1] + c[xp1,yp1] + cn[x,y]
if c[x,y] = 1 then
if cn[x,y] < 2 or cn[x,y] > 3 then
cn[x,y] = 0
else
cn[x,y] = 1
alive = alive + 1
end if
else
if cn[x,y] = 3 then
cn[x,y] = 1
alive = alive + 1
else
cn[x,y] = 0
end if
end if
if c[x,y] then
if cn[x,y] then
if cl[x,y] then color purple		# adult
if not cl[x,y] then color green	        # newborn
else
if cl[x,y] then color red		# old
if not cl[x,y] then color yellow	# shortlived
end if
rect x*H,y*H,H,H
end if
next x
next y
refresh
pause 0.06
# Copy arrays
for i = 0 to X-1
for j = 0 to Y-1
if cl[i,j]<>cn[i,j] then stable = 0
cl[i,j] = c[i,j]
c[i,j] = cn[i,j]
next j
next i
until not alive or stable

if not alive then
print "Died in "+s+" iterations"
color black
rect 0,0,graphwidth,graphheight
refresh
else
print "Stabilized in "+(s-2)+" iterations"
end if```
Output:
``` Stabilized in 243 iterations
```

### BBC BASIC

```      dx% = 64
dy% = 64
DIM old&(dx%+1,dy%+1), new&(dx%+1,dy%+1)
VDU 23,22,dx%*4;dy%*4;16,16,16,0
OFF

old&(50,50) = 1 : old&(50,51) = 1 : old&(50,52) = 1
REM Set glider:
old&(5,7) = 1 : old&(6,7) = 1 : old&(7,7) = 1 : old&(7,6) = 1 : old&(6,5) = 1

REM Draw initial grid:
FOR X% = 1 TO dx%
FOR Y% = 1 TO dy%
IF old&(X%,Y%) GCOL 11 ELSE GCOL 4
PLOT 69, X%*8-6, Y%*8-4
NEXT
NEXT X%

REM Run:
GCOL 4,0
REPEAT
FOR X% = 1 TO dx%
FOR Y% = 1 TO dy%
S% = old&(X%-1,Y%) + old&(X%,Y%-1) + old&(X%-1,Y%-1) + old&(X%+1,Y%-1) + \
\    old&(X%+1,Y%) + old&(X%,Y%+1) + old&(X%-1,Y%+1) + old&(X%+1,Y%+1)
O% = old&(X%,Y%)
N% = -(S%=3 OR (O%=1 AND S%=2))
new&(X%,Y%) = N%
IF N%<>O% PLOT X%*8-6, Y%*8-4
NEXT
NEXT X%
SWAP old&(), new&()
WAIT 30
UNTIL FALSE
```
Output:

### CASIO BASIC

```Filename:JG VIDA
Cls
20→D
D+2→F
1→E
{F,F}→Dim Mat A
{F,F}→Dim Mat B
{F,F}→Dim Mat C
Fill(0,Mat A)
Fill(0,Mat B)
Fill(0,Mat C)
"PONDERACION 1"?→G
"PONDERACION 2"?→H
For 1→I To D
For 1→J To D
RanInt#(1,G)→R
If R≦H:Then
0→Mat A[I+1,J+1]
Else
1→Mat A[I+1,J+1]
IfEnd
Next
Next
Goto 2
Lbl 1
Mat A→Mat C
Mat B→Mat A
Lbl 2
For 1→I To D
For 1→J To D
I+1→K
J+1→L
K→M
L+20→N
If Mat C[K,L]=0:Then
If Mat A[K,L]=1:Then For 0→R To 2
For 0→S To 2
PxlOn 3I+R-2,3J+S-2
Next
Next
IfEnd
IfEnd
If Mat C[K,L]=1:Then
If Mat A[K,L]=0:Then For 0→R To 2
For 0→S To 2
PxlOff 3I+R-2,3J+S-2
Next
Next
IfEnd
IfEnd
Next
Next
For 1→I To D
For 1→J To D
0→C
I+1→K
J+1→L
Mat A[I,J]=1⇨C+1→C
Mat A[I+1,J]=1⇨C+1→C
Mat A[I+2,J]=1⇨C+1→C
Mat A[I+2,J+1]=1⇨C+1→C
Mat A[I+2,J+2]=1⇨C+1→C
Mat A[I+1,J+2]=1⇨C+1→C
Mat A[I,J+2]=1⇨C+1→C
Mat A[I,J+1]=1⇨C+1→C
If Mat A[K,L]=1:Then
C<2⇨0→Mat B[K,L]
C>3⇨0→Mat B[K,L]
IfEnd
If Mat A[K,L]=0:Then
C=3⇨1→Mat B[K,L]
IfEnd
Next
Next
Goto 1```

### FreeBASIC

```' FreeBASIC Conway's Game of Life
' May 2015
' 07-10-2016 cleanup/little changes
' moved test inkey outside the ScreenLock - ScreenUnLock block
' compile: fbc -s gui

Const As UInteger grid  = 300  '480 by 480
Const As UInteger gridy = grid
Const As UInteger gridx = grid
Const As UInteger pointsize = 5 'pixels
Const As UInteger steps = 10
Dim As UInteger gen, n, neighbours, x, y, was

Dim As String press

Const As UByte red   = 4  'red is color 6
Const As UByte white = 15 'color
Const As UByte black = 0  'color

'color 0 normaly is black
'color 1 normaly is dark blue
'color 2 normaly is green
Const As UInteger bot = 35 'this is 35 lines from the top of the page
Dim As UByte old( grid + 10, grid +10), new_( grid +10, grid +10)

' old( 160, 160) =1: old( 160, 170) =1 : old( 160, 180) =1

' old( 160, 20) =1: old( 160, 30) =1 : old( 160, 40) =1

' old( 20, 20) =1: old( 20, 30) =1 : old( 20, 40) =1

'Set glider:
'  old(  50,  70) =1: old(  60,  70) =1: old(  70,  70) =1
' old(  70,  60) =1: old(  60,  50) =1

' http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life
' Thunderbird methuselah
'X = 59 : Y = 35 : H = 4
'c[X/2-1,Y/3+1] = 1 : c[X/2,Y/3+1] = 1 : c[X/2+1,Y/3+1] = 1
'c[X/2,Y/3+3] = 1 : c[X/2,Y/3+4] = 1 : c[X/2,Y/3+5] = 1

'xb = 59 : yb = 35
' old( Xb/2-1,Yb/3+1) =1: old(Xb/2,Yb/3+1) =1: old(Xb/2+1,Yb/3+1) =1
' old( Xb/2,Yb/3+3) =1: old(Xb/2,Yb/3+4) =1 :old(Xb/2,Yb/3+5) = 1
'r-pentomino
'  old( 150,140) =1: old( 160,140) =1
'  old( 140,150) =1 :old( 150,150) =1
'  old( 150,160) =1

'Die Hard  around 150 generations
' old( 150,140) =1: old(160,140) =1 : old(160,150) =1
' old( 200,150) =1: old(210,150) =1 : old(210,130) = 1 : old(220,150) = 1

'Acorn  around 450 generations
' it looks like this:
'   0X
'   000X
'   XX00XXX
old( 180,200) =1
old( 200,210) =1
old( 170,220) =1 : old( 180,220) =1 : old( 210,220) =1 : old( 220,220) =1 : old( 230,220) =1

Screen 20 'Resolution 800x600 with at least 256 colors

Color white
Line (10, 10) - (gridx + 10, gridy + 10),,B  'box from top left to bottom right

Locate bot, 1  'Use a standard place on the bottom of the page
Color white
Print " Welcome to Conway's Game of Life"
Print " Using a constrained playing field (300x300), the Acorn seed runs"
Print " for about 450 generations before it becomes stable (or stale)."
Print " Enter any key to start"
Beep
Sleep

Do      ' flush the key input buffer
press = Inkey
Loop Until press = ""
'Print "                       "

'Draw initial grid
For x = 10 To gridX Step steps
For y = 10 To gridY Step steps
Color white 'old(x,y)
If old(x,y) = 1 Then Circle (x + pointsize, y + pointsize), pointsize,,,,, F
Next y
Next x
'
Locate bot, 1
Color white
Print " Welcome to Conway's Game of Life"
Print " Using a constrained playing field, the Acorn seed runs for      "
Print " about 450 generations before it becomes stable (or stale).    "
Color red
Print " Enter spacebar to continue or pause, ESC to stop"
Sleep
'
Do      ' flush the key input buffer
press = Inkey
Loop Until press = ""

Do
gen = gen + 1
Locate bot+5,1
Color white
Print " Gen = "; gen
ScreenLock
For x = 10 To gridX Step steps
For y = 10 To gridY Step steps
'find number of live neighbours
neighbours = old( x - steps, y - steps) +old( x , y - steps)
neighbours = neighbours + old( x + steps, y -steps)
neighbours = neighbours + old( x - steps, y) + old( x + steps, y)
neighbours = neighbours + old( x - steps, y + steps)
neighbours = neighbours + old( x, y + steps) +old( x + steps, y + steps)
was =old( x, y)
If was =0 Then
If neighbours =3 Then N =1 Else N =0
Else
If neighbours =3  Or neighbours =2 Then N =1 Else N =0
End If
new_( x, y) = N
If n = 2 Then Color white
If n = 1 Then Color red
If n = 0 Then Color black
Circle (x + pointsize, y + pointsize), pointsize,,,,, F
Next y
Next x
Color white
Line (10, 10) - (gridx + 10, gridy + 10),,B  'box from top left to bottom right
' Locate bot,1
'
't = timer
'do
'loop until timer > t + .2
ScreenUnlock
' might not be slow enough
Sleep 70, 1  ' ignore key press

press = Inkey
If press = " " Then
Do      ' flush the key input buffer
press = Inkey
Loop Until press = ""
Do      ' wait until a key is pressed
press = Inkey
Loop Until press <> ""
End If
If press = Chr(27) Then Exit Do
' mouse click on close window "X"
If press = Chr(255)+"k" Then End ' stop and close window

For x =10 To gridX Step steps
For y =10 To gridY Step steps
old( x, y) =new_( x, y)
Next y
Next x

Loop ' UNTIL press = CHR(27) 'return to do loop up top until "esc" key is pressed.

Color white
Locate bot+3,1
Print Space(55) 'clear instructions
Locate bot+6,1
Print " Press any key to exit                            "
Sleep
End```

### GFA Basic

```'
' Conway's Game of Life
'
' 30x30 world held in an array size 32x32
' world is in indices 1->30, 0 and 31 are always false, for neighbourhoods
'
DIM world!(32,32)
DIM ns%(31,31) ! used to hold the neighbour counts
clock%=1
'
' run the world
'
@setup_world
@open_window
DO
@display_world
t\$=INKEY\$
EXIT IF t\$="q" ! need to hold key down to exit
@update_world
DELAY 0.5 ! delay of 0.5s needed in compiled version
LOOP
@close_window
'
' Setup the world, with a blinker in one corner and a glider in the other
'
PROCEDURE setup_world
ARRAYFILL world!(),FALSE
world!(25,25)=TRUE
world!(26,25)=TRUE
world!(27,25)=TRUE
' glider in top-left
world!(2,2)=TRUE
world!(3,3)=TRUE
world!(3,4)=TRUE
world!(2,4)=TRUE
world!(1,4)=TRUE
RETURN
'
' Count the number of neighbours of the point i,j
' (Assume i/j +/- 1 will not fall out of world)
'
FUNCTION count_neighbours(i%,j%)
LOCAL count%,l%
count%=0
FOR l%=-1 TO 1
IF world!(i%+l%,j%-1)
count%=count%+1
ENDIF
IF world!(i%+l%,j%+1)
count%=count%+1
ENDIF
NEXT l%
IF world!(i%-1,j%)
count%=count%+1
ENDIF
IF world!(i%+1,j%)
count%=count%+1
ENDIF
RETURN count%
ENDFUNC
'
' Update the world one step
'
PROCEDURE update_world
LOCAL i%,j%
' compute neighbour counts and store
FOR i%=1 TO 30
FOR j%=1 TO 30
ns%(i%,j%)=@count_neighbours(i%,j%)
NEXT j%
NEXT i%
' update the world cells
FOR i%=1 TO 30
FOR j%=1 TO 30
IF world!(i%,j%)
SELECT ns%(i%,j%)
CASE 0,1
world!(i%,j%)=FALSE ! LONELY
CASE 2,3
world!(i%,j%)=TRUE ! LIVES
CASE 4,5,6,7,8
world!(i%,j%)=FALSE ! OVERCROWDED
ENDSELECT
ELSE
IF ns%(i%,j%)=3
world!(i%,j%)=TRUE ! BIRTH
ELSE
world!(i%,j%)=FALSE ! BARREN
ENDIF
ENDIF
NEXT j%
NEXT i%
' update the clock
clock%=clock%+1
RETURN
'
' Display the world in window
'
PROCEDURE display_world
LOCAL offsetx%,offsety%,i%,j%,x%,y%,scale%
@clear_window
' show clock
VSETCOLOR 2,0,0,0
DEFTEXT 2
PRINT AT(5,1);"Clock: ";clock%
' offset from top-left of display
offsetx%=10
offsety%=10
' colour to display active cell
VSETCOLOR 1,15,0,0
DEFFILL 1
' scale of display
scale%=9
' display each cell in world
FOR i%=1 TO 30
FOR j%=1 TO 30
IF world!(i%,j%)
' display active cell
x%=offsetx%+scale%*i%
y%=offsety%+scale%*j%
PBOX x%,y%,x%+scale%,y%+scale%
ENDIF
NEXT j%
NEXT i%
RETURN
'
' Manage window for display
'
PROCEDURE open_window
OPENW 1
CLEARW 1
RETURN
'
PROCEDURE clear_window
VSETCOLOR 0,15,15,15
DEFFILL 0
PBOX 0,0,300,300
RETURN
'
PROCEDURE close_window
CLOSEW 1
RETURN
```

### GW-BASIC

Allows a blinker to be loaded. It also has a routine for randomising the grid; common objects like blocks, gliders, etc turn up semi-frequently so it won't take long to verify that these all work.

```10 REM Conway's Game of Life
20 REM 30x30 grid, padded with zeroes as the boundary
30 DIM WORLD(31,  31, 1)
40 RANDOMIZE TIMER
50 CUR = 0 : BUF = 1
60 CLS
70 SCREEN 2
80 LOCATE 5,10: PRINT "Press space to perform one iteration"
100 LOCATE 7,10: PRINT "R to randomise the world"
110 LOCATE 8,10: PRINT "Q to quit"
120 K\$ = INKEY\$
130 IF K\$=" " THEN GOSUB 250: GOSUB 180
140 IF K\$="B" OR K\$="b" THEN GOSUB 400: GOSUB 180
150 IF K\$="R" OR K\$="r" THEN GOSUB 480: GOSUB 180
160 IF K\$="Q" OR K\$="q" THEN SCREEN 0: END
170 GOTO 120
180 REM draw the world
190 FOR XX=1 TO 30
200 FOR YY=1 TO 30
210 PSET (XX, YY), 15*WORLD(XX, YY, CUR)
220 NEXT YY
230 NEXT XX
240 RETURN
250 REM perform one iteration
260 FOR XX=1 TO 30
270 FOR YY=1 TO 30
280 SM=0
290 SM = SM + WORLD(XX-1, YY-1, CUR) + WORLD(XX, YY-1, CUR) + WORLD(XX+1, YY-1, CUR)
300 SM = SM + WORLD(XX-1, YY, CUR) + WORLD(XX+1, YY, CUR)
310 SM = SM + WORLD(XX-1, YY+1, CUR) + WORLD(XX, YY+1, CUR) + WORLD(XX+1, YY+1, CUR)
320 IF SM<2 OR SM>3 THEN WORLD(XX, YY, BUF) = 0
330 IF SM=3 THEN WORLD(XX, YY, BUF) = 1
340 IF SM=2 THEN WORLD(XX,YY,BUF) = WORLD(XX,YY,CUR)
350 NEXT YY
360 NEXT XX
370 CUR = BUF : REM exchange identities of current and buffer
380 BUF = 1 - BUF
390 RETURN
400 REM produces a vertical blinker at the top left corner, and blanks the rest
410 FOR XX=1 TO 30
420 FOR YY=1 TO 30
430 WORLD(XX,YY,CUR) = 0
440 IF XX=2 AND YY<4 THEN WORLD(XX, YY, CUR) = 1
450 NEXT YY
460 NEXT XX
470 RETURN
480 REM randomizes the world with a density of 1/2
490 FOR XX = 1 TO 30
500 FOR YY = 1 TO 30
510 WORLD(XX, YY, CUR) = INT(RND*2)
520 NEXT YY
530 NEXT XX
540 RETURN```

### Liberty BASIC

It will run slow for grids above say 25!

```      nomainwin

gridX = 20
gridY = gridX

mult      =500 /gridX
pointSize =360 /gridX

dim old( gridX +1, gridY +1), new( gridX +1, gridY +1)

old( 16, 16) =1: old( 16, 17) =1 : old( 16, 18) =1

'Set glider:
old(  5,  7) =1: old(  6,  7) =1: old(  7,  7) =1
old(  7,  6) =1: old(  6,  5) =1

WindowWidth  =570
WindowHeight =600

open "Conway's 'Game of Life'." for graphics_nsb_nf as #w

#w "trapclose [quit]"
#w "down ; size "; pointSize
#w "fill black"

'Draw initial grid
for x = 1 to gridX
for y = 1 to gridY
'#w "color "; int( old( x, y) *256); " 0 255"
if old( x, y) <>0 then #w "color red" else #w "color darkgray"
#w "set "; x *mult +20; " "; y *mult +20
next y
next x
'   ______________________________________________________________________________
'Run
do
for x =1 to gridX
for y =1 to gridY
'find number of live Moore neighbours
neighbours =old( x -1, y -1) +old( x, y -1) +old( x +1, y -1)+_
old( x -1, y)                   +old( x +1, y   )+_
old( x -1, y +1) +old( x, y +1) +old( x +1, y +1)
was =old( x, y)
if was =0 then
if neighbours =3 then N =1 else N =0
else
if neighbours =3  or neighbours =2 then N =1 else N =0Tail Recursive
end if
new( x, y) = N
'#w "color "; int( N /8 *256); " 0 255"
if N <>0 then #w "color red" else #w "color darkgray"
#w "set "; x *mult +20; " "; y *mult +20
next y
next x
scan
'swap
for x =1 to gridX
for y =1 to gridY
old( x, y) =new( x, y)
next y
next x
'Re-run until interrupted...
loop until FALSE
[quit]
close #w
end```

### MSX Basic

```10 DEFINT A-Z
20 DIM L(16,16), N(16,16)
30 M = 16
40 CLS
50 PRINT "PRESS A KEY TO START...";
60 W = RND(1)
70 IF INKEY\$ = "" THEN 60
80 CLS
100 FOR I=1 TO M
110   FOR J=1 TO M
120     IF RND(1)>=.7 THEN N(I,J) = 1 ELSE N(I,J) = 0
130   NEXT J
140 NEXT I
1000 FOR I=0 TO M+1
1010   LOCATE I,0 : PRINT "+";
1020   LOCATE I,M+1 : PRINT "+";
1030   LOCATE 0,I : PRINT "+";
1040   LOCATE M+1,I : PRINT "+";
1050 NEXT I
1080 G=0
1090 LOCATE 1,M+3 : PRINT USING "#####";G
1100 FOR I=1 TO M
1110   FOR J=1 TO M
1115     W = N(I,J) : L(I,J) = W
1120     LOCATE I,J
1130     IF W=0 THEN PRINT " "; ELSE PRINT "*";
1160   NEXT J
1170 NEXT I
1180 FOR I=1 TO M
1190   FOR J=1 TO M
1200     NC=0
1210     FOR K=I-1 TO I+1
1215       IF K=0 OR K>M THEN 1260
1220       FOR W=J-1 TO J+1
1230         IF W=0 OR W>M OR (K=I AND W=J) THEN 1250
1240         NC = NC + L(K,W)
1250       NEXT W
1260     NEXT K
1270     IF NC=2 THEN N(I,J)=L(I,J) : GOTO 1300
1280     IF NC=3 THEN N(I,J)=1 ELSE N(I,J)=0
1300   NEXT J
1310 NEXT I
1350 G=G+1
1360 GOTO 1090
```

### PureBasic

```EnableExplicit
Define.i x, y ,Xmax ,Ymax ,N
Xmax = 13 : Ymax = 20
Dim     world.i(Xmax+1,Ymax+1)
Dim Nextworld.i(Xmax+1,Ymax+1)

; Glider test
;------------------------------------------
world(1,1)=1 : world(1,2)=0 : world(1,3)=0
world(2,1)=0 : world(2,2)=1 : world(2,3)=1
world(3,1)=1 : world(3,2)=1 : world(3,3)=0
;------------------------------------------

OpenConsole()
EnableGraphicalConsole(1)
ClearConsole()
Print("Press any key to interrupt")
Repeat
ConsoleLocate(0,2)
PrintN(LSet("", Xmax+2, "-"))
;---------- endless world ---------
For y = 1 To Ymax
world(0,y)=world(Xmax,y)
world(Xmax+1,y)=world(1,y)
Next
For x = 1 To Xmax
world(x,0)=world(x,Ymax)
world(x,Ymax+1)=world(x,1)
Next
world(0     ,0     )=world(Xmax,Ymax)
world(Xmax+1,Ymax+1)=world(1   ,1   )
world(Xmax+1,0     )=world(1   ,Ymax)
world(     0,Ymax+1)=world(Xmax,1   )
;---------- endless world ---------
For y = 1 To Ymax
Print("|")
For x = 1 To Xmax
Print(Chr(32+world(x,y)*3))
N = world(x-1,y-1)+world(x-1,y)+world(x-1,y+1)+world(x,y-1)
N + world(x,y+1)+world(x+1,y-1)+world(x+1,y)+world(x+1,y+1)
If (world(x,y) And (N = 2 Or N = 3))Or (world(x,y)=0 And N = 3)
Nextworld(x,y)=1
Else
Nextworld(x,y)=0
EndIf
Next
PrintN("|")
Next
PrintN(LSet("", Xmax+2, "-"))
Delay(100)
;Swap world() , Nextworld()    ;PB  <4.50
CopyArray(Nextworld(), world());PB =>4.50
Dim Nextworld.i(Xmax+1,Ymax+1)
Until Inkey() <> ""

PrintN("Press any key to exit"): Repeat: Until Inkey() <> ""```

Sample output:

### QBasic

El código es de Ben Wagner (bwgames.org)
The code is from Ben Wagner (bwgames.org)
Yo solo lo transcrito y comento al español.
I just transcribed it and comment it in Spanish.

```SCREEN 9, 0, 0, 1

RANDOMIZE TIMER

WINDOW (0, 0)-(80, 80)

'La matrizA es la actual, la matrizB es la siguiente iteración
'ArrayA is current, arrayB is next iteration
DIM matrizA(-1 TO 81, -1 TO 81)
DIM matrizB(-1 TO 81, -1 TO 81)

'Aleatorizar las celdas de matrizA,
'Randomize cells in arrayA,
'y establecer las de matrizB a 0
'and set those of matrixB to 0
y = 0
DO
x = 0
DO
x = x + 1
matrizA(x, y) = INT(RND + .5)
matrizB(x, y) = 0
LOOP UNTIL x > 80

y = y + 1
LOOP UNTIL y > 80

''--- Bucle Principal ---
'' --- Main Loop ---
DO
CLS
'Dibuja la matriz
'Draw the matrix
y = 0
DO
x = 0
DO
IF matrizA(x, y) = 1 THEN LINE (x, y)-(x + 1, y + 1), 1, BF
x = x + 1
LOOP UNTIL x > 80

y = y + 1
LOOP UNTIL y > 80

'Cuenta el recuento de la celda circundante
'Counts the count of the surrounding cell
'Luego aplica la operación a la celda
'Then apply the operation to the cell
y = 0
DO
x = 0
DO
'Cuenta las células circundantes
'Count the surrounding cells
cuenta = 0

IF matrizA(x - 1, y + 1) = 1 THEN cuenta = cuenta + 1
IF matrizA(x, y + 1) = 1 THEN cuenta = cuenta + 1
IF matrizA(x + 1, y + 1) = 1 THEN cuenta = cuenta + 1
IF matrizA(x - 1, y) = 1 THEN cuenta = cuenta + 1
IF matrizA(x + 1, y) = 1 THEN cuenta = cuenta + 1
IF matrizA(x - 1, y - 1) = 1 THEN cuenta = cuenta + 1
IF matrizA(x, y - 1) = 1 THEN cuenta = cuenta + 1
IF matrizA(x + 1, y - 1) = 1 THEN cuenta = cuenta + 1

'Aplica las operaciones
'Apply the operations
'Muerte
'Death
IF matrizA(x, y) = 1 THEN
IF cuenta = 2 OR cuenta = 3 THEN matrizB(x, y) = 1 ELSE matrizB(x, y) = 0
END IF

'Nacimiento
'Birth
IF matrizA(x, y) = 0 THEN
IF cuenta = 3 THEN matrizB(x, y) = 1 ELSE matrizB(x, y) = 0
END IF
x = x + 1
LOOP UNTIL x > 80

y = y + 1
LOOP UNTIL y > 80

'Actualiza la matriz con la nueva matriz que hemos calculado.
'Update the matrix with the new matrix that we have calculated.
y = 0
DO
x = 0
DO
x = x + 1
matrizA(x, y) = matrizB(x, y)
LOOP UNTIL x > 80
y = y + 1

LOOP UNTIL y > 80
PCOPY 0, 1
LOOP WHILE INKEY\$ = ""
```

### Sinclair ZX81 BASIC

Requires at least 2k of RAM. Expects to find a square array of "0" and "1" characters, L\$(), giving the initial configuration. You can build this up by issuing commands in immediate mode and then run the program by entering `GOTO 1000`, but it's probably easier—assuming you can spare some RAM—to write the setup into the program using line numbers below 1000.

The graphics character in lines 1030 to 1060 can be obtained by typing `SHIFT``9` then `SHIFT``H`, and the one in line 1130 by typing `SHIFT``9` then `SPACE`.

```1000 LET M=LEN L\$(1)
1010 DIM N\$(M,M)
1020 FOR I=0 TO M+1
1030 PRINT AT I,0;"▩"
1040 PRINT AT I,M+1;"▩"
1050 PRINT AT 0,I;"▩"
1060 PRINT AT M+1,I;"▩"
1070 NEXT I
1080 LET G=0
1090 PRINT AT 1,M+3;G
1100 FOR I=1 TO M
1110 FOR J=1 TO M
1120 IF L\$(I,J)="0" THEN GOTO 1150
1130 PRINT AT I,J;"■"
1140 GOTO 1160
1150 PRINT AT I,J;" "
1160 NEXT J
1170 NEXT I
1180 FOR I=1 TO M
1190 FOR J=1 TO M
1200 LET N=0
1210 FOR K=I-1 TO I+1
1220 FOR L=J-1 TO J+1
1230 IF K=0 OR K>M OR L=0 OR L>M OR (K=I AND L=J) THEN GOTO 1250
1240 LET N=N+VAL L\$(K,L)
1250 NEXT L
1260 NEXT K
1270 LET N\$(I,J)=L\$(I,J)
1280 IF N<=1 OR N>=4 THEN LET N\$(I,J)="0"
1290 IF N=3 THEN LET N\$(I,J)="1"
1300 NEXT J
1310 NEXT I
1320 FOR I=1 TO M
1330 LET L\$(I)=N\$(I)
1340 NEXT I
1350 LET G=G+1
1360 GOTO 1090
```

```10 DIM L\$(3,3)
20 LET L\$(1)="000"
30 LET L\$(2)="111"
40 LET L\$(3)="000"
```

A screenshot of it running can be found here.

To try a random starting configuration on a 16x16 grid, use this:

```10 DIM L\$(16,16)
20 FOR I=1 TO 16
30 FOR J=1 TO 16
40 LET L\$(I,J)="0"
50 IF RND>=.7 THEN LET L\$(I,J)="1"
60 NEXT J
70 NEXT I
```

A screenshot is here.

### TI-83 BASIC

This implementation is loosely based on the Processing Version. It uses the home screen and draws cells as "X"s. It is extremely slow, and limited to a bounding box of 16 by 8. In order for it to work, you need to initialize arrays [A] and [B] to be 18x10.

``` PROGRAM:CONWAY
:While 1
:For(X,2,9,1)
:For(Y,2,17,1)
:If [A](Y,X)
:Then
:Output(X-1,Y-1,"X")
:Else
:Output(X-1,Y-1," ")
:End
:[A](Y-1,X-1)+[A](Y,X-1)+[A](Y+1,X-1)+[A](Y-1,X)+[A](Y+1,X)+[A](Y-1,X+1)+[A](Y,X+1)+[A](Y+1,X+1)→N
:If ([A](Y,X) and (N=2 or N=3)) or (not([A](Y,X)) and N=3)
:Then
:1→[B](Y,X)
:Else
:0→[B](Y,X)
:End
:End
:End
:[B]→[A]
:End```

Here is an additional, very simple program to input the top corner of the GRAPH screen into the starting array. Make sure to draw on pixels in the rectangle (1,1) to (8,16).

```PROGRAM:PIC2LIFE
:For(I,0,17,1)
:For(J,0,9,1)
:pxl-Test(J,I)→[A](I+1,J+1)
:End
:End```

### TI-89 BASIC

This program draws its cells as 2x2 blocks on the graph screen. In order to avoid needing external storage for the previous generation, it uses the upper-left corner of each block to mark the next generation's state in all cells, then updates each cell to match its corner pixel.

A further improvement would be to have an option to start with the existing picture rather than clearing, and stop at a point where the picture has clean 2x2 blocks.

```Define life(pattern) = Prgm
Local x,y,nt,count,save,xl,yl,xh,yh
Define nt(y,x) = when(pxlTest(y,x), 1, 0)

{}→save
setGraph("Axes", "Off")→save[1]
setGraph("Grid", "Off")→save[2]
setGraph("Labels", "Off")→save[3]
FnOff
PlotOff
ClrDraw

36→yl
40→yh
78→xl
82→xh
PxlOn  36,80
PxlOn  38,80
PxlOn  40,80
ElseIf pattern = "glider" Then
30→yl
40→yh
76→xl
88→xh
PxlOn  38,76
PxlOn  36,78
PxlOn  36,80
PxlOn  38,80
PxlOn  40,80
ElseIf pattern = "r" Then
38-5*2→yl
38+5*2→yh
80-5*2→xl
80+5*2→xh
PxlOn  38,78
PxlOn  36,82
PxlOn  36,80
PxlOn  38,80
PxlOn  40,80
EndIf

While getKey() = 0
© Expand upper-left corner to whole cell
For y,yl,yh,2
For x,xl,xh,2
If pxlTest(y,x) Then
PxlOn y+1,x
PxlOn y+1,x+1
PxlOn y,  x+1
Else
PxlOff y+1,x
PxlOff y+1,x+1
PxlOff y,  x+1
EndIf
EndFor
EndFor

For y,yl,yh,2
For x,xl,xh,2
nt(y-1,x-1) + nt(y-1,x) + nt(y-1,x+2) + nt(y,x-1) + nt(y+1,x+2) + nt(y+2,x-1) + nt(y+2,x+1) + nt(y+2,x+2) → count
If count = 3 Then
PxlOn y,x
ElseIf count ≠ 2 Then
PxlOff y,x
EndIf
EndFor
EndFor
EndWhile

setGraph("Axes", save[1])
setGraph("Grid", save[2])
setGraph("Labels", save[3])
EndPrgm```

## Batch File

This code takes three parameters: `m chance iterations` Where,
m - The length and width of the array of cells
chance - The percent chance of any cell within the set array initially being alive. Full numbers only.
iterations - The amount of iterations of evolution the array goes through to display.

If no parameters are parsed, it defaults to 5 iterations of the blinking example.

```@echo off
setlocal enabledelayedexpansion

if "%1"=="" (
) else (
call:_randomArray %*
)

for /l %%i in (1,1,%iterations%) do (
call:_setStatus
call:_display

for /l %%m in (1,1,%m%) do (
for /l %%n in (1,1,%m%) do (
call:_evolution %%m %%n
)
)
)

for /l %%m in (0,1,4) do (
for /l %%n in (0,1,4) do (
set cell[%%m][%%n]=0
)
)
set cell[2][1]=1
set cell[2][2]=1
set cell[2][3]=1
set iterations=5
set m=3

exit /b

:_randomArray
for /l %%m in (0,1,%cellsaddone%) do for /l %%n in (0,1,%cellsaddone%) do set cell[%%m][%%n]=0
for /l %%m in (1,1,%1) do (
for /l %%n in (1,1,%1) do (
set /a cellrandom=!random! %% 101
set cell[%%m][%%n]=0
if !cellrandom! leq %2 set cell[%%m][%%n]=1
)
)
set iterations=%3
set m=%1

exit /b

:_setStatus
for /l %%m in (0,1,%cellsaddone%) do (
for /l %%n in (0,1,%cellsaddone%) do (
if !cell[%%m][%%n]!==1 set cellstatus[%%m][%%n]=alive
)
)
exit /b

:_evolution
set /a lowerm=%1-1
set /a upperm=%1+1
set /a lowern=%2-1
set /a uppern=%2+1
set numm=%1
set numn=%2
set sum=0
for /l %%m in (%lowerm%,1,%upperm%) do (
for /l %%n in (%lowern%,1,%uppern%) do (
if %%m==%numm% (
if %%n==%numn% (
set /a sum=!sum!
) else (
if !cellstatus[%%m][%%n]!==alive set /a sum+=1
)
) else (
if !cellstatus[%%m][%%n]!==alive set /a sum+=1
)
)
)
goto:!cell[%numm%][%numn%]!

exit /b

:0
set alive=3
set death=0 1 2 4 5 6 7 8
for %%i in (%alive%) do if %sum%==%%i set cell[%numm%][%numn%]=1
for %%i in (%death%) do if %sum%==%%i set cell[%numm%][%numn%]=0
exit /b

:1
set alive=2 3
set death=0 1 4 5 6 7 8
for %%i in (%alive%) do if %sum%==%%i set cell[%1][%2]=1
for %%i in (%death%) do if %sum%==%%i set cell[%1][%2]=0
exit /b

:_display
echo.
for /l %%m in (1,1,%m%) do (
set m%%m=
for /l %%n in (1,1,%m%) do set m%%m=!m%%m! !cell[%%m][%%n]!
echo !m%%m!
)

exit /b```
Output:

```0 0 0
1 1 1
0 0 0

0 1 0
0 1 0
0 1 0

0 0 0
1 1 1
0 0 0

0 1 0
0 1 0
0 1 0

0 0 0
1 1 1
0 0 0
```
Input:
```10 35 5
```
Output:
```1 1 0 0 0 0 1 1 0 0
1 1 0 0 1 1 0 1 1 0
1 0 1 1 0 0 0 1 0 0
0 1 0 1 0 1 0 1 0 1
1 0 0 0 1 0 0 1 0 1
0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0
0 0 1 0 0 0 0 0 0 0
1 0 1 0 0 0 0 0 1 1
1 1 0 0 1 0 0 1 1 0

1 1 0 0 0 1 1 1 1 0
0 0 0 1 1 1 0 0 1 0
1 0 0 1 0 1 0 1 0 0
1 1 0 1 0 0 0 1 0 0
0 0 1 1 1 0 1 0 0 0
0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 1 1 0
1 0 1 1 0 0 0 1 1 1
1 1 0 0 0 0 0 1 1 1

0 0 0 0 0 1 1 1 1 0
1 1 1 1 0 0 0 0 1 0
1 1 0 1 0 1 0 1 1 0
1 1 0 0 0 1 0 1 0 0
0 1 1 1 1 1 1 0 1 0
0 0 0 1 0 1 1 1 0 0
0 0 0 0 0 0 1 0 0 0
0 1 1 0 0 0 0 1 0 1
1 0 1 0 0 0 1 0 0 0
1 1 1 0 0 0 0 1 0 1

0 1 1 0 0 0 1 1 1 0
1 0 0 1 0 1 0 0 0 1
0 0 0 1 0 0 0 1 1 0
0 0 0 0 0 0 0 0 0 0
1 1 0 1 0 0 0 0 1 0
0 0 0 1 0 0 0 0 0 0
0 0 1 0 0 1 0 0 1 0
0 1 1 0 0 0 1 1 0 0
1 0 0 1 0 0 1 1 0 0
1 0 1 0 0 0 0 0 0 0

0 1 1 0 0 0 1 1 1 0
0 1 0 1 1 0 0 0 0 1
0 0 0 0 1 0 0 0 1 0
0 0 1 0 0 0 0 1 1 0
0 0 1 0 0 0 0 0 0 0
0 1 0 1 1 0 0 0 0 0
0 1 1 1 0 0 1 1 0 0
0 1 1 1 0 1 0 0 1 0
1 0 0 1 0 0 1 1 0 0
0 1 0 0 0 0 0 0 0 0
```

## Befunge

Takes as input the width and height of the universe, followed by the pattern (which is terminated by the end of file). If your interpreter can't easily redirect the input from a file, or doesn't handle end-of-file detection, you can also type in the pattern manually and mark the end of input with a ~ character.

The pattern format itself is fairly lenient in what it accepts. You can use either space or . for dead cells, and o, O, * or # for live cells. This should make it fairly easy to cut and paste a number of existing formats, including the Life 1.05 format and the Plaintext .cells format used on the LifeWiki website (comments aren't supported though, so make sure to copy just the pattern itself).

In Befunge-93, the maximum value for the width and height of the universe is 127, but there is an additional constraint of 4080 cells in total, so the largest universe would really be something like 120x34 or 68x60. Befunge-98 has no real limit on the size, although in practice a much larger universe will probably be unbearably slow.

```00p10p20p30p&>40p&>50p60p>\$#v~>:55+-vv+`1:%3:+*g04p03< >3/"P"%\56v>p\56*8*/8+:v
v5\`\"~"::-*3p06!:!-+67:_^#!<*<!g06!<>1+70g*\:3/"P"%v^ ^::+*g04%<*0v`1:%3\gp08<
>6*`*#v_55+-#v_p10g1+10p>^pg08g07+gp08:+8/*8*65\p07:<^ >/10g-50g^87>+1+:01p/8/v
>%#74#<-!!70p 00g::1+00p:20g\-:0`*+20p10g::30g\-:0`*+^ ^2+2+g03*<*:v+g06p09:%2<
.v,:*93"[2J"0<>"H["39*,,,50g0v!:-1,+55\$_:40g3*20g+2+2/\-40g%50g3^/%\ >:3-\3-90v
O>"l52?[">:#,_^v/3+2:*g05g04\$_>:10p40g0^!:-1,g+4\0%2/+1+`1:%3\g+8<^: \$v10!*-g<<
g+70g80gp:#v_\$^>1-:::"P"%\"P"/8+:10v  >/10g+1-50g+50g%40g*+::3/"P"^>!|>g*70g80g
:p00%g04:-1<<\$_^#!:pg01%"P"\*8%8gp<<  ^3\%g04+g04-1+g00%3:%9+4:-1p06\<90p01/g04
```
Input:

Here's an example of what the input could look like for the Blinker pattern in a 5x5 universe:

```5
5
OOO```

And for a more complicated example, this is the Queen bee pattern in a 50x30 universe:

```50
30
...*
..*.*
.*...*
..***
**...**```
Output:

In order to produce an animated view of the universe evolving, we use a few basic ANSI escape sequences to reset the cursor position between frames. Without ANSI support, you'll just see the individual frames scrolling past with a bit of junk inbetween. The output shown below is just an extract of the first three generations of the Blinker in a 5x5 universe.

```.....   .....   .....
.....   ..O..   .....
.OOO.   ..O..   .OOO.
.....   ..O..   .....
.....   .....   .....```

## Brainf***

A life-program written in Brainf***

With Example-Output.

## Brat

```width = 3
height = 3
rounds = 3

universe = [[0 1 0]
[0 1 0]
[0 1 0]]

next = height.of({width.of(0)})

cell = { x, y |
true? x < width && { x >= 0 && { y >= 0 && { y < height }}}
{
universe[y][x]
}
{ 0 }
}

neighbors = { x, y |
cell(x - 1, y - 1) +
cell(x, y - 1) +
cell(x + 1, y - 1) +
cell(x + 1, y) +
cell(x + 1, y + 1) +
cell(x, y + 1) +
cell(x - 1, y + 1) +
cell(x - 1, y)
}

set_next = { x, y, v |
next[y][x] = v
}

step = {
universe.each_with_index { row, y |
row.each_with_index { c, x |
n = neighbors(x, y)

when { n < 2 } { set_next x,y, 0 }
{ n > 3 } { set_next x, y, 0 }
{ n == 3 } { set_next x, y, 1 }
{ true } { set_next x, y, c }
}
}

u2 = universe
universe = next
next = u2
}

display = {
p universe.map({ r |
r.map({ n | true? n == 0, '-', "O" }).join
}).join("\n")
}

rounds.times {
display
p
step
}```
Output:
```-O-
-O-
-O-

---
OOO
---

-O-
-O-
-O-
```

## BQN

```Life←{
r←¯1(⌽⎉1)¯1⌽(2+≢𝕩)↑𝕩
s←∨´ (1∾<r) ∧ 3‿4 = <+´⥊ ¯1‿0‿1 (⌽⎉1)⌜ ¯1‿0‿1 ⌽⌜ <r
1(↓⎉1) ¯1(↓⎉1) 1↓ ¯1↓s
}

```
Output:
```┌─
· ┌─      ┌─      ┌─
╵"...   ╵".#.   ╵"...
###     .#.     ###
..."    .#."    ..."
┘       ┘       ┘
┘```

## C

Play game of life on your console: `gcc -std=c99 -Wall game.c; ./a.out [width] [height]`

```#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define for_x for (int x = 0; x < w; x++)
#define for_y for (int y = 0; y < h; y++)
#define for_xy for_x for_y
void show(void *u, int w, int h)
{
int (*univ)[w] = u;
printf("\033[H");
for_y {
for_x printf(univ[y][x] ? "\033[07m  \033[m" : "  ");
printf("\033[E");
}
fflush(stdout);
}

void evolve(void *u, int w, int h)
{
unsigned (*univ)[w] = u;
unsigned new[h][w];

for_y for_x {
int n = 0;
for (int y1 = y - 1; y1 <= y + 1; y1++)
for (int x1 = x - 1; x1 <= x + 1; x1++)
if (univ[(y1 + h) % h][(x1 + w) % w])
n++;

if (univ[y][x]) n--;
new[y][x] = (n == 3 || (n == 2 && univ[y][x]));
}
for_y for_x univ[y][x] = new[y][x];
}

void game(int w, int h)
{
unsigned univ[h][w];
for_xy univ[y][x] = rand() < RAND_MAX / 10 ? 1 : 0;
while (1) {
show(univ, w, h);
evolve(univ, w, h);
usleep(200000);
}
}

int main(int c, char **v)
{
int w = 0, h = 0;
if (c > 1) w = atoi(v[1]);
if (c > 2) h = atoi(v[2]);
if (w <= 0) w = 30;
if (h <= 0) h = 30;
game(w, h);
}
```

Also see Conway's Game of Life/C

### C for Arduino

Play game of life on your arduino (using FastLED) - based on the C example.

```#include <FastLED.h>

#define LED_PIN     3
#define LED_TYPE    WS2812B
#define WIDTH       20
#define HEIGHT      15
#define NUM_LEDS    (WIDTH*HEIGHT)
#define BRIGHTNESS  100
#define COLOR_ORDER GRB
#define SERPENTINE  1
#define FRAMERATE   1
#define SCALE       1

CRGB leds[NUM_LEDS];

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define for_x for (int x = 0; x < w; x++)
#define for_y for (int y = 0; y < h; y++)
#define for_xy for_x for_y

const int w = WIDTH, h = HEIGHT;
unsigned univ[h][w];

int getLEDpos(int x, int y){ // for a serpentine raster
return (y%2 || !SERPENTINE) ? y*WIDTH + x : y*WIDTH + (WIDTH - 1 - x);
}

void show(void *u, int w, int h)
{
int (*univ)[w] = u;
for_xy {
leds[getLEDpos(x, y)] = univ[y][x] ? CRGB::White: CRGB::Black;
}
FastLED.show();
}

void evolve(void *u, int w, int h)
{
unsigned (*univ)[w] = u;
unsigned newU[h][w];

for_y for_x {
int n = 0;
for (int y1 = y - 1; y1 <= y + 1; y1++)
for (int x1 = x - 1; x1 <= x + 1; x1++)
if (univ[(y1 + h) % h][(x1 + w) % w])
n++;

if (univ[y][x]) n--;
newU[y][x] = (n == 3 || (n == 2 && univ[y][x]));
}
for_y for_x univ[y][x] = newU[y][x];
}

void setup(){
//Initialize leds after safety period
FastLED.delay(500);
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
FastLED.setBrightness(  BRIGHTNESS );

//Seed random with analog noise

for_xy univ[y][x] = random() %10 <= 1 ? 1 : 0;
}

void loop(){
show(univ, w, h);
evolve(univ, w, h);
FastLED.delay(1000/FRAMERATE);
}
```

### C for Arduino

Play game of life on your arduino (using two MAX7219 led 'screens') - based on the C example.

```#include <MaxMatrix.h>

int DIN = 11;   // DIN pin of MAX7219 module
int CS = 12;    // CS pin of MAX7219 module
int CLK = 13;   // CLK pin of MAX7219 module
int DIN2 = 8;   // DIN pin of MAX7219 module
int CS2 = 9;    // CS pin of MAX7219 module
int CLK2 = 10;   // CLK pin of MAX7219 module
int maxInUse = 1;

//setup two screens
MaxMatrix m(DIN, CS, CLK, maxInUse);
MaxMatrix m2(DIN2, CS2, CLK2, maxInUse);

void setup() {
m.init(); // MAX7219 initialization
m.setIntensity(0); // initial led matrix intensity, 0-15
m.clear(); // Clears the display
m2.init(); // MAX7219 initialization
m2.setIntensity(0); // initial led matrix intensity, 0-15
m2.clear(); // Clears the display
}

void loop() {
game(16,8);//w,h
}

void setDot(int x,int y,bool isOn){
if(x<8){
m.setDot(x,y,isOn);
}else{
m2.setDot(x-8,y,isOn);
}
}

void show(void *u, int w, int h){
int (*univ)[w] = u;
for (int y = 0; y < h; y++){
for (int x = 0; x < w; x++){
bool sh=(univ[y][x]==1);
setDot(x,y,sh);
}
}
}

void evolve(void *u, int w, int h){
unsigned (*univ)[w] = u;
unsigned newar[h][w];

for (int y = 0; y < h; y++){
for (int x = 0; x < w; x++){
int n = 0;
for (int y1 = y - 1; y1 <= y + 1; y1++)
for (int x1 = x - 1; x1 <= x + 1; x1++)
if (univ[(y1 + h) % h][(x1 + w) % w])
n++;

if (univ[y][x]) n--;
newar[y][x] = (n == 3 || (n == 2 && univ[y][x]));

}
}

for (int y = 0; y < h; y++){
for (int x = 0; x < w; x++){
univ[y][x] = newar[y][x];
}
}
}

void game(int w, int h) {
unsigned univ[h][w];
for (int x = 0; x < w; x++){
for (int y = 0; y < h; y++){
univ[y][x] = random(0, 100)>65 ? 1 : 0;
}
}
int sc=0;
while (1) {
show(univ, w, h);
evolve(univ, w, h);
delay(150);
sc++;if(sc>150)break;
}
}
```

## C#

```using System;
using System.Text;

namespace ConwaysGameOfLife
{
// Plays Conway's Game of Life on the console with a random initial state.
class Program
{
// The delay in milliseconds between board updates.
private const int DELAY = 50;

// The cell colors.
private const ConsoleColor DEAD_COLOR = ConsoleColor.White;
private const ConsoleColor LIVE_COLOR = ConsoleColor.Black;

// The color of the cells that are off of the board.
private const ConsoleColor EXTRA_COLOR = ConsoleColor.Gray;

private const char EMPTY_BLOCK_CHAR = ' ';
private const char FULL_BLOCK_CHAR = '\u2588';

// Holds the current state of the board.
private static bool[,] board;

// The dimensions of the board in cells.
private static int width = 32;
private static int height = 32;

// True if cell rules can loop around edges.
private static bool loopEdges = true;

static void Main(string[] args)
{
// Use initializeRandomBoard for a larger, random board.
initializeDemoBoard();

initializeConsole();

// Run the game until the Escape key is pressed.
while (!Console.KeyAvailable || Console.ReadKey(true).Key != ConsoleKey.Escape) {
Program.drawBoard();
Program.updateBoard();

// Wait for a bit between updates.
}
}

// Sets up the Console.
private static void initializeConsole()
{
Console.BackgroundColor = EXTRA_COLOR;
Console.Clear();

Console.CursorVisible = false;

// Each cell is two characters wide.
// Using an extra row on the bottom to prevent scrolling when drawing the board.
int width = Math.Max(Program.width, 8) * 2 + 1;
int height = Math.Max(Program.height, 8) + 1;
Console.SetWindowSize(width, height);
Console.SetBufferSize(width, height);

Console.ForegroundColor = LIVE_COLOR;
}

// Creates the initial board with a random state.
private static void initializeRandomBoard()
{
var random = new Random();

Program.board = new bool[Program.width, Program.height];
for (var y = 0; y < Program.height; y++) {
for (var x = 0; x < Program.width; x++) {
// Equal probability of being true or false.
Program.board[x, y] = random.Next(2) == 0;
}
}
}

// Creates a 3x3 board with a blinker.
private static void initializeDemoBoard()
{
Program.width = 3;
Program.height = 3;

Program.loopEdges = false;

Program.board = new bool[3, 3];
Program.board[1, 0] = true;
Program.board[1, 1] = true;
Program.board[1, 2] = true;
}

// Draws the board to the console.
private static void drawBoard()
{
// One Console.Write call is much faster than writing each cell individually.
var builder = new StringBuilder();

for (var y = 0; y < Program.height; y++) {
for (var x = 0; x < Program.width; x++) {
char c = Program.board[x, y] ? FULL_BLOCK_CHAR : EMPTY_BLOCK_CHAR;

// Each cell is two characters wide.
builder.Append(c);
builder.Append(c);
}
builder.Append('\n');
}

// Write the string to the console.
Console.SetCursorPosition(0, 0);
Console.Write (builder.ToString());
}

// Moves the board to the next state based on Conway's rules.
private static void updateBoard()
{
// A temp variable to hold the next state while it's being calculated.
bool[,] newBoard = new bool[Program.width, Program.height];

for (var y = 0; y < Program.height; y++) {
for (var x = 0; x < Program.width; x++) {
var n = countLiveNeighbors(x, y);
var c = Program.board[x, y];

// A live cell dies unless it has exactly 2 or 3 live neighbors.
// A dead cell remains dead unless it has exactly 3 live neighbors.
newBoard[x, y] = c && (n == 2 || n == 3) || !c && n == 3;
}
}

// Set the board to its new state.
Program.board = newBoard;
}

// Returns the number of live neighbors around the cell at position (x,y).
private static int countLiveNeighbors(int x, int y)
{
// The number of live neighbors.
int value = 0;

// This nested loop enumerates the 9 cells in the specified cells neighborhood.
for (var j = -1; j <= 1; j++) {
// If loopEdges is set to false and y+j is off the board, continue.
if (!Program.loopEdges && y + j < 0 || y + j >= Program.height) {
continue;
}

// Loop around the edges if y+j is off the board.
int k = (y + j + Program.height) % Program.height;

for (var i = -1; i <= 1; i++) {
// If loopEdges is set to false and x+i is off the board, continue.
if (!Program.loopEdges && x + i < 0 || x + i >= Program.width) {
continue;
}

// Loop around the edges if x+i is off the board.
int h = (x + i + Program.width) % Program.width;

// Count the neighbor cell at (h,k) if it is alive.
value += Program.board[h, k] ? 1 : 0;
}
}

// Subtract 1 if (x,y) is alive since we counted it as a neighbor.
return value - (Program.board[x, y] ? 1 : 0);
}
}
}
```

Output:

```Frame 1:    Frame 2:    Frame 3:
██
██████        ██        ██████
██
```

## C++

Considering that the simplest implementation in C++ would lack any use of the object-oriented paradigm, this code was specifically written to demonstrate the various object-oriented features of C++. Thus, while it is somewhat verbose, it fully simulates Conway's Game of Life and is relatively simple to expand to feature different starting shapes.

```#include <iostream>
#define HEIGHT 4
#define WIDTH 4

struct Shape {
public:
char xCoord;
char yCoord;
char height;
char width;
char **figure;
};

struct Glider : public Shape {
static const char GLIDER_SIZE = 3;
Glider( char x , char y );
~Glider();
};

struct Blinker : public Shape {
static const char BLINKER_HEIGHT = 3;
static const char BLINKER_WIDTH = 1;
Blinker( char x , char y );
};

class GameOfLife {
public:
GameOfLife( Shape sh );
void print();
void update();
char getState( char state , char xCoord , char yCoord , bool toggle);
void iterate(unsigned int iterations);
private:
char world[HEIGHT][WIDTH];
char otherWorld[HEIGHT][WIDTH];
bool toggle;
Shape shape;
};

GameOfLife::GameOfLife( Shape sh ) :
shape(sh) ,
toggle(true)
{
for ( char i = 0; i < HEIGHT; i++ ) {
for ( char j = 0; j < WIDTH; j++ ) {
world[i][j] = '.';
}
}
for ( char i = shape.yCoord; i - shape.yCoord < shape.height; i++ ) {
for ( char j = shape.xCoord; j - shape.xCoord < shape.width; j++ ) {
if ( i < HEIGHT && j < WIDTH ) {
world[i][j] =
shape.figure[ i - shape.yCoord ][j - shape.xCoord ];
}
}
}
}

void GameOfLife::print() {
if ( toggle ) {
for ( char i = 0; i < HEIGHT; i++ ) {
for ( char j = 0; j < WIDTH; j++ ) {
std::cout << world[i][j];
}
std::cout << std::endl;
}
} else {
for ( char i = 0; i < HEIGHT; i++ ) {
for ( char j = 0; j < WIDTH; j++ ) {
std::cout << otherWorld[i][j];
}
std::cout << std::endl;
}
}
for ( char i = 0; i < WIDTH; i++ ) {
std::cout << '=';
}
std::cout << std::endl;
}

void GameOfLife::update() {
if (toggle) {
for ( char i = 0; i < HEIGHT; i++ ) {
for ( char j = 0; j < WIDTH; j++ ) {
otherWorld[i][j] =
GameOfLife::getState(world[i][j] , i , j , toggle);
}
}
toggle = !toggle;
} else {
for ( char i = 0; i < HEIGHT; i++ ) {
for ( char j = 0; j < WIDTH; j++ ) {
world[i][j] =
GameOfLife::getState(otherWorld[i][j] , i , j , toggle);
}
}
toggle = !toggle;
}
}

char GameOfLife::getState( char state, char yCoord, char xCoord, bool toggle ) {
char neighbors = 0;
if ( toggle ) {
for ( char i = yCoord - 1; i <= yCoord + 1; i++ ) {
for ( char j = xCoord - 1; j <= xCoord + 1; j++ ) {
if ( i == yCoord && j == xCoord ) {
continue;
}
if ( i > -1 && i < HEIGHT && j > -1 && j < WIDTH ) {
if ( world[i][j] == 'X' ) {
neighbors++;
}
}
}
}
} else {
for ( char i = yCoord - 1; i <= yCoord + 1; i++ ) {
for ( char j = xCoord - 1; j <= xCoord + 1; j++ ) {
if ( i == yCoord && j == xCoord ) {
continue;
}
if ( i > -1 && i < HEIGHT && j > -1 && j < WIDTH ) {
if ( otherWorld[i][j] == 'X' ) {
neighbors++;
}
}
}
}
}
if (state == 'X') {
return ( neighbors > 1 && neighbors < 4 ) ? 'X' : '.';
}
else {
return ( neighbors == 3 ) ? 'X' : '.';
}
}

void GameOfLife::iterate( unsigned int iterations ) {
for ( int i = 0; i < iterations; i++ ) {
print();
update();
}
}

Glider::Glider( char x , char y ) {
xCoord = x;
yCoord = y;
height = GLIDER_SIZE;
width = GLIDER_SIZE;
figure = new char*[GLIDER_SIZE];
for ( char i = 0; i < GLIDER_SIZE; i++ ) {
figure[i] = new char[GLIDER_SIZE];
}
for ( char i = 0; i < GLIDER_SIZE; i++ ) {
for ( char j = 0; j < GLIDER_SIZE; j++ ) {
figure[i][j] = '.';
}
}
figure[0][1] = 'X';
figure[1][2] = 'X';
figure[2][0] = 'X';
figure[2][1] = 'X';
figure[2][2] = 'X';
}

Glider::~Glider() {
for ( char i = 0; i < GLIDER_SIZE; i++ ) {
delete[] figure[i];
}
delete[] figure;
}

xCoord = x;
yCoord = y;
for ( char i = 0; i < BLINKER_HEIGHT; i++ ) {
}
for ( char i = 0; i < BLINKER_HEIGHT; i++ ) {
for ( char j = 0; j < BLINKER_WIDTH; j++ ) {
figure[i][j] = 'X';
}
}
}

for ( char i = 0; i < BLINKER_HEIGHT; i++ ) {
delete[] figure[i];
}
delete[] figure;
}

int main() {
Glider glider(0,0);
GameOfLife gol(glider);
gol.iterate(5);
gol2.iterate(4);
}
```
Output:
first a glider, then a blinker, over a few iterations

(reformatted for convenience).

```.X.. .... .... .... ....
..X. X.X. ..X. .X.. ..X.
XXX. .XX. X.X. ..XX ...X
.... .X.. .XX. .XX. .XXX
==== ==== ==== ==== ====

.X.. .... .X..
.X.. XXX. .X..
.X.. .... .X..
.... .... ....
==== ==== ====
```

### Alternate version

Another aproach - a pretty simple one.
This version allows you to start the automata with different set of rules. Just for the fun of it.

```#include <algorithm>
#include <vector>
#include <iostream>
#include <string>

typedef unsigned char byte;

class world {
public:
world( int x, int y ) : _wid( x ), _hei( y ) {
int s = _wid * _hei * sizeof( byte );
_cells = new byte[s];
memset( _cells, 0, s );
}
~world() {
delete [] _cells;
}
int wid() const {
return _wid;
}
int hei() const {
return _hei;
}
byte at( int x, int y ) const {
return _cells[x + y * _wid];
}
void set( int x, int y, byte c ) {
_cells[x + y * _wid] = c;
}
void swap( world* w ) {
memcpy( _cells, w->_cells, _wid * _hei * sizeof( byte ) );
}
private:
int _wid, _hei;
byte* _cells;
};
class rule {
public:
rule( world* w ) : wrd( w ) {
wid = wrd->wid();
hei = wrd->hei();
wrdT = new world( wid, hei );
}
~rule() {
if( wrdT ) delete wrdT;
}
bool hasLivingCells() {
for( int y = 0; y < hei; y++ )
for( int x = 0; x < wid; x++ )
if( wrd->at( x, y ) ) return true;
std::cout << "*** All cells are dead!!! ***\n\n";
return false;
}
void swapWrds() {
wrd->swap( wrdT );
}
void setRuleB( std::vector<int>& birth ) {
_birth = birth;
}
void setRuleS( std::vector<int>& stay ) {
_stay = stay;
}
void applyRules() {
int n;
for( int y = 0; y < hei; y++ ) {
for( int x = 0; x < wid; x++ ) {
n = neighbours( x, y );
if( wrd->at( x, y ) ) {
wrdT->set( x, y, inStay( n ) ? 1 : 0 );
} else {
wrdT->set( x, y, inBirth( n ) ? 1 : 0 );
}
}
}
}
private:
int neighbours( int xx, int yy ) {
int n = 0, nx, ny;
for( int y = -1; y < 2; y++ ) {
for( int x = -1; x < 2; x++ ) {
if( !x && !y ) continue;
nx = ( wid + xx + x ) % wid;
ny = ( hei + yy + y ) % hei;
n += wrd->at( nx, ny ) > 0 ? 1 : 0;
}
}
return n;
}
bool inStay( int n ) {
return( _stay.end() != find( _stay.begin(), _stay.end(), n ) );
}
bool inBirth( int n ) {
return( _birth.end() != find( _birth.begin(), _birth.end(), n ) );
}
int wid, hei;
world *wrd, *wrdT;
std::vector<int> _stay, _birth;
};
class cellular {
public:
cellular( int w, int h ) : rl( 0 ) {
wrd = new world( w, h );
}
~cellular() {
if( rl ) delete rl;
delete wrd;
}
void start( int r ) {
rl = new rule( wrd );
gen = 1;
std::vector<int> t;
switch( r ) {
case 1: // conway
t.push_back( 2 ); t.push_back( 3 ); rl->setRuleS( t );
t.clear(); t.push_back( 3 ); rl->setRuleB( t );
break;
case 2: // amoeba
t.push_back( 1 ); t.push_back( 3 ); t.push_back( 5 ); t.push_back( 8 ); rl->setRuleS( t );
t.clear(); t.push_back( 3 ); t.push_back( 5 ); t.push_back( 7 ); rl->setRuleB( t );
break;
case 3: // life34
t.push_back( 3 ); t.push_back( 4 ); rl->setRuleS( t );
rl->setRuleB( t );
break;
case 4: // maze
t.push_back( 1 ); t.push_back( 2 ); t.push_back( 3 ); t.push_back( 4 ); t.push_back( 5 ); rl->setRuleS( t );
t.clear(); t.push_back( 3 ); rl->setRuleB( t );
break;
}

/* just for test - shoud read from a file */
/* GLIDER */
wrd->set( 6, 1, 1 ); wrd->set( 7, 2, 1 );
wrd->set( 5, 3, 1 ); wrd->set( 6, 3, 1 );
wrd->set( 7, 3, 1 );
wrd->set( 1, 3, 1 ); wrd->set( 2, 3, 1 );
wrd->set( 3, 3, 1 );
/******************************************/
generation();
}
private:
void display() {
system( "cls" );
int wid = wrd->wid(),
hei = wrd->hei();
std::cout << "+" << std::string( wid, '-' ) << "+\n";
for( int y = 0; y < hei; y++ ) {
std::cout << "|";
for( int x = 0; x < wid; x++ ) {
if( wrd->at( x, y ) ) std::cout << "#";
else std::cout << ".";
}
std::cout << "|\n";
}
std::cout << "+" << std::string( wid, '-' ) << "+\n";
std::cout << "Generation: " << gen << "\n\nPress [RETURN] for the next generation...";
std::cin.get();
}
void generation() {
do {
display();
rl->applyRules();
rl->swapWrds();
gen++;
}
while ( rl->hasLivingCells() );
}
rule* rl;
world* wrd;
int gen;
};

int main( int argc, char* argv[] ) {
cellular c( 20, 12 );
std::cout << "\n\t*** CELLULAR AUTOMATA ***" << "\n\n Which one you want to run?\n\n\n";
std::cout << " [1]\tConway's Life\n [2]\tAmoeba\n [3]\tLife 34\n [4]\tMaze\n\n > ";
int o;
do {
std::cin >> o;
}
while( o < 1 || o > 4 );
std::cin.ignore();
c.start( o );
return system( "pause" );
}
```
Output:
```
+--------------------+  +--------------------+  +--------------------+  +--------------------+
|....................|  |....................|  |....................|  |....................|
|......#.............|  |....................|  |....................|  |....................|
|.......#............|  |..#..#.#............|  |.......#............|  |..#...#.............|
|.###.###............|  |..#...##............|  |.###.#.#............|  |..#....##...........|
|....................|  |..#...#.............|  |......##............|  |..#...##............|
|....................|  |....................|  |....................|  |....................|
|....................|  |....................|  |....................|  |....................|
|....................|  |....................|  |....................|  |....................|
+--------------------+  +--------------------+  +--------------------+  +--------------------+
Generation: 1           Generation: 2           Generation: 3           Generation: 4

```

### Simple Without Classes

Shows a glider over 20 generations Board edges wrap around to simulate infinite board

```#include <iostream>
#include <vector>
#include <numeric>

// ----------------------------------------------------------------------------

using Row   = std::vector<int>;
using Cells = std::vector<Row>;

// ----------------------------------------------------------------------------

Cells board = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
};

int numRows = 10;
int numCols = 20;

// ----------------------------------------------------------------------------

int getNeighbor(int row, int col, Cells& board) {
// use modulus to get wrapping effect at board edges
return board.at((row + numRows) % numRows).at((col + numCols) % numCols);
}

int getCount(int row, int col, Cells& board) {
int count = 0;
std::vector<int> deltas {-1, 0, 1};
for (int dc : deltas) {
for (int dr : deltas) {
if (dr || dc) {
count += getNeighbor(row + dr, col + dc, board);
}
}
}
return count;
}

void showCell(int cell) {
std::cout << (cell ? "*" : " ");
}

void showRow(const Row& row) {
std::cout << "|";
for (int cell : row) {showCell(cell);}
std::cout << "|\n";
}

void showCells(Cells board) {
for (const Row& row : board) { showRow(row); }
}

int tick(Cells& board, int row, int col) {
int count = getCount(row, col, board);
bool birth = !board.at(row).at(col) && count == 3;
bool survive = board.at(row).at(col) && (count == 2 || count == 3);
return birth || survive;
}

void updateCells(Cells& board) {
Cells original = board;
for (int row = 0; row < numRows; row++) {
for (int col = 0; col < numCols; col++) {
board.at(row).at(col) = tick(original, row, col);
}
}
}

int main () {
for (int gen = 0; gen < 20; gen++) {
std::cout << "\ngeneration " << gen << ":\n";
showCells(board);
updateCells(board);
}
}
```
Output:
```
generation 0:
|                    |
|  *                 |
|   *                |
| ***                |
|                    |
|                    |
|                    |
|                    |
|                    |
|                    |
generation 1:
|                    |
|                    |
| * *                |
|  **                |
|  *                 |
|                    |
|                    |
|                    |
|                    |
|                    |
generation 2:
|                    |
|                    |
|   *                |
| * *                |
|  **                |
|                    |
|                    |
|                    |
|                    |
|                    |
generation 3:
|                    |
|                    |
|  *                 |
|   **               |
|  **                |
|                    |
|                    |
|                    |
|                    |
|                    |
...

```

## Chapel

```config const gridHeight: int = 3;
config const gridWidth: int = 3;

enum State { dead = 0, alive = 1 };

class ConwaysGameofLife {

var gridDomain: domain(2);
var computeDomain: subdomain( gridDomain );
var grid: [gridDomain] int;

proc ConwaysGameofLife( height: int, width: int ) {
this.gridDomain = {0..#height+2, 0..#width+2};
this.computeDomain = this.gridDomain.expand( -1 );
}

proc step(){

var tempGrid: [this.computeDomain] State;
forall (i,j) in this.computeDomain {
var isAlive = this.grid[i,j] == State.alive;
var numAlive = (+ reduce this.grid[ i-1..i+1, j-1..j+1 ]) - if isAlive then 1 else 0;
tempGrid[i,j] = if ( (2 == numAlive && isAlive) || numAlive == 3 ) then State.alive else State.dead ;
}

this.grid[this.computeDomain] = tempGrid;

}

proc this( i: int, j: int ) ref : State {
return this.grid[i,j];
}

proc prettyPrint(): string {
var str: string;
for i in this.gridDomain.dim(1) {
if i == 0 || i == gridDomain.dim(1).last {
for j in this.gridDomain.dim(2) {
str += "-";
}
} else {
for j in this.gridDomain.dim(2) {
if j == 0 || j == this.gridDomain.dim(2).last {
str += "|";
} else {
str += if this.grid[i,j] == State.alive then "#" else " ";
}
}
}
str += "\n";
}
return str;
}

}

proc main{
var game = new ConwaysGameofLife( gridHeight, gridWidth );
game[gridHeight/2 + 1, gridWidth/2     ] = State.alive;
game[gridHeight/2 + 1, gridWidth/2 + 1 ] = State.alive;
game[gridHeight/2 + 1, gridWidth/2 + 2 ] = State.alive;
for i in 1..3 {
writeln( game.prettyPrint() );
game.step();
}
}
```

Output:

```-----
|   |
|###|
|   |
-----

-----
| # |
| # |
| # |
-----

-----
|   |
|###|
|   |
-----

```

## Clojure

Based on the implementation by Christophe Grand here: http://clj-me.cgrand.net/2011/08/19/conways-game-of-life/ This implementation models the live cells as a set of coordinates.

```(defn moore-neighborhood [[x y]]
(for [dx [-1 0 1]
dy [-1 0 1]
:when (not (= [dx dy] [0 0]))]
[(+ x dx) (+ y dy)]))

(defn step [set-of-cells]
(set (for [[cell count] (frequencies (mapcat moore-neighborhood set-of-cells))
:when (or (= 3 count)
(and (= 2 count) (contains? set-of-cells cell)))]
cell)))

(defn print-world
([set-of-cells] (print-world set-of-cells 10))
([set-of-cells world-size]
(let [r (range 0 (+ 1 world-size))]
(pprint (for [y r] (apply str (for [x r] (if (set-of-cells [x y]) \# \.))))))))

(defn run-life [world-size num-steps set-of-cells]
(loop [s num-steps
cells set-of-cells]
(print-world cells world-size)
(when (< 0 s)
(recur (- s 1) (step cells)))))

(def *blinker* #{[1 2] [2 2] [3 2]})
(def *glider* #{[1 0] [2 1] [0 2] [1 2] [2 2]})
```

## COBOL

```identification division.
program-id. game-of-life-program.

data division.
working-storage section.
01  grid.
05 cell-table.
10 row occurs 5 times.
15 cell pic x value space occurs 5 times.
05 next-gen-cell-table.
10 next-gen-row occurs 5 times.
15 next-gen-cell pic x occurs 5 times.
01  counters.
05 generation pic 9.
05 current-row pic 9.
05 current-cell pic 9.
05 living-neighbours pic 9.
05 neighbour-row pic 9.
05 neighbour-cell pic 9.
05 check-row pic s9.
05 check-cell pic s9.

procedure division.
control-paragraph.
perform blinker-paragraph varying current-cell from 2 by 1
until current-cell is greater than 4.
perform show-grid-paragraph through life-paragraph
varying generation from 0 by 1
until generation is greater than 2.
stop run.
move '#' to cell(3,current-cell).
show-grid-paragraph.
display 'GENERATION ' generation ':'.
display '   +---+'.
perform show-row-paragraph varying current-row from 2 by 1
until current-row is greater than 4.
display '   +---+'.
display ''.
life-paragraph.
perform update-row-paragraph varying current-row from 2 by 1
until current-row is greater than 4.
move next-gen-cell-table to cell-table.
show-row-paragraph.
display '   |' with no advancing.
perform show-cell-paragraph varying current-cell from 2 by 1
until current-cell is greater than 4.
display '|'.
show-cell-paragraph.
update-row-paragraph.
perform update-cell-paragraph varying current-cell from 2 by 1
until current-cell is greater than 4.
update-cell-paragraph.
move 0 to living-neighbours.
perform check-row-paragraph varying check-row from -1 by 1
until check-row is greater than 1.
evaluate living-neighbours,
when 2 move cell(current-row,current-cell) to next-gen-cell(current-row,current-cell),
when 3 move '#' to next-gen-cell(current-row,current-cell),
when other move space to next-gen-cell(current-row,current-cell),
end-evaluate.
check-row-paragraph.
add check-row to current-row giving neighbour-row.
perform check-cell-paragraph varying check-cell from -1 by 1
until check-cell is greater than 1.
check-cell-paragraph.
add check-cell to current-cell giving neighbour-cell.
if cell(neighbour-row,neighbour-cell) is equal to '#',
and check-cell is not equal to zero or check-row is not equal to zero,

end program game-of-life-program.
```
Output:
```GENERATION 0:
+---+
|   |
|###|
|   |
+---+

GENERATION 1:
+---+
| # |
| # |
| # |
+---+

GENERATION 2:
+---+
|   |
|###|
|   |
+---+```

## Common Lisp

```(defun next-life (array &optional results)
(let* ((dimensions (array-dimensions array))
(results (or results (make-array dimensions :element-type 'bit))))
(destructuring-bind (rows columns) dimensions
(labels ((entry (row col)
"Return array(row,col) for valid (row,col) else 0."
(if (or (not (< -1 row rows))
(not (< -1 col columns)))
0
(aref array row col)))
(neighbor-count (row col &aux (count 0))
"Return the sum of the neighbors of (row,col)."
(dolist (r (list (1- row) row (1+ row)) count)
(dolist (c (list (1- col) col (1+ col)))
(unless (and (eql r row) (eql c col))
(incf count (entry r c))))))
(live-or-die? (current-state neighbor-count)
(if (or (and (eql current-state 1)
(<=  2 neighbor-count 3))
(and (eql current-state 0)
(eql neighbor-count 3)))
1
0)))
(dotimes (row rows results)
(dotimes (column columns)
(setf (aref results row column)
(live-or-die? (aref array row column)
(neighbor-count row column)))))))))

(defun print-grid (grid &optional (out *standard-output*))
(destructuring-bind (rows columns) (array-dimensions grid)
(dotimes (r rows grid)
(dotimes (c columns (terpri out))
(write-char (if (zerop (aref grid r c)) #\+ #\#) out)))))

(defun run-life (&optional world (iterations 10) (out *standard-output*))
(let* ((world (or world (make-array '(10 10) :element-type 'bit)))
(result (make-array (array-dimensions world) :element-type 'bit)))
(do ((i 0 (1+ i))) ((eql i iterations) world)
(terpri out) (print-grid world out)
(psetq world (next-life world result)
result world))))
```
```(run-life (make-array '(3 3)
:element-type 'bit
:initial-contents '((0 0 0)
(1 1 1)
(0 0 0)))
3)
```

produces

```+++
###
+++

+#+
+#+
+#+

+++
###
+++```

A version using a sparse list of living cells rather than an explicit board.

```(defun moore-neighborhood (cell)
(let ((r '(-1 0 1)))
(mapcan
(lambda (delta-x)
(loop for delta-y in r
unless (and (= delta-x 0) (= delta-y 0))
collect (cons (+ (car cell) delta-x) (+ (cdr cell) delta-y))))
r)))

(defun frequencies (cells)
(let ((h (make-hash-table :test #'equal)))
(loop for c in cells
if (gethash c h)
do (incf (gethash c h))
else
do (setf (gethash c h) 1))
h))

(defun life-step (cells)
(let ((f (frequencies (mapcan #'moore-neighborhood cells))))
(loop for k being the hash-keys in f
when (or
(= (gethash k f) 3)
(and (= (gethash k f) 2) (member k cells :test #'equal)))
collect k)))

(defun print-world (live-cells &optional (world-size 10))
(dotimes (y world-size)
(dotimes (x world-size)
(if (member (cons x y) live-cells :test #'equal)
(format t "X")
(format t ".")))
(format t "~%")))

(defun run-life (world-size steps cells)
(print-world cells world-size)
(format t "~%")
(when (< 0 steps)
(run-life world-size (- steps 1) (life-step cells))))

(defparameter *blinker* '((1 . 2) (2 . 2) (3 . 2)))
(defparameter *glider* '((1 . 0) (2 . 1) (0 . 2) (1 . 2) (2 . 2)))
```

## D

```import std.stdio, std.string, std.algorithm, std.array, std.conv;

struct GameOfLife {
enum Cell : char { dead = ' ', alive = '#' }
Cell[][] grid, newGrid;

this(in int x, in int y) pure nothrow @safe {
grid = new typeof(grid)(y + 2, x + 2);
newGrid = new typeof(grid)(y + 2, x + 2);
}

void opIndexAssign(in string[] v, in size_t y, in size_t x)
pure /*nothrow*/ @safe /*@nogc*/ {
foreach (immutable nr, row; v)
foreach (immutable nc, state; row)
grid[y + nr][x + nc] = state.to!Cell;
}

void iteration() pure nothrow @safe @nogc {
foreach (row; newGrid)
row[0] = row[\$ - 1] = Cell.dead;

foreach (immutable r; 1 .. grid.length - 1)
foreach (immutable c; 1 .. grid[0].length - 1) {
uint count = 0;
foreach (immutable i; -1 .. 2)
foreach (immutable j; -1 .. 2)
if (i != 0 || j != 0)
count += grid[r + i][c + j] == Cell.alive;
immutable a = count == 3 ||
(count == 2 && grid[r][c] == Cell.alive);
newGrid[r][c] = a ? Cell.alive : Cell.dead;
}

grid.swap(newGrid);
}

string toString() const pure /*nothrow @safe*/ {
auto ret = "-".replicate(grid[0].length - 1) ~ "\n";
foreach (const row; grid[1 .. \$ - 1])
ret ~= "|%(%c%)|\n".format(row[1 .. \$ - 1]);
return ret ~ "-".replicate(grid[0].length - 1);
}
}

void main() /*@safe*/ {
immutable glider1 = ["  #", "# #", " ##"];
immutable glider2 = ["#  ", "# #", "## "];

auto uni = GameOfLife(60, 20);
uni[3,  2] = glider1;
uni[3, 15] = glider2;
uni[3, 19] = glider1;
uni[3, 32] = glider2;
uni[5, 50] = [" #  #", "#  ", "#   #", "#### "];
uni.writeln;

foreach (immutable _; 0 .. 20) {
uni.iteration;
uni.writeln;
}
}
```
Output, first iteration:
```-------------------------------------------------------------
|                                                            |
|                                                            |
|   #          #     #          #                            |
| # #          # # # #          # #                          |
|  ##          ##   ##          ##                 #  #      |
|                                                 #          |
|                                                 #   #      |
|                                                 ####       |
|                                                            |
|                                                            |
|                                                            |
|                                                            |
|                                                            |
|                                                            |
|                                                            |
|                                                            |
|                                                            |
|                                                            |
|                                                            |
|                                                            |
-------------------------------------------------------------```

### Faster Version

Same output.

```import std.stdio, std.string, std.algorithm, std.typetuple,
std.array, std.conv;

struct GameOfLife {
enum Cell : char { dead = ' ', alive = '#' }
Cell[] grid, newGrid;
immutable size_t nCols;

this(in int nx, in int ny) pure nothrow @safe {
nCols = nx + 2;
grid = new typeof(grid)(nCols * (ny + 2));
newGrid = new typeof(grid)(grid.length);
}

void opIndexAssign(in string[] v, in size_t y, in size_t x)
pure /*nothrow*/ @safe /*@nogc*/ {
foreach (immutable nr, const row; v)
foreach (immutable nc, immutable state; row)
grid[(y + nr) * nCols + x + nc] = state.to!Cell;
}

void iteration() pure nothrow @safe @nogc {
newGrid[\$ - nCols .. \$] = Cell.dead;
foreach (immutable nr; 1 .. (newGrid.length / nCols) - 1) {
newGrid[nr * nCols + 0] = Cell.dead;
newGrid[nr * nCols + nCols - 1] = Cell.dead;
}

foreach (immutable nr; 1 .. (grid.length / nCols) - 1) {
size_t nr_nCols = nr * nCols;
foreach (immutable nc; 1 .. nCols - 1) {
uint count = 0;
/*static*/ foreach (immutable i; TypeTuple!(-1, 0, 1))
/*static*/ foreach (immutable j; TypeTuple!(-1, 0, 1))
static if (i != 0 || j != 0)
count += (grid[nr_nCols + i * nCols + nc + j] == Cell.alive);
immutable a = count == 3 ||
(count == 2 && grid[nr_nCols + nc] == Cell.alive);
newGrid[nr_nCols + nc] = a ? Cell.alive : Cell.dead;
}
}

swap(grid, newGrid);
}

string toString() const pure /*nothrow @safe*/ {
string ret = "-".replicate(nCols - 1) ~ "\n";
foreach (immutable nr; 1 .. (grid.length / nCols) - 1)
ret ~= "|%(%c%)|\n".format(grid[nr * nCols + 1 .. nr * nCols + nCols - 1]);
return ret ~ "-".replicate(nCols - 1);
}
}

void main() {
immutable glider1 = ["  #", "# #", " ##"];
immutable glider2 = ["#  ", "# #", "## "];

auto uni = GameOfLife(60, 20);
uni[3,  2] = glider1;
uni[3, 15] = glider2;
uni[3, 19] = glider1;
uni[3, 32] = glider2;
uni[5, 50] = [" #  #", "#  ", "#   #", "#### "];
uni.writeln;

foreach (immutable _; 0 .. 20) {
uni.iteration;
uni.writeln;
}
}
```

## Dart

```/**
* States of a cell. A cell is either [ALIVE] or [DEAD].
* The state contains its [symbol] for printing.
*/
class State {
const State(this.symbol);

static final ALIVE = const State('#');
static final DEAD = const State(' ');

final String symbol;
}

/**
* The "business rule" of the game. Depending on the count of neighbours,
* the [cellState] changes.
*/
class Rule {
Rule(this.cellState);

reactToNeighbours(int neighbours) {
if (neighbours == 3) {
cellState = State.ALIVE;
} else if (neighbours != 2) {
}
}

var cellState;
}

/**
* A coordinate on the [Grid].
*/
class Point {
const Point(this.x, this.y);

operator +(other) => new Point(x + other.x, y + other.y);

final int x;
final int y;
}

/**
* List of the relative indices of the 8 cells around a cell.
*/
class Neighbourhood {
List<Point> points() {
return [
new Point(LEFT, UP), new Point(MIDDLE, UP), new Point(RIGHT, UP),
new Point(LEFT, SAME), new Point(RIGHT, SAME),
new Point(LEFT, DOWN), new Point(MIDDLE, DOWN), new Point(RIGHT, DOWN)
];
}

static final LEFT = -1;
static final MIDDLE = 0;
static final RIGHT = 1;
static final UP = -1;
static final SAME = 0;
static final DOWN = 1;
}

/**
* The grid is an endless, two-dimensional [field] of cell [State]s.
*/
class Grid {
Grid(this.xCount, this.yCount) {
_field = new Map();
_neighbours = new Neighbourhood().points();
}

set(point, state) {
_field[_pos(point)] = state;
}

State get(point) {
var state = _field[_pos(point)];
return state != null ? state : State.DEAD;
}

int countLiveNeighbours(point) =>
_neighbours.filter((offset) => get(point + offset) == State.ALIVE).length;

_pos(point) => '\${(point.x + xCount) % xCount}:\${(point.y + yCount) % yCount}';

print() {
var sb = new StringBuffer();
return sb.toString();
}

iterate(eachCell, [finishedRow]) {
for (var x = 0; x < xCount; x++) {
for (var y = 0; y < yCount; y++) {
eachCell(new Point(x, y));
}
if(finishedRow != null) {
finishedRow(x);
}
}
}

final xCount, yCount;
List<Point> _neighbours;
Map<String, State> _field;
}

/**
* The game updates the [grid] in each step using the [Rule].
*/
class Game {
Game(this.grid);

tick() {
var newGrid = createNewGrid();

grid.iterate((point) {
var rule = new Rule(grid.get(point));
rule.reactToNeighbours(grid.countLiveNeighbours(point));
newGrid.set(point, rule.cellState);
});

grid = newGrid;
}

createNewGrid() => new Grid(grid.xCount, grid.yCount);

printGrid() => print(grid.print());

Grid grid;
}

main() {
// Run the GoL with a blinker.
}

for(int i = 0; i < 3; i++) {
game.printGrid();
game.tick();
}
game.printGrid();
}

var grid = new Grid(4, 4);
return grid;
}

blinkerPoints() => [new Point(0, 1), new Point(1, 1), new Point(2, 1)];
```

Test cases driving the design of this code:

```#import('<path to sdk>/lib/unittest/unittest.dart');

main() {
group('rules', () {
test('should let living but lonely cell die', () {
var rule = new Rule(State.ALIVE);
rule.reactToNeighbours(1);
});
test('should let proper cell live on', () {
var rule = new Rule(State.ALIVE);
rule.reactToNeighbours(2);
expect(rule.cellState, State.ALIVE);
});
test('should let dead cell with three neighbours be reborn', () {
rule.reactToNeighbours(3);
expect(rule.cellState, State.ALIVE);
});
test('should let living cell with too many neighbours die', () {
var rule = new Rule(State.ALIVE);
rule.reactToNeighbours(4);
});
});

group('grid', () {
var origin = new Point(0, 0);
test('should have state', () {
var grid = new Grid(1, 1);
grid.set(origin, State.ALIVE);
expect(grid.get(origin), State.ALIVE);
});
test('should have dimension', () {
var grid = new Grid(2, 3);
grid.set(origin, State.ALIVE);
expect(grid.get(origin), State.ALIVE);
grid.set(new Point(1, 2), State.ALIVE);
expect(grid.get(new Point(1, 2)), State.ALIVE);
});
test('should be endless', () {
var grid = new Grid(2, 4);
grid.set(new Point(2, 4), State.ALIVE);
expect(grid.get(origin), State.ALIVE);
grid.set(new Point(-1, -1), State.ALIVE);
expect(grid.get(new Point(1, 3)), State.ALIVE);
});
test('should print itself', () {
var grid = new Grid(1, 2);
grid.set(new Point(0, 1), State.ALIVE);
expect(grid.print(), " #\n");
});
});

group('game', () {
test('should exists', () {
var game = new Game(null);
expect(game, isNotNull);
});
test('should create a new grid when ticked', () {
var grid = new Grid(1, 1);
var game = new Game(grid);
game.tick();
expect(game.grid !== grid);
});
test('should have a grid with the same dimension after tick', (){
var game = new Game(new Grid(2, 3));
game.tick();
expect(game.grid.xCount, 2);
expect(game.grid.yCount, 3);
});
test('should apply rules to middle cell', (){
var grid = new Grid(3, 3);
grid.set(new Point(1, 1), State.ALIVE);
var game = new Game(grid);
game.tick();

grid.set(new Point(0, 0), State.ALIVE);
grid.set(new Point(1, 0), State.ALIVE);
game = new Game(grid);
game.tick();
expect(game.grid.get(new Point(1, 1)), State.ALIVE);
});
test('should apply rules to all cells', (){
var grid = new Grid(3, 3);
grid.set(new Point(0, 1), State.ALIVE);
grid.set(new Point(1, 0), State.ALIVE);
grid.set(new Point(1, 1), State.ALIVE);
var game = new Game(grid);
game.tick();
expect(game.grid.get(new Point(0, 0)), State.ALIVE);
});
});
}
```
Output:
``` #
#
#

###

#
#
#

###

```

## Delphi

Translation of: Go

Thanks Rudy Velthuis for the Velthuis.Console library.

```program game_of_life;

{\$APPTYPE CONSOLE}

uses
System.SysUtils,
Velthuis.Console; // CrlScr

type
TBoolMatrix = TArray<TArray<Boolean>>;

TField = record
s: TBoolMatrix;
w, h: Integer;
procedure SetValue(x, y: Integer; b: boolean);
function Next(x, y: Integer): boolean;
function State(x, y: Integer): boolean;
class function NewField(w1, h1: Integer): TField; static;
end;

TLife = record
a, b: TField;
w, h: Integer;
class function NewLife(w1, h1: Integer): TLife; static;
procedure Step;
function ToString: string;
end;

{ TField }

class function TField.NewField(w1, h1: Integer): TField;
var
s1: TBoolMatrix;
begin
SetLength(s1, h1);
for var i := 0 to High(s1) do
SetLength(s1[i], w1);
with Result do
begin
s := s1;
w := w1;
h := h1;
end;
end;

function TField.Next(x, y: Integer): boolean;
var
_on: Integer;
begin
_on := 0;
for var i := -1 to 1 do
for var j := -1 to 1 do
if self.State(x + i, y + j) and not ((j = 0) and (i = 0)) then
inc(_on);
Result := (_on = 3) or (_on = 2) and self.State(x, y);
end;

procedure TField.SetValue(x, y: Integer; b: boolean);
begin
self.s[y, x] := b;
end;

function TField.State(x, y: Integer): boolean;
begin
while y < 0 do
inc(y, self.h);
while x < 0 do
inc(x, self.w);
result := self.s[y mod self.h, x mod self.w]
end;

{ TLife }

class function TLife.NewLife(w1, h1: Integer): TLife;
var
a1: TField;
begin
a1 := TField.NewField(w1, h1);
for var i := 0 to (w1 * h1 div 2) do
a1.SetValue(Random(w1), Random(h1), True);
with Result do
begin
a := a1;
b := TField.NewField(w1, h1);
w := w1;
h := h1;
end;
end;

procedure TLife.Step;
var
tmp: TField;
begin
for var y := 0 to self.h - 1 do
for var x := 0 to self.w - 1 do
self.b.SetValue(x, y, self.a.Next(x, y));
tmp := self.a;
self.a := self.b;
self.b := tmp;
end;

function TLife.ToString: string;
begin
result := '';
for var y := 0 to self.h - 1 do
begin
for var x := 0 to self.w - 1 do
begin
var b: char := ' ';
if self.a.State(x, y) then
b := '*';
result := result + b;
end;
result := result + #10;
end;
end;

begin
Randomize;

var life := TLife.NewLife(80, 15);

for var i := 1 to 300 do
begin
life.Step;
ClrScr;
writeln(life.ToString);
sleep(30);
end;
end.
```
Output:
```                *  ***   *        *                   *
*  **                                           **      *
****     *                                   *  *      *
*** *                               *  ** *       *
*** **                              * *  *
*        *                                   *
** **   ****                                ** *
******    **                                  * *
*  *                                     * *** **     ***
**                                          * *
*                                 *    **
*                                   * *
*  *            *                         *
* ***        * *                  *     **
* ***        * *                  *                    ***```

## E

Just does three generations of a blinker in a dead-boundary grid, as specified. (User:Kevin Reid has graphical and wrapping versions.)

```def gridWidth := 3
def gridHeight := 3
def X := 0..!gridWidth
def Y := 0..!gridHeight

def makeFlexList := <elib:tables.makeFlexList>
def makeGrid() {
def storage := makeFlexList.fromType(<type:java.lang.Boolean>, gridWidth * gridHeight)
storage.setSize(gridWidth * gridHeight)

def grid {
to __printOn(out) {
for y in Y {
out.print("[")
for x in X {
out.print(grid[x, y].pick("#", " "))
}
out.println("]")
}
}
to get(xb :int, yb :int) {
return if (xb =~ x :X && yb =~ y :Y) {
storage[y * gridWidth + x]
} else {
false
}
}
to put(x :X, y :Y, c :boolean) {
storage[y * gridWidth + x] := c
}
}
return grid
}

def mooreNeighborhood := [[-1,-1],[0,-1],[1,-1],[-1,0],[1,0],[-1,1],[0,1],[1,1]]
def computeNextLife(prevGrid, nextGrid) {
for y in Y {
for x in X {
var neighbors := 0
for [nx, ny] ? (prevGrid[x+nx, y+ny]) in mooreNeighborhood {
neighbors += 1
}
def self := prevGrid[x, y]
nextGrid[x, y] := (self && neighbors == 2 || neighbors == 3)
}
}
}

var currentFrame := makeGrid()
var nextFrame := makeGrid()
currentFrame[1, 0] := true
currentFrame[1, 1] := true
currentFrame[1, 2] := true

for _ in 1..3 {
def frame := nextFrame
computeNextLife(currentFrame, frame)
nextFrame := currentFrame
currentFrame := frame
println(currentFrame)
}```

## EasyLang

```n = 70
time = 0.1
#
nx = n + 1
subr init
for r = 1 to n
for c = 1 to n
i = r * nx + c
if randomf < 0.3
f[i] = 1
.
.
.
.
f = 100 / n
subr show
clear
for r = 1 to n
for c = 1 to n
if f[r * nx + c] = 1
move c * f - f r * f - f
rect f * 0.9 f * 0.9
.
.
.
.
subr update
swap f[] p[]
for r = 1 to n
sm = 0
i = r * nx + 1
sr = p[i - nx] + p[i] + p[i + nx]
for c = 1 to n
sl = sm
sm = sr
in = i + 1
sr = p[in - nx] + p[in] + p[in + nx]
s = sl + sm + sr
if s = 3 or s = 4 and p[i] = 1
f[i] = 1
else
f[i] = 0
.
i = in
.
.
.
on timer
update
show
timer time
.
on mouse_down
c = mouse_x div f + 1
r = mouse_y div f + 1
i = r * nx + c
f[i] = 1 - f[i]
show
timer 3
.
len f[] nx * nx + nx
len p[] nx * nx + nx
init
timer 0
```

## eC

Library: Ecere
```import "ecere"

define seed = 12345;
define popInit = 1000;
define width = 100;
define height = 100;
define cellWidth = 4;
define cellHeight = 4;

Array<byte> grid { size = width * height };
Array<byte> newState { size = width * height };

class GameOfLife : Window
{
caption = \$"Conway's Game of Life";
background = lightBlue;
borderStyle = sizable;
hasMaximize = true;
hasMinimize = true;
hasClose = true;
clientSize = { width * cellWidth, height * cellHeight };

Timer tickTimer
{
delay = 0.05, started = true, userData = this;

bool DelayExpired()
{
int y, x, ix = 0;
for(y = 0; y < height; y++)
{
for(x = 0; x < width; x++, ix++)
{
int nCount = 0;
byte alive;
if(x > 0       && y > 0        && grid[ix - width - 1]) nCount++;
if(               y > 0        && grid[ix - width    ]) nCount++;
if(x < width-1 && y > 0        && grid[ix - width + 1]) nCount++;
if(x > 0                       && grid[ix         - 1]) nCount++;
if(x < width - 1               && grid[ix         + 1]) nCount++;
if(x > 0       && y < height-1 && grid[ix + width - 1]) nCount++;
if(               y < height-1 && grid[ix + width    ]) nCount++;
if(x < width-1 && y < height-1 && grid[ix + width + 1]) nCount++;

if(grid[ix])
alive = nCount >= 2 && nCount <= 3; // Death
else
alive = nCount == 3; // Birth
newState[ix] = alive;
}
}
memcpy(grid.array, newState.array, width * height);
Update(null);
return true;
}
};

void OnRedraw(Surface surface)
{
int x, y;
int ix = 0;

surface.background = navy;
for(y = 0; y < height; y++)
{
for(x = 0; x < width; x++, ix++)
{
if(grid[ix])
{
int sy = y * cellHeight;
int sx = x * cellWidth;
surface.Area(sx, sy, sx + cellWidth-1, sy + cellHeight-1);
}
}
}
}

bool OnCreate()
{
int i;

RandomSeed(seed);

for(i = 0; i < popInit; i++)
{
int x = GetRandom(0, width-1);
int y = GetRandom(0, height-1);

grid[y * width + x] = 1;
}
return true;
}
}

GameOfLife life {};
```

## Egel

```import "prelude.eg"
import "io.ego"

using System
using List
using IO

def boardsize = 5

def empty = [ X Y -> 0 ]

def insert =
[ X Y BOARD ->
[ X0 Y0 -> if and (X0 == X) (Y0 == Y) then 1
else BOARD X0 Y0 ] ]

def coords =
let R = fromto 0 (boardsize - 1) in
[ XX YY -> map (\X -> map (\Y -> X Y) YY) XX ] R R

def printcell =
[ 0 -> print ". "
| _ -> print "* " ]

def printboard =
[ BOARD ->
let M  = map [XX -> let _ = map [(X Y) -> printcell (BOARD X Y)] XX in print "\n" ] coords in
nop ]

def count =
[ BOARD, X, Y ->
(BOARD (X - 1) (Y - 1)) + (BOARD (X) (Y - 1)) + (BOARD (X+1) (Y - 1)) +
(BOARD (X - 1) Y) + (BOARD (X+1) Y) +
(BOARD (X - 1) (Y+1)) + (BOARD (X) (Y+1)) + (BOARD (X+1) (Y+1)) ]

def next =
[ 0 N -> if N == 3 then 1 else 0
| _ N -> if or (N == 2) (N == 3) then 1 else 0 ]

def updateboard =
[ BOARD ->
let XX = map (\(X Y) -> X Y (BOARD X Y) (count BOARD X Y)) (flatten coords) in
let YY = map (\(X Y C N) -> X Y (next C N)) XX in
foldr [(X Y 0) BOARD -> BOARD | (X Y _) BOARD -> insert X Y BOARD ] empty YY ]

(insert 1 2) @ (insert 2 2) @ (insert 3 2)

def main =
let GEN0 = blinker empty in
let GEN1 = updateboard GEN0 in
let GEN2 = updateboard GEN1 in
let _ = map [ G -> let _ = print "generation:\n" in printboard G ] {GEN0, GEN1, GEN2} in
nop```

## Elena

ELENA 6.0, using cellular library

```import extensions;
import system'text;
import cellular;

const int maxX = 48;
const int maxY = 28;

const int DELAY = 50;

sealed class Model
{
Space   _space;
RuleSet _ruleSet;
bool    _started;

Func<Space, object> OnUpdate : event;

constructor newRandomset(RuleSet transformSet)
{
_space := IntMatrixSpace.allocate(maxY, maxX, randomSet);

_ruleSet := transformSet;

_started := false
}

private onUpdate()
{
OnUpdate.?(_space)
}

run()
{
if (_started)
{
_space.update(_ruleSet)
}
else
{
_started := true
};

self.onUpdate()
}
}

singleton gameOfLifeRuleSet : RuleSet
{
int proceed(Space s, int x, int y)
{
int cell := s.at(x, y);
int number := s.LiveCell(x, y, 1); // NOTE : number of living cells around the self includes the cell itself

if (cell == 0 && number == 3)
{
^ 1
}
else if (cell == 1 && (number == 4 || number == 3))
{
^ 1
}
else
{
^ 0
}
}
}

public extension presenterOp : Space
{
print()
{
console.setCursorPosition(0, 0);

int columns := self.Columns;
int rows := self.Rows;

auto line := new TextBuilder();
for(int i := 0, i < rows, i += 1)
{
line.clear();
for(int j := 0, j < columns, j += 1)
{
int cell := self.at(i, j);

line.write((cell == 0).iif(" ","o"));
};

console.writeLine(line.Value)
}
}
}

public program()
{
auto model := Model.newRandomset(gameOfLifeRuleSet);
console.clear();

model.OnUpdate := (Space sp){ sp.print() };

until (console.KeyAvailable)
{
model.run();

};

}```

## Elixir

Works with: Elixir version 1.2
Translation of: Ruby
```defmodule Conway do
def game_of_life(name, size, generations, initial_life\\nil) do
board = seed(size, initial_life)
print_board(board, name, size, 0)
reason = generate(name, size, generations, board, 1)
case reason do
:static   -> "no movement"
end
|> IO.puts
IO.puts ""
end

defp new_board(n) do
for x <- 1..n, y <- 1..n, into: %{}, do: {{x,y}, 0}
end

defp seed(n, points) do
if points do
points
else # randomly seed board
(for x <- 1..n, y <- 1..n, do: {x,y}) |> Enum.take_random(10)
end
|> Enum.reduce(new_board(n), fn pos,acc -> %{acc | pos => 1} end)
end

defp generate(_, _, generations, _, gen) when generations < gen, do: :ok
defp generate(name, size, generations, board, gen) do
new = evolve(board, size)
print_board(new, name, size, gen)
cond do
board == new -> :static
true         -> generate(name, size, generations, new, gen+1)
end
end

defp evolve(board, n) do
for x <- 1..n, y <- 1..n, into: %{}, do: {{x,y}, fate(board, x, y, n)}
end

defp fate(board, x, y, n) do
irange = max(1, x-1) .. min(x+1, n)
jrange = max(1, y-1) .. min(y+1, n)
sum = ((for i <- irange, j <- jrange, do: board[{i,j}]) |> Enum.sum) - board[{x,y}]
cond do
sum == 3                       -> 1
sum == 2 and board[{x,y}] == 1 -> 1
true                           -> 0
end
end

defp barren?(board) do
Enum.all?(board, fn {_,v} -> v == 0 end)
end

defp print_board(board, name, n, generation) do
IO.puts "#{name}: generation #{generation}"
Enum.each(1..n, fn y ->
Enum.map(1..n, fn x -> if board[{x,y}]==1, do: "#", else: "." end)
|> IO.puts
end)
end
end

Conway.game_of_life("glider", 4, 4, [{2,1},{3,2},{1,3},{2,3},{3,3}])
Conway.game_of_life("random", 5, 10)
```
Output:
```blinker: generation 0
.#.
.#.
.#.
...
###
...
.#.
.#.
.#.

glider: generation 0
.#..
..#.
###.
....
glider: generation 1
....
#.#.
.##.
.#..
glider: generation 2
....
..#.
#.#.
.##.
glider: generation 3
....
.#..
..##
.##.
glider: generation 4
....
..#.
...#
.###

random: generation 0
.#...
#.#..
#...#
###.#
..#..
random: generation 1
.#...
#....
#.#..
#.#..
..##.
random: generation 2
.....
#....
#....
..#..
.###.
random: generation 3
.....
.....
.#...
..##.
.###.
random: generation 4
.....
.....
..#..
...#.
.#.#.
random: generation 5
.....
.....
.....
...#.
..#..
random: generation 6
.....
.....
.....
.....
.....
no more life.
```

## Emacs Lisp

```#!/usr/bin/env emacs -script
;; -*- lexical-binding: t -*-
;; run: ./conways-life conways-life.config
(require 'cl-lib)

(defconst pentomino-p '(".**" ".**" ".*."))
(defconst pi-heptomino '("***" "*.*" "*.*"))
(defconst glider '(".*." "..*" "***"))
(defconst pre-pulsar '("***...***" "*.*...*.*" "***...***"))
(defconst ship '("**." "*.*" ".**"))
(defconst clock '("..*." "*.*." ".*.*" ".*.."))

(defmacro swap (a b)
`(setq ,b (prog1 ,a (setq ,a ,b))))

(cl-defstruct world rows cols data)

(defun new-world (rows cols)
(make-world :rows rows :cols cols :data (make-vector (* rows cols) nil)))

(defmacro world-pt (w r c)
`(+ (* (mod ,r (world-rows ,w)) (world-cols ,w))
(mod ,c (world-cols ,w))))

(defmacro world-ref (w r c)
`(aref (world-data ,w) (world-pt ,w ,r ,c)))

(defun print-world (world)
(dotimes (r (world-rows world))
(dotimes (c (world-cols world))
(princ (format "%c" (if (world-ref world r c) ?* ?.))))
(terpri)))

(defun insert-pattern (world row col shape)
(let ((r row)
(c col))
(unless (listp shape)
(setq shape (symbol-value shape)))
(dolist (row-data shape)
(dolist (col-data (mapcar 'identity row-data))
(setf (world-ref world r c) (not (or (eq col-data ?.))))
(setq c (1+ c)))
(setq r (1+ r))
(setq c col))))

(defun neighbors (world row col)
(let ((n 0))
(dolist (offset '((1 . 1) (1 . 0) (1 . -1) (0 . 1) (0 . -1) (-1 . 1) (-1 . 0) (-1 . -1)))
(when (world-ref world (+ row (car offset)) (+ col (cdr offset)))
(setq n (1+ n))))
n))

(dotimes (r (world-rows old))
(dotimes (c (world-cols old))
(let ((n (neighbors old r c)))
(setf (world-ref new r c)
(if (world-ref old r c)
(or (= n 2) (= n 3))
(= n 3)))))))

(with-temp-buffer
(insert-file-contents-literally file-name)

(defun get-config (key config)
(let ((val (assoc key config)))
(if (null val)
(error (format "missing value for %s" key))
(cdr val))))

(defun insert-patterns (world patterns)
(dolist (p patterns)
(apply 'insert-pattern (cons world p))))

(defun simulate-life (file-name)
(rows (get-config 'rows config))
(cols (get-config 'cols config))
(generations (get-config 'generations config))
(a (new-world rows cols))
(b (new-world rows cols)))
(insert-patterns a (get-config 'patterns config))
(dotimes (g generations)
(princ (format "generation %d\n" g))
(print-world a)
(swap a b))))

(simulate-life (elt command-line-args-left 0))
```

Configuration file, which defines the size starting patterns and how long the simulation will run.

```((rows . 8)
(cols . 10)
(generations . 3)
(patterns
;; Blinker is defined in the script.
;; This is a custom pattern.
(4 4 (".***"
"***."))))
```
Output:
```generation 0
..........
.***......
..........
..........
.....***..
....***...
..........
..........
generation 1
..*.......
..*.......
..*.......
......*...
....*..*..
....*..*..
.....*....
..........
generation 2
..........
.***......
..........
..........
.....***..
....***...
..........
..........
```

## Erlang

```-module(life).

-export([bang/1]).

-define(CHAR_ALIVE, 111).  % "o"
-define(CHAR_BAR,    45).  % "-"

-define(GEN_INTERVAL, 100).

-record(state, {x            :: non_neg_integer()
,y            :: non_neg_integer()
,n            :: pos_integer()
,bar          :: nonempty_string()
,board        :: array()
,gen_count    :: pos_integer()
,gen_duration :: non_neg_integer()
,print_time   :: non_neg_integer()
}).

%% ============================================================================
%% API
%% ============================================================================

bang(Args) ->
[X, Y] = [atom_to_integer(A) || A <- Args],
{Time, Board} = timer:tc(fun() -> init_board(X, Y) end),
State = #state{x            = X
,y            = Y
,n            = X * Y
,bar          = [?CHAR_BAR || _ <- lists:seq(1, X)]
,board        = Board
,gen_count    = 1  % Consider inital state to be generation 1
,gen_duration = Time
,print_time   = 0  % There was no print time yet
},
life_loop(State).

%% ============================================================================
%% Internal
%% ============================================================================

life_loop(
#state{x            = X
,y            = Y
,n            = N
,bar          = Bar
,board        = Board
,gen_count    = GenCount
,gen_duration = Time
,print_time   = LastPrintTime
}=State) ->

{PrintTime, ok} = timer:tc(
fun() ->
do_print_screen(Board, Bar, X, Y, N, GenCount, Time, LastPrintTime)
end
),

{NewTime, NewBoard} = timer:tc(
fun() ->
next_generation(X, Y, Board)
end
),

NewState = State#state{board        = NewBoard
,gen_count    = GenCount + 1
,gen_duration = NewTime
,print_time   = PrintTime
},

NewTimeMil = NewTime / 1000,
NextGenDelay = at_least_zero(round(?GEN_INTERVAL - NewTimeMil)),
timer:sleep(NextGenDelay),

life_loop(NewState).

at_least_zero(Integer) when Integer >= 0 -> Integer;
at_least_zero(_) -> 0.

do_print_screen(Board, Bar, X, Y, N, GenCount, Time, PrintTime) ->
ok = do_print_status(Bar, X, Y, N, GenCount, Time, PrintTime),
ok = do_print_board(Board).

do_print_status(Bar, X, Y, N, GenCount, TimeMic, PrintTimeMic) ->
TimeSec = TimeMic / 1000000,
PrintTimeSec = PrintTimeMic / 1000000,
ok = io:format("~s~n", [Bar]),
ok = io:format(
"X: ~b Y: ~b CELLS: ~b GENERATION: ~b DURATION: ~f PRINT TIME: ~f~n",
[X, Y, N, GenCount, TimeSec, PrintTimeSec]
),
ok = io:format("~s~n", [Bar]).

do_print_board(Board) ->
% It seems that just doing a fold should be faster than map + to_list
% combo, but, after measuring several times, map + to_list has been
% consistently (nearly twice) faster than either foldl or foldr.
RowStrings = array:to_list(
array:map(
fun(_, Row) ->
array:to_list(
array:map(
fun(_, State) ->
state_to_char(State)
end,
Row
)
)
end,
Board
)
),

ok = lists:foreach(
fun(RowString) ->
ok = io:format("~s~n", [RowString])
end,
RowStrings
).

state_to_char(1) -> ?CHAR_ALIVE.

next_generation(W, H, Board) ->
array:map(
fun(Y, Row) ->
array:map(
fun(X, State) ->
Neighbors = filter_offsides(H, W, neighbors(X, Y)),
States = neighbor_states(Board, Neighbors),
LiveNeighbors = lists:sum(States),
new_state(State, LiveNeighbors)
end,
Row
)
end,
Board
).

new_state(1, LiveNeighbors) when LiveNeighbors  <  2 -> 0;
new_state(1, LiveNeighbors) when LiveNeighbors  <  4 -> 1;
new_state(1, LiveNeighbors) when LiveNeighbors  >  3 -> 0;
new_state(0, LiveNeighbors) when LiveNeighbors =:= 3 -> 1;
new_state(State, _LiveNeighbors) -> State.

neighbor_states(Board, Neighbors) ->
[array:get(X, array:get(Y, Board)) || {X, Y} <- Neighbors].

filter_offsides(H, W, Coordinates) ->
[{X, Y} || {X, Y} <- Coordinates, is_onside(X, Y, H, W)].

is_onside(X, Y, H, W) when (X >= 0) and (Y >= 0) and (X < W) and (Y < H) -> true;
is_onside(_, _, _, _) -> false.

neighbors(X, Y) ->
[{X + OffX, Y + OffY} || {OffX, OffY} <- offsets()].

offsets() ->
[offset(D) || D <- directions()].

offset('N')  -> { 0, -1};
offset('NE') -> { 1, -1};
offset('E')  -> { 1,  0};
offset('SE') -> { 1,  1};
offset('S')  -> { 0,  1};
offset('SW') -> {-1,  1};
offset('W')  -> {-1,  0};
offset('NW') -> {-1, -1}.

directions() ->
['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW'].

init_board(X, Y) ->
array:map(fun(_, _) -> init_row(X) end, array:new(Y)).

init_row(X) ->
array:map(fun(_, _) -> init_cell_state() end, array:new(X)).

init_cell_state() ->
crypto:rand_uniform(0, 2).

atom_to_integer(Atom) ->
list_to_integer(atom_to_list(Atom)).
```

## ERRE

This is a simple implementation of Conway's game of Life with an endless world. Test pattern configuration is 'glider'.

```PROGRAM LIFE

!\$INTEGER

!\$KEY
!for C-64 compatibility

CONST Xmax=38,Ymax=20

DIM x,y,N
DIM WORLD[39,21],NextWORLD[39,21]

BEGIN

! Glider test
!------------------------------------------
WORLD[1,1]=1 WORLD[1,2]=0 WORLD[1,3]=0
WORLD[2,1]=0 WORLD[2,2]=1 WORLD[2,3]=1
WORLD[3,1]=1 WORLD[3,2]=1 WORLD[3,3]=0
!------------------------------------------

PRINT(CHR\$(12);"Press any key to interrupt")
LOOP
PRINT(CHR\$(11);) PRINT
PRINT(STRING\$(Xmax+2,"-"))
!---------- endless world ---------
FOR y=1 TO Ymax DO
WORLD[0,y]=WORLD[Xmax,y]
WORLD[Xmax+1,y]=WORLD[1,y]
END FOR
FOR x=1 TO Xmax DO
WORLD[x,0]=WORLD[x,Ymax]
WORLD[x,Ymax+1]=WORLD[x,1]
END FOR
WORLD[0,0]=WORLD[Xmax,Ymax]
WORLD[Xmax+1,Ymax+1]=WORLD[1,1]
WORLD[Xmax+1,0]=WORLD[1,Ymax]
WORLD[0,Ymax+1]=WORLD[Xmax,1]
!---------- endless world ---------
FOR y=1 TO Ymax DO
PRINT("|";)
FOR x=1 TO Xmax DO
PRINT(CHR\$(32+WORLD[x,y]*3);)
N=WORLD[x-1,y-1]+WORLD[x-1,y]+WORLD[x-1,y+1]+WORLD[x,y-1]
N=N+WORLD[x,y+1]+WORLD[x+1,y-1]+WORLD[x+1,y]+WORLD[x+1,y+1]
IF (WORLD[x,y]<>0 AND (N=2 OR N=3)) OR (WORLD[x,y]=0 AND N=3) THEN
NextWORLD[x,y]=1
ELSE
NextWORLD[x,y]=0
END IF
END FOR
PRINT("|")
END FOR
PRINT(STRING\$(Xmax+2,"-"))
PAUSE(0.1)

FOR x=0 TO Xmax+1 DO
FOR y=0 TO Ymax+1 DO
WORLD[x,y]=NextWORLD[x,y]
NextWORLD[x,y]=0
END FOR
END FOR
REPEAT
GET(A\$)
UNTIL A\$<>""
EXIT IF A\$=CHR\$(27)
END LOOP

PRINT("Press any key to exit")
REPEAT
UNTIL GETKEY\$<>""
END PROGRAM```

## F#

The following F# implementation uses for visualization and is easily compiled into a standalone executable:
```let count (a: _ [,]) x y =
let m, n = a.GetLength 0, a.GetLength 1
let mutable c = 0
for x in x-1..x+1 do
for y in y-1..y+1 do
if x>=0 && x<m && y>=0 && y<n && a.[x, y] then
c <- c + 1
if a.[x, y] then c-1 else c

let rule (a: _ [,]) x y =
match a.[x, y], count a x y with
| true, (2 | 3) | false, 3 -> true
| _ -> false

open System.Windows
open System.Windows.Media.Imaging

do
let rand = System.Random()
let n = 256
let game = Array2D.init n n (fun _ _ -> rand.Next 2 = 0) |> ref
let image = Controls.Image(Stretch=Media.Stretch.Uniform)
let format = Media.PixelFormats.Gray8
let pixel = Array.create (n*n) 0uy
let update _ =
game := rule !game |> Array2D.init n n
for x in 0..n-1 do
for y in 0..n-1 do
pixel.[x+y*n] <- if (!game).[x, y] then 255uy else 0uy
image.Source <-
BitmapSource.Create(n, n, 1.0, 1.0, format, null, pixel, n)
Window(Content=image, Title="Game of Life")
|> (Application()).Run |> ignore
```

## Fermat

```;{Conway's Game of Life in Fermat}
;{square grid with wrap-around boundaries}

size:=50;                         {how big a grid do you want? This fits my screen OK, change this for your own screen}

Array w1[size,size], w2[size,size];      {set up an active world and a 'scratchpad' world}
act:=1;
buf:=2;
%[1]:=[w1];                      {Fermat doesn't have 3D arrays in the normal sense--}
%[2]:=[w2];                      {we need to use the somewhat odd "array of arrays" functionality}

Func Cls = for i = 1 to size do !!; od.;     {"clear screen" by printing a bunch of newlines}

Func Draw =                     {draw the active screen}
for i = 1 to size do
for j = 1 to size do
if %[act][i, j] = 1 then !('# ') else !('. ') fi;
od;
!;
od;
.;

Func Rnd =                                   {randomize the grid with a density of 40% live cells}
for i = 1 to size do
for j = 1 to size do
if Rand|5<2 then %[act][i, j] := 1 else %[act][i, j] := 0 fi;
od;
od;
Cls;
Draw;
.;

Func Blinker =                               {clears the screen except for a blinker in the top left corner}
for i = 1 to size do
for j = 1 to size do
%[act][i, j] := 0;
od;
od;
%[act][1,2] := 1;
%[act][2,2] := 1;
%[act][3,2] := 1;
Cls;
Draw;
.;

Func Iter =                                 {do one iteration}
for i = 1 to size do
if i = 1 then im := size else im := i - 1 fi;        {handle wrap around}
if i = size then ip := 1 else ip := i + 1 fi;
for j = 1 to size do
if j = 1 then jm := size else jm := j - 1 fi;
if j = size then jp := 1 else jp := j + 1 fi;
neigh :=  %[act][im, jm];                        {count neigbours}
neigh :+ (%[act][im, j ]);
neigh :+ (%[act][im, jp]);
neigh :+ (%[act][i , jm]);
neigh :+ (%[act][i , jp]);
neigh :+ (%[act][ip, jm]);
neigh :+ (%[act][ip, j ]);
neigh :+ (%[act][ip, jp]);
if neigh < 2 or neigh > 3 then %[buf][i, j] := 0 fi;      {alive and dead rules}
if neigh = 2 then %[buf][i, j] := %[act][i, j] fi;
if neigh = 3 then %[buf][i, j] := 1 fi;
od;
od;
Swap(act, buf);     {rather than copying the scratch over into the active, just exchange their identities}
Cls;
Draw;
.;

choice := 9;
while choice <> 0 do              {really rough menu, not the point of this exercise}
?choice;
if choice=4 then Cls fi;
if choice=2 then Rnd fi;
if choice=1 then Iter fi;
od;

!!'John Horton Conway (26 December 1937 – 11 April 2020)';```
Output:
One iteration starting from random soup, showing a few well-known objects (blinker, block, glider, beehive, loaf)
```# . . . . . . . . . # . . # . . . . . . . . # . . . . . . . . . . . . . . . . . . . . . . # # . . .
. . . . . . . # . . # . . . # . . . . # # . # # . . # # # . . . . . . . . . . . . . . . # # . # . #
. . . . . . # . # # . . . # . . . . . # # . # . . . # . . # . . . . . . . . . . . . . . # # . . # .
. . . . . . # . # . # . . # . . . . . # . # # . . # . . . # . . . . # # . . . . . . . . . . . . . .
. . . . . . . # . # # . . # . . . # # # # . . . . # . . # . . . . # . . # . . . . . . . . . . . . .
. . . . . . . . . . . . # . . . . # . . . . . . . . . . . . . . . . # . . # . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . # # # . . . . . . # # . . . . . . # . . # . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . # . . . . . . . . . . . . . . . # . # . . . . . . . . . . . . .
. . . . # # # . . . . . . . . . . . # . . . . # # . . . . . . . . . . # . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . # # # # . . # . # . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . # # . . # . . # . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . # # # . . . . . . . # # . . . . . # . . . . . . . . . . # . . . . . . . . . . . . . . .
. . . . . . # # # . . . . . . . . . . . # # . . . . . . . . . . . # . # . . . . . . . . . . . . . .
. . . . . # . . # . # # . . . . . . # # . # . . . . . . . . . . . # . . # . . . . . . . . . . . . .
. . . . . . # # . # # . . . . . . . . # # . . . . . . . . . . . . . # # . . . . . . . . . . . . . .
. . . . . . # # # # # . . . . . . . . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . # . . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # . . . . . . . .
. . . . . . . . # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # . . . . . . .
. . . . . . . . # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . # # . . . . . . # # #
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # . . . . . . # . . .
# . . . . . . # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # . #
. . . . . . # . . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . # . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . . . . . . . . . .
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # #
# # . . . . . . . # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . # #
. # # . . . . . . # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # . . #
. # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . # . # # . . . . . . . # # . . .
# . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . # . # . . . . . . . . . # # . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . . . # . # # . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . . # # # # . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # . . # # . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . # # # . . . . . . . . . . . . . . . . . . . . . . . . # . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # . . . . . . . . . . # . . . . . . . .
. . . . . . . . . . . . # . . . . . . . . . . . . . . # . # . # # . # . . . . . . # . . . . . . . .
. . . . . . . . . . . . # . . . . . . . . . . . . . # . . . . . . . . # . . . . . . . . . . . . . .
. . . . . . . . . . . . # . . . . . . . . . . . . # . . # # # # . . . # . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . # # # . . . . . . # . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # .
. . . . . . . . . . . . . . . . . # # . . . . . . . . . . . . . . . . . . . . . . . . . . . # . # .
. . . . . . . . . . . . # # . . # . . . . . . . . . . . . . . . . . . . . . . . . . . . . # . . # .
. . . . . . . . . . . . # . # . . # . . . . . . . . . . . . . . # . . . . . . . . . . . . # . . . .
. . . . . . . . . . . . # . . . . . . # . . . . . . . . . . . # . . # . . . . . . . . . # # . # . .
. . . . . . . . . . . . . . . . . . # . . . . . . . . . . . . . # # . . . . . . . . . . . . . . # #
. . . . . . . . . . . # . # . . . . # . . # . . . . . . . . . . . . . . . . . . . . . . . # # # . #
```

## Forth

gencell uses an optimization for the core Game of Life rules: new state = (old state | neighbors == 3).

``` \ The fast wrapping requires dimensions that are powers of 2.
1 6 lshift constant w \ 64
1 4 lshift constant h \ 16

: rows    w * 2* ;
1 rows constant row
h rows constant size

create world size allot
world   value old
old w + value new

variable gens
: clear  world size erase     0 gens ! ;
: age  new old to new to old  1 gens +! ;

: col+  1+ ;
: col-  1- dup w and + ; \ avoid borrow into row
: row+  row + ;
: row-  row - ;
: wrap ( i -- i ) [ size w - 1- ] literal and ;
: w@ ( i -- 0/1 ) wrap old + c@ ;
: w! ( 0/1 i -- ) wrap old + c! ;

: foreachrow ( xt -- )
size 0 do  I over execute  row +loop drop ;

: showrow ( i -- ) cr
old + w over + swap do I c@ if [char] * else bl then emit loop ;
: show  ['] showrow foreachrow  cr ." Generation " gens @ . ;

: sum-neighbors ( i -- i n )
dup  col- row- w@
over      row- w@ +
over col+ row- w@ +
over col-      w@ +
over col+      w@ +
over col- row+ w@ +
over      row+ w@ +
over col+ row+ w@ + ;
: gencell ( i -- )
sum-neighbors  over old + c@
or 3 = 1 and   swap new + c! ;
: genrow ( i -- )
w over + swap do I gencell loop ;
: gen  ['] genrow foreachrow  age ;

: life  begin gen 0 0 at-xy show key? until ;

\ patterns
char | constant '|'
: pat ( i addr len -- )
rot dup 2swap  over + swap do
I c@ '|' = if drop row+ dup else
I c@ bl  = 1+ over w!  col+ then
loop 2drop ;

: blinker s" ***" pat ;
: toad s" ***| ***" pat ;
: pentomino s" **| **| *" pat ;
: pi s" **| **|**" pat ;
: glider s"  *|  *|***" pat ;
: pulsar s" *****|*   *" pat ;
: ship s"  ****|*   *|    *|   *" pat ;
: pentadecathalon s" **********" pat ;
: clock s"  *|  **|**|  *" pat ;

clear  0 glider show
*
*
***

Generation 0  ok
gen show

* *
**
*
Generation 1  ok
```

## Fortran

Works with: Fortran version 90 and later
``` PROGRAM LIFE_2D
IMPLICIT NONE

INTEGER, PARAMETER :: gridsize = 10
LOGICAL :: cells(0:gridsize+1,0:gridsize+1) = .FALSE.
INTEGER :: i, j, generation=0
REAL :: rnums(gridsize,gridsize)

!  Start patterns
!  **************
!  cells(2,1:3) = .TRUE.                                                  ! Blinker
!  cells(3,4:6) = .TRUE. ; cells(4,3:5) = .TRUE.                          ! Toad
!  cells(1,2) = .TRUE. ; cells(2,3) = .TRUE. ; cells(3,1:3) = .TRUE.      ! Glider
cells(3:5,3:5) = .TRUE. ; cells(6:8,6:8) = .TRUE.                      ! Figure of Eight
!  CALL RANDOM_SEED
!  CALL RANDOM_NUMBER(rnums)
!  WHERE (rnums>0.6) cells(1:gridsize,1:gridsize) = .TRUE.                ! Random universe

CALL Drawgen(cells(1:gridsize, 1:gridsize), generation)
DO generation = 1, 8
CALL NextgenV2(cells)
CALL Drawgen(cells(1:gridsize, 1:gridsize), generation)
END DO

CONTAINS

SUBROUTINE Drawgen(cells, gen)
LOGICAL, INTENT(IN OUT) :: cells(:,:)
INTEGER, INTENT(IN) :: gen

WRITE(*, "(A,I0)") "Generation ", gen
DO i = 1, SIZE(cells,1)
DO j = 1, SIZE(cells,2)
IF (cells(i,j)) THEN
WRITE(*, "(A)", ADVANCE = "NO") "#"
ELSE
WRITE(*, "(A)", ADVANCE = "NO") " "
END IF
END DO
WRITE(*,*)
END DO
WRITE(*,*)
END SUBROUTINE Drawgen

SUBROUTINE Nextgen(cells)
LOGICAL, INTENT(IN OUT) :: cells(0:,0:)
LOGICAL :: buffer(0:SIZE(cells, 1)-1, 0:SIZE(cells, 2)-1)
INTEGER :: neighbours, i, j

buffer = cells   ! Store current status
DO j = 1, SIZE(cells, 2)-2
DO i = 1, SIZE(cells, 1)-2
if(buffer(i, j)) then
neighbours = sum(count(buffer(i-1:i+1, j-1:j+1), 1)) - 1
else
neighbours = sum(count(buffer(i-1:i+1, j-1:j+1), 1))
end if

SELECT CASE(neighbours)
CASE (0:1, 4:8)
cells(i,j) = .FALSE.

CASE (2)
! No change

CASE (3)
cells(i,j) = .TRUE.
END SELECT

END DO
END DO
END SUBROUTINE Nextgen

!###########################################################################
!   In this version instead of cycling through all points an integer array
! is used the sum the live neighbors of all points. The sum is done with
! the entire array cycling through the eight positions of the neighbors.
!   Executing a grid size of 10000 in 500 generations this version gave a
! speedup of almost 4 times.
!###########################################################################
PURE SUBROUTINE NextgenV2(cells)
LOGICAL, INTENT(IN OUT) :: cells(:,:)
INTEGER(KIND=1) :: buffer(1:SIZE(cells, 1)-2,1:SIZE(cells, 2)-2)
INTEGER :: gridsize, i, j

gridsize=SIZE(cells, 1)
buffer=0

DO j=-1, 1
DO i=-1,1
IF(i==0 .AND. j==0) CYCLE
WHERE(cells(i+2:gridsize-i-1,j+2:gridsize-j-1)) buffer=buffer+1
END DO
END DO

WHERE(buffer<2 .or. buffer>3) cells(2:gridsize-1,2:gridsize-1) = .FALSE.
WHERE(buffer==3) cells(2:gridsize-1,2:gridsize-1) = .TRUE.
END SUBROUTINE NextgenV2
!###########################################################################
END PROGRAM LIFE_2D
```
Output:
```Blinker
Generation 0

###

Generation 1
#
#
#

Generation 2

###
Figure of Eight (a period eight oscillator)
Generation 0

###
###
###
###
###
###

Generation 1

#
# #
#   #
#   #
#   #
#   #
# #
#

Generation 2

#
###
### #
#   #
#   #
# ###
###
#

Generation 3

###
#
#   #
#  # #
# #  #
#   #
#
###

Generation 4
#
##
# ##
###  #
# # #
# # #
#  ###
## #
##
#

Generation 5
##

#   #
#    #
# # #
# # #
#    #
#   #

##

Generation 6

#

# ###
## #
# ##
### #

#

Generation 7

##
## #
#
#
# ##
##

Generation 8

###
###
###
###
###
###
```

## Frink

Simple solution using two dictionaries (a display and a toggle) to store grid and track changes. The program outputs an animation of the game.

```start = now[]
// Generate a random 10x10 grid with "1" being on and "0" being off
instructions = ["1000100110","0001100010","1000111101","1001111110","0000110011","1111000001","0100001110","1011101001","1001011000","1101110111"]

// Create dictionary of starting positions.
rowCounter = 0
display = new dict
for instructionStr = instructions
{
rowCounter = rowCounter + 1
columnCounter = 0
instructionArr = charList[instructionStr]
for instruction = instructionArr
{
columnCounter = columnCounter + 1
arr = [rowCounter,columnCounter]
if instruction == "1"
display@arr = 1
else
display@arr = 0
}
}

// Create toggle dictionary to track changes. It starts off with everything off.
toggle = new dict
multifor[x,y] = [new range[1,10],new range[1,10]]
{
arr = [x,y]
toggle@arr = 0
}

// Animate the game of life
a = new Animation[3/s]
win = undef

// Loop through 10 changes to the grid. The starting points will tick down to two stable unchanging shapes in 10 steps.
for i = 1 to 12 // 12 steps so animation will pause on final state.
{
// Graphics item for this frame of the animation.
g = new graphics
g.backgroundColor[1,1,1]
// Add in a transparent shape to prevent the image from jiggle to automatic scaling.
g.color[0,0,0,0] // Transparent black
g.fillRectSides[-1, -1, 12, 12] // Set minimum size
g.clipRectSides[-1, -1, 12, 12] // Set maximum size
g.color[0,0,0] // Color back to default black
multifor[x1,y1] = [new range[1,10],new range[1,10]]
{
tval = [x1,y1]
// This is programmed with a hard edge. Points beyond the border aren't considered.
xmax = min[x1+1,10]
xmin = max[x1-1,1]
ymax = min[y1+1,10]
ymin = max[y1-1,1]
// Range will be 8 surrounding cells or cells up to border.
pointx = new range[xmin,xmax]
pointy = new range[ymin,ymax]
pointsum = 0
status = 0
// Process each surrounded point
multifor[x2,y2] = [pointx,pointy]
{
// Assign the array to a variable so it can be used as a dictionary reference.
point = [x2,y2]
if x2 == x1 && y2 == y1
{
status = display@point
} else // Calculate the total of surrounding points
{
pointsum = pointsum + display@point
}
}
// Animate if the point is on.
if status == 1
{
g.color[0,0,0]
g.fillEllipseCenter[x1,y1,1,1]
}
toggle@tval = status // This will be overwritten if needed by neighbor check conditions below.
// Check if off point has 3 on point neighbors
if status == 0 && pointsum == 3
{
toggle@tval = 1
}
// Check if on point has between 2 and 3 on point neighbors
if status == 1 && (pointsum < 2 || pointsum > 3)
{
toggle@tval = 0
}
}
// Add the current frame to the animation
// Replace the current display with the toggle values.
for toggleKeys = keys[toggle]
{
val = toggle@toggleKeys
display@toggleKeys = val
}
}

// Write the animation file
a.write["FrinkAnimationGoL.gif",400,400]

end = now[]
println["Program run time: " + ((end - start)*1.0 -> "seconds")]```

## FunL

```import lists.zipWithIndex
import util.Regex

data Rule( birth, survival )

val Mirek = Regex( '([0-8]+)/([0-8]+)' )
val Golly = Regex( 'B([0-8]+)/S([0-8]+)' )

def decode( rule ) =
def makerule( b, s ) = Rule( [int(d) | d <- b], [int(d) | d <- s] )

case rule
Mirek( s, b ) -> makerule( b, s )
Golly( b, s ) -> makerule( b, s )
_ -> error( "unrecognized rule: \$rule" )

def fate( state, crowding, rule ) = crowding in rule( int(state) )

def crowd( buffer, x, y ) =
res = 0

def neighbour( x, y ) =
if x >= 0 and x < N and y >= 0 and y < N
res += int( buffer(x, y) )

for i <- x-1..x+1
neighbour( i, y - 1 )
neighbour( i, y + 1 )

neighbour( x - 1, y )
neighbour( x + 1, y )
res

def display( buffer ) =
for j <- 0:N
for i <- 0:N
print( if buffer(i, j) then '*' else '\u00b7' )

println()

def generation( b1, b2, rule ) =
for i <- 0:N, j <- 0:N
b2(i, j) = fate( b1(i, j), crowd(b1, i, j), rule )

def pattern( p, b, x, y ) =
for (r, j) <- zipWithIndex( list(WrappedString(p).stripMargin().split('\n')).drop(1).dropRight(1) )
for i <- 0:r.length()
b(x + i, y + j) = r(i) == '*'

var current = 0
val LIFE = decode( '23/3' )
val N = 4
val buffers = (array( N, N, (_, _) -> false ), array( N, N ))

def reset =
for i <- 0:N, j <- 0:N
buffers(0)(i, j) = false

current = 0

def iteration =
display( buffers(current) )
generation( buffers(current), buffers(current = (current + 1)%2), LIFE )
println( 5'-' )

// two patterns to be tested
|
|***
'''

glider = '''
| *
|  *
|***
'''

pattern( blinker, buffers(0), 0, 0 )

repeat 3
iteration()

// clear grid, load "glider" pattern and run for five generations
reset()
pattern( glider, buffers(0), 0, 0 )

repeat 5
iteration()```
Output:
```····
***·
····
····
-----
·*··
·*··
·*··
····
-----
····
***·
····
····
-----
·*··
··*·
***·
····
-----
····
*·*·
·**·
·*··
-----
····
··*·
*·*·
·**·
-----
····
·*··
··**
·**·
-----
····
··*·
···*
·***
-----
```

## Furor

```// Life simulator (game). Console (CLI) version.
// It is a 'cellular automaton', and was invented by Cambridge mathematician John Conway.

// The Rules

// For a space that is 'populated':
//     Each cell with one or no neighbors dies, as if by solitude.
//     Each cell with four or more neighbors dies, as if by overpopulation.
//     Each cell with two or three neighbors survives.
// For a space that is 'empty' or 'unpopulated'
//     Each cell with three neighbors becomes populated.
// -----------------------------------------------------
#g
// Get the terminal-resolution:
terminallines   -- sto tlin
terminalcolumns    sto tcol
// .............................
// Verify the commandline parameters:
argc 3 < { #s ."Usage: " 0 argv print SPACE 1 argv print ." lifeshape-file.txt\n" end }
2 argv 'f !istrue { #s ."The given file ( " 2 argv print ." ) doesn't exist!\n" end }
startingshape 2 argv filetolist // read the file into the list
startingshape maxlinelength sto maxlinlen
neighbour    @tlin @tcol createlist   // Generate the stringarray for the neighbour-calculations
livingspace  @tlin @tcol createlist   // Generate the stringarray for the actual generations
cellscreen   @tlin @tcol createscreen // Generate the stringarray for the visible livingspace
// Calculate offset for the shape ( it must be put to the centre):
@tlin startingshape~ - 2 / sto originlin
@tcol @maxlinlen     - 2 / sto origincol

startingshape {{|
{{}} {{|}} {{-}} [[]] 32 > { 1 }{ 0 } sto emblem
livingspace @originlin {{|}} + @origincol {{-}} + @emblem [[^]]
|}}

cursoroff
// ==================================================================
{... // infinite loop starts
sbr §renderingsbr
topleft cellscreen !printlist
."Generation: " {...} print fflush // print the number of the generations.
neighbour 0 filluplist // fill up the neighbour list with zero value
// Calculate neighbourhoods
neighbour {{|
{{|}} {{-}} sbr §neighbors
{{}} {{|}} {{-}} @n [[^]] // store the neighbournumber
|}}

// Now, kill everybody if the neighbors are less than 2 or more than 3:
neighbour {{|
{{|}} {{-}} sbr §killsbr
|}}

// Generate the newborn cells:
neighbour {{|
{{}} {{|}} {{-}} [[]] 3 == { livingspace {{|}} {{-}} 1 [[^]] }
|}}

50000 usleep
//2 sleep
...} // infinite loop ends
// ==================================================================
end
killsbr:
sto innerindex sto outerindex
neighbour @outerindex @innerindex [[]] 2 < then §kill
neighbour @outerindex @innerindex [[]] 3 > then §kill
rts
kill: livingspace @outerindex @innerindex 0 [[^]] rts
// ==========================================================
neighbors: // This subroutine calculates the quantity of neighborhood
sto y sto x zero n
livingspace @x ? @tlin --                 @y ? @tcol --                  [[]] sum n // upleft    corner
livingspace @x ? @tlin --                 @y                             [[]] sum n // upmid     corner
livingspace @x ? @tlin --                 @y ++ dup  @tcol == { drop 0 } [[]] sum n // upright   corner
livingspace @x                            @y ? @tcol --                  [[]] sum n // midleft   corner
livingspace @x                            @y ++ dup  @tcol == { drop 0 } [[]] sum n // midright  corner
livingspace @x ++ dup @tlin == { drop 0 } @y ? @tcol --                  [[]] sum n // downleft  corner
livingspace @x ++ dup @tlin == { drop 0 } @y                             [[]] sum n // downmid   corner
livingspace @x ++ dup @tlin == { drop 0 } @y ++ dup  @tcol == { drop 0 } [[]] sum n // downright corner
rts
// ==========================================================
renderingsbr:
livingspace {{|
cellscreen   {{|}} {{-}}
{{}} {{|}} {{-}} [[]] { '* }{ 32 } [[^]]
|}}
rts

{ „startingshape” }
{ „livingspace” }
{ „cellscreen” }
{ „innerindex” }
{ „outerindex” }
{ „maxlinlen” }
{ „neighbour” }
{ „originlin” }
{ „origincol” }
{ „emblem” }
{ „tlin” }
{ „tcol” }
{ „x” } { „y” } { „n” }```

## Peri

```###sysinclude standard.uh
###sysinclude args.uh
###sysinclude str.uh
###sysinclude system.uh
// Life simulator (game).
// It is a 'cellular automaton', and was invented by Cambridge mathematician John Conway.

// The Rules

// For a space that is 'populated':
//     Each cell with one or no neighbors dies, as if by solitude.
//     Each cell with four or more neighbors dies, as if by overpopulation.
//     Each cell with two or three neighbors survives.
// For a space that is 'empty' or 'unpopulated'
//     Each cell with three neighbors becomes populated.
// --------------------------------------------------------------------------------------------
#g
// Get the terminal-resolution:
terminallines   -- sto tlin
terminalcolumns    sto tcol
// .............................
// Verify the commandline parameters:
argc 3 < { #s ."Usage: " 0 argv print SPACE    1 argv print ." lifeshape-file.txt\n" end }
2 argv 'f inv istrue { #s ."The given file ( " 2 argv print ." ) doesn't exist!\n"   end }
2 argv filetolist sto startingshape // read the file into the list
[[startingshape]]~~~  sto maxlinlen
@tlin @tcol [[mem]]   sto neighbour   // Generate the stringarray for the neighbour-calculations
@tlin @tcol [[mem]]   sto livingspace // Generate the stringarray for the actual generations
@tlin @tcol [[mem]]!  sto cellscreen  // Generate the stringarray for the visible livingspace
// Calculate offset for the shape ( it must be put to the centre):
@tlin startingshape~ - 2 / sto originlin
@tcol @maxlinlen     - 2 / sto origincol

32 > { 1 }{ 0 } sto emblem
@originlin {{}}§shaperead + @origincol {{}} + @emblem inv [[livingspace]][]
}}
}}
cursoroff
// ==================================================================
{.. // infinite loop starts
sbr §renderingsbr
topleft @cellscreen ![[print]]
."Generation: " {..} print fflush // print the number of the generations.
0 [[neighbour]][^] // fill up the neighbour list with zero value
// Calculate neighbourhoods
@tlin linloop: {{ // loop for every lines
@tcol          {{ // loop for every columns
{{}}§linloop {{}} sbr §neighbors
{{}}§linloop {{}} @nn inv [[neighbour]][] // store the neighbournumber
}} }}
// Now, kill everybody if the neighbors are less than 2 or more than 3:
@tlin linloop2: {{ // loop for every lines
@tcol           {{ // loop for every columns
{{}}§linloop2 {{}} [[neighbour]][] 2 < then §kill
{{}}§linloop2 {{}} [[neighbour]][] 3 > then §kill
{{<}} // Continue the inner loop
kill: {{}}§linloop2 {{}} 0 inv [[livingspace]][]
}} }}
@tlin linloop3: {{ // loop for every lines
@tcol           {{ // loop for every columns
// Generate the newborn cells:
{{}}§linloop3 {{}} [[neighbour]][] 3 == { {{}}§linloop3 {{}} 1 inv [[livingspace]][] }
}} }}
50000 inv sleep
..} // infinite loop ends
// ==================================================================
end
// ==========================================================
neighbors: // This subroutine calculates the quantity of neighborhood
sto xx sto yy zero nn
@yy ?   @tlin -- @xx ?   @tcol --  [[livingspace]][] sum nn // upleft    corner
@yy              @xx ?   @tcol --  [[livingspace]][] sum nn // upmid     corner
@yy ++?  tlin    @xx ?   @tcol --  [[livingspace]][] sum nn // upright   corner
@yy ?   @tlin -- @xx               [[livingspace]][] sum nn // midleft   corner
@yy ++?  tlin    @xx               [[livingspace]][] sum nn // midright  corner
@yy ?   @tlin -- @xx ++?  tcol     [[livingspace]][] sum nn // downleft  corner
@yy              @xx ++?  tcol     [[livingspace]][] sum nn // downmid   corner
@yy ++?  tlin    @xx ++?  tcol     [[livingspace]][] sum nn // downright corner
rts
// ==========================================================
renderingsbr:
@tlin livingspaceloop: {{ @tcol {{
{{}}§livingspaceloop {{}}
{{}}§livingspaceloop {{}} [[livingspace]][] { '* }{ 32 } inv [[cellscreen]][]
}}
}}
rts

{ „tlin” }
{ „tcol” }
{ „startingshape” }
{ „maxlinlen” }
{ „livingspace” }
{ „neighbour” }
{ „originlin” }
{ „origincol” }
{ „emblem” }
{ „cellscreen” }
{ „xx” } { „yy” } { „nn” }```

## Futhark

 This example is incorrect. Please fix the code and remove this message.Details: Futhark's syntax has changed, so this example will not compile
```fun bint(b: bool): int = if b then 1 else 0
fun intb(x: int): bool = if x == 0 then False else True

fun to_bool_board(board: [][]int): [][]bool =
map (fn (r: []int): []bool  => map intb r) board

fun to_int_board(board: [][]bool): [][]int =
map (fn (r: []bool): []int  => map bint r) board

fun cell_neighbors(i: int, j: int, board: [n][m]bool): int =
unsafe
let above = (i - 1) % n
let below = (i + 1) % n
let right = (j + 1) % m
let left = (j - 1) % m in
bint board[above,left] + bint board[above,j]  + bint board[above,right] +
bint board[i,left] + bint board[i,right] +
bint board[below,left] + bint board[below,j] + bint board[below,right]

fun all_neighbours(board: [n][m]bool): [n][m]int =
map (fn (i: int): []int  =>
map (fn (j: int): int  => cell_neighbors(i,j,board)) (iota m))
(iota n)

fun iteration(board: [n][m]bool): [n][m]bool =
let lives = all_neighbours(board) in
zipWith (fn (lives_r: []int) (board_r: []bool): []bool  =>
zipWith (fn (neighbors: int) (alive: bool): bool  =>
if neighbors < 2
then False
else if neighbors == 3 then True
else if alive && neighbors < 4 then True
else False)
lives_r board_r)
lives board

fun main(int_board: [][]int, iterations: int): [][]int =
-- We accept the board as integers for convenience, and then we
-- convert to booleans here.
let board = to_bool_board int_board in
loop (board) = for i < iterations do
iteration board in
to_int_board board
```

## Go

```package main

import (
"bytes"
"fmt"
"math/rand"
"time"
)

type Field struct {
s    [][]bool
w, h int
}

func NewField(w, h int) Field {
s := make([][]bool, h)
for i := range s {
s[i] = make([]bool, w)
}
return Field{s: s, w: w, h: h}
}

func (f Field) Set(x, y int, b bool) {
f.s[y][x] = b
}

func (f Field) Next(x, y int) bool {
on := 0
for i := -1; i <= 1; i++ {
for j := -1; j <= 1; j++ {
if f.State(x+i, y+j) && !(j == 0 && i == 0) {
on++
}
}
}
return on == 3 || on == 2 && f.State(x, y)
}

func (f Field) State(x, y int) bool {
for y < 0 {
y += f.h
}
for x < 0 {
x += f.w
}
return f.s[y%f.h][x%f.w]
}

type Life struct {
w, h int
a, b Field
}

func NewLife(w, h int) *Life {
a := NewField(w, h)
for i := 0; i < (w * h / 2); i++ {
a.Set(rand.Intn(w), rand.Intn(h), true)
}
return &Life{
a: a,
b: NewField(w, h),
w: w, h: h,
}
}

func (l *Life) Step() {
for y := 0; y < l.h; y++ {
for x := 0; x < l.w; x++ {
l.b.Set(x, y, l.a.Next(x, y))
}
}
l.a, l.b = l.b, l.a
}

func (l *Life) String() string {
var buf bytes.Buffer
for y := 0; y < l.h; y++ {
for x := 0; x < l.w; x++ {
b := byte(' ')
if l.a.State(x, y) {
b = '*'
}
buf.WriteByte(b)
}
buf.WriteByte('\n')
}
return buf.String()
}

func main() {
l := NewLife(80, 15)
for i := 0; i < 300; i++ {
l.Step()
fmt.Print("\x0c")
fmt.Println(l)
time.Sleep(time.Second / 30)
}
}
```

Running this program will compute and draw the first 300 "frames". The final frame looks like this:

```        ** ****        *
* **
*                                         **
*                                                  *  *
*                   **        ****                 **                         *
*                  **       *  **
*                      **        *
**      *
****              *        *                                     **         *
***   **           *         ** ****                             *  *        **
* **     *  **      *              **                              **
*    *** ***
* **
**   **       **
** *  *      * *
```

## Groovy

```class GameOfLife {

int generations
int dimensions
def board

GameOfLife(generations = 5, dimensions = 5) {
this.generations = generations
this.dimensions```