[PYTHON] I made a life game with Numpy

Article first posted on the Playground Advent Calendar!

What is a life game?

Below, [wikipedia](https://ja.wikipedia.org/wiki/%E3%83%A9%E3%82%A4%E3%83%95%E3%82%B2%E3%83%BC%E3 Quoted from% 83% A0). ~~ I think it's easier to understand if you jump to the link than to read the quote below w ~~

In the life game, the subsequent state is determined only by the initial state. There is a grid like a grid, and one grid is called a cell. Each cell has eight neighboring cells. Each cell has two states, "life" and "death", and the state of the next step (generation) of a cell is determined by the state of the surrounding eight cells in the current generation.

The life and death of a cell follows the following rules.

birth If there are exactly three living cells adjacent to a dead cell, the next generation will be born. ** Survival ** If there are two or three living cells adjacent to a living cell, they will survive in the next generation. ** Depopulated ** If there is less than one living cell adjacent to a living cell, it will die due to depopulation. ** Overcrowding ** If there are 4 or more living cells adjacent to a living cell, it will die due to overcrowding. Below is an example of life and death in the next step in the central cell. Live cells are indicated by ■, and dead cells are indicated by □.

Package used

import matplotlib.pyplot as plt
import numpy as np

initial state

n = 50

#Create a random cell
cells = np.random.randint(0, 2, (n, n), dtype=bool)

A random selection of either True or False creates an n × n matrix of elements. ("Life" for True," Death "for False) (If you increase it to about n = 500, it will become heavy ...)

Count the number of adjacent "raw" cells

sum_around = lambda i, j : cells[max(0, i-1):i+2, max(0, j-1):j+2].sum() - cells[i, j]

First, a 3 × 3 matrix centered on the ʻi row j column component of the matrix is extracted, and the sum of the elements of the matrix is obtained. Subtracting the center from the result gives the number of "raw" cells adjacent to the ʻi row j column component. (Calculated as True = 1, False = 0)

Reasons for using the max function

When you want to specify the cell to the left (or above) of the cell in the 0th row (or 0th column), even if ʻi -1 = -1, then max (0, -1) = 0` Therefore, only the area inside the wall can be referred to. Python seems to be okay if the index exceeds the size of the matrix, and I didn't have to do the same for the nth row (or nth column).

Update to the next generation

def update(old):

    sum_around = lambda i, j : cells[max(0, i-1):i+2, max(0, j-1):j+2].sum() - cells[i, j]
    
    around = np.fromfunction(np.vectorize(sum_around), old.shape)
    new = np.where(old , ((2 <= around) & (around <= 3)), (around == 3))
    return new

By putting the sum_around function in the first argument of the np.fromfunction function, we create a new matrix ʻaroundwhere ** the value of each element = the number of adjacent" raw "cells **. When each element isTrue, that is, when it is a" raw "cell, the judgment result of ** survival / depopulation / overcrowding ** is returned, and when it is False, that is, when it is a "death" cell, the judgment result is returned. Returns the judgment result of ** birth **. The return value is a bool` type, which will be the next generation cell as it is.

Reasons for using the np.vectorize function

It seems that the function of the first argument needs to be a universal function (ufunc).

Parameters :

function : callable The function is called with N parameters, where N is the rank of shape. Each parameter represents the coordinates of the array varying along a specific axis. For example, if shape were (2, 2), then the parameters would be array([[0, 0], [1, 1]]) and array([[0, 1], [0, 1]]) numpy.fromfunction

Since the argument of the sum_around function assumes the ʻint type, it is ufunced with np.vectorizeso that it can receive thendarray` type.

output

while True:
# for _ in range(200):  #If you want to specify the number of times

    cells = update(cells)
    
    plt.imshow(cells)
    plt.pause(.01)   # 0.Updated every 01 seconds
    plt.cla()        #Without this, it gets heavier and heavier

: santa: Christmas color: christamas_tree:

from matplotlib.colors import LinearSegmentedColormap

colors = ['green', 'red']
xmas = LinearSegmentedColormap.from_list('xmas', colors)
norm = plt.Normalize(0, 1)

plt.tick_params(labelbottom=False, labelleft=False,
                bottom=False, left=False)

You can change to the specified color by changing the inside of the while statement to plt.imshow (cells, cmap = xmas, norm = norm).

Execution result

ezgif-3-866aafd6a847.gif

Whole code

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LinearSegmentedColormap


n = 15

cells = np.zeros([n, n], dtype=bool)

#Galaxy
cells[3:9, 3:5] = True
cells[3:5, 6:12] = True
cells[-5:-3, 3:9] = True
cells[6:12, -5:-3] = True

#random
# cells = np.random.randint(0, 2, (n, n), dtype=bool)


def update(old):

    sum_around = lambda i, j : cells[max(0, i-1):i+2, max(0, j-1):j+2].sum() - cells[i, j]
    
    around = np.fromfunction(np.vectorize(sum_around), old.shape, dtype=int)
    new = np.where(old , ((2 <= around) & (around <= 3)), (around == 3))
    return new


colors = ['green', 'red']
xmas = LinearSegmentedColormap.from_list('xmas', colors)
norm = plt.Normalize(0, 1)

plt.tick_params(labelbottom=False, labelleft=False,
                bottom=False, left=False)

# for _ in range(200):
while True:

    cells = update(cells)
    
    plt.imshow(cells, cmap=xmas, norm=norm)
    plt.pause(.01)
    plt.cla()

: 8ball: Impressions: 8ball:

It's probably the first time since I started programming that something I made by myself from scratch worked ... I did it (urgent recruitment: verbalization of joy)

Recommended Posts

I made a life game with Numpy
〇✕ I made a game
I made a roguelike game with Python
I made a random number graph with Numpy
I made a bin picking game with Python
I made a Christmas tree lighting game with Python
I made a vim learning game "PacVim" with Go
I made a falling block game with Sense HAT
I made a fortune with Python.
Zura made like a life game
I made a daemon with Python
I made a simple typing game with tkinter in Python
I made a puzzle game (like) with Tkinter in Python
I made a Hex map with Python
I made a stamp generator with GAN
I made a simple blackjack with Python
I made a configuration file with Python
I made a WEB application with Django
I made a neuron simulator with Python
Life game with Python [I made it] (on the terminal & Tkinter)
I made a poker game server chat-holdem using websocket with python
I made a stamp substitute bot with line
I made a competitive programming glossary with Python
I made a weather forecast bot-like with Python.
I made a GUI application with Python + PyQt5
I made a Twitter fujoshi blocker with Python ①
I want to make a game with Python
[Python] I made a Youtube Downloader with Tkinter.
I made a simple Bitcoin wallet with pycoin
I made a LINE Bot with Serverless Framework!
I made a Mattermost bot with Python (+ Flask)
I made a QR code image with CuteR
[AWS] I made a reminder BOT with LINE WORKS
I wrote GP with numpy
I made a Twitter BOT with GAE (python) (with a reference)
I made a household account book bot with LINE Bot
I made a ready-to-use syslog server with Play with Docker
I made a window for Log output with Tkinter
I made blackjack with python!
I made a net news notification app with Python
I made a Python3 environment on Ubuntu with direnv.
I made a LINE BOT with Python and Heroku
I made a python text
I made a discord bot
I made COVID19_simulator with JupyterLab
I made Word2Vec with Pytorch
I made blackjack with Python.
I made a school festival introduction game using Ren’py
I made wordcloud with Python.
A story that stumbled when I made a chatbot with Transformer
I made a LINE BOT that returns parrots with Go
I made a package to filter time series with python
Create a life game that is manually updated with tkinter
I made a simple book application with python + Flask ~ Introduction ~
I made a Numer0n battle game in Java (I also made AI)
I made a resource monitor for Raspberry Pi with a spreadsheet
I made a rigid Pomodoro timer that works with CUI
I made a surveillance camera with my first Raspberry PI.
I tried a stochastic simulation of a bingo game with Python
I made a plug-in that can "Daruma-san fell" with Minecraft
[AWS] I made a reminder BOT with LINE WORKS (implementation)