Initial project structure: reusable isometric bot engine with D2R implementation

This commit is contained in:
Hoid 2026-02-14 08:50:36 +00:00
commit e0282a7111
44 changed files with 3433 additions and 0 deletions

97
games/d2r/game.py Normal file
View file

@ -0,0 +1,97 @@
"""Main D2R bot class — orchestrates the bot loop.
Entry point for the Diablo II: Resurrected bot. Manages the main
game loop, state transitions, and routine execution.
"""
import logging
import time
from typing import Optional
from engine.screen.capture import ScreenCapture
from engine.input.humanize import Humanizer
from engine.state.events import EventBus
from engine.safety.timing import SessionTimer
from games.d2r.config import D2RConfig
from games.d2r.screens.ingame import InGameDetector
from games.d2r.screens.menu import MenuDetector
logger = logging.getLogger(__name__)
class D2RBot:
"""Main Diablo II: Resurrected bot."""
def __init__(self, config: Optional[D2RConfig] = None):
self.config = config or D2RConfig()
self.screen = ScreenCapture()
self.humanizer = Humanizer()
self.events = EventBus()
self.session_timer = SessionTimer()
self.menu_detector = MenuDetector(self.config)
self.ingame_detector = InGameDetector(self.config)
self._running = False
self._current_routine = None
def start(self, routine_name: str = "mephisto") -> None:
"""Start the bot with a specific farming routine."""
logger.info(f"Starting D2R bot with routine: {routine_name}")
self._running = True
try:
self._main_loop(routine_name)
except KeyboardInterrupt:
logger.info("Bot stopped by user")
except Exception as e:
logger.error(f"Bot error: {e}", exc_info=True)
finally:
self._running = False
def stop(self) -> None:
"""Signal the bot to stop."""
self._running = False
def _main_loop(self, routine_name: str) -> None:
"""Core bot loop."""
while self._running:
# Check session timing
if self.session_timer.should_stop_session():
break_duration = self.session_timer.get_break_duration()
logger.info(f"Session break: {break_duration/60:.0f} min")
time.sleep(break_duration)
self.session_timer.start_new_session()
# Check for breaks
break_time = self.humanizer.should_take_break()
if break_time:
time.sleep(break_time)
# Capture screen
frame = self.screen.capture_screen()
# Detect state and act
# TODO: Implement state detection and routine execution
# Small delay between loop iterations
time.sleep(0.05)
def main():
"""CLI entry point."""
import argparse
parser = argparse.ArgumentParser(description="D2R Bot")
parser.add_argument("--routine", default="mephisto", choices=["mephisto", "pindle", "countess"])
parser.add_argument("--resolution", default="1920x1080")
args = parser.parse_args()
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(name)s] %(levelname)s: %(message)s")
config = D2RConfig()
bot = D2RBot(config)
bot.start(args.routine)
if __name__ == "__main__":
main()