# L-15 MCS 507 Mon 25 Sep 2023 : game_of_life.py

"""
The script uses scitools.std to run the game of life
applying the rules of John Conway.
"""

import numpy as np
from scipy import sparse
import matplotlib
import matplotlib.pyplot as plt

def neighbors(alive, i, j):
    """
    Returns the number of cells alive
    next to alive[i, j].
    """
    cnt = 0
    if i > 0:
        if alive[i-1, j]:
            cnt = cnt + 1
        if(j > 0):
            if alive[i-1, j-1]:
                cnt = cnt + 1
        if(j < alive.shape[1]-1):
            if alive[i-1, j+1]:
                cnt = cnt + 1
    if(i < alive.shape[0]-1):
        if alive[i+1, j]:
            cnt = cnt + 1
        if(j > 0):
            if alive[i+1, j-1]:
                cnt = cnt + 1
        if(j < alive.shape[1]-1):
            if alive[i+1, j+1]:
                cnt = cnt + 1
    if(j > 0):
        if alive[i, j-1]:
            cnt = cnt + 1
    if(j < alive.shape[1]-1):
        if alive[i, j+1]:
            cnt = cnt + 1
    return cnt

def update(alive):
    """
    Applies the rules of Conway's game of life.
    """
    result = np.zeros(alive.shape, int)
    for i in range(0, alive.shape[0]):
        for j in range(0, alive.shape[1]):
            nbn = neighbors(alive, i, j)
            if alive[i, j] == 1:
                if((nbn < 2) or (nbn > 3)):
                    result[i, j] = 0
                else:
                    result[i, j] = 1
            else:
                if(nbn == 3):
                    result[i, j] = 1
    return result

def main():
    """
    Generates a random matrix and
    applies the rules for Conway's
    game of life.
    """
    ratio = 0.2  # ratio of nonzeroes
    dim = 200  # dimension of the matrix
    alive = np.random.rand(dim, dim)
    alive = np.matrix(alive < ratio, int)
    plt.ion()
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.set_xlim(-1, dim+1)
    ax.set_ylim(-1, dim+1)
    spm = sparse.coo_matrix(alive)
    dots, = ax.plot(spm.row, spm.col, 'b.')
    strtitle = 'game of life'
    ax.set_title(strtitle)
    fig.canvas.draw()
    plt.pause(0.00001)
    for i in range(5*dim):
        spm = sparse.coo_matrix(alive)
        dots.set_xdata(spm.row)
        dots.set_ydata(spm.col)
        strtitle = 'game of life at step %d' % (i+1)
        ax.set_title(strtitle)
        fig.canvas.draw()
        plt.pause(0.01)
        alive = update(alive)

main()
