Compare commits

..

2 Commits

5 changed files with 126 additions and 3 deletions

View File

@ -10,11 +10,9 @@
from .agent import Agent from .agent import Agent
from .chaos import AgentOfChaos from .chaos import AgentOfChaos
from .mute import MuteAgent from .mute import MuteAgent
from .remote import RemoteAgent
__all__ = [ __all__ = [
"Agent", "Agent",
"AgentOfChaos", "AgentOfChaos",
"MuteAgent", "MuteAgent",
"RemoteAgent",
] ]

View File

@ -0,0 +1,117 @@
"""
The naive line counter aims to calculate the best move by comparing the
lines and checking how many are filled.
"""
from __future__ import annotations
import random
from .agent import Agent, Payload
class NaiveLineCounter(Agent):
"""
Tic-tac-toe has 8 possible lines where you can get 3 in a row.
For all 8 lines, count how many would benefit from the addition of a
single sign. In priority, count how many lines are added.
"""
def __init__(self) -> None:
super().__init__(
name="Naive line counter",
author="Bram",
version="1.0.0",
profile={},
)
self.add_tic_tac_toe(on_move=self.play_tic_tac_toe, profile={})
def play_tic_tac_toe(self, payload : Payload) -> Payload:
"""
For each line:
[X][X][_] -> 3 in a row
[O][O][_] -> ruin an opponent's 3 in a row
[X][_][ ] -> 2 in a row
[O][_][ ] -> ruin an opponent's 2 in a row
[_][ ][ ] -> 1 in a row
Count how many they occur, then sort based on priority.
"""
lines = [
[ 1, 2, 3, ],
[ 4, 5, 6, ],
[ 7, 8, 9, ],
[ 1, 4, 7, ],
[ 2, 5, 8, ],
[ 3, 6, 9, ],
[ 1, 5, 9, ],
[ 3, 5, 7, ],
]
my_piece = payload["your_token"]
moves, value = [], ( 0, 0, 0, 0, 0 )
for i in range(1, 10):
i_val = field_score(payload=payload, field=i, my_piece=my_piece)
if i_val > value:
moves, value = [i], i_val
elif i_val == value:
moves.append(i)
return dict(move=random.choice(moves))
def field_score(payload : Payload, field : int, my_piece : str) -> tuple[int, int, int, int, int]:
"""
Determine the score of a specific field in the grid.
"""
a, b, c, d, e = 0, 0, 0, 0, 0
lines = [
[ 1, 2, 3, ],
[ 4, 5, 6, ],
[ 7, 8, 9, ],
[ 1, 4, 7, ],
[ 2, 5, 8, ],
[ 3, 6, 9, ],
[ 1, 5, 9, ],
[ 3, 5, 7, ],
]
if payload[str(field)] != "":
return ( a, b, c, d, e )
for line in lines:
if field not in line:
continue
values = [ payload[str(f)] for f in line if field != f ]
x = values.count("X")
o = values.count("O")
s = ( x, o ) if my_piece == "X" else ( o, x )
match s:
case ( 2, 0 ):
a += 1
case ( 0, 2 ):
b += 1
case ( 1, 0 ):
c += 1
case ( 0, 1 ):
d += 1
case ( 0, 0 ):
e += 1
case ( 1, 1 ):
pass
case _:
raise ValueError(
f"Unknown number of items: {s}"
)
return ( a, b, c, d, e )

View File

@ -19,7 +19,10 @@ RUN pip install --no-cache-dir --no-index --find-links=/wheels \
-r requirements-pyserver.txt && rm -rf /wheels -r requirements-pyserver.txt && rm -rf /wheels
# Install PyServer code # Install PyServer code
COPY agents/ agents/
COPY pyserver/ pyserver/ COPY pyserver/ pyserver/
COPY server.py . COPY server.py .
ENV CONTAINERIZED=1
CMD ["python", "server.py"] CMD ["python", "server.py"]

View File

@ -2,6 +2,8 @@
from __future__ import annotations from __future__ import annotations
import os
from flask import Flask, jsonify, request from flask import Flask, jsonify, request
from agents import Agent from agents import Agent
from typing import Any from typing import Any
@ -24,6 +26,7 @@ class PyServer:
:param import_name: Flask application import name :param import_name: Flask application import name
:type import_name: str :type import_name: str
""" """
self.containerized : bool = bool(int(os.environ.get("CONTAINERIZED", "0")))
self.agent = agent self.agent = agent
self.app = Flask(import_name) self.app = Flask(import_name)
@ -49,6 +52,7 @@ class PyServer:
d = { **self.agent.profile, **d } d = { **self.agent.profile, **d }
d["me.noordstar.peanuts.containerized"] = self.containerized
d["games"] = {} d["games"] = {}
for game, (profile, _) in self.agent.registered_games.items(): for game, (profile, _) in self.agent.registered_games.items():
d["games"][game] = profile d["games"][game] = profile

View File

@ -6,6 +6,7 @@ from __future__ import annotations
import agents import agents
from agents.naive_line_counter import NaiveLineCounter
from pyserver import PyServer from pyserver import PyServer
def main() -> int: def main() -> int:
@ -15,7 +16,7 @@ def main() -> int:
:return: Exit code :return: Exit code
:rtype: int :rtype: int
""" """
player = PyServer(agents.RemoteAgent(url="https://bmt001.noordstar.me/")) player = PyServer(NaiveLineCounter())
# Start listening for games # Start listening for games
player.start( player.start(