Create proof-of-concept update for mute & chaos agents
parent
7b0f147a89
commit
b563c8422f
|
|
@ -8,7 +8,10 @@
|
|||
"""
|
||||
|
||||
from .agent import Agent
|
||||
from .chaos import AgentOfChaos
|
||||
from .mute import MuteAgent
|
||||
|
||||
__all__ = [
|
||||
"Agent"
|
||||
"Agent",
|
||||
"MuteAgent",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
|
@ -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={})
|
||||
Loading…
Reference in New Issue