field = cluster is create, clear, size, dimensions, all_changes, display_changes, display_cell, random_changes, is_alive, set_alive, get_setpix, get_clearpix acell = array[cell] cells = sequence[cell] seq_cells = sequence[cells] seq_acell = sequence[acell] rep = record[ Cell_Size: int, %% Size of a cell in pixels Generation: int, %% Generation count Matrix: seq_cells, %% The actual cells Testers: seq_acell, %% Cells that may have changed % %% between generations. SetPix: int, ClearPix: int ] ints = sequence[int] Create = proc (Height: int, Width: int, Cell_Size: int, Gap_Size: int, HNs: ints, WNs: ints, SetPix, ClearPix: int) returns (cvt) CellA: array[cell] := array[cell]$Predict(1, Width) ACells: array[cells] := array[cells]$Predict(1, Height) AACell: array[acell] := array[acell]$Predict(1, Height) XPos: int := Gap_Size for I: int in int$From_To(1, Height) do YPos: int := Gap_Size TL: acell := acell$Predict(1, Width) array[acell]$AddH(AACell, TL) array[cell]$Trim(CellA, 1, 0) for J: int in int$From_To(1, Width) do C: cell := cell$New(XPos, YPos) array[cell]$AddH(CellA, C) C.Test_List := TL YPos := YPos + Cell_Size end array[cells]$AddH(ACells, cells$A2S(CellA)) XPos := XPos + Cell_Size end Fld: seq_cells := seq_cells$A2S(ACells) array[cells]$Trim(ACells, 1, 0) for I: int in int$From_To(1, Height) do for J: int in int$From_To(1, Width) do array[cell]$Trim(CellA, 1, 0) for N: int in ints$Indexes(HNs) do H: int := I + HNs[N] if (H <= 0) then H := H + Height elseif (H > Height) then H := H - Height end W: int := J + WNs[N] if (W <= 0) then W := W + Width elseif (W > Width) then W := W - Width end array[cell]$AddH(CellA, Fld[H][W]) end Fld[I][J].Neighbors := cells$A2S(CellA) end end return (rep${ Cell_Size: Cell_Size, Generation: 0, Matrix: Fld, Testers: seq_acell$A2S(AACell), SetPix: SetPix, ClearPix: ClearPix}) end Create Size = proc (F: cvt) returns (int); return (seq_cells$Size(F.Matrix) * cells$Size(F.Matrix[1])) except when Bounds: return (0) end end Size; Dimensions = proc (F: cvt) returns (int, int); return (seq_cells$Size(F.Matrix), cells$Size(F.Matrix[1])) except when Bounds: return (0, 0) end end Dimensions; Clear = proc (F: cvt); F.Generation := 0 for Row: cells in seq_cells$Elements(F.Matrix) do for C: cell in cells$Elements(Row) do cell$Clear(C, -1) end; end; for Row: acell in seq_acell$Elements(F.Testers) do acell$Trim(Row, 1, 0) end; end Clear; All_Changes = iter (F: cvt) yields (int, int, bool); own Changes: array[cell] := array[cell]$New() Generation: int := F.Generation + 1 except when Overflow: Generation := 1 end F.Generation := Generation XPos: int := 1 Cell_Size: int := F.Cell_Size for Row: acell in seq_acell$Elements(F.Testers) do YPos: int := 1 for C: cell in acell$Elements(Row) do Changed: bool := cell$Generate(C) if (Changed) then array[cell]$AddH(Changes, C) yield (XPos, YPos, C.Born) end YPos := YPos + Cell_Size end; XPos := XPos + Cell_Size acell$Trim(Row, 1, 0) end; while (true) do cell$Affect_Neighbors(array[cell]$RemH(Changes), Generation) end except when Bounds: end end All_Changes; Display_Changes = proc (F: cvt, w: x_window, dwidth: int) returns (bool) own Changes: array[cell] := array[cell]$New() Generation: int := F.Generation + 1 except when Overflow: Generation := 1 end F.Generation := Generation Something_Changed: bool := false for Row: acell in seq_acell$Elements(F.Testers) do for C: cell in acell$Elements(Row) do if (cell$Generate(C)) then Something_Changed := true array[cell]$AddH(Changes, C) if (C.Born) then x_window$pix_set(w, F.SetPix, C.Y, C.X, dwidth, dwidth) else x_window$pix_set(w, F.ClearPix, C.Y, C.X, dwidth, dwidth) end end end; acell$Trim(Row, 1, 0) end; while (true) do cell$Affect_Neighbors(array[cell]$RemH(Changes), Generation) end except when Bounds: end return (Something_Changed) end Display_Changes Random_Changes = iter (F: cvt) yields (int, int, bool); Generation: int := F.Generation Prob: int := 8 %% 1/8 chance of life for I: int in seq_cells$Indexes(F.Matrix) do Row: cells := F.Matrix[I] for J: int in cells$Indexes(Row) do C: cell := Row[J] %% Only randomly make cells alive. Do not kill them. if (random$Next(Prob) = 0) then Changed: bool := cell$Set_Alive(C, true, Generation) if (Changed) then cell$Affect_Neighbors(C, Generation) yield (I, J, true) end end end; end; end Random_Changes; Is_Alive = proc (F: cvt, I: int, J: int) returns (bool) signals (bounds); return (F.Matrix[I][J].Alive) resignal Bounds end Is_Alive; Set_Alive = proc (F: cvt, I: int, J: int, Alive: bool) signals (bounds); C: cell := F.Matrix[I][J] resignal Bounds cell$Set_Alive(C, Alive, F.Generation) cell$Affect_Neighbors(C, F.Generation) end Set_Alive; Display_Cell = proc (F: cvt, I, J: int, w: x_window, dwidth: int) signals (bounds) C: cell := F.Matrix[I][J] resignal Bounds if (C.Alive) then x_window$pix_set(w, F.SetPix, C.Y, C.X, dwidth, dwidth) else x_window$pix_set(w, F.ClearPix, C.Y, C.X, dwidth, dwidth) end end Display_Cell Get_SetPix = proc (F: cvt) returns (int) return (F.SetPix) end Get_SetPix Get_ClearPix = proc (F: cvt) returns (int) return (F.ClearPix) end Get_ClearPix end field