Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Introduce mouse latency & add non-stop online matches #37

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/grabbers/chesscom_grabber.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,8 @@ def is_game_puzzles(self):
def click_puzzle_next(self):
pass

def click_game_next(self):
pass

def make_mouseless_move(self, move, move_count):
pass
34 changes: 25 additions & 9 deletions src/grabbers/lichess_grabber.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import re

from selenium.common import NoSuchElementException
from selenium.common import NoSuchElementException, StaleElementReferenceException
from selenium.webdriver.common.by import By

from grabbers.grabber import Grabber
Expand All @@ -13,16 +13,20 @@ def __init__(self, chrome_url, chrome_session_id):
self.moves_list = {}

def update_board_elem(self):
try:
# Try finding the normal board
self._board_elem = self.chrome.find_element(By.XPATH,
'//*[@id="main-wrap"]/main/div[1]/div[1]/div/cg-container')
except NoSuchElementException:
# Keep looking for board
while True:
try:
# Try finding the board in the puzzles page
self._board_elem = self.chrome.find_element(By.XPATH, '/html/body/div[2]/main/div[1]/div/cg-container')
# Try finding the normal board
self._board_elem = self.chrome.find_element(By.XPATH,
'//*[@id="main-wrap"]/main/div[1]/div[1]/div/cg-container')
return
except NoSuchElementException:
self._board_elem = None
try:
# Try finding the board in the puzzles page
self._board_elem = self.chrome.find_element(By.XPATH, '/html/body/div[2]/main/div[1]/div/cg-container')
return
except NoSuchElementException:
self._board_elem = None

def is_white(self):
# Get "ranks" child
Expand Down Expand Up @@ -168,6 +172,18 @@ def click_puzzle_next(self):
# Click the continue training button
self.chrome.execute_script("arguments[0].click();", next_button)

def click_game_next(self):
# Find the next new game button
try:
next_button = self.chrome.find_element(By.XPATH, "//*[contains(text(), 'New opponent')]")
except NoSuchElementException:
return
except StaleElementReferenceException:
return

# Click the next game button
self.chrome.execute_script("arguments[0].click();", next_button)

def make_mouseless_move(self, move, move_count):
message = '{"t":"move","d":{"u":"' + move + '","b":1,"a":' + str(move_count) + '}}'
script = 'lichess.socket.ws.send(JSON.stringify(' + message + '))'
Expand Down
19 changes: 17 additions & 2 deletions src/gui.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import multiprocessing

import multiprocess
import threading
import time
Expand Down Expand Up @@ -110,11 +108,26 @@ def __init__(self, master):
variable=self.enable_non_stop_puzzles)
self.non_stop_puzzles_check_button.pack(anchor=tk.NW)

# Create the non-stop matches check button
self.enable_non_stop_matches = tk.IntVar(value=0)
self.non_stop_matches_check_button = tk.Checkbutton(left_frame, text="Non-stop online matches",
variable=self.enable_non_stop_matches)
self.non_stop_matches_check_button.pack(anchor=tk.NW)

# Create the bongcloud check button
self.enable_bongcloud = tk.IntVar()
self.bongcloud_check_button = tk.Checkbutton(left_frame, text='Bongcloud', variable=self.enable_bongcloud)
self.bongcloud_check_button.pack(anchor=tk.NW)

# Create the mouse latency scale
mouse_latency_frame = tk.Frame(left_frame)
tk.Label(mouse_latency_frame, text="Mouse Latency (seconds)").pack(side=tk.LEFT, pady=(17, 0))
self.mouse_latency = tk.DoubleVar(value=0.0)
self.mouse_latency_scale = tk.Scale(mouse_latency_frame, from_=0.0, to=5, resolution=0.2, orient=tk.HORIZONTAL,
variable=self.mouse_latency)
self.mouse_latency_scale.pack()
mouse_latency_frame.pack(anchor=tk.NW)

# Separator
separator_frame = tk.Frame(left_frame)
separator = ttk.Separator(separator_frame, orient='horizontal')
Expand Down Expand Up @@ -431,6 +444,8 @@ def on_start_button_listener(self):
self.enable_manual_mode.get() == 1,
self.enable_mouseless_mode.get() == 1,
self.enable_non_stop_puzzles.get() == 1,
self.enable_non_stop_matches.get() == 1,
self.mouse_latency.get(),
self.enable_bongcloud.get() == 1,
self.slow_mover.get(),
self.skill_level.get(),
Expand Down
37 changes: 24 additions & 13 deletions src/stockfish_bot.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from random import random

import multiprocess
from stockfish import Stockfish
import pyautogui
Expand All @@ -15,7 +13,7 @@


class StockfishBot(multiprocess.Process):
def __init__(self, chrome_url, chrome_session_id, website, pipe, overlay_queue, stockfish_path, enable_manual_mode, enable_mouseless_mode, enable_non_stop_puzzles, bongcloud, slow_mover, skill_level, stockfish_depth, memory, cpu_threads):
def __init__(self, chrome_url, chrome_session_id, website, pipe, overlay_queue, stockfish_path, enable_manual_mode, enable_mouseless_mode, enable_non_stop_puzzles, enable_non_stop_matches, mouse_latency, bongcloud, slow_mover, skill_level, stockfish_depth, memory, cpu_threads):
multiprocess.Process.__init__(self)

self.chrome_url = chrome_url
Expand All @@ -27,6 +25,8 @@ def __init__(self, chrome_url, chrome_session_id, website, pipe, overlay_queue,
self.enable_manual_mode = enable_manual_mode
self.enable_mouseless_mode = enable_mouseless_mode
self.enable_non_stop_puzzles = enable_non_stop_puzzles
self.enable_non_stop_matches = enable_non_stop_matches
self.mouse_latency = mouse_latency
self.bongcloud = bongcloud
self.slow_mover = slow_mover
self.skill_level = skill_level
Expand Down Expand Up @@ -73,6 +73,7 @@ def make_move(self, move):

# Drag the piece from the start to the end position
pyautogui.moveTo(start_pos[0], start_pos[1])
time.sleep(self.mouse_latency)
pyautogui.dragTo(end_pos[0], end_pos[1])

# Check for promotion. If there is a promotion,
Expand All @@ -95,6 +96,17 @@ def wait_for_gui_to_delete(self):
while self.pipe.recv() != "DELETE":
pass

def go_to_next_puzzle(self):
self.grabber.click_puzzle_next()
self.pipe.send("RESTART")
self.wait_for_gui_to_delete()

def find_new_online_match(self):
time.sleep(2)
self.grabber.click_game_next()
self.pipe.send("RESTART")
self.wait_for_gui_to_delete()

def run(self):
if self.website == "chesscom":
self.grabber = ChesscomGrabber(self.chrome_url, self.chrome_session_id)
Expand Down Expand Up @@ -223,9 +235,9 @@ def run(self):
if board.is_checkmate():
# Send restart message to GUI
if self.enable_non_stop_puzzles and self.grabber.is_game_puzzles():
self.grabber.click_puzzle_next()
self.pipe.send("RESTART")
self.wait_for_gui_to_delete()
self.go_to_next_puzzle()
elif self.enable_non_stop_matches and not self.enable_non_stop_puzzles:
self.find_new_online_match()
return

time.sleep(0.1)
Expand All @@ -238,9 +250,9 @@ def run(self):
if self.grabber.is_game_over():
# Send restart message to GUI
if self.enable_non_stop_puzzles and self.grabber.is_game_puzzles():
self.grabber.click_puzzle_next()
self.pipe.send("RESTART")
self.wait_for_gui_to_delete()
self.go_to_next_puzzle()
elif self.enable_non_stop_matches and not self.enable_non_stop_puzzles:
self.find_new_online_match()
return
move_list = self.grabber.get_move_list()
if move_list is None:
Expand All @@ -256,10 +268,9 @@ def run(self):
if board.is_checkmate():
# Send restart message to GUI
if self.enable_non_stop_puzzles and self.grabber.is_game_puzzles():
self.grabber.click_puzzle_next()
self.pipe.send("RESTART")
self.wait_for_gui_to_delete()

self.go_to_next_puzzle()
elif self.enable_non_stop_matches and not self.enable_non_stop_puzzles:
self.find_new_online_match()
return
except Exception as e:
print(e)
Expand Down