@@ -379,7 +379,7 @@ def connect_nodes(self) -> None:
379379 gene .from_node .output_connections .append (gene )
380380
381381 def fully_connect (self , innovation_history : list [History ]) -> None :
382- """Connects all nodes to each other."""
382+ """Connect all nodes to each other."""
383383 for inode in (self .nodes [i ] for i in range (self .inputs )):
384384 for onode in (
385385 self .nodes [len (self .nodes ) - ii - 2 ]
@@ -437,7 +437,7 @@ def get_node(self, node_no: int) -> Node:
437437 raise LookupError (f"Node with ID { node_no !r} does not exist!" )
438438
439439 def feed_forward (self , input_values : Iterable [float ]) -> tuple [float , ...]:
440- """Feeding in input values for the neural network and return output."""
440+ """Feed in input values for the neural network and return output."""
441441 # Set the outputs of the input nodes
442442 for idx , value in enumerate (input_values ):
443443 self .nodes [idx ].output_value = value
@@ -459,8 +459,8 @@ def feed_forward(self, input_values: Iterable[float]) -> tuple[float, ...]:
459459
460460 return tuple (outs [k ] for k in sorted (outs .keys ()))
461461
462- def gen_network (self ) -> None :
463- """Sets up the neural network as a list of nodes in order to be engaged."""
462+ def generate_network (self ) -> list [ Node ] :
463+ """Set up the neural network as a list of nodes in order to be engaged."""
464464 self .connect_nodes ()
465465 self .network = []
466466 # For each layer add the node in that layer,
@@ -472,6 +472,7 @@ def gen_network(self) -> None:
472472 if node .layer == layer :
473473 # Add that node to the network
474474 self .network .append (node )
475+ return self .network
475476
476477 def fully_connected (self ) -> bool :
477478 """Return whether the network is fully connected or not."""
@@ -508,7 +509,7 @@ def random_conn_nodes_bad(self, rn_1: int, rn_2: int) -> bool:
508509 return False
509510
510511 def add_conn (self , innovation_history : list [History ]) -> None :
511- """Adds a connection between two nodes which aren't currently connected."""
512+ """Add a new connection between two nodes that aren't currently connected."""
512513 # Cannot add a connection to a fully connected network
513514 if self .fully_connected ():
514515 print ("Connection failed." )
@@ -625,7 +626,7 @@ def mutate(self, innovation_history: list[History]) -> None:
625626 return
626627
627628 def crossover (self , parent : Genome ) -> Genome :
628- """Called when this genome is better than other parent ."""
629+ """Return new genome by combining this genome with another ."""
629630 child = self .__class__ (int (self .inputs ), int (self .outputs ), True )
630631 child .genes = []
631632 child .nodes = []
@@ -682,7 +683,7 @@ def crossover(self, parent: Genome) -> Genome:
682683 return child
683684
684685 def print_geneome (self ) -> None :
685- """Prints out information about genome."""
686+ """Print out information about genome."""
686687 print ("Private genome layers:" , self .layers )
687688 print ("Bias node:" , self .bias_node )
688689 print ("Nodes:" )
@@ -765,8 +766,8 @@ def load(cls, data: GenomeSave) -> Genome:
765766 for gene , enabled in tmpgenes :
766767 gene .enabled = bool (enabled )
767768 self .genes .append (gene )
768- # self.connect_nodes() already called in gen_network
769- self .gen_network ()
769+ # self.connect_nodes() already called in generate_network
770+ self .generate_network ()
770771 return self
771772
772773
@@ -782,7 +783,6 @@ def __init__(self) -> None:
782783 """Initialize BasePlayer."""
783784 self .fitness = 0.0
784785 self .vision : list [float ] = [] # The input array for the neural network
785- self .decision : tuple [float , ...] # The output of the neural network
786786 self .unadjusted_fitness = 0
787787 self .lifespan = 0 # How long the player lived for fitness
788788 self .best_score = 0.0 # Stores the score achieved used for replay
@@ -798,14 +798,14 @@ def __init__(self) -> None:
798798 self .brain : Genome
799799 self .start ()
800800
801- def start (self ) -> None :
802- """Called during initialization to setup self. brain."""
803- self . brain = Genome (self .genome_inputs , self .genome_outputs )
801+ def start (self ) -> Genome :
802+ """Return new brain."""
803+ return Genome (self .genome_inputs , self .genome_outputs )
804804
805- def update (self ) -> None :
805+ def update (self , decision : tuple [ float , ...] ) -> None :
806806 """Move the player according to the outputs from the neural network."""
807- ## print(self. decision)
808- ## do = self. decision.index(max(self.decision))
807+ # print(decision)
808+ # do = decision.index(max(self.decision))
809809 return
810810
811811 def look (self ) -> None :
@@ -814,31 +814,31 @@ def look(self) -> None:
814814 random .random () * 2 - 1 for _ in range (self .genome_inputs )
815815 ]
816816
817- def think (self ) -> None :
818- """Use outputs from neural network."""
819- self . decision = self .brain .feed_forward (self .vision )
817+ def think (self ) -> tuple [ float , ...] :
818+ """Return decision from nural network."""
819+ return self .brain .feed_forward (self .vision )
820820
821821 def clone (self ) -> BasePlayer :
822822 """Return a clone of self."""
823823 clone = self .__class__ ()
824824 clone .brain = self .brain .clone ()
825825 clone .fitness = float (self .fitness )
826- clone .brain .gen_network ()
826+ clone .brain .generate_network ()
827827 clone .gen = int (self .gen )
828828 clone .best_score = float (self .score )
829829 return clone
830830
831831 clone_for_replay = clone
832832
833833 def calculate_fitness (self ) -> None :
834- """Calculates the fitness of the AI."""
834+ """Calculate the fitness of the AI."""
835835 self .fitness = random .randint (0 , 10 )
836836
837837 def crossover (self , parent : BasePlayer ) -> BasePlayer :
838838 """Return a BasePlayer object by crossing over our brain and parent2's brain."""
839839 child = self .__class__ ()
840840 child .brain = self .brain .crossover (parent .brain )
841- child .brain .gen_network ()
841+ child .brain .generate_network ()
842842 return child
843843
844844 def save (self ) -> PlayerSave :
@@ -951,7 +951,7 @@ def same_species(self, genome: Genome) -> bool:
951951 return self .compat_threshold > compatibility
952952
953953 def add_to_species (self , player : BasePlayer ) -> None :
954- """Adds player to this species."""
954+ """Add given player to this species."""
955955 self .players .append (player )
956956
957957 def sort_species (self ) -> None :
@@ -994,7 +994,7 @@ def fitness_sharing(self) -> None:
994994 player .fitness /= len (self .players )
995995
996996 def select_player (self ) -> BasePlayer :
997- """Selects a player based on it's fitness."""
997+ """Select a player based on it's fitness."""
998998 if len (self .players ) == 0 :
999999 raise RuntimeError ("No players!" )
10001000 fitness_sum = math .floor (
@@ -1111,19 +1111,21 @@ def __init__(self, size: int, add_players: bool = True) -> None:
11111111 for _ in range (size ):
11121112 self .players .append (self .player ())
11131113 self .players [- 1 ].brain .mutate (self .innovation_history )
1114- self .players [- 1 ].brain .gen_network ()
1114+ self .players [- 1 ].brain .generate_network ()
11151115
11161116 def __repr__ (self ) -> str :
11171117 """Representation of Population."""
11181118 return f"<Population Object with { len (self .players )} Players and { self .gen } Generations>"
11191119
11201120 def update_alive (self ) -> None :
1121- """Updates all of the players that are alive."""
1121+ """Update all of the players that are alive."""
11221122 for player in list (self .players ):
11231123 if not player .dead :
11241124 player .look () # Get inputs for brain
1125- player .think () # Use outputs from neural network
1126- player .update () # Move the player according to the outputs from the neural network
1125+ decision = player .think () # outputs from neural network
1126+ player .update (
1127+ decision ,
1128+ ) # Move the player according to the outputs from the neural network
11271129 if player .score > self .global_best_score :
11281130 self .global_best_score = player .score
11291131
@@ -1132,7 +1134,7 @@ def done(self) -> bool:
11321134 return all (player .dead for player in self .players )
11331135
11341136 def setbest_player (self ) -> None :
1135- """Sets the best player globally and for current generation."""
1137+ """Set the best player globally and for current generation."""
11361138 if not (self .species and self .species [0 ].players ):
11371139 return
11381140 temp_best = self .species [0 ].players [0 ]
@@ -1278,7 +1280,7 @@ def natural_selection(self) -> None:
12781280 self .players = children
12791281 self .gen += 1
12801282 for player in self .players :
1281- player .brain .gen_network ()
1283+ player .brain .generate_network ()
12821284
12831285 def player_in_batch (self , player : BasePlayer , worlds : list [World ]) -> bool :
12841286 """Return True if a player is in worlds...???."""
@@ -1294,9 +1296,11 @@ def update_alive_in_batches(self, worlds: list[World]) -> None:
12941296 for player in list (self .players ):
12951297 if self .player_in_batch (player , worlds ) and not player .dead :
12961298 alive += 1
1297- player .look ()
1298- player .think ()
1299- player .update ()
1299+ player .look () # Get inputs for brain
1300+ decision = player .think () # outputs from neural network
1301+ player .update (
1302+ decision ,
1303+ ) # Move the player according to the outputs from the neural network
13001304 if player .score > self .global_best_score :
13011305 self .global_best_score = player .score
13021306
0 commit comments