Skip to content
Permalink
Browse files
adding Conway gol
  • Loading branch information
hamilr4 committed Oct 19, 2020
1 parent 87c5adb commit 951ec8a99e1e472308d8c2bf9bb26cf70c137981
Show file tree
Hide file tree
Showing 13 changed files with 1,321 additions and 43 deletions.
940 conway.pd

Large diffs are not rendered by default.

@@ -0,0 +1,331 @@
# Extension of game code by Nick Jarvis and Nick Wayne
# https://www.pygame.org/project-John+Conway's+Game+of+Life-2899-.html

'''
Conway Composer by Darius Smith
Uses Conway's Game of Life to send OSC messages to another program (PureData)
to generate music
Required libraries
pip3 install osc4py3, pygame
================================================================================
Rules (from Conway's Game of Life)
1) Any live cell with fewer than two live neighbours dies, as if by underpopulation.
2) Any live cell with two or three live neighbours lives on to the next generation.
3) Any live cell with more than three live neighbours dies, as if by overpopulation.
4) Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
================================================================================
TO PLAY (KEY MAPPINGS)
LEFT CLICK >> mark a cell as 'alive' (blue)
RIGHT CLICK >> mark a cell as 'dead' (black)
- KEY >> clear grid
= KEY >> random grid
a-z or A-Z >> assign a letter to the cell your mouse is over (
UP ARROW - progress time 1 frame
SPACEBAR - starts and stops the progression of time (toggle)
================================================================================
When a cell is "born" (transitions from dead to alive) if it contains a letter
it sends out an OSC message "/conway/<letter>" which can be used to trigger
sounds/events in another program (PureData)
'''

from math import ceil

from osc4py3.as_eventloop import *
from osc4py3 import oscbuildparse

from collections import OrderedDict
import pygame,random
from pygame.locals import *

# Start the system.
osc_startup()

# Make client channels to send packets.
osc_udp_client("127.0.0.1", 8000, "pureData")


pygame.init()

''' ###### PARAMETERS ####### '''

speed = 10 # how many iterations per second
squares = 2 # size of squares: 0 = 8X8, 1 = 16X16, 2 = 32X32, 3 = 64X64
map_size = 32 # the width and height

''' ######################### '''

if squares == 0:
imgs = ["res/alive_8.png","res/dead_8.png",8]
if squares == 1:
imgs = ["res/alive_16.png","res/dead_16.png",16]
if squares == 2:
imgs = ["res/alive_32.png","res/dead_32.png",32]
if squares == 3:
imgs = ["res/alive_64.png","res/dead_64.png",64]

#-----CONFIG-----

width = map_size*imgs[2]
height = map_size*imgs[2]
screen_size = width,height
screen = pygame.display.set_mode(screen_size)
clock = pygame.time.Clock()
alive = pygame.image.load(imgs[0]).convert()
dead = pygame.image.load(imgs[1]).convert()
done = False

marked_alive = []
font = pygame.font.Font('freesansbold.ttf', 12)
white = (255, 255, 255)

class cell:

def __init__(self,location,alive = False):
self.to_be = None
self.alive = alive
self.pressed = False
self.location = location
self.osc = ''
self.text = font.render('', True, white)

class board:

def __init__(self):
self.map = []

def fill(self,ran):
for i in range(map_size):
self.map.append([])
for g in range(map_size):
if ran == True:
a = random.randint(0,4)
if a == 0: self.map[i].insert(g,cell((i,g),True))
else: self.map[i].insert(g,cell((i,g)))
else: self.map[i].insert(g,cell((i,g)))


def draw(self):
for i in range(map_size):
for g in range(map_size):
cell = self.map[i][g]
loc = cell.location
if cell.alive == True:
screen.blit(alive,(loc[0]*imgs[2],loc[1]*imgs[2]))
else:
screen.blit(dead,(loc[0]*imgs[2],loc[1]*imgs[2]))

