Implement Agent of Chaos reference for tic-tac-toe

bram/agent-of-chaos
Bram van den Heuvel 2026-06-19 14:51:39 +02:00
parent eb5a869cf4
commit 2abf07564c
1 changed files with 32 additions and 60 deletions

View File

@ -1,5 +1,21 @@
""" """
This module enables a user to host a server that is able to play games. This implementation describes the Agent of chaos. This agent mostly uses
randomness to determine which action to take.
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 from __future__ import annotations
@ -17,22 +33,18 @@ def main() -> int:
:rtype: int :rtype: int
""" """
player = PyServer( player = PyServer(
# Customize this to whatever you'd like to call your player name="Agent of chaos",
name="My super smart robot player", profile={
"me.noordstar.peanuts.author": "Bram",
# Custom information that you can use to tell people about this player "me.noordstar.peanuts.containerized": True,
profile={}, },
# Unless you know what you're doing, don't touch this.
import_name=__name__, import_name=__name__,
) )
# Register games! Comment out any you don't want your player to play.
player.add_tic_tac_toe(on_move=play_tic_tac_toe, profile={}) player.add_tic_tac_toe(on_move=play_tic_tac_toe, profile={})
# Start listening for games
player.start( player.start(
host="0.0.0.0", # Comment out when using only locally host="0.0.0.0",
port=5000, port=5000,
) )
@ -40,59 +52,19 @@ def main() -> int:
def play_tic_tac_toe(payload : dict[str, Any]) -> dict[str, Any]: def play_tic_tac_toe(payload : dict[str, Any]) -> dict[str, Any]:
""" """
Play a game of tic-tac-toe. In tic-tac-toe, the agent of chaos makes uniformly distributed choices
on unclaimed tiles.
You receive a payload that looks like this: :param payload: The incoming game state.
{
"1": "X", "2": "", "3": "O",
"4": "X", "5": "O", "6": "",
"7": "", "8": "", "9": "",
"your_token": "X"
}
And you're expected to return a response of which field you'd like to
place your piece in. For example, if you wish to place your token in
field 7, your response should look like this:
{ "move": 7 }
The board is arranged as follows:
1 | 2 | 3
---+---+---
4 | 5 | 6
---+---+---
7 | 8 | 9
:param payload: The incoming JSON that contains the game state.
:type payload: dict[str, Any] :type payload: dict[str, Any]
:return: The move you wish to take. :return: The agent of chaos' random choice
:rtype: dict[str, Any] :rtype: dict[str, Any]
""" """
options = [
# Try printing the payload to see what it looks like! int(k)
print(payload) for k, v in dict(payload).items()
if k in "0123456789" and v == ""
options = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, ] ]
# 1. Try filtering out the impossible moves!
# If an X or O was already placed at a field, remove it from the options
#
# 2. Try finding two in a row! If possible, you can try to place the third
# item on the board and get 3 in a row.
#
# 3. Perhaps you can block the opponent from getting 3 in a row?
#
# Now, pick any of the remaining options.
# This is just a simple implementation. Naturally, you're welcome to try
# your own logic.
return { "move": random.choice(options) } return { "move": random.choice(options) }
if __name__ == "__main__": if __name__ == "__main__":