Exemple #1
0
def test2():
    print('----World Tests----')

    w1 = World(3, 4)
    print(w1)
    assert w1.__str__() == '....\n....\n....\n'
    w1.set_cell(0, 0, True)
    w1.set_cell(0, 3, True)
    w1.set_cell(2, 0, True)
    w1.set_cell(2, 3, True)
    print(w1)
    assert w1.__str__() == 'X..X\n....\nX..X\n'
    assert w1._World__rows == 3
    assert w1._World__columns == 4
Exemple #2
0
def test4():

    print('----Next Generation Tests----')
    w1 = World(3, 4)
    print(w1)
    w1.set_cell(0, 1, True)
    w1.set_cell(1, 1, True)
    w1.set_cell(2, 1, True)
    print(w1)
    assert w1.__str__() == '.X..\n.X..\n.X..\n'
    w1.next_generation()
    print(w1)
    assert w1.__str__() == '....\nXXX.\n....\n'
    w1.next_generation()
    print(w1)
    assert w1.__str__() == '.X..\n.X..\n.X..\n'
    w1.next_generation()
    print(w1)
    assert w1.__str__() == '....\nXXX.\n....\n'
Exemple #3
0
class Life(object):
    def __init__(self):
        self.__world = World(34, 69)
        self.__fillrate = 25
        self.__delay = 0.5
        self.__generation = 0
        self.random()
        self.__lastWorld = ''
        self.__secondWorld = ''

    def main(self):
        """
        Main event loop for store.
        :return: None
        """
        command = 'help'
        parameter = None
        while command != 'quit':
            if command == 'help':
                self.help('help.txt', 'Press <return> to continue.')
                print(self.__world, end="")
                print(self.status() + '\n' + self.menu(), end=' ')
            elif command == 'next generation':
                self.next_generation(parameter)
            elif command == 'run simulation':
                self.run_simulation(parameter)
            elif command == 'skip generations':
                self.skip_generations(parameter)
            elif command == 'random world':
                self.random()
            elif command == 'change fillrate':
                self.change_fillrate(parameter)
            elif command == 'change delay':
                self.change_delay(parameter)
            elif command == 'change size':
                self.change_size(parameter)
            elif command == 'change display':
                self.change_display(parameter)
            elif command == 'customize-world':
                print(
                    '[F]illrate   [D]elay   [S]ize   d[I]splay  sa[V]e to disk    load [W]orld   c[u]stom display     li[B]rary'
                )
            elif command == 'save world':
                self.save(parameter, './worlds/')
            elif command == 'open world':
                self.open(parameter, './worlds/')
            elif command == 'custom-cells':
                self.user_display()
                self.change_display(parameter)
            elif command == 'geometry':
                self.set_geometry()
            elif command == 'library':
                self.from_library(parameter, './library/')
            elif command == 'change rules':
                self.change_rule(parameter)

            command, parameter = self.get_command()
        print('goodbye')

    def menu(self):
        """
        returns a string containing the menu.
        :return: Menu string
        """
        return '[N]ext  [R]un   s[K]ip   n[E]w   [H]elp   [Q]uit   [C]ustom     [G]eometry   Ch[A]nge Rules '

    def get_command(self):
        """
        Get a valid command from the user.
        :return: command, parameter
        """
        commands = {
            'n': 'next generation',
            'r': 'run simulation',
            'k': 'skip generations',
            'e': 'random world',
            'f': 'change fillrate',
            'd': 'change delay',
            's': 'change size',
            'i': 'change display',
            'h': 'help',
            '?': 'help',
            'q': 'quit',
            'c': 'customize-world',
            'v': 'save world',
            'w': 'open world',
            'u': 'custom-cells',
            'g': 'geometry',
            'b': 'library',
            'a': 'change rules'
        }

        validCommands = commands.keys()

        userInput = '&'
        parameter = None
        while userInput[0].lower() not in validCommands:
            userInput = input()
            if userInput == '':
                userInput = 'n'
                parameter = 1
        command = commands[userInput[0].lower()]
        if len(userInput) > 1:
            parameter = userInput[1:].strip()
        return command, parameter

    def status(self):
        """
        Returns a string representing the status of the world.
        :return: string
        """
        geometry = self.__world.get_currentGeo()
        #ruleSet = Rule.__current
        rows = self.__world.get_rows()
        columns = self.__world.get_columns()
        percentAlive = (self.__world.get_living_cell_count() /
                        (rows * columns)) * 100
        speed = self.__delay
        generation = self.__generation
        string = 'Status:   '
        string += f'size:[{rows}x{columns}]      '
        string += f'alive: {percentAlive:0.0f}%      '
        string += f'speed: 1 gen every {speed} seconds     '
        string += f'generation: {generation}    '
        string += f'geometry: {geometry}    '
        #string += f'ruleSet: {ruleSet}    '
        return string

    def help(self, filename, prompt=None):
        """
        Displays instructions.
        :param filename: The string of helping instructions.
        :param prompt:
        :return: None
        """
        with open(filename, 'r') as file:
            help = file.read()
        print(help, end='')
        if prompt:
            input('\n' + prompt)

    def next_generation(self, parameter):
        """
        Displays the next generation of the world.
        :param parameter:
        :return: None
        """
        self.__world.next_generation()
        self.__generation += 1
        print(self.__world, end='')
        print()
        print('You have now gone 1 gen forward.')
        print()
        print(self.status() + '\n' + self.menu(), end=' ')

    def run_simulation(self, parameter):
        """
        Displays the next generation of the world.
        :param parameter:
        :return: None
        """
        if toolbox.is_integer(parameter) and int(parameter) > 0:
            generations = int(parameter)
        else:
            prompt = 'How many generations would you like to simulate?'
            generations = toolbox.get_integer_between(1, 10000, prompt)
        for generation in range(generations):
            self.__world.next_generation()
            if self.__world.is_stable() == True:
                "It is stable now."
                break
            else:
                pass

            #self.__world.__lastWorld = self.__world.__secondWorld
            string = self.__world.__str__()
            string += self.status()
            string += f'left: {generations - generation}'
            print(string)
            time.sleep(self.__delay)

        print()
        print(f'You have now been through {generations} generations. ')
        print()
        print(self.menu(), end=' ')
        self.__generation += generations

    def skip_generations(self, parameter):
        """
        Displays the next generation of the world.
        :param parameter:
        :return: None
        """
        if toolbox.is_integer(parameter) and int(parameter) > 0:
            generations = int(parameter)
        else:
            prompt = 'How many generations would you like to skip?'
            generations = toolbox.get_integer_between(1, 10000, prompt)
        print(f'Skipping {generations} generations.', end='')
        for generation in range(generations):
            self.__world.next_generation(self.__world)
            if self.__world.is_stable() == True:
                "It is stable now."
                break
            else:
                pass
            if generation % 100 == 0:
                print('.', end='')
        print(' done!')
        self.__generation += generations
        time.sleep(2)
        string = self.__world.__str__()
        string += self.status()
        print(string)
        print()
        print(f'You now have skipped forward {generations} generations.')
        print()
        print(self.menu(), end=' ')

    def change_fillrate(self, parameter):
        """
        Change the fillrate for the simulation.
        :param parameter:
        :return: None
        """
        if toolbox.is_number(parameter) and 0 <= float(parameter) <= 100:
            fillrate = float(parameter)
        else:
            prompt = 'What percent of cells should be alive?'
            fillrate = toolbox.get_integer_between(0, 100, prompt)
        self.__fillrate = fillrate
        self.random()
        print(f'The percent of alive cells is now {fillrate} percent.')

    def change_delay(self, parameter):
        """
        Change the delay betwen generations of the simulation.
        :param parameter:
        :return: None
        """
        if toolbox.is_number(parameter):
            delay = float(parameter)
        else:
            prompt = 'Seconds of delay between generations?'
            delay = toolbox.get_number(prompt)
        self.__delay = delay
        print(
            f'Your speed of running the simulation is now 1 gen every {delay} seconds.'
        )

    def change_display(self, parameter):
        """
        Change the live and dead characters for the cells.
        :param parameter:
        :return: None
        """
        if toolbox.is_integer(parameter) and \
                1 <= int(parameter) <= len(Cell.displaySets.keys()):
            setNumber = int(parameter)
        else:
            print('**************************************')
            for number, set in enumerate(Cell.displaySets):
                liveChar = Cell.displaySets[set]['liveChar']
                deadChar = Cell.displaySets[set]['deadChar']
                print(
                    f'{number + 1}: living cells: {liveChar} dead cells: {deadChar}'
                )
            print('**************************************')
            prompt = 'What character set would you like to use?'
            setNumber = toolbox.get_integer_between(1, number + 1, prompt)
        setString = list(Cell.displaySets.keys())[setNumber - 1]
        Cell.set_display(setString)
        print(self.__world, end='')
        print()
        print(
            f'Your living cell is now {liveChar} and a dead cell is {deadChar}.'
        )
        print()
        print(self.status() + '\n' + self.menu(), end=' ')

    def user_display(self):
        living = toolbox.get_string(
            'What would you like your living cell to be?')
        dead = toolbox.get_string('What would you like your dead cell to be?')
        Cell.set_display_user_values(living, dead)
        print()
        print(
            f"You now have a choice of a '{living}' as a living cell and a dead cell as '{dead}'."
        )
        print()

    def random(self):
        """
        Create a random world
        :return: None
        """
        self.__world.randomize(self.__fillrate)
        print(self.__world, end='')
        print()
        print(' You just created a brand new random world.')
        print()
        self.__generation = 0
        print(self.status() + '\n' + self.menu(), end=' ')

    def change_size(self, parameter):
        """
        changes the size of the current grid world.
        :param parameter:
        :return: None
        """
        if parameter:
            rows, columns = parameter.split('x', 2)
            if toolbox.is_integer(rows) and toolbox.is_integer(columns):
                rows = int(rows)
                columns = int(columns)
        else:
            prompt = 'How many rows of cells?'
            rows = toolbox.get_integer_between(1, 40, prompt)
            prompt = 'How many cells in each row?'
            columns = toolbox.get_integer_between(1, 120, prompt)
        self.__world = World(rows, columns)
        self.random()
        print(self.__world, end='')
        self.__generation = 0
        print()
        print(f'Your world size is now {rows} by {columns}.')
        print()
        print(self.status() + '\n' + self.menu(), end=' ')

    def save(self, filename, myPath='./'):
        """
        Save the current generation of the current world as a text file.
        :param filename: name of the file, may be None at this point.
        :param myPath: Where the file should be saved.
        :return: None
        """
        replace = False
        Cell.set_display('basic')
        if filename == None:
            filename = toolbox.get_string(
                'What do you want to call the file? ')

        #
        # Make sure the file has the correct file extension.
        #
        if filename[-5:] != '.life':
            filename = filename + '.life'
        allFiles = os.listdir(myPath)

        if filename in allFiles:
            replace = toolbox.get_boolean(
                'There is already a file with this name. Would like to replace it?'
            )

        if replace == True:

            #
            # if the path doesn't already exist, create it.
            #
            if not os.path.isdir(myPath):
                os.mkdir(myPath)

            #
            # Add on the correct path for saving files if the user didn't
            # include it in the filename.
            #
            if filename[0:len(myPath)] != myPath:
                filename = myPath + filename
            self.__world.save(filename)
            print()
            print('You now saved this world.')
            print()
        else:
            print("Okay I won't save it.")
            print(self.__world, end='')
        print()
        print(self.status() + '\n' + self.menu(), end=' ')

    def open(self, filename, myPath='./'):
        """
        open a text file and use it to populate a new world.
        :param filename: name of the file, may be None at this point.
        :param myPath: Where the file is located.
        :return: None
        """
        Cell.set_display('basic')
        if filename == None:
            filename = toolbox.get_string('Which file do you want to open?')
        #
        # Check for and add the correct file extension.
        #
        if filename[-5:] != '.life':
            filename = filename + '.life'
        allFiles = os.listdir(myPath)
        if filename not in allFiles:
            print('404: File not found...')
            for filenames in allFiles:
                print(filenames)
            print('Try one of these next time.')
            print()
        else:
            #
            # Add on the correct path for saving files if the user didn't
            # include it in the filename.
            #
            if filename[0:len(myPath)] != myPath:
                filename = myPath + filename
            self.__world = World.from_file(filename)
            print(self.__world, end='')
            print()
            print(f'You now opened {filename} world.')
            print()
        print(self.status() + '\n' + self.menu(), end=' ')

    def set_geometry(self):
        userGeo = toolbox.get_integer_between(
            1, 2, """
        Choose 1 or 2:
        1. Basic Geometry 
        2. Donut Geometry""")
        self.__world.set_geometry(userGeo)
        print(self.__world, end='')
        print(self.status() + '\n' + self.menu(), end=' ')

    def from_library(self, filename, myPath='./'):
        Cell.set_display('basic')
        files = []
        number = 1
        print('**************************************')
        for file in os.listdir(myPath):
            print(f'{number}: {file}')
            files.append(file)
            number += 1
        print('**************************************')
        prompt = 'Which file would you like to open? '
        fileNumber = toolbox.get_integer_between(1, number - 1, prompt)
        filename = files[fileNumber - 1]
        print(filename)
        #
        # Check for and add the correct file extension.
        #
        if filename[-5:] != '.life':
            filename = filename + '.life'
        allFiles = os.listdir(myPath)
        if filename not in allFiles:
            print('404: File not found...')
            for filenames in allFiles:
                print(filenames)
            print('Try one of these next time.')
            print()
        else:
            #
            # Add on the correct path for saving files if the user didn't
            # include it in the filename.
            #
            if filename[0:len(myPath)] != myPath:
                filename = myPath + filename
            self.__world = World.from_file(filename)
            print(self.__world, end='')
            print()
            print(f'You now opened {filename} world.')
            print()
        print(self.status() + '\n' + self.menu(), end=' ')

    def change_rule(self, parameter):
        """
        Change the number of neighbors a cell needs to live or die.
        :param parameter:
        :return: None
        """
        if toolbox.is_integer(parameter) and \
                1 <= int(parameter) <= len(Rule.ruleSets.keys()):
            setNumber = int(parameter)
        else:
            print('**************************************')
            for number, set in enumerate(Rule.ruleSets):
                neighbor1 = Rule.ruleSets[set]['neighbor1']
                neighbor2 = Rule.ruleSets[set]['neighbor2']
                neighbor3 = Rule.ruleSets[set]['neighbor3']
                print(
                    f'{number + 1}: neighbor1: {neighbor1} neighbor2: {neighbor2} neighbor3: {neighbor3}'
                )
            print('**************************************')
            prompt = 'What rule set would you like to use?'
            setNumber = toolbox.get_integer_between(1, number + 1, prompt)
        setString = list(Rule.ruleSets.keys())[setNumber - 1]
        Rule.set_rule(setString)
        print(self.__world, end='')
        print()
        print(
            f'Your rule set is now neighbor1:{neighbor1}, neighbor2:{neighbor2}, neighbor3:{neighbor3}.'
        )
        print()
        print(self.status() + '\n' + self.menu(), end=' ')
Exemple #4
0
class Life(object):
    def __init__(self):
        self.__world = World(34, 66)
        self.__fillrate = 25
        self.__delay = 0.5
        self.random()

    def main(self):
        """Main event loop for store."""
        command = 'help'
        parameter = None
        while command != 'quit':
            if command == 'help':
                self.help('help.txt', 'Press <return> to continue.')
                print(self.__world, end="")
                print(self.status() + '\n' + self.menu(), end=' ')
            elif command == 'next generation':
                self.next_generation(parameter)
            elif command == 'run simulation':
                self.run_simulation(parameter)
            elif command == 'skip generations':
                self.skip_generations(parameter)
            elif command == 'random world':
                self.random()
            elif command == 'change fillrate':
                self.change_fillrate(parameter)
            elif command == 'change delay':
                self.change_delay(parameter)
            elif command == 'change size':
                self.change_size(parameter)
            elif command == 'change display':
                self.change_display(parameter)
            elif command == 'long l world':
                self.long_l_world()
            elif command == 'acorn world':
                self.acorn_world()
            command, parameter = self.get_command()
        print('goodbye')

    def menu(self):
        """returns a string containing the menu."""
        return '[N]ext  [R]un   s[K]ip   n[E]w   [F]illrate   [D]elay   [S]ize   d[I]splay   [L]ong l   [A]corn   [H]elp   [Q]uit'

    def get_command(self):
        """Get a valid command from the user."""
        commands = {
            'n': 'next generation',
            'r': 'run simulation',
            'k': 'skip generations',
            'e': 'random world',
            'f': 'change fillrate',
            'd': 'change delay',
            's': 'change size',
            'i': 'change display',
            'l': 'long l world',
            'a': 'acorn world',
            'h': 'help',
            '?': 'help',
            'q': 'quit'
        }

        validCommands = commands.keys()

        userInput = '&'
        parameter = None
        while userInput[0].lower() not in validCommands:
            userInput = input()
            if userInput == '':
                userInput = 'n'
                parameter = 1
        command = commands[userInput[0].lower()]
        if len(userInput) > 1:
            parameter = userInput[1:].strip()
        return command, parameter

    def status(self):
        """Returns a string representing the status of the world."""
        rows = self.__world.get_rows()
        columns = self.__world.get_columns()
        percentAlive = (self.__world.get_living_cell_count() /
                        (rows * columns)) * 100
        string = 'Status:   '
        string += f'size:[{rows}x{columns}]   '
        string += f'alive: {percentAlive:0.0f}%   '
        return string

    def help(self, filename, prompt=None):
        """Displays instructions."""
        with open(filename, 'r') as file:
            help = file.read()
        print(help, end='')
        if prompt:
            input('\n' + prompt)

    def next_generation(self, parameter):
        """Displays the next generation of the world"""
        self.__world.next_generation()
        print(self.__world, end='')
        print(self.status() + '\n' + self.menu(), end=' ')

    def run_simulation(self, parameter):
        """Displays the next generation of the world"""
        if toolbox.is_integer(parameter) and int(parameter) > 0:
            generations = int(parameter)
        else:
            prompt = 'How many generations would you like to simulate?'
            generations = toolbox.get_integer_between(1, 10000, prompt)
        for generation in range(generations):
            self.__world.next_generation()
            string = self.__world.__str__()
            string += self.status()
            string += f'left: {generations - generation}'
            print(string)
            time.sleep(self.__delay)
        print(self.menu(), end=' ')

    def skip_generations(self, parameter):
        """Displays the next generation of the world"""
        if toolbox.is_integer(parameter) and int(parameter) > 0:
            generations = int(parameter)
        else:
            prompt = 'How many generations would you like to skip?'
            generations = toolbox.get_integer_between(1, 10000, prompt)
        print(f'Skipping {generations} generations.', end='')
        for generation in range(generations):
            self.__world.next_generation()
            if generation % 100 == 0:
                print('.', end='')
        print(' done!')
        time.sleep(2)
        string = self.__world.__str__()
        string += self.status()
        print(string)
        print(self.menu(), end=' ')

    def change_fillrate(self, parameter):
        """Change the fillrate for the simulation."""
        if toolbox.is_number(parameter) and 0 <= float(parameter) <= 100:
            fillrate = float(parameter)
        else:
            prompt = 'What percent of cells should be alive?'
            fillrate = toolbox.get_integer_between(0, 100, prompt)
        self.__fillrate = fillrate
        self.random()

    def change_delay(self, parameter):
        """Change the delay betwen generations of the simulation."""
        if toolbox.is_number(parameter):
            delay = float(parameter)
        else:
            prompt = 'Seconds of delay between generations?'
            delay = toolbox.get_number(prompt)
        self.__delay = delay

    def change_display(self, parameter):
        """Change the live and dead characters for the cells."""
        if toolbox.is_integer(parameter) and \
           1 <= int(parameter) <= len(Cell.displaySets.keys()):
            setNumber = int(parameter)
        else:
            print('**************************************')
            for number, set in enumerate(Cell.displaySets):
                liveChar = Cell.displaySets[set]['liveChar']
                deadChar = Cell.displaySets[set]['deadChar']
                print(
                    f'{number+1}: living cells: {liveChar} dead cells: {deadChar}'
                )
            print('**************************************')
            prompt = 'What character set would you like to use?'
            setNumber = toolbox.get_integer_between(1, number + 1, prompt)
        setString = list(Cell.displaySets.keys())[setNumber - 1]
        Cell.set_display(setString)
        print(self.__world, end='')
        print(self.status() + '\n' + self.menu(), end=' ')

    def random(self):
        """Create a random world"""
        self.__world.randomize(self.__fillrate)
        print(self.__world, end='')
        print(self.status() + '\n' + self.menu(), end=' ')

    def change_size(self, parameter):
        if parameter:
            rows, columns = parameter.split('x', 2)
            if toolbox.is_integer(rows) and toolbox.is_integer(columns):
                rows = int(rows)
                columns = int(columns)
        else:
            prompt = 'How many rows of cells?'
            rows = toolbox.get_integer_between(1, 40, prompt)
            prompt = 'How many cells in each row?'
            columns = toolbox.get_integer_between(1, 120, prompt)
        self.__world = World(rows, columns)
        self.random()

    def long_l_world(self):
        """Create a blank world and put this pattern in the middle:
        ....
        .x..
        .x..
        .x..
        .xx.
        .... """
        rows = self.__world.get_rows()
        columns = self.__world.get_columns()
        self.__world = World(rows, columns)

        middleRow = int(rows / 2)
        middleColumn = int(columns / 2)

        self.__world.set_cell(middleRow - 2, middleColumn, True)
        self.__world.set_cell(middleRow - 1, middleColumn, True)
        self.__world.set_cell(middleRow - 0, middleColumn, True)
        self.__world.set_cell(middleRow + 1, middleColumn, True)
        self.__world.set_cell(middleRow + 1, middleColumn + 1, True)
        print(self.__world, end='')
        print(self.status() + '\n' + self.menu(), end=' ')

    def acorn_world(self):
        """Create a blank world and put this pattern in the middle:
         .........
         ..x......
         ....x....
         .xx..xxx.
         .........
         """
        rows = self.__world.get_rows()
        columns = self.__world.get_columns()
        self.__world = World(rows, columns)

        middleRow = int(rows / 2)
        middleColumn = int(columns / 2)

        self.__world.set_cell(middleRow - 1, middleColumn - 2, True)
        self.__world.set_cell(middleRow - 0, middleColumn - 0, True)
        self.__world.set_cell(middleRow + 1, middleColumn - 3, True)
        self.__world.set_cell(middleRow + 1, middleColumn - 2, True)
        self.__world.set_cell(middleRow + 1, middleColumn + 1, True)
        self.__world.set_cell(middleRow + 1, middleColumn + 2, True)
        self.__world.set_cell(middleRow + 1, middleColumn + 3, True)
        print(self.__world, end='')
        print(self.status() + '\n' + self.menu(), end=' ')
Exemple #5
0
class Life(object):

    speeds = [10, 7, 5, 3, 2, 1.5, 1, 0.75, 0.5, 0.25, 0.15, 0]

    def __init__(self):
        self.__world = World(34, 66)
        self.__fillrate = 25
        self.__speed = 5
        self.__delay = Life.speeds[self.__speed]
        self.__menu = 'main'
        self.random()

    def main(self):
        """
        Main event loop for store.
        :return: choice
        """
        command = 'help'
        parameter = None
        while command != 'quit':
            if command == 'help':
                self.help('help3.txt', 'Press <return> to continue. ')
            elif command == 'more menu':
                self.__menu = 'more'
            elif command == 'back to main menu':
                self.__menu = 'main'
            elif command == 'run simulation':
                self.run_simulation(parameter)
            elif command == 'skip generations':
                self.skip_generations(parameter)
            elif command == 'random world':
                self.random()
            elif command == 'save world':
                self.save(parameter, './worlds/')
            elif command == 'open world':
                self.open(parameter, './worlds/')
            elif command == 'change fillrate':
                self.change_fillrate(parameter)
            elif command == 'change speed':
                self.change_speed(parameter)
            elif command == 'change size':
                self.change_size(parameter)
            elif command == 'change graphics':
                self.change_graphics(parameter)
            elif command == 'geometry':
                self.set_geometry()
            elif command == 'library':
                self.from_library(parameter, './library/')
            self.display()
            command, parameter = self.get_command()
        print('See ya, thanks for playing!')

    def menu(self):
        """
        returns a string containing the menu.
        :return: string containing the menu
        """
        return '[R]un  s[K]ip   [N]ew   [S]ave   [O]pen   [M]ore   [H]elp [L]ibrary   [Q]uit'

    def menu_more(self):
        """
        returns a string containing the menu.
        :return: string containing the menu
        """
        return 's[P]eed   [D]elay   s[I]ze   [G]raphics  g[E]ometry   [H]elp   [B]ack'

    def get_command(self):
        """
        Get a valid command from the user.
        :return: command
        """
        commands = {
            'r': 'run simulation',
            'k': 'skip generations',
            'n': 'random world',
            's': 'save world',
            'o': 'open world',
            'f': 'change fillrate',
            'p': 'change speed',
            'i': 'change size',
            'g': 'change graphics',
            'e': 'geometry',
            'l': 'library',
            'm': 'more menu',
            'b': 'back to main menu',
            'h': 'help',
            '?': 'help',
            'q': 'quit'
        }

        validCommands = commands.keys()

        userInput = '&'
        parameter = None
        while userInput[0].lower() not in validCommands:
            userInput = input('Command: ')
            if userInput == '':
                userInput = 'r'
                parameter = 1
        command = commands[userInput[0].lower()]
        if len(userInput) > 1:
            parameter = userInput[1:].strip()
        return command, parameter

    def status(self):
        """
        Returns a string representing the status of the world.
        :return: string showing the status
        """
        rows = self.__world.get_rows()
        columns = self.__world.get_columns()
        percentAlive = (self.__world.get_living_cell_count() /
                        (rows * columns)) * 100
        string = 'Status:   '
        string += f'gen: {self.__world.get_generation()}   '
        string += f'speed: {self.__speed}   '
        string += f'size:[{rows}x{columns}]   '
        string += f'alive: {percentAlive:0.0f}%   '
        return string

    def help(self, filename, prompt=None):
        """
        Displays instructions.
        :param filename: help3.txt
        :param prompt:
        :return: None
        """
        with open(filename, 'r') as file:
            help = file.read()
        print(help, end='')
        if prompt:
            input('\n' + prompt)

    def next_generation(self, parameter):
        """
        Displays the next generation of the world
        :param parameter: parameter
        :return:
        """
        self.__world.next_generation()
        self.display()

    def run_simulation(self, generations):
        """
        Displays the next generation of the world
        :param generations:
        :return: next generation
        """
        if toolbox.is_integer(generations) and int(generations) > 0:
            generations = int(generations)
        else:
            prompt = 'How many generations do you want to do?'
            generations = toolbox.get_integer_between(1, 10000, prompt)
        for generation in range(generations):
            self.__world.next_generation()
            if self.__world.is_stable() == True:
                break
            string = self.__world.__str__()
            string += self.status()
            string += f'left: {generations - generation}'
            print(string)
            time.sleep(self.__delay)
        print(self.menu())

    def skip_generations(self, generations):
        """
        Displays the next generation of the world
        :param generations:
        :return: next generation
        """
        if toolbox.is_integer(generations) and int(generations) > 0:
            generations = int(generations)
        else:
            prompt = 'How many generations do you wanna skip?'
            generations = toolbox.get_integer_between(1, 10000, prompt)
        print(f'Skipping {generations} generations.', end='')
        while True:
            for generation in range(generations):
                self.__world.next_generation()
                self.__world.is_stable(self.__world)
                if generation % 100 == 0:
                    print('.', end='')
        print(' done!')
        time.sleep(2)
        self.display()

    def change_fillrate(self, fillrate):
        """
        Change the fillrate for the simulation.
        :param fillrate:
        :return: fillrate
        """
        if toolbox.is_number(fillrate) and 0 <= float(fillrate) <= 100:
            fillrate = float(fillrate)
        else:
            prompt = 'What percent of cells do you want to be alive?'
            fillrate = toolbox.get_integer_between(0, 100, prompt)
        self.__fillrate = fillrate
        self.random()

    def change_speed(self, speed):
        """
        Change the delay betwen generations of the simulation.
        :param speed:
        :return: speed
        """
        if toolbox.is_number(speed):
            speed = int(speed)
        else:
            prompt = 'How fast should the generations update?'
            speed = toolbox.get_integer_between(0, 11, prompt)
        self.__delay = Life.speeds[speed]

    def change_graphics(self, whichCharacters):
        """
        Change the live and dead characters for the cells.
        :param whichCharacters:
        :return: whichCharacters
        """
        if toolbox.is_integer(whichCharacters) and \
           1 <= int(whichCharacters) <= len(Cell.displaySets.keys()):
            whichCharacters = int(whichCharacters)
        else:
            print('**************************************')
            for number, set in enumerate(Cell.displaySets):
                liveChar = Cell.displaySets[set]['liveChar']
                deadChar = Cell.displaySets[set]['deadChar']
                print(
                    f'{number+1}: living cells: {liveChar} dead cells: {deadChar}'
                )
            print(f'{number + 2}: pick your own characters')
            print('**************************************')
            prompt = 'What character do you want to use?'
            whichCharacters = toolbox.get_integer_between(
                1, number + 2, prompt)
            if whichCharacters == number + 2:
                alive = toolbox.get_string(
                    'Which character should represent alive cells?')
                dead = toolbox.get_string(
                    'Which character should represent dead cells?')
                Cell.set_display_user_values(alive, dead)
        setString = list(Cell.displaySets.keys())[whichCharacters - 1]
        Cell.set_display(setString)
        self.display()

    def set_geometry(self):
        userGeo = toolbox.get_integer_between(
            1, 2, """
        Choose 1 or 2:
        1. bowl
        2. torus""")
        self.__world.set_geometry(userGeo)
        print(self.__world, end='')
        print(self.status() + '\n' + self.menu(), end='')

    def random(self):
        """
        Create a random world
        :return: world
        """
        self.__world.randomize(self.__fillrate)
        self.display()

    def save(self, filename, myPath='./'):
        """
        Save the current generation of the current world as a text file.
        :param filename: name of the file, may be None at this point.
        :param myPath: Where the file should be saved.
        :return: None
        """
        if filename == None:
            filename = toolbox.get_string('What do you wanna call the file? ')
        #
        # Make sure the file has the correct file extension.
        #
        if filename[-5:] != '.life':
            filename = filename + '.life'
        #
        # if the path doesn't already exist, create it.
        #
        if not os.path.isdir(myPath):
            os.mkdir(myPath)
        #
        # Add on the correct path for saving files if the user didn't
        # include it in the filename.
        #
        if filename[0:len(myPath)] != myPath:
            filename = myPath + filename
        self.__world.save(filename)

    def open(self, filename, myPath='./'):
        """
        open a text file and use it to populate a new world.
        :param filename: name of the file, may be None at this point.
        :param myPath: Where the file is located.
        :return: None
        """
        if filename == None:
            filename = toolbox.get_string('Which file do you wanna open?')
        #
        # Check for and add the correct file extension.
        #
        if filename[-5:] != '.life':
            filename = filename + '.life'
        allFiles = os.listdir(myPath)
        if filename not in allFiles:
            print(
                '404: File not found...thanks for breaking the program, idiot.'
            )
        else:
            #
            # Add on the correct path for saving files if the user didn't
            # include it in the filename.
            #
            if filename[0:len(myPath)] != myPath:
                filename = myPath + filename
            self.__world = World.from_file(filename)

    def change_size(self, parameter):
        if parameter and ('x' in parameter):
            rows, columns = parameter.split('x', 2)
            if toolbox.is_integer(rows) and toolbox.is_integer(columns):
                rows = int(rows)
                columns = int(columns)
        else:
            prompt = 'How many rows of cells?'
            rows = toolbox.get_integer_between(1, 40, prompt)
            prompt = 'How many cells in each row?'
            columns = toolbox.get_integer_between(1, 120, prompt)
        self.__world = World(rows, columns)
        self.random()

    def display(self):
        """
        Prints the world, status bar and menu
        :return: None
        """
        if self.__menu == 'main':
            print(self.__world, self.status() + '\n' + self.menu())
        elif self.__menu == 'more':
            print(self.__world, self.status() + '\n' + self.menu_more())

    def long_l_world(self):
        """Create a blank world and put this pattern in the middle:
        ....
        .x..
        .x..
        .x..
        .xx.
        .... """
        rows = self.__world.get_rows()
        columns = self.__world.get_columns()
        self.__world = World(rows, columns)

        middleRow = int(rows / 2)
        middleColumn = int(columns / 2)

        self.__world.set_cell(middleRow - 2, middleColumn, True)
        self.__world.set_cell(middleRow - 1, middleColumn, True)
        self.__world.set_cell(middleRow - 0, middleColumn, True)
        self.__world.set_cell(middleRow + 1, middleColumn, True)
        self.__world.set_cell(middleRow + 1, middleColumn + 1, True)
        self.display()

    def acorn_world(self):
        """Create a blank world and put this pattern in the middle:
         .........
         ..x......
         ....x....
         .xx..xxx.
         .........
         """
        rows = self.__world.get_rows()
        columns = self.__world.get_columns()
        self.__world = World(rows, columns)

        middleRow = int(rows / 2)
        middleColumn = int(columns / 2)

        self.__world.set_cell(middleRow - 1, middleColumn - 2, True)
        self.__world.set_cell(middleRow - 0, middleColumn - 0, True)
        self.__world.set_cell(middleRow + 1, middleColumn - 3, True)
        self.__world.set_cell(middleRow + 1, middleColumn - 2, True)
        self.__world.set_cell(middleRow + 1, middleColumn + 1, True)
        self.__world.set_cell(middleRow + 1, middleColumn + 2, True)
        self.__world.set_cell(middleRow + 1, middleColumn + 3, True)
        self.display()

    def from_library(self, filename, myPath='./'):
        allFiles = os.listdir(myPath)
        if filename not in allFiles:
            for file in allFiles:
                print(file)
        if filename == None:
            filename = toolbox.get_string('Which world do you wanna use?')
        if filename[-5:] != '.life':
            filename = filename + '.life'
        else:
            if filename[0:len(myPath)] != myPath:
                filename = myPath + filename
            self.__world = World.from_file(filename)
Exemple #6
0
class Life(object):
    speeds = [10, 7, 5, 3, 2, 1.5, 1, 0.75, 0.5, 0.25, 0.15, 0]

    def __init__(self):
        self.__world = World_Torus(17, 33)
        self.__fillrate = 25
        self.__speed = 5
        self.__delay = Life.speeds[self.__speed]
        self.__menu = 'main'
        self.__worldType = World_Torus
        self.random()
        self.__feedback = ''
        self.__lastWorld = ''

    def main(self):
        """Main event loop for Conway's game of life."""
        command = 'help'
        parameter = None
        while command != 'quit':
            if command == 'help':
                if self.__menu == 'main':
                    self.help('help.txt', 'Press <return> to continue.')
                elif self.__menu == 'more':
                    self.help('help2.txt', 'Press <return> to continue.')
            if command == 'more menu':
                self.__menu = 'more'
            if command == 'back to main menu':
                self.__menu = 'main'
            elif command == 'run simulation':
                self.__feedback = '(Running....)'
                self.run_simulation(parameter)
            elif command == 'skip generations':
                self.skip_generations(parameter)
            elif command == 'random world':
                self.random()
            elif command == 'save world':
                self.save(parameter, './worlds/')
            elif command == 'open world':
                self.open(parameter, './worlds/')
            elif command == 'change fillrate':
                self.change_fillrate(parameter)
            elif command == 'change speed':
                self.change_speed(parameter)
            elif command == 'change size':
                self.change_size(parameter)
            elif command == 'change graphics':
                self.change_graphics(parameter)
            elif command == 'long l world':
                self.long_l_world()
            elif command == 'acorn world':
                self.acorn_world()
            self.display()
            command, parameter = self.get_command()
        print('goodbye')

    def menu(self):
        """returns a string containing the menu."""
        return '[R]un  s[K]ip   [N]ew   [S]ave   [O]pen   [M]ore   [H]elp   [Q]uit'

    def menu_more(self):
        """returns a string containing the menu."""
        return 's[P]eed   [D]elay   s[I]ze   [G]raphics   [L]ong l   [A]corn   [H]elp   [B]ack'

    def get_command(self):
        """Get a valid command from the user."""
        commands = {'r': 'run simulation',
                    'k': 'skip generations',
                    'n': 'random world',
                    's': 'save world',
                    'o': 'open world',
                    'f': 'change fillrate',
                    'p': 'change speed',
                    'i': 'change size',
                    'g': 'change graphics',
                    'l': 'long l world',
                    'a': 'acorn world',
                    'm': 'more menu',
                    'b': 'back to main menu',
                    'h': 'help',
                    '?': 'help',
                    'q': 'quit'}

        validCommands = commands.keys()

        userInput = '&'
        parameter = None
        while userInput[0].lower() not in validCommands:
            userInput = input('Command: ')
            if userInput == '':
                userInput = 'r'
                parameter = 1
        command = commands[userInput[0].lower()]
        if len(userInput) > 1:
            parameter = userInput[1:].strip()
        return command, parameter

    def status(self):
        """Returns a string representing the status of the world."""
        rows = self.__world.get_rows()
        columns = self.__world.get_columns()
        percentAlive = (self.__world.get_living_cell_count() / (rows * columns)) * 100
        string = 'Status:   '
        # string += f'gen:{self.__generations}   '
        string += f'speed: {self.__delay} sec.   '
        string += f'size:[{rows}x{columns}]   '
        string += f'alive: {percentAlive:0.0f}%   '
        return string

    def help(self, filename, prompt=None):
        """Displays instructions."""
        with open(filename, 'r') as file:
            help = file.read()
        print(help, end='')
        if prompt:
            input('\n' + prompt)

    def next_generation(self, parameter):
        """Displays the next generation of the world"""
        self.__world.next_generation()
        self.display()

    def run_simulation(self, generations):
        """Displays the next generation of the world"""
        if toolbox.is_integer(generations) and int(generations) > 0:
            generations = int(generations)
        else:
            prompt = 'How many generations would you like to simulate?'
            generations = toolbox.get_integer_between(1, 10000, prompt)
        for generation in range(generations):
            if self.__world.stop_simulation():
                print('simulation is steady')
                break
            else:
                self.__world.next_generation()
                string = self.__world.__str__()
                string += self.status()
                string += f'left: {generations - generation}'
                print(string)
                # self.__generations += 1
                time.sleep(self.__delay)
        print(self.menu())

    def skip_generations(self, generations):
        """Displays the next generation of the world"""
        if toolbox.is_integer(generations) and int(generations) > 0:
            generations = int(generations)
        else:
            prompt = 'How many generations would you like to skip?'
            generations = toolbox.get_integer_between(1, 10000, prompt)
        print(f'Skipping {generations} generations.', end='')
        for generation in range(generations):
            self.__world.next_generation()
            if generation % 100 == 0:
                print('.', end='')
        print(' done!')
        self.__generations = generations
        time.sleep(2)
        self.display()

    def change_fillrate(self, fillrate):
        """Change the fillrate for the simulation."""
        if toolbox.is_number(fillrate) and 0 <= float(fillrate) <= 100:
            fillrate = float(fillrate)
        else:
            prompt = 'What percent of cells should be alive?'
            fillrate = toolbox.get_integer_between(0, 100, prompt)
        self.__fillrate = fillrate
        self.random()

    def change_speed(self, speed):
        """Change the delay betwen generations of the simulation."""
        if toolbox.is_number(speed):
            speed = int(speed)
        else:
            prompt = 'How fast should the generations update?'
            speed = toolbox.get_integer_between(0, 11, prompt)
        self.__delay = Life.speeds[speed]

    def change_graphics(self, whichCharacters):
        """Change the live and dead characters for the cells."""
        if toolbox.is_integer(whichCharacters) and \
                1 <= int(whichCharacters) <= len(Cell.displaySets.keys()):
            whichCharacters = int(whichCharacters)
        else:
            print('**************************************')
            for number, set in enumerate(Cell.displaySets):
                liveChar = Cell.displaySets[set]['liveChar']
                deadChar = Cell.displaySets[set]['deadChar']
                print(f'{number + 1}: living cells: {liveChar} dead cells: {deadChar}')
            print(f'{number + 2}: pick your own characters')
            print('**************************************')
            prompt = 'What character set would you like to use?'
            whichCharacters = toolbox.get_integer_between(1, number + 2, prompt)
            if whichCharacters == number + 2:
                alive = toolbox.get_string('Which character should represent alive cells?')
                dead = toolbox.get_string('Which character should represent dead cells?')
                Cell.set_display_user_values(alive, dead)
        setString = list(Cell.displaySets.keys())[whichCharacters - 1]
        Cell.set_display(setString)
        self.display()

    def change_rules(self, parameter):
        """
        Print possible display changes for the user.
        :param parameter:
        :return: none
        """
        if toolbox.is_integer(parameter) and \
                1 <= int(parameter) <= len(Rules.ruleSets.keys()):
            setNumber = int(parameter)
        else:
            print('**************************************')
            for number, ruleSet in enumerate(Rules.ruleSets):
                bornNum = Rules.ruleSets[ruleSet]['bornNum']
                surviveNum = Rules.ruleSets[ruleSet]['surviveNum']
                print(f'{number+1}: Born Number: {bornNum} Survive Number: {surviveNum}')
            print(f'{number+2}: Choose your own characters! ')
            print('**************************************')
            prompt = 'What character set would you like to use?'
            setNumber = toolbox.get_integer_between(1, number + 2, prompt)
            numberOfSets = number + 2
        if setNumber == numberOfSets:
            setString = 'choice'
        else:
            setString = list(rules.Rules.ruleSets.keys())[setNumber - 1]
        rules.Rules.set_rules(setString)
        print(self.__lastWorld, end='')

    def random(self):
        """Create a random world"""
        self.__world.randomize(self.__fillrate)
        self.display()

    def save(self, filename, myPath='./'):
        """
        Save the current generation of the current world as a text file.
        :param filename: name of the file, may be None at this point.
        :param myPath: Where the file should be saved.
        :return: None
        """
        if filename == None:
            filename = toolbox.get_string('What do you want to call the file? ')
        #
        # Make sure the file has the correct file extension.
        #
        if filename[-5:] != '.life':
            filename = filename + '.life'
        #
        # if the path doesn't already exist, create it.
        #
        if not os.path.isdir(myPath):
            os.mkdir(myPath)
        #
        # Add on the correct path for saving files if the user didn't
        # include it in the filename.
        #
        if filename[0:len(myPath)] != myPath:
            filename = myPath + filename
        self.__world.save(filename)

    def open(self, filename, myPath='./worlds'):
        """
        open a text file and use it to populate a new world.
        :param filename: name of the file, may be None at this point.
        :param myPath: Where the file is located.
        :return: None
        """
        if filename == None:
            filename = toolbox.get_string('Which file do you want to open?')
        #
        # Check for and add the correct file extension.
        #
        if filename[-5:] != '.life':
            filename = filename + '.life'
        allFiles = os.listdir(myPath)
        if filename not in allFiles:
            print('404: File not found...')
        else:
            #
            # Add on the correct path for saving files if the user didn't
            # include it in the filename.
            #
            if filename[0:len(myPath)] != myPath:
                filename = myPath + filename
            self.__world = self.__worldType.from_file(filename, self.__worldType)
        print(self.__world)

    def change_size(self, parameter):
        if parameter and ('x' in parameter):
            rows, columns = parameter.split('x', 2)
            if toolbox.is_integer(rows) and toolbox.is_integer(columns):
                rows = int(rows)
                columns = int(columns)
        else:
            prompt = 'How many rows of cells?'
            rows = toolbox.get_integer_between(1, 40, prompt)
            prompt = 'How many cells in each row?'
            columns = toolbox.get_integer_between(1, 120, prompt)
        self.__world = self.__worldType(rows, columns)
        self.random()

    def display(self):
        """
        Prints the world, status bar and menu
        :return: None
        """
        if self.__menu == 'main':
            print(self.__world, self.status() + '\n' + self.menu())
        elif self.__menu == 'more':
            print(self.__world, self.status() + '\n' + self.menu_more())

    def long_l_world(self):
        """Create a blank world and put this pattern in the middle:
        ....
        .x..
        .x..
        .x..
        .xx.
        .... """
        rows = self.__world.get_rows()
        columns = self.__world.get_columns()
        self.__world = self.__worldType(rows, columns)

        middleRow = int(rows / 2)
        middleColumn = int(columns / 2)

        self.__world.set_cell(middleRow - 2, middleColumn, True)
        self.__world.set_cell(middleRow - 1, middleColumn, True)
        self.__world.set_cell(middleRow - 0, middleColumn, True)
        self.__world.set_cell(middleRow + 1, middleColumn, True)
        self.__world.set_cell(middleRow + 1, middleColumn + 1, True)
        self.display()

    def acorn_world(self):
        """Create a blank world and put this pattern in the middle:
         .........
         ..x......
         ....x....
         .xx..xxx.
         .........
         """
        rows = self.__world.get_rows()
        columns = self.__world.get_columns()
        self.__world = World(rows, columns)

        middleRow = int(rows / 2)
        middleColumn = int(columns / 2)

        self.__world.set_cell(middleRow - 1, middleColumn - 2, True)
        self.__world.set_cell(middleRow - 0, middleColumn - 0, True)
        self.__world.set_cell(middleRow + 1, middleColumn - 3, True)
        self.__world.set_cell(middleRow + 1, middleColumn - 2, True)
        self.__world.set_cell(middleRow + 1, middleColumn + 1, True)
        self.__world.set_cell(middleRow + 1, middleColumn + 2, True)
        self.__world.set_cell(middleRow + 1, middleColumn + 3, True)
        self.display()

    def change_geometry(self):
        string = '1. Flat World'
        string += '/n2. Torus World'
        print(string)
        choice = toolbox.get_integer_between(1, 2, 'Which geometry type would you like?: ')
        if choice == 1:
            self.__worldType = World
        else:
            self.__worldType = World_Torus