Skip to content

Commit

Permalink
Merge pull request #39 from lukemurphy147/main
Browse files Browse the repository at this point in the history
Fixed tie-vote handling
  • Loading branch information
TomCasavant authored Jul 11, 2024
2 parents b0e1a26 + 426e52c commit fedf105
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 111 deletions.
177 changes: 86 additions & 91 deletions bot.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
A bot that interacts with a Mastodon compatible API, plays gameboy games via a Poll
A bot that interacts with a Mastodon compatible API, plays Game Boy games via a poll
"""

import os
Expand All @@ -10,7 +10,7 @@
from mastodon import Mastodon
from requests.exceptions import RequestException

from gb import Gameboy
from gb import GameBoy


script_dir = os.path.dirname(os.path.realpath(__file__))
Expand All @@ -19,7 +19,7 @@

class Bot:
"""
A Mastodon-API Compatible bot that handles gameboy gameplay through polls
A Mastodon-API compatible bot that handles Game Boy gameplay through polls
"""

def __init__(self, config_path="config.toml"):
Expand All @@ -29,61 +29,43 @@ def __init__(self, config_path="config.toml"):
with open(config_path, "r", encoding="utf-8") as config_file:
self.config = toml.load(config_file)
self.mastodon_config = self.config.get("mastodon", {})
self.gameboy_config = self.config.get("gameboy", {})
self.game_boy_config = self.config.get("gameboy", {})

self.mastodon = self.login()
print(self.gameboy_config.get("rom"))
rom = os.path.join(script_dir, self.gameboy_config.get("rom"))
self.gameboy = Gameboy(rom, True)
print(self.game_boy_config.get("rom"))
rom = os.path.join(script_dir, self.game_boy_config.get("rom"))
self.game_boy = GameBoy(rom, True)

def simulate(self):
"""Simulates gameboy actions by pressing random buttons, useful for testing"""
"""Simulates Game Boy actions by pressing random buttons, useful for testing"""
while True:
# print(self.gameboy.is_running())
# self.gameboy.random_button()
# print(self.game_boy.is_running())
# self.game_boy.random_button()
buttons = {
"a": self.gameboy.a,
"b": self.gameboy.b,
"start": self.gameboy.start,
"select": self.gameboy.select,
"up": self.gameboy.dpad_up,
"down": self.gameboy.dpad_down,
"right": self.gameboy.dpad_right,
"left": self.gameboy.dpad_left,
"random": self.gameboy.random_button,
"a": self.game_boy.a,
"b": self.game_boy.b,
"start": self.game_boy.start,
"select": self.game_boy.select,
"up": self.game_boy.dpad_up,
"down": self.game_boy.dpad_down,
"right": self.game_boy.dpad_right,
"left": self.game_boy.dpad_left,
"random": self.game_boy.random_button,
"tick": "tick",
}
# self.gameboy.random_button()
# self.game_boy.random_button()
print(buttons)
press = input("Button: ")
if press == "tick":
for _ in range(60):
self.gameboy.pyboy.tick()
self.game_boy.pyboy.tick()
else:
buttons[press]()
self.gameboy.pyboy.tick()
self.game_boy.pyboy.tick()
# time.sleep(1)

def random_button(self):
"""Chooses a random button and presses it on the gameboy"""
buttons = {
"a": self.gameboy.a,
"b": self.gameboy.b,
"start": self.gameboy.start,
"select": self.gameboy.select,
"up": self.gameboy.dpad_up,
"down": self.gameboy.dpad_down,
"right": self.gameboy.dpad_right,
"left": self.gameboy.dpad_left,
}

random_button = random.choice(list(buttons.keys()))
action = buttons[random_button]
action()
return random_button

def login(self):
"""Logs into the mastodon server using config credentials"""
"""Logs into the Mastodon server using config credentials"""
server = self.mastodon_config.get("server")
print(f"Logging into {server}")
return Mastodon(
Expand Down Expand Up @@ -128,27 +110,34 @@ def unpin_posts(self, post_id, poll_id):
self.mastodon.status_unpin(poll_id)

def take_action(self, result):
"""Presses button on gameboy based on poll result"""
"""Presses button on Game Boy based on poll result"""
buttons = {
"up ⬆️": self.gameboy.dpad_up,
"down ⬇️": self.gameboy.dpad_down,
"right ➡️": self.gameboy.dpad_right,
"left ⬅️": self.gameboy.dpad_left,
"🅰": self.gameboy.a,
"🅱": self.gameboy.b,
"start": self.gameboy.start,
"select": self.gameboy.select,
"Up ⬆️": self.game_boy.dpad_up,
"Down ⬇️": self.game_boy.dpad_down,
"Right ➡️": self.game_boy.dpad_right,
"Left ⬅️": self.game_boy.dpad_left,
"🅰": self.game_boy.a,
"🅱": self.game_boy.b,
"Start": self.game_boy.start,
"Select": self.game_boy.select,
}
print(buttons)
# Perform the corresponding action
if result.lower() in buttons:
action = buttons[result.lower()]
if result in buttons:
action = buttons[result]
action()
return result
elif result == "random":
random_button = random.choice(list(buttons.keys()))
action = buttons[random_button]
action()
return random_button
else:
print(f"No action defined for '{result}'.")
return "INVALID BUTTON"

def retry_mastodon_call(self, func, *args, retries=5, interval=10, **kwargs):
"""Continuously retries mastodon call, useful for servers with timeout issues"""
"""Continuously retries Mastodon call, useful for servers with timeout issues"""
for _ in range(retries):
try:
return func(*args, **kwargs)
Expand All @@ -159,9 +148,9 @@ def retry_mastodon_call(self, func, *args, retries=5, interval=10, **kwargs):

def run(self):
"""
Runs the main gameplay, reads mastodon poll result, takes action, generates new posts
Runs the main gameplay, reads Mastodon poll result, takes action, generates new posts
"""
self.gameboy.load()
self.game_boy.load()
post_id, poll_id = self.read_ids()
top_result = None

Expand All @@ -174,23 +163,29 @@ def run(self):

poll_status = self.mastodon.status(poll_id)
poll_results = poll_status.poll["options"]
max_result = max(poll_results, key=lambda x: x["votes_count"])
if max_result["votes_count"] == 0:
button = self.random_button()
top_result = f"Random (no votes, chose {button})"
max_votes = max(map(lambda x: x["votes_count"], poll_results))
if max_votes == 0:
random_button = self.take_action("random")
top_result = f"Random (no votes, chose {random_button})"
else:
top_result = max_result["title"]
self.take_action(top_result)
top_results = [x for x in poll_results if x["votes_count"] == max_votes]
if len(top_results) > 1:
top_result = random.choice(top_results)["title"]
self.take_action(top_result)
top_result = f"Random (tie vote, chose {top_result})"
else:
top_result = top_results[0]["title"]
self.take_action(top_result)

frames = self.gameboy.loop_until_stopped()
frames = self.game_boy.loop_until_stopped()
result = False
if frames >= 70:
result = self.gameboy.build_gif("gif_images", self.gameboy_config['gif_outline'])
result = self.game_boy.build_gif("gif_images", self.game_boy_config['gif_outline'])
else:
self.gameboy.empty_directory(gif_dir)
self.game_boy.empty_directory(gif_dir)

image = self.gameboy.screenshot()
alt_text = 'Screenshot of ' + self.gameboy_config.get('title', 'a Game Boy game.')
image = self.game_boy.screenshot()
alt_text = 'Screenshot of ' + self.game_boy_config.get('title', 'a Game Boy game.')
media = self.retry_mastodon_call(
self.mastodon.media_post,
retries=5,
Expand All @@ -202,9 +197,9 @@ def run(self):
# Probably add a check here if generating a gif is enabled (so we don't
# have to generate one every single hour?)
try:
previous_frames = self.gameboy.get_recent_frames("screenshots",
previous_frames = self.game_boy.get_recent_frames("screenshots",
25,
self.gameboy_config['gif_outline']
self.game_boy_config['gif_outline']
)
previous_media = self.retry_mastodon_call(
self.mastodon.media_post,
Expand All @@ -224,7 +219,7 @@ def run(self):
interval=10,
status=(
f"Previous Action: {top_result}\n\n"
"#pokemon #gameboy #nintendo #FediPlaysPokemon"
"#Pokemon #GameBoy #Nintendo #FediPlaysPokemon"
),
media_ids=[media_ids],
)
Expand Down Expand Up @@ -264,7 +259,7 @@ def run(self):
retries=5,
interval=10,
media_file=result,
description="Video of pokemon gold movement",
description="Video of Pokémon Gold movement",
)
self.retry_mastodon_call(
self.mastodon.status_post,
Expand All @@ -278,41 +273,41 @@ def run(self):
self.save_ids(post["id"], poll["id"])

# Save game state
self.gameboy.save()
self.game_boy.save()

def test(self):
"""Method used for testing"""
self.gameboy.load()
self.gameboy.get_recent_frames("screenshots", 25)
# self.gameboy.build_gif("gif_images")
self.game_boy.load()
self.game_boy.get_recent_frames("screenshots", 25)
# self.game_boy.build_gif("gif_images")
while True:
inp = input("Action: ")
buttons = {
"up": self.gameboy.dpad_up,
"down": self.gameboy.dpad_down,
"right": self.gameboy.dpad_right,
"left": self.gameboy.dpad_left,
"a": self.gameboy.a,
"b": self.gameboy.b,
"start": self.gameboy.start,
"select": self.gameboy.select,
"up": self.game_boy.dpad_up,
"down": self.game_boy.dpad_down,
"right": self.game_boy.dpad_right,
"left": self.game_boy.dpad_left,
"a": self.game_boy.a,
"b": self.game_boy.b,
"start": self.game_boy.start,
"select": self.game_boy.select,
}
# Perform the corresponding action
if inp.lower() in buttons:
action = buttons[inp.lower()]
# self.gameboy.tick()
if inp in buttons:
action = buttons[inp]
# self.game_boy.tick()
action()
frames = self.gameboy.loop_until_stopped()
frames = self.game_boy.loop_until_stopped()
if frames > 51:
self.gameboy.build_gif("gif_images")
self.game_boy.build_gif("gif_images")
else:
self.gameboy.empty_directory(gif_dir)
self.game_boy.empty_directory(gif_dir)
else:
print(f"No action defined for '{inp}'.")
self.gameboy.save()
# self.gameboy.build_gif("gif_images")
self.game_boy.save()
# self.game_boy.build_gif("gif_images")
# self.take_action(inp)
# self.gameboy.tick(300)
# self.game_boy.tick(300)


if __name__ == "__main__":
Expand Down
Loading

0 comments on commit fedf105

Please sign in to comment.