Skip to content

Instantly share code, notes, and snippets.

@G33kDude
Last active February 28, 2022 00:00
Show Gist options
  • Save G33kDude/80ecd32230ade42f2f1e1765f0fc5e60 to your computer and use it in GitHub Desktop.
Save G33kDude/80ecd32230ade42f2f1e1765f0fc5e60 to your computer and use it in GitHub Desktop.
Game of Life for Discord competition
#Include precode.ahk
global W=20,H=20,b=[]
OnCellAlive(x,y){
OnCellDead(x,y,1)
}OnCellDead(x,y,n=0){
SetCell(x,y,b[x,y]:=n)
}SetupBoard(W,H)
r::
i:=0,c=[]
while i<W*H,n=-s:=b[x:=mod(i,W),y:=i++//W],j=0{
Loop,9
n+=b[mod(x+j//3-1+W,W),mod(y+mod(j++,3)-1+H,H)]
SetCell(x,y,c[x,y]:=s&&n=2||n=3)
}b:=c
#Include precode.ahk
global W := 20, H := 20, board := []
SetupBoard(W,H)
return
r::
new_board := []
loop, % W * H
{
; Calculate discrete x and y values based on the loop index
x := mod(A_Index - 1, W)
y := (A_Index - 1) // W
neighbors := -board[x, y] ; Subtract center from 3x3 subgrid to get only adjacent cells
loop, 9 {
; Calculate delta x and y values (-1,0,1 / -1,0,1) based on the loop index
dx := mod(A_Index - 1, 3) - 1
dy := (A_Index - 1) // 3 - 1
; Wrap coordinate-delta sums by board boundaries
nx := mod(x + dx + W, W)
ny := mod(y + dy + H, H)
neighbors += board[nx, ny]
}
; Calculate the new cell state
new_state := board[x, y] && neighbors == 2 || neighbors == 3
SetCell(x, y, new_board[x, y] := new_state)
}
board := new_board
return
OnCellAlive(x,y) {
SetCell(x, y, board[x, y] := 1)
}
OnCellDead(x,y) {
SetCell(x, y, board[x, y] := 0)
}
CoordMode, Mouse, Client
SetBatchLines -1
global _SIZE := 24, _CELL_DIM := _SIZE + 1
global _BOARD_WIDTH, _BOARD_HEIGHT, _CLIENT_WIDTH, _CLIENT_HEIGHT, _token, _grap, _on_brush, _off_brush, _prev_cell, _prev_type
SetupBoard(width, height) {
_BOARD_WIDTH := width
_BOARD_HEIGHT := height
_CLIENT_WIDTH := _BOARD_WIDTH * _SIZE + _BOARD_WIDTH - 1
_CLIENT_HEIGHT := _BOARD_HEIGHT * _SIZE + _BOARD_HEIGHT - 1
; create gui
Gui +hwnd_hwnd
Gui Show, % "w" _CLIENT_WIDTH " h" _CLIENT_HEIGHT, Game of Life
if !(dc := DllCall("GetDC", "Ptr", _hwnd, "Ptr"))
throw Exception("Failed getting device context")
if (!DllCall("LoadLibrary", "Str", "gdiplus"))
throw Exception("Failed loading gdiplus library")
VarSetCapacity(si, A_PtrSize = 8 ? 24 : 16, 0)
si := Chr(1)
if (ret := DllCall("gdiplus\GdiplusStartup", "Ptr*", _token, "Ptr", &si, "Ptr", 0))
throw Exception("GdiplusStartup failed: " ret)
DllCall("gdiplus\GdipCreateFromHDC", "Ptr", dc, "Ptr*", _grap)
DllCall("gdiplus\GdipCreateSolidFill", "UInt", 0xFFFFFF00, "UPtr*", _on_brush)
DllCall("gdiplus\GdipCreateSolidFill", "UInt", 0xFF808080, "UPtr*", _off_brush)
DllCall("gdiplus\GdipCreateSolidFill", "UInt", 0xFF000000, "UPtr*", _bg_brush)
DllCall("gdiplus\GdipFillRectangle", "Ptr", _grap, "Ptr", _bg_brush, "float", 0, "float", 0, "float", _CLIENT_WIDTH, "float", _CLIENT_HEIGHT)
Loop % _BOARD_HEIGHT
Loop % (_BOARD_WIDTH, y := A_Index - 1)
SetCell(A_Index - 1, y, false)
Hotkey, IfWinActive, % "ahk_id" _hwnd
fn := Func("_OnClick")
Hotkey, ~LButton, % fn
Hotkey, ~RButton, % fn
return _hwnd
}
SetCell(x, y, state) {
_prev_type := 0
DllCall("gdiplus\GdipFillRectangle", "Ptr", _grap, "Ptr", state ? _on_brush : _off_brush, "float", x * _CELL_DIM, "float", y * _CELL_DIM, "float", _SIZE, "float", _SIZE)
}
_OnClick() {
while GetKeyState(SubStr(A_ThisHotkey, 2), "P") {
MouseGetPos, x, y
if (x < 0 || y < 0 || x > _CLIENT_WIDTH || y > _CLIENT_HEIGHT)
continue
cell_x := x // _CELL_DIM
cell_y := y // _CELL_DIM
cell_index := cell_y * _BOARD_WIDTH + cell_x
if (A_ThisHotkey = "~LButton" && !(_prev_type = 1 && _prev_cell = cell_index)) {
OnCellAlive(cell_x, cell_y)
_prev_cell := cell_index
_prev_type := 1
} else if (A_ThisHotkey = "~RButton" && !(_prev_type = 2 && _prev_cell = cell_index)) {
OnCellDead(cell_x, cell_y)
_prev_cell := cell_index
_prev_type := 2
}
}
}
GuiEscape(hwnd) {
GuiClose(hwnd)
}
GuiClose(hwnd) {
ExitApp
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment