Game of life inspired ASCII program

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
6
down vote

favorite
1












I'd found myself getting back into programming, and had recalled a fascinating little 'game' many might know of. I'm a very inexperienced programmer, and I know this is sloppy, but I'd wanted to make something that had a sort of pseudo-cellular life kind of behavior.



There's no real pattern to their movement, but it does create a quite mesmerizing effect. All it does is generate a 'turtle' that wanders around turning tiles to the 'on' state until it dies after about 10 steps. If it encounters an 'on' tile, the turtle creates a new turtle in an adjacent space.



I'm well aware I have this really horribly optimized, but I'm hoping to expand upon it and probably just rewrite it more sanely. I used a little package called 'tdl' for ASCII graphics because I enjoy them and I really don't understand matplotlab animation at all or animation in general.



Controls:



  • Press 2 or 3 (not numpad) to add a new turtle value at a random position

  • Press Enter to increment one 'step'

  • Press c to clear the board

  • Press p to print the current population to the console

This is my bag of colors. It'll ask if you want to download upon opening the link.



This is the font used:



enter image description here



from random import randint #Woot! My turtles live life with no aim! Just livin on psudo-random whims XD

import numpy as np #You all know what this is, but I barely do

import tdl #A neat little package for handling ascii graphics. Just using it because it's very simple and fun.... and I don't really understand matplotlib animations....

import colors #Just a big bag of color values

SCREEN_WIDTH = 80
SCREEN_HEIGHT = 80

FONTSET = 'arial10x10.png'

LIMIT_FPS = 20

MAP_WIDTH = 100
MAP_HEIGHT = 80

BOARD = np.zeros( (MAP_WIDTH, MAP_HEIGHT) )



class TurtleBrain():
def __init__(self, pattern):
self.flag = True
self.pattern = pattern


def process(self):
"""Handles the 'steps' for each turtle value
I did it this way so that I could later decide to add new values with different movements and behaviors
or have several different types of life on the board at once, if I so choose to impliment them
"""
while self.pattern == 'original':
if self.flag:
self.move_twos()
self.flag = (not self.flag)
break
else:
self.move_threes()
self.flag = (not self.flag)
break



def move_twos(self):
"""
I'm sure there are so many better ways to do this:
Form lists of coordinates and data
Make a dictionary of coordinate keys with data values?
Sparse arrays?
"""
#Find every 2 turtle
for y in range(MAP_HEIGHT-1):
for x in range(MAP_WIDTH-1):
cell = BOARD[x, y]
if 2.0 <= cell <= 2.2:
failed = True
while True:
dx = randint(-1, 1)
dy = randint(-1, 1)
new_x = x + dx
new_y = y + dy
if dx == 0 and dy == 0:
continue
else:
failed = False
break

new_cell = BOARD[int(new_x), int(new_y)]

if new_cell == 1.0:

BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] + 1

BOARD[int(x), int(y)] = 0.0

self.make_child(new_x, new_y)



elif new_cell == 0.0:

BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] + 1

BOARD[int(x), int(y)] = 1.0

else:
BOARD[int(new_x), int(new_y)] += .01





def move_threes(self):
#find every 3 turtle
for y in range(MAP_HEIGHT-1):
for x in range(MAP_WIDTH-1):
cell = BOARD[x, y]
if 3.0 <= cell <= 3.2:

failed = True
while True:
dx = randint(-1, 1)
dy = randint(-1, 1)
new_x = x + dx
new_y = y + dy
if dx == 0 and dy == 0:
continue
else:
failed = False
break

new_cell = BOARD[int(new_x), int(new_y)]

if new_cell == 1.0:
BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] - 1

BOARD[int(x), int(y)] = 0.0


self.make_child(new_x, new_y)

elif new_cell == 0.0:
BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] - 1

BOARD[int(x), int(y)] = 1.0

else:
BOARD[int(new_x), int(new_y)] += .01



def move_fours(self):
"""Planned as a predator type to cull the 2 and 3 hoards mwuahaha"""
for x in BOARD:
for y in BOARD[x]:
cell = BOARD[x, y]
if 4.0 <= cell <= 4.2:
pass





def make_child(self, px, py):
failed = True
while True:
child_x = px + randint(-1, 1)
child_y = py + randint(-1, 1)
if BOARD[int(child_x), int(child_y)] == 0.0 or BOARD[int(child_x), int(child_y)] == 1.0:
failed = False
break

if not failed:
BOARD[int(child_x), int(child_y)] = 2.0
#print("I made a child at (%d, %d)" % (child_x, child_y))

class TimeStep():
def __init__(self, age_value):
self.age_value = age_value

def process(self):

for y in range(MAP_HEIGHT):
for x in range(MAP_WIDTH):
if 2.0 <= BOARD[x, y] <= 3.1:
#print("Test?")
BOARD[x, y] += self.age_value
#print(str(BOARD[x, y]) + " at (%d, %d)" % (x, y))
if 2.1 <= BOARD[x, y] <= 2.9 or 3.1 <= BOARD[x, y] <= 3.9:
BOARD[x, y] = 0.0
#print("Turtle at (%d, %d) died" % (x, y))
pass


class RenderProcessor():
def __init__(self, _con, _root):
super().__init__()
self._con = _con
self._root = _root

def process(self):
for y in range(MAP_HEIGHT):
for x in range(MAP_WIDTH):


if BOARD[x, y] == 0.0:
self._con.draw_char(x, y, '#', fg=colors.dark_grey, bg=colors.darker_grey)
#elif 2.0 <= BOARD[x, y] <= 2.99 or 3.0 <= BOARD[x, y] <= 3.99:
# self._con.draw_char(x, y, '@', fg=colors.dark_green, bg=colors.black)
elif 2.0 <= BOARD[x, y] <= 2.01 or 3.0 <= BOARD[x, y] <= 3.01:
self._con.draw_char(x, y, '0', fg=colors.dark_green, bg=colors.black)
elif 2.01 <= BOARD[x, y] <= 2.02 or 3.01 <= BOARD[x, y] <= 3.02:
self._con.draw_char(x, y, '1', fg=colors.dark_lime, bg=colors.black)
elif 2.02 <= BOARD[x, y] <= 2.03 or 3.02 <= BOARD[x, y] <= 3.03:
self._con.draw_char(x, y, '2', fg=colors.dark_red, bg=colors.black)
elif 2.03 <= BOARD[x, y] <= 2.04 or 3.03 <= BOARD[x, y] <= 3.04:
self._con.draw_char(x, y, '3', fg=colors.dark_blue, bg=colors.black)
elif 2.04 <= BOARD[x, y] <= 2.05 or 3.04 <= BOARD[x, y] <= 3.05:
self._con.draw_char(x, y, '4', fg=colors.dark_purple, bg=colors.black)
elif 2.05 <= BOARD[x, y] <= 2.06 or 3.05 <= BOARD[x, y] <= 3.06:
self._con.draw_char(x, y, '5', fg=colors.dark_violet, bg=colors.black)
elif 2.06 <= BOARD[x, y] <= 2.07 or 3.06 <= BOARD[x, y] <= 3.07:
self._con.draw_char(x, y, '6', fg=colors.dark_sky, bg=colors.black)
elif 2.07 <= BOARD[x, y] <= 2.08 or 3.07 <= BOARD[x, y] <= 3.08:
self._con.draw_char(x, y, '7', fg=colors.dark_cyan, bg=colors.black)
elif 2.08 <= BOARD[x, y] <= 2.09 or 3.08 <= BOARD[x, y] <= 3.09:
self._con.draw_char(x, y, '8', fg=colors.dark_cyan, bg=colors.black)
elif 2.09 <= BOARD[x, y] < 2.1 or 3.09 <= BOARD[x, y] <= 3.1:
self._con.draw_char(x, y, '9', fg=colors.darkest_pink, bg=colors.black)
else:
self._con.draw_char(x, y, '#', fg=colors.darker_green, bg=colors.dark_green)