def get_cells(self,cell):# gets the cells around a cell
mapa = self.map
a = []
b = []
c = 0
cell_loc = cell.location
try: a.append(mapa[abs(cell_loc[0]-1)][abs(cell_loc[1]-1)].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0])][abs(cell_loc[1]-1)].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0]+1)][abs(cell_loc[1]-1)].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0]-1)][abs(cell_loc[1])].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0]+1)][abs(cell_loc[1])].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0]-1)][abs(cell_loc[1]+1)].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0])][abs(cell_loc[1]+1)].location)
except Exception: pass
try: a.append(mapa[abs(cell_loc[0]+1)][abs(cell_loc[1]+1)].location)
except Exception: pass
num = len(list(OrderedDict.fromkeys(a)))# removes duplicates
for i in range(len(a)): b.append(mapa[a[i][0]][a[i][1]].alive)
for i in b:# c houses how many cells are alive around it
if i == True: c+=1
if cell.alive == True: # rules
if c < 2: cell.to_be = False
if c > 3:cell.to_be = False
else:
if c == 3: cell.to_be = True
# rules
def update_frame(self):
for i in range(map_size):
for g in range(map_size):
cell = self.map[i][g]
self.get_cells(cell)

def update(self):
for i in range(map_size):
for g in range(map_size):
cell = self.map[i][g]
loc = cell.location
if cell.to_be != None: cell.alive = cell.to_be
if self.map[i][g].alive == True:
screen.blit(alive,(loc[0]*imgs[2],loc[1]*imgs[2]))

textRect = cell.text.get_rect()
textRect.center = (loc[0]*imgs[2] +ceil(imgs[2]/2),loc[1]*imgs[2]+ceil(imgs[2]/2))
screen.blit(cell.text, textRect)

if run and loc not in marked_alive:
# OSC
if cell.osc != '':
print(cell.osc)
# Build a message with autodetection of data types, and send it.
msg = oscbuildparse.OSCMessage("/conway", None, [cell.osc])
osc_send(msg, "pureData")
osc_process()
marked_alive.append(loc)
else:
screen.blit(dead,(loc[0]*imgs[2],loc[1]*imgs[2]))

textRect = cell.text.get_rect()
textRect.center = (loc[0]*imgs[2] +ceil(imgs[2]/2),loc[1]*imgs[2]+ceil(imgs[2]/2))
screen.blit(cell.text, textRect)

if loc in marked_alive:
marked_alive.remove(loc)
cell.to_be = None

def cell_list():
lst = []
for i in range(map_size):
lst.append([])
for g in range(map_size): lst[i].append((board.map[i][g].location[0]*imgs[2],board.map[i][g].location[1]*imgs[2]))
return lst

#############################################################################################

board = board()
board.fill(False)
board.draw()
tp = 0
run = False

shift = False

while done == False:
milliseconds = clock.tick(60)
seconds = milliseconds / 1000.0
tp += milliseconds

for event in pygame.event.get():
if event.type == QUIT:
osc_terminate()
done = True

if event.type == KEYDOWN:
if event.key == K_SPACE:
run = not run

elif event.key == K_MINUS:
board.map = []
board.fill(False)
board.draw()

elif event.key == K_EQUALS:
board.map = []
board.fill(True)
board.draw()

elif event.key == K_RSHIFT or event.key == K_LSHIFT:
shift = True

elif event.key == K_BACKSPACE:
pos = pygame.mouse.get_pos()
rects = cell_list()
for i in range(map_size):
for g in range(map_size):
if pos[0] >= rects[i][g][0] and pos[0] < rects[i][g][0]+imgs[2] and pos[1] >= rects[i][g][1] and pos[1] < rects[i][g][1]+imgs[2]:
#print(i,g,key)
board.map[i][g].osc = ''
board.map[i][g].text = font.render('', True, white)
board.update()

else:
key = pygame.key.name(event.key)
if shift:
key = key.upper()
if key.isalpha() and len(key) == 1:
pos = pygame.mouse.get_pos()
rects = cell_list()
for i in range(map_size):
for g in range(map_size):
if pos[0] >= rects[i][g][0] and pos[0] < rects[i][g][0]+imgs[2] and pos[1] >= rects[i][g][1] and pos[1] < rects[i][g][1]+imgs[2]:
#print(i,g,key)
board.map[i][g].osc = key
board.map[i][g].text = font.render(key, True, white)
board.update()

if event.type == KEYUP:
if event.key == K_UP:
run = True
board.update_frame()
board.update()
run = False
elif event.key == K_RSHIFT or event.key == K_LSHIFT:
shift = False

if event.type == MOUSEBUTTONUP:
for i in range(map_size):
for g in range(map_size):
board.map[i][g].pressed = False

pressed = pygame.key.get_pressed()
mouse = pygame.mouse.get_pressed()
pos = pygame.mouse.get_pos()

# if pressed[K_MINUS]:
# board.map = []
# board.fill(False)
# board.draw()
# if pressed[K_EQUALS]:
# board.map = []
# board.fill(True)
# board.draw()

if run == True and tp >= 1000/speed :
tp = 0
board.update_frame()
board.update()

if mouse[0]:# makes cells alive
rects = cell_list()
for i in range(map_size):
for g in range(map_size):
if pos[0] >= rects[i][g][0] and pos[0] < rects[i][g][0]+imgs[2] and pos[1] >= rects[i][g][1] and pos[1] < rects[i][g][1]+imgs[2] and board.map[i][g].pressed == False:
board.map[i][g].alive = True
board.map[i][g].pressed = True
board.update()

if mouse[2]: # kills cells
rects = cell_list()
for i in range(map_size):
for g in range(map_size):
if pos[0] >= rects[i][g][0] and pos[0] < rects[i][g][0]+imgs[2] and pos[1] >= rects[i][g][1] and pos[1] < rects[i][g][1]+imgs[2] and board.map[i][g].pressed == False:
board.map[i][g].alive = False
board.map[i][g].pressed = False
board.update()

pygame.display.flip()

pygame.quit()
Binary file not shown.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN +214 Bytes conwayOSC/res/alive_8.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN +252 Bytes conwayOSC/res/dead_16.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN +435 Bytes conwayOSC/res/dead_32.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN +822 Bytes conwayOSC/res/dead_64.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN +203 Bytes conwayOSC/res/dead_8.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
@@ -1866,15 +1866,15 @@ to "hamilr4_control";
#X connect 3 0 4 0;
#X restore 207 313 pd more_structure;
#X obj 1628 422 channel;
#X obj 519 599 catch~ monkey;
#X obj 518 562 throw~ monkey;
#X text 506 526 AUDIO DATA (~);
#X floatatom 286 532 5 0 0 0 - - -;
#X floatatom 287 628 5 0 0 0 - - -;
#X obj 285 562 send hippo;
#X obj 285 595 receive hippo;
#X text 337 526 CONTROL DATA;
#X obj 274 457 class_3;
#X obj 519 689 catch~ monkey;
#X obj 518 652 throw~ monkey;
#X text 506 616 AUDIO DATA (~);
#X floatatom 286 622 5 0 0 0 - - -;
#X floatatom 287 718 5 0 0 0 - - -;
#X obj 285 652 send hippo;
#X obj 285 685 receive hippo;
#X text 337 616 CONTROL DATA;
#X obj 274 567 class_3;
#N canvas 0 23 960 1031 data_parsing 0;
#X obj 259 124 textfile;
#X obj 259 81 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
@@ -2715,6 +2715,13 @@ to "hamilr4_control";
#X restore 276 354 pd midi;
#X text 342 353 More MIDI...;
#X text 343 398 More Data...;
#N canvas 0 23 765 247 more_networking 0;
#X obj 153 115 conway;
#X text 143 75 Darius Smith's OSC "The Game Of Life" audio code;
#X text 223 109 To use \, launch the python Conway's Game of Life app
in the conwayOSC folder in the masheen folder;
#X restore 199 440 pd more_networking;
#X text 346 442 More Networking...;
#X connect 6 0 46 0;
#X connect 7 0 9 0;
#X connect 8 0 12 0;

0 comments on commit 951ec8a

Please sign in to comment.