#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.14.5
 Author:         alpines

 Script Function:
	AutoIt implementation of the "game" Rule 110.
	https://en.wikipedia.org/wiki/Rule_110

#ce ----------------------------------------------------------------------------

#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <StringConstants.au3>

Global Const $I_GUI_WIDTH = 1024
Global Const $I_GUI_HEIGHT = 768

Opt("GUIOnEventMode", 1)

#cs
	Interessante Rules

	Rule 126 = Sierpinski Dreieck
	Rule 122 = Schachbrett
	Rule 118 = Schattierte Pyramide

	Rule 137 = Invertiertes Rule 110
#ce

Global Const $I_RULE = 110 ; max. 8 bit => 255

Global $oRule = ObjCreate("Scripting.Dictionary")

For $iBitA = 0 To 1
	For $iBitB = 0 To 1
		For $iBitC = 0 To 1
			Local $iCurrentBit = BitShift(1, -(BitShift($iBitA, -2) + BitShift($iBitB, -1) + BitShift($iBitC, -0)))
			$oRule.Add($iBitA & $iBitB & $iBitC, BitAND($I_RULE, $iCurrentBit) ? 1 : 0)
		Next
	Next
Next

Global $hGUI = GUICreate("Rule " & $I_RULE, $I_GUI_WIDTH, $I_GUI_HEIGHT)
GUISetOnEvent($GUI_EVENT_CLOSE, ExitApp)
GUISetState(@SW_SHOW, $hGUI)

Global $aCells[$I_GUI_HEIGHT][$I_GUI_WIDTH]
For $i = 0 To UBound($aCells) - 1
	For $j = 0 To UBound($aCells, 2) - 1
		$aCells[$i][$j] = 0
	Next
Next

;Ausgangssituation! Für Rule 110 die letzte Spalte in der ersten Zeile 1 setzen.
;Es ist hier in die Mitte gesetzt um es nicht ständig umsetzen zu müssen.
;Interessante Muster kommen auch raus wenn man mehrere Startpunkte 1 setzt ;)
$aCells[0][UBound($aCells, 2) / 2] = 1

_GDIPlus_Startup()
Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
Global $hBlackBrush = _GDIPlus_BrushCreateSolid(0xFF000000)
Global $hWhiteBrush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF)

Global $hBitmap = _GDIPlus_BitmapCreateFromScan0($I_GUI_WIDTH, 1)
Global $hBitmapGraphics = _GDIPlus_ImageGetGraphicsContext($hBitmap)

For $iColumn = 0 To UBound($aCells, 2) - 1
	_GDIPlus_GraphicsFillRect($hGraphics, $iColumn, 0, 1, 1, $aCells[0][$iColumn] ? $hBlackBrush : $hWhiteBrush)
Next

For $iRow = 1 To UBound($aCells) - 1
	Local $tmrRow = TimerInit()

	For $iColumn = 0 To UBound($aCells, 2) - 1
		$aCells[$iRow][$iColumn] = GetNextGeneration($oRule, $aCells, $iRow, $iColumn)

		_GDIPlus_GraphicsFillRect($hBitmapGraphics, $iColumn, 0, 1, 1, $aCells[$iRow][$iColumn] ? $hBlackBrush : $hWhiteBrush)
	Next

	_GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, $iRow)
Next

While Sleep(10)
WEnd

Func GetNextGeneration(ByRef $oRule, ByRef $aCells, ByRef $iRow, ByRef $iColumn)
	Local $iLeft, $iCenter, $iRight

	$iLeft = ($iColumn = 0) ? 0 : $aCells[$iRow - 1][$iColumn - 1]
	$iCenter = $aCells[$iRow - 1][$iColumn]
	$iRight = ($iColumn = UBound($aCells, 2) - 1) ? 0 : $aCells[$iRow - 1][$iColumn + 1]

	Return $oRule.Item($iLeft & $iCenter & $iRight)
EndFunc

Func ExitApp()
	_GDIPlus_Shutdown()
	Exit
EndFunc