Sikuli - Как перебрать все совпадения с find

Я работаю над ботом для онлайн-игры. При входе в систему есть несколько серверов, из которых я должен выбрать. Каждый сервер имеет идентификатор "онлайн"/"оффлайн" рядом с именами серверов. Даже если есть несколько онлайн-серверов, бот будет выбирать только один из них, один и тот же каждый раз. И что странно, так это то, что сначала нужно найти другого, потому что на него надо нажать.

Я хочу настроить свой код, чтобы найти все "онлайн" экземпляры и выбрать один. Если это не удается подключиться, я хочу, чтобы он вернулся через меню и попробовал следующий потенциальный онлайн-сервер. Если серверу не удается подключиться или соединение с сервером потеряно, оно возвращается в главное меню с всплывающим окном "Потеря соединения с сервером". Ниже приведен код, с которым я работаю. Логика в основном проверяет любые проблемы, такие как потерянное соединение с сервером или смерть, и исправляет эти проблемы, прежде чем пытаться бороться.

BotOn = True
FighterBot = False

def runHotkey(event):
    global BotOn
    BotOn = False
Env.addHotkey(Key.ESC, KeyModifier.SHIFT, runHotkey)

def BotFighter(event):
    global FighterBot
    FighterBot = True
Env.addHotkey(Key.PAGE_UP,0, BotFighter)

def BotFighterOff(event):
    global FighterBot
    FighterBot = False
Env.addHotkey(Key.PAGE_DOWN,0, BotFighterOff)

while BotOn == True:
    while FighterBot == True:
        if exists("LostServerConnection.png"):
            click("LostServerConnection.png")
            wait(.5)
        if exists("LoginFailed.png"):
            click("LoginFailed.png")
            wait(.5)
        if exists("Login.png"):
            click("Login.png")
            wait(.5)
        if exists("Play.png"):
            click("Play.png") 
            wait(.5)
        if exists("OnlineServer.png"):
            click("OnlineServer.png")
            wait(("AttackButton.png")or("LostServerConnection.png"),FOREVER)
            if exists("AttackButton.png"):
                #commands for moving to specific location
            elif exists("LostServerConnection.png"):
                click("LostServerConnection.png")
                wait(.5)
        if exists("Revive.png"):
            click("Revive.png")     
            waitVanish("Revive.png")  
            wait("AttackButton.png")
            #commands for moving to specific location
        else:
            #commands for fighting

Я прошу прощения, что это грубо написано. Я все еще учусь и пытаюсь разобраться в этом вопросе, прежде чем очистить его.

Мой идеальный результат - иметь функцию, которая будет проверять, сколько серверов подключено к сети, создавать для них индекс и иметь возможность циклически проходить через этот индекс, когда он пытается войти в тот, который действительно работает.

( Sikuli Проверьте несколько одинаковых изображений на экране) Однако я попробовал то, что сказал Юджин С. в этой ссылке, когда я вводил изображение в "части изображения" его кода, и Sikuli допустил ошибку в первой строке:

Edit1: я перечитал некоторую важную информацию, которую я пропустил и исправил код. Это не ошибка сейчас, но на самом деле ничего не нажимает. Я уверен, что что-то упустил, поэтому я продолжу изучать это в то же время. (спасибо Евгений)

def returnImageCount(image):
    count = 0
    for i in findAll(image):
        count += 1
    return count
imageCount = returnImageCount("OnlineServer.png")

if imageCount == 1:
    click(buttonX.image)
elif imageCount == 2:
    click(buttonY.image)
else:
    pass

Edit2: я обновил ниже текущий код, с которым я работаю. Кажется, это намного ближе к тому, что я ищу. Но сейчас он находит все совпадения, затем нажимает на каждое, даже после того, как оно исчезает из загрузки первого, на которое оно щелкает. Я хотел бы иметь возможность делать то, что я добавил в своих комментариях. (спасибо Евгений)

wait(5)
OnlineServers = findAll(Pattern("OnlineServer.png").exact())
for Server in OnlineServers:
    Server.click()#(only click the first match)
    #wait for game to load OR server connection failed(wait as long as it takes)
    #if game load 
        #proceed to standard actions
    #elif server connection failed
        #log in
        #retry logic with next match in list
#(after it finishes going through all possible matches and fails each one, I want it to try again from the first match and go through the cycle again. So if there is only 1 match I want it to just keep trying that one.)

1 ответ

Решение

Я не осведомлен о вашей игровой логике, но если вам нужно работать с несколькими шаблонами, вы можете сделать это следующим образом:

Найдите их и сохраните в некотором списке:

resultsList = findAll("YOUR_FILE_NAME.png")

Затем для каждого найденного шаблона делайте с ним то, что вам нужно

for result in resultsList:
    result.highlight(1)
    #DO WHAT YOU NEED

В качестве альтернативы вы можете просто использовать первый элемент в списке и удалять его каждый раз, когда вам требуется следующий элемент:

NEXT_PATTERN = results.pop(0)

Вам придется подумать о стратегии, которая имеет смысл для вас, и реализовать ее, используя концепции, которые я упомянул. ИМХО, вы должны разбить все свои основные задачи на блоки, а затем построить свою основную логику. Например, вы можете реализовать такие функции:

def waitForGameToLoad():
    # Wait sufficienttime and verify that the game has been actually successfully started

def isGameLoaded():
    # Just and exmaple of another function that can be used internally inside waitForGameToLoad

def getNextAvailableServer():
    # Get next available server from a list that you have previously created

В результате вы можете построить основной логический блок так, чтобы его было гораздо проще понять, например:

availableServersList = getAvailableServers() # getAvailableServers is a function that you will have to implement yourself

while True:
    connectServer(availableServersList)

    if connected():
        break

НОТА

То, что я описал выше, является лишь общим предложением о том, как вы можете реализовать свою основную логику. Вам не нужно следовать этому напрямую. Попробуйте создать функции, которые будут иметь смысл для вас, а затем использовать их вместе для создания логического потока.

Другие вопросы по тегам