Example #1
0
def parseLevel(levelname,tiles):
    level = cv2.imread(levelname) 
    
    # plt.imshow(level);
    # plt.show()
    tilemap = {}
    
    prefix =  'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = 'X'
    for t in ['LLground','LLground2','LLground3','LLground4','LLground5',
                    'LLground6','LLground7','LLground8','LLground9',
                    'LLground10','LL1','LL2','LL3',                    
                    '00','10','33','66','99','269','270','271','434','435','436','437','438','439','450','girder','CR','C','CL']:
        tilemap['{}{}{}'.format(prefix,t,postfix)] = tile

    
    prefix =  'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = '?'
    for t in ['Mushroom','MushroomLL','MushroomLL2','MushroomLL3','MushroomLL4',
                    'MushroomLL5','MushroomLL6','MushroomLL7','MushroomLL8','MushroomHidden']:
        tilemap['{}{}{}'.format(prefix,t,postfix)] = tile
    
    prefix =  'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = 'S'
    for t in ['LLbreak','LLbreak2','01','03','67','68','69']:
        tilemap['{}{}{}'.format(prefix,t,postfix)] = tile
    
    prefix =  'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = 'Q'
    for t in ['24','90']:
        tilemap['{}{}{}'.format(prefix,t,postfix)] = tile
        
    prefix =  'Tiles/SMBTiles/'
    postfix = '.png'
    tile = 'E'
    for t in ['hammerbro','turtle1','turtle2','fly1','fly2','fly3','fly4','turtle1D','turtle2D','fly1D','fly2D','fly3D','fly4D','pirannha','turtle1b','turtle2b','fly1b','fly2b','fly3b','fly4b','pirannha2','turtle1bD','turtle2bD','fly1bD','fly2bD','fly3bD','fly4bD','pirannha2D','goomba','goomba2','goomba2D','PPR','PPRud']:
        tilemap['{}{}{}'.format(prefix,t,postfix)] = tile
   

    prefix =  'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = 'B'
    for t in ['09','75']:
        tilemap['{}{}{}'.format(prefix,t,postfix)] = tile

    prefix =  'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = 'b'
    for t in ['108','42']:
        tilemap['{}{}{}'.format(prefix,t,postfix)] = tile

    prefix =  'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = 'o'
    for t in  ['57','58','123']:
        tilemap['{}{}{}'.format(prefix,t,postfix)] = tile

    prefix =  'Tiles/SMBTiles/'
    postfix = '.png'
    tile = '['
    for t in  ['pipe','pipeD','Lg']:
        tilemap['{}{}{}'.format(prefix,t,postfix)] = tile

    prefix =  'Tiles/SMBTiles/'
    postfix = '.png'
    tile = '>'
    for t in  ['pipe_ur','URg']:
        tilemap['{}{}{}'.format(prefix,t,postfix)] = tile
    prefix =  'Tiles/SMBTiles/'
    postfix = '.png'
    tile = '<'
    for t in  ['pipe_ul','ULg']:
        tilemap['{}{}{}'.format(prefix,t,postfix)] = tile
    prefix =  'Tiles/SMBTiles/'
    postfix = '.png'
    tile = ']'
    for t in  ['pipe_r','pipe_rD','Rg']:
        tilemap['{}{}{}'.format(prefix,t,postfix)] = tile
    levelMap = {}

    tileToCertainty = {'X':.78,'?':.75,'S':.85,'Q':.85,'E':.6,'o':.7,'B':.8,'b':.8,'<':.85,'>':.85,'[':.95,']':.85}
    
    maxX = -1
    maxY = -1
    
    tm = {}
    for tileImage,tile in tilemap.items():
        if tile not in tm:
            tm[tile] = []
        tm[tile].append(tileImage)
    
    tiles = ['o','X','E','Q','S','?','B','b','[',']','<','>']
    for tile in tiles:
        images = tm[tile]
        #print images
        locs = findSubImageLocations(level,map(cv2.imread,images),tileToCertainty[tile])
        for yy,xx in zip(locs[0],locs[1]):
            xx = int(math.ceil(xx/16))
            yy = int(math.ceil(yy/16))
            levelMap[(xx,yy)] = tile
            maxX = max(maxX,xx)
            maxY = max(maxY,yy)
        
    
    levelStr = [['-' for xx in range(maxX+1)] for yy in range(maxY+1)] 

    for loc,tile in levelMap.items():
        levelStr[loc[1]][loc[0]] = tile
    curX = 2
    curY = -1
    
    def isSolid(tile):
        return tile in ['X','Q','S','?','B','b','[',']','<','>']
    for yy in range(maxY-1,-1,-1):
        if levelStr[yy][curX] == '-' and isSolid(levelStr[yy+1][curX]) :
             curY = yy
             break
    import pathfinding
    jumps  = [[( 0,-1),
               ( 0,-2),
               ( 1,-3),
               (1,-4),
               ( 0,-4)]
              , [( 0,-1),
                 ( 0,-2),
                 ( 0,-3),
                 (0,-4),
                 ( 1,-4)]
              ,[( 1,-1),
                ( 1,-2),
                ( 1,-3),
                (1,-4),
                ( 2,-4)]
              ,[( 1,-1),
                ( 1,-2),
                ( 2,-2),
                ( 2,-3),
                ( 3,-3),
                ( 3,-4),
                ( 4,-4),
                ( 5,-3),
                ( 6,-3),
                ( 7,-3),
                ( 8,-2),
                ( 8,-1)]
              ,[( 1,-1),
                ( 1,-2),
                ( 2,-2),
                ( 2,-3),
                ( 3,-3),
                ( 3,-4),
                ( 4,-4),
                ( 5,-4),
                ( 6,-3),
                ( 7,-3),
                ( 8,-2),
                ( 8,-1)]]
    jumpDiffs = []
    for jump in jumps:
        jumpDiff = [jump[0]]
        for ii in range(1,len(jump)):
            jumpDiff.append((jump[ii][0]-jump[ii-1][0],jump[ii][1]-jump[ii-1][1]))
        jumpDiffs.append(jumpDiff)
    jumps = jumpDiffs
    visited = set()
    def getNeighbors(pos):
        dist = pos[0]
        pos = pos[1]
        #print pos
        visited.add((pos[0],pos[1]))
        below = (pos[0],pos[1]+1)
        neighbors = []
        if below[1] > maxY:
            return []
        if pos[2] != -1:
            ii = pos[3] +1
            jump = pos[2]
            if ii < len(jumps[jump]):
                if  not (pos[0]+pos[4]*jumps[jump][ii][0] > maxX or pos[0]+pos[4]*jumps[jump][ii][0] < 0 or pos[1]+jumps[jump][ii][1] < 0) and not isSolid(levelStr[pos[1]+jumps[jump][ii][1]][pos[0]+pos[4]*jumps[jump][ii][0]]):
                    #print jump, jumps[jump], ii, (pos[0],pos[1]), (pos[0]+pos[4]*jumps[jump][ii][0],pos[1]+jumps[jump][ii][1])
                    neighbors.append([dist+1,(pos[0]+pos[4]*jumps[jump][ii][0],pos[1]+jumps[jump][ii][1],jump,ii,pos[4])])
                if pos[1]+jumps[jump][ii][1] < 0 and not isSolid(levelStr[pos[1]+jumps[jump][ii][1]][pos[0]+pos[4]*jumps[jump][ii][0]]):
                    neighbors.append([dist+1,(pos[0]+pos[4]*jumps[jump][ii][0],0,jump,ii,pos[4])])
                
        if isSolid(levelStr[below[1]][below[0]]):
            if pos[0]+1 <= maxX and not isSolid(levelStr[pos[1]][pos[0]+1]):
                neighbors.append([dist+1,(pos[0]+1,pos[1],-1)])
            if pos[0]-1 >= 0 and not isSolid(levelStr[pos[1]][pos[0]-1]):
                neighbors.append([dist+1,(pos[0]-1,pos[1],-1)])

            for jump in range(len(jumps)):
                ii = 0
                if not (pos[0]+jumps[jump][ii][0] > maxX or pos[1] < 0) and not isSolid(levelStr[pos[1]+jumps[jump][ii][1]][pos[0]+jumps[jump][ii][0]]):
                    neighbors.append([dist+ii+1,(pos[0]+jumps[jump][ii][0],pos[1]+jumps[jump][ii][1],jump,ii,1)])

                if not (pos[0]-jumps[jump][ii][0] < 0 or pos[1] < 0) and not isSolid(levelStr[pos[1]+jumps[jump][ii][1]][pos[0]-jumps[jump][ii][0]]):
                    neighbors.append([dist+ii+1,(pos[0]-jumps[jump][ii][0],pos[1]+jumps[jump][ii][1],jump,ii,-1)])

        else:
            neighbors.append([dist+1,(pos[0],pos[1]+1,-1)])
            if pos[1]+1 <= maxY:
                if not isSolid(levelStr[pos[1]+1][pos[0]+1]):
                    neighbors.append([dist+1.4,(pos[0]+1,pos[1]+1,-1)])
                if not isSolid(levelStr[pos[1]+1][pos[0]-1]):
                    neighbors.append([dist+1.4,(pos[0]-1,pos[1]+1,-1)])
            if pos[1]+2 <= maxY:
                if not isSolid(levelStr[pos[1]+2][pos[0]+1]):
                    neighbors.append([dist+2,(pos[0]+1,pos[1]+2,-1)])
                if not isSolid(levelStr[pos[1]+2][pos[0]-1]):
                    neighbors.append([dist+2,(pos[0]-1,pos[1]+2,-1)])
        return neighbors
            
    paths = pathfinding.dijkstras_shortest_path( (curX,curY,-1), lambda pos: pos[0] == maxX, getNeighbors)
    paths = [[ (p[0],p[1]) for p in path] for path in paths]
    print levelname, len(paths)
    for yy in range(maxY+1):
        s = ''
        for xx in range(maxX+1):
            if (xx,yy) in visited:# paths[0]:
                s+= '*'
            else:
                s += levelStr[yy][xx]
        print s
    if len(paths) == 0:
        exit()
    for path in paths:
        with open('input.txt','a') as outputFile:
            outputFile.write('\n')
            direction  = 1
            offset = 0
            for xx in range(maxX):
                if direction == 1:
                    line = '('
                elif direction == -1:
                    line = ')'
                for dy in range(16):
                    yy = offset+direction*dy
                    if (xx,yy) in path and levelStr[yy][xx] == '-' :
                        line += '*'
                    else:
                        if yy <= maxY:
                            line += levelStr[yy][xx]
                        else :
                            line += levelStr[maxY][xx]

                if direction == 1:
                    direction = -1
                    offset = 15
                elif direction == -1:
                    direction = 1
                    offset = 0
                #line += ':'
                outputFile.write(line)
            outputFile.write('\n')

            direction  = -1
            offset = 15
            for xx in range(maxX):
                if direction == 1:
                    line = '('
                elif direction == -1:
                    line = ')'
                for dy in range(16):
                    yy = offset+direction*dy
                    if (xx,yy) in path and levelStr[yy][xx] == '-' :
                        line += '*'
                    else:
                        if yy <= maxY:
                            line += levelStr[yy][xx]
                        else :
                            line += levelStr[maxY][xx]

                if direction == 1:
                    direction = -1
                    offset = 15
                elif direction == -1:
                    direction = 1
                    offset = 0
                #line += ':'
                outputFile.write(line)


            outputFile.write('\n')
