monop-board/test/play_bot.py

151 lines
4.3 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Simple IRC bot that plays monop by sending dot-prefixed commands."""
import ssl
import sys
import time
import random
import irc.client
import irc.connection
SERVER = "irc.darkscience.net"
PORT = 6697
CHANNEL = "#monop-dev"
class PlayerBot:
def __init__(self, nick, commands):
self.nick = nick
self.commands = list(commands) # list of (delay, command) tuples
self.cmd_idx = 0
self.connection = None
self.joined = False
self.last_cmd_time = 0
def on_connect(self, conn, event):
print(f"[{self.nick}] Connected, joining {CHANNEL}", flush=True)
self.connection = conn
conn.join(CHANNEL)
def on_join(self, conn, event):
if event.source.nick == self.nick:
print(f"[{self.nick}] Joined {CHANNEL}", flush=True)
self.joined = True
self.last_cmd_time = time.time()
def on_pubmsg(self, conn, event):
msg = event.arguments[0] if event.arguments else ""
nick = event.source.nick if event.source else ""
# React to game prompts
if nick == "monopoly" and self.joined:
if "Do you want to buy?" in msg:
time.sleep(0.5)
conn.privmsg(CHANNEL, ".yes")
elif "How many players?" in msg:
time.sleep(0.5)
conn.privmsg(CHANNEL, ".3")
def send_next_command(self):
if self.cmd_idx < len(self.commands) and self.joined:
delay, cmd = self.commands[self.cmd_idx]
if time.time() - self.last_cmd_time >= delay:
print(f"[{self.nick}] Sending: {cmd}", flush=True)
self.connection.privmsg(CHANNEL, cmd)
self.last_cmd_time = time.time()
self.cmd_idx += 1
return True
return False
def main():
# Script the game setup and several turns
# Player 1 starts the game with ".3" (3 players)
# Then each player provides their name
# Then they take turns rolling (just press enter = ".roll" or ".")
alice_cmds = [
(3, ".3"), # start 3 player game
(2, ".Alice"), # enter name
(8, "."), # roll (first turn after setup)
(4, "."), # action/roll
(6, "."),
(6, "."),
(6, "."),
(6, "."),
(6, "."),
(6, "."),
(6, "."),
(6, "."),
]
bob_cmds = [
(6, ".Bob"), # enter name
(10, "."), # roll
(6, "."),
(6, "."),
(6, "."),
(6, "."),
(6, "."),
(6, "."),
(6, "."),
(6, "."),
]
charlie_cmds = [
(8, ".Charlie"), # enter name
(12, "."), # roll
(6, "."),
(6, "."),
(6, "."),
(6, "."),
(6, "."),
(6, "."),
(6, "."),
(6, "."),
]
bots = [
PlayerBot("alice_m", alice_cmds),
PlayerBot("bob_m", bob_cmds),
PlayerBot("charlie_m", charlie_cmds),
]
reactor = irc.client.Reactor()
ssl_ctx = ssl.create_default_context()
for bot in bots:
factory = irc.connection.Factory(
wrapper=lambda s: ssl_ctx.wrap_socket(s, server_hostname=SERVER))
server = reactor.server()
server.connect(SERVER, PORT, bot.nick, connect_factory=factory)
server.add_global_handler("welcome", bot.on_connect)
server.add_global_handler("join", bot.on_join)
server.add_global_handler("pubmsg", bot.on_pubmsg)
time.sleep(1) # stagger connections
print("All bots connecting...", flush=True)
start = time.time()
timeout = 180 # 3 minutes
while time.time() - start < timeout:
reactor.process_once(timeout=0.5)
for bot in bots:
bot.send_next_command()
# Check if all bots are done
if all(b.cmd_idx >= len(b.commands) for b in bots):
print("All commands sent. Waiting 10s for final output...", flush=True)
end = time.time() + 10
while time.time() < end:
reactor.process_once(timeout=0.5)
break
print("Done!", flush=True)
for bot in bots:
if bot.connection:
bot.connection.quit("Game over!")
if __name__ == "__main__":
main()