#!/usr/bin/env python
# life.py -- A curses-based version of Conway's Game of Life.
# Contributed by AMK
#
# 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
#

import random, string, traceback
import curses

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=False)

    def display(self, update_board=True):
        """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 += 1
                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"
        self.state = {}
        for i in range(0, self.X):
            for j in range(0, self.Y):
                if random.random() > 0.5:
                    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 keyloop(stdscr):
    # 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=False)

    # 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=False)
            elif c in 'Ss':
                board.display()
            else: pass                  # Ignore incorrect keys
        elif c == curses.KEY_UP and ypos>0:            ypos -= 1
        elif c == curses.KEY_DOWN and ypos<board.Y-1:  ypos += 1
        elif c == curses.KEY_LEFT and xpos>0:          xpos -= 1
        elif c == curses.KEY_RIGHT and xpos<board.X-1: xpos += 1
        else:
            # Ignore incorrect keys
            pass


def main(stdscr):
    keyloop(stdscr)                    # Enter the main loop


if __name__ == '__main__':
    curses.wrapper(main)
