Reputation: 139
I trained a neural network for playing TicTacToe. Now i want to play against it. In the training sessions i use this code
output = neat.nn.FeedForwardNetwork.create(genome, config).activate(input)
How can i play vs a chosen genome? I tried this:
output = genome.activate(input)
Result AttributeError: 'DefaultGenome' object has no attribute 'activate'
code: (the error occures in def game())
import neat
import pygame
import os
import json
import random
import checkpoint
import winsound
import time
import matplotlib.pyplot as plt
pygame.init()
shown = True
cloud = checkpoint.Checkpointer()
GEN = 0
if shown:
screen = pygame.display.set_mode((300, 300))
pygame.display.set_caption("Tic Tac Toe")
o_icon = pygame.image.load("o.png")
x_icon = pygame.image.load("x.png")
class Field:
def __init__(self, c_shown):
self.field = [0,0,0, 0,0,0, 0,0,0]
self.shown = c_shown
self.winner = None
def reset(self):
self.field = [0,0,0, 0,0,0, 0,0,0]
self.winner = None
def display(self):
screen.fill([0,0,0])
self.display_pieces()
self.display_board()
pygame.display.update()
def display_pieces(self):
pos_to_pix = {
0: (0,0),
1: (100,0),
2: (200,0),
3: (0,100),
4: (100,100),
5: (200,100),
6: (0, 200),
7: (100, 200),
8: (200, 200)
}
for pos in range(len(self.field)):
if self.field[pos] == 1:
screen.blit(o_icon, pos_to_pix[pos])
elif self.field[pos] == 2:
screen.blit(x_icon, pos_to_pix[pos])
@staticmethod
def pos_to_field(pos):
x = pos[0]
y = pos[1]
if x < 100:
x = 0
elif x < 200:
x = 1
else:
x = 2
if y < 100:
y = 0
elif y < 200:
y = 1
else:
y = 2
return x+y*3
@staticmethod
def display_board():
pygame.draw.rect(screen, "White", [0,99, 300,2])
pygame.draw.rect(screen, "White", [0,199, 300,2])
pygame.draw.rect(screen, "White", [99,0, 2,300])
pygame.draw.rect(screen, "White", [199,0, 2,300])
def action(self, field_id, player_id):
self.field[field_id] = player_id
def field_is_free(self, field):
if self.field[field] == 0:
return True
return False
def check_winner(self):
for line in range(3):
# check horizontal
if self.field[line*3] == self.field[line*3+1] == self.field[line*3+2] != 0:
self.winner = self.field[line]
return True, self.winner
if self.field[line] == self.field[line+3] == self.field[line+6] != 0:
self.winner = self.field[line]
return True, self.winner
if self.field[0] == self.field[4] == self.field[8] != 0 or self.field[2] == self.field[4] == self.field[6] != 0:
self.winner = self.field[0]
return True, self.winner
return False
def first_free(self):
for index, value in enumerate(self.field):
if value == 0:
return index
class Player:
def __init__(self, id, being):
self.id = id
self.being = being
class Graph:
def __init__(self):
self.gens = []
self.maxs = []
self.losts = []
self.drawns = []
self.wons = []
self.average = []
self.last_gens = 20
self.vmax = None
def add(self, gen, vmax_round, losts, drawns, wons):
self.gens.append(gen)
self.maxs.append(vmax_round)
self.losts.append(losts)
self.drawns.append(drawns)
self.wons.append(wons)
self.average.append(sum(self.maxs[-self.last_gens:]) / self.last_gens)
self.vmax = max(self.maxs)
def display(self):
plt.figure(figsize=(10,6))
plt.plot(self.gens, self.maxs, label="Best Fitness")
plt.plot(self.gens, self.average, label="Average Fitness last " + str(self.last_gens) + " generations")
plt.plot(self.gens, self.losts, label="Lost")
plt.plot(self.gens, self.drawns, label="Drawn")
plt.plot(self.gens, self.wons, label="Won")
plt.legend(bbox_to_anchor=(1.05, 1), loc="upper left")
plt.grid("on")
plt.tight_layout()
plt.show()
def save(self):
with open('gens.txt', 'w') as filehandle:
json.dump(self.gens, filehandle)
with open('maxs.txt', 'w') as filehandle:
json.dump(self.maxs, filehandle)
with open('average.txt', 'w') as filehandle:
json.dump(self.average, filehandle)
with open('losts.txt', 'w') as filehandle:
json.dump(self.losts, filehandle)
with open('drawns.txt', 'w') as filehandle:
json.dump(self.drawns, filehandle)
with open('wons.txt', 'w') as filehandle:
json.dump(self.wons, filehandle)
def load(self):
with open('gens.txt', 'r') as filehandle:
self.gens = json.load(filehandle)
with open('maxs.txt', 'r') as filehandle:
self.maxs = json.load(filehandle)
with open('average.txt', 'r') as filehandle:
self.average = json.load(filehandle)
with open('losts.txt', 'r') as filehandle:
self.losts = json.load(filehandle)
with open('drawns.txt', 'r') as filehandle:
self.drawns = json.load(filehandle)
with open('wons.txt', 'r') as filehandle:
self.wons = json.load(filehandle)
graph = Graph()
board = Field(shown)
players = [Player(1, "random"), None]
def place_piece(player, field):
board.field[field] = player.id
def sound():
winsound.Beep(440,100)
def main(genomes, config):
global GEN
GEN += 1
best_fitness = 0
for index, genome in genomes:
index -= 1
genome.fitness = 0
net = neat.nn.FeedForwardNetwork.create(genome, config)
players[1] = Player(2, "ai")
player = players[0]
lost, drawn, won = 0,0,0
for round in range(100):
field_to_go = -1
placed = 0
while True:
if player.being == "random" or player.being == "ai":
field_to_go = random.randint(0,8)
elif player.being == "ai":
output = net.activate(board.field)
field_to_go = output.index(max(output))
elif player.being == "human":
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
break
elif event.type == pygame.MOUSEBUTTONUP:
field_to_go = board.pos_to_field(pygame.mouse.get_pos())
if field_to_go > -1:
if board.field_is_free(field_to_go):
board.action(field_to_go, player.id)
else:
board.action(board.first_free(), player.id)
if player == players[0]:
player = players[1]
else:
player = players[0]
placed += 1
if shown:
board.display()
if board.check_winner() or placed == 9:
if board.winner == 1:
genome.fitness += 0
lost += 1
elif board.winner is None:
genome.fitness += 1
drawn += 1
else:
genome.fitness += 2
won += 1
board.reset()
break
if genome.fitness > best_fitness:
best_fitness = genome.fitness
best_lost = lost
best_drawn = drawn
best_won = won
graph.add(GEN, best_fitness, best_lost, best_drawn, best_won)
def game(genome):
running = True
while running:
placed = 0
players[0] = Player(1, "human")
players[1] = Player(2, "ai")
player = players[0]
while True:
field_to_go = -1
if player.being == "random":
field_to_go = random.randint(0, 8)
elif player.being == "ai":
output = genome.activate(board.field)
field_to_go = output.index(max(output))
elif player.being == "human":
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
break
elif event.type == pygame.MOUSEBUTTONUP:
field_to_go = board.pos_to_field(pygame.mouse.get_pos())
if field_to_go > -1:
if board.field_is_free(field_to_go):
board.action(field_to_go, player.id)
else:
board.action(board.first_free(), player.id)
if player == players[0]:
player = players[1]
else:
player = players[0]
placed += 1
board.display()
if board.check_winner() or placed == 9:
board.reset()
break
def run(config_path):
global shown
global GEN
config = neat.config.Config(neat.DefaultGenome, neat.DefaultReproduction,
neat.DefaultSpeciesSet, neat.DefaultStagnation, config_path)
nc_name = "population"
shown = False
new = True
sound()
while GEN < 50:
if new:
p = neat.Population(config)
p.add_reporter(neat.StdOutReporter(True))
p.add_reporter(neat.StatisticsReporter())
else:
p = cloud.restore_checkpoint(nc_name).population
graph.load()
GEN = p.generation
p.run(main, 10)
cloud.save_checkpoint(config, p, p.species, GEN, nc_name)
graph.save()
if new:
new = False
graph.save()
graph.display()
game(cloud.restore_checkpoint("population").population.best_genome)
if __name__ == "__main__":
local_dir = os.path.dirname(__file__)
config_path = os.path.join(local_dir, "config_feedforward")
run(config_path)
Upvotes: 1
Views: 216