Example #2
0
def metrics(levelStr):
    maxY = len(levelStr)
    maxX = len(levelStr[0])

    visited = set()
    curX = 2
    curY = 0
    solids = set(['X', 'Q', 'S', '?', 'B', 'b', '[', ']', 'T', '|', '<', '>', 'v', 'f', 'm'])

    def isSolid(tile):
        return tile in solids
    for yy in range(maxY - 2, -1, -1):
        if (levelStr[yy][curX] == '-' or levelStr[yy][curX] == '*') and isSolid(levelStr[yy + 1][curX]):
            curY = yy
            break

    jumps = [[(0, -1),
              (0, -2),
              (1, -3),
              (1, -4),
              (0, -4)],
             [(0, -1),
              (0, -2),
              (0, -3),
              (0, -4),
              (1, -4)],
             [(1, -1),
              (1, -2),
              (1, -3),
              (1, -4),
              (2, -4)],
             [(1, -1),
              (1, -2),
              (2, -2),
              (2, -3),
              (3, -3),
              (3, -4),
              (4, -4),
              (5, -3),
              (6, -3),
              (7, -3),
              (8, -2),
              (8, -1)],
             [(1, -1),
              (1, -2),
              (2, -2),
              (2, -3),
              (3, -3),
              (3, -4),
              (4, -4),
              (5, -4),
              (6, -3),
              (7, -3),
              (8, -2),
              (8, -1)]]
    jumpDiffs = []
    for jump in jumps:
        jumpDiff = [jump[0]]
        for ii in range(1, len(jump)):
            jumpDiff.append((jump[ii][0] - jump[ii - 1][0], jump[ii][1] - jump[ii - 1][1]))
        jumpDiffs.append(jumpDiff)
    jumps = jumpDiffs
    visited = set()

    def getNeighbors(pos):
        dist = pos[0]
        pos = pos[1]
        visited.add((pos[0], pos[1]))
        below = (pos[0], pos[1] + 1)
        neighbors = []
        if below[1] >= maxY:
            return []
        if pos[2] != -1:
            ii = pos[3] + 1
            jump = pos[2]
            if ii < len(jumps[jump]):
                if not (pos[0] + pos[4] * jumps[jump][ii][0] >= maxX or pos[0] + pos[4] * jumps[jump][ii][0] < 0 or pos[1] + jumps[jump][ii][1] < 0) and not isSolid(levelStr[pos[1] + jumps[jump][ii][1]][pos[0] + pos[4] * jumps[jump][ii][0]]):
                    neighbors.append([dist + 1, (pos[0] + pos[4] * jumps[jump][ii][0], pos[1] + jumps[jump][ii][1], jump, ii, pos[4])])

        if isSolid(levelStr[below[1]][below[0]]):
            if pos[0] + 1 < maxX and not isSolid(levelStr[pos[1]][pos[0] + 1]):
                neighbors.append([dist + 1, (pos[0] + 1, pos[1], -1)])
            if pos[0] - 1 >= 0 and not isSolid(levelStr[pos[1]][pos[0] - 1]):
                neighbors.append([dist + 1, (pos[0] - 1, pos[1], -1)])

            for jump in range(len(jumps)):
                ii = 0
                if not (pos[0] + jumps[jump][ii][0] >= maxX or pos[1] + jumps[jump][ii][1] < 0) and not isSolid(levelStr[pos[1] + jumps[jump][ii][1]][pos[0] + jumps[jump][ii][0]]):
                    neighbors.append([dist + ii + 1, (pos[0] + jumps[jump][ii][0], pos[1] + jumps[jump][ii][1], jump, ii, 1)])

                if not (pos[0] - jumps[jump][ii][0] < 0 or pos[1] + jumps[jump][ii][1] < 0) and not isSolid(levelStr[pos[1] + jumps[jump][ii][1]][pos[0] - jumps[jump][ii][0]]):
                    neighbors.append([dist + ii + 1, (pos[0] - jumps[jump][ii][0], pos[1] + jumps[jump][ii][1], jump, ii, -1)])

        else:
            neighbors.append([dist + 1, (pos[0], pos[1] + 1, -1)])
            if pos[1] + 1 < maxY:
                if pos[0] + 1 < maxX and not isSolid(levelStr[pos[1] + 1][pos[0] + 1]):
                    neighbors.append([dist + 1.4, (pos[0] + 1, pos[1] + 1, -1)])
                if pos[0] - 1 >= 0 and not isSolid(levelStr[pos[1] + 1][pos[0] - 1]):
                    neighbors.append([dist + 1.4, (pos[0] - 1, pos[1] + 1, -1)])
            if pos[1] + 2 < maxY:
                if pos[0] + 1 < maxX and not isSolid(levelStr[pos[1] + 2][pos[0] + 1]):
                    neighbors.append([dist + 2, (pos[0] + 1, pos[1] + 2, -1)])
                if pos[0] - 1 >= 0 and not isSolid(levelStr[pos[1] + 2][pos[0] - 1]):
                    neighbors.append([dist + 2, (pos[0] - 1, pos[1] + 2, -1)])
        return neighbors
    subOptimal = 0

    paths = pathfinding.dijkstras_shortest_path((curX, curY, -1), lambda pos: pos[0] == maxX - 2, getNeighbors, subOptimal)

    pathDict = {path[0]: [] for path in paths}

    for yy in range(maxY):
        s = ''
        for xx in range(maxX):
            if (xx, yy) in visited:
                s += '*'
            else:
                s += levelStr[yy][xx]

        # print s
    for path in paths:
        pathDict[path[0]].append([(p[0], p[1]) for p in path[1]])
    # print paths
    paths = pathDict
    pathStats = {}
    gaps = set()
    for xx in range(maxX):
        if levelStr[maxY - 1][xx] == '-':
            gaps.add(xx)
    for pathLength in paths:
        pathStats[pathLength] = {'jumps': [], 'meaningfulJumps': []}
        for path in paths[pathLength]:
            jumps = 0
            meaningfulJumps = 0
            onGround = True
            for p in path:
                if p[1] < 15 and isSolid(levelStr[p[1] + 1][p[0]]):
                    onGround = True
                elif onGround:
                    jumps += 1
                    onGround = False
                    for xx in range(5):
                        if p[0] + xx < maxX and p[0] + xx in gaps:
                            meaningfulJumps += 1
                            break
            pathStats[pathLength]['jumps'].append(jumps)
            pathStats[pathLength]['meaningfulJumps'].append(meaningfulJumps)
    totalJumps = 0
    totalMeaningfulJumps = 0
    pathcount = 0
    smallest = float('inf')

    for path in pathStats:
        if path < smallest:
            smallest = path
        for p in pathStats[path]['jumps']:
            totalJumps += p
            pathcount += 1
        for p in pathStats[path]['meaningfulJumps']:
            totalMeaningfulJumps += p
    jumpVariance = 0
    meaningfulJumpVariance = 0

    for path in pathStats:
        for p in pathStats[path]['jumps']:
            temp = p - float(totalJumps) / float(pathcount)
            jumpVariance += temp * temp

        for p in pathStats[path]['meaningfulJumps']:
            temp = p - float(totalMeaningfulJumps) / float(pathcount)
            meaningfulJumpVariance += temp * temp

    totalSize = maxX * maxY
    #negativeSpace = float(len(visited))/float(totalSize)
    enemies = 0
    pipes = 0
    empty = 0
    breakable = 0
    rewards = 0
    solid = 0
    powerups = 0
    for row in levelStr:
        enemies += row.count('E')
        empty += row.count('-') + row.count('E') + row.count('o') + row.count('*')
        pipes += row.count('|') + row.count('T')
        breakable += row.count('B')
        rewards += row.count('o') + row.count('?') + row.count('M')
        powerups += row.count('M')
        solid += row.count('X') + row.count('?') + row.count('|') + row.count('T') + row.count('M') + row.count('B')

    negativeSpace = float(len(visited)) / float(empty)
    pathPercentage = float(smallest) / float(empty)
    emptyPercentage = float(empty) / float(totalSize)
    decorationPercentage = (float(pipes) + float(breakable) + float(enemies) + float(rewards)) / float(totalSize)
    leniency = enemies - powerups * 0.5 - 0.5 * rewards + len(gaps)

    solidX = []
    solidY = []
    yy = 0
    for yy in range(maxY):
        xx = 0
        if yy > 0:
            for c in levelStr[yy]:
                if isSolid(c) and not isSolid(levelStr[yy - 1][xx]):
                    # solidPts.append([xx,yy])
                    solidX.append(xx)
                    solidY.append(yy)
                xx += 1
        yy += 1
    x = np.array(solidX)
    y = np.array(solidY)
    from scipy import stats
    slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
    linearity = np.abs(r_value)
    if len(paths) > 0:
        return {'length': maxX,
                'negativeSpace': negativeSpace,
                'pathPercentage': pathPercentage,
                'emptyPercentage': emptyPercentage,
                'decorationPercentage': decorationPercentage,
                'leniency': leniency,
                'meaningfulJumps': float(totalMeaningfulJumps) / float(pathcount),
                'jumps': float(totalJumps) / float(pathcount),
                'meaningfulJumpVariance': float(meaningfulJumpVariance) / float(pathcount),
                'jumpVariance': float(jumpVariance) / float(pathcount),
                'linearity': linearity,
                'solvability': 1.0}
    else:
        return {
            'length': maxX,
            'negativeSpace': negativeSpace,
            'pathPercentage': -1,
            'emptyPercentage': emptyPercentage,
            'decorationPercentage': decorationPercentage,
            'leniency': leniency,
            'meaningfulJumps': -1,
            'jumps': -1,
            'meaningfulJumpVariance': -1,
            'jumpVariance': -1,
            'linearity': linearity,
            'solvability': 0}
Example #3
0
def parseLevel(levelname, tiles, nums):
    print 'here?'
    level = cv2.imread(levelname)

    # plt.imshow(level);
    # plt.show()
    tilemap = {}

    prefix = 'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = 'X'
    for t in [
            'LLground', 'LLground2', 'LLground3', 'LLground4', 'LLground5',
            'LLground6', 'LLground7', 'LLground8', 'LLground9', 'LLground10',
            'LL1', 'LL2', 'LL3', '00', '10', '33', '66', '99', '269', '270',
            '271', '434', '435', '436', '437', '438', '439', '450', 'girder',
            'CR', 'C', 'CL'
    ]:
        tilemap['{}{}{}'.format(prefix, t, postfix)] = tile

    prefix = 'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = '?'
    for t in [
            'Mushroom', 'MushroomLL', 'MushroomLL2', 'MushroomLL3',
            'MushroomLL4', 'MushroomLL5', 'MushroomLL6', 'MushroomLL7',
            'MushroomLL8', 'MushroomHidden'
    ]:
        tilemap['{}{}{}'.format(prefix, t, postfix)] = tile

    prefix = 'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = 'S'
    for t in ['LLbreak', 'LLbreak2', '01', '03', '67', '68', '69']:
        tilemap['{}{}{}'.format(prefix, t, postfix)] = tile

    prefix = 'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = 'Q'
    for t in ['24', '90']:
        tilemap['{}{}{}'.format(prefix, t, postfix)] = tile

    prefix = 'Tiles/SMBTiles/'
    postfix = '.png'
    tile = 'E'
    for t in [
            'hammerbro', 'turtle1', 'turtle2', 'fly1', 'fly2', 'fly3', 'fly4',
            'turtle1D', 'turtle2D', 'fly1D', 'fly2D', 'fly3D', 'fly4D',
            'pirannha', 'turtle1b', 'turtle2b', 'fly1b', 'fly2b', 'fly3b',
            'fly4b', 'pirannha2', 'turtle1bD', 'turtle2bD', 'fly1bD', 'fly2bD',
            'fly3bD', 'fly4bD', 'pirannha2D', 'goomba', 'goomba2', 'goomba2D',
            'PPR', 'PPRud'
    ]:
        tilemap['{}{}{}'.format(prefix, t, postfix)] = tile

    prefix = 'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = 'B'
    for t in ['09', '75']:
        tilemap['{}{}{}'.format(prefix, t, postfix)] = tile

    prefix = 'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = 'b'
    for t in ['108', '42']:
        tilemap['{}{}{}'.format(prefix, t, postfix)] = tile

    prefix = 'Tiles/SMBTiles/tileset_tile'
    postfix = '.png'
    tile = 'o'
    for t in ['57', '58', '123']:
        tilemap['{}{}{}'.format(prefix, t, postfix)] = tile

    prefix = 'Tiles/SMBTiles/'
    postfix = '.png'
    tile = '['
    for t in ['pipe', 'pipeD', 'Lg']:
        tilemap['{}{}{}'.format(prefix, t, postfix)] = tile

    prefix = 'Tiles/SMBTiles/'
    postfix = '.png'
    tile = '>'
    for t in ['pipe_ur', 'URg']:
        tilemap['{}{}{}'.format(prefix, t, postfix)] = tile
    prefix = 'Tiles/SMBTiles/'
    postfix = '.png'
    tile = '<'
    for t in ['pipe_ul', 'ULg']:
        tilemap['{}{}{}'.format(prefix, t, postfix)] = tile
    prefix = 'Tiles/SMBTiles/'
    postfix = '.png'
    tile = ']'
    for t in ['pipe_r', 'pipe_rD', 'Rg']:
        tilemap['{}{}{}'.format(prefix, t, postfix)] = tile
    levelMap = {}

    tileToCertainty = {
        'X': .78,
        '?': .75,
        'S': .85,
        'Q': .85,
        'E': .6,
        'o': .7,
        'B': .8,
        'b': .8,
        '<': .85,
        '>': .85,
        '[': .95,
        ']': .85
    }

    maxX = -1
    maxY = -1

    tm = {}
    for tileImage, tile in tilemap.items():
        if tile not in tm:
            tm[tile] = []
        tm[tile].append(tileImage)

    tiles = ['o', 'X', 'E', 'Q', 'S', '?', 'B', 'b', '[', ']', '<', '>']
    for tile in tiles:
        images = tm[tile]
        #print images
        locs = findSubImageLocations(level, map(cv2.imread, images),
                                     tileToCertainty[tile])
        for yy, xx in zip(locs[0], locs[1]):
            xx = int(math.ceil(xx / 16))
            yy = int(math.ceil(yy / 16))
            levelMap[(xx, yy)] = tile
            maxX = max(maxX, xx)
            maxY = max(maxY, yy)

    levelStr = [['-' for xx in range(maxX + 1)] for yy in range(maxY + 1)]

    for loc, tile in levelMap.items():
        levelStr[loc[1]][loc[0]] = tile
    curX = 2
    curY = -1

    def isSolid(tile):
        return tile in ['X', 'Q', 'S', '?', 'B', 'b', '[', ']', '<', '>']

    for yy in range(maxY - 1, -1, -1):
        if levelStr[yy][curX] == '-' and isSolid(levelStr[yy + 1][curX]):
            curY = yy
            break
    import pathfinding
    jumps = [[(0, -1), (0, -2), (1, -3), (1, -4), (0, -4)],
             [(0, -1), (0, -2), (0, -3), (0, -4), (1, -4)],
             [(1, -1), (1, -2), (1, -3), (1, -4), (2, -4)],
             [(1, -1), (1, -2), (2, -2), (2, -3), (3, -3), (3, -4), (4, -4),
              (5, -3), (6, -3), (7, -3), (8, -2), (8, -1)],
             [(1, -1), (1, -2), (2, -2), (2, -3), (3, -3), (3, -4), (4, -4),
              (5, -4), (6, -3), (7, -3), (8, -2), (8, -1)]]
    jumpDiffs = []
    for jump in jumps:
        jumpDiff = [jump[0]]
        for ii in range(1, len(jump)):
            jumpDiff.append(
                (jump[ii][0] - jump[ii - 1][0], jump[ii][1] - jump[ii - 1][1]))
        jumpDiffs.append(jumpDiff)
    jumps = jumpDiffs
    visited = set()

    def getNeighbors(pos):
        dist = pos[0]
        pos = pos[1]
        #print pos
        visited.add((pos[0], pos[1]))
        below = (pos[0], pos[1] + 1)
        neighbors = []
        if below[1] > maxY:
            return []
        if pos[2] != -1:
            ii = pos[3] + 1
            jump = pos[2]
            if ii < len(jumps[jump]):
                if not (pos[0] + pos[4] * jumps[jump][ii][0] > maxX
                        or pos[0] + pos[4] * jumps[jump][ii][0] < 0
                        or pos[1] + jumps[jump][ii][1] < 0) and not isSolid(
                            levelStr[pos[1] + jumps[jump][ii][1]][
                                pos[0] + pos[4] * jumps[jump][ii][0]]):
                    #print jump, jumps[jump], ii, (pos[0],pos[1]), (pos[0]+pos[4]*jumps[jump][ii][0],pos[1]+jumps[jump][ii][1])
                    neighbors.append([
                        dist + 1,
                        (pos[0] + pos[4] * jumps[jump][ii][0],
                         pos[1] + jumps[jump][ii][1], jump, ii, pos[4])
                    ])
                if pos[1] + jumps[jump][ii][1] < 0 and not isSolid(
                        levelStr[pos[1] + jumps[jump][ii][1]][
                            pos[0] + pos[4] * jumps[jump][ii][0]]):
                    neighbors.append([
                        dist + 1,
                        (pos[0] + pos[4] * jumps[jump][ii][0], 0, jump, ii,
                         pos[4])
                    ])

        if isSolid(levelStr[below[1]][below[0]]):
            if pos[0] + 1 <= maxX and not isSolid(
                    levelStr[pos[1]][pos[0] + 1]):
                neighbors.append([dist + 1, (pos[0] + 1, pos[1], -1)])
            if pos[0] - 1 >= 0 and not isSolid(levelStr[pos[1]][pos[0] - 1]):
                neighbors.append([dist + 1, (pos[0] - 1, pos[1], -1)])

            for jump in range(len(jumps)):
                ii = 0
                if not (pos[0] + jumps[jump][ii][0] > maxX
                        or pos[1] < 0) and not isSolid(
                            levelStr[pos[1] +
                                     jumps[jump][ii][1]][pos[0] +
                                                         jumps[jump][ii][0]]):
                    neighbors.append([
                        dist + ii + 1,
                        (pos[0] + jumps[jump][ii][0],
                         pos[1] + jumps[jump][ii][1], jump, ii, 1)
                    ])

                if not (pos[0] - jumps[jump][ii][0] < 0
                        or pos[1] < 0) and not isSolid(
                            levelStr[pos[1] +
                                     jumps[jump][ii][1]][pos[0] -
                                                         jumps[jump][ii][0]]):
                    neighbors.append([
                        dist + ii + 1,
                        (pos[0] - jumps[jump][ii][0],
                         pos[1] + jumps[jump][ii][1], jump, ii, -1)
                    ])

        else:
            neighbors.append([dist + 1, (pos[0], pos[1] + 1, -1)])
            if pos[1] + 1 <= maxY:
                if not isSolid(levelStr[pos[1] + 1][pos[0] + 1]):
                    neighbors.append(
                        [dist + 1.4, (pos[0] + 1, pos[1] + 1, -1)])
                if not isSolid(levelStr[pos[1] + 1][pos[0] - 1]):
                    neighbors.append(
                        [dist + 1.4, (pos[0] - 1, pos[1] + 1, -1)])
            if pos[1] + 2 <= maxY:
                if not isSolid(levelStr[pos[1] + 2][pos[0] + 1]):
                    neighbors.append([dist + 2, (pos[0] + 1, pos[1] + 2, -1)])
                if not isSolid(levelStr[pos[1] + 2][pos[0] - 1]):
                    neighbors.append([dist + 2, (pos[0] - 1, pos[1] + 2, -1)])
        return neighbors

    subOptimal = 10
    paths = pathfinding.dijkstras_shortest_path(
        (curX, curY, -1), lambda pos: pos[0] == maxX, getNeighbors, subOptimal)
    paths = [[(p[0], p[1]) for p in path] for path in paths]
    print levelname, len(paths)
    for yy in range(maxY + 1):
        s = ''
        for xx in range(maxX + 1):
            if (xx, yy) in visited:  # paths[0]:
                s += '*'
            else:
                s += levelStr[yy][xx]
        print s
    if len(paths) == 0:
        exit()

    strs = {}
    basic = []
    basicLineNo = []
    div = 10
    s = '('
    sln = '('
    for xx in range(maxX + 1):
        sln += 'v' * int(round(xx / div))
        for yy in range(16):
            if yy <= maxY:
                s += levelStr[yy][xx]
                sln += levelStr[yy][xx]
            else:
                s += levelStr[maxY][xx]
                sln += levelStr[maxY][xx]

        s += '('
        sln += '('
    basic.append(s)
    basicLineNo.append(sln)

    bi = []
    biLineNo = []
    direction = 1
    offset = 0
    s = ''
    sln = ''
    for xx in range(maxX + 1):
        if direction == 1:
            line = '('
        elif direction == -1:
            line = ')'
        for dy in range(16):
            yy = offset + direction * dy
            if yy <= maxY:
                line += levelStr[yy][xx]
            else:
                line += levelStr[maxY][xx]

        if direction == 1:
            direction = -1
            offset = 15
        elif direction == -1:
            direction = 1
            offset = 0
        s += line
        sln += 'v' * int(round(xx / div)) + line
    bi.append(s)
    biLineNo.append(sln)
    direction = -1
    offset = 15
    s = ''
    sln = ''
    for xx in range(maxX + 1):
        if direction == 1:
            line = '('
        elif direction == -1:
            line = ')'
        for dy in range(16):
            yy = offset + direction * dy
            if yy <= maxY:
                line += levelStr[yy][xx]
            else:
                line += levelStr[maxY][xx]

        if direction == 1:
            direction = -1
            offset = 15
        elif direction == -1:
            direction = 1
            offset = 0
        s += line
        sln += 'v' * int(round(xx / div)) + line
    bi.append(s)
    biLineNo.append(sln)

    biP = []
    basicP = []
    basicLineNoP = []
    biLineNoP = []
    for path in paths:
        str = ''
        if True:
            s = '('
            sln = '('
            for xx in range(maxX + 1):
                sln += 'v' * int(round(xx / div))
                for yy in range(16):
                    if (xx, yy) in path and levelStr[yy][xx] == '-':
                        s += '*'
                        sln += '*'
                    else:
                        if yy <= maxY:
                            s += levelStr[yy][xx]
                            sln += levelStr[yy][xx]
                        else:
                            s += levelStr[maxY][xx]
                            sln += levelStr[maxY][xx]
                s += '('
                sln += '('
            basicP.append(s)
            basicLineNoP.append(sln)
            #with open('input.txt','a') as outputFile:
            #outputFile.write('\n')
            #str += ';'
            #for ii in range(nums[0]):
            #    outputFile.write('W')
            #for ii in range(nums[1]):
            #    outputFile.write('L')

            direction = 1
            offset = 0

            s = ''
            sln = ''
            for xx in range(maxX + 1):

                if direction == 1:
                    line = '('
                elif direction == -1:
                    line = ')'
                for dy in range(16):
                    yy = offset + direction * dy
                    if (xx, yy) in path and levelStr[yy][xx] == '-':
                        line += '*'
                    else:
                        if yy <= maxY:
                            line += levelStr[yy][xx]
                        else:
                            line += levelStr[maxY][xx]

                if direction == 1:
                    direction = -1
                    offset = 15
                elif direction == -1:
                    direction = 1
                    offset = 0
                #line += ':'
                s += line
                sln += 'v' * int(round(xx / div)) + line
                #outputFile.write(line)
            #outputFile.write('\n')
            biP.append(s)
            biLineNoP.append(sln)

            s = ''
            sln = ''
            direction = -1
            offset = 15
            for xx in range(maxX + 1):
                if direction == 1:
                    line = '('
                elif direction == -1:
                    line = ')'
                for dy in range(16):
                    yy = offset + direction * dy
                    if (xx, yy) in path and levelStr[yy][xx] == '-':
                        line += '*'
                    else:
                        if yy <= maxY:
                            line += levelStr[yy][xx]
                        else:
                            line += levelStr[maxY][xx]

                if direction == 1:
                    direction = -1
                    offset = 15
                elif direction == -1:
                    direction = 1
                    offset = 0
                #line += ':'
                #outputFile.write(line)
                s += line
                sln += 'v' * int(round(xx / div)) + line
            biP.append(s)
            biLineNoP.append(sln)

            #outputFile.write('\n')
    return {
        'basic': basic,
        'basicLineNo': basicLineNo,
        'bi': bi,
        'biLineNo': biLineNo,
        'basicP': basicP,
        'biP': biP,
        'biLineNoP': biLineNoP,
        'basicLineNoP': basicLineNoP
    }
Example #4
0
def testLevel(levelStr):
    maxY = 16
    maxX = len(levelStr[0])

    visited = set()
    curX = 2
    curY = 0
    solids = set(['X','Q','S','?','B','b','[',']','<','>'])
    def isSolid(tile):
        return tile in solids
    for yy in range(maxY-2,-1,-1):
        if (levelStr[yy][curX] == '-' or levelStr[yy][curX] == '*') and isSolid(levelStr[yy+1][curX]) :
             curY = yy
             break

    jumps  = [[( 0,-1),
               ( 0,-2),
               ( 1,-3),
               (1,-4),
               ( 0,-4)]
              , [( 0,-1),
                 ( 0,-2),
                 ( 0,-3),
                 (0,-4),
                 ( 1,-4)]
              ,[( 1,-1),
                ( 1,-2),
                ( 1,-3),
                (1,-4),
                ( 2,-4)]
              ,[( 1,-1),
                ( 1,-2),
                ( 2,-2),
                ( 2,-3),
                ( 3,-3),
                ( 3,-4),
                ( 4,-4),
                ( 5,-3),
                ( 6,-3),
                ( 7,-3),
                ( 8,-2),
                ( 8,-1)]
              ,[( 1,-1),
                ( 1,-2),
                ( 2,-2),
                ( 2,-3),
                ( 3,-3),
                ( 3,-4),
                ( 4,-4),
                ( 5,-4),
                ( 6,-3),
                ( 7,-3),
                ( 8,-2),
                ( 8,-1)]]
    jumpDiffs = []
    for jump in jumps:
        jumpDiff = [jump[0]]
        for ii in range(1,len(jump)):
            jumpDiff.append((jump[ii][0]-jump[ii-1][0],jump[ii][1]-jump[ii-1][1]))
        jumpDiffs.append(jumpDiff)
    jumps = jumpDiffs
    visited = set()
    def getNeighbors(pos):
        dist = pos[0]
        pos = pos[1]
        visited.add((pos[0],pos[1]))
        below = (pos[0],pos[1]+1)
        neighbors = []
        if below[1] >= maxY:
            return []
        if pos[2] != -1:
            ii = pos[3] +1
            jump = pos[2]
            if ii < len(jumps[jump]):
                if not (pos[0]+pos[4]*jumps[jump][ii][0] >= maxX or pos[0]+pos[4]*jumps[jump][ii][0] < 0 or pos[1]+jumps[jump][ii][1] < 0) and not isSolid(levelStr[pos[1]+jumps[jump][ii][1]][pos[0]+pos[4]*jumps[jump][ii][0]]):
                    neighbors.append([dist+1,(pos[0]+pos[4]*jumps[jump][ii][0],pos[1]+jumps[jump][ii][1],jump,ii,pos[4])])
               
        if isSolid(levelStr[below[1]][below[0]]):
            if pos[0]+1 < maxX and not isSolid(levelStr[pos[1]][pos[0]+1]):
                neighbors.append([dist+1,(pos[0]+1,pos[1],-1)])
            if pos[0]-1 >= 0 and not isSolid(levelStr[pos[1]][pos[0]-1]):
                neighbors.append([dist+1,(pos[0]-1,pos[1],-1)])

            for jump in range(len(jumps)):
                ii = 0
                if not (pos[0]+jumps[jump][ii][0] >= maxX or pos[1]+jumps[jump][ii][1] < 0) and not isSolid(levelStr[pos[1]+jumps[jump][ii][1]][pos[0]+jumps[jump][ii][0]]):
                    neighbors.append([dist+ii+1,(pos[0]+jumps[jump][ii][0],pos[1]+jumps[jump][ii][1],jump,ii,1)])

                if not (pos[0]-jumps[jump][ii][0] < 0 or pos[1]+jumps[jump][ii][1] < 0) and not isSolid(levelStr[pos[1]+jumps[jump][ii][1]][pos[0]-jumps[jump][ii][0]]):
                    neighbors.append([dist+ii+1,(pos[0]-jumps[jump][ii][0],pos[1]+jumps[jump][ii][1],jump,ii,-1)])

        else:
            neighbors.append([dist+1,(pos[0],pos[1]+1,-1)])
            if pos[1]+1 < maxY:
                if  pos[0]+1 < maxX and not isSolid(levelStr[pos[1]+1][pos[0]+1]):
                    neighbors.append([dist+1.4,(pos[0]+1,pos[1]+1,-1)])
                if pos[0]-1 >= 0 and not isSolid(levelStr[pos[1]+1][pos[0]-1]):
                    neighbors.append([dist+1.4,(pos[0]-1,pos[1]+1,-1)])
            if pos[1]+2 < maxY:
                if pos[0]+1 < maxX and not isSolid(levelStr[pos[1]+2][pos[0]+1]):
                    neighbors.append([dist+2,(pos[0]+1,pos[1]+2,-1)])
                if pos[0]-1 >= 0 and not isSolid(levelStr[pos[1]+2][pos[0]-1]):
                    neighbors.append([dist+2,(pos[0]-1,pos[1]+2,-1)])
        return neighbors
    subOptimal = 0

    paths = pathfinding.dijkstras_shortest_path( (curX,curY,-1), lambda pos: pos[0] == maxX-1, getNeighbors, subOptimal)

    pathDict = {path[0]:[] for path in paths}
    
    for yy in range(maxY):
        s = ''
        for xx in range(maxX):
            if (xx,yy) in visited:
                s += '*'
            else:
                s += levelStr[yy][xx]
                
        print s
    for path in paths:
        pathDict[path[0]].append([(p[0],p[1]) for p in path[1] ])
    #print paths    
    paths = pathDict
    pathStats = {}
    gaps = set()
    for xx in range(maxX):
        if levelStr[maxY-1][xx] == '-':
            gaps.add(xx)
    for pathLength in paths:
        pathStats[pathLength] = {'jumps':[],'meaningfulJumps':[]}
        for path in paths[pathLength]:
            jumps = 0
            meaningfulJumps = 0
            onGround = True
            for p in path:
                if p[1] < 15 and isSolid(levelStr[p[1]+1][p[0]]):
                    onGround = True
                elif onGround:
                    jumps += 1
                    onGround = False
                    for xx in range(5):
                        if p[0]+xx < maxX and p[0]+xx in gaps:
                            meaningfulJumps += 1
                            break
            pathStats[pathLength]['jumps'].append(jumps)
            pathStats[pathLength]['meaningfulJumps'].append( meaningfulJumps)
    totalJumps = 0
    totalMeaningfulJumps = 0
    pathcount   = 0
    smallest = float('inf')

    for path in pathStats:
        if path < smallest:
            smallest = path
        for p in pathStats[path]['jumps']:
            totalJumps += p
            pathcount += 1
        for p in pathStats[path]['meaningfulJumps']:
            totalMeaningfulJumps += p
    jumpVariance = 0
    meaningfulJumpVariance = 0
    
    for path in pathStats:
        for p in pathStats[path]['jumps']:
            temp = p - float(totalJumps)/float(pathcount)
            jumpVariance += temp*temp

        for p in pathStats[path]['meaningfulJumps']:            
            temp = p - float(totalMeaningfulJumps)/float(pathcount)
            meaningfulJumpVariance += temp*temp

    totalSize = maxX*maxY
    #negativeSpace = float(len(visited))/float(totalSize)
    enemies = 0
    pipes = 0
    empty = 0
    breakable = 0
    rewards = 0
    solid = 0
    powerups = 0
    for rowVal,row in levelStr.items():
       enemies += row.count('E') + row.count('B')
       empty += row.count('-') + row.count('E') + row.count('o') + row.count('*')
       pipes += row.count('[') + row.count(']') + row.count('<') + row.count('>')
       breakable += row.count('S')
       rewards += row.count('o') + row.count('?') + row.count('Q')
       powerups += row.count('?')
       solid +=  row.count('#') + row.count('?') + row.count('Q') + row.count('[') + row.count(']') + row.count('<') + row.count('>') + row.count('B')
    
    negativeSpace = float(len(visited))/float(empty)
    pathPercentage = float(smallest)/float(empty)
    emptyPercentage = float(empty)/float(totalSize)
    decorationPercentage = (float(pipes) + float(breakable) + float(enemies) + float(rewards))/float(totalSize)
    leniency = enemies - powerups*0.5 - 0.5*rewards + len(gaps)
    
    solidX = []
    solidY = []
    yy = 0
    for yy in range(maxY):
        xx = 0
        if yy > 0:
            for c in levelStr[yy]:
                if isSolid(c) and not isSolid(levelStr[yy-1][xx]):
                    #solidPts.append([xx,yy])
                    solidX.append(xx)
                    solidY.append(yy)
                xx += 1
        yy += 1
    x = np.array(solidX)
    y = np.array(solidY)
    from scipy import stats
    slope, intercept, r_value, p_value, std_err = stats.linregress(x,y)
    linearity = np.abs(r_value)
    if len(paths) > 0:
        return {'length':maxX,
                'negativeSpace':negativeSpace,
            'pathPercentage':pathPercentage,
            'emptyPercentage':emptyPercentage,
            'decorationPercentage':decorationPercentage,
            'leniency':leniency,
            'meaningfulJumps':float(totalMeaningfulJumps)/float(pathcount),
            'jumps':float(totalJumps)/float(pathcount),
            'meaningfulJumpVariance':float(meaningfulJumpVariance)/float(pathcount),
            'jumpVariance':float(jumpVariance)/float(pathcount),
            'linearity' :linearity}
    else:
        return {
            'length':maxX,
            'negativeSpace':negativeSpace,
            'pathPercentage':-1,
            'emptyPercentage':emptyPercentage,
            'decorationPercentage':decorationPercentage,
            'leniency':leniency,
            'meaningfulJumps':-1,
            'jumps':-1,
            'meaningfulJumpVariance':-1,
            'jumpVariance':-1,
            'linearity' :linearity}