Skip to content

Commit b5abfd8

Browse files
committed
Get rid of statefull functions (change to return state) and remove unused attributes.
1 parent e672366 commit b5abfd8

File tree

1 file changed

+35
-35
lines changed

1 file changed

+35
-35
lines changed

src/neat/neat.py

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -782,9 +782,7 @@ class BasePlayer:
782782
def __init__(self) -> None:
783783
"""Initialize BasePlayer."""
784784
self.fitness = 0.0
785-
self.vision: list[float] = [] # The input array for the neural network
786785
self.unadjusted_fitness = 0
787-
self.lifespan = 0 # How long the player lived for fitness
788786
self.best_score = 0.0 # Stores the score achieved used for replay
789787
self.dead = False
790788
self.score = 0.0
@@ -802,22 +800,20 @@ def start(self) -> Genome:
802800
"""Return new brain."""
803801
return Genome(self.genome_inputs, self.genome_outputs)
804802

805-
def update(self, decision: tuple[float, ...]) -> None:
803+
def look(self) -> Iterable[float]:
804+
"""Return inputs for the nural network."""
805+
return (random.random() * 2 - 1 for _ in range(self.genome_inputs))
806+
807+
def think(self, inputs: Iterable[float]) -> Iterable[float]:
808+
"""Return decision from nural network."""
809+
return self.brain.feed_forward(inputs)
810+
811+
def update(self, decision: Iterable[float]) -> None:
806812
"""Move the player according to the outputs from the neural network."""
807813
# print(decision)
808814
# do = decision.index(max(self.decision))
809815
return
810816

811-
def look(self) -> None:
812-
"""Get inputs for brain."""
813-
self.vision = [
814-
random.random() * 2 - 1 for _ in range(self.genome_inputs)
815-
]
816-
817-
def think(self) -> tuple[float, ...]:
818-
"""Return decision from nural network."""
819-
return self.brain.feed_forward(self.vision)
820-
821817
def clone(self) -> BasePlayer:
822818
"""Return a clone of self."""
823819
clone = self.__class__()
@@ -828,11 +824,9 @@ def clone(self) -> BasePlayer:
828824
clone.best_score = float(self.score)
829825
return clone
830826

831-
clone_for_replay = clone
832-
833-
def calculate_fitness(self) -> None:
827+
def calculate_fitness(self) -> float:
834828
"""Calculate the fitness of the AI."""
835-
self.fitness = random.randint(0, 10)
829+
return random.randint(0, 10)
836830

837831
def crossover(self, parent: BasePlayer) -> BasePlayer:
838832
"""Return a BasePlayer object by crossing over our brain and parent2's brain."""
@@ -904,7 +898,7 @@ def __init__(self, player: BasePlayer | None = None) -> None:
904898
# Since it is the only one in the species it is by default the best
905899
self.best_fitness = player.fitness
906900
self.rep = player.brain.clone()
907-
self.champ = player.clone_for_replay()
901+
self.champ = player.clone()
908902

909903
def __repr__(self) -> str:
910904
"""Return what this object should be represented by in the python interpreter."""
@@ -975,7 +969,7 @@ def sort_species(self) -> None:
975969
if self.players[0].fitness > self.best_fitness:
976970
self.staleness = 0
977971
self.best_fitness = self.players[0].fitness
978-
# self.rep = self.players[0].clone_for_replay()
972+
# self.rep = self.players[0].clone()
979973
self.rep = self.players[0].brain.clone()
980974
else: # If no new best player,
981975
self.staleness += 1
@@ -1121,27 +1115,30 @@ def update_alive(self) -> None:
11211115
"""Update all of the players that are alive."""
11221116
for player in list(self.players):
11231117
if not player.dead:
1124-
player.look() # Get inputs for brain
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
1118+
# Get inputs for nural network
1119+
inputs = player.look()
1120+
# Get nural network's decision (output) from inputs
1121+
decision = player.think(inputs)
1122+
# Move the player according to the outputs from the
1123+
# neural network
1124+
player.update(decision)
1125+
# Update max score
11291126
if player.score > self.global_best_score:
11301127
self.global_best_score = player.score
11311128

11321129
def done(self) -> bool:
11331130
"""Return True if all the players are dead. :(."""
11341131
return all(player.dead for player in self.players)
11351132

1136-
def setbest_player(self) -> None:
1133+
def set_best_player(self) -> None:
11371134
"""Set the best player globally and for current generation."""
11381135
if not (self.species and self.species[0].players):
11391136
return
11401137
temp_best = self.species[0].players[0]
11411138
temp_best.gen = self.gen
11421139

11431140
if temp_best.score >= self.best_score:
1144-
best_clone = temp_best.clone_for_replay()
1141+
best_clone = temp_best.clone()
11451142
self.gen_players.append(best_clone)
11461143
# print stuff was here, removed
11471144
self.best_score = temp_best.score
@@ -1169,10 +1166,10 @@ def separate(self) -> None:
11691166
if not species_found:
11701167
self.species.append(Species(player))
11711168

1172-
def calculate_fitness(self) -> None:
1169+
def calculate_fitnesses(self) -> None:
11731170
"""Calculate the fitness of each player."""
11741171
for player in self.players:
1175-
player.calculate_fitness()
1172+
player.fitness = player.calculate_fitness()
11761173

11771174
def sort_species(self) -> None:
11781175
"""Sort the species to be ranked in fitness order, best first."""
@@ -1235,7 +1232,7 @@ def natural_selection(self) -> None:
12351232
# Separate players into species
12361233
self.separate()
12371234
# Calculate the fitness of each player
1238-
self.calculate_fitness()
1235+
self.calculate_fitnesses()
12391236
# Sort the species to be ranked in fitness order, best first
12401237
self.sort_species()
12411238
if self.mass_extinction_event:
@@ -1244,7 +1241,7 @@ def natural_selection(self) -> None:
12441241
# Kill off the bottom half of each species
12451242
self.cull_species()
12461243
# Save the best player of this generation
1247-
self.setbest_player()
1244+
self.set_best_player()
12481245
# Remove species which haven't improved in 15 generations
12491246
self.kill_stale_species()
12501247
# Kill species which are super bad
@@ -1296,11 +1293,14 @@ def update_alive_in_batches(self, worlds: list[World]) -> None:
12961293
for player in list(self.players):
12971294
if self.player_in_batch(player, worlds) and not player.dead:
12981295
alive += 1
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
1296+
# Get inputs for nural network
1297+
inputs = player.look()
1298+
# Get nural network's decision (output) from inputs
1299+
decision = player.think(inputs)
1300+
# Move the player according to the outputs from the
1301+
# neural network
1302+
player.update(decision)
1303+
# Update max score
13041304
if player.score > self.global_best_score:
13051305
self.global_best_score = player.score
13061306

0 commit comments

Comments
 (0)