Skip to content

Commit

Permalink
Precommit fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
Pbatch committed Jun 20, 2024
1 parent 456e17e commit c2eba28
Show file tree
Hide file tree
Showing 21 changed files with 120 additions and 152 deletions.
20 changes: 12 additions & 8 deletions clashroyalebuildabot/__init__.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
# Exports for clashroyalebuildabot
from . import constants
from . import debugger
from .bot import Action
from .bot import Bot
from .bot import RandomBot
from .bot import TwoSixHogCycle
from .detectors import CardDetector
from .detectors import Detector
from .detectors import NumberDetector
from .detectors import OnnxDetector
from .detectors import ScreenDetector
from .detectors import UnitDetector
from .emulator import Emulator
from .namespaces import Cards
from .namespaces import Screens
from .namespaces import State
from .namespaces import Units
from .screen import Screen
from .state import CardDetector
from .state import Detector
from .state import NumberDetector
from .state import OnnxDetector
from .state import ScreenDetector
from .state import UnitDetector

__all__ = [
"RandomBot",
"TwoSixHogCycle",
"constants",
"Cards",
"Units",
"State",
"Detector",
"OnnxDetector",
"ScreenDetector",
"NumberDetector",
"UnitDetector",
"CardDetector",
"Screen",
"Emulator",
"Action",
"Bot",
]
30 changes: 14 additions & 16 deletions clashroyalebuildabot/bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
from clashroyalebuildabot.constants import DISPLAY_HEIGHT
from clashroyalebuildabot.constants import LEFT_PRINCESS_TILES
from clashroyalebuildabot.constants import RIGHT_PRINCESS_TILES
from clashroyalebuildabot.constants import SCREEN_CONFIG
from clashroyalebuildabot.constants import TILE_HEIGHT
from clashroyalebuildabot.constants import TILE_INIT_X
from clashroyalebuildabot.constants import TILE_INIT_Y
from clashroyalebuildabot.constants import TILE_WIDTH
from clashroyalebuildabot.screen import Screen
from clashroyalebuildabot.state.detector import Detector
from clashroyalebuildabot.detectors.detector import Detector
from clashroyalebuildabot.emulator import Emulator
from clashroyalebuildabot.namespaces import Screens


class Bot:
Expand All @@ -29,7 +29,7 @@ def __init__(
self.action_class = action_class
self.auto_start = auto_start
self.debug = debug
self.screen = Screen()
self.emulator = Emulator()
self.detector = Detector(cards, debug=self.debug)
self.state = None

Expand Down Expand Up @@ -59,9 +59,9 @@ def _get_card_centre(card_n):

def _get_valid_tiles(self):
tiles = ALLY_TILES
if self.state["numbers"]["left_enemy_princess_hp"]["number"] == 0:
if self.state.numbers["left_enemy_princess_hp"]["number"] == 0:
tiles += LEFT_PRINCESS_TILES
if self.state["numbers"]["right_enemy_princess_hp"]["number"] == 0:
if self.state.numbers["right_enemy_princess_hp"]["number"] == 0:
tiles += RIGHT_PRINCESS_TILES
return tiles

Expand All @@ -71,9 +71,9 @@ def get_actions(self):
all_tiles = ALLY_TILES + LEFT_PRINCESS_TILES + RIGHT_PRINCESS_TILES
valid_tiles = self._get_valid_tiles()
actions = []
for i in self.state["ready"]:
card = self.state["cards"][i + 1]
if int(self.state["numbers"]["elixir"]["number"]) < card.cost:
for i in self.state.ready:
card = self.state.cards[i + 1]
if int(self.state.numbers["elixir"]["number"]) < card.cost:
continue

tiles = all_tiles if card.target_anywhere else valid_tiles
Expand All @@ -85,18 +85,16 @@ def get_actions(self):

def set_state(self):
try:
screenshot = self.screen.take_screenshot()
screenshot = self.emulator.take_screenshot()
self.state = self.detector.run(screenshot)
if self.auto_start and self.state["screen"] != "in_game":
self.screen.click(
*SCREEN_CONFIG[self.state["screen"]]["click_coordinates"]
)
if self.auto_start and self.state.screen != Screens.IN_GAME:
self.emulator.click(*self.state.screen.click_xy)
time.sleep(2)
except Exception as e:
logger.error(f"Error occurred while taking screenshot: {e}")

def play_action(self, action):
card_centre = self._get_card_centre(action.index)
tile_centre = self._get_tile_centre(action.tile_x, action.tile_y)
self.screen.click(*card_centre)
self.screen.click(*tile_centre)
self.emulator.click(*card_centre)
self.emulator.click(*tile_centre)
22 changes: 10 additions & 12 deletions clashroyalebuildabot/bot/example/custom_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ def _calculate_spell_score(self, units, radius, min_to_hit):
return [1 if hit_units >= min_to_hit else 0, hit_units, max_distance]

def _calculate_unit_score(self, state, tile_x_conditions, score_if_met):
score = [0.5] if state["numbers"]["elixir"]["number"] == 10 else [0]
score = [0.5] if state.numbers["elixir"]["number"] == 10 else [0]
for unit in (
unit
for v in state["units"]["enemy"].values()
for v in state.units["enemy"].values()
for unit in v["positions"]
):
tile_x, tile_y = unit["tile_xy"]
Expand All @@ -54,10 +54,10 @@ def _calculate_knight_score(self, state):
)

def _calculate_minions_score(self, state):
score = [0.5] if state["numbers"]["elixir"]["number"] == 10 else [0]
score = [0.5] if state.numbers["elixir"]["number"] == 10 else [0]
for unit in (
unit
for v in state["units"]["enemy"].values()
for v in state.units["enemy"].values()
for unit in v["positions"]
):
tile_x, tile_y = unit["tile_xy"]
Expand All @@ -70,13 +70,11 @@ def _calculate_minions_score(self, state):

def _calculate_fireball_score(self, state):
return self._calculate_spell_score(
state["units"], radius=2.5, min_to_hit=3
state.units, radius=2.5, min_to_hit=3
)

def _calculate_arrows_score(self, state):
return self._calculate_spell_score(
state["units"], radius=4, min_to_hit=5
)
return self._calculate_spell_score(state.units, radius=4, min_to_hit=5)

def _calculate_archers_score(self, state):
return self._calculate_unit_score(
Expand All @@ -91,10 +89,10 @@ def _calculate_archers_score(self, state):
def _calculate_giant_score(self, state):
score = [0]
left_hp, right_hp = (
state["numbers"][f"{direction}_enemy_princess_hp"]["number"]
state.numbers[f"{direction}_enemy_princess_hp"]["number"]
for direction in ["left", "right"]
)
if state["numbers"]["elixir"]["number"] == 10:
if state.numbers["elixir"]["number"] == 10:
if self.tile_x == 3:
score = [1, self.tile_y, left_hp != -1, left_hp <= right_hp]
elif self.tile_x == 14:
Expand All @@ -103,7 +101,7 @@ def _calculate_giant_score(self, state):

def _calculate_minipekka_score(self, state):
left_hp, right_hp = (
state["numbers"][f"{direction}_enemy_princess_hp"]["number"]
state.numbers[f"{direction}_enemy_princess_hp"]["number"]
for direction in ["left", "right"]
)
if self.tile_x in [3, 14]:
Expand All @@ -117,7 +115,7 @@ def _calculate_minipekka_score(self, state):
def _calculate_musketeer_score(self, state):
for unit in (
unit
for v in state["units"]["enemy"].values()
for v in state.units["enemy"].values()
for unit in v["positions"]
):
distance = self._distance(
Expand Down
6 changes: 3 additions & 3 deletions clashroyalebuildabot/bot/example/custom_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def __init__(self, cards, debug=False):

def _preprocess(self):
for side in ["ally", "enemy"]:
for k, v in self.state["units"][side].items():
for k, v in self.state.units[side].items():
for unit in v["positions"]:
bbox = unit["bounding_box"]
bbox[0] *= self.scale_x
Expand Down Expand Up @@ -76,9 +76,9 @@ def step(self):
if self.end_of_game_clicked:
self._end_of_game()

old_screen = self.state["screen"] if self.state is not None else None
old_screen = self.state.screen if self.state is not None else None
self.set_state()
new_screen = self.state["screen"]
new_screen = self.state.screen
if new_screen != old_screen:
logger.debug(f"New screen state: {new_screen}")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def _calculate_hog_rider_score(self, state):
Place hog rider on the bridge as high up as possible
Try to target the lowest hp tower
"""
for v in state["units"]["enemy"].values():
for v in state.units["enemy"].values():
for unit in v["positions"]:
tile_x, tile_y = unit["tile_xy"]
if self.tile_y < tile_y <= 14:
Expand All @@ -28,9 +28,9 @@ def _calculate_hog_rider_score(self, state):
):
return [0]

if state["numbers"]["elixir"]["number"] >= 7:
if state.numbers["elixir"]["number"] >= 7:
left_hp, right_hp = [
state["numbers"][f"{direction}_enemy_princess_hp"]["number"]
state.numbers[f"{direction}_enemy_princess_hp"]["number"]
for direction in ["left", "right"]
]
if self.tile_x == 3:
Expand All @@ -49,7 +49,7 @@ def _calculate_cannon_score(self, state):
return [0]

for side in ["ally", "enemy"]:
for v in state["units"][side].values():
for v in state.units[side].values():
for unit in v["positions"]:
tile_y = unit["tile_xy"][1]
if v["transport"] == "ground" and tile_y >= 10:
Expand All @@ -64,7 +64,7 @@ def _calculate_musketeer_score(self, state):
That should be just within her range and not too close to the enemy
"""
for side in ["ally", "enemy"]:
for v in state["units"][side].values():
for v in state.units[side].values():
for unit in v["positions"]:
tile_y = unit["tile_xy"][1]
if v["transport"] == "air" and self.tile_y == tile_y - 7:
Expand All @@ -81,7 +81,7 @@ def _calculate_ice_golem_score(self, state):
return [0]

for side in ["ally", "enemy"]:
for v in state["units"][side].values():
for v in state.units[side].values():
for unit in v["positions"]:
tile_x, tile_y = unit["tile_xy"]
if not (18 >= tile_y >= 15) or v["transport"] != "ground":
Expand All @@ -102,7 +102,7 @@ def _calculate_ice_spirit_score(self, state):
return [0]

for side in ["ally", "enemy"]:
for v in state["units"][side].values():
for v in state.units[side].values():
for unit in v["positions"]:
tile_x, tile_y = unit["tile_xy"]
if not (18 >= tile_y >= 15) or v["transport"] != "ground":
Expand Down Expand Up @@ -149,9 +149,8 @@ def _calculate_log_score(self, state):
"""
Calculate the score for the log card
"""
units = state["units"]
score = [0]
for v in units["enemy"].values():
for v in state.units["enemy"].values():
for unit in v["positions"]:
tile_x, tile_y = unit["tile_xy"]
if tile_y <= 8 and v["transport"] == "ground":
Expand All @@ -164,8 +163,7 @@ def _calculate_fireball_score(self, state):
"""
Play the fireball card if it will hit flying units
"""
units = state["units"]
for v in units["enemy"].values():
for v in state.units["enemy"].values():
for unit in v["positions"]:
tile_x, tile_y = unit["tile_xy"]
if (
Expand All @@ -176,7 +174,7 @@ def _calculate_fireball_score(self, state):
return [1]

return self._calculate_spell_score(
state["units"], radius=2.5, min_to_hit=3
state.units, radius=2.5, min_to_hit=3
)

def calculate_score(self, state):
Expand Down
27 changes: 0 additions & 27 deletions clashroyalebuildabot/constants.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import os

from loguru import logger

from clashroyalebuildabot.namespaces import Units

# Directories
Expand All @@ -20,31 +18,6 @@
SCREENSHOT_WIDTH = 368
SCREENSHOT_HEIGHT = 652

# Screen ID
CHEST_SIZE = 62
CHEST_X = 0
CHEST_Y = 590
OK_X = 143
OK_Y = 558
OK_WIDTH = 82
OK_HEIGHT = 30
SCREEN_CONFIG = {
"lobby": {
"bbox": (CHEST_X, CHEST_Y, CHEST_X + CHEST_SIZE, CHEST_Y + CHEST_SIZE),
"click_coordinates": (220, 830),
},
"end_of_game": {
"bbox": (OK_X, OK_Y, OK_X + OK_WIDTH, OK_Y + OK_HEIGHT),
"click_coordinates": (360, 1125),
},
}

# Log click coordinates for screen configurations
for screen, config in SCREEN_CONFIG.items():
logger.info(
f"Screen: {screen}, Click coordinates: {config['click_coordinates']}"
)

# Playable tiles
TILE_HEIGHT = 27.6
TILE_WIDTH = 34
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Exports for state submodule
from .card_detector import CardDetector
from .debugger import Debugger
from .detector import Detector
from .number_detector import NumberDetector
from .onnx_detector import OnnxDetector
Expand All @@ -14,5 +13,4 @@
"NumberDetector",
"UnitDetector",
"CardDetector",
"Debugger",
]
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import os

from clashroyalebuildabot.constants import MODELS_DIR
from clashroyalebuildabot.state.card_detector import CardDetector
from clashroyalebuildabot.state.debugger import Debugger
from clashroyalebuildabot.state.number_detector import NumberDetector
from clashroyalebuildabot.state.screen_detector import ScreenDetector
from clashroyalebuildabot.state.unit_detector import UnitDetector
from clashroyalebuildabot.debugger import Debugger
from clashroyalebuildabot.detectors.card_detector import CardDetector
from clashroyalebuildabot.detectors.number_detector import NumberDetector
from clashroyalebuildabot.detectors.screen_detector import ScreenDetector
from clashroyalebuildabot.detectors.unit_detector import UnitDetector
from clashroyalebuildabot.namespaces import State


class Detector:
Expand Down Expand Up @@ -35,14 +36,11 @@ def __init__(self, cards, debug=False):

def run(self, image):
cards, ready = self.card_detector.run(image)
state = {
"units": self.unit_detector.run(image),
"numbers": self.number_detector.run(image),
"cards": cards,
"ready": ready,
"screen": self.screen_detector.run(image),
}
units = self.unit_detector.run(image)
numbers = self.number_detector.run(image)
screen = self.screen_detector.run(image)

state = State(units, numbers, cards, ready, screen)
if self.debugger is not None:
self.debugger.run(image, state)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from clashroyalebuildabot.constants import NUMBER_CONFIG
from clashroyalebuildabot.constants import NUMBER_HEIGHT
from clashroyalebuildabot.constants import NUMBER_WIDTH
from clashroyalebuildabot.state.onnx_detector import OnnxDetector
from clashroyalebuildabot.detectors.onnx_detector import OnnxDetector


class NumberDetector(OnnxDetector):
Expand Down
File renamed without changes.
Loading

0 comments on commit c2eba28

Please sign in to comment.