games/ares.py (103 lines of code) (raw):

#!/usr/bin/env python # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import logging import re import threading import discord import params import play import pyparsing from absl import app def purge_mentions(message: str): mentions = ( pyparsing.Suppress("<@") + pyparsing.SkipTo(">", include=True).suppress() ) return mentions.transform_string(message) def extract_move(text): # Define the pattern to search for 'rock', 'paper', or 'scissors' pattern = r"\b(rock|paper|scissors)\b" match = re.search(pattern, text, re.IGNORECASE) if match: return match.group(0) return None def main(argv): # Define the intents intents = discord.Intents.default() # Initialize Client client = discord.Client(intents=intents) # Event listener for when the client has switched from offline to online @client.event async def on_ready(): logging.info(f"Logged in as {client.user}") player = play.make_ares() step = 0 game = 0 wins = 0 plays = 0 reward = "START" last_move = "START" lock = threading.Lock() # Event listener for when a message is sent to a channel the client is in @client.event async def on_message(message): nonlocal step, game, reward, last_move, wins, plays # Don't let the client respond to its own messages if message.author == client.user: return # Check if the client was mentioned in the message if ( client.user.mentioned_in(message) and message.mention_everyone is False ): if (move := extract_move(purge_mentions(message.content))) is None: return await message.channel.send( f"{message.author.mention}, what move are you trying to make?" # noqa: E501 ) move = move.upper() with lock: player.observations.append(move) # Let's keep observations at 10 for now. if len(player.observations) > 10: player.observations.pop(0) with lock: if step == 0: reward = "START" with lock: try: response = player.crew.kickoff( inputs={ "observations": player.observations, "reward": reward, "step": step, "game": game, } ) except Exception as e: return await message.channel.send( f"{message.author.mention}, {str(e)}" ) player_move = player.move() reward = 0 plays = plays + 1 if move == "ROCK": if player_move == "SCISSORS": reward = "LOSS" elif player_move == "PAPER": reward = "WIN" wins = wins + 1 elif move == "SCISSORS": if player_move == "PAPER": reward = "LOSS" elif player_move == "ROCK": reward = "WIN" wins = wins + 1 elif move == "PAPER": if player_move == "ROCK": reward = "LOSS" elif player_move == "SCISSORS": reward = "WIN" wins = wins + 1 last_move = player_move step = step + 1 if step % 7 == 0: step = 0 game = game + 1 reward = "START" last_move = "START" return await message.channel.send( f"{message.author.mention}, {response} ({wins} / {plays} wins)" # noqa: E501 ) client.run(params.ARES_TOKEN) if __name__ == "__main__": app.run(main)