From 21eca45c80d84d1c9363a6858e3b1661bb53a849 Mon Sep 17 00:00:00 2001 From: donachys Date: Thu, 27 Feb 2025 15:28:14 -0800 Subject: [PATCH] fix(Nexto_EZ): buffer randomness value consistency Updates the Nexto_EZ bot to match user expectations when the GUI slider is unmodified. * when initialized the `Nexto_EZ` class loads the shared memory buffer with a value from 0-255 where 0 represents a fully random bot and 255 is fully nexto. * when initialized the gui expects the value to be in the 0=fully-random format and displays correctly, but does not update the value until the slider is adjusted. * when the slider is adjusted it writes a 0-255 value where 255 is random and 0 is fully nexto. (Note that this is inverted from the initialization step.) * when deciding whether the tick should be random or not the `Nexto_EZ` class expects the buffer to contain a 0-255 value where 255 is fully random. (see line 50) It seems to match expectations if the user modifies the slider before playing. However if the slider is not changed, or when `SHOW_GUI` is set to False the bot's behavior will be the inverse of expectation. * update the initialization of the class and gui to set and expect the 0=fully-nexto 255=fully-random format, respectively. * add debug logging to elevate confidence the bot is behaving as expected. defaults to False/Off --- RLBotPack/Necto/Nexto_EZ/bot.py | 25 ++++++++++++++++++++++++- RLBotPack/Necto/Nexto_EZ/config.py | 12 +++++++++++- RLBotPack/Necto/Nexto_EZ/gui.py | 4 ++-- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/RLBotPack/Necto/Nexto_EZ/bot.py b/RLBotPack/Necto/Nexto_EZ/bot.py index 0a3929a8..60c5ea6a 100644 --- a/RLBotPack/Necto/Nexto_EZ/bot.py +++ b/RLBotPack/Necto/Nexto_EZ/bot.py @@ -1,8 +1,11 @@ import numpy as np from config import * +from collections import deque +from logging import DEBUG, StreamHandler, Formatter from pathlib import Path from rlbot.botmanager.helper_process_request import HelperProcessRequest +from rlbot.utils.logging_utils import get_logger, FORMAT from rlbot.utils.structures.game_data_struct import GameTickPacket from multiprocessing import shared_memory @@ -21,13 +24,32 @@ class Nexto_EZ(Nexto): def __init__(self, name, team, index): super().__init__(name, team, index) + self.logger = get_logger("nexto-ez") + if DEBUG_RANDOM_TICKS: + ch = StreamHandler() + ch.setFormatter(Formatter(FORMAT)) + ch.setLevel(DEBUG) + self.logger.addHandler(ch) self.shared_memory = shared_memory.SharedMemory(create=True, size=1) - self.shared_memory.buf[0] = int(round(STRENGTH * 2.55)) + # buf[0] is a value from 0 - 255 (max random=255, max nexto=0) + self.shared_memory.buf[0] = int(round((100-STRENGTH) * 2.55)) + self.random_debug_log_rate = STRENGTH_LOG_RATE + self.random_debug_tick_count = 0 + self.random_debug_tick_history = deque(maxlen=TICK_HISTORY_LENGTH) def update_controls(self, packet: GameTickPacket): + self.random_debug_tick_count += 1 + if self.random_debug_tick_count >= self.random_debug_log_rate: + self.random_debug_tick_count = 0 + sum_, len_ = sum(self.random_debug_tick_history), len(self.random_debug_tick_history) + self.logger.debug( + "bot#:%d %d of the last %d (%.2f%%) ticks were random compared to configured value of %d%%", + self.index, sum_, len_, sum_/len_ * 100, self.shared_memory.buf[0]/2.55 + ) if np.random.random() * 255 > self.shared_memory.buf[0]: super().update_controls(packet) + self.random_debug_tick_history.append(0) # not random this tick else: # Randomize inputs. Don't influence long term inputs such as jump. self.controls.throttle = np.random.random() @@ -35,6 +57,7 @@ def update_controls(self, packet: GameTickPacket): self.controls.pitch = np.random.random() * 2 - 1 self.controls.yaw = np.random.random() * 2 - 1 self.controls.roll = np.random.random() * 2 - 1 + self.random_debug_tick_history.append(1) # is random this tick def get_helper_process_request(self): if SHOW_GUI: diff --git a/RLBotPack/Necto/Nexto_EZ/config.py b/RLBotPack/Necto/Nexto_EZ/config.py index a31df33e..276d3a43 100644 --- a/RLBotPack/Necto/Nexto_EZ/config.py +++ b/RLBotPack/Necto/Nexto_EZ/config.py @@ -2,4 +2,14 @@ SHOW_GUI = True # in Percent. 100% = Full Nexto, 0% = random agent -STRENGTH = 80 \ No newline at end of file +STRENGTH = 80 + +# enable logging for randomness check +DEBUG_RANDOM_TICKS = False + +# frequency of logging, to avoid spamming +# every # of ticks, log the percent of random ticks +STRENGTH_LOG_RATE = 240 + +# maximum window of ticks to store for computing percent of random +TICK_HISTORY_LENGTH = 240 diff --git a/RLBotPack/Necto/Nexto_EZ/gui.py b/RLBotPack/Necto/Nexto_EZ/gui.py index 6033b650..1bc50f3d 100644 --- a/RLBotPack/Necto/Nexto_EZ/gui.py +++ b/RLBotPack/Necto/Nexto_EZ/gui.py @@ -109,7 +109,7 @@ def format_value(val): # percentage label value_label = ttk.Label( root, - text=format_value(memory.buf[0] / 255), + text=format_value((255 - memory.buf[0]) / 255), ) value_label.grid( column=1, @@ -128,7 +128,7 @@ def update_slider(val): root, from_=0, to=1, - value=memory.buf[0] / 255, + value=(255 - memory.buf[0]) / 255, orient='horizontal', command=lambda val: update_slider(val), ).grid(