From da10e7ffad0edd65e9daa52428cbe187316726d5 Mon Sep 17 00:00:00 2001 From: Matt Popovich Date: Wed, 31 Dec 2025 21:49:15 -0500 Subject: [PATCH 1/3] First pass at having coordinates based on an anchor point --- Dockerfile | 2 +- Point.py | 3 + battler.py | 30 +++++----- config.py | 67 ---------------------- configs/__init__.py | 0 configs/iPhone11.py | 131 +++++++++++++++++++++++++++++++++++++++++++ configs/iPhoneMax.py | 131 +++++++++++++++++++++++++++++++++++++++++++ modifyFavorite.py | 8 +-- trader.py | 14 ++--- 9 files changed, 292 insertions(+), 94 deletions(-) create mode 100644 Point.py delete mode 100644 config.py create mode 100644 configs/__init__.py create mode 100644 configs/iPhone11.py create mode 100644 configs/iPhoneMax.py diff --git a/Dockerfile b/Dockerfile index e591453..b5cb543 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ ### Cliclick is needed to run the scripts, and that is only available on macOS. # Get current python image -FROM python:3.12.11-bullseye +FROM python:3.13.6-bullseye # Update image RUN apt-get update && apt-get upgrade -y diff --git a/Point.py b/Point.py new file mode 100644 index 0000000..0011a09 --- /dev/null +++ b/Point.py @@ -0,0 +1,3 @@ +from collections import namedtuple + +Point = namedtuple('Point', ['x', 'y']) diff --git a/battler.py b/battler.py index 8ccca16..146515a 100644 --- a/battler.py +++ b/battler.py @@ -25,7 +25,7 @@ import sys # Custom imports -import config +from configs.iPhone11 import coordinates from functions.cliclick import Cliclick import functions.utils as utils @@ -63,20 +63,20 @@ sys.exit("ERROR: must specify one of --great, --ultra, or --master") # Access the coordinates from the active system -lets_do_it_coordinates = config.SETTINGS["lets_do_it_coordinates"] -start_battle_coordinates = config.SETTINGS["start_battle_coordinates"] -great_league_coordinates = config.SETTINGS["great_league_coordinates"] -ultra_league_coordinates = config.SETTINGS["ultra_league_coordinates"] -master_league_coordinates = config.SETTINGS["master_league_coordinates"] -lets_battle_coordinates = config.SETTINGS["lets_battle_coordinates"] -use_party_coordinates = config.SETTINGS["use_party_coordinates"] -rematch_coordinates = config.SETTINGS["rematch_coordinates"] -first_pokemon_in_party_coordinates = config.SETTINGS["first_pokemon_in_party_coordinates"] -first_pokemon_coordinates = config.SETTINGS["first_pokemon_coordinates"] -second_pokemon_coordinates = config.SETTINGS["second_pokemon_coordinates"] -third_pokemon_coordinates = config.SETTINGS["third_pokemon_coordinates"] -done_button_coordinates = config.SETTINGS["done_button_coordinates"] -change_prng = config.SETTINGS["change_prng"] +lets_do_it_coordinates = coordinates["lets_do_it_coordinates"] +start_battle_coordinates = coordinates["start_battle_coordinates"] +great_league_coordinates = coordinates["great_league_coordinates"] +ultra_league_coordinates = coordinates["ultra_league_coordinates"] +master_league_coordinates = coordinates["master_league_coordinates"] +lets_battle_coordinates = coordinates["lets_battle_coordinates"] +use_party_coordinates = coordinates["use_party_coordinates"] +rematch_coordinates = coordinates["rematch_coordinates"] +first_pokemon_in_party_coordinates = coordinates["first_pokemon_in_party_coordinates"] +first_pokemon_coordinates = coordinates["first_pokemon_coordinates"] +second_pokemon_coordinates = coordinates["second_pokemon_coordinates"] +third_pokemon_coordinates = coordinates["third_pokemon_coordinates"] +done_button_coordinates = coordinates["done_button_coordinates"] +change_prng = coordinates["change_prng"] pixel_randomness = 10 diff --git a/config.py b/config.py deleted file mode 100644 index 23ea2e6..0000000 --- a/config.py +++ /dev/null @@ -1,67 +0,0 @@ -# Define the active system -ACTIVE_SYSTEM = "iPhone15ProMaxWidescreen" - -# TODO: Scale these based on Ex. top left and bottom right corners or something -# Scale would be dependent on screen aspect ratio -# Define system-specific coordinates -# Depending on which script you are running, -# not all of these need to be defined -systems = { - "iPhone15ProMaxWidescreen": { # Widescreen monitor - "start_battle_coordinates": [3377, 1285], - "start_trade_coordinates": [3227, 1263], - "first_trade_pokemon_coordinates": [3161, 953], - # "between_first_second_pokemon": [3213, 947], # Whitespace - "next_button_coordinates": [3268, 1321], - "confirm_button_coordinates": [3141, 1086], - # "pokemon_details_left_health_white": [3146, 1021], # Whitespace left of health bar - "x_button_coordinates": [3268, 1389], - "start_drag_next_poke": [3396, 1132], # Right side of screen - "end_drag_next_poke": [3147, 1132], # Left side of screen - "modify_favorite": [3401, 770], - "lets_do_it_coordinates": [3265, 1154], - "great_league_coordinates": [3272, 1042], - "ultra_league_coordinates": [3272, 1147], - "master_league_coordinates": [3272, 1251], - "lets_battle_coordinates": [3265, 1146], - "first_pokemon_in_party_coordinates": [3178, 1242], - "use_party_coordinates": [3266, 1359], - "rematch_coordinates": [3268, 1174], - # "sort_button_coordinates": [3388,1320], # Unused - "first_pokemon_coordinates": [3160, 1026], - "second_pokemon_coordinates": [3267, 1026], - "third_pokemon_coordinates": [3373, 1026], - "done_button_coordinates": [3343, 1402], - "change_prng": False, # One of the devices should be false, the other true. This allows their 'randomness' to be different - }, - "iPhone11ProMBAirLarger": { # iPhone Mirroring -> View -> Larger - "start_battle_coordinates": [1608, 871], - "start_trade_coordinates": [1440, 849], - "first_trade_pokemon_coordinates": [1366, 489], - # "between_first_second_pokemon": [1420, 488], # Unused - "next_button_coordinates": [1487, 917], - "confirm_button_coordinates": [1347, 650], - # "pokemon_details_left_health_white": [1350, 579], # Unused - "x_button_coordinates": [1486, 995], - "start_drag_next_poke": [1633, 710], - "end_drag_next_poke": [1340, 710], - "modify_favorite": [1636, 294], - "lets_do_it_coordinates": [1483, 728], - "great_league_coordinates": [1485, 604], - "ultra_league_coordinates": [1486, 720], - "master_league_coordinates": [1487, 841], - "lets_battle_coordinates": [1482, 719], - "first_pokemon_in_party_coordinates": [1384, 828], - "use_party_coordinates": [1499, 959], - "rematch_coordinates": [1482, 750], - # "sort_button_coordinates": [1621, 915], # Unused - "first_pokemon_coordinates": [1367, 566], - "second_pokemon_coordinates": [1485, 566], - "third_pokemon_coordinates": [1602, 566], - "done_button_coordinates": [1571, 1009], - "change_prng": True, - }, -} - -# Get the active system's coordinates -SETTINGS = systems[ACTIVE_SYSTEM] diff --git a/configs/__init__.py b/configs/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/configs/iPhone11.py b/configs/iPhone11.py new file mode 100644 index 0000000..ff1d554 --- /dev/null +++ b/configs/iPhone11.py @@ -0,0 +1,131 @@ +""" +This is a config file for screen mirroring with an iPhone 11 with a "Larger" view window. +To use this with an iPhone 11, the only thing you should modify is the `anchor` variable. +""" + +from Point import Point + +# Red 'x' in the top left of the mirroring window +anchor = Point(1311, 213) # MacBook Air + +# Individual offset values with a "larger" view +# iPhone Mirroring -> View -> Larger +start_battle_offset = Point(286, 633) +start_trade_offset = Point(129, 636) +first_trade_pokemon_offset = Point(55, 276) +between_first_second_pokemon_offset = Point(109, 275) # unused +next_button_offset = Point(176, 704) +confirm_button_offset = Point(36, 437) +pokemon_details_left_health_white_offset = Point(39, 366) # unused +x_button_offset = Point(175, 782) +start_drag_next_poke_offset = Point(322, 497) +end_drag_next_poke_offset = Point(29, 497) +modify_favorite_offset = Point(325, 81) +lets_do_it_offset = Point(172, 515) +great_league_offset = Point(174, 391) +ultra_league_offset = Point(175, 507) +master_league_offset = Point(176, 628) +lets_battle_offset = Point(171, 506) +first_pokemon_in_party_offset = Point(73, 615) +use_party_offset = Point(188, 746) +rematch_offset = Point(171, 537) +sort_button_offset = Point(310, 702) # unused +first_pokemon_offset = Point(56, 353) +second_pokemon_offset = Point(174, 353) +third_pokemon_offset = Point(291, 353) +done_button_offset = Point(260, 796) + +# Recreated configuration using anchor + individual offsets +coordinates = { + "start_battle_coordinates": [ + anchor.x + start_battle_offset.x, + anchor.y + start_battle_offset.y, + ], + "start_trade_coordinates": [ + anchor.x + start_trade_offset.x, + anchor.y + start_trade_offset.y, + ], + "first_trade_pokemon_coordinates": [ + anchor.x + first_trade_pokemon_offset.x, + anchor.y + first_trade_pokemon_offset.y, + ], + "between_first_second_pokemon": [ + anchor.x + between_first_second_pokemon_offset.x, + anchor.y + between_first_second_pokemon_offset.y, + ], + "next_button_coordinates": [ + anchor.x + next_button_offset.x, + anchor.y + next_button_offset.y, + ], + "confirm_button_coordinates": [ + anchor.x + confirm_button_offset.x, + anchor.y + confirm_button_offset.y, + ], + "pokemon_details_left_health_white": [ + anchor.x + pokemon_details_left_health_white_offset.x, + anchor.y + pokemon_details_left_health_white_offset.y, + ], + "x_button_coordinates": [anchor.x + x_button_offset.x, anchor.y + x_button_offset.y], + "start_drag_next_poke": [ + anchor.x + start_drag_next_poke_offset.x, + anchor.y + start_drag_next_poke_offset.y, + ], + "end_drag_next_poke": [ + anchor.x + end_drag_next_poke_offset.x, + anchor.y + end_drag_next_poke_offset.y, + ], + "modify_favorite": [ + anchor.x + modify_favorite_offset.x, + anchor.y + modify_favorite_offset.y, + ], + "lets_do_it_coordinates": [ + anchor.x + lets_do_it_offset.x, + anchor.y + lets_do_it_offset.y, + ], + "great_league_coordinates": [ + anchor.x + great_league_offset.x, + anchor.y + great_league_offset.y, + ], + "ultra_league_coordinates": [ + anchor.x + ultra_league_offset.x, + anchor.y + ultra_league_offset.y, + ], + "master_league_coordinates": [ + anchor.x + master_league_offset.x, + anchor.y + master_league_offset.y, + ], + "lets_battle_coordinates": [ + anchor.x + lets_battle_offset.x, + anchor.y + lets_battle_offset.y, + ], + "first_pokemon_in_party_coordinates": [ + anchor.x + first_pokemon_in_party_offset.x, + anchor.y + first_pokemon_in_party_offset.y, + ], + "use_party_coordinates": [ + anchor.x + use_party_offset.x, + anchor.y + use_party_offset.y, + ], + "rematch_coordinates": [anchor.x + rematch_offset.x, anchor.y + rematch_offset.y], + "sort_button_coordinates": [ + anchor.x + sort_button_offset.x, + anchor.y + sort_button_offset.y, + ], + "first_pokemon_coordinates": [ + anchor.x + first_pokemon_offset.x, + anchor.y + first_pokemon_offset.y, + ], + "second_pokemon_coordinates": [ + anchor.x + second_pokemon_offset.x, + anchor.y + second_pokemon_offset.y, + ], + "third_pokemon_coordinates": [ + anchor.x + third_pokemon_offset.x, + anchor.y + third_pokemon_offset.y, + ], + "done_button_coordinates": [ + anchor.x + done_button_offset.x, + anchor.y + done_button_offset.y, + ], + "change_prng": True, +} diff --git a/configs/iPhoneMax.py b/configs/iPhoneMax.py new file mode 100644 index 0000000..1638a19 --- /dev/null +++ b/configs/iPhoneMax.py @@ -0,0 +1,131 @@ +""" +This is a config file for screen mirroring with an iPhone 15 Pro Max. +To use this with an iPhone 15 Pro Max, the only thing you should modify is the `anchor` variable. +""" + +from Point import Point + +# Red 'x' in the top left of the mirroring window +anchor = Point(3115, 695) # 36" windscreen monitor +anchor = Point(1595, 335) # 1080p monitor + +# Individual offset values +start_battle_offset = Point(262, 590) +start_trade_offset = Point(112, 568) # TODO: Update this since remote trades were added +first_trade_pokemon_offset = Point(46, 258) +between_first_second_pokemon_offset = Point(98, 252) # unused +next_button_offset = Point(153, 626) +confirm_button_offset = Point(26, 391) +pokemon_details_left_health_white_offset = Point(31, 326) # unused +x_button_offset = Point(153, 694) +start_drag_next_poke_offset = Point(281, 437) +end_drag_next_poke_offset = Point(32, 437) +modify_favorite_offset = Point(286, 75) +lets_do_it_offset = Point(150, 459) +great_league_offset = Point(157, 347) +ultra_league_offset = Point(157, 452) +master_league_offset = Point(157, 556) +lets_battle_offset = Point(150, 451) +first_pokemon_in_party_offset = Point(63, 547) +use_party_offset = Point(151, 664) +rematch_offset = Point(153, 479) +sort_button_offset = Point(273, 625) # unused +first_pokemon_offset = Point(45, 331) +second_pokemon_offset = Point(152, 331) +third_pokemon_offset = Point(258, 331) +done_button_offset = Point(228, 707) + +# Recreated configuration using anchor + individual offsets +coordinates = { + "start_battle_coordinates": [ + anchor.x + start_battle_offset.x, + anchor.y + start_battle_offset.y, + ], + "start_trade_coordinates": [ + anchor.x + start_trade_offset.x, + anchor.y + start_trade_offset.y, + ], + "first_trade_pokemon_coordinates": [ + anchor.x + first_trade_pokemon_offset.x, + anchor.y + first_trade_pokemon_offset.y, + ], + "between_first_second_pokemon": [ + anchor.x + between_first_second_pokemon_offset.x, + anchor.y + between_first_second_pokemon_offset.y, + ], + "next_button_coordinates": [ + anchor.x + next_button_offset.x, + anchor.y + next_button_offset.y, + ], + "confirm_button_coordinates": [ + anchor.x + confirm_button_offset.x, + anchor.y + confirm_button_offset.y, + ], + "pokemon_details_left_health_white": [ + anchor.x + pokemon_details_left_health_white_offset.x, + anchor.y + pokemon_details_left_health_white_offset.y, + ], + "x_button_coordinates": [anchor.x + x_button_offset.x, anchor.y + x_button_offset.y], + "start_drag_next_poke": [ + anchor.x + start_drag_next_poke_offset.x, + anchor.y + start_drag_next_poke_offset.y, + ], + "end_drag_next_poke": [ + anchor.x + end_drag_next_poke_offset.x, + anchor.y + end_drag_next_poke_offset.y, + ], + "modify_favorite": [ + anchor.x + modify_favorite_offset.x, + anchor.y + modify_favorite_offset.y, + ], + "lets_do_it_coordinates": [ + anchor.x + lets_do_it_offset.x, + anchor.y + lets_do_it_offset.y, + ], + "great_league_coordinates": [ + anchor.x + great_league_offset.x, + anchor.y + great_league_offset.y, + ], + "ultra_league_coordinates": [ + anchor.x + ultra_league_offset.x, + anchor.y + ultra_league_offset.y, + ], + "master_league_coordinates": [ + anchor.x + master_league_offset.x, + anchor.y + master_league_offset.y, + ], + "lets_battle_coordinates": [ + anchor.x + lets_battle_offset.x, + anchor.y + lets_battle_offset.y, + ], + "first_pokemon_in_party_coordinates": [ + anchor.x + first_pokemon_in_party_offset.x, + anchor.y + first_pokemon_in_party_offset.y, + ], + "use_party_coordinates": [ + anchor.x + use_party_offset.x, + anchor.y + use_party_offset.y, + ], + "rematch_coordinates": [anchor.x + rematch_offset.x, anchor.y + rematch_offset.y], + "sort_button_coordinates": [ + anchor.x + sort_button_offset.x, + anchor.y + sort_button_offset.y, + ], + "first_pokemon_coordinates": [ + anchor.x + first_pokemon_offset.x, + anchor.y + first_pokemon_offset.y, + ], + "second_pokemon_coordinates": [ + anchor.x + second_pokemon_offset.x, + anchor.y + second_pokemon_offset.y, + ], + "third_pokemon_coordinates": [ + anchor.x + third_pokemon_offset.x, + anchor.y + third_pokemon_offset.y, + ], + "done_button_coordinates": [ + anchor.x + done_button_offset.x, + anchor.y + done_button_offset.y, + ], + "change_prng": False, +} diff --git a/modifyFavorite.py b/modifyFavorite.py index 51e69e5..f68c05d 100644 --- a/modifyFavorite.py +++ b/modifyFavorite.py @@ -7,16 +7,16 @@ import random import time -import config +from configs.iPhone11 import coordinates from functions.cliclick import Cliclick import datetime import functions.utils as utils # Access the coordinates from the active system -start_drag_next_poke = config.SETTINGS["start_drag_next_poke"] -end_drag_next_poke = config.SETTINGS["end_drag_next_poke"] -modify_favorite = config.SETTINGS["modify_favorite"] +start_drag_next_poke = coordinates["start_drag_next_poke"] +end_drag_next_poke = coordinates["end_drag_next_poke"] +modify_favorite = coordinates["modify_favorite"] pixel_randomness = 10 diff --git a/trader.py b/trader.py index 6981e0c..f6630fd 100644 --- a/trader.py +++ b/trader.py @@ -13,17 +13,17 @@ import datetime # Custom imports -import config +from configs.iPhone11 import coordinates from functions.cliclick import Cliclick import functions.utils as utils # Access the coordinates from the active system -start_trade_coordinates = config.SETTINGS["start_trade_coordinates"] -first_trade_pokemon_coordinates = config.SETTINGS["first_trade_pokemon_coordinates"] -next_button_coordinates = config.SETTINGS["next_button_coordinates"] -confirm_button_coordinates = config.SETTINGS["confirm_button_coordinates"] -x_button_coordinates = config.SETTINGS["x_button_coordinates"] -change_prng = config.SETTINGS["change_prng"] +start_trade_coordinates = coordinates["start_trade_coordinates"] +first_trade_pokemon_coordinates = coordinates["first_trade_pokemon_coordinates"] +next_button_coordinates = coordinates["next_button_coordinates"] +confirm_button_coordinates = coordinates["confirm_button_coordinates"] +x_button_coordinates = coordinates["x_button_coordinates"] +change_prng = coordinates["change_prng"] pixel_randomness = 10 LOG_FILE = "trader_log.txt" From 5768916dd9a4229413e6c938fdeaa5e7313fa9d8 Mon Sep 17 00:00:00 2001 From: Matt Popovich Date: Thu, 1 Jan 2026 01:45:30 -0500 Subject: [PATCH 2/3] Add TODOs --- functions/cliclick.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/functions/cliclick.py b/functions/cliclick.py index 138a05b..b6c627a 100644 --- a/functions/cliclick.py +++ b/functions/cliclick.py @@ -2,6 +2,12 @@ from functions.utils import randomize_location +# TODO: Handle cliclick not being installed +# TODO: Handle cliclick not having permissions: +# WARNING: Accessibility privileges not enabled. Many actions may fail. +# Enable the checkbox for the containing app in: +# System Preferences → Security & Privacy → Accessibility + class Cliclick: def __init__(self, executable="cliclick"): From 51fcdbc8dda822098d4dcd33674decfe63bac965 Mon Sep 17 00:00:00 2001 From: Matt Popovich Date: Thu, 1 Jan 2026 02:12:50 -0500 Subject: [PATCH 3/3] Fixing linting --- Point.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Point.py b/Point.py index 0011a09..1eb5564 100644 --- a/Point.py +++ b/Point.py @@ -1,3 +1,3 @@ from collections import namedtuple -Point = namedtuple('Point', ['x', 'y']) +Point = namedtuple("Point", ["x", "y"])