self._root.blit(self._con, 0, 0, MAP_WIDTH, MAP_HEIGHT, 0, 0)
tdl.flush()


##################################################################
tdl.set_font(FONTSET, greyscale=True, altLayout=True)
root = tdl.init(SCREEN_WIDTH, SCREEN_HEIGHT, title="TURTLES",
fullscreen=False)
tdl.setFPS(LIMIT_FPS)
con = tdl.Console(MAP_HEIGHT, MAP_WIDTH)
##################################################################


def count_turts():
total = 0
for y in range(MAP_HEIGHT - 1):
for x in range(MAP_WIDTH - 1):
cell = BOARD[x, y]
if 2.0 <= cell <= 2.12 or 3.0 <= cell <= 3.12:
total += 1

print("There are %d total turtles" % (total))


BOARD[50, 50] = 2.0

turtlebrain = TurtleBrain(pattern='original')
timeprocessor = TimeStep(.01)
renderprocessor = RenderProcessor(con, root)

con.clear()


def handle_keys():

user_input = tdl.event.key_wait()
if user_input.key == 'ESCAPE':
return 'exit'


if user_input.key == 'ENTER':
return 'go'

if user_input.char == '2':
return user_input.char

if user_input.char == '3':
return user_input.char


if user_input.char == 'c':
return 'clear'

if user_input.char == 'p':
return user_input.char

if user_input.key == 'F11':
return user_input.key



renderprocessor.process()

def add_turtle(turt):
BOARD[randint(0, MAP_WIDTH - 1), randint(0, MAP_HEIGHT - 1)] = 2.0

while not tdl.event.is_window_closed():
player_input = handle_keys()
if player_input == 'go':
turtlebrain.process()
timeprocessor.process()
renderprocessor.process()

elif player_input == 'exit':
break

elif player_input == 'F11':
tdl.set_fullscreen(not tdl.get_fullscreen())
pass

elif player_input == '2':
add_turtle(2)
elif player_input == '3':
add_turtle(3)

elif player_input == 'p':
count_turts()


elif player_input == 'clear':
BOARD = np.zeros( (MAP_WIDTH, MAP_HEIGHT) )

renderprocessor.process()






