#!/usr/bin/env python
# life.py -- A curses-based version of Conway's Game of Life.
# Contributed by A.M. Kuchling <amk1@bigfoot.com>
#
# An empty board will be displayed, and the following commands are available:
#  E : Erase the board
#  R : Fill the board randomly
#  S : Step for a single generation
#  C : Update continuously until a key is struck
#  Q : Quit
#  Cursor keys :  Move the cursor around the board
#  Space or Enter : Toggle the contents of the cursor's position
#
# TODO : 
#   Support the mouse
#   Use colour if available
#   Make board updates faster
#

class LifeBoard:
    """Encapsulates a Life board

    Attributes:
    X,Y : horizontal and vertical size of the board
    state : dictionary mapping (x,y) to 0 or 1
    
    Methods:
    display(update_board) -- If update_board is true, compute the 
                             next generation.  Then display the state
			     of the board and refresh the screen.
    erase() -- clear the entire board
    makeRandom() -- fill the board randomly
    set(y,x) -- set the given cell to Live; doesn't refresh the screen
    toggle(y,x) -- change the given cell from live to dead, or vice
                   versa, and refresh the screen display

    """
    def __init__(self, scr, char=ord('*')):
	"""Create a new LifeBoard instance.

	scr -- curses screen object to use for display
	char -- character used to render live cells (default: '*')
	"""
	self.state={} ; self.scr=scr
	Y, X = self.scr.getmaxyx()
	self.X, self.Y = X-2, Y-2-1
	self.char = char
	self.scr.clear()	

	# Draw a border around the board
	border_line='+'+(self.X*'-')+'+'
	self.scr.addstr(0, 0, border_line)
	self.scr.addstr(self.Y+1,0, border_line)
	for y in range(0, self.Y): 
	    self.scr.addstr(1+y, 0, '|') 
	    self.scr.addstr(1+y, self.X+1, '|')
	self.scr.refresh()

    def set(self, y, x): 
	"""Set a cell to the live state"""
	if x<0 or self.X<=x or y<0 or self.Y<=y:
	    raise ValueError, "Coordinates out of range %i,%i"% (y,x)
	self.state[x,y] = 1

    def toggle(self, y, x): 
	"""Toggle a cell's state between live and dead"""
	if x<0 or self.X<=x or y<0 or self.Y<=y:
	    raise ValueError, "Coordinates out of range %i,%i"% (y,x)
	if self.state.has_key( (x,y) ): 
	    del self.state[x,y]
	    self.scr.addch(y+1, x+1, ' ')
	else:
	    self.state[x,y]=1
	    self.scr.addch(y+1, x+1, self.char)
	self.scr.refresh()

    def erase(self):
	"""Clear the entire board and update the board display"""
	self.state={}
	self.display(update_board=0)

    def display(self, update_board=1):
	"""Display the whole board, optionally computing one generation"""
	M,N = self.X, self.Y 
	if not update_board:
	    for i in range(0, M):
		for j in range(0, N):
			if self.state.has_key( (i,j) ): 
			    self.scr.addch(j+1, i+1, self.char)
			else:
			    self.scr.addch(j+1, i+1, ' ')
	    self.scr.refresh()
	    return

	d={} ; self.boring=1
	for i in range(0, M):
	    L=range( max(0, i-1), min(M, i+2) )
	    for j in range(0, N):
		s=0
		live=self.state.has_key( (i,j) )
		for k in range( max(0, j-1), min(N, j+2) ):
		    for l in L:
			if self.state.has_key( (l,k) ):
			    s=s+1
		s=s-live
		if s==3: 
		    # Birth
		    d[i,j]=1 
		    self.scr.addch(j+1, i+1, self.char)
		    if not live: self.boring=0  
		elif s==2 and live: d[i,j]=1       # Survival
		elif live: 
		    # Death
		    self.scr.addch(j+1, i+1, ' ')
		    self.boring=0
	self.state=d
	self.scr.refresh()

    def makeRandom(self):
	"Fill the board with a random pattern"
	import whrandom
	self.state={}
	for i in range(0, self.X): 
            for j in range(0, self.Y):
		if whrandom.random()*10>5.0: self.set(j,i)


def erase_menu(stdscr, menu_y):
    "Clear the space where the menu resides"
    stdscr.move(menu_y, 0) ; stdscr.clrtoeol()
    stdscr.move(menu_y+1, 0) ; stdscr.clrtoeol()

def display_menu(stdscr, menu_y):
    "Display the menu of possible keystroke commands"
    erase_menu(stdscr, menu_y)
    stdscr.addstr(menu_y, 4,
                  'Use the cursor keys to move, and space or Enter to toggle a cell.')
    stdscr.addstr(menu_y+1, 4,
                  'E)rase the board, R)andom fill, S)tep once or C)ontinuously, Q)uit')

def main(stdscr):
    import string, curses

    # Clear the screen and display the menu of keys
    stdscr.clear()
    stdscr_y, stdscr_x = stdscr.getmaxyx()
    menu_y=(stdscr_y-3)-1
    display_menu(stdscr, menu_y)

    # Allocate a subwindow for the Life board and create the board object
    subwin=stdscr.subwin(stdscr_y-3, stdscr_x, 0, 0) 
    board=LifeBoard(subwin, char=ord('*'))
    board.display(update_board=0)

    # xpos, ypos are the cursor's position
    xpos, ypos = board.X/2, board.Y/2

    # Main loop:
    while (1):
	stdscr.move(1+ypos, 1+xpos)     # Move the cursor
	c=stdscr.getch()		# Get a keystroke
	if 0<c<256:
	    c=chr(c)
	    if c in ' \n':
		board.toggle(ypos, xpos)
	    elif c in 'Cc':
		erase_menu(stdscr, menu_y)
		stdscr.addstr(menu_y, 6, ' Hit any key to stop continuously '
			      'updating the screen.')
		stdscr.refresh()
		# Activate nodelay mode; getch() will return -1
		# if no keystroke is available, instead of waiting.
		stdscr.nodelay(1)   
		while (1):
		    c=stdscr.getch()
		    if c!=-1: break
		    stdscr.addstr(0,0, '/'); stdscr.refresh()
		    board.display()
		    stdscr.addstr(0,0, '+'); stdscr.refresh()

		stdscr.nodelay(0)	# Disable nodelay mode
		display_menu(stdscr, menu_y)

	    elif c in 'Ee': board.erase()
	    elif c in 'Qq': break
	    elif c in 'Rr': 
		board.makeRandom()
		board.display(update_board=0)
	    elif c in 'Ss':
		board.display()
	    else: pass                  # Ignore incorrect keys
	elif c==curses.KEY_UP and ypos>0: 	     ypos=ypos-1
	elif c==curses.KEY_DOWN and ypos<board.Y-1:  ypos=ypos+1
	elif c==curses.KEY_LEFT and xpos>0:          xpos=xpos-1
	elif c==curses.KEY_RIGHT and xpos<board.X-1: xpos=xpos+1
        else: pass			# Ignore incorrect keys

if __name__=='__main__':
    import curses, traceback
    try:
	# Initialize curses
	stdscr=curses.initscr()
	# Turn off echoing of keys, and enter cbreak mode,
	# where no buffering is performed on keyboard input
	curses.noecho() ; curses.cbreak()

	# In keypad mode, escape sequences for special keys
	# (like the cursor keys) will be interpreted and
	# a special value like curses.KEY_LEFT will be returned
	stdscr.keypad(1)
	main(stdscr)			# Enter the main loop
	# Set everything back to normal
	stdscr.keypad(0)
	curses.echo() ; curses.nocbreak()
	curses.endwin()			# Terminate curses
    except:
        # In the event of an error, restore the terminal
	# to a sane state.
	stdscr.keypad(0)
	curses.echo() ; curses.nocbreak()
	curses.endwin()
	traceback.print_exc()		# Print the exception

