fix bug-道中战斗失败撤退#99
Conversation
审阅者指南(在小型 PR 上折叠)审阅者指南回滚并简化了中途战斗撤退逻辑,将其改为更稳定的、基于计时器确认的流程,并移除了未使用的、由紧急委托驱动的撤退处理。 auto_search_combat_status 中撤退处理与紧急委托的时序图sequenceDiagram
participant AutoSearch as AutoSearchCombat
participant Timer as withdraw_stable_timer
loop auto_search_combat_status loop
alt _withdraw is True
AutoSearch->>AutoSearch: appear_then_click FLEET_SWITCH_CONFIRM
alt FLEET_SWITCH_CONFIRM clicked
AutoSearch->>AutoSearch: set fleet_alive_multiple False
AutoSearch->>AutoSearch: set _withdraw False
AutoSearch-->>AutoSearch: continue
else not clicked
AutoSearch->>AutoSearch: appear WITHDRAW
alt WITHDRAW appears
AutoSearch->>Timer: reached
alt not reached
AutoSearch-->>AutoSearch: continue
else reached
AutoSearch->>AutoSearch: appear WITHDRAW
alt WITHDRAW no longer appears
AutoSearch->>Timer: reset
AutoSearch-->>AutoSearch: continue
else stable WITHDRAW
AutoSearch->>AutoSearch: set _withdraw False
alt config.Campaign_DefeatWithdraw or not fleet_alive_multiple
AutoSearch->>AutoSearch: withdraw
AutoSearch-->>AutoSearch: break
else need continue battle
AutoSearch->>AutoSearch: wait loop (screenshot, click)
end
end
end
else WITHDRAW not appears
AutoSearch->>Timer: reset
AutoSearch-->>AutoSearch: continue
end
end
else normal handling
AutoSearch->>AutoSearch: handle_popup_confirm
AutoSearch->>AutoSearch: handle_urgent_commission
AutoSearch->>AutoSearch: handle_story_skip
end
end
文件级变更
提示与命令与 Sourcery 交互
自定义你的体验访问你的控制面板以:
获取帮助Original review guide in EnglishReviewer's guide (collapsed on small PRs)Reviewer's GuideReverts and simplifies the mid-route combat withdrawal logic to a more stable, timer-based confirmation flow and removes unused urgent-commission-driven withdrawal handling. Sequence diagram for withdrawal handling and urgent commission in auto_search_combat_statussequenceDiagram
participant AutoSearch as AutoSearchCombat
participant Timer as withdraw_stable_timer
loop auto_search_combat_status loop
alt _withdraw is True
AutoSearch->>AutoSearch: appear_then_click FLEET_SWITCH_CONFIRM
alt FLEET_SWITCH_CONFIRM clicked
AutoSearch->>AutoSearch: set fleet_alive_multiple False
AutoSearch->>AutoSearch: set _withdraw False
AutoSearch-->>AutoSearch: continue
else not clicked
AutoSearch->>AutoSearch: appear WITHDRAW
alt WITHDRAW appears
AutoSearch->>Timer: reached
alt not reached
AutoSearch-->>AutoSearch: continue
else reached
AutoSearch->>AutoSearch: appear WITHDRAW
alt WITHDRAW no longer appears
AutoSearch->>Timer: reset
AutoSearch-->>AutoSearch: continue
else stable WITHDRAW
AutoSearch->>AutoSearch: set _withdraw False
alt config.Campaign_DefeatWithdraw or not fleet_alive_multiple
AutoSearch->>AutoSearch: withdraw
AutoSearch-->>AutoSearch: break
else need continue battle
AutoSearch->>AutoSearch: wait loop (screenshot, click)
end
end
end
else WITHDRAW not appears
AutoSearch->>Timer: reset
AutoSearch-->>AutoSearch: continue
end
end
else normal handling
AutoSearch->>AutoSearch: handle_popup_confirm
AutoSearch->>AutoSearch: handle_urgent_commission
AutoSearch->>AutoSearch: handle_story_skip
end
end
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - 我发现了 1 个问题
给 AI 代理的提示
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="module/combat/auto_search_combat.py" line_range="336-337" />
<code_context>
- continue
-
- logger.info(f'fleet_alive_multiple: {self.fleet_alive_multiple}')
+ if self._withdraw and self.appear(WITHDRAW, offset=(30, 30)):
self._withdraw = False
if self.config.Campaign_DefeatWithdraw or not self.fleet_alive_multiple:
self.withdraw()
</code_context>
<issue_to_address>
**issue (bug_risk):** 当 WITHDRAW 未出现时的行为发生了变化,可能会在继续执行剩余循环的同时让 `_withdraw` 保持为 True。
在旧的逻辑下,一旦 `self._withdraw` 被设置为 True,循环就会一直 `continue`,直到撤退 UI 达到已知状态(处理完 `FLEET_SWITCH_CONFIRM`,或 `WITHDRAW` 未能出现)。在新的条件下,如果 `self._withdraw` 为 True 但 `self.appear(WITHDRAW, …)` 为 False,执行就会向下继续,`auto_search_combat_status` 剩余的部分会在 `_withdraw` 仍为 True 的情况下运行。这改变了控制流,并可能在其他分支执行时让系统处于待撤退的悬而未决状态。如果你想保持之前的行为,大概率需要在 `_withdraw` 为 True 但 `WITHDRAW` 不可见时,保留一个提前的 `continue`(或等价的显式处理)。
</issue_to_address>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据反馈改进给你的代码评审。
Original comment in English
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="module/combat/auto_search_combat.py" line_range="336-337" />
<code_context>
- continue
-
- logger.info(f'fleet_alive_multiple: {self.fleet_alive_multiple}')
+ if self._withdraw and self.appear(WITHDRAW, offset=(30, 30)):
self._withdraw = False
if self.config.Campaign_DefeatWithdraw or not self.fleet_alive_multiple:
self.withdraw()
</code_context>
<issue_to_address>
**issue (bug_risk):** Behavior when WITHDRAW does not appear has changed and may leave `_withdraw` True while continuing the rest of the loop.
Under the old logic, once `self._withdraw` was set, the loop always `continue`d until the withdraw UI reached a known state (`FLEET_SWITCH_CONFIRM` handled, or `WITHDRAW` failed to appear). With the new condition, if `self._withdraw` is True but `self.appear(WITHDRAW, …)` is False, execution now falls through and the rest of `auto_search_combat_status` runs with `_withdraw` still True. This changes the control flow and can leave the system in a pending withdraw state while other branches execute. If you want to match the previous behavior, you likely need to keep an early `continue` (or equivalent explicit handling) when `_withdraw` is True but `WITHDRAW` is not visible.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| if self._withdraw and self.appear(WITHDRAW, offset=(30, 30)): | ||
| self._withdraw = False |
There was a problem hiding this comment.
issue (bug_risk): 当 WITHDRAW 未出现时的行为发生了变化,可能会在继续执行剩余循环的同时让 _withdraw 保持为 True。
在旧的逻辑下,一旦 self._withdraw 被设置为 True,循环就会一直 continue,直到撤退 UI 达到已知状态(处理完 FLEET_SWITCH_CONFIRM,或 WITHDRAW 未能出现)。在新的条件下,如果 self._withdraw 为 True 但 self.appear(WITHDRAW, …) 为 False,执行就会向下继续,auto_search_combat_status 剩余的部分会在 _withdraw 仍为 True 的情况下运行。这改变了控制流,并可能在其他分支执行时让系统处于待撤退的悬而未决状态。如果你想保持之前的行为,大概率需要在 _withdraw 为 True 但 WITHDRAW 不可见时,保留一个提前的 continue(或等价的显式处理)。
Original comment in English
issue (bug_risk): Behavior when WITHDRAW does not appear has changed and may leave _withdraw True while continuing the rest of the loop.
Under the old logic, once self._withdraw was set, the loop always continued until the withdraw UI reached a known state (FLEET_SWITCH_CONFIRM handled, or WITHDRAW failed to appear). With the new condition, if self._withdraw is True but self.appear(WITHDRAW, …) is False, execution now falls through and the rest of auto_search_combat_status runs with _withdraw still True. This changes the control flow and can leave the system in a pending withdraw state while other branches execute. If you want to match the previous behavior, you likely need to keep an early continue (or equivalent explicit handling) when _withdraw is True but WITHDRAW is not visible.
There was a problem hiding this comment.
Code Review
This pull request simplifies the withdrawal logic in the combat module and introduces a minor formatting change. The review feedback identifies a potential logic bug where resetting the withdrawal flag too early could cause the script to skip necessary actions if interrupted by other events, such as urgent commissions. Additionally, a PEP 8 style violation was noted due to a missing space after a comma in a function call.
| if self._withdraw and self.appear(WITHDRAW, offset=(30, 30)): | ||
| self._withdraw = False |
There was a problem hiding this comment.
这里的逻辑修改可能会导致在战斗失败后的撤退操作被跳过。在第337行直接将 self._withdraw 设为 False,如果此时 get_urgent_commission 为 True(例如在之前的循环中处理了紧急委托),代码会进入第341行的 elif 分支并执行 continue。由于 _withdraw 标志已被清除,后续的循环将无法再次进入此撤退逻辑块,导致脚本卡在显示“撤退”按钮的地图界面,无法继续执行。建议将 self._withdraw = False 的赋值移动到实际执行撤退操作(如调用 self.withdraw() 或进入切换舰队循环)的分支内部,以确保撤退逻辑被正确执行。
| if self.appear_then_click(FLEET_WITHDRAW, offset=(30, 30)): | ||
| break | ||
| if self.appear_then_click(SWITCH_OVER, interval=2): | ||
| if self.appear_then_click(SWITCH_OVER,interval=2): |
|
会出现卡在切换到第二舰队的弹窗 |
|
刚刚试了一下,确实会卡住,我之前处理这个弹窗利用的这段代码 如果这段代码不行的话,换成你新加的也可以,但是需要get_urgent_commission = True,用于判断已经弹过窗导致舰队撤退了,否则 此段代码的elif不生效,会触发while死循环。 |
|
不知道,我只知道你之前pr的版本会有这个问题所以做了点改动,我这边跑起来可以正常撤退来着
获取Outlook for Android<https://aka.ms/AAb9ysg>
…________________________________
From: ~月 ***@***.***>
Sent: Saturday, May 16, 2026 10:44:30 PM
To: wess09/AzurPilot ***@***.***>
Cc: 茗 ***@***.***>; Comment ***@***.***>
Subject: Re: [wess09/AzurPilot] fix bug-道中战斗失败撤退 (PR #99)
[https://avatars.githubusercontent.com/u/73020805?s=20&v=4]moon-dim left a comment (wess09/AzurPilot#99)<#99 (comment)>
刚刚试了一下,确实会卡住,我之前处理这个弹窗利用的这段代码
if self.handle_urgent_commission():
get_urgent_commission = True
如果这段代码不行的话,换成你新加的也可以,但是需要get_urgent_commission = True,用于判断已经弹过窗导致舰队撤退了,否则
elif get_urgent_commission:
self.fleet_alive_multiple = False
continue
else:
while True:
此段代码的elif不生效,会触发while死循环。
―
Reply to this email directly, view it on GitHub<#99 (comment)>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/BEIZFPMJTNUZGY63NIWUPQT43B5E5AVCNFSM6AAAAACZALY5OGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DINRXGE3DIMJWHE>.
You are receiving this because you commented.Message ID: ***@***.***>
|
建议你来做修复 毕竟你的需求你更清楚些 |
我正在试,不过我现在用你的代码也识别不到弹窗了,并且在有弹窗的情况下还会识别到红色的撤退TAT |
我来改吧,改好了再给提交给你 |
|
现在应该可以了,弹窗会比红色撤退按钮后出现,所以会有一刻检测到红色撤退按钮,导致判断成另一种不会不会出现弹窗的情况。 |
There was a problem hiding this comment.
Hey - 我发现了 2 个问题
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="module/combat/auto_search_combat.py" line_range="324" />
<code_context>
self.device.click_record_clear()
exp_info = False # This is for the white screen bug in game
- get_urgent_commission = False
+ withdraw_stable_timer = Timer(2)
for _ in self.loop():
</code_context>
<issue_to_address>
**issue (bug_risk):** 计时器在真正需要之前就被启动了,这会破坏预期的 2 秒稳定性检查。
由于 `withdraw_stable_timer` 是在 `auto_search_combat_status` 开头创建的,当 `self._withdraw` 变为 `True` 且 WITHDRAW 界面出现时,它可能已经过期。这样 `withdraw_stable_timer.reached()` 会在第一次检测到 WITHDRAW 时就返回 `True`,从而跳过预期的 2 秒稳定窗口。相反,应在首次进入撤退流程时(例如 `_withdraw` 变为 `True` 时,或第一次检测到 WITHDRAW 时)创建或重置计时器,使其衡量的是 WITHDRAW 界面保持稳定的 2 秒时间,而不是整个函数执行时间。
</issue_to_address>
### Comment 2
<location path="module/combat/auto_search_combat.py" line_range="342-345" />
<code_context>
+ self._withdraw = False
continue
+
+ if self.appear(WITHDRAW, offset=(30, 30)):
+ if not withdraw_stable_timer.reached():
+ continue
if not self.appear(WITHDRAW, offset=(30, 30)):
+ withdraw_stable_timer.reset()
continue
</code_context>
<issue_to_address>
**suggestion (bug_risk):** 在每次循环迭代中检查两次 WITHDRAW,可能会引入不稳定性和冗余工作。
`self.appear(WITHDRAW, offset=(30, 30))` 在同一个分支中被调用了两次:一次在计时器检查之前,一次在重置之前。这样会造成多余的工作,并引入 TOCTOU 风险,因为第二次调用可能与第一次不一致(例如由于瞬时画面变化),从而导致意外的计时器重置。可以考虑只调用一次 `appear`,将结果存储下来,并用这一份结果同时驱动 `reached()` 检查以及重置/continue 逻辑:
```python
visible = self.appear(WITHDRAW, offset=(30, 30))
if visible:
if not withdraw_stable_timer.reached():
continue
else:
withdraw_stable_timer.reset()
continue
```
</issue_to_address>帮我变得更有用!请在每条评论上点击 👍 或 👎,我会根据你的反馈改进后续的代码审查。
Original comment in English
Hey - I've found 2 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="module/combat/auto_search_combat.py" line_range="324" />
<code_context>
self.device.click_record_clear()
exp_info = False # This is for the white screen bug in game
- get_urgent_commission = False
+ withdraw_stable_timer = Timer(2)
for _ in self.loop():
</code_context>
<issue_to_address>
**issue (bug_risk):** Timer is started long before it is actually needed, which can defeat the intended 2-second stability check.
Because `withdraw_stable_timer` is created at the start of `auto_search_combat_status`, it may have already expired by the time `self._withdraw` is `True` and the WITHDRAW screen appears. Then `withdraw_stable_timer.reached()` will return `True` on the first WITHDRAW detection, skipping the intended 2-second stability window. Instead, create or reset the timer when you first enter the withdraw flow (e.g. when `_withdraw` becomes `True` or on the first WITHDRAW detection) so it measures 2 seconds of a stable WITHDRAW screen, not total function time.
</issue_to_address>
### Comment 2
<location path="module/combat/auto_search_combat.py" line_range="342-345" />
<code_context>
+ self._withdraw = False
continue
+
+ if self.appear(WITHDRAW, offset=(30, 30)):
+ if not withdraw_stable_timer.reached():
+ continue
if not self.appear(WITHDRAW, offset=(30, 30)):
+ withdraw_stable_timer.reset()
continue
</code_context>
<issue_to_address>
**suggestion (bug_risk):** WITHDRAW is checked twice per loop iteration, which can introduce instability and redundant work.
`self.appear(WITHDRAW, offset=(30, 30))` is invoked twice in the same branch: once before the timer check and once before the reset. This does redundant work and introduces a TOCTOU risk where the second call may disagree with the first (e.g., due to a transient frame), causing an unintended timer reset. Consider calling `appear` once, storing the result, and using that single value for both the `reached()` check and the reset/continue logic:
```python
visible = self.appear(WITHDRAW, offset=(30, 30))
if visible:
if not withdraw_stable_timer.reached():
continue
else:
withdraw_stable_timer.reset()
continue
```
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| self.device.click_record_clear() | ||
| exp_info = False # This is for the white screen bug in game | ||
| get_urgent_commission = False | ||
| withdraw_stable_timer = Timer(2) |
There was a problem hiding this comment.
issue (bug_risk): 计时器在真正需要之前就被启动了,这会破坏预期的 2 秒稳定性检查。
由于 withdraw_stable_timer 是在 auto_search_combat_status 开头创建的,当 self._withdraw 变为 True 且 WITHDRAW 界面出现时,它可能已经过期。这样 withdraw_stable_timer.reached() 会在第一次检测到 WITHDRAW 时就返回 True,从而跳过预期的 2 秒稳定窗口。相反,应在首次进入撤退流程时(例如 _withdraw 变为 True 时,或第一次检测到 WITHDRAW 时)创建或重置计时器,使其衡量的是 WITHDRAW 界面保持稳定的 2 秒时间,而不是整个函数执行时间。
Original comment in English
issue (bug_risk): Timer is started long before it is actually needed, which can defeat the intended 2-second stability check.
Because withdraw_stable_timer is created at the start of auto_search_combat_status, it may have already expired by the time self._withdraw is True and the WITHDRAW screen appears. Then withdraw_stable_timer.reached() will return True on the first WITHDRAW detection, skipping the intended 2-second stability window. Instead, create or reset the timer when you first enter the withdraw flow (e.g. when _withdraw becomes True or on the first WITHDRAW detection) so it measures 2 seconds of a stable WITHDRAW screen, not total function time.
| if self.appear(WITHDRAW, offset=(30, 30)): | ||
| if not withdraw_stable_timer.reached(): | ||
| continue | ||
| if not self.appear(WITHDRAW, offset=(30, 30)): |
There was a problem hiding this comment.
suggestion (bug_risk): 在每次循环迭代中检查两次 WITHDRAW,可能会引入不稳定性和冗余工作。
self.appear(WITHDRAW, offset=(30, 30)) 在同一个分支中被调用了两次:一次在计时器检查之前,一次在重置之前。这样会造成多余的工作,并引入 TOCTOU 风险,因为第二次调用可能与第一次不一致(例如由于瞬时画面变化),从而导致意外的计时器重置。可以考虑只调用一次 appear,将结果存储下来,并用这一份结果同时驱动 reached() 检查以及重置/continue 逻辑:
visible = self.appear(WITHDRAW, offset=(30, 30))
if visible:
if not withdraw_stable_timer.reached():
continue
else:
withdraw_stable_timer.reset()
continueOriginal comment in English
suggestion (bug_risk): WITHDRAW is checked twice per loop iteration, which can introduce instability and redundant work.
self.appear(WITHDRAW, offset=(30, 30)) is invoked twice in the same branch: once before the timer check and once before the reset. This does redundant work and introduces a TOCTOU risk where the second call may disagree with the first (e.g., due to a transient frame), causing an unintended timer reset. Consider calling appear once, storing the result, and using that single value for both the reached() check and the reset/continue logic:
visible = self.appear(WITHDRAW, offset=(30, 30))
if visible:
if not withdraw_stable_timer.reached():
continue
else:
withdraw_stable_timer.reset()
continue
由于出现bug,将道中战斗失败撤退的代码修改回原pr的代码。

log.txt
原代码中
if self.appear_then_click(FLEET_SWITCH_CONFIRM, offset=(30, 30)):的功能等价于if self.handle_urgent_commission():。我没测试出我写的代码的bug,于是复原了我的代码,若有发现bug请告知一下。
Summary by Sourcery
恢复并调整战斗中撤退处理逻辑,以解决基于战败触发的撤退行为问题。
Bug 修复:
增强:
Original summary in English
Summary by Sourcery
Restore and adjust in-battle withdrawal handling logic to address issues with defeat-based retreat behavior.
Bug Fixes:
Enhancements:
Original summary in English
Summary by Sourcery
恢复并调整战斗中撤退处理逻辑,以解决基于战败触发的撤退行为问题。
Bug 修复:
增强:
Original summary in English
Summary by Sourcery
Restore and adjust in-battle withdrawal handling logic to address issues with defeat-based retreat behavior.
Bug Fixes:
Enhancements: