Create proof-of-concept update for mute & chaos agents

sam/sneaky
Bram van den Heuvel 2026-06-23 23:45:33 +02:00
parent 7b0f147a89
commit b563c8422f
3 changed files with 113 additions and 1 deletions

View File

@ -8,7 +8,10 @@
"""
from .agent import Agent
from .chaos import AgentOfChaos
from .mute import MuteAgent
__all__ = [
"Agent"
"Agent",
"MuteAgent",
]

64
agents/chaos.py Normal file
View File

@ -0,0 +1,64 @@
"""
The agent of chaos is an agent that always attempts to return a random
response.
In most games, the Agent of chaos makes two considerations:
1. Which moves are valid? Since invalid moves fallback to "default" moves,
this can destabilize the probability distribution, making some moves
more likely to be chosen than others. As a result, we refrain from
"invalid" moves and take the effort to filter them out.
2. What's a reasonable probability distribution? Sometimes, a uniform
distribution across all options doesn't make a lot of sense. For
example, imagine asking the agent every turn whether they want to
use their super duper special single-use ability, and leaving that to
a 50/50 call every turn. It feels much more random if such an ability
is more randomly used throughout the GAME, than to have every choice
be a uniformly distributed decision.
"""
from __future__ import annotations
import random
from .agent import Agent, Payload
class AgentOfChaos(Agent):
"""
The agent of chaos always aims to deliver a random response.
"""
def __init__(self) -> None:
"""
Create a new instance of the agent of chaos.
"""
super().__init__(
name="Agent of chaos",
author="Bram",
version="1.0.1",
profile={
"me.noordstar.peanuts.is_ai": False,
},
)
self.add_tic_tac_toe(on_move=play_tic_tac_toe, profile={})
def play_tic_tac_toe(payload : Payload) -> Payload:
"""
In tic-tac-toe, the agent of chaos makes uniformly distributed choices
on unclaimed tiles.
:param payload: The incoming game state.
:type payload: dict[str, Any]
:return: The agent of chaos' random choice
:rtype: dict[str, Any]
"""
options = [
int(k)
for k, v in dict(payload).items()
if k in "0123456789" and v == ""
]
return { "move": random.choice(options) }

45
agents/mute.py Normal file
View File

@ -0,0 +1,45 @@
"""
The mute agent is a proof-of-concept agent of an agent that simply doesn't
respond - it always responds with an empty object.
This is the simplest agent to implement, and it can be used as a test to
make sure that the "default" move can be picked properly each turn.
"""
from __future__ import annotations
from .agent import Agent, Payload
def respond_mute(payload : Payload) -> Payload:
"""
Standard response from the mute. Returns an empty object, always.
:param payload: Incoming game state.
:type payload: dict[str, Any]
:return: The empty object.
:rtype: dict[str, Any]
"""
return {}
class MuteAgent(Agent):
"""
The mute agent class refuses to respond to any incoming game states,
and simply responds with an empty dictionary. For most games,
this means that the mute player takes the "default" option as a result
of not responding.
"""
def __init__(self) -> None:
"""
Create a new instance of the mute agent.
"""
super().__init__(
name="Mute",
author="Bram",
version="1.0.1",
profile={
"me.noordstar.peanuts.is_ai": False,
},
)
self.add_tic_tac_toe(on_move=respond_mute, profile={})