share|improve this question



























    up vote
    6
    down vote

    favorite
    1












    I'd found myself getting back into programming, and had recalled a fascinating little 'game' many might know of. I'm a very inexperienced programmer, and I know this is sloppy, but I'd wanted to make something that had a sort of pseudo-cellular life kind of behavior.



    There's no real pattern to their movement, but it does create a quite mesmerizing effect. All it does is generate a 'turtle' that wanders around turning tiles to the 'on' state until it dies after about 10 steps. If it encounters an 'on' tile, the turtle creates a new turtle in an adjacent space.



    I'm well aware I have this really horribly optimized, but I'm hoping to expand upon it and probably just rewrite it more sanely. I used a little package called 'tdl' for ASCII graphics because I enjoy them and I really don't understand matplotlab animation at all or animation in general.



    Controls:



    • Press 2 or 3 (not numpad) to add a new turtle value at a random position

    • Press Enter to increment one 'step'

    • Press c to clear the board

    • Press p to print the current population to the console

    This is my bag of colors. It'll ask if you want to download upon opening the link.



    This is the font used:



    enter image description here



    from random import randint #Woot! My turtles live life with no aim! Just livin on psudo-random whims XD

    import numpy as np #You all know what this is, but I barely do

    import tdl #A neat little package for handling ascii graphics. Just using it because it's very simple and fun.... and I don't really understand matplotlib animations....

    import colors #Just a big bag of color values

    SCREEN_WIDTH = 80
    SCREEN_HEIGHT = 80

    FONTSET = 'arial10x10.png'

    LIMIT_FPS = 20

    MAP_WIDTH = 100
    MAP_HEIGHT = 80

    BOARD = np.zeros( (MAP_WIDTH, MAP_HEIGHT) )



    class TurtleBrain():
    def __init__(self, pattern):
    self.flag = True
    self.pattern = pattern


    def process(self):
    """Handles the 'steps' for each turtle value
    I did it this way so that I could later decide to add new values with different movements and behaviors
    or have several different types of life on the board at once, if I so choose to impliment them
    """
    while self.pattern == 'original':
    if self.flag:
    self.move_twos()
    self.flag = (not self.flag)
    break
    else:
    self.move_threes()
    self.flag = (not self.flag)
    break



    def move_twos(self):
    """
    I'm sure there are so many better ways to do this:
    Form lists of coordinates and data
    Make a dictionary of coordinate keys with data values?
    Sparse arrays?
    """
    #Find every 2 turtle
    for y in range(MAP_HEIGHT-1):
    for x in range(MAP_WIDTH-1):
    cell = BOARD[x, y]
    if 2.0 <= cell <= 2.2:
    failed = True
    while True:
    dx = randint(-1, 1)
    dy = randint(-1, 1)
    new_x = x + dx
    new_y = y + dy
    if dx == 0 and dy == 0:
    continue
    else:
    failed = False
    break

    new_cell = BOARD[int(new_x), int(new_y)]

    if new_cell == 1.0:

    BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] + 1

    BOARD[int(x), int(y)] = 0.0

    self.make_child(new_x, new_y)



    elif new_cell == 0.0:

    BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] + 1

    BOARD[int(x), int(y)] = 1.0

    else:
    BOARD[int(new_x), int(new_y)] += .01





    def move_threes(self):
    #find every 3 turtle
    for y in range(MAP_HEIGHT-1):
    for x in range(MAP_WIDTH-1):
    cell = BOARD[x, y]
    if 3.0 <= cell <= 3.2:

    failed = True
    while True:
    dx = randint(-1, 1)
    dy = randint(-1, 1)
    new_x = x + dx
    new_y = y + dy
    if dx == 0 and dy == 0:
    continue
    else:
    failed = False
    break

    new_cell = BOARD[int(new_x), int(new_y)]

    if new_cell == 1.0:
    BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] - 1

    BOARD[int(x), int(y)] = 0.0


    self.make_child(new_x, new_y)

    elif new_cell == 0.0:
    BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] - 1

    BOARD[int(x), int(y)] = 1.0

    else:
    BOARD[int(new_x), int(new_y)] += .01



    def move_fours(self):
    """Planned as a predator type to cull the 2 and 3 hoards mwuahaha"""
    for x in BOARD:
    for y in BOARD[x]:
    cell = BOARD[x, y]
    if 4.0 <= cell <= 4.2:
    pass





    def make_child(self, px, py):
    failed = True
    while True:
    child_x = px + randint(-1, 1)
    child_y = py + randint(-1, 1)
    if BOARD[int(child_x), int(child_y)] == 0.0 or BOARD[int(child_x), int(child_y)] == 1.0:
    failed = False
    break

    if not failed:
    BOARD[int(child_x), int(child_y)] = 2.0
    #print("I made a child at (%d, %d)" % (child_x, child_y))

    class TimeStep():
    def __init__(self, age_value):
    self.age_value = age_value

    def process(self):

    for y in range(MAP_HEIGHT):
    for x in range(MAP_WIDTH):
    if 2.0 <= BOARD[x, y] <= 3.1:
    #print("Test?")
    BOARD[x, y] += self.age_value
    #print(str(BOARD[x, y]) + " at (%d, %d)" % (x, y))
    if 2.1 <= BOARD[x, y] <= 2.9 or 3.1 <= BOARD[x, y] <= 3.9:
    BOARD[x, y] = 0.0
    #print("Turtle at (%d, %d) died" % (x, y))
    pass


    class RenderProcessor():
    def __init__(self, _con, _root):
    super().__init__()
    self._con = _con
    self._root = _root

    def process(self):
    for y in range(MAP_HEIGHT):
    for x in range(MAP_WIDTH):


    if BOARD[x, y] == 0.0:
    self._con.draw_char(x, y, '#', fg=colors.dark_grey, bg=colors.darker_grey)
    #elif 2.0 <= BOARD[x, y] <= 2.99 or 3.0 <= BOARD[x, y] <= 3.99:
    # self._con.draw_char(x, y, '@', fg=colors.dark_green, bg=colors.black)
    elif 2.0 <= BOARD[x, y] <= 2.01 or 3.0 <= BOARD[x, y] <= 3.01:
    self._con.draw_char(x, y, '0', fg=colors.dark_green, bg=colors.black)
    elif 2.01 <= BOARD[x, y] <= 2.02 or 3.01 <= BOARD[x, y] <= 3.02:
    self._con.draw_char(x, y, '1', fg=colors.dark_lime, bg=colors.black)
    elif 2.02 <= BOARD[x, y] <= 2.03 or 3.02 <= BOARD[x, y] <= 3.03:
    self._con.draw_char(x, y, '2', fg=colors.dark_red, bg=colors.black)
    elif 2.03 <= BOARD[x, y] <= 2.04 or 3.03 <= BOARD[x, y] <= 3.04:
    self._con.draw_char(x, y, '3', fg=colors.dark_blue, bg=colors.black)
    elif 2.04 <= BOARD[x, y] <= 2.05 or 3.04 <= BOARD[x, y] <= 3.05:
    self._con.draw_char(x, y, '4', fg=colors.dark_purple, bg=colors.black)
    elif 2.05 <= BOARD[x, y] <= 2.06 or 3.05 <= BOARD[x, y] <= 3.06:
    self._con.draw_char(x, y, '5', fg=colors.dark_violet, bg=colors.black)
    elif 2.06 <= BOARD[x, y] <= 2.07 or 3.06 <= BOARD[x, y] <= 3.07:
    self._con.draw_char(x, y, '6', fg=colors.dark_sky, bg=colors.black)
    elif 2.07 <= BOARD[x, y] <= 2.08 or 3.07 <= BOARD[x, y] <= 3.08:
    self._con.draw_char(x, y, '7', fg=colors.dark_cyan, bg=colors.black)
    elif 2.08 <= BOARD[x, y] <= 2.09 or 3.08 <= BOARD[x, y] <= 3.09:
    self._con.draw_char(x, y, '8', fg=colors.dark_cyan, bg=colors.black)
    elif 2.09 <= BOARD[x, y] < 2.1 or 3.09 <= BOARD[x, y] <= 3.1:
    self._con.draw_char(x, y, '9', fg=colors.darkest_pink, bg=colors.black)
    else:
    self._con.draw_char(x, y, '#', fg=colors.darker_green, bg=colors.dark_green)


    self._root.blit(self._con, 0, 0, MAP_WIDTH, MAP_HEIGHT, 0, 0)
    tdl.flush()


    ##################################################################
    tdl.set_font(FONTSET, greyscale=True, altLayout=True)
    root = tdl.init(SCREEN_WIDTH, SCREEN_HEIGHT, title="TURTLES",
    fullscreen=False)
    tdl.setFPS(LIMIT_FPS)
    con = tdl.Console(MAP_HEIGHT, MAP_WIDTH)
    ##################################################################


    def count_turts():
    total = 0
    for y in range(MAP_HEIGHT - 1):
    for x in range(MAP_WIDTH - 1):
    cell = BOARD[x, y]
    if 2.0 <= cell <= 2.12 or 3.0 <= cell <= 3.12:
    total += 1

    print("There are %d total turtles" % (total))


    BOARD[50, 50] = 2.0

    turtlebrain = TurtleBrain(pattern='original')
    timeprocessor = TimeStep(.01)
    renderprocessor = RenderProcessor(con, root)

    con.clear()


    def handle_keys():

    user_input = tdl.event.key_wait()
    if user_input.key == 'ESCAPE':
    return 'exit'


    if user_input.key == 'ENTER':
    return 'go'

    if user_input.char == '2':
    return user_input.char

    if user_input.char == '3':
    return user_input.char


    if user_input.char == 'c':
    return 'clear'

    if user_input.char == 'p':
    return user_input.char

    if user_input.key == 'F11':
    return user_input.key



    renderprocessor.process()

    def add_turtle(turt):
    BOARD[randint(0, MAP_WIDTH - 1), randint(0, MAP_HEIGHT - 1)] = 2.0

    while not tdl.event.is_window_closed():
    player_input = handle_keys()
    if player_input == 'go':
    turtlebrain.process()
    timeprocessor.process()
    renderprocessor.process()

    elif player_input == 'exit':
    break

    elif player_input == 'F11':
    tdl.set_fullscreen(not tdl.get_fullscreen())
    pass

    elif player_input == '2':
    add_turtle(2)
    elif player_input == '3':
    add_turtle(3)

    elif player_input == 'p':
    count_turts()


    elif player_input == 'clear':
    BOARD = np.zeros( (MAP_WIDTH, MAP_HEIGHT) )

    renderprocessor.process()






    share|improve this question























      up vote
      6
      down vote

      favorite
      1









      up vote
      6
      down vote

      favorite
      1






      1





      I'd found myself getting back into programming, and had recalled a fascinating little 'game' many might know of. I'm a very inexperienced programmer, and I know this is sloppy, but I'd wanted to make something that had a sort of pseudo-cellular life kind of behavior.



      There's no real pattern to their movement, but it does create a quite mesmerizing effect. All it does is generate a 'turtle' that wanders around turning tiles to the 'on' state until it dies after about 10 steps. If it encounters an 'on' tile, the turtle creates a new turtle in an adjacent space.



      I'm well aware I have this really horribly optimized, but I'm hoping to expand upon it and probably just rewrite it more sanely. I used a little package called 'tdl' for ASCII graphics because I enjoy them and I really don't understand matplotlab animation at all or animation in general.



      Controls:



      • Press 2 or 3 (not numpad) to add a new turtle value at a random position

      • Press Enter to increment one 'step'

      • Press c to clear the board

      • Press p to print the current population to the console

      This is my bag of colors. It'll ask if you want to download upon opening the link.



      This is the font used:



      enter image description here



      from random import randint #Woot! My turtles live life with no aim! Just livin on psudo-random whims XD

      import numpy as np #You all know what this is, but I barely do

      import tdl #A neat little package for handling ascii graphics. Just using it because it's very simple and fun.... and I don't really understand matplotlib animations....

      import colors #Just a big bag of color values

      SCREEN_WIDTH = 80
      SCREEN_HEIGHT = 80

      FONTSET = 'arial10x10.png'

      LIMIT_FPS = 20

      MAP_WIDTH = 100
      MAP_HEIGHT = 80

      BOARD = np.zeros( (MAP_WIDTH, MAP_HEIGHT) )



      class TurtleBrain():
      def __init__(self, pattern):
      self.flag = True
      self.pattern = pattern


      def process(self):
      """Handles the 'steps' for each turtle value
      I did it this way so that I could later decide to add new values with different movements and behaviors
      or have several different types of life on the board at once, if I so choose to impliment them
      """
      while self.pattern == 'original':
      if self.flag:
      self.move_twos()
      self.flag = (not self.flag)
      break
      else:
      self.move_threes()
      self.flag = (not self.flag)
      break



      def move_twos(self):
      """
      I'm sure there are so many better ways to do this:
      Form lists of coordinates and data
      Make a dictionary of coordinate keys with data values?
      Sparse arrays?
      """
      #Find every 2 turtle
      for y in range(MAP_HEIGHT-1):
      for x in range(MAP_WIDTH-1):
      cell = BOARD[x, y]
      if 2.0 <= cell <= 2.2:
      failed = True
      while True:
      dx = randint(-1, 1)
      dy = randint(-1, 1)
      new_x = x + dx
      new_y = y + dy
      if dx == 0 and dy == 0:
      continue
      else:
      failed = False
      break

      new_cell = BOARD[int(new_x), int(new_y)]

      if new_cell == 1.0:

      BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] + 1

      BOARD[int(x), int(y)] = 0.0

      self.make_child(new_x, new_y)



      elif new_cell == 0.0:

      BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] + 1

      BOARD[int(x), int(y)] = 1.0

      else:
      BOARD[int(new_x), int(new_y)] += .01





      def move_threes(self):
      #find every 3 turtle
      for y in range(MAP_HEIGHT-1):
      for x in range(MAP_WIDTH-1):
      cell = BOARD[x, y]
      if 3.0 <= cell <= 3.2:

      failed = True
      while True:
      dx = randint(-1, 1)
      dy = randint(-1, 1)
      new_x = x + dx
      new_y = y + dy
      if dx == 0 and dy == 0:
      continue
      else:
      failed = False
      break

      new_cell = BOARD[int(new_x), int(new_y)]

      if new_cell == 1.0:
      BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] - 1

      BOARD[int(x), int(y)] = 0.0


      self.make_child(new_x, new_y)

      elif new_cell == 0.0:
      BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] - 1

      BOARD[int(x), int(y)] = 1.0

      else:
      BOARD[int(new_x), int(new_y)] += .01



      def move_fours(self):
      """Planned as a predator type to cull the 2 and 3 hoards mwuahaha"""
      for x in BOARD:
      for y in BOARD[x]:
      cell = BOARD[x, y]
      if 4.0 <= cell <= 4.2:
      pass





      def make_child(self, px, py):
      failed = True
      while True:
      child_x = px + randint(-1, 1)
      child_y = py + randint(-1, 1)
      if BOARD[int(child_x), int(child_y)] == 0.0 or BOARD[int(child_x), int(child_y)] == 1.0:
      failed = False
      break

      if not failed:
      BOARD[int(child_x), int(child_y)] = 2.0
      #print("I made a child at (%d, %d)" % (child_x, child_y))

      class TimeStep():
      def __init__(self, age_value):
      self.age_value = age_value

      def process(self):

      for y in range(MAP_HEIGHT):
      for x in range(MAP_WIDTH):
      if 2.0 <= BOARD[x, y] <= 3.1:
      #print("Test?")
      BOARD[x, y] += self.age_value
      #print(str(BOARD[x, y]) + " at (%d, %d)" % (x, y))
      if 2.1 <= BOARD[x, y] <= 2.9 or 3.1 <= BOARD[x, y] <= 3.9:
      BOARD[x, y] = 0.0
      #print("Turtle at (%d, %d) died" % (x, y))
      pass


      class RenderProcessor():
      def __init__(self, _con, _root):
      super().__init__()
      self._con = _con
      self._root = _root

      def process(self):
      for y in range(MAP_HEIGHT):
      for x in range(MAP_WIDTH):


      if BOARD[x, y] == 0.0:
      self._con.draw_char(x, y, '#', fg=colors.dark_grey, bg=colors.darker_grey)
      #elif 2.0 <= BOARD[x, y] <= 2.99 or 3.0 <= BOARD[x, y] <= 3.99:
      # self._con.draw_char(x, y, '@', fg=colors.dark_green, bg=colors.black)
      elif 2.0 <= BOARD[x, y] <= 2.01 or 3.0 <= BOARD[x, y] <= 3.01:
      self._con.draw_char(x, y, '0', fg=colors.dark_green, bg=colors.black)
      elif 2.01 <= BOARD[x, y] <= 2.02 or 3.01 <= BOARD[x, y] <= 3.02:
      self._con.draw_char(x, y, '1', fg=colors.dark_lime, bg=colors.black)
      elif 2.02 <= BOARD[x, y] <= 2.03 or 3.02 <= BOARD[x, y] <= 3.03:
      self._con.draw_char(x, y, '2', fg=colors.dark_red, bg=colors.black)
      elif 2.03 <= BOARD[x, y] <= 2.04 or 3.03 <= BOARD[x, y] <= 3.04:
      self._con.draw_char(x, y, '3', fg=colors.dark_blue, bg=colors.black)
      elif 2.04 <= BOARD[x, y] <= 2.05 or 3.04 <= BOARD[x, y] <= 3.05:
      self._con.draw_char(x, y, '4', fg=colors.dark_purple, bg=colors.black)
      elif 2.05 <= BOARD[x, y] <= 2.06 or 3.05 <= BOARD[x, y] <= 3.06:
      self._con.draw_char(x, y, '5', fg=colors.dark_violet, bg=colors.black)
      elif 2.06 <= BOARD[x, y] <= 2.07 or 3.06 <= BOARD[x, y] <= 3.07:
      self._con.draw_char(x, y, '6', fg=colors.dark_sky, bg=colors.black)
      elif 2.07 <= BOARD[x, y] <= 2.08 or 3.07 <= BOARD[x, y] <= 3.08:
      self._con.draw_char(x, y, '7', fg=colors.dark_cyan, bg=colors.black)
      elif 2.08 <= BOARD[x, y] <= 2.09 or 3.08 <= BOARD[x, y] <= 3.09:
      self._con.draw_char(x, y, '8', fg=colors.dark_cyan, bg=colors.black)
      elif 2.09 <= BOARD[x, y] < 2.1 or 3.09 <= BOARD[x, y] <= 3.1:
      self._con.draw_char(x, y, '9', fg=colors.darkest_pink, bg=colors.black)
      else:
      self._con.draw_char(x, y, '#', fg=colors.darker_green, bg=colors.dark_green)


      self._root.blit(self._con, 0, 0, MAP_WIDTH, MAP_HEIGHT, 0, 0)
      tdl.flush()


      ##################################################################
      tdl.set_font(FONTSET, greyscale=True, altLayout=True)
      root = tdl.init(SCREEN_WIDTH, SCREEN_HEIGHT, title="TURTLES",
      fullscreen=False)
      tdl.setFPS(LIMIT_FPS)
      con = tdl.Console(MAP_HEIGHT, MAP_WIDTH)
      ##################################################################


      def count_turts():
      total = 0
      for y in range(MAP_HEIGHT - 1):
      for x in range(MAP_WIDTH - 1):
      cell = BOARD[x, y]
      if 2.0 <= cell <= 2.12 or 3.0 <= cell <= 3.12:
      total += 1

      print("There are %d total turtles" % (total))


      BOARD[50, 50] = 2.0

      turtlebrain = TurtleBrain(pattern='original')
      timeprocessor = TimeStep(.01)
      renderprocessor = RenderProcessor(con, root)

      con.clear()


      def handle_keys():

      user_input = tdl.event.key_wait()
      if user_input.key == 'ESCAPE':
      return 'exit'


      if user_input.key == 'ENTER':
      return 'go'

      if user_input.char == '2':
      return user_input.char

      if user_input.char == '3':
      return user_input.char


      if user_input.char == 'c':
      return 'clear'

      if user_input.char == 'p':
      return user_input.char

      if user_input.key == 'F11':
      return user_input.key



      renderprocessor.process()

      def add_turtle(turt):
      BOARD[randint(0, MAP_WIDTH - 1), randint(0, MAP_HEIGHT - 1)] = 2.0

      while not tdl.event.is_window_closed():
      player_input = handle_keys()
      if player_input == 'go':
      turtlebrain.process()
      timeprocessor.process()
      renderprocessor.process()

      elif player_input == 'exit':
      break

      elif player_input == 'F11':
      tdl.set_fullscreen(not tdl.get_fullscreen())
      pass

      elif player_input == '2':
      add_turtle(2)
      elif player_input == '3':
      add_turtle(3)

      elif player_input == 'p':
      count_turts()


      elif player_input == 'clear':
      BOARD = np.zeros( (MAP_WIDTH, MAP_HEIGHT) )

      renderprocessor.process()






      share|improve this question













      I'd found myself getting back into programming, and had recalled a fascinating little 'game' many might know of. I'm a very inexperienced programmer, and I know this is sloppy, but I'd wanted to make something that had a sort of pseudo-cellular life kind of behavior.



      There's no real pattern to their movement, but it does create a quite mesmerizing effect. All it does is generate a 'turtle' that wanders around turning tiles to the 'on' state until it dies after about 10 steps. If it encounters an 'on' tile, the turtle creates a new turtle in an adjacent space.



      I'm well aware I have this really horribly optimized, but I'm hoping to expand upon it and probably just rewrite it more sanely. I used a little package called 'tdl' for ASCII graphics because I enjoy them and I really don't understand matplotlab animation at all or animation in general.



      Controls:



      • Press 2 or 3 (not numpad) to add a new turtle value at a random position

      • Press Enter to increment one 'step'

      • Press c to clear the board

      • Press p to print the current population to the console

      This is my bag of colors. It'll ask if you want to download upon opening the link.



      This is the font used:



      enter image description here



      from random import randint #Woot! My turtles live life with no aim! Just livin on psudo-random whims XD

      import numpy as np #You all know what this is, but I barely do

      import tdl #A neat little package for handling ascii graphics. Just using it because it's very simple and fun.... and I don't really understand matplotlib animations....

      import colors #Just a big bag of color values

      SCREEN_WIDTH = 80
      SCREEN_HEIGHT = 80

      FONTSET = 'arial10x10.png'

      LIMIT_FPS = 20

      MAP_WIDTH = 100
      MAP_HEIGHT = 80

      BOARD = np.zeros( (MAP_WIDTH, MAP_HEIGHT) )



      class TurtleBrain():
      def __init__(self, pattern):
      self.flag = True
      self.pattern = pattern


      def process(self):
      """Handles the 'steps' for each turtle value
      I did it this way so that I could later decide to add new values with different movements and behaviors
      or have several different types of life on the board at once, if I so choose to impliment them
      """
      while self.pattern == 'original':
      if self.flag:
      self.move_twos()
      self.flag = (not self.flag)
      break
      else:
      self.move_threes()
      self.flag = (not self.flag)
      break



      def move_twos(self):
      """
      I'm sure there are so many better ways to do this:
      Form lists of coordinates and data
      Make a dictionary of coordinate keys with data values?
      Sparse arrays?
      """
      #Find every 2 turtle
      for y in range(MAP_HEIGHT-1):
      for x in range(MAP_WIDTH-1):
      cell = BOARD[x, y]
      if 2.0 <= cell <= 2.2:
      failed = True
      while True:
      dx = randint(-1, 1)
      dy = randint(-1, 1)
      new_x = x + dx
      new_y = y + dy
      if dx == 0 and dy == 0:
      continue
      else:
      failed = False
      break

      new_cell = BOARD[int(new_x), int(new_y)]

      if new_cell == 1.0:

      BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] + 1

      BOARD[int(x), int(y)] = 0.0

      self.make_child(new_x, new_y)



      elif new_cell == 0.0:

      BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] + 1

      BOARD[int(x), int(y)] = 1.0

      else:
      BOARD[int(new_x), int(new_y)] += .01





      def move_threes(self):
      #find every 3 turtle
      for y in range(MAP_HEIGHT-1):
      for x in range(MAP_WIDTH-1):
      cell = BOARD[x, y]
      if 3.0 <= cell <= 3.2:

      failed = True
      while True:
      dx = randint(-1, 1)
      dy = randint(-1, 1)
      new_x = x + dx
      new_y = y + dy
      if dx == 0 and dy == 0:
      continue
      else:
      failed = False
      break

      new_cell = BOARD[int(new_x), int(new_y)]

      if new_cell == 1.0:
      BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] - 1

      BOARD[int(x), int(y)] = 0.0


      self.make_child(new_x, new_y)

      elif new_cell == 0.0:
      BOARD[int(new_x), int(new_y)] = BOARD[int(x), int(y)] - 1

      BOARD[int(x), int(y)] = 1.0

      else:
      BOARD[int(new_x), int(new_y)] += .01



      def move_fours(self):
      """Planned as a predator type to cull the 2 and 3 hoards mwuahaha"""
      for x in BOARD:
      for y in BOARD[x]:
      cell = BOARD[x, y]
      if 4.0 <= cell <= 4.2:
      pass





      def make_child(self, px, py):
      failed = True
      while True:
      child_x = px + randint(-1, 1)
      child_y = py + randint(-1, 1)
      if BOARD[int(child_x), int(child_y)] == 0.0 or BOARD[int(child_x), int(child_y)] == 1.0:
      failed = False
      break

      if not failed:
      BOARD[int(child_x), int(child_y)] = 2.0
      #print("I made a child at (%d, %d)" % (child_x, child_y))

      class TimeStep():
      def __init__(self, age_value):
      self.age_value = age_value

      def process(self):

      for y in range(MAP_HEIGHT):
      for x in range(MAP_WIDTH):
      if 2.0 <= BOARD[x, y] <= 3.1:
      #print("Test?")
      BOARD[x, y] += self.age_value
      #print(str(BOARD[x, y]) + " at (%d, %d)" % (x, y))
      if 2.1 <= BOARD[x, y] <= 2.9 or 3.1 <= BOARD[x, y] <= 3.9:
      BOARD[x, y] = 0.0
      #print("Turtle at (%d, %d) died" % (x, y))
      pass


      class RenderProcessor():
      def __init__(self, _con, _root):
      super().__init__()
      self._con = _con
      self._root = _root

      def process(self):
      for y in range(MAP_HEIGHT):
      for x in range(MAP_WIDTH):


      if BOARD[x, y] == 0.0:
      self._con.draw_char(x, y, '#', fg=colors.dark_grey, bg=colors.darker_grey)
      #elif 2.0 <= BOARD[x, y] <= 2.99 or 3.0 <= BOARD[x, y] <= 3.99:
      # self._con.draw_char(x, y, '@', fg=colors.dark_green, bg=colors.black)
      elif 2.0 <= BOARD[x, y] <= 2.01 or 3.0 <= BOARD[x, y] <= 3.01:
      self._con.draw_char(x, y, '0', fg=colors.dark_green, bg=colors.black)
      elif 2.01 <= BOARD[x, y] <= 2.02 or 3.01 <= BOARD[x, y] <= 3.02:
      self._con.draw_char(x, y, '1', fg=colors.dark_lime, bg=colors.black)
      elif 2.02 <= BOARD[x, y] <= 2.03 or 3.02 <= BOARD[x, y] <= 3.03:
      self._con.draw_char(x, y, '2', fg=colors.dark_red, bg=colors.black)
      elif 2.03 <= BOARD[x, y] <= 2.04 or 3.03 <= BOARD[x, y] <= 3.04:
      self._con.draw_char(x, y, '3', fg=colors.dark_blue, bg=colors.black)
      elif 2.04 <= BOARD[x, y] <= 2.05 or 3.04 <= BOARD[x, y] <= 3.05:
      self._con.draw_char(x, y, '4', fg=colors.dark_purple, bg=colors.black)
      elif 2.05 <= BOARD[x, y] <= 2.06 or 3.05 <= BOARD[x, y] <= 3.06:
      self._con.draw_char(x, y, '5', fg=colors.dark_violet, bg=colors.black)
      elif 2.06 <= BOARD[x, y] <= 2.07 or 3.06 <= BOARD[x, y] <= 3.07:
      self._con.draw_char(x, y, '6', fg=colors.dark_sky, bg=colors.black)
      elif 2.07 <= BOARD[x, y] <= 2.08 or 3.07 <= BOARD[x, y] <= 3.08:
      self._con.draw_char(x, y, '7', fg=colors.dark_cyan, bg=colors.black)
      elif 2.08 <= BOARD[x, y] <= 2.09 or 3.08 <= BOARD[x, y] <= 3.09:
      self._con.draw_char(x, y, '8', fg=colors.dark_cyan, bg=colors.black)
      elif 2.09 <= BOARD[x, y] < 2.1 or 3.09 <= BOARD[x, y] <= 3.1:
      self._con.draw_char(x, y, '9', fg=colors.darkest_pink, bg=colors.black)
      else:
      self._con.draw_char(x, y, '#', fg=colors.darker_green, bg=colors.dark_green)


      self._root.blit(self._con, 0, 0, MAP_WIDTH, MAP_HEIGHT, 0, 0)
      tdl.flush()


      ##################################################################
      tdl.set_font(FONTSET, greyscale=True, altLayout=True)
      root = tdl.init(SCREEN_WIDTH, SCREEN_HEIGHT, title="TURTLES",
      fullscreen=False)
      tdl.setFPS(LIMIT_FPS)
      con = tdl.Console(MAP_HEIGHT, MAP_WIDTH)
      ##################################################################


      def count_turts():
      total = 0
      for y in range(MAP_HEIGHT - 1):
      for x in range(MAP_WIDTH - 1):
      cell = BOARD[x, y]
      if 2.0 <= cell <= 2.12 or 3.0 <= cell <= 3.12:
      total += 1

      print("There are %d total turtles" % (total))


      BOARD[50, 50] = 2.0

      turtlebrain = TurtleBrain(pattern='original')
      timeprocessor = TimeStep(.01)
      renderprocessor = RenderProcessor(con, root)

      con.clear()


      def handle_keys():

      user_input = tdl.event.key_wait()
      if user_input.key == 'ESCAPE':
      return 'exit'


      if user_input.key == 'ENTER':
      return 'go'

      if user_input.char == '2':
      return user_input.char

      if user_input.char == '3':
      return user_input.char


      if user_input.char == 'c':
      return 'clear'

      if user_input.char == 'p':
      return user_input.char

      if user_input.key == 'F11':
      return user_input.key



      renderprocessor.process()

      def add_turtle(turt):
      BOARD[randint(0, MAP_WIDTH - 1), randint(0, MAP_HEIGHT - 1)] = 2.0

      while not tdl.event.is_window_closed():
      player_input = handle_keys()
      if player_input == 'go':
      turtlebrain.process()
      timeprocessor.process()
      renderprocessor.process()

      elif player_input == 'exit':
      break

      elif player_input == 'F11':
      tdl.set_fullscreen(not tdl.get_fullscreen())
      pass

      elif player_input == '2':
      add_turtle(2)
      elif player_input == '3':
      add_turtle(3)

      elif player_input == 'p':
      count_turts()


      elif player_input == 'clear':
      BOARD = np.zeros( (MAP_WIDTH, MAP_HEIGHT) )

      renderprocessor.process()








      share|improve this question












      share|improve this question




      share|improve this question








      edited Jun 9 at 22:29









      Jamal♦

      30.1k11114225




      30.1k11114225









      asked Jun 9 at 19:41









      J-Sebastian-B

      312




      312




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          3
          down vote













          Here are few recommendations, in no particular order.



          PEP8



          You should consider formatting your code in accordance with pep8. This is important when sharing code, as the consistent style makes it much easier for other programmers to read your code.



          There are various tools available to assist in making the code pep8 compliant. I use the PyCharm IDE which will show pep8 violations right in the editor.



          Pylint



          pylint can be used to help find code errors and non-best practice constructs. Here again PyCharm (and other IDEs) can run these tools on your code and show the results directly in the editor.



          Try to simplify similar paths



          In this code:



          while self.pattern == 'original':
          if self.flag:
          self.move_twos()
          self.flag = (not self.flag)
          break
          else:
          self.move_threes()
          self.flag = (not self.flag)
          break


          Both if and else have a break, therefore the loop is unneeded. So it can be done more simply as:



          if self.flag:
          self.move_twos()
          else:
          self.move_threes()
          self.flag = not self.flag


          In addition, this loop:



          failed = True
          while True:
          dx = randint(-1, 1)
          dy = randint(-1, 1)
          new_x = x + dx
          new_y = y + dy
          if dx == 0 and dy == 0:
          continue
          else:
          failed = False
          break


          can be simplified as:



          while True:
          new_x = x + randint(-1, 1)
          new_y = y + randint(-1, 1)
          if x != new_x or y != newy:
          break


          Calculate relationships, and use dict lookups:



          Just about anytime you see a stacked if, in which the conditions and actions are basically the same, you should look to use a dict lookup instead.



          So something this:



          ....
          elif 2.0 <= BOARD[x, y] <= 2.01 or 3.0 <= BOARD[x, y] <= 3.01:
          self._con.draw_char(x, y, '0', fg=colors.dark_green, bg=colors.black)
          elif 2.01 <= BOARD[x, y] <= 2.02 or 3.01 <= BOARD[x, y] <= 3.02:
          self._con.draw_char(x, y, '1', fg=colors.dark_lime, bg=colors.black)
          elif 2.02 <= BOARD[x, y] <= 2.03 or 3.02 <= BOARD[x, y] <= 3.03:
          self._con.draw_char(x, y, '2', fg=colors.dark_red, bg=colors.black)
          elif 2.03 <= BOARD[x, y] <= 2.04 or 3.03 <= BOARD[x, y] <= 3.04:
          ....


          can likely be changed to something like (untested):



          actions = 
          0: dict(char='0', fg=colors.dark_green, bg=colors.black),
          1: dict(char='1', fg=colors.dark_lime, bg=colors.black),
          2: dict(char='2', fg=colors.dark_red, bg=colors.black),
          ....

          lookup = int((BOARD[x, y] - int(BOARD[x, y]) * 100)
          self._con.draw_char(x, y, **actions[lookup])


          This calculates a a lookup index into the actions dict and the gets the values for draw_char from there. The resulting construct will be much easier to read and modify.






          share|improve this answer





















          • Thank you! I knew there was room to simplify the loops and the if statements but the solutions went right over my head. Much appreciated. I'm pretty sure my nestedfor loops over a big board isn't the best way to do this, perhaps I can find a cleaner algorithm for the entire thing.
            – J-Sebastian-B
            Jun 11 at 5:54











          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196190%2fgame-of-life-inspired-ascii-program%23new-answer', 'question_page');

          );

          Post as a guest






























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          3
          down vote













          Here are few recommendations, in no particular order.



          PEP8



          You should consider formatting your code in accordance with pep8. This is important when sharing code, as the consistent style makes it much easier for other programmers to read your code.



          There are various tools available to assist in making the code pep8 compliant. I use the PyCharm IDE which will show pep8 violations right in the editor.



          Pylint



          pylint can be used to help find code errors and non-best practice constructs. Here again PyCharm (and other IDEs) can run these tools on your code and show the results directly in the editor.



          Try to simplify similar paths



          In this code:



          while self.pattern == 'original':
          if self.flag:
          self.move_twos()
          self.flag = (not self.flag)
          break
          else:
          self.move_threes()
          self.flag = (not self.flag)
          break


          Both if and else have a break, therefore the loop is unneeded. So it can be done more simply as:



          if self.flag:
          self.move_twos()
          else:
          self.move_threes()
          self.flag = not self.flag


          In addition, this loop:



          failed = True
          while True:
          dx = randint(-1, 1)
          dy = randint(-1, 1)
          new_x = x + dx
          new_y = y + dy
          if dx == 0 and dy == 0:
          continue
          else:
          failed = False
          break


          can be simplified as:



          while True:
          new_x = x + randint(-1, 1)
          new_y = y + randint(-1, 1)
          if x != new_x or y != newy:
          break


          Calculate relationships, and use dict lookups:



          Just about anytime you see a stacked if, in which the conditions and actions are basically the same, you should look to use a dict lookup instead.



          So something this:



          ....
          elif 2.0 <= BOARD[x, y] <= 2.01 or 3.0 <= BOARD[x, y] <= 3.01:
          self._con.draw_char(x, y, '0', fg=colors.dark_green, bg=colors.black)
          elif 2.01 <= BOARD[x, y] <= 2.02 or 3.01 <= BOARD[x, y] <= 3.02:
          self._con.draw_char(x, y, '1', fg=colors.dark_lime, bg=colors.black)
          elif 2.02 <= BOARD[x, y] <= 2.03 or 3.02 <= BOARD[x, y] <= 3.03:
          self._con.draw_char(x, y, '2', fg=colors.dark_red, bg=colors.black)
          elif 2.03 <= BOARD[x, y] <= 2.04 or 3.03 <= BOARD[x, y] <= 3.04:
          ....


          can likely be changed to something like (untested):



          actions = 
          0: dict(char='0', fg=colors.dark_green, bg=colors.black),
          1: dict(char='1', fg=colors.dark_lime, bg=colors.black),
          2: dict(char='2', fg=colors.dark_red, bg=colors.black),
          ....

          lookup = int((BOARD[x, y] - int(BOARD[x, y]) * 100)
          self._con.draw_char(x, y, **actions[lookup])


          This calculates a a lookup index into the actions dict and the gets the values for draw_char from there. The resulting construct will be much easier to read and modify.






          share|improve this answer





















          • Thank you! I knew there was room to simplify the loops and the if statements but the solutions went right over my head. Much appreciated. I'm pretty sure my nestedfor loops over a big board isn't the best way to do this, perhaps I can find a cleaner algorithm for the entire thing.
            – J-Sebastian-B
            Jun 11 at 5:54















          up vote
          3
          down vote













          Here are few recommendations, in no particular order.



          PEP8



          You should consider formatting your code in accordance with pep8. This is important when sharing code, as the consistent style makes it much easier for other programmers to read your code.



          There are various tools available to assist in making the code pep8 compliant. I use the PyCharm IDE which will show pep8 violations right in the editor.



          Pylint



          pylint can be used to help find code errors and non-best practice constructs. Here again PyCharm (and other IDEs) can run these tools on your code and show the results directly in the editor.



          Try to simplify similar paths



          In this code:



          while self.pattern == 'original':
          if self.flag:
          self.move_twos()
          self.flag = (not self.flag)
          break
          else:
          self.move_threes()
          self.flag = (not self.flag)
          break


          Both if and else have a break, therefore the loop is unneeded. So it can be done more simply as:



          if self.flag:
          self.move_twos()
          else:
          self.move_threes()
          self.flag = not self.flag


          In addition, this loop:



          failed = True
          while True:
          dx = randint(-1, 1)
          dy = randint(-1, 1)
          new_x = x + dx
          new_y = y + dy
          if dx == 0 and dy == 0:
          continue
          else:
          failed = False
          break


          can be simplified as:



          while True:
          new_x = x + randint(-1, 1)
          new_y = y + randint(-1, 1)
          if x != new_x or y != newy:
          break


          Calculate relationships, and use dict lookups:



          Just about anytime you see a stacked if, in which the conditions and actions are basically the same, you should look to use a dict lookup instead.



          So something this:



          ....
          elif 2.0 <= BOARD[x, y] <= 2.01 or 3.0 <= BOARD[x, y] <= 3.01:
          self._con.draw_char(x, y, '0', fg=colors.dark_green, bg=colors.black)
          elif 2.01 <= BOARD[x, y] <= 2.02 or 3.01 <= BOARD[x, y] <= 3.02:
          self._con.draw_char(x, y, '1', fg=colors.dark_lime, bg=colors.black)
          elif 2.02 <= BOARD[x, y] <= 2.03 or 3.02 <= BOARD[x, y] <= 3.03:
          self._con.draw_char(x, y, '2', fg=colors.dark_red, bg=colors.black)
          elif 2.03 <= BOARD[x, y] <= 2.04 or 3.03 <= BOARD[x, y] <= 3.04:
          ....


          can likely be changed to something like (untested):



          actions = 
          0: dict(char='0', fg=colors.dark_green, bg=colors.black),
          1: dict(char='1', fg=colors.dark_lime, bg=colors.black),
          2: dict(char='2', fg=colors.dark_red, bg=colors.black),
          ....

          lookup = int((BOARD[x, y] - int(BOARD[x, y]) * 100)
          self._con.draw_char(x, y, **actions[lookup])


          This calculates a a lookup index into the actions dict and the gets the values for draw_char from there. The resulting construct will be much easier to read and modify.






          share|improve this answer





















          • Thank you! I knew there was room to simplify the loops and the if statements but the solutions went right over my head. Much appreciated. I'm pretty sure my nestedfor loops over a big board isn't the best way to do this, perhaps I can find a cleaner algorithm for the entire thing.
            – J-Sebastian-B
            Jun 11 at 5:54













          up vote
          3
          down vote










          up vote
          3
          down vote









          Here are few recommendations, in no particular order.



          PEP8



          You should consider formatting your code in accordance with pep8. This is important when sharing code, as the consistent style makes it much easier for other programmers to read your code.



          There are various tools available to assist in making the code pep8 compliant. I use the PyCharm IDE which will show pep8 violations right in the editor.



          Pylint



          pylint can be used to help find code errors and non-best practice constructs. Here again PyCharm (and other IDEs) can run these tools on your code and show the results directly in the editor.



          Try to simplify similar paths



          In this code:



          while self.pattern == 'original':
          if self.flag:
          self.move_twos()
          self.flag = (not self.flag)
          break
          else:
          self.move_threes()
          self.flag = (not self.flag)
          break


          Both if and else have a break, therefore the loop is unneeded. So it can be done more simply as:



          if self.flag:
          self.move_twos()
          else:
          self.move_threes()
          self.flag = not self.flag


          In addition, this loop:



          failed = True
          while True:
          dx = randint(-1, 1)
          dy = randint(-1, 1)
          new_x = x + dx
          new_y = y + dy
          if dx == 0 and dy == 0:
          continue
          else:
          failed = False
          break


          can be simplified as:



          while True:
          new_x = x + randint(-1, 1)
          new_y = y + randint(-1, 1)
          if x != new_x or y != newy:
          break


          Calculate relationships, and use dict lookups:



          Just about anytime you see a stacked if, in which the conditions and actions are basically the same, you should look to use a dict lookup instead.



          So something this:



          ....
          elif 2.0 <= BOARD[x, y] <= 2.01 or 3.0 <= BOARD[x, y] <= 3.01:
          self._con.draw_char(x, y, '0', fg=colors.dark_green, bg=colors.black)
          elif 2.01 <= BOARD[x, y] <= 2.02 or 3.01 <= BOARD[x, y] <= 3.02:
          self._con.draw_char(x, y, '1', fg=colors.dark_lime, bg=colors.black)
          elif 2.02 <= BOARD[x, y] <= 2.03 or 3.02 <= BOARD[x, y] <= 3.03:
          self._con.draw_char(x, y, '2', fg=colors.dark_red, bg=colors.black)
          elif 2.03 <= BOARD[x, y] <= 2.04 or 3.03 <= BOARD[x, y] <= 3.04:
          ....


          can likely be changed to something like (untested):



          actions = 
          0: dict(char='0', fg=colors.dark_green, bg=colors.black),
          1: dict(char='1', fg=colors.dark_lime, bg=colors.black),
          2: dict(char='2', fg=colors.dark_red, bg=colors.black),
          ....

          lookup = int((BOARD[x, y] - int(BOARD[x, y]) * 100)
          self._con.draw_char(x, y, **actions[lookup])


          This calculates a a lookup index into the actions dict and the gets the values for draw_char from there. The resulting construct will be much easier to read and modify.






          share|improve this answer













          Here are few recommendations, in no particular order.



          PEP8



          You should consider formatting your code in accordance with pep8. This is important when sharing code, as the consistent style makes it much easier for other programmers to read your code.



          There are various tools available to assist in making the code pep8 compliant. I use the PyCharm IDE which will show pep8 violations right in the editor.



          Pylint



          pylint can be used to help find code errors and non-best practice constructs. Here again PyCharm (and other IDEs) can run these tools on your code and show the results directly in the editor.



          Try to simplify similar paths



          In this code:



          while self.pattern == 'original':
          if self.flag:
          self.move_twos()
          self.flag = (not self.flag)
          break
          else:
          self.move_threes()
          self.flag = (not self.flag)
          break


          Both if and else have a break, therefore the loop is unneeded. So it can be done more simply as:



          if self.flag:
          self.move_twos()
          else:
          self.move_threes()
          self.flag = not self.flag


          In addition, this loop:



          failed = True
          while True:
          dx = randint(-1, 1)
          dy = randint(-1, 1)
          new_x = x + dx
          new_y = y + dy
          if dx == 0 and dy == 0:
          continue
          else:
          failed = False
          break


          can be simplified as:



          while True:
          new_x = x + randint(-1, 1)
          new_y = y + randint(-1, 1)
          if x != new_x or y != newy:
          break


          Calculate relationships, and use dict lookups:



          Just about anytime you see a stacked if, in which the conditions and actions are basically the same, you should look to use a dict lookup instead.



          So something this:



          ....
          elif 2.0 <= BOARD[x, y] <= 2.01 or 3.0 <= BOARD[x, y] <= 3.01:
          self._con.draw_char(x, y, '0', fg=colors.dark_green, bg=colors.black)
          elif 2.01 <= BOARD[x, y] <= 2.02 or 3.01 <= BOARD[x, y] <= 3.02:
          self._con.draw_char(x, y, '1', fg=colors.dark_lime, bg=colors.black)
          elif 2.02 <= BOARD[x, y] <= 2.03 or 3.02 <= BOARD[x, y] <= 3.03:
          self._con.draw_char(x, y, '2', fg=colors.dark_red, bg=colors.black)
          elif 2.03 <= BOARD[x, y] <= 2.04 or 3.03 <= BOARD[x, y] <= 3.04:
          ....


          can likely be changed to something like (untested):



          actions = 
          0: dict(char='0', fg=colors.dark_green, bg=colors.black),
          1: dict(char='1', fg=colors.dark_lime, bg=colors.black),
          2: dict(char='2', fg=colors.dark_red, bg=colors.black),
          ....

          lookup = int((BOARD[x, y] - int(BOARD[x, y]) * 100)
          self._con.draw_char(x, y, **actions[lookup])


          This calculates a a lookup index into the actions dict and the gets the values for draw_char from there. The resulting construct will be much easier to read and modify.







          share|improve this answer













          share|improve this answer



          share|improve this answer











          answered Jun 11 at 0:40









          Stephen Rauch

          3,49951430




          3,49951430











          • Thank you! I knew there was room to simplify the loops and the if statements but the solutions went right over my head. Much appreciated. I'm pretty sure my nestedfor loops over a big board isn't the best way to do this, perhaps I can find a cleaner algorithm for the entire thing.
            – J-Sebastian-B
            Jun 11 at 5:54

















          • Thank you! I knew there was room to simplify the loops and the if statements but the solutions went right over my head. Much appreciated. I'm pretty sure my nestedfor loops over a big board isn't the best way to do this, perhaps I can find a cleaner algorithm for the entire thing.
            – J-Sebastian-B
            Jun 11 at 5:54
















          Thank you! I knew there was room to simplify the loops and the if statements but the solutions went right over my head. Much appreciated. I'm pretty sure my nestedfor loops over a big board isn't the best way to do this, perhaps I can find a cleaner algorithm for the entire thing.
          – J-Sebastian-B
          Jun 11 at 5:54





          Thank you! I knew there was room to simplify the loops and the if statements but the solutions went right over my head. Much appreciated. I'm pretty sure my nestedfor loops over a big board isn't the best way to do this, perhaps I can find a cleaner algorithm for the entire thing.
          – J-Sebastian-B
          Jun 11 at 5:54













           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f196190%2fgame-of-life-inspired-ascii-program%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Python Lists

          Aion

          JavaScript Array Iteration Methods