new cellular automaton
This commit is contained in:
parent
facc15cebc
commit
390c95df30
@ -1,11 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.7" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7" project-jdk-type="Python SDK" />
|
||||
</project>
|
@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/WorldGeneration.iml" filepath="$PROJECT_DIR$/.idea/WorldGeneration.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
@ -1,405 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="5a936069-819f-4c75-93de-a950897acf14" name="Default Changelist" comment="" />
|
||||
<ignored path="$PROJECT_DIR$/venv/" />
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="FUSProjectUsageTrigger">
|
||||
<session id="1685401553">
|
||||
<usages-collector id="statistics.lifecycle.project">
|
||||
<counts>
|
||||
<entry key="project.closed" value="1" />
|
||||
<entry key="project.open.time.1" value="1" />
|
||||
<entry key="project.open.time.4" value="1" />
|
||||
<entry key="project.open.time.5" value="2" />
|
||||
<entry key="project.opened" value="4" />
|
||||
</counts>
|
||||
</usages-collector>
|
||||
<usages-collector id="statistics.file.extensions.open">
|
||||
<counts>
|
||||
<entry key="py" value="11" />
|
||||
</counts>
|
||||
</usages-collector>
|
||||
<usages-collector id="statistics.file.types.open">
|
||||
<counts>
|
||||
<entry key="Python" value="11" />
|
||||
</counts>
|
||||
</usages-collector>
|
||||
<usages-collector id="statistics.file.extensions.edit">
|
||||
<counts>
|
||||
<entry key="dummy" value="25" />
|
||||
<entry key="py" value="2139" />
|
||||
</counts>
|
||||
</usages-collector>
|
||||
<usages-collector id="statistics.file.types.edit">
|
||||
<counts>
|
||||
<entry key="PLAIN_TEXT" value="25" />
|
||||
<entry key="Python" value="2139" />
|
||||
</counts>
|
||||
</usages-collector>
|
||||
</session>
|
||||
</component>
|
||||
<component name="FileEditorManager">
|
||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/world_generator.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state>
|
||||
<caret selection-end-column="22" />
|
||||
<folding>
|
||||
<element signature="e#24#38#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/scripts/main_ui.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="272">
|
||||
<caret line="16" column="59" selection-start-line="16" selection-start-column="59" selection-end-line="16" selection-end-column="59" />
|
||||
<folding>
|
||||
<element signature="e#24#37#0" expanded="true" />
|
||||
<marker date="1543672995350" expanded="true" signature="132:425" ph="..." />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/cellular_automaton/__init__.py">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/cellular_automaton/cellular_automaton.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="680">
|
||||
<caret line="44" column="87" selection-start-line="44" selection-start-column="87" selection-end-line="44" selection-end-column="87" />
|
||||
<folding>
|
||||
<element signature="e#0#16#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/cellular_automaton/ca_rule.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="170">
|
||||
<caret line="10" column="39" selection-start-line="10" selection-start-column="39" selection-end-line="10" selection-end-column="39" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/cellular_automaton/ca_neighberhood.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="51">
|
||||
<caret line="3" column="63" selection-start-line="3" selection-start-column="55" selection-end-line="3" selection-end-column="63" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/cellular_automaton/ca_grid.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="629">
|
||||
<caret line="38" column="10" selection-start-line="38" selection-start-column="9" selection-end-line="38" selection-end-column="10" />
|
||||
<folding>
|
||||
<element signature="e#0#45#0" expanded="true" />
|
||||
<marker date="1540986500017" expanded="true" signature="3484:3522" ph="..." />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/cellular_automaton/ca_cell.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="17">
|
||||
<caret line="1" column="43" selection-start-line="1" selection-start-column="43" selection-end-line="1" selection-end-column="43" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
</leaf>
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
<list>
|
||||
<option value="Python Script" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="FindInProjectRecents">
|
||||
<findStrings>
|
||||
<find>get_coordinate_from_index</find>
|
||||
<find>print</find>
|
||||
</findStrings>
|
||||
</component>
|
||||
<component name="IdeDocumentHistory">
|
||||
<option name="CHANGED_PATHS">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/src/cellular_automaton/ca_neighberhood.py" />
|
||||
<option value="$PROJECT_DIR$/src/cellular_automaton/ca_cell.py" />
|
||||
<option value="$PROJECT_DIR$/src/cellular_automaton/ca_rule.py" />
|
||||
<option value="$PROJECT_DIR$/src/cellular_automaton/ca_grid.py" />
|
||||
<option value="$PROJECT_DIR$/src/cellular_automaton/cellular_automaton.py" />
|
||||
<option value="$PROJECT_DIR$/src/world_generator.py" />
|
||||
<option value="$PROJECT_DIR$/src/cellular_automaton/__init__.py" />
|
||||
<option value="$PROJECT_DIR$/src/cellular_automaton/pygame_main.py" />
|
||||
<option value="$PROJECT_DIR$/scripts/main_ui.py" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds" extendedState="6">
|
||||
<option name="x" value="442" />
|
||||
<option name="y" value="-11" />
|
||||
<option name="width" value="1400" />
|
||||
<option name="height" value="1000" />
|
||||
</component>
|
||||
<component name="ProjectView">
|
||||
<navigator proportions="" version="1">
|
||||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="Scope" />
|
||||
<pane id="ProjectPane">
|
||||
<subPane>
|
||||
<expand>
|
||||
<path>
|
||||
<item name="WorldGeneration" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="WorldGeneration" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="WorldGeneration" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="WorldGeneration" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="images" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="WorldGeneration" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="WorldGeneration" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="scripts" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="WorldGeneration" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="WorldGeneration" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="src" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="WorldGeneration" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="WorldGeneration" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="src" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="cellular_automaton" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
</expand>
|
||||
<select />
|
||||
</subPane>
|
||||
</pane>
|
||||
</panes>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
||||
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
|
||||
</component>
|
||||
<component name="RecentsManager">
|
||||
<key name="MoveFile.RECENT_KEYS">
|
||||
<recent name="D:\DamKoVosh\Eigene Dokumente\Programming\WorldGeneration\scripts" />
|
||||
</key>
|
||||
</component>
|
||||
<component name="RunDashboard">
|
||||
<option name="ruleStates">
|
||||
<list>
|
||||
<RuleState>
|
||||
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
<RuleState>
|
||||
<option name="name" value="StatusDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="RunManager" selected="Python.main_ui">
|
||||
<configuration name="main_ui" type="PythonConfigurationType" factoryName="Python" temporary="true">
|
||||
<module name="WorldGeneration" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/scripts" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/scripts/main_ui.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<configuration name="world_generator" type="PythonConfigurationType" factoryName="Python" temporary="true">
|
||||
<module name="WorldGeneration" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/src" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/src/world_generator.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
<list>
|
||||
<item itemvalue="Python.world_generator" />
|
||||
<item itemvalue="Python.main_ui" />
|
||||
</list>
|
||||
<recent_temporary>
|
||||
<list>
|
||||
<item itemvalue="Python.main_ui" />
|
||||
<item itemvalue="Python.world_generator" />
|
||||
</list>
|
||||
</recent_temporary>
|
||||
</component>
|
||||
<component name="SvnConfiguration">
|
||||
<configuration />
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="5a936069-819f-4c75-93de-a950897acf14" name="Default Changelist" comment="" />
|
||||
<created>1540970314178</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1540970314178</updated>
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TodoView">
|
||||
<todo-panel id="selected-file">
|
||||
<is-autoscroll-to-source value="true" />
|
||||
</todo-panel>
|
||||
<todo-panel id="all">
|
||||
<are-packages-shown value="true" />
|
||||
<is-autoscroll-to-source value="true" />
|
||||
</todo-panel>
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="1912" y="-6" width="1936" height="1056" extended-state="6" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info content_ui="combo" id="Project" order="0" visible="true" weight="0.24973656" />
|
||||
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
|
||||
<window_info id="Favorites" order="2" side_tool="true" />
|
||||
<window_info anchor="bottom" id="Message" order="0" />
|
||||
<window_info anchor="bottom" id="Find" order="1" />
|
||||
<window_info active="true" anchor="bottom" id="Run" order="2" sideWeight="0.49894625" visible="true" weight="0.329718" />
|
||||
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
|
||||
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
|
||||
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
|
||||
<window_info anchor="bottom" id="TODO" order="6" weight="0.329718" />
|
||||
<window_info anchor="bottom" id="Version Control" order="7" show_stripe_button="false" />
|
||||
<window_info anchor="bottom" id="Terminal" order="8" sideWeight="0.49894625" weight="0.329718" />
|
||||
<window_info anchor="bottom" id="Event Log" order="9" sideWeight="0.50105375" side_tool="true" visible="true" weight="0.329718" />
|
||||
<window_info anchor="bottom" id="Python Console" order="10" sideWeight="0.49947312" weight="0.329718" />
|
||||
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
|
||||
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
|
||||
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
|
||||
</layout>
|
||||
</component>
|
||||
<component name="VcsContentAnnotationSettings">
|
||||
<option name="myLimit" value="2678400000" />
|
||||
</component>
|
||||
<component name="editorHistoryManager">
|
||||
<entry file="file://$USER_HOME$/AppData/Roaming/Python/Python37/site-packages/pygame/__init__.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="221">
|
||||
<caret line="143" selection-start-line="143" selection-end-line="143" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/world_generator.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state>
|
||||
<caret selection-end-column="22" />
|
||||
<folding>
|
||||
<element signature="e#24#38#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/cellular_automaton/__init__.py">
|
||||
<provider selected="true" editor-type-id="text-editor" />
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/cellular_automaton/cellular_automaton.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="680">
|
||||
<caret line="44" column="87" selection-start-line="44" selection-start-column="87" selection-end-line="44" selection-end-column="87" />
|
||||
<folding>
|
||||
<element signature="e#0#16#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/cellular_automaton/ca_rule.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="170">
|
||||
<caret line="10" column="39" selection-start-line="10" selection-start-column="39" selection-end-line="10" selection-end-column="39" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/cellular_automaton/ca_neighberhood.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="51">
|
||||
<caret line="3" column="63" selection-start-line="3" selection-start-column="55" selection-end-line="3" selection-end-column="63" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/cellular_automaton/ca_grid.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="629">
|
||||
<caret line="38" column="10" selection-start-line="38" selection-start-column="9" selection-end-line="38" selection-end-column="10" />
|
||||
<folding>
|
||||
<element signature="e#0#45#0" expanded="true" />
|
||||
<marker date="1540986500017" expanded="true" signature="3484:3522" ph="..." />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/cellular_automaton/ca_cell.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="17">
|
||||
<caret line="1" column="43" selection-start-line="1" selection-start-column="43" selection-end-line="1" selection-end-column="43" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/scripts/main_ui.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="272">
|
||||
<caret line="16" column="59" selection-start-line="16" selection-start-column="59" selection-end-line="16" selection-end-column="59" />
|
||||
<folding>
|
||||
<element signature="e#24#37#0" expanded="true" />
|
||||
<marker date="1543672995350" expanded="true" signature="132:425" ph="..." />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
</project>
|
@ -3,7 +3,10 @@
|
||||
import pygame
|
||||
import random
|
||||
|
||||
from cellular_automaton import cellular_automaton
|
||||
from cellular_automaton.cellular_automaton import CellularAutomaton
|
||||
from cellular_automaton.ca_cell import CACell
|
||||
from cellular_automaton.ca_grid import CAGrid
|
||||
from cellular_automaton.ca_rule import CARule
|
||||
|
||||
|
||||
class WorldGeneratorWindow:
|
||||
@ -44,5 +47,19 @@ def main():
|
||||
running = False
|
||||
|
||||
|
||||
class TestRule(CARule):
|
||||
def evolve_cell(self, cell, neighbors):
|
||||
if neighbors[1][0] != 0:
|
||||
return [1]
|
||||
else:
|
||||
return [0]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
dim = [200, 500]
|
||||
ca = CellularAutomaton(2)
|
||||
|
||||
new_grid = CAGrid(dim)
|
||||
new_grid.set_cell_by_coordinate([1, 1], CACell([1]))
|
||||
rule = TestRule()
|
||||
|
@ -1,19 +1,7 @@
|
||||
class CACell:
|
||||
def __init__(self, initial_state=None):
|
||||
if initial_state:
|
||||
assert isinstance(initial_state, (tuple, list))
|
||||
self._state = initial_state
|
||||
else:
|
||||
self._state = [0]
|
||||
class Cell:
|
||||
def __init__(self, name: str):
|
||||
self.name = name
|
||||
self.neighbours = []
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self._state[index]
|
||||
|
||||
def __setitem__(self, index, value):
|
||||
self._state[index] = value
|
||||
|
||||
def __len__(self):
|
||||
return len(self._state)
|
||||
|
||||
def __str__(self):
|
||||
return str(self._state)
|
||||
def set_neighbours(self, neighbours: list):
|
||||
self.neighbours = neighbours
|
||||
|
@ -1,124 +1,78 @@
|
||||
from cellular_automaton.ca_cell import CACell
|
||||
from functools import reduce
|
||||
from cellular_automaton.ca_cell import Cell
|
||||
from cellular_automaton.ca_neighborhood import CellularAutomatonNeighborhood
|
||||
|
||||
|
||||
class CAGrid:
|
||||
def __init__(self, dimensions, initial_grid_state=None):
|
||||
assert isinstance(dimensions, list)
|
||||
assert len(dimensions) > 0
|
||||
self._dimensions = dimensions
|
||||
class Grid:
|
||||
def __init__(self, dimension: list, neighborhood: CellularAutomatonNeighborhood):
|
||||
self._dimension = dimension
|
||||
self._cells = {}
|
||||
self._neighborhood = neighborhood
|
||||
|
||||
self._cell_count = reduce(lambda x, y: x*y, dimensions)
|
||||
self._create_cells()
|
||||
self._set_cell_neighbours()
|
||||
|
||||
if initial_grid_state:
|
||||
assert isinstance(initial_grid_state, list)
|
||||
assert len(initial_grid_state) == self._cell_count
|
||||
assert isinstance(initial_grid_state[0], CACell)
|
||||
self._grid = initial_grid_state
|
||||
else:
|
||||
self._grid = []
|
||||
self._active_cells = {}
|
||||
self.set_all_cells_active()
|
||||
|
||||
for i in range(self._cell_count):
|
||||
self._grid.append(CACell())
|
||||
def set_all_cells_active(self):
|
||||
for cell_key in self._cells:
|
||||
self._active_cells[cell_key] = 1
|
||||
|
||||
def get_index_from_coordinate(self, coordinate):
|
||||
""" Convert a coordinate to the index in the grid list.
|
||||
:param coordinate: A tuple or list with the position of the cell.
|
||||
Has to have the same dimension as the grid.
|
||||
:return: The index of the cell at the coordinates
|
||||
def get_active_cells(self):
|
||||
return self._active_cells.keys()
|
||||
|
||||
def get_cell_and_neighbors(self, cell_name):
|
||||
cell = self._cells[cell_name]
|
||||
neighbours = cell.neighbours
|
||||
neighbour_objects = []
|
||||
for ne in neighbours:
|
||||
neighbour_objects.append(self._cells[ne])
|
||||
|
||||
return [cell, neighbour_objects]
|
||||
|
||||
|
||||
def _create_cells(self, dimension_index=0, coordinate=None):
|
||||
""" Recursively steps down the dimensions to create cells in n dimensions and adds them to a dict.
|
||||
:param dimension_index: The index indicating which dimension is currently traversed.
|
||||
:param coordinate: The coordinate generated so far.
|
||||
(each recursion adds one dimension to the coordinate.
|
||||
"""
|
||||
assert len(self._dimensions) == len(coordinate)
|
||||
index = 0
|
||||
for i, c in enumerate(coordinate[1:]):
|
||||
index += c * reduce(lambda x, y: x * y, self._dimensions[:i+1])
|
||||
index += coordinate[0]
|
||||
return index
|
||||
coordinate = self.instantiate_coordinate_if_necessary(coordinate)
|
||||
|
||||
def get_coordinate_from_index(self, index):
|
||||
""" Convert an index to the coordinate in the grid list.
|
||||
:param index: The Index of the cell in the grid.
|
||||
:return: The coordinate pointing at the indexed cell in the grid.
|
||||
try:
|
||||
self._recursive_step_down_dimensions(coordinate, dimension_index, self._create_cells)
|
||||
except IndexError:
|
||||
coordinate_string = '-'.join(coordinate)
|
||||
self._cells[coordinate_string] = Cell(coordinate_string)
|
||||
|
||||
def _recursive_step_down_dimensions(self, coordinate, dimension_index, recursion_method):
|
||||
""" For the range of the current dimension, recalls the recursion method.
|
||||
:param coordinate: The coordinate so far.
|
||||
:param dimension_index: The current dimension lvl.
|
||||
:param recursion_method: The method to call for recursion.
|
||||
"""
|
||||
coordinate = len(self._dimensions)*[0]
|
||||
for i, d in enumerate(self._dimensions):
|
||||
coordinate[-(i + 1)] = index // reduce(lambda x, y: x * y, self._dimensions[-(i + 1):])
|
||||
index = index % reduce(lambda x, y: x * y, self._dimensions[-(i + 1):])
|
||||
for cell_index in range(self._dimension[dimension_index]):
|
||||
coordinate.append(cell_index)
|
||||
recursion_method(dimension_index + 1, coordinate.copy())
|
||||
|
||||
coordinate[0] = index
|
||||
@staticmethod
|
||||
def instantiate_coordinate_if_necessary(coordinate):
|
||||
if coordinate is None:
|
||||
coordinate = []
|
||||
return coordinate
|
||||
|
||||
def get_cell_by_coordinate(self, coordinate):
|
||||
""" Read a cell using a list or tuple as reference
|
||||
:param coordinate A tuple or list with the position of the cell.
|
||||
Has to have the same dimension as the grid.
|
||||
:return: The CACell at the coordinate in the grid.
|
||||
def _set_cell_neighbours(self, dimension_index=0, coordinate=None):
|
||||
""" Recursively steps down the dimensions to get the string instances for each cells neighbours.
|
||||
:param dimension_index: The index indicating which dimension is currently traversed.
|
||||
:param coordinate: The coordinate generated so far.
|
||||
(each recursion adds one dimension to the coordinate.
|
||||
"""
|
||||
coordinate = self.instantiate_coordinate_if_necessary(coordinate)
|
||||
|
||||
try:
|
||||
return self[self.get_index_from_coordinate(coordinate)]
|
||||
self._recursive_step_down_dimensions(coordinate, dimension_index, self._set_cell_neighbours)
|
||||
except IndexError:
|
||||
return None
|
||||
neighbours_coordinates = self._neighborhood.get_neighbor_coordinates(coordinate, self._dimension)
|
||||
neighbour_names = [self._cells['-'.join(nc)].name for nc in neighbours_coordinates]
|
||||
self._cells['-'.join(coordinate)].set_neighbours(neighbour_names)
|
||||
|
||||
def get_all_neighbour_cells(self, position, neighborhood):
|
||||
""" Get a list with all cells defined by the neighborhood.
|
||||
:param position: The position as index or coordinate.
|
||||
:param neighborhood: The neighborhood definition as tuple.
|
||||
:return: All Cells defined by the neighborhood in a list.
|
||||
"""
|
||||
if isinstance(position, (tuple, list)):
|
||||
coordinate = position[:]
|
||||
else:
|
||||
coordinate = self.get_coordinate_from_index(position)
|
||||
|
||||
neighbors = []
|
||||
|
||||
for neighbor in neighborhood:
|
||||
neighbor_coordinate = []
|
||||
for i, (c, nc) in enumerate(zip(coordinate, neighbor)):
|
||||
coord = c + nc
|
||||
if coord < 0:
|
||||
coord = self._dimensions[i] - 1
|
||||
elif coord == self._dimensions[i]:
|
||||
coord = 0
|
||||
|
||||
neighbor_coordinate.append(coord)
|
||||
|
||||
index_ = self.get_cell_by_coordinate(neighbor_coordinate)
|
||||
if index_:
|
||||
neighbors.append(index_)
|
||||
|
||||
return neighbors
|
||||
|
||||
def get_dimensions(self):
|
||||
return self._dimensions
|
||||
|
||||
def set_cell_by_coordinate(self, coordinate, value):
|
||||
""" Write to a cell using a list or tuple as reference
|
||||
:param coordinate A tuple or list with the position of the cell.
|
||||
Has to have the same dimension as the grid.
|
||||
"""
|
||||
try:
|
||||
self._grid[self.get_index_from_coordinate(coordinate)] = value
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def __eq__(self, other):
|
||||
if len(self._grid) != len(other):
|
||||
return False
|
||||
|
||||
for i in self._cell_count:
|
||||
if self._grid[i] != other[i]:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def __len__(self):
|
||||
return len(self._grid)
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self._grid[int(index)]
|
||||
|
||||
def __setitem__(self, index, value):
|
||||
self._grid[index] = value
|
||||
|
||||
def __str__(self):
|
||||
return str(self._grid)
|
||||
|
@ -1,7 +0,0 @@
|
||||
|
||||
|
||||
class Neighborhood:
|
||||
MOOR_2_X_2 = [[-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 0], [0, 1], [1, -1], [1, 0], [1, 1]]
|
||||
|
||||
def __init__(self):
|
||||
pass
|
64
src/cellular_automaton/ca_neighborhood.py
Normal file
64
src/cellular_automaton/ca_neighborhood.py
Normal file
@ -0,0 +1,64 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class EdgeRule(Enum):
|
||||
IGNORE_MISSING_NEIGHBORS_OF_EDGE_CELLS = 0
|
||||
IGNORE_EDGE_CELLS = 1
|
||||
FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS = 2
|
||||
|
||||
|
||||
class CellularAutomatonNeighborhood:
|
||||
def __init__(self, neighbors: list, edge_rule: EdgeRule):
|
||||
self._neighbors = neighbors
|
||||
self.edge_rule = edge_rule
|
||||
self.dimensions = []
|
||||
|
||||
def get_relative_neighbor_coordinates(self):
|
||||
return self._neighbors
|
||||
|
||||
def get_neighbor_coordinates(self, cell_coordinate, dimensions):
|
||||
self.dimensions = dimensions
|
||||
if not self._does_ignore_edge_cell_rule_apply(cell_coordinate):
|
||||
return self._apply_edge_rule_to_neighbours_of(cell_coordinate)
|
||||
|
||||
def _does_ignore_edge_cell_rule_apply(self, coordinate):
|
||||
if self.edge_rule == EdgeRule.IGNORE_EDGE_CELLS and self._is_coordinate_on_an_edge(coordinate):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _is_coordinate_on_an_edge(self, coordinate):
|
||||
for nd, d in zip(coordinate, self.dimensions):
|
||||
if nd == 0 or nd == d - 1:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _apply_edge_rule_to_neighbours_of(self, cell_coordinate):
|
||||
remaining_neighbours = []
|
||||
for neighbour in self._neighbors:
|
||||
if not self._does_ignore_edge_cell_neighbours_rule_apply(neighbour, cell_coordinate):
|
||||
remaining_neighbours.append(self._calculate_neighbour_coordinate(neighbour, cell_coordinate))
|
||||
|
||||
def _does_ignore_edge_cell_neighbours_rule_apply(self, neighbour, cell_coordinate):
|
||||
if self.edge_rule == EdgeRule.IGNORE_MISSING_NEIGHBORS_OF_EDGE_CELLS:
|
||||
for rel_nd, cd, d in zip(neighbour, cell_coordinate, self.dimensions):
|
||||
nd = cd + rel_nd
|
||||
if nd < 0 or nd >= d:
|
||||
return True
|
||||
return False
|
||||
|
||||
def _calculate_neighbour_coordinate(self, neighbour, cell_coordinate):
|
||||
for rel_nd, cd, d in zip(neighbour, cell_coordinate, self.dimensions):
|
||||
nd = cd + rel_nd
|
||||
if nd < 0:
|
||||
nd = d - 1
|
||||
elif nd >= d:
|
||||
nd = 0
|
||||
return nd
|
||||
|
||||
|
||||
class MooreNeighborhood(CellularAutomatonNeighborhood):
|
||||
def __init__(self, edge_rule: EdgeRule):
|
||||
super().__init__([[-1, -1], [0, -1], [1, -1],
|
||||
[-1, 0], [0, 0], [1, 0],
|
||||
[-1, 1], [0, 1], [1, 1]],
|
||||
edge_rule)
|
@ -1,13 +1,9 @@
|
||||
import abc
|
||||
from cellular_automaton.ca_cell import Cell
|
||||
|
||||
|
||||
class CARule(abc.ABC):
|
||||
@abc.abstractmethod
|
||||
def evolve_cell(self, cell, neighbors):
|
||||
"""
|
||||
Evolves a cell and returns its new state as list of states.
|
||||
:param cell: The cell to evolve.
|
||||
:param neighbors: A list of its neighbors.
|
||||
:return: The new state list.
|
||||
"""
|
||||
class Rule:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def evolve_cell(self, cell: Cell, neighbours: list):
|
||||
pass
|
||||
|
@ -1,50 +1,66 @@
|
||||
import threading
|
||||
import time
|
||||
|
||||
from cellular_automaton.ca_cell import CACell
|
||||
from cellular_automaton.ca_grid import CAGrid
|
||||
from cellular_automaton.ca_grid import Grid
|
||||
from cellular_automaton.ca_rule import Rule
|
||||
|
||||
|
||||
class CellularAutomaton:
|
||||
def __init__(self, threads=1):
|
||||
assert threads > 0
|
||||
self._thread_count = threads
|
||||
def __init__(self, dimension: list, rule_: Rule=None, thread_count: int=4):
|
||||
self.grid = Grid(dimension)
|
||||
self._rule = rule_
|
||||
self._thread_count=thread_count
|
||||
|
||||
def evolve(self, grid, neighborhood, rule):
|
||||
range_ = int(len(grid) / self._thread_count)
|
||||
def set_rule(self, rule: Rule):
|
||||
self._rule = rule
|
||||
|
||||
def set_thread_count(self, thread_count: int):
|
||||
self._thread_count = thread_count
|
||||
|
||||
def evolve(self):
|
||||
cell_lists_for_threats = self.create_cell_lists_for_threads()
|
||||
threads = self._start_treads_to_evolve_grid(cell_lists_for_threats)
|
||||
self._wait_for_all_threads_to_finish(threads)
|
||||
|
||||
def create_cell_lists_for_threads(self):
|
||||
active_cells = self.grid.get_active_cells()
|
||||
cell_count_per_thread = int(len(active_cells) / self._thread_count)
|
||||
return self.divide_active_cells(cell_count_per_thread, active_cells)
|
||||
|
||||
@staticmethod
|
||||
def divide_active_cells(cell_count_per_thread, active_cells):
|
||||
return [active_cells[i:i + cell_count_per_thread]
|
||||
for i in range(0, len(active_cells), cell_count_per_thread)]
|
||||
|
||||
def _start_treads_to_evolve_grid(self, cell_lists_for_threats):
|
||||
threads = []
|
||||
for t in range(self._thread_count):
|
||||
new_thread = EvolutionThread(grid, neighborhood, rule, [t * range_, t * range_ + range_])
|
||||
new_thread = _EvolutionThread(self.grid, self._rule, cell_lists_for_threats[t])
|
||||
threads.append(new_thread)
|
||||
new_thread.start()
|
||||
return threads
|
||||
|
||||
new_grid_state = []
|
||||
@staticmethod
|
||||
def _wait_for_all_threads_to_finish(threads):
|
||||
for thread in threads:
|
||||
while not thread.is_finished():
|
||||
time.sleep(0.01)
|
||||
|
||||
new_grid_state.extend(thread.get_new_cell_states())
|
||||
thread.join()
|
||||
|
||||
return CAGrid(grid.get_dimensions(), new_grid_state)
|
||||
|
||||
|
||||
class EvolutionThread(threading.Thread):
|
||||
def __init__(self, grid, neighborhood, rule, range_):
|
||||
super(EvolutionThread, self).__init__()
|
||||
class _EvolutionThread(threading.Thread):
|
||||
def __init__(self, grid: Grid, rule: Rule, cell_list: list):
|
||||
super(_EvolutionThread, self).__init__()
|
||||
self._grid = grid
|
||||
self._neighborhood = neighborhood
|
||||
self._rule = rule
|
||||
self._range = range_
|
||||
self._cell_list = cell_list
|
||||
self._next_state = []
|
||||
self._finished = False
|
||||
|
||||
def run(self):
|
||||
for cell_id in range(*self._range):
|
||||
neighbors = self._grid.get_all_neighbour_cells(cell_id, self._neighborhood)
|
||||
cell = self._grid[cell_id]
|
||||
self._next_state.append(CACell(self._rule.evolve_cell(cell, neighbors)))
|
||||
for cell in self._cell_list:
|
||||
self._rule.evolve_cell(*self._grid.get_cell_and_neighbors(cell))
|
||||
self._finished = True
|
||||
|
||||
def get_new_cell_states(self):
|
||||
|
@ -1,90 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import tkinter
|
||||
|
||||
from cellular_automaton.cellular_automaton import CellularAutomaton
|
||||
from cellular_automaton.ca_neighberhood import Neighborhood
|
||||
from cellular_automaton.ca_rule import CARule
|
||||
from cellular_automaton.ca_grid import CAGrid
|
||||
from cellular_automaton.ca_cell import CACell
|
||||
|
||||
import datetime
|
||||
import pygame
|
||||
|
||||
UPDATE_RATE = 10
|
||||
|
||||
|
||||
class TkGUI:
|
||||
def __init__(self):
|
||||
self.root = tkinter.Tk()
|
||||
|
||||
self.canvas = tkinter.Canvas(self.root)
|
||||
self.canvas.pack(padx=5, pady=5)
|
||||
|
||||
self.ca = None
|
||||
self.current_state = None
|
||||
self.dimensions = None
|
||||
self.rule_ = None
|
||||
|
||||
self.grid_image = None
|
||||
|
||||
def run(self):
|
||||
self.root.after(10, self.update_state())
|
||||
self.root.mainloop()
|
||||
|
||||
def update_state(self):
|
||||
a = datetime.datetime.now()
|
||||
self.current_state = self.ca.evolve(self.current_state, Neighborhood.MOOR_2_X_2, self.rule_)
|
||||
b = datetime.datetime.now()
|
||||
self.draw_current_state()
|
||||
c = datetime.datetime.now()
|
||||
print(b-a)
|
||||
print(c-b)
|
||||
self.root.after(UPDATE_RATE, self.update_state)
|
||||
|
||||
def draw_current_state(self):
|
||||
for idx in range(self.dimensions[0]):
|
||||
for idy in range(self.dimensions[1]):
|
||||
cell = self.current_state[idy * self.dimensions[0] + idx]
|
||||
if cell[0] == 0:
|
||||
cell_color = "#ffffff"
|
||||
else:
|
||||
cell_color = "#444444"
|
||||
|
||||
self.grid_image.put(cell_color, (idx, idy))
|
||||
|
||||
def start(self, ca_, grid, dimensions, rule_):
|
||||
self.grid_image = tkinter.PhotoImage(width=dimensions[0], height=dimensions[1])
|
||||
self.ca = ca_
|
||||
self.current_state = grid
|
||||
self.dimensions = dimensions
|
||||
self.rule_ = rule_
|
||||
|
||||
# Clear the canvas (remove all shapes)
|
||||
self.canvas.delete(tkinter.ALL)
|
||||
|
||||
self.draw_current_state()
|
||||
self.canvas.create_image(self.dimensions, image=self.grid_image, state="normal")
|
||||
|
||||
# Draw the canvas
|
||||
self.draw_current_state()
|
||||
|
||||
|
||||
class TestRule(CARule):
|
||||
def evolve_cell(self, cell, neighbors):
|
||||
if neighbors[1][0] != 0:
|
||||
return [1]
|
||||
else:
|
||||
return [0]
|
||||
|
||||
#if __name__ == '__main__':
|
||||
# gui = TkGUI()
|
||||
# dim = [200, 500]
|
||||
# ca = CellularAutomaton(2)
|
||||
#
|
||||
# new_grid = CAGrid(dim)
|
||||
# new_grid.set_cell_by_coordinate([1, 1], CACell([1]))
|
||||
# rule = TestRule()
|
||||
# gui.start(ca, new_grid, dim, rule)##
|
||||
#
|
||||
# gui.run()
|
Loading…
Reference in New Issue
Block a user