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 .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
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):

View File

@ -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)

View File

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

View File

@ -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")