← Back to team overview

sikuli-driver team mailing list archive

Re: [Question #207372]: Create Region from Match/Speeding up Searches!

 

Question #207372 on Sikuli changed:
https://answers.launchpad.net/sikuli/+question/207372

    Status: Open => Answered

RaiMan proposed the following answer:
Since it looked challenging, I made a script based on how I think the
game has to be played (In Germany it is called Memory).

You have to turn 2 cards. If they have the same image, it is a pair and
is taken away. If not, then they are turned again and you can turn again
2 cards. The game is over, if all pairs are found (or the time is over).

Supposing this online version is played alone (usually it is played by 2
or more players with many more cards), I have made a generally usable
script, that only needs the geometry of the play GUI and "learns" the
images on its own:

1. start with the top left 2 cards
2. if they match, remove them
3. if not, remember the images and turn them again
4. turn the next card in order left-right/top-down and check against remembered images
5. if we know the card already, turn the remembered card, un-remember it, remove the cards and proceed with 4.
6. if it is new, turn next card in order
7. if they match,remove them and proceed with 4.
8. otherwise check wether we know the card, turn the cards again, open these 2 known cards again, remove them and proceed with step 4

Since I do not know the game in real life and its behavior, I used hover(), to position on the cards.
These have to be changed to click() (which seems to turn the card) and there might be some wait()'s necessary, to give the GUI some time to react.

The script is faster than a human player(even much faster, if the
highlight()'s are commented out), but does not check the timeout (so if
the timeout happens, it will crash with an index out of bounds
exception).

The GUI geometry might have to be adjusted.

If I totally misunderstood the game, then at least the script contains
some interesting things ;-)

the script can be downloaded here:
https://dl.dropbox.com/u/42895525/memory.sikuli.zip

unzip and try to understand, maybe supported by the comments ;-)

---------------------- for those who are interested in the approach:


# check wether 2 cards are equal
def checkPrevious(image, index):
    if not cards[index].nearby(10).exists(image, 0):
        images[index-1] = image
        images[index] = capture(cards[index])
        return False
    else:
        images[index-1] = None        
        cards[index].highlight(1)
        return True

# check wether we already know a card
def checkImages(index):
    check = Finder(capture(cards[index].nearby(10)))
    for k in range(index-1):
        if images[k]:
            check.find(images[k])
            if check.hasNext():
                images[k] = None
                return k
    images[index] = capture(cards[index])
    return -1

# no mouse animation
Settings.MoveMouseDelay = 0
    
# game layout
# absolute pixels are measured with a pixel tool or the IDE Preview
rows = 3
cols = 4
maxCards = rows * cols
pairs = 0
maxPairs = maxCards/2

# card area cw x ch to be checked / captured
ch = 135
cw = 135

# horizontal/vertical offset between 2 cards
sh = 190
sv = 180

# setup cards areas
# we start with a reference image in the bottom left corner of the play ground
tl = find(Pattern("HHHPIANET.png").targetOffset(40,-100)).getTarget().above(130 + 2*sv)
card1 = Region(0,0,cw,ch).offset(tl)

cards = []
for i in range(rows):
    for k in range(cols):
        card = card1.offset(Location(k*sh, i*sv))
        #card.highlight(1)
        cards.append(card)

# storage for images to remember
images = []
for i in range(maxCards): images.append(None)

# start with the 2 top left cards
hover(cards[0])
image1 = capture(cards[0])
hover(cards[1])
# check equal ?
if checkPrevious(image1, 1):
    pairs += 1
#continue with 3rd card
nextCard = 2
# do we have to wait before next click ??

# loop until finished
while pairs < maxPairs:
    hover(cards[nextCard])
    # check wether we know it already
    n = checkImages(nextCard)
    if n > -1:
        # we already know it
        cards[n].highlight(1)
        hover(cards[n])
        pairs += 1
    else:
        # open the 2nd card and check match
        image1 = capture(cards[nextCard])
        nextCard += 1
        hover(cards[nextCard])
        if checkPrevious(image1, nextCard):
            # these 2 match
            pairs += 1
        else:
            # no match, so check wether we know it
            n = checkImages(nextCard)
            if n > -1:
                # we know were the 2nd card is
                # so lets make a pair
                cards[n].highlight(1)
                # do we have to wait before next click ??
                hover(cards[n])
                hover(cards[nextCard])
    # do we have to wait before next click ??
    nextCard += 1

-- 
You received this question notification because you are a member of
Sikuli Drivers, which is an answer contact for Sikuli.