diff --git a/src/ai/__init__.py b/src/ai/__init__.py index 38f89c2..19c9b57 100644 --- a/src/ai/__init__.py +++ b/src/ai/__init__.py @@ -1,4 +1,5 @@ +from .config import get_config from .io import read_genome from .training import train -__all__ = ["train", "read_genome"] +__all__ = ["train", "read_genome", "get_config"] diff --git a/src/ai/evaluation.py b/src/ai/evaluation.py index 7aa64a1..e128ad7 100644 --- a/src/ai/evaluation.py +++ b/src/ai/evaluation.py @@ -39,15 +39,18 @@ def eval_genomes(genomes, config: neat.Config): time_passed = time.perf_counter() - start_time score = app.game.board.score - if ( - app.game.board.is_game_over() - or (app.game.board._is_full() and time_passed >= 0.1) - or max_val >= 2048 - ): + if max_val >= 32: calculate_fitness(genome, max_val) logger.info(f"{max_val=}\t{score=:_}\t{genome_id=}") app.game.restart() break + elif app.game.board.is_game_over() or ( + app.game.board._is_full() and time_passed >= 0.1 + ): + calculate_fitness(genome, -max_val) + logger.info(f"{max_val=}\t{score=:_}\t{genome_id=}") + app.game.restart() + break def calculate_fitness(genome: neat.DefaultGenome, score: int): diff --git a/src/ai/io.py b/src/ai/io.py index e858dde..d5c7a45 100644 --- a/src/ai/io.py +++ b/src/ai/io.py @@ -5,11 +5,11 @@ import neat from path import BASE_PATH -def read_genome(filename: Path) -> neat.DefaultGenome: - with open(filename, "rb") as f: +def read_genome() -> neat.DefaultGenome: + with open(BASE_PATH / "best_genome", "rb") as f: return pickle.load(f) -def save_genome(genome, filename: Path) -> None: - with open(filename, "wb") as f: +def save_genome(genome) -> None: + with open(BASE_PATH / "best_genome", "wb") as f: pickle.dump(genome, f) diff --git a/src/py2048/screens/game.py b/src/py2048/screens/game.py index f721c73..54d0e9b 100644 --- a/src/py2048/screens/game.py +++ b/src/py2048/screens/game.py @@ -1,3 +1,4 @@ +import neat import pygame from loguru import logger diff --git a/src/py2048/screens/menu.py b/src/py2048/screens/menu.py index 7cc1348..5fd664c 100644 --- a/src/py2048/screens/menu.py +++ b/src/py2048/screens/menu.py @@ -1,7 +1,9 @@ import sys +from pathlib import Path import neat import pygame +from ai import get_config, read_genome from loguru import logger from py2048 import Config @@ -68,7 +70,8 @@ class Menu: if self._game_active: self.game.draw(self._surface) elif self._ai_active: - pass + self._ai_move() + self.game.draw(self._surface) elif self._setting_active: pass else: @@ -99,6 +102,28 @@ class Menu: def ai(self) -> None: logger.debug("AI") + self._ai_active = True + self.game = Game() + self.network = neat.nn.FeedForwardNetwork.create(read_genome(), get_config()) + + def _ai_move(self) -> None: + decisions = { + 0: self.game.move_up, + 1: self.game.move_down, + 2: self.game.move_left, + 3: self.game.move_right, + } + + output = self.network.activate( + ( + *self.game.board.matrix(), + self.game.board.score, + ) + ) + decision = output.index(max(output)) + + decisions[decision]() + def settings(self) -> None: logger.debug("Settings")