From 2abf07564c5eb0ccd2d7e0b6a96434f8145ae227 Mon Sep 17 00:00:00 2001 From: Bram van den Heuvel Date: Fri, 19 Jun 2026 14:51:39 +0200 Subject: [PATCH] Implement Agent of Chaos reference for tic-tac-toe --- server.py | 92 +++++++++++++++++++------------------------------------ 1 file changed, 32 insertions(+), 60 deletions(-) diff --git a/server.py b/server.py index bf95a28..c5b7189 100644 --- a/server.py +++ b/server.py @@ -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 @@ -17,22 +33,18 @@ def main() -> int: :rtype: int """ player = PyServer( - # Customize this to whatever you'd like to call your player - name="My super smart robot player", - - # Custom information that you can use to tell people about this player - profile={}, - - # Unless you know what you're doing, don't touch this. + name="Agent of chaos", + profile={ + "me.noordstar.peanuts.author": "Bram", + "me.noordstar.peanuts.containerized": True, + }, 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={}) - # Start listening for games player.start( - host="0.0.0.0", # Comment out when using only locally + host="0.0.0.0", port=5000, ) @@ -40,59 +52,19 @@ def main() -> int: 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: - - { - "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. + :param payload: The incoming game state. :type payload: dict[str, Any] - :return: The move you wish to take. + :return: The agent of chaos' random choice :rtype: dict[str, Any] """ - - # Try printing the payload to see what it looks like! - print(payload) - - 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. + options = [ + int(k) + for k, v in dict(payload).items() + if k in "0123456789" and v == "" + ] return { "move": random.choice(options) } if __name__ == "__main__":