feat(game, AI): add option with AI play

This commit is contained in:
Kristofers Solo 2024-01-03 05:24:37 +02:00
parent 5cd4a6d0ae
commit b10c90cbdf
5 changed files with 41 additions and 11 deletions

View File

@ -1,4 +1,5 @@
from .config import get_config
from .io import read_genome from .io import read_genome
from .training import train from .training import train
__all__ = ["train", "read_genome"] __all__ = ["train", "read_genome", "get_config"]

View File

@ -39,15 +39,18 @@ def eval_genomes(genomes, config: neat.Config):
time_passed = time.perf_counter() - start_time time_passed = time.perf_counter() - start_time
score = app.game.board.score score = app.game.board.score
if ( if max_val >= 32:
app.game.board.is_game_over()
or (app.game.board._is_full() and time_passed >= 0.1)
or max_val >= 2048
):
calculate_fitness(genome, max_val) calculate_fitness(genome, max_val)
logger.info(f"{max_val=}\t{score=:_}\t{genome_id=}") logger.info(f"{max_val=}\t{score=:_}\t{genome_id=}")
app.game.restart() app.game.restart()
break 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): def calculate_fitness(genome: neat.DefaultGenome, score: int):

View File

@ -5,11 +5,11 @@ import neat
from path import BASE_PATH from path import BASE_PATH
def read_genome(filename: Path) -> neat.DefaultGenome: def read_genome() -> neat.DefaultGenome:
with open(filename, "rb") as f: with open(BASE_PATH / "best_genome", "rb") as f:
return pickle.load(f) return pickle.load(f)
def save_genome(genome, filename: Path) -> None: def save_genome(genome) -> None:
with open(filename, "wb") as f: with open(BASE_PATH / "best_genome", "wb") as f:
pickle.dump(genome, f) pickle.dump(genome, f)

View File

@ -1,3 +1,4 @@
import neat
import pygame import pygame
from loguru import logger from loguru import logger

View File

@ -1,7 +1,9 @@
import sys import sys
from pathlib import Path
import neat import neat
import pygame import pygame
from ai import get_config, read_genome
from loguru import logger from loguru import logger
from py2048 import Config from py2048 import Config
@ -68,7 +70,8 @@ class Menu:
if self._game_active: if self._game_active:
self.game.draw(self._surface) self.game.draw(self._surface)
elif self._ai_active: elif self._ai_active:
pass self._ai_move()
self.game.draw(self._surface)
elif self._setting_active: elif self._setting_active:
pass pass
else: else:
@ -99,6 +102,28 @@ class Menu:
def ai(self) -> None: def ai(self) -> None:
logger.debug("AI") 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: def settings(self) -> None:
logger.debug("Settings") logger.debug("Settings")