Skip to content
This repository was archived by the owner on Mar 1, 2020. It is now read-only.

适应当前活动(羽蛇神圣诞) #4

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e3ef2ef
适应当前活动(羽蛇神圣诞)
yuezhilanyi Jan 12, 2020
55cabbc
毛巾本调整
yuezhilanyi Jan 16, 2020
def1bb6
适配女武神free本
yuezhilanyi Jan 21, 2020
5f37c82
连续刷同一关卡
yuezhilanyi Apr 17, 2021
39b20e1
fix a issue
yuezhilanyi Apr 18, 2021
d4c990b
add quest
yuezhilanyi Apr 22, 2021
96933ce
add caigang.py
yuezhilanyi Apr 27, 2021
8412db5
Create friend_merlin1.png
yuezhilanyi May 21, 2021
1b44675
Update tmhg422.py
yuezhilanyi May 21, 2021
2907983
__get_current_stage to get_current_stage
yuezhilanyi May 23, 2021
63e551c
Update tmhg422.py
yuezhilanyi May 23, 2021
77931fb
Create exp_cards_special.png
yuezhilanyi May 23, 2021
0650527
Create deming.py
yuezhilanyi May 23, 2021
4bdf6fb
Update bot.py
yuezhilanyi May 23, 2021
bd5d7ba
fix a bug using attack
yuezhilanyi May 23, 2021
68ca66e
add __end_battle to run
yuezhilanyi May 24, 2021
653b8e4
Update bot.py
yuezhilanyi May 24, 2021
0332426
Update bot.py
yuezhilanyi May 26, 2021
8a6aff1
add tm images
yuezhilanyi May 29, 2021
15fa93f
add todos
yuezhilanyi May 29, 2021
89ee752
remove __continue_battle
yuezhilanyi May 29, 2021
10c23c3
add an interval in front of friend choose
yuezhilanyi May 30, 2021
d31ab3c
Create friend_kuangna3.png
yuezhilanyi May 30, 2021
1226214
delete some files
yuezhilanyi Dec 18, 2021
8de5886
Update bot.py
yuezhilanyi Dec 18, 2021
6076866
add qp farm
yuezhilanyi Dec 18, 2021
80cdc02
Update refresh_friends.png
yuezhilanyi Jul 31, 2022
f730b7a
use skill fastly
yuezhilanyi Jul 31, 2022
58f699f
Update qp.png
yuezhilanyi Jul 31, 2022
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ m4/lt~obsolete.m4
autom4te.cache

/.idea
fgobot/__pycache__
screenshots/
16 changes: 16 additions & 0 deletions adb.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 连接 Mumu 模拟器
[关于 如何用电脑的adb连接Mumu模拟器](https://www.cnblogs.com/hankzhouAndroid/p/9070473.html)
```powershell
adb connect 127.0.0.1:7555
adb devices
```


# 连接 Nox 模拟器
[adb 如何连接夜神模拟器](https://blog.csdn.net/qq_36350532/article/details/79000653)

夜神模拟器需要使用自带的 adb.exe

```powershell
adb connect 127.0.0.1:62001
```
Binary file added exp_cards.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
106 changes: 75 additions & 31 deletions fgobot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
from time import sleep
from typing import Tuple, List, Union
from random import randint
import cv2
import time

logger = logging.getLogger('bot')

INTERVAL_SHORT = 1
INTERVAL_MID = 2
INTERVAL_LONG = 10
INTERVAL_SHORT = 0.5
INTERVAL_MID = 1
INTERVAL_LONG = 5


class BattleBot:
Expand Down Expand Up @@ -86,7 +88,7 @@ def __init__(self,
self.friend_threshold = friend_threshold

# Load button coords from config
btn_path = Path(__file__).absolute().parent / 'config' / 'buttons.json'
btn_path = 'fgobot/config/buttons.json'
with open(btn_path) as f:
self.buttons = json.load(f)

Expand Down Expand Up @@ -166,7 +168,7 @@ def __wait_until(self, im: str):
while not self.__exists(im):
self.__wait(INTERVAL_MID)

def __get_current_stage(self) -> int:
def get_current_stage(self) -> int:
"""
Get the current stage in battle.

Expand All @@ -189,6 +191,7 @@ def __get_current_stage(self) -> int:

def __find_friend(self) -> str:
self.__wait_until('refresh_friends')
self.__wait(INTERVAL_SHORT)
for _ in range(6):
for fid in range(self.friend_count):
im = 'f_{}'.format(fid)
Expand All @@ -198,16 +201,19 @@ def __find_friend(self) -> str:
self.__wait(INTERVAL_SHORT)
return ''

def __enter_battle(self) -> bool:
def __enter_battle(self, first: bool = None) -> bool:
"""
Enter the battle.

:return: whether successful.
"""
self.__wait_until('menu')
while not self.__find_and_tap('quest', threshold=self.quest_threshold):
self.__swipe('quest')
self.__wait(INTERVAL_SHORT)
if first:
self.__wait_until('menu')
while not self.__find_and_tap('quest', threshold=self.quest_threshold):
self.__swipe('quest')
self.__wait(INTERVAL_SHORT)
else:
self.__end_battle(continue_battle=True)
self.__wait(INTERVAL_MID)

# no enough AP
Expand All @@ -216,6 +222,10 @@ def __enter_battle(self) -> bool:
return False
else:
ok = False
# self.__find_and_tap('scoll_bar')
# self.__wait(1)
self.__swipe('ap')
self.__wait(INTERVAL_SHORT)
for ap_item in self.ap:
if self.__find_and_tap(ap_item):
self.__wait(1)
Expand All @@ -232,12 +242,14 @@ def __enter_battle(self) -> bool:
self.__find_and_tap('refresh_friends')
self.__wait(INTERVAL_SHORT)
self.__find_and_tap('yes')
self.__wait(INTERVAL_LONG)
friend = self.__find_friend()
# TODO: reduce wait time to 2.0(4xINTERVAL_SHORT)
self.__wait(INTERVAL_LONG)
self.__find_and_tap(friend)
self.__wait(INTERVAL_SHORT)
self.__wait_until('start_quest')
self.__find_and_tap('start_quest')
if first:
self.__wait_until('start_quest')
self.__find_and_tap('start_quest')
self.__wait(INTERVAL_SHORT)
self.__wait_until('attack')
return True
Expand All @@ -250,7 +262,7 @@ def __play_battle(self) -> int:
"""
rounds = 0
while True:
stage = self.__get_current_stage()
stage = self.get_current_stage()
if stage == -1:
logger.error("Failed to get current stage. Leaving battle...")
return rounds
Expand All @@ -260,27 +272,39 @@ def __play_battle(self) -> int:
.format(stage, self.stage_count, rounds))
self.stage_handlers[stage]()

flag = False
if stage == 3:
flag = True

while True:
self.__wait(INTERVAL_MID)
if self.__exists('bond') or self.__exists('bond_up'):
logger.info("'与从者的羁绊' detected. Leaving battle...")
return rounds
elif self.__exists('attack'):
logger.info("'Attack' detected. Continuing loop...")
break

def __end_battle(self):
# self.__find_and_tap('bond')
# self.__wait(INTERVAL_SHORT)
# self.__wait_until('gain_exp')
# self.__find_and_tap('gain_exp')
# self.__wait(INTERVAL_SHORT)
logger.debug("'Attack' detected. Continuing to next stage...")
if flag:
# TODO: brave card first
self.attack([1, 2, 3])
self.__wait(INTERVAL_MID)
else:
break

def __end_battle(self, continue_battle: bool = None):
"""
End the battle, or continue to the next battle

:param continue_battle: 是否连续初级

:return: count of rounds.
"""
self.__wait(INTERVAL_MID)
while not self.__exists('next_step'):
self.device.tap_rand(640, 360, 50, 50)
self.__wait(INTERVAL_MID)

self.__find_and_tap('next_step')
cv2.imwrite('screenshots/{}.jpg'.format(time.strftime("%Y%m%d-%H%M%S")), self.tm.screen)
self.__wait(INTERVAL_MID)

# quest first-complete reward
Expand All @@ -292,7 +316,16 @@ def __end_battle(self):
if self.__exists('not_apply'):
self.__find_and_tap('not_apply')

self.__wait_until('menu')
self.__wait_until('continue_battle')

if continue_battle:
# 连续战斗(点击连续出击,触发ap_regen或者从者的选择)
self.__find_and_tap('continue_battle')
else:
# TODO: exit for 1st exp card quest everyday
# 退出战斗(点击关闭,退出到菜单页面)
self.__find_and_tap('close')
self.__wait_until('menu')

def at_stage(self, stage: int):
"""
Expand Down Expand Up @@ -331,9 +364,14 @@ def use_skill(self, servant: int, skill: int, obj=None):
x, y, w, h = self.__button('choose_object')
x += self.buttons['choose_object_distance'] * (obj - 1)
self.device.tap_rand(x, y, w, h)
time.sleep(0.01)
self.device.tap_rand(x, y, w, h)
logger.debug('Chose skill object {}.'.format(obj))
else:
time.sleep(0.01)
self.device.tap_rand(x, y, w, h)

self.__wait(INTERVAL_SHORT * 2)
self.__wait(INTERVAL_SHORT)

def use_master_skill(self, skill: int, obj=None, obj2=None):
"""
Expand Down Expand Up @@ -408,8 +446,10 @@ def attack(self, cards: list):
x += self.buttons['card_distance'] * (card - 1)
self.device.tap_rand(x, y, w, h)
elif 6 <= card <= 8:
# self.__wait(INTERVAL_SHORT * 2)
x, y, w, h = self.__button('noble_card')
x += self.buttons['card_distance'] * (card - 6)
sleep(INTERVAL_MID * 2)
self.device.tap_rand(x, y, w, h)
else:
logger.error('Card number must be in range [1, 8]')
Expand All @@ -421,14 +461,18 @@ def run(self, max_loops: int = 10):
:param max_loops: the max number of loops.
"""
count = 0
for n_loop in range(max_loops):
self.__enter_battle(first=True)
self.__play_battle()
for n_loop in range(1, max_loops):
logger.info('Entering battle...')
if not self.__enter_battle():
if not self.__enter_battle(first=False):
logger.info('AP runs out. Quiting...')
break
rounds = self.__play_battle()
self.__end_battle()
count += 1
logger.info('{}-th Battle complete. {} rounds played.'.format(count, rounds))

logger.info('{} Battles played in total. Good bye!'.format(count))
if count == max_loops - 1:
logger.info('{} Battles played in total. Good bye!'.format(count + 1))
break
else:
logger.info('{}-th Battle complete. {} rounds played.'.format(count + 1, rounds))
self.__end_battle(continue_battle=False)
3 changes: 2 additions & 1 deletion fgobot/config/buttons.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"change_distance": 200,
"swipe": {
"friend": [600, 602, 600, 400],
"quest": [960, 588, 960, 400]
"quest": [960, 588, 960, 400],
"ap": [900, 500, 900, 400]
}
}
Binary file added fgobot/images/ap_regen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fgobot/images/bond_up.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fgobot/images/bronze_apple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fgobot/images/change.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fgobot/images/change_disabled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fgobot/images/continue_battle.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fgobot/images/decide.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fgobot/images/gold_apple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified fgobot/images/menu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified fgobot/images/not_apply.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified fgobot/images/refresh_friends.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added fgobot/images/silver_apple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified fgobot/images/start_quest.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added free.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added friend_merlin.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added friend_merlin1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified friend_qp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added friend_sikaha.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added friend_sikaha2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 8 additions & 12 deletions my_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

# AP策略为:当体力耗尽时,优先吃银苹果,再吃金苹果
# 如果不指定ap参数,则当体力耗尽时停止运行
ap=['silver_apple', 'gold_apple'],
# ap=['silver_apple', 'gold_apple'],

# 要打的关卡有3面
stage_count=3,
Expand All @@ -45,27 +45,23 @@
@bot.at_stage(1)
def stage_1():
# s(1, 1)表示使用1号从者的技能1
s(1, 1)
s(2, 1)
s(3, 1)
s(3, 3)
s(2, 3) # 大英雄充能
# (a[6, 1, 2])表示出卡顺序为:6号卡(1号从者宝具卡),1号卡,2号卡
a([6, 1, 2])
a([7, 1, 2]) # 大英雄宝具卡


# 第二面的打法
@bot.at_stage(2)
def stage_2():
# m(2, 1)表示使用御主技能2,对象为1号从者
m(2, 1)
a([6, 1, 2])
m(3, 3) # 拉尔群冲
a([7, 1, 2]) # 大流士宝具卡


# 第三面的打法
@bot.at_stage(3)
def stage_3():
s(1, 3)
a([6, 1, 2])
a([6, 1, 2]) # 狂兰宝具卡


# 程序的入口点(不加这行也可以)
Expand All @@ -74,7 +70,7 @@ def stage_3():
# 检查设备是否连接
if not bot.device.connected():
# 如果没有连接,则尝试通过本地端口62001连接(具体参数请参考自己的设备/模拟器)
bot.device.connect('127.0.0.1:62001')
bot.device.connect('127.0.0.1:7555')

# 启动bot,最多打5次
bot.run(max_loops=5)
# bot.run(max_loops=5)
Binary file modified qp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
79 changes: 79 additions & 0 deletions qp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import logging
import datetime
import argparse

from fgobot import BattleBot


# 指定日志的输出等级(DEBUG / INFO / WARNING / ERROR)
logging.basicConfig(level=logging.INFO)

# 实例化一个bot
bot = BattleBot(

# 要打的关卡截图为'qp.png',放在这个文件的同一级目录下
quest='qp.png',

# 需要的助战截图为'friend_qp.png',放在这个文件的同一级目录下
# 如果可以接受的助战有多个,可以传入一个list,例如:friend=['friend1.png', 'friend2.png]
friend=['friend_qp.png'],

# AP策略为:当体力耗尽时,优先吃银苹果,再吃金苹果
# 如果不指定ap参数,则当体力耗尽时停止运行
ap=['gold_apple'],

# 要打的关卡有3面
stage_count=3,

# 关卡图像识别的阈值为0.97
# 如果设的过低会导致进错本,太高会导致无法进本,请根据实际情况调整
quest_threshold=0.97,

# 助战图像识别的阈值为0.95
# 如果设的过低会导致选择错误的助战,太高会导致选不到助战,请根据实际情况调整
friend_threshold=0.85
)

# 为了方便,使用了简写
s = bot.use_skill
m = bot.use_master_skill
a = bot.attack


# 第一面的打法
@bot.at_stage(1)
def stage_1():
s(3, 1) # 梅林群冲
a([7, 1, 2]) # 尼托宝具卡


# 第二面的打法
@bot.at_stage(2)
def stage_2():
# m(2, 1)表示使用御主技能2,对象为1号从者
s(2, 2) # 尼托自冲
a([7, 1, 2]) # 尼托宝具卡


# 第三面的打法
@bot.at_stage(3)
def stage_3():
a([6, 1, 2]) # 宝具卡


# 程序的入口点(不加这行也可以)
# 使用时,可以直接在命令行运行'python my_bot.py'
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('-p', dest='port', default=62001, help='adb device port')
parser.add_argument('-n', dest='number_loops', default=3, help='number of loops to be ran')
parser.add_argument('-v', dest='verbosity', action='store_true', help='debug or not')
args = parser.parse_args()

# 检查设备是否连接
if not bot.device.connected():
# 如果没有连接,则尝试通过本地端口62001连接(具体参数请参考自己的设备/模拟器)
bot.device.connect(f'127.0.0.1:{args.port}')

# 启动bot,最多打5次
bot.run(max_loops=int(args.number_loops))
Loading