(* ::Package:: *)

(************************************************************************)
(* This file was generated automatically by the Mathematica front end.  *)
(* It contains Initialization cells from a Notebook file, which         *)
(* typically will have the same name as this file except ending in      *)
(* ".nb" instead of ".m".                                               *)
(*                                                                      *)
(* This file is intended to be loaded into the Mathematica kernel using *)
(* the package loading commands Get or Needs.  Doing so is equivalent   *)
(* to using the Evaluate Initialization Cells menu command in the front *)
(* end.                                                                 *)
(*                                                                      *)
(* DO NOT EDIT THIS FILE.  This entire file is regenerated              *)
(* automatically each time the parent Notebook file is saved in the     *)
(* Mathematica front end.  Any changes you make to this file will be    *)
(* overwritten.                                                         *)
(************************************************************************)



InitializeBoard[n_, step_] :=
DynamicModule[{p}, 

If[n > 0,
A = Table[0,{i, n},{j, n}];
buttonlabel = "Start";
action = "Stop";
playing = True;
Glider = {{18,21},{19,22},{20,20},{20,21},{20,22}};
Exploder = {{18,20},{19,19},{19,20},{19,21},{20,19},{20,21},{21,20}};
Tumbler= {{16,19},{16,20},{16,22},{16,23},{17,19},{17,20},{17,22},
{17,23},{18,20},{18,22},{19,18},{19,20},{19,22},{19,24},{20,18},
{20,20},{20,22},{20,24},{21,18},{21,19},{21,23},{21,24}};

Print[
Column[
{Row[{
(* Initialize the game buttons *)

(* Start/Stop button *)
EventHandler[Dynamic[Button[buttonlabel]], 
{"MouseClicked" :> ({buttonlabel = buttonlabel/.{"Start" -> "Stop", "Stop" -> "Start"},
action = action /.{"Start" -> "Stop", "Stop" -> "Start"}})}],
(* Reset button *)
Button["Reset", 
{A = Table[0,{i, n},{j, n}], buttonlabel = "Start", action = "Stop"}, 
ImageSize -> 71],

(*Preset configuration button: Glider *)
If[n ==40,  Button["Glider", 
A = Table[0,{i, n},{j, n}];
Do[ 
A[[Sequence@@i]] = 1, {i, Glider}]]],

(*Preset configuration button: Exploder *)
If[n ==40,  Button["Exploder", 
A = Table[0,{i, n},{j, n}];
Do[ 
A[[Sequence@@i]] = 1, {i, Exploder}]]],

(*Preset configuration button: Tumbler *)
If[n ==40,  Button["Tumbler", 
A = Table[0,{i, n},{j, n}];
Do[ 
A[[Sequence@@i]] = 1, {i, Tumbler}]]],

(* Spacing for aesthetic purposes *)
"         ",

(* QUIT button *)
Button["Quit", 
{playing = False, A = Table[0,{i, n},{j, n}]}, 
ImageSize -> 71]
}
],

(* Initialize the game grid *)
EventHandler[
EventHandler[
Dynamic[ArrayPlot[A, Mesh -> True, ImageSize-> {500, 500}]], 

{"MouseDown":> (p = {-1,1}*Reverse[Ceiling[MousePosition["Graphics"]]] )},
PassEventsUp-> True],
{"MouseDown" :> (A[[Sequence@@p]] = A[[Sequence@@p]]/. {0 -> 1, 1-> 0})}
]
}
]
], 
(*ELSE*)
None
]
]


(* Find the coordinates of the squares surrounding square {i,j} *)
SurroundingSquares[{i_,j_}]:=
DeleteCases[Flatten[Table[{i+k,j+l}, {k, {-1,0,1}},{l, {-1,0,1}}], 1], {i,j}]


(* Test whether square at position, pos, will survive the next iteration *)
LiveOrDie[A_, pos_, n_] :=
Module[{i, j, Sq, sum, k},

i= pos[[1]];
j= pos[[2]];
Sq = SurroundingSquares[{i,j}] \[Intersection] Flatten[Table[{i,j}, {i, n}, {j, n}],1];
sum = 0;
For[k = 1, k <= Length[Sq], k++, sum += A[[Sequence@@Sq[[k]]]]];
Which[
(*IF*) A[[i,j]] == 1 \[And] (sum == 2 \[Or] sum == 3) ,
True, 
(*ELIF*) A[[i,j]] == 1 \[And] sum != 2 \[And] sum != 3, 
False, 
(*ELIF*) A[[i,j]] == 0 \[And] sum == 3,
True,
(*ELIF*) A[[i,j]] == 0 , 
False
]
]


(* Play the game with time step, step *)
PlayGame[n_, step_]:= DynamicModule[{B,indices},

(* Create a set of reference indices *)
indices = Flatten[Table[{i,j}, {i, n}, {j, n}],1];

(* A loop to iterate through game sequences *)
While[playing == True,
Which[(*If*)action == "Start", 
(*THEN*)
B = A;
Do[ 
If[LiveOrDie[A, indices[[i]], n],
B[[Sequence@@indices[[i]]]] = 1, 
B[[Sequence@@indices[[i]]]] = 0], {i, 1,n^2}];
A = B;
Pause[step];
]
]
]


(* A function to tie it all together *)
GameOfLife[]:= 
Module[{BoardSize = 40, TimeStep = 0.1},
InitializeBoard[BoardSize,TimeStep];
PlayGame[BoardSize, TimeStep]];



