Skip to content

Commit

Permalink
more settings
Browse files Browse the repository at this point in the history
  • Loading branch information
latorc committed Apr 7, 2024
1 parent ae5adf5 commit 4f2510f
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 111 deletions.
2 changes: 1 addition & 1 deletion MahjongCopilot.spec
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


a = Analysis(
['gui.py'],
['main.py'],
pathex=[],
binaries=[],
datas=[],
Expand Down
2 changes: 1 addition & 1 deletion bot_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ def _update_overlay_botleft(self):

text += '\n' + line
# display fps numbers and limit total width
text += f"\nFPS: {self.fps_counter.fps:3.0f} / {self.browser.fps_counter.fps:3.0f}"[:18]
# text += f"\nFPS: {self.fps_counter.fps:3.0f} / {self.browser.fps_counter.fps:3.0f}"[:18]

# update if there is a change or time elapsed. avoid too often to burden browser
if text != self._overlay_botleft_text or time.time() - self._overlay_botleft_last_update > 1:
Expand Down
4 changes: 3 additions & 1 deletion common/lan_str.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class LanStr:
LOGIN_TO_REFRESH = "Log in to refresh"
MITM_PORT_ERROR_PROMPT = "Invalid MITM Port (must between 1000~65535)"
AUTO_PLAY_SETTINGS = "Autoplay Settings"
RANDOM_DELAY_RANGE = "Base Delay Range (sec)"
AUTO_JOIN_GAME = "Auto Join"
GAME_LEVELS = ["Bronze", "Silver", "Gold", "Jade", "Throne"]
GAME_MODES = ["4-p East","4-p South","3-p East","3-p South"]
Expand Down Expand Up @@ -200,9 +201,10 @@ class LanStrZHS(LanStr):
MITM_PORT_ERROR_PROMPT = "错误的 MITM 服务端口(必须是1000~65535)"
AUTO_PLAY_SETTINGS = "自动打牌设置"
AUTO_JOIN_GAME = "自动加入"
RANDOM_DELAY_RANGE = "基础延迟随机范围(秒)"
GAME_LEVELS = ["铜之间", "银之间", "金之间", "玉之间", "王座之间"]
GAME_MODES = ["四人东","四人南","三人东","三人南"]
MOUSE_RANDOM_MOVES = "鼠标移动随机化"
MOUSE_RANDOM_MOVES = "鼠标随机移动次数"

# Status
MAIN_THREAD = "主程序"
Expand Down
11 changes: 8 additions & 3 deletions common/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,11 @@ def __init__(self, json_file:str=DEFAULT_SETTING_FILE) -> None:
self.enable_automation:bool = self._get_value("enable_automation", False, self.valid_bool)
self.enable_overlay:bool = self._get_value("enable_overlay", True, self.valid_bool)

self.delay_random_lower:float = self._get_value("delay_random_lower", 1, lambda x: 0 <= x )
self.delay_random_upper:float = self._get_value(
"delay_random_upper",self.delay_random_lower, lambda x: x >= self.delay_random_lower)
self.auto_retry_interval:float = self._get_value("auto_retry_interval", 1.5, lambda x: 0.5 < x < 30.0)
self.auto_random_move:int = self._get_value("auto_random_move", 3, lambda x: 0 <= x <= 5)
self.auto_random_moves:int = self._get_value("auto_random_moves", 3, lambda x: 0 <= x <= 10)
self.auto_join_game:bool = self._get_value("auto_join_game", False, self.valid_bool)
self.auto_join_level:int = self._get_value("auto_join_level", 1, self.valid_game_level)
self.auto_join_mode:int = self._get_value("auto_join_mode", utils.GAME_MODES[0], self.valid_game_mode)
Expand Down Expand Up @@ -114,7 +117,7 @@ def valid_username(self, username:str) -> bool:
return True
else:
return False

def valid_game_level(self, level:int) -> bool:
""" return true if game level is valid"""
if 0 <= level <= 4:
Expand All @@ -128,4 +131,6 @@ def valid_game_mode(self, mode:str) -> bool:
if mode in utils.GAME_MODES:
return True
else:
return False
return False


37 changes: 18 additions & 19 deletions game/automation.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ def __init__(self, browser: GameBrowser, setting:Settings):
if browser is None:
raise ValueError("Browser is None")
self.executor = browser
self.settings = setting
self.st = setting
self.g_v = GameVisual(browser)

self._task:AutomationTask = None # the task thread
Expand All @@ -286,7 +286,7 @@ def can_automate(self) -> bool:
"""return True if automation conditions met
params:
in_game(bool): True if must in game"""
if not self.settings.enable_automation: # automation not enabled
if not self.st.enable_automation: # automation not enabled
return False
if not self.executor.is_page_normal(): # browser is not running
return False
Expand All @@ -295,8 +295,7 @@ def can_automate(self) -> bool:
def get_delay(self, mjai_action:dict, gi:GameInfo):
""" return the delay based on action type and game info"""
mjai_type = mjai_action['type']
delay = random.uniform(0.5, 1.5) # base delay

delay = random.uniform(self.st.delay_random_lower, self.st.delay_random_upper) # base delay
if mjai_type == MJAI_TYPE.DAHAI:
# extra time for first round and East
if gi.is_first_round:
Expand Down Expand Up @@ -395,10 +394,10 @@ def steps_action_dahai(self, mjai_action:dict, gi:GameInfo) -> list[ActionStepTu
else:
x = Positions.TEHAI_X[dahai_count] + Positions.TRUMO_SPACE
y = Positions.TEHAI_Y
steps = self.steps_randomized_move_click(x, y, random.randint(1,3))
steps = self.steps_randomized_move_click(x, y)
else: # tedashi: find the index and discard
idx = gi.my_tehai.index(dahai)
steps = self.steps_randomized_move_click(Positions.TEHAI_X[idx], Positions.TEHAI_Y, random.randint(1,5))
steps = self.steps_randomized_move_click(Positions.TEHAI_X[idx], Positions.TEHAI_Y)
# move to mid to avoid highlighting a tile
delay_step = ActionStepDelay(random.uniform(0.5, 0.1))
delay_step.ignore_step_change = True
Expand All @@ -419,7 +418,7 @@ def _process_oplist_for_kan(self, mstype_from_mjai, op_list:list) -> list:
kan_combs:list[str] = []
idx_to_keep = None
idx_to_del = None
for idx, op in op_list:
for idx, op in enumerate(op_list):
op_type = op['type']
if op_type in (MSType.kakan, MSType.ankan):
if op_type== MSType.kakan:
Expand Down Expand Up @@ -531,13 +530,13 @@ def steps_randomized_move(self, x:float, y:float, random_moves:int=None) -> list
random_moves(int): number of random moves before target. None -> use randint"""
steps = []
if random_moves is None:
random_moves = random.randint(1,5)
random_moves = self.st.auto_random_moves

for _i in range(random_moves): # random moves, within (-0.5, 0.5) of target
rx = int(x + random.uniform(-0.5, 0.5))
rx = max(0, min(1, rx))
ry = int(y + random.uniform(-0.5, 0.5))
ry = max(0, min(1, ry))
rx = x + 16*random.uniform(-0.5, 0.5)
rx = max(0, min(16, rx))
ry = y + 9*random.uniform(-0.5, 0.5)
ry = max(0, min(9, ry))
steps.append(ActionStepMove(rx*self.scaler, ry*self.scaler, random.randint(5,15)))
steps.append(ActionStepDelay(random.uniform(0.05, 0.15)))
tx, ty = x*self.scaler, y*self.scaler
Expand Down Expand Up @@ -593,7 +592,7 @@ def automate_end_game(self):
"""Automate Game end go back to menu"""
if not self.can_automate():
return False
if self.settings.auto_join_game is False:
if self.st.auto_join_game is False:
return False
self.stop_previous()

Expand All @@ -613,17 +612,17 @@ def _end_game_iter(self) -> Iterator[ActionStep]:
yield ActionStepDelay(random.uniform(1,2))

x,y = Positions.GAMEOVER[0]
for step in self.steps_randomized_move_click(x,y,random.randint(1,3)):
for step in self.steps_randomized_move_click(x,y):
yield step

def automate_join_game(self):
""" Automate join next game """
if not self.can_automate():
return False
if self.settings.auto_join_game is False:
if self.st.auto_join_game is False:
return False
self.stop_previous()
desc = f"Join the next game level={self.settings.auto_join_level}, mode={self.settings.auto_join_mode}"
desc = f"Join the next game level={self.st.auto_join_level}, mode={self.st.auto_join_mode}"
self._task = AutomationTask(self.executor, JOIN_GAME, desc)
self._task.start_action_steps(self._join_game_iter(), None)
return
Expand All @@ -647,19 +646,19 @@ def _join_game_iter(self) -> Iterator[ActionStep]:
yield ActionStepDelay(random.uniform(1.5,2))

# click on level
if self.settings.auto_join_level >= 3: # jade/throne requires mouse wheel
if self.st.auto_join_level >= 3: # jade/throne requires mouse wheel
wx,wy = Positions.LEVELS[1] # wheel at this position
for step in self.steps_randomized_move(wx,wy):
yield step
for step in self.steps_random_wheels(0, 500):
yield step
x,y = Positions.LEVELS[self.settings.auto_join_level]
x,y = Positions.LEVELS[self.st.auto_join_level]
for step in self.steps_randomized_move_click(x,y):
yield step
yield ActionStepDelay(random.uniform(1.5,2))

# click on mode
mode_idx = GAME_MODES.index(self.settings.auto_join_mode)
mode_idx = GAME_MODES.index(self.st.auto_join_mode)
x,y = Positions.MODES[mode_idx]
for step in self.steps_randomized_move_click(x,y):
yield step
Expand Down
2 changes: 1 addition & 1 deletion game/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ def _action_overlay_update_botleft(self, text:str=None):
if self.is_overlay_working() is False:
return
font_size = int(self.height/48)
box_top = 0.86
box_top = 0.885
box_left = 0
box_width = 0.115
box_height = 1- box_top
Expand Down
6 changes: 3 additions & 3 deletions game/game_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -594,9 +594,9 @@ def _react_all(self, data=None) -> dict | None:
# return output_reactions[-1] # return the last reaction

# return None if no operation options provided by Majsoul
if data:
if 'operation' not in data or 'operationList' not in data['operation'] or len(data['operation']['operationList']) == 0:
return None
# if data:
# if 'operation' not in data or 'operationList' not in data['operation'] or len(data['operation']['operationList']) == 0:
# return None
LOGGER.info("Bot in: %s", self.mjai_pending_input_msgs)
if len(self.mjai_pending_input_msgs) == 1:
output_reaction = self.mjai_bot.react(self.mjai_pending_input_msgs[0])
Expand Down
Loading

0 comments on commit 4f2510f

Please sign in to comment.