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')
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}
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 }
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}