John Conway's game of life in Haskell: Code Review
I have written a small code that simulates the Game of Life by John Conway. This is the code
import Control.Concurrent
import System.Random
import Control.Monad
data Cell = Alive  Dead deriving Eq
instance Show Cell where
show Alive = "X"
show Dead = "0"
toCells :: [Int] > [Cell]
toCells arr = (\ x > if x==1 then Alive else Dead) <$> arr
getValue :: [Cell] > Int > Int > Int > Int > Int
getValue state w h x y =
if x>=0 && x < w && y>=0 && y<h
then case state !! (y*w + x) of
Dead > 0
Alive > 1
else 0
countNeighbours :: [Cell] > Int > Int > Int > Int > Int
countNeighbours state w h x y = sum $ (uncurry $ getValue state w h) <$> [(x,y+1),(x,y1),(x+1,y+1),(x+1,y),(x+1,y1),(x1,y+1),(x1,y),(x1,y1)]
newCell :: [Cell] > Int > Int > Int > Int > Cell
newCell state w h x y =
if state !! (y*w + x) == Alive
then if countNeighbours state w h x y == 3  countNeighbours state w h x y == 2 then Alive else Dead
else
if countNeighbours state w h x y == 3 then Alive else Dead
clock :: [Cell] > Int > Int >Int > Int > [Cell]
clock state x y w h =
if x == w1
then if y == h1 then [newCell state w h x y] else [newCell state w h x y] ++ clock state 0 (y+1) w h
else [newCell state w h x y] ++ clock state (x+1) y w h
coolPrint :: [Cell] > Int > String
coolPrint [] w = ""
coolPrint arr w = (show $ take w arr) ++ "\n" ++ coolPrint (drop w arr) w
update state w h= do
threadDelay 1000000
putStr "\ESC[2J"
putStrLn $ coolPrint state w
update (clock state 0 0 w h) w h
input = replicateM 625 (randomRIO (0,1))
runGame = do
s < input
update (toCells s) 25 25
I have to admit, I am not very proud of it... Perhaps the update and clock functions could be implemented using the StateT monad, giving it a cleaner look. The cell data seems redundant and useless. What do you think? Any suggestion?
See also questions close to this topic

Need help extracting the value of a variable
I want to extract the value of
v
from the following code into m2.It is a little difficult to understand these chains. I am trying to understand the flow for a long, couldn't find any specific solution.
m1 < newEmptyMVar m2 < newEmptyMVar forkIO $ do g < view (hasLens . to seed) let g' = mkStdGen $ fromMaybe (d' ^. defSeed) g execStateT (evalRandT runCampaign g') (Campaign ((,Open (1)) <$> ts) c d') where step = runUpdate (updateTest v Nothing) >> lift u >> runCampaign runCampaign = use (hasLens . tests . to (fmap snd)) >>= update update c = view hasLens >>= \(CampaignConf tl q sl _ _) > if  any (\case Open n > n < tl; _ > False) c > callseq v w q >> step  any (\case Large n _ > n < sl; _ > False) c > step  otherwise > lift u
Helping functions
runUpdate :: (MonadState x m, Has Campaign x) => ((SolTest, TestState) > m (SolTest, TestState)) > m () runUpdate f = use (hasLens . tests) >>= mapM f >>= (hasLens . tests .=)
updateTest :: ( MonadCatch m, MonadRandom m, MonadReader x m, Has TestConf x, Has CampaignConf x) => VM > Maybe (VM, [Tx]) > (SolTest, TestState) > m (SolTest, TestState)
I tried to include
putMVar m1 v
as the following in thestep
linestep = runUpdate (updateTest v Nothing) >> lift u >> putMVar m1 v >> runCampaign
I thought these are just sequencing, putting
putMVar m1 v
in between produces following error.parse error (possibly incorrect indentation or mismatched brackets)  192  runCampaign = use (hasLens . tests . to (fmap snd)) >>= update  ^
Some extra information
campaign u v w ts d = let d' = fromMaybe defaultDict d in fmap (fromMaybe mempty) (view (hasLens . to knownCoverage)) >>= \c > do g < view (hasLens . to seed) let g' = mkStdGen $ fromMaybe (d' ^. defSeed) g execStateT (evalRandT runCampaign g') (Campaign ((,Open (1)) <$> ts) c d') where step = runUpdate (updateTest v Nothing) >> lift u >> runCampaign runCampaign = use (hasLens . tests . to (fmap snd)) >>= update update c = view hasLens >>= \(CampaignConf tl q sl _ _) > if  any (\case Open n > n < tl; _ > False) c > callseq v w q >> step  any (\case Large n _ > n < sl; _ > False) c > step  otherwise > lift u
This is the code I'm trying to work on.
Here, I want to declare one variable
m1 < newEmptyMVar
andm2
. Then I want to run the code from 2nd line(through the end) on two threads concurrently usingforkIO
.I want
v
to get stored inm1
&m2
from both the threads. So that I can manually check if both threads have the samev
Hope it helps!

Haskell: Understanding the bind operator (>>=) for Monads
I have the following function:
parse :: String > Maybe Token
And I am trying to implement the following function:
maketokenlist :: String > Maybe [Token]
The function returns Nothing if there is a token that was not able to be parsed (i.e. parse returns Nothing if the token is not an integer or an arithmetic operator), otherwise it returns a list of Tokens.
As Maybe is an instance of the Monad type class, I have the following approach:
maketokenlist str = return (words str) >>= parse
I convert the string into a list of individual tokens (e.g. "2 3 +" becomes ["2","3","+"] , and then map the parse function over each string in the list.
Since the Monad instance for lists is defined as:
instance Monad [] where return x = [x] xs >>= f = concat (map f xs) fail _ = []
However, say that I had the list of strings [2, 3, "+", "a"] and after mapping parse over each element using >>= I get [Just 2, Just 3, Just (+), Nothing], as "a" cannot be parsed. Is there a way to make the function maketokenlist return Nothing using just the >>= operator? Any insights are appreciated.

Permission denied trying to finish my program
I want to write a simple calculator by giving an acc back. The program runs perfectly as I wish except the finishing of the program.
I also tried 'then do putStrLn $ "Result: " ++ show total hilf(total,op)' at the end but it doesn't work as well.
import System.IO import Data.Char as Char data Op = Add  Subtract  Multiply  Divide deriving (Eq,Enum) instance Show Op where show Add = "+" show Subtract = "" show Multiply = "*" show Divide = "/" instance Read Op where readsPrec :: Int > String > [(Op,String)] readsPrec _ ('+':r) = [(Add,r)] readsPrec _ ('':r) = [(Subtract,r)] readsPrec _ ('*':r) = [(Multiply,r)] readsPrec _ ('/':r) = [(Divide,r)] readsPrec _ other = [] maybeRead :: Read a => String > Maybe a maybeRead s = case reads s of [(x,"")] > Just x  only accept single parse _ > Nothing main :: IO () main = do hSetBuffering stdout NoBuffering putStrLn "Welcome to my calculator!" putStrLn "In every line please insert: Number or +, , *, / " putStrLn "To finish the program, please just push return with no input" (total,_) < hilf (0,Nothing)  acc putStrLn $ "Result: " ++ show total hilf :: (Double, Maybe Op) > IO (Double, Maybe Op) hilf (total,op) = do putStr $ show total ++ " > " input < dropWhile Char.isSpace <$> getLine case (maybeRead input, maybeRead input) of (Just val, _ ) > hilf (perform op total val, Nothing) (Nothing , newOp@(Just _)) > hilf (total, newOp) _ > if null input then do return (total + 1, Nothing) putStrLn $ "Result " ++ show total hilf (total, Nothing) else do return (total + 1, Nothing) putStrLn "Wrong input!" hilf (total, op) where perform Nothing = flip const perform (Just Add) = (+) perform (Just Subtract) = () perform (Just Multiply) = (*) perform (Just Divide) = (/)
Pushing return with no input should finish the program (null input) and giving back 'Result: total' but it doesn't work and I don't know why.
Error: Permission denied collect2.exe: error: ld returned 1 exit status
gcc.exe' failed in phase
Linker'. (Exit code: 1) 
Typelevel monoidlike operations for generalizing indexed monads?
To motivate this question, let's first recall a bogstandard HoareDijkstrastyle indexed monad, and the example instance of an indexed writer monad.
For an indexed monad, we just require type alignment on
(i)bind
s:class IMonadHoare m where ireturn :: a > m i i a ibind :: m i j a > (a > m j k b) > m i k b
and then just to show that this is usable, let's implement an indexed writer monad:
import Prelude hiding (id, (.)) import Control.Category newtype IWriter cat i j a = IWriter{ runIWriter :: (a, cat i j) } instance (Category cat) => IMonadHoare (IWriter cat) where ireturn x = IWriter (x, id) ibind (IWriter (x, f)) k = IWriter $ let (y, g) = runIWriter (k x) in (y, g . f)
And it really is a writerlike monad, since we can implement the usual methods:
itell :: (Category cat) => cat i j > IWriter cat i j () itell f = IWriter ((), f) ilisten :: (Category cat) => IWriter cat i j a > IWriter cat i j (a, cat i j) ilisten w = IWriter $ let (x, f) = runIWriter w in ((x, f), f) ipass :: (Category cat) => IWriter cat i j (a, cat i j > cat i j) > IWriter cat i j a ipass w = IWriter $ let ((x, censor), f) = runIWriter w in (x, censor f)
OK, so far so good. But now I'd like to generalize this to other kinds (heh) of indices. I thought it would work to simply add associated type families for the typelevel monoid operations, like so:
{# LANGUAGE TypeFamilies, PolyKinds, MultiParamTypeClasses, FunctionalDependencies #} import Data.Kind class IMonadTF idx (m :: idx > Type > Type)  m > idx where type Empty m :: idx type Append m (i :: idx) (j :: idx) :: idx ireturn :: a > m (Empty m) a ibind :: m i a > (a > m j b) > m (Append m i j) b
So, does this work? Well, you can use it to define something where
Empty
/Append
is nonindexed, like so:{# LANGUAGE DataKinds, TypeOperators #} import GHC.TypeLists newtype Counter (n :: Nat) a = Counter{ runCounter :: a } instance IMonadTF Nat Counter where type Empty Counter = 0 type Append Counter n m = n + m ireturn = Counter ibind (Counter x) k = Counter . runCounter $ k x tick :: Counter 1 () tick = Counter ()
But now can we recreate our
IWriter
example? Unfortunately, I haven't been able to.First of all, we can't even declare
Empty
:data IWriter cat (ij :: (Type, Type)) a where IWriter :: { runIWriter :: (a, cat i j) } > IWriter cat '(i, j) a instance (Category cat) => IMonadTF (Type, Type) (IWriter cat) where type Empty (IWriter cat) = '(i, i)
This, of course, fails because the type variable
i
is not in scope.Let's change
Empty
into aConstraint
instead, and recreate theCounter
instance just to validate it:class IMonadConstraint idx (m :: idx > Type > Type)  m > idx where type IsEmpty m (i :: idx) :: Constraint type Append m (i :: idx) (j :: idx) :: idx ireturn :: (IsEmpty m i) => a > m i a ibind :: m i a > (a > m j b) > m (Append m i j) b newtype Counter (n :: Nat) a = Counter{ runCounter :: a } instance IMonadConstraint Nat Counter where type IsEmpty Counter n = n ~ 0 type Append Counter n m = n + m ireturn = Counter ibind (Counter x) k = Counter . runCounter $ k x tick :: Counter 1 () tick = Counter ()
Now we can at least write down the definition of
IsEmpty (Writer cat)
, but in the code below,ireturn
still doesn't typecheck. It is as if the defintion ofIsEmpty
isn't used to solve constraints:instance (Category cat) => IMonadConstraint (Type, Type) (IWriter cat) where type IsEmpty (IWriter cat) '(i, j) = i ~ j ireturn x = IWriter (x, id)
Could not deduce
i ~ '(j0, j0)
from the contextIsEmpty (IWriter cat) i
Similarly, we can try to enforce the alignment in the middle by adding a constraint for appending:
class IMonadConstraint2 idx (m :: idx > Type > Type)  m > idx where type IsAppend m (i :: idx) (j :: idx) :: Constraint type Append m (i :: idx) (j :: idx) :: idx ireturn :: (IsEmpty m i) => a > m i a ibind :: (IsAppend m i j) => m i a > (a > m j b) > m (Append m i j) b
But then that fails for
IWriter
in a similar way:instance (Category cat) => IMonadConstraint2 (Type, Type) (IWriter cat) where type IsAppend (IWriter cat) '(i, j) '(j', k) = j ~ j' type Append (IWriter cat) '(i, j) '(j', k) = '(i, k) ibind (IWriter (x, w)) k = IWriter $ let (y, w') = runIWriter (k x) in (y, w' . w)
Could not deduce
j ~ '(j1, j0)
from the contextIsAppend (IWriter cat) i j
Is it because
IsEmpty
andIsAppend
defined "pointwise"? 
How does the do notation work in this Haskell function? Could someone explain what the return lines do?
I am trying to solve a Homework for my Haskell course and I need help understanding this function. Also creating the Monad, Applicative and Functor instances for the "Logger" data type used in this code:
fib' :: (Log a) => Int > Logger a In fib' n  n < 2 = do logMsgM ("fib' " ++ show n) return 1  otherwise = do n1 < fib' (n1) n2 < fib' (n2) logMsgM ("fib' " ++ show n) return $ n1 + n2 newtype Logger l a = Logger (a,l) deriving Show logMsgM :: Log l => String > Logger l () logMsgM s = Logger ((), logMsg s) class (Semigroup a, Monoid a) => Log a where logMsg :: String > a data FullLog = FullLog [String] deriving Show instance Log FullLog where logMsg m = FullLog [ m ] instance Semigroup FullLog where ( FullLog x ) <> ( FullLog y ) = FullLog ( x <> y ) instance Monoid FullLog where mempty = FullLog [] mappend = (<>)

How does the after method works in tkinter?
I am new at programing and I am trying to make a simple animation to better learn. I have just learned python (still nooby) and starting to learn tkinter. I am trying to make an animation of the Conway's Game of Life because it has very simple principles and looks cool. I have manage to actually make my code work but I really dont understand how. The thing is that the method after I cannot understand how it works.
The part of the code that I dont understand is the method called start. I really dont understand how "loop finished" can be printed before startloop function returns None (which it should be the same as saying the animation hasnt stop yet)
import tkinter as tk width = 1400 height = 600 dist = 5 drawlines = False celstate = set() numcol = width//dist numrow = height//dist def getdeadcells(setcells): global celstate deadcells = set() for cell in setcells: i, j = cell list = [(i1, j1), (i, j1), (i+1, j1), (i1, j), (i+1, j), (i1, j+1), (i, j+1), (i+1, j+1)] for cel in list: if cel not in celstate: deadcells.add(cel) return deadcells def getnewstate(): def neight(cell): i, j = cell count = 0 list = [(i1, j1), (i, j1), (i+1, j1), (i1, j), (i+1, j), (i1, j+1), (i, j+1), (i+1, j+1)] for cel in list: if cel in celstate: count +=1 return count global celstate, numcol, numrow alivecells = celstate.copy() deadcells = getdeadcells(alivecells) newstate = set() for cell in alivecells: neigh = neight(cell) if neigh == 2 or neigh == 3: newstate.add(cell) for cell in deadcells: neigh = neight(cell) if neigh == 3: newstate.add(cell) if newstate == celstate: return None else: celstate = newstate if len(newstate) == 0: return "" else: return newstate def getcords(x, y): col = x//dist row = y//dist return (col, row) class GUI(): def __init__(self, master, width, height, dist): master.geometry("{}x{}".format(width, height)) master.bind("<Key>", self.start) self.master = master self.width = width self.height = height self.dist = dist self.canvas = tk.Canvas(master, width=width, height=height) self.canvas.pack(expand=True) self.drawlimits(dist) def start(self, event): if event.keycode == 32 or event.keycode == 13: def startloop(): newstate = getnewstate() if newstate == None: return None elif newstate == "": self.canvas.delete("rect") return None else: self.canvas.delete("rect") self.fillrects(list(newstate)) self.master.after(100, startloop) startloop() print("loop finished") def drawlimits(self, dist): if self.width % dist == 0 and self.height % dist == 0: self.canvas.bind("<B1Motion>", self.drawcells) self.canvas.bind("<ButtonRelease1>", self.drawcells) self.canvas.bind("<B3Motion>", self.killcell) self.canvas.bind("<ButtonRelease3>", self.killcell) if drawlines: xsteps = self.width/dist ysteps = self.height/dist for num in range(int(xsteps1)): self.canvas.create_line((num+1)*dist, 0, (num+1)*dist, self.height) for num in range(int(ysteps1)): self.canvas.create_line(0, (num+1)*dist, self.width, (num+1)*dist) def drawcells(self, event): cell = getcords(event.x, event.y) if cell not in celstate: self.fillrects([cell]) celstate.add(cell) def killcell(self, event): cell = getcords(event.x, event.y) if cell in celstate: celstate.remove(cell) col, row = cell tag = "{},{}".format(col, row) obj.canvas.delete(tag) def fillrects(self, cords): for gcords in cords: col, row = gcords tag = "{},{}".format(col,row) dist = self.dist self.canvas.create_rectangle(col*dist, row*dist, (col+1)*dist, (row+1)*dist, fill="black", tags=(tag, "rect")) root = tk.Tk() obj = GUI(root, width, height, dist) root.mainloop()
The code works as following: I only save the cells that are alive in the celstate set. I then find the deadcells that could become alive and iterate over the dead and alive cells in the
If the celstate is the same as the previous or theres no alive cells: then the function getnewstate returns None.
In the start method I then call the function getnewstate and draw its content until celstate returns None (with the function startloop that calls itself with the after method). I dont understand why "loop finished" can be printed if startloop hasnt stop yet. Even though I dont understand this part the code still works as intended which just makes it more anoyingly mistirious for me. Can anyone help clarify whats going on??
 The dist variable represents the cell size in pixels
 You can draw new cells using the left button of the mouse or erase existing ones using the right button. (The cool part is that you can do that while the animation is still going)
I'm sure the problem comes because I dont really understand how the mainloop works

How to condense many ifstatements into something smaller and more readable?
I am working on code for game of life. And one of the functions is supposed to "evolve" the current set of cells. This means that I have to have some conditions and if the ifstatement meets the condition then the cell becomes a DEAD or a ALIVE cell.
However, there are only some next cells which are being initialized, so I would have to set the rest of the next cells to DEAD who are not affected by the conditions.
Since there are four conditions I would like to condense my ifstatements to the smallest possible amount.
The conditions are:
 A cell which has 0 or 1 living neighbours dies next generation.
 A cell which has 2 or 3 living neighbours lives next generation.
 A cell which has 4 or more living neighbours dies next generation.
 An empty cell which has exactly 3 living neighbours becomes a live cell next generation.
I've tried fitting as many of the conditions into one ifstatement and an elsestatement at the if, meaning if non of the cells meet the conditions it will automatically be set to DEAD. Such that all cell in
field[i][j].next
are either dead or alive.I would like to mention that the array
field[i][j].current
is already initialized with DEAD and ALIVE cells.void evolve(const int rows,const int cols,cell field[rows][cols], int NeighbourCounter[i][j]){ CellNeighbour(rows, cols,field,NeighbourCounter); for(int i = 0;i<rows;i++){ for(int j =0;j<cols;j++){ switch (NeighbourCounter[i][j]) { case 0: case 1: field[i][j].next = DEAD; break; case 2: / field[i][j].next = field[i][j].current; break; case 3: field[i][j].next = ALIVE; break; case 4: case 5: case 6: case 7: case 8: field[i][j].next = DEAD; break; default: } } }
NeighbourCounter
is an array which calculates how many ALIVE neighbours each cell has.The expected output should be that
field[rows][cols]
should be updated and the updated version is stored in ``field[rows][cols].next`. 
How to update world inorder to get next iteration of DEAD/ALIVE cells
I am writing the code for Game of Life. With little progress.
The problem is not very evident for me but I have a suspicion to why I can't iterate my world.
Description of what my code is supposed to do:
In my mainfunction I have declared the dimensions for my array/world.
a characters array
field
where I can store each element asDEAD
orALIVE
.a declared array
counts
which is passed on to a functionPrintWorld
where the array stores the amount of neighbours each cell has.a function
intitField(rows,cols,field)
which initializes myfield
array.Lastly I have my function
printWorld(rows,cols,field,counts)
which is supposed to perform the neccessary operations inorder to update my World.A summary of what
printWorld
does and how it interacts with other functions:What
printWorld
does is:prints the current intilized field. While being the user presses enter, this being enforced by a whileloop.
inside the whileloop is a function
evolve
which should update the world every time the user presses enter.Inside the
evolve
function we will find a functionCellNeighbour
.CellNeighbour
makes use of the array declared in my mainfunctioncounts[rows][cols]
.Inside
CellNeighbour
we store the amount of ALIVE neighbours each cells has inside the arraycounts
.When all ALIVE neighbours have been stored in
counts
we continue with the rest ofevolve
.Now I can use this fact inorder to check the conditions imposed by game of life.
As you can see in
evolve
, next iteration of cell is being prepared by checking the conditions.Then determining if next cell should be DEAD or ALIVE.
When all the cell for next generation have been determined we continue with the function
evolve
.Now we get to the function
updateWorld
.All
updateWorld
does is that it takes all the newly stored cells for the next generation and stores it in the character arrayfield[rows][cols].current
Thus when we return to the function
printWorld
I should get new values forfield[i][j].current
inside the whileloop. And the new generation of cells should be printed.Unfortunaley I can not find what i'm doing wrong. However I do suspect that when calling functions some of the arrays lose their stored information. But I am not able to confirm this.
You're able to find my code below:
#include <stdio.h> #include <stdlib.h> #include <time.h> /* Constants, representation of states */ #define ALIVE 'X' #define DEAD '.' /* Declaration of data structure */ typedef struct{ char current; char next; } cell; /* Declaration of functions */ void initField(const int rows, const int cols, cell field[rows][cols]); void loadGlider(const int rows, const int cols, cell field[rows][cols]); void loadSemaphore(const int rows, const int cols, cell field[rows][cols]); void printWorld(const int rows, const int cols, cell field[rows][cols],int counts[rows][cols]); void CellNeighbour(const int rows, const int cols, cell field[rows][cols], int counts[rows][cols]); void evolve(const int rows,const int cols,cell field[rows][cols], int counts[rows][cols]); void updateWorld(int const rows, int const cols, cell field[rows][cols]); /* Function: main * Description: Start and run games, interact with the user. * Input: About what initial structure and whether to step or exit. * Output: Information to the user, and the game field in each step. */ int main(void) { const int rows = 20; const int cols = 20; cell field[rows][cols]; int counts[rows][cols]; initField(rows,cols, field); printWorld(rows,cols,field,counts); //CellNeighbour(rows,cols,field,counts);//test /*Used for testing*/ for (int i = 0; i < rows; i++){ for (int j = 0; j < cols; j++){ printf("%d ", counts[i][j]);// updated in CellNeighbour } printf("\n"); } return 0; } /* Function: initField * Description: Initialize all the cells to dead, then asks the user about * which structure to load, and finally load the structure. * Input: The field array and its size. * Output: The field array is updated. */ void initField(const int rows, const int cols, cell field[rows][cols]) { for (int r = 0 ; r < rows ; r++) { for (int c = 0 ; c < cols ; c++) { field[r][c].current = DEAD; } } printf("Select field spec to load ([G]lider, [S]emaphore)"); int ch = getchar(); /* Ignore following newline */ if (ch != '\n') { getchar(); } switch (ch) { case 'g': case 'G': loadGlider(rows, cols, field); break; case 's': case 'S': loadSemaphore(rows, cols, field); } } /* Function: loadGlider * Description: Inserts a glider into the field. * Input: The field array and its size. * Output: The field array is updated. */ void loadGlider(const int rows, const int cols, cell field[rows][cols]) { field[0][1].current = ALIVE; field[1][2].current = ALIVE; field[2][0].current = ALIVE; field[2][1].current = ALIVE; field[2][2].current = ALIVE; } /* Function: loadSemaphore * Description: Inserts a semaphore into the field. * Input: The field array and its size. * Output: The field array is updated. */ void loadSemaphore(const int rows, const int cols, cell field[rows][cols]) { field[8][1].current = ALIVE; field[8][2].current = ALIVE; field[8][3].current = ALIVE; } /* Function: printWorld * Description: Prints the current field * Input: The field array and its size. * Output: The field array is updated. */ void printWorld(const int rows, const int cols, cell field[rows][cols], int counts[rows][cols]){ char c = '\n'; while(c == '\n'){ for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { printf("%c ", field[i][j].current); } printf("\n"); } evolve(rows,cols,field,counts); printf("EXIT PROGRAM PRESS ANY CHARACTERS\n"); printf("TO GET NEXT ITERATION PRESS ENTER\n"); c = getchar(); if(c != '\n'){ //exits the loop break; } } } void evolve(const int rows,const int cols,cell field[rows][cols], int counts[rows][cols]){ CellNeighbour(rows, cols,field,counts); for(int i = 0;i<rows;i++){ for(int j =0;j<cols;j++){ if (field[i][j].current == ALIVE && counts[i][j] == 2){ field[i][j].next = ALIVE; } else if (counts[i][j] == 3){ field[i][j].next = ALIVE; } else{ field[i][j].next = DEAD; } } //Updating the next iteration, below: updateWorld(rows, cols, field); } } void CellNeighbour(const int rows, const int cols, cell field[rows][cols], int counts[rows][cols]){ int i,j; for(i = 0;i<rows;i++){ for(j =0;j<cols;j++){ counts[i][j] =0; } } for( i =0;i<rows;i++){ for( j = 0;j<cols;j++){ if(i>0 && j>0){ if(field[i1][j1].current == ALIVE){ counts[i][j]++; } } if(j>0){ if(field[i][j1].current == ALIVE){ counts[i][j]++; } } if(j>0){ if(field[i+1][j1].current == ALIVE){ counts[i][j]++; } } if(i<rows1){ if(field[i+1][j].current == ALIVE){ counts[i][j]++; } } if(i <rows1 && j <cols1){ if(field[i+1][j+1].current == ALIVE){ counts[i][j]++; } } if(j<cols1){ if(field[i][j+1].current == ALIVE){ counts[i][j]++; } } if(i>0 && j<cols1){ if(field[i1][j+1].current == ALIVE){ counts[i][j]++; } } if(i>0){ if(field[i1][j].current == ALIVE){ counts[i][j]++; } } } } } void updateWorld(int const rows, int const cols, cell field[rows][cols]){ for(int i = 0;i<rows;i++){ for(int j =0;j<cols;j++){ field[i][j].current = field[i][j].next; } } }
When printworld prints out the intial field. Say the we chose the field spec Glider which initializes the field with the coordinates:
field[0][1].current = ALIVE; field[1][2].current = ALIVE; field[2][0].current = ALIVE; field[2][1].current = ALIVE; field[2][2].current = ALIVE;
I get:
. X . . . . . . . . . . . . . . . . . . . . X . . . . . . . . . . . . . . . . . X X X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
So after the cells have evolved(updated) once I should get:
. . x . . . . . . . . . . . . . . . . . . X . X . . . . . . . . . . . . . . . . . . X X . . . . . . . . . . . . . . . . . . X . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Here is a video of what I get when I initialize the field with a glider spec:
It should however "glide" from the upperleft corner of the screen to the lowerright side.
Any ideas to why it does this?