2365 lines
102 KiB
Python
2365 lines
102 KiB
Python
|
from collections import OrderedDict
|
||
|
from PIL import Image, ImageChops, ImageDraw
|
||
|
import time
|
||
|
import json
|
||
|
import os
|
||
|
import os.path
|
||
|
|
||
|
try:
|
||
|
import pymongo
|
||
|
except:
|
||
|
pass
|
||
|
|
||
|
import math
|
||
|
try:
|
||
|
from bson.objectid import ObjectId
|
||
|
except:
|
||
|
pass
|
||
|
from image_util import load_image, image_to_string_format,\
|
||
|
reduce_to_colors
|
||
|
try:
|
||
|
conn = pymongo.Connection('localhost')
|
||
|
|
||
|
db = conn.ztrans
|
||
|
except:
|
||
|
pass
|
||
|
|
||
|
def replace_color(im, color1, color2):
|
||
|
mode = im.mode
|
||
|
im = im.convert("P", palette=Image.ADAPTIVE)
|
||
|
p = im.getpalette()
|
||
|
new_p = list()
|
||
|
for i in range(256):
|
||
|
r = p[3*i]
|
||
|
g = p[3*i+1]
|
||
|
b = p[3*i+2]
|
||
|
if r == color1[0] and g == color1[1] and b == color1[2]:
|
||
|
new_p.extend(color2[:3])
|
||
|
else:
|
||
|
new_p.extend([r,g,b])
|
||
|
im.putpalette(new_p)
|
||
|
return im.convert(mode)
|
||
|
|
||
|
|
||
|
class TileSetParser:
|
||
|
@classmethod
|
||
|
def parse_images(cls, image_list, seed_list, seed_fails, tilesize):
|
||
|
x = None
|
||
|
y = None
|
||
|
|
||
|
tiles = OrderedDict()
|
||
|
fail_tiles = OrderedDict()
|
||
|
seed_tiles = OrderedDict()
|
||
|
|
||
|
for ii, im in enumerate(seed_list):
|
||
|
#print(ii, len(seed_list))
|
||
|
if x is None:
|
||
|
x,y = TileTools.find_tileset_offset(im, tilesize)
|
||
|
these_tiles = TileTools.get_tiles(im, x, y, tilesize)
|
||
|
for t in these_tiles:
|
||
|
seed_tiles[t] = seed_tiles.get(t,0)+these_tiles[t]
|
||
|
|
||
|
for im in seed_fails:
|
||
|
these_tiles = TileTools.get_tiles(im, x, y, tilesize)
|
||
|
for t in these_tiles:
|
||
|
fail_tiles[t] = fail_tiles.get(t,0)+these_tiles[t]
|
||
|
|
||
|
maps = 0
|
||
|
for ii, image in enumerate(image_list):
|
||
|
#print("tt--", ii)
|
||
|
these_tiles = TileTools.get_tiles(image, x,y, tilesize)
|
||
|
c = 0
|
||
|
for t in these_tiles:
|
||
|
if t in fail_tiles:
|
||
|
c+=these_tiles[t]
|
||
|
|
||
|
for t in these_tiles:
|
||
|
if t in fail_tiles and c > 10:
|
||
|
for s in these_tiles:
|
||
|
if s not in tiles:
|
||
|
fail_tiles[s] = 1
|
||
|
break
|
||
|
else:
|
||
|
print("succ")
|
||
|
#test for success tiles...
|
||
|
succ = 0
|
||
|
ox, oy = TileTools.find_tileset_offset(image, tilesize)
|
||
|
if ox == x and oy == y:
|
||
|
image.save("maps_"+str(maps)+".png")
|
||
|
maps+=1
|
||
|
for s in these_tiles:
|
||
|
tiles[s] = tiles.get(s,0)+these_tiles[s]
|
||
|
|
||
|
width = 16*tilesize
|
||
|
height = int(len(tiles)/tilesize+1)*tilesize
|
||
|
nim = Image.new("RGB", (width, height))
|
||
|
wx = 0
|
||
|
wy = 0
|
||
|
|
||
|
for key in tiles:
|
||
|
subi = load_image(key)
|
||
|
draw = ImageDraw.Draw(subi)
|
||
|
draw.line((0,0, subi.width,0), fill = 128)
|
||
|
draw.line((0,0, 0, subi.height), fill=128)
|
||
|
nim.paste(subi, (wx,wy))
|
||
|
|
||
|
wx+=tilesize
|
||
|
if wx >= width:
|
||
|
wx = 0
|
||
|
wy+=tilesize
|
||
|
nim.save("t.png")
|
||
|
#import pdb
|
||
|
#pdb.set_trace()
|
||
|
return {"tileset": nim, "tiles": tiles, "fail_tiles": fail_tiles,
|
||
|
"off_x": x, "off_y": y, "tilesize": tilesize}
|
||
|
|
||
|
|
||
|
def main():
|
||
|
start_image_id = ObjectId("5df9d8208ac3d956387c0941")
|
||
|
doc = db.ocr_images.find_one({"_id": start_image_id})
|
||
|
game_id = doc['game_id']
|
||
|
user_id = doc['user_id']
|
||
|
|
||
|
seed_list_ids = [ObjectId("5df9d8df8ac3d956387c0957"),
|
||
|
ObjectId("5df9d9008ac3d956387c095d"),
|
||
|
]
|
||
|
|
||
|
seed_fail_ids = []
|
||
|
|
||
|
seed_list = list()
|
||
|
fail_list = list()
|
||
|
for seed_id in seed_list_ids:
|
||
|
doc = db.ocr_images.find_one({"_id": seed_id})
|
||
|
img = load_image(doc['image_data'])
|
||
|
seed_list.append(img)
|
||
|
|
||
|
for fail_id in seed_fail_ids:
|
||
|
doc = db.ocr_images.find_one({"_id": fail_id})
|
||
|
img = load_image(doc['image_data'])
|
||
|
fail_list.append(img)
|
||
|
|
||
|
image_list = [Image.open("text"+str(i)+".png") for i in range(7)]
|
||
|
f = ParseScreenText.get_font(image_list)
|
||
|
|
||
|
start_image_id = ObjectId("5df9d8208ac3d956387c0941")
|
||
|
doc = db.ocr_images.find_one({"_id": start_image_id})
|
||
|
game_id = doc['game_id']
|
||
|
user_id = doc['user_id']
|
||
|
|
||
|
image_list = list()
|
||
|
c = 0
|
||
|
for image in db.ocr_images.find({"user_id": user_id,
|
||
|
"game_id": game_id},
|
||
|
sort=[("_id", pymongo.ASCENDING)]):
|
||
|
im = load_image(image['image_data'])
|
||
|
tex = ParseScreenText.parse_screen(im, f)
|
||
|
c+=1
|
||
|
|
||
|
if image['_id'] in [ObjectId('5e3e44e48ac3d94113fa1361'),
|
||
|
ObjectId('5e3e44e68ac3d94112f910c6'),
|
||
|
ObjectId('5e3e44e88ac3d94113fa1363'),
|
||
|
ObjectId('5e3e44ff8ac3d94113fa1366')]:
|
||
|
im.paste(im.crop((0,0, 160, im.height)), (32,0))
|
||
|
|
||
|
if not tex:
|
||
|
image_list.append(im)
|
||
|
|
||
|
res = TileSetParser.parse_images(image_list, seed_list, fail_list,
|
||
|
tilesize=16)
|
||
|
|
||
|
ts = ["grass", "woods", "wall", "castle", "water",
|
||
|
"town", "port", "building","inn", "tree",
|
||
|
"path", "door", "fence", "armor shop", "weapon shop",
|
||
|
"foutain", "well", "bridge", "item shop", "clinic",
|
||
|
"swamp", "rock", "ruins", "black magic shop", "white magic shop",
|
||
|
"tile", "stairs up", "column", "statue", "fireplace",
|
||
|
"chair", "table", "bed", "stairs down", "throne",
|
||
|
"chest", "orb", "cave", "skull", "vase",
|
||
|
"desert", "ship", "river", "meadow", "tombstone",
|
||
|
"ladder down", "ladder up", "dirt","hammer", "sword",
|
||
|
"anvil", "lid", "alter", "exit", "hole",
|
||
|
"poison", "candles", "volcano","fairy", "submarine",
|
||
|
"tower", "computer", "runes", "teleporter up", "teleporter down",
|
||
|
"fire", "door", "king"
|
||
|
]
|
||
|
res['tileset'].save("tileset__.png")
|
||
|
res['tileset'].show()
|
||
|
import pdb
|
||
|
pdb.set_trace()
|
||
|
sounds = []
|
||
|
|
||
|
obss = [0,0,1,2,1,
|
||
|
2,2,1,3,1,
|
||
|
0,0,1,3,3,
|
||
|
1,1,2,3,3,
|
||
|
0,1,2,3,3,
|
||
|
0,2,1,1,1,
|
||
|
0,1,1,2,1,
|
||
|
2,3,2,0,1,
|
||
|
0,2,1,0,1,
|
||
|
2,2,0,1,1,
|
||
|
1,3,1,2,2,
|
||
|
0,1,2,3,2,
|
||
|
2,1,1,2,2,
|
||
|
1,3,3
|
||
|
]#0-no obs, 1-obst, 2-no obst special, 3-special obst
|
||
|
|
||
|
mapp = [ 1, 1, 1, 0, 2, 3, 3, 3, 2, 2, 4, 2, 5, 0, 2, 2,
|
||
|
2, 2, 2, 1, 2, 2, 2, 2, 1, 1, 1, 1, 0, 4, 0, 6,
|
||
|
6, 6, 4, 4, 6, 6, 2, 2, 2, 2, 2, 2, 7, 8, 0, 9,
|
||
|
10, 0, 4, 2,11, 0,12,-1,10,-1, 9, 2, 2, 2, 7,-1,
|
||
|
-1, 7,-1,-1,10, 2, 2,13,14,10,-1,-1,-1,-1,15, 0,
|
||
|
-1,-1,-1,-1,-1,16, 7,-1,-1,17,-1,18, 4,-1, 4,17,
|
||
|
7,19,-1,-1,-1,-1, 0, 1, 0, 4,20,20,20,21,21,21,
|
||
|
21,21,20,20,21,21,22,22, 0,22,22, 0,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,23,24,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,25,-1, 2, 2, 0, 2,26,27, 2,
|
||
|
2, 2, 2, 2, 2, 2, 2, 2,11,-1, 2,-1, 2, 2, 2, 2,
|
||
|
28,29,28, 2,30,31,30,-1,31,-1,25, 2,25, 2,11,32,
|
||
|
-1, 2,-1,-1,25,-1, 2,33,34,34,34,34,67,34,25, 2,
|
||
|
66,27, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,25,
|
||
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,11,35,28,-1,-1,-1,
|
||
|
25,28,-1,-1,-1,28,-1,25, 2,-1, 2,-1,27, 2,26,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,36, 2,-1,-1,-1,-1,
|
||
|
17, 4, 4,21,21,37, 2, 2, 2, 2, 2, 2,26, 2,11,25,
|
||
|
2, 2, 2, 2,-1,-1,38,-1,-1,25, 2, 2, 2, 2,-1, 2,
|
||
|
11, 2,-1,39,-1,-1,31,-1,-1,-1,-1,-1,-1,-1,-1, 0,
|
||
|
40, 0, 0, 0, 2, 5, 2, 2,10,-1,10,-1, 2, 2, 2,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,41,42,42,43,43,43,43, 3, 3,43, 5, 3,
|
||
|
3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,28,32,-1,
|
||
|
-1,44,42,54,-1,25,27,26,25,-1,25,25,-1,25, 2, 2,
|
||
|
2, 2, 2, 2, 2, 2, 2, 2,66,25,27, 2, 2, 2, 2, 2,
|
||
|
46, 2,25, 2, 2,11,27,33,35,26,47,11,-1, 2, 2, 2,
|
||
|
25, 2, 2, 2, 2, 2, 2,27,25,26, 2, 2, 2, 2, 2, 2,
|
||
|
25, 2, 2,11,11,-1,-1,25,25,27,25,-1,28,-1,25,25,
|
||
|
-1,-1,-1,25,-1,-1,34,-1,35,34,34,-1,-1,-1,-1,-1,
|
||
|
2,-1, 2, 2, 2,-1,-1,28,-1,30,-1,30,31,-1,30,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0,47,21,
|
||
|
2, 2, 2,-1, 2,-1,-1,-1, 2, 2, 2, 2, 2, 2,-1,-1,
|
||
|
-1,-1,21, 2, 2, 2, 2,-1, 2,-1,30, 2,25, 2, 2,-1,
|
||
|
-1,29,48,49,50, 5, 0,40,10,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,40,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,21,47,26, 2, 2, 2, 2, 2,47,-1,-1,47,21,47, 2,
|
||
|
2, 2, 2, 2, 2,25, 2, 2,11,11,47,-1,-1,-1,-1,47,
|
||
|
-1, 2, 2, 2, 2,33, 2,47,47,-1,-1, 2, 2, 2, 2, 2,
|
||
|
2, 2, 2, 2,-1,47,-1,-1,-1,-1, 2, 2,-1, 2,26,21,
|
||
|
-1,51,47,21,-1,47,26, 2, 2, 2, 2, 2, 2,-1,47, 2,
|
||
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,25, 2, 2, 2, 2, 2,
|
||
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,29,32,-1,32,-1, 2,
|
||
|
2, 2, 2,35, 2, 2, 2,-1, 2, 2,25, 2, 2, 2,35,47,
|
||
|
47,47,47,47,-1,-1,-1,-1,-1,-1,-1,-1,-1, 2, 2, 2,
|
||
|
2, 2, 2,52, 2,-1,36, 2,53, 5, 0,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1, 2, 2, 2,47,21,33, 2, 2, 2, 2,
|
||
|
2, 2, 2, 2,54, 2,21, 2, 2, 2, 2,25, 2, 2, 2, 2,
|
||
|
2,55, 2, 2, 2,-1,-1,-1,-1,-1,47, 2, 2, 2, 2, 2,
|
||
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,47, 2, 2, 2, 2,-1,
|
||
|
2,-1, 2,25, 2,-1,-1,-1,-1,-1,-1,-1,-1, 2, 2, 2,
|
||
|
2,-1,-1,-1,-1,16,-1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||
|
2, 2,25, 2, 2, 2, 2,56,-1,-1, 2, 2, 2,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,10,-1,-1,-1,-1,
|
||
|
-1, 9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1, 9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1, 9,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 2, 2,
|
||
|
47, 2,47,47,47,-1,-1,-1,-1,-1,57,57,57,57,21,21,
|
||
|
47,55,26,33, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||
|
2, 2, 2, 2,25, 2, 2, 2, 2,47,55,26, 2, 2, 2, 2,
|
||
|
2, 2, 2, 2, 2, 2, 2, 2,33,21,21, 2, 2, 2,47,47,
|
||
|
2, 2, 2, 2,25, 2, 2, 2, 2, 2, 2, 2,-1,36, 2, 2,
|
||
|
2, 2, 2, 2, 2, 2,53, 2, 2,52, 2,25, 2, 2, 2,11,
|
||
|
-1,-1,-1,-1,58,59, 2, 2,25, 2, 2, 2, 4,59, 2, 2,
|
||
|
2, 2, 2,27, 2, 2,66,47,47, 2, 2, 2, 2,35, 2, 2,
|
||
|
25, 2, 2,11,33,26, 4,25,33, 2, 2, 2, 2, 2, 2, 2,
|
||
|
2, 2, 2,66, 2, 2, 2, 2, 2, 2,25, 2,11,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1, 2, 2, 2, 2,66, 2,26,
|
||
|
33,53, 2,52, 2,28,-1,28,36,10,-1,-1,10,-1,-1,10,
|
||
|
-1,-1,-1,60,60,40, 2, 2, 2, 2,25,66, 2, 2, 2, 2,
|
||
|
26,33,27,25, 2, 2,11, 2, 2,11, 2, 2, 2,26,33, 2,
|
||
|
2, 2,61,61,-1,-1,-1, 2, 2,27, 2,-1,-1, 2, 2,-1,
|
||
|
-1,-1,-1,-1,-1, 2,27,61, 2,61, 2, 2, 2, 2,25,33,
|
||
|
2, 2, 2, 2, 2, 2, 2, 2, 2,66, 2, 2,28, 2,62, 2,
|
||
|
2,-1, 2,25,25, 2, 2,25, 2, 2, 2, 2, 2, 2, 2, 2,
|
||
|
62, 2, 2,25,66, 2, 2, 2, 2, 2, 2, 2, 2,35,11,63,
|
||
|
64,-1,-1,-1,61,61,30,61,62, 2,52, 2,-1,36,53,36,
|
||
|
-1,-1,66,28,36,-1,-1,-1,28,-1,-1,-1,-1,25,27, 2,
|
||
|
2, 2, 2, 2, 2,25, 2, 2, 2, 2, 2,27, 2,52, 2,53,
|
||
|
45,53,51,26,46, 2, 2, 2,62,11, 2, 2,65,65,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,26,41,41,41
|
||
|
]
|
||
|
|
||
|
lud = dict()
|
||
|
person_dict = dict()
|
||
|
person_box = (6, 5, 10,11)
|
||
|
person_tiles = list()
|
||
|
fail_person_tiles = list()
|
||
|
fail_person_dict = dict()
|
||
|
|
||
|
for i, key in enumerate(res['tiles']):
|
||
|
if i >= len(mapp):
|
||
|
continue
|
||
|
elif mapp[i] >= 0:
|
||
|
num = mapp[i]
|
||
|
typ = ts[num]
|
||
|
obs = obss[num]
|
||
|
subi = load_image(key)
|
||
|
subi_key = image_to_string_format(subi, "BMP")
|
||
|
lud[subi_key] = {"type": typ, "obs": obs, "num": num, "raw_i": i}
|
||
|
elif mapp[i] == -1:
|
||
|
#this is a person tile, so put it into the person-sets.
|
||
|
#go through all (regular) tiles and find the one with the lowest
|
||
|
#difference with this tile.
|
||
|
max_c = 0
|
||
|
succ_tile = None
|
||
|
diff_tile = None
|
||
|
for j, tile in enumerate(res['tiles']):
|
||
|
if j<len(mapp) and mapp[j] >= 0:
|
||
|
dd = ImageChops.difference(load_image(key), load_image(tile))
|
||
|
for c in dd.convert("RGBA").getcolors():
|
||
|
if c[1][:3] == (0,0,0):
|
||
|
val = c[0]
|
||
|
if val > max_c:
|
||
|
max_c = val
|
||
|
succ_tile = tile
|
||
|
diff_tile = dd
|
||
|
if succ_tile:
|
||
|
cropped1 = load_image(succ_tile).crop(person_box)
|
||
|
cropped2 = load_image(key).crop(person_box)
|
||
|
dd = ImageChops.difference(cropped1, cropped2).convert("RGBA")
|
||
|
cc = None
|
||
|
for cc in dd.getcolors():
|
||
|
if cc[1][:3] == (0,0,0):
|
||
|
break
|
||
|
if (cc and cc[0] < cropped1.width*cropped1.height/2) or cc is None:
|
||
|
if cc:
|
||
|
print([cc[0], 64])
|
||
|
|
||
|
pkey = image_to_string_format(cropped2, "BMP")
|
||
|
person_dict[key] = pkey
|
||
|
person_tiles.append(key)
|
||
|
else:
|
||
|
pkey = image_to_string_format(cropped2, "BMP")
|
||
|
fail_person_tiles.append(key)
|
||
|
fail_person_dict[key] = pkey
|
||
|
#...a
|
||
|
tilesize = 16
|
||
|
width = 8*tilesize
|
||
|
height = int(len(person_tiles)/8+1)*tilesize
|
||
|
pim = Image.new("RGB", (width, height))
|
||
|
wx = 0
|
||
|
wy = 0
|
||
|
for key in person_tiles:
|
||
|
subi = load_image(key).crop((0,0,tilesize-1, tilesize-1))
|
||
|
|
||
|
pim.paste(subi, (wx,wy))
|
||
|
wx+=tilesize
|
||
|
if wx >= width:
|
||
|
wx = 0
|
||
|
wy+=tilesize
|
||
|
pim.save("p.png")
|
||
|
pim.show()
|
||
|
|
||
|
wx=0
|
||
|
wy=0
|
||
|
width = 8*tilesize
|
||
|
height = int(len(fail_person_tiles)/8+1)*tilesize
|
||
|
pim2 = Image.new("RGB", (width, height))
|
||
|
for key in fail_person_tiles:
|
||
|
subi = load_image(key).crop((0,0,tilesize-1, tilesize-1))
|
||
|
|
||
|
pim2.paste(subi, (wx,wy))
|
||
|
wx+=tilesize
|
||
|
if wx >= width:
|
||
|
wx = 0
|
||
|
wy+=tilesize
|
||
|
pim2.save("p_f.png")
|
||
|
pim2.show()
|
||
|
|
||
|
#fix p.png stuff here below--v !!!
|
||
|
pmap = [ 0, 0, 0, 1, 1, 2, 1, 0,
|
||
|
3, 0, 2, 0, 2, 2, 2, 1,
|
||
|
2, 1, 2, 2, 1, 1, 2, 4,
|
||
|
1, 5, 4, 5, 4, 4, 1, 0,
|
||
|
3, 3, 0, 3, 0, 3, 0, 3,
|
||
|
6, 6, 7, 0, 6, 6, 6, 6,
|
||
|
6,10,10,10,11,10,10,11,
|
||
|
10,10,12,12,12,12,13,13,
|
||
|
13,13, 0,13, 0,12, 0,12,
|
||
|
0, 5, 5, 5,13, 5,13,14,
|
||
|
14,14,14,14,14,14,14,14,
|
||
|
10,10,10,14, 6, 6, 6, 6,
|
||
|
5, 1, 5, 7, 0, 7, 0,16,
|
||
|
16,16,16,16,16,16,12,12,
|
||
|
12,12,12, 0,12,12,12,16,
|
||
|
12, 5,16, 5,16,16, 0,16,
|
||
|
7, 7,12, 7,12, 7,17,18,
|
||
|
18, 5, 5, 0, 0, 0, 0,12,
|
||
|
12,19,19,19,20,20,20,20,
|
||
|
20,20,20,20,20,12,12,12,
|
||
|
12, 7, 2, 7, 7, 2, 7, 2,
|
||
|
7, 7,10, 2, 2,10,10,10,
|
||
|
11,10,11,10, 2, 2, 2, 4,
|
||
|
4,12, 4, 4, 4, 0, 0, 0,
|
||
|
4, 0,21,21,21, 2,13, 2,
|
||
|
2,13,13, 1,13, 1, 1, 2,
|
||
|
2,13,21,21,13,13,12,21,
|
||
|
12,21, 5, 1, 2, 5, 2,11,
|
||
|
11, 0, 0, 0, 0, 0, 0,20,
|
||
|
20,20,22,22,19,19,19,23,
|
||
|
23,23,23,23,24,24,24,24,
|
||
|
24,22,22,22,25,25,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1
|
||
|
]
|
||
|
pmapf = [-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
1,-1,-1,-1,-1,-1,25,25,
|
||
|
-1,-1,-1, 9,25,-1,25,25,
|
||
|
25,-1, 9,-1,25,25,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,13,-1,
|
||
|
13,-1,13,-1,21,-1,-1,-1,
|
||
|
-1,21,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,25,25,
|
||
|
-1,-1,-1,-1,25,25,25,-1,
|
||
|
25,25,-1,15,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,12,
|
||
|
-1, 0,12,-1,-1,-1, 0,-1,
|
||
|
0,-1, 0,-1,-1, 0,-1,-1,
|
||
|
12,-1,-1,12,-1,-1,-1,-1,
|
||
|
0,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,16,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,16,-1,-1,
|
||
|
-1,-1,25,-1,-1,-1,-1,25,
|
||
|
-1,-1,-1,25,-1,25,-1,25,
|
||
|
-1,25,25,-1,25,25,25,-1,
|
||
|
25,-1,25,-1,-1,-1,-1,-1,
|
||
|
-1,19,19,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
2,-1,-1,-1,-1, 2,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1, 0,
|
||
|
-1,-1,21,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,21,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,20,
|
||
|
-1,-1,-1,25,25,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,22,22,-1,-1,-1,
|
||
|
22,-1,-1,-1,22,22,-1,-1,
|
||
|
25,-1,-1,-1,-1,25,-1, 9,
|
||
|
9,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1,-1,-1,-1,-1,-1,-1,-1,
|
||
|
-1
|
||
|
]
|
||
|
|
||
|
persons = ["woman", "guard", "dancer", "boy", "old woman",
|
||
|
"old man", "girl", "scholar", "king", "garland",
|
||
|
"broom", "witch", "man", "punk", "elf",
|
||
|
"astros", "dwarf", "vampire", "monster", "airship",
|
||
|
"dragon", "pirate","robot", "mermaid", "robed",
|
||
|
"bat",
|
||
|
]
|
||
|
plud = {"person_box": person_box,
|
||
|
"person_dict": {}}
|
||
|
for i, key in enumerate(person_tiles):
|
||
|
print("p", i,key)
|
||
|
if pmap[i] >= 0:
|
||
|
cropped_pic = person_dict[key]
|
||
|
plud['person_dict'][cropped_pic] = {
|
||
|
"num": pmap[i],
|
||
|
"type": persons[pmap[i]],
|
||
|
"obs": 1,
|
||
|
"raw_i": i
|
||
|
}
|
||
|
|
||
|
for i, key in enumerate(fail_person_tiles):
|
||
|
print("pp", i,key)
|
||
|
if pmapf[i] >= 0:
|
||
|
cropped_pic = fail_person_dict[key]
|
||
|
plud['person_dict'][cropped_pic] = {
|
||
|
"num": pmapf[i],
|
||
|
"type": persons[pmapf[i]],
|
||
|
"obs": 1,
|
||
|
"raw_i": i,
|
||
|
"fail_set": True,
|
||
|
}
|
||
|
|
||
|
tile_info = {"off_x": res['off_x'],
|
||
|
"off_y": res['off_y'],
|
||
|
"tilesize": res['tilesize']
|
||
|
}
|
||
|
saved_data = {"tile_info": tile_info, "lud": lud,
|
||
|
"plud": plud}
|
||
|
file_w = open("ff1_data.lud", "w")
|
||
|
file_w.write(json.dumps(saved_data))
|
||
|
for i in range(10):
|
||
|
im = Image.open("maps_"+str(2+i)+".png")
|
||
|
t = time.time()
|
||
|
k, map_data = ParseScreenObstructions.parse_screen(im, tile_info, lud,
|
||
|
plud, partial_center=True)
|
||
|
print(time.time()-t)
|
||
|
import pdb
|
||
|
pdb.set_trace()
|
||
|
|
||
|
|
||
|
class PathFinder:
|
||
|
persons_set = {"woman", "guard", "dancer", "boy", "old woman",
|
||
|
"old man", "girl", "scholar", "king", "garland",
|
||
|
"broom", "witch", "man", "punk", "elf",
|
||
|
"astros", "dwarf", "vampire", "monster", "airship",
|
||
|
"dragon", "pirate","robot", "mermaid", "robed"}
|
||
|
dont_expand_types = ['stairs up', 'stairs down', 'ladder up', 'ladder down', "teleporter up", "teleporter down", "hole"]
|
||
|
|
||
|
@classmethod
|
||
|
def find_paths(cls, map_data, y, x):
|
||
|
def valid(y,x):
|
||
|
if map_data['tiles'][y][x]['obs'] in ob or map_data['tiles'][y][x]['type'] in cls.persons_set:
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
def dont_expand(y,x):
|
||
|
if map_data['tiles'][y][x]['obs'] in obs or map_data['tiles'][y][x]['type'] in cls.persons_set or map_data['tiles'][y][x]['type'] in cls.dont_expand_types:
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
marked = {(y,x): (0,0)}
|
||
|
last_marked = [(y,x)]
|
||
|
ob = [0,2,3]
|
||
|
obs = [3]
|
||
|
print(map_data)
|
||
|
try:
|
||
|
while last_marked:
|
||
|
new_marked = list()
|
||
|
for y,x in last_marked:
|
||
|
if map_data['tiles'][y][x] and dont_expand(y,x):
|
||
|
continue
|
||
|
#mark up
|
||
|
if y > 0 and (y-1,x) not in marked and valid(y-1,x):
|
||
|
new_marked.append((y-1,x, 1, 0))
|
||
|
marked[(y-1, x)] = (-1,0)
|
||
|
#mark down
|
||
|
if y < len(map_data['tiles'])-1 and (y+1,x) not in marked and valid(y+1,x):
|
||
|
new_marked.append((y+1,x, -1,0))
|
||
|
marked[(y+1,x)] = (1,0)
|
||
|
#mark left
|
||
|
if x > 0 and (y,x-1) not in marked and valid(y,x-1):
|
||
|
new_marked.append((y, x-1, 0,1))
|
||
|
marked[(y,x-1)] = (0,-1)
|
||
|
#mark right
|
||
|
if x < len(map_data['tiles'][0])-1 and (y,x+1) not in marked and valid(y,x+1):
|
||
|
new_marked.append((y, x+1, 0,-1))
|
||
|
marked[(y,x+1)] = (0,1)
|
||
|
last_marked = list()
|
||
|
for y,x,vy,vx in new_marked:
|
||
|
last_marked.append((y,x))
|
||
|
except:
|
||
|
return None
|
||
|
return marked
|
||
|
|
||
|
@classmethod
|
||
|
def find_path(cls, marked, y,x):
|
||
|
if not (y,x) in marked:
|
||
|
return None
|
||
|
path = list()
|
||
|
py,px = y,x
|
||
|
|
||
|
while marked[(py, px)] not in [(0,0), None]:
|
||
|
vy, vx = marked[(py,px)]
|
||
|
path.append((py,px, vy,vx))
|
||
|
py-=vy
|
||
|
px-=vx
|
||
|
print("path", path[-1])
|
||
|
|
||
|
path = path[::-1]
|
||
|
return path
|
||
|
|
||
|
|
||
|
class PackageOutput:
|
||
|
def __init__(self, filename, enemy_filename):
|
||
|
ScreenSelector._load_content(None, None, None, filename, enemy_filename)
|
||
|
self.memory = list()
|
||
|
self.pause_mode = {"active": False, "goal": None}
|
||
|
self.press_mem = {}
|
||
|
self.state_mem = {}
|
||
|
|
||
|
def get_output(self, im, state_dict):
|
||
|
typ, k, map_data = ScreenSelector.parse_whole_screen(im)
|
||
|
path_data = PathFinder.find_paths(map_data, 6,7)
|
||
|
#for key in state_dict:
|
||
|
# if key in ['up', 'down', 'left', 'right'] and state_dict.get(key) == 1:
|
||
|
# self.pause_mode['active'] = False
|
||
|
# self.pause_mode['goal'] = 'menu'
|
||
|
|
||
|
#print(k)
|
||
|
#print(typ, '-----')
|
||
|
mem = self.memory
|
||
|
if self.state_mem.get('paused') != state_dict.get("paused"):
|
||
|
mem = dict()
|
||
|
|
||
|
output = list()
|
||
|
press_output = list()
|
||
|
|
||
|
mem_dont = False
|
||
|
|
||
|
if typ == "world":
|
||
|
if state_dict.get("paused") == 0 or True:
|
||
|
if not k:
|
||
|
mem_dont = True
|
||
|
for entry in k:
|
||
|
#if entry not in mem:
|
||
|
output.append(entry)
|
||
|
else:
|
||
|
#maybe not?
|
||
|
for entry in k:
|
||
|
output.append(entry)
|
||
|
elif typ == 'map':
|
||
|
#print(state_dict)
|
||
|
specials = dict()
|
||
|
specials_list = list()
|
||
|
if state_dict.get('paused')==0:
|
||
|
special_flag = False
|
||
|
for entry in k:
|
||
|
if entry == "special":
|
||
|
special_flag = True
|
||
|
elif special_flag:
|
||
|
sp = entry.split(" ")
|
||
|
spec = sp[0]
|
||
|
for i in range(len(sp)):
|
||
|
if sp[i].replace("-", "").isdigit():
|
||
|
spec = " ".join(sp[:i])
|
||
|
break
|
||
|
if spec not in " ".join(mem):
|
||
|
print("spec", spec)
|
||
|
print(" ".join(mem).split())
|
||
|
specials[spec] = 1
|
||
|
else:
|
||
|
sp = entry.split(" ")
|
||
|
if len(sp) > 3:
|
||
|
sp[2] = " ".join(sp[2:])
|
||
|
if len(sp) > 2 and sp[2] in ['grass', 'woods',
|
||
|
'dirt', 'desert',
|
||
|
'swamp', 'tile', 'meadow']:
|
||
|
continue
|
||
|
output.append(sp[0]+" "+sp[2]+",")
|
||
|
if not output:
|
||
|
output.append("None")
|
||
|
if specials:
|
||
|
print("____++", mem)
|
||
|
output.append("special,")
|
||
|
for key in specials:
|
||
|
output.append(key+",")
|
||
|
if output and output[-1] and output[-1][-1] == ",":
|
||
|
output[-1] = output[-1][:-1]
|
||
|
for key in ['west', 'east', 'south', 'north']:
|
||
|
if key+" unknown" not in output and\
|
||
|
key+" unknown," not in output:
|
||
|
break
|
||
|
else:
|
||
|
output = [" "]
|
||
|
mem_dont = True
|
||
|
else:
|
||
|
special = False
|
||
|
dir_seen = dict()
|
||
|
mem_seen = dict()
|
||
|
try:
|
||
|
mem[5:]
|
||
|
except:
|
||
|
mem = list()
|
||
|
|
||
|
for entry in k:
|
||
|
if special is False and entry.split(" ")[0].lower() in ['west','east','north','south']:
|
||
|
output.append(entry+",")
|
||
|
elif entry == 'special':
|
||
|
special = True
|
||
|
output.append(entry+",")
|
||
|
else:
|
||
|
#for the ai menu...
|
||
|
specials_list.append(entry)
|
||
|
|
||
|
sp = entry.split(" ")
|
||
|
seen = []
|
||
|
#convert from coordinates here to west/east directions
|
||
|
count = 0
|
||
|
res = list()
|
||
|
for i, ent in enumerate(sp):
|
||
|
if ent.replace("-", "").isdigit():
|
||
|
if count == 0:
|
||
|
if int(ent) > 0:
|
||
|
res.append("east "+ent)
|
||
|
else:
|
||
|
res.append("west "+ent.replace("-", ""))
|
||
|
count+=1
|
||
|
else:
|
||
|
if int(ent) > 0:
|
||
|
res.append("north "+ent)
|
||
|
else:
|
||
|
res.append("south "+ent.replace("-", ""))
|
||
|
else:
|
||
|
res.append(ent)
|
||
|
entry = " ".join(res)
|
||
|
|
||
|
if entry not in mem_seen:
|
||
|
seen.append(entry)
|
||
|
|
||
|
if len(seen) > 0:
|
||
|
output.append(" ".join(seen)+",")
|
||
|
if output[-1] in ['special', 'special,']:
|
||
|
output = output[:-1]
|
||
|
if output and output[-1] and output[-1][-1] == ",":
|
||
|
output[-1] = output[-1][:-1]
|
||
|
elif typ == 'text':
|
||
|
for entry in k:
|
||
|
if entry not in mem:
|
||
|
output.append(entry)
|
||
|
elif typ == 'menu':
|
||
|
for entry in k:
|
||
|
if entry not in mem:
|
||
|
output.append(entry)
|
||
|
elif typ == 'shop':
|
||
|
if type(k) != type(mem):
|
||
|
output = [k['title'], k['text'], k['menu']]
|
||
|
else:
|
||
|
output = list()
|
||
|
for key in ['title', 'text', 'menu']:
|
||
|
if mem.get(key) != k[key]:
|
||
|
output.append(k[key])
|
||
|
elif typ == 'battle':
|
||
|
output = list()
|
||
|
if state_dict.get("paused", 0) == 0:
|
||
|
for key in ['enemy_string', 'status', 'character', 'menu']:
|
||
|
if key == "status":
|
||
|
if type(k) != type(mem) and k[key]:
|
||
|
output.extend(k[key])
|
||
|
elif k[key]:
|
||
|
for entry in k[key]:
|
||
|
if entry not in mem.get(key,[]):
|
||
|
output.append(entry)
|
||
|
elif (type(k) != type(mem) or mem.get(key) != k.get(key)) and k.get(key):
|
||
|
if type(k[key]) == list:
|
||
|
output.extend(k[key])
|
||
|
else:
|
||
|
output.append(k[key])
|
||
|
else:
|
||
|
for key in ['enemy_string', 'status', 'textbox', 'character', 'menu']:
|
||
|
if k[key]:
|
||
|
if type(k[key]) == list:
|
||
|
output.extend(k[key])
|
||
|
else:
|
||
|
output.append(k[key])
|
||
|
if mem_dont == False:
|
||
|
self.memory = k
|
||
|
self.state_mem = state_dict
|
||
|
|
||
|
clicked = dict()
|
||
|
for key in state_dict:
|
||
|
if state_dict[key] and not self.press_mem.get(key):
|
||
|
self.press_mem[key] = True
|
||
|
clicked[key] = True
|
||
|
print(clicked)
|
||
|
for key in self.press_mem:
|
||
|
if not state_dict.get(key):
|
||
|
self.press_mem[key] = False
|
||
|
|
||
|
if state_dict.get("paused") == 1:
|
||
|
if self.pause_mode['active'] is True:
|
||
|
output = list()
|
||
|
print(self.pause_mode)
|
||
|
if self.pause_mode['active'] is False and clicked.get('start'):
|
||
|
self.pause_mode['active'] = True
|
||
|
self.pause_mode['goal'] = "menu"
|
||
|
self.pause_mode['select'] = 0
|
||
|
output = ["AI Menu"]
|
||
|
if typ == "map":
|
||
|
self.pause_mode['menu'] = [str(i+1)+": "+" ".join(x.strip().split(" ")[:-2])+", " for i,x in enumerate(specials_list)]
|
||
|
self.pause_mode['total'] = len(self.pause_mode['menu'])
|
||
|
#output.extend(self.pause_mode['menu'])
|
||
|
elif clicked.get("start") and self.pause_mode['goal'] == "menu":
|
||
|
#activate menu selection
|
||
|
output = ["Going to: "+self.pause_mode['menu'][self.pause_mode['select']].partition(": ")[2]]
|
||
|
self.pause_mode['goal'] = self.pause_mode['menu'][self.pause_mode['select']]
|
||
|
elif self.pause_mode['active'] and state_dict.get("start") and self.pause_mode['goal'] != "menu":
|
||
|
pass
|
||
|
elif self.pause_mode['active'] and not state_dict.get("start") and self.pause_mode['goal'] != "menu":
|
||
|
print(self.pause_mode['goal'])
|
||
|
press_output = ["unpause"]
|
||
|
elif self.pause_mode['active'] and self.pause_mode['total'] > 0:
|
||
|
if state_dict.get("a"):#clicked.get("a"):
|
||
|
self.pause_mode['select'] += 1
|
||
|
if state_dict.get("b"):#clicked.get("b"):
|
||
|
self.pause_mode['select'] -= 1
|
||
|
|
||
|
if self.pause_mode['select'] < 0:
|
||
|
self.pause_mode['select'] += self.pause_mode['total']
|
||
|
if self.pause_mode['select'] >= self.pause_mode['total']:
|
||
|
self.pause_mode['select'] -= self.pause_mode['total']
|
||
|
if self.pause_mode['active'] and self.pause_mode['goal'] == "menu":
|
||
|
if self.pause_mode['total'] > 0:
|
||
|
output.append("Go to: "+self.pause_mode['menu'][self.pause_mode['select']])
|
||
|
else:
|
||
|
if self.pause_mode['active'] and self.pause_mode['goal'] != "menu":
|
||
|
#move to target
|
||
|
#find shortest path to target here...
|
||
|
#aaa AAA
|
||
|
goal = self.pause_mode['goal']
|
||
|
num = int(goal.partition(": ")[0])-1
|
||
|
target = goal.partition(": ")[2]
|
||
|
|
||
|
count = 0
|
||
|
x, y = None, None
|
||
|
special_flag = False
|
||
|
print(k)
|
||
|
for entry in k:
|
||
|
ee = target.partition(",")[0]
|
||
|
if "special" in entry:
|
||
|
special_flag = True
|
||
|
if ee in entry and special_flag:
|
||
|
count+=1
|
||
|
coords = entry.partition(ee)[2].strip().split(" ")
|
||
|
x, y = int(coords[0]), int(coords[1])
|
||
|
if count == num:
|
||
|
break
|
||
|
if path_data and x is not None and y is not None:
|
||
|
path = PathFinder.find_path(path_data, 6-y,7+x)
|
||
|
print("X Y ",x,y,target, num, goal)
|
||
|
if path:
|
||
|
vy = -1*path[0][2]
|
||
|
vx = path[0][3]
|
||
|
if vx != None:
|
||
|
if vy < 0:
|
||
|
press_output.append("down")
|
||
|
elif vy > 0:
|
||
|
press_output.append("up")
|
||
|
elif vx < 0:
|
||
|
press_output.append("left")
|
||
|
elif vx > 0:
|
||
|
press_output.append("right")
|
||
|
print("AAAA ", map_data['tiles'][6-vy][7+vx]['type'], target)
|
||
|
if map_data['tiles'][6-vy][7+vx]['type'] == target.replace(",", "").strip():
|
||
|
press_output.append("a")
|
||
|
output = list()
|
||
|
if "unknown" not in" ".join(k).partition("special")[0] and (count == 0 or abs(x)+abs(y) <= 1):
|
||
|
self.pause_mode['active'] = False
|
||
|
self.pause_mode['goal'] = 'menu'
|
||
|
else:
|
||
|
output = list()
|
||
|
else:
|
||
|
self.pause_mode['active'] = False
|
||
|
self.pause_mode['goal'] = 'menu'
|
||
|
output = ['No path available']
|
||
|
else:
|
||
|
output = list()
|
||
|
elif self.pause_mode['active']:
|
||
|
if self.pause_mode['goal'] == "menu":
|
||
|
self.pause_mode['active'] = False
|
||
|
else:
|
||
|
pass
|
||
|
if typ != "map":
|
||
|
self.pause_mode['active'] = False
|
||
|
self.pause_mode['goal'] = 'menu'
|
||
|
|
||
|
return output, press_output
|
||
|
|
||
|
def run(self, im, state_dict):
|
||
|
new_out = self.get_output(im, state_dict)
|
||
|
return new_out
|
||
|
|
||
|
|
||
|
def main_b():
|
||
|
doc = json.loads(open("ff1_data.lud", "r").read())
|
||
|
tile_info = doc['tile_info']
|
||
|
lud = doc['lud']
|
||
|
plud = doc['plud']
|
||
|
|
||
|
for i in range(10):
|
||
|
im = Image.open("maps_"+str(2+i)+".png")
|
||
|
t = time.time()
|
||
|
k, map_data = ParseScreenObstructions.parse_screen(im, tile_info, lud,
|
||
|
plud, partial_center=True)
|
||
|
print( time.time()-t)
|
||
|
import pdb
|
||
|
pdb.set_trace()
|
||
|
|
||
|
def main_c():
|
||
|
po = PackageOutput("ff1_data.lud", "enemy_lookup.dat")
|
||
|
for i in range(10):
|
||
|
im = Image.open("maps_"+str(2+i)+".png")
|
||
|
t = time.time()
|
||
|
print ("--", po.memory)
|
||
|
print (po.run(im))
|
||
|
print (time.time()-t)
|
||
|
import pdb
|
||
|
pdb.set_trace()
|
||
|
|
||
|
|
||
|
class ParseScreenObstructions:
|
||
|
@classmethod
|
||
|
def parse_screen(cls, im, tile_info, lud, plud, partial_center=False):
|
||
|
off_x = tile_info['off_x']#0
|
||
|
off_y = tile_info['off_y']#8
|
||
|
tilesize = tile_info['tilesize']
|
||
|
map_data = {"center": [6,7], "tiles": []}
|
||
|
|
||
|
#AAAAAAAAaaaaaaaaaaa
|
||
|
#-start at center of the screen, go out in 4 directions and
|
||
|
# get the tiles
|
||
|
screen = TileTools.parse_tiles(im, off_x, off_y, tilesize,
|
||
|
partial_center=partial_center)
|
||
|
horizontal = list()
|
||
|
vertical = list()
|
||
|
special = list()
|
||
|
unknown_limit = 32
|
||
|
unknown_count = 0
|
||
|
for y, row in enumerate(screen):
|
||
|
map_data['tiles'].append([])
|
||
|
for x, tile in enumerate(row):
|
||
|
person = None
|
||
|
if partial_center == True and x == 7 and y == 5:
|
||
|
doc = None
|
||
|
for key in lud:
|
||
|
#bmps are stored upside down, so do endswith here..
|
||
|
if key.endswith(tile[-len(tile)*3/4:]):
|
||
|
doc = lud.get(key)
|
||
|
break
|
||
|
else:
|
||
|
doc = lud.get(tile)
|
||
|
if doc is None and tile is not None:
|
||
|
#check person tiles
|
||
|
|
||
|
pt = load_image(tile)
|
||
|
cropped = pt.crop(plud['person_box'])
|
||
|
pkey = image_to_string_format(cropped, "BMP")
|
||
|
|
||
|
if pkey in plud['person_dict']:
|
||
|
person = plud['person_dict'][pkey]
|
||
|
doc = {"obs": person['obs'],
|
||
|
"type": person['type'],
|
||
|
"num": person['num'],
|
||
|
"raw_i": person['raw_i']}
|
||
|
else:
|
||
|
#handle tiles that are overlayed a bit with a
|
||
|
#sprite below them
|
||
|
for key in lud:
|
||
|
#bmps are stored upside down, so do endswith here..
|
||
|
if key.endswith(tile[-len(tile)*3/4:]):
|
||
|
doc = lud.get(key)
|
||
|
break
|
||
|
else:
|
||
|
unknown_count+=1
|
||
|
|
||
|
if y == 6:
|
||
|
horizontal.append(doc)
|
||
|
if x == 7:
|
||
|
vertical.append(doc)
|
||
|
map_data['tiles'][-1].append(doc)
|
||
|
|
||
|
if doc and (doc['obs'] in [2,3] or person):
|
||
|
if doc['type'] != 'bat':
|
||
|
special.append([x,y, doc, tile])
|
||
|
if unknown_count > unknown_limit:
|
||
|
horizontal = [None for x in horizontal]
|
||
|
vertical = [None for x in vertical]
|
||
|
special_groups = dict()
|
||
|
|
||
|
for tup in sorted(special, key=lambda x:(x[0],x[1])):
|
||
|
if tup[2]['type'] not in special_groups:
|
||
|
special_groups[tup[2]['type']] = [[tup]]
|
||
|
else:
|
||
|
for entry_tup in special_groups[tup[2]['type']]:
|
||
|
for e_tup2 in entry_tup:
|
||
|
if abs(tup[0]-e_tup2[0])+abs(tup[1]-e_tup2[1])<2:
|
||
|
entry_tup.append(tup)
|
||
|
break
|
||
|
else:
|
||
|
continue
|
||
|
break
|
||
|
else:
|
||
|
special_groups[tup[2]['type']].append([tup])
|
||
|
new_special = list()
|
||
|
for ent_group in special_groups:
|
||
|
for ent in special_groups[ent_group]:
|
||
|
num = 0
|
||
|
sx=0
|
||
|
sy=0
|
||
|
for tup in ent:
|
||
|
sx+=tup[0]
|
||
|
sy+=tup[1]
|
||
|
num+=1
|
||
|
ent[0][0] = int(sx/num)
|
||
|
ent[0][1] = int(sy/num)
|
||
|
new_special.append(ent[0])
|
||
|
special = new_special
|
||
|
results = {"horizontal": horizontal, "vertical": vertical,
|
||
|
"special": special, "im": im}
|
||
|
return cls.output_to_text(results), map_data
|
||
|
|
||
|
#-compute the tile types (obstruction or not, special or not).
|
||
|
#--have sound types for wood, brick, water, etc.
|
||
|
#-convert to sound info.
|
||
|
#--if no info found, assume that the play moved a bit.
|
||
|
pass
|
||
|
|
||
|
@classmethod
|
||
|
def output_to_text(cls, results):
|
||
|
west_obs = None
|
||
|
east_obs = None
|
||
|
south_obs = None
|
||
|
north_obs = None
|
||
|
for i, doc in enumerate(results['horizontal']):
|
||
|
if doc and i != 7 and doc['obs']%2 == 1:
|
||
|
if i < 7:
|
||
|
west_obs = 6-i;
|
||
|
if i > 7 and east_obs == None:
|
||
|
east_obs = i-8;
|
||
|
|
||
|
for j, doc in enumerate(results['vertical']):
|
||
|
if doc and j != 6 and doc['obs']%2 == 1:
|
||
|
if j < 6:
|
||
|
north_obs = 5-j;
|
||
|
if j > 6 and south_obs == None:
|
||
|
south_obs = j-7;
|
||
|
|
||
|
west_tile = results['horizontal'][6]
|
||
|
if west_tile is not None:
|
||
|
west_tile = west_tile['type']
|
||
|
else:
|
||
|
west_tile = "unknown"
|
||
|
|
||
|
east_tile = results['horizontal'][8]
|
||
|
if east_tile is not None:
|
||
|
east_tile = east_tile['type']
|
||
|
else:
|
||
|
east_tile = "unknown"
|
||
|
|
||
|
south_tile = results['vertical'][7]
|
||
|
if south_tile is not None:
|
||
|
south_tile = south_tile['type']
|
||
|
else:
|
||
|
south_tile = "unknown"
|
||
|
|
||
|
north_tile = results['vertical'][5]
|
||
|
if north_tile is not None:
|
||
|
north_tile = north_tile['type']
|
||
|
else:
|
||
|
north_tile = "unknown"
|
||
|
|
||
|
outputs = ["west "+str(west_obs)+" "+west_tile,
|
||
|
"north "+str(north_obs)+" "+north_tile,
|
||
|
"east "+str(east_obs)+" "+east_tile,
|
||
|
"south "+str(south_obs)+" "+south_tile]
|
||
|
|
||
|
sp = dict()
|
||
|
sp_a = list()
|
||
|
for k, doc in enumerate(results['special']):
|
||
|
x,y = doc[0]-7, doc[1]-6
|
||
|
angle = math.atan2(-y,x)
|
||
|
while angle < 0:
|
||
|
angle+=math.pi*2
|
||
|
while angle > math.pi*2:
|
||
|
angle-=math.pi*2
|
||
|
|
||
|
if math.pi/8 <= angle <= 3*math.pi/8:
|
||
|
dr = "northeast"
|
||
|
elif 3*math.pi/8 < angle <= 5*math.pi/8:
|
||
|
dr = "north"
|
||
|
elif 5*math.pi/8 < angle <= 7*math.pi/8:
|
||
|
dr = "northwest"
|
||
|
elif 7*math.pi/8 < angle <= 9*math.pi/8:
|
||
|
dr = "west"
|
||
|
elif 9*math.pi/8 < angle <= 11*math.pi/8:
|
||
|
dr = "southwest"
|
||
|
elif 11*math.pi/8 < angle <= 13*math.pi/8:
|
||
|
dr = "south"
|
||
|
elif 13*math.pi/8 < angle <= 15*math.pi/8:
|
||
|
dr = "southeast"
|
||
|
elif angle < math.pi/8 or angle > 15*(math.pi/8):
|
||
|
dr = "east"
|
||
|
"""
|
||
|
if math.pi/4 <= angle <= 3*math.pi/4:
|
||
|
dr = "north"
|
||
|
elif 3*math.pi/4 < angle <= 5*math.pi/4:
|
||
|
dr = "west"
|
||
|
elif 5*math.pi/4 < angle <= 7*math.pi/4:
|
||
|
dr = "south"
|
||
|
elif angle < math.pi/4 or angle > 7*(math.pi/4):
|
||
|
dr = "east"
|
||
|
"""
|
||
|
sp_a.append(doc[2]['type']+" "+str(x)+" "+str(-1*y)+" ")
|
||
|
|
||
|
if dr not in sp:
|
||
|
sp[dr] = OrderedDict()
|
||
|
sp[dr][doc[2]['type']] = 1
|
||
|
if sp:
|
||
|
outputs.append("special")
|
||
|
outputs.extend(sp_a)
|
||
|
"""
|
||
|
for key in ['west', 'northwest', 'north', 'northeast',
|
||
|
'east', 'southeast', 'south', 'southwest']:
|
||
|
if sp.get(key):
|
||
|
outputs.append(key)
|
||
|
for subkey in sp[key]:
|
||
|
outputs[-1] = outputs[-1]+" "+subkey
|
||
|
"""
|
||
|
return outputs
|
||
|
|
||
|
class ParseScreenText:
|
||
|
@classmethod
|
||
|
def get_font(cls, text_image_list):
|
||
|
found_tiles = OrderedDict()
|
||
|
for image in text_image_list:
|
||
|
for j in range(int(image.height/8)):
|
||
|
for i in range(int(image.width/8)):
|
||
|
subi = image.crop((i*8, j*8, i*8+8, j*8+8))
|
||
|
ss = image_to_string_format(subi, "BMP")
|
||
|
found_tiles[ss] = found_tiles.get(ss,0)+1
|
||
|
|
||
|
seen = OrderedDict()
|
||
|
c=0
|
||
|
for i, ch in enumerate(found_tiles):
|
||
|
ss = image_to_string_format(reduce_to_colors(load_image(ch).convert("P", palette=Image.ADAPTIVE), ["FFFFFF"], 32), "BMP")
|
||
|
if ss not in seen:
|
||
|
c+=1
|
||
|
seen[ss] = ch
|
||
|
|
||
|
im = Image.new("RGB", (8*c, 8))
|
||
|
for c, k in enumerate(seen):
|
||
|
ch = seen[k]
|
||
|
im.paste(load_image(ch), (c*8, 0))
|
||
|
|
||
|
kk = found_tiles.keys()
|
||
|
stra = [x for x in " >>ABCDEFGHIJ KLMNOPQRSTUVWXYZ',.123456789abcdefghijklmnopqrstuvwxyz-"]
|
||
|
stra.extend(["..", "!", "?", " "," "," "," "," "," "," "," ",">",">"," "," ", "Mail", "Rod", " ", "Sword", " ", " "," "," "," "," "," ","Nunchucks", " ", " ","Hammer", " ", " ", " ", "Level", "/", "Weapon", " ", " ", " ", " ", "Status", " ", " ", " ", " ", " ", " ", ">", ">", " ", "E", ">", ">", "Fight", " ", " ", " "," ", " ", "Magic", " ", " ", " ", "Drink", " ", " ", " "])
|
||
|
output_dict = OrderedDict()
|
||
|
kk2 = [seen[x] for x in seen.keys()]
|
||
|
for i, ch in enumerate(kk2):
|
||
|
subi = load_image(ch)
|
||
|
new_subi = reduce_to_colors(subi.convert("P", palette=Image.ADAPTIVE), ["FFFFFF"], 32)
|
||
|
str_image = image_to_string_format(new_subi, "BMP")
|
||
|
if i < len(stra) and str_image not in output_dict:
|
||
|
output_dict[str_image] = stra[i]
|
||
|
|
||
|
return output_dict
|
||
|
|
||
|
@classmethod
|
||
|
def parse_screen(cls, im, font_dict):
|
||
|
im = reduce_to_colors(im.convert("P", palette=Image.ADAPTIVE), ["FFFFFF"], 32).convert("RGB")
|
||
|
text = [[]]
|
||
|
for j in range(int(im.height/8)):
|
||
|
for i in range(int(im.width/8)):
|
||
|
subi = im.crop((i*8, j*8, i*8+8, j*8+8))
|
||
|
subi_key= image_to_string_format(subi, "BMP")
|
||
|
value = font_dict.get(subi_key, " ")
|
||
|
text[-1].append(value)
|
||
|
text.append([])
|
||
|
output = list()
|
||
|
current_output = ""
|
||
|
si = 0
|
||
|
sj = 0
|
||
|
for j, line in enumerate(text):
|
||
|
for i, ch in enumerate(line):
|
||
|
if ch.strip() or current_output:
|
||
|
if not current_output:
|
||
|
current_output = ch
|
||
|
si = i
|
||
|
sj = j
|
||
|
elif ch == ">" and current_output[-1] != ">":
|
||
|
output.append([(si, sj), current_output])
|
||
|
current_output = ">"
|
||
|
si = i
|
||
|
sj = j
|
||
|
elif ch == " " and current_output[-1] == " " and current_output[-2] == " ":
|
||
|
output.append([(si,sj), current_output])
|
||
|
current_output = ""
|
||
|
else:
|
||
|
current_output += ch
|
||
|
if current_output:
|
||
|
output.append([(si, sj), current_output.replace("_","..")])
|
||
|
current_output = ""
|
||
|
|
||
|
return output
|
||
|
|
||
|
|
||
|
class TileTools:
|
||
|
@classmethod
|
||
|
def parse_tiles(cls, im, off_x, off_y, tilesize, partial_center=False):
|
||
|
cx = off_x
|
||
|
cy = off_y
|
||
|
res = OrderedDict()
|
||
|
rr = [[]]
|
||
|
while True:
|
||
|
if cx+tilesize < im.size[0]:
|
||
|
sim= im.crop((cx, cy, cx+tilesize,cy+tilesize))
|
||
|
|
||
|
s = image_to_string_format(sim, format_type="BMP")
|
||
|
if cy in [88, 104] and cx == 112:
|
||
|
#if cy == 104 or partial_center == False:
|
||
|
if partial_center == False:
|
||
|
s = None
|
||
|
rr[-1].append(s)
|
||
|
cx+=tilesize
|
||
|
|
||
|
elif cy+tilesize < im.size[1]-tilesize:
|
||
|
cx= off_x
|
||
|
cy+=tilesize
|
||
|
rr.append([])
|
||
|
else:
|
||
|
break
|
||
|
return rr
|
||
|
|
||
|
@classmethod
|
||
|
def get_tiles(cls, im, off_x, off_y, tilesize):
|
||
|
rr = cls.parse_tiles(im, off_x, off_y, tilesize)
|
||
|
res = OrderedDict()
|
||
|
for y, row in enumerate(rr):
|
||
|
for x, tile in enumerate(row):
|
||
|
if tile:
|
||
|
res[tile] = res.get(tile,0)+1
|
||
|
return res
|
||
|
|
||
|
|
||
|
@classmethod
|
||
|
def find_tileset_offset(cls, im, tilesize):
|
||
|
ress = list()
|
||
|
for x in range(tilesize):
|
||
|
for y in range(tilesize):
|
||
|
tiles = cls.get_tiles(im, x,y, tilesize)
|
||
|
ress.append([x,y,len(tiles), tiles])
|
||
|
ress.sort(key=lambda x: x[2])
|
||
|
return ress[0][0:2]
|
||
|
|
||
|
def to_image_key(img):
|
||
|
if isinstance(img, basestring):
|
||
|
img = load_image(img)
|
||
|
key = image_to_string_format(img, "BMP")
|
||
|
return key
|
||
|
|
||
|
|
||
|
|
||
|
class ScreenSelector:
|
||
|
shop_image = load_image("iVBORw0KGgoAAAANSUhEUgAAAKAAAAAYCAIAAADyNGFiAAAAhUlEQVR4nO3UMQ6AIAxGYTTqGekJ6Rl1cSAQNnCqbd43Mf7hBVICAAAAAAAAAHOb9QA3cs7WEz5Q1Xog8JJat5RiPWSJiKTWmMBzY916d3827lTV3XqPD17qpjayfzaH6RhP6sWdelsPmXjyJSI9MC84OAIHR+DgCBwcgYMjcHAEDo7Awb3rRh8l+sp+JAAAAABJRU5ErkJggg==")
|
||
|
|
||
|
battle_image = to_image_key("iVBORw0KGgoAAAANSUhEUgAAAQAAAAAICAIAAACZNLboAAAAgklEQVR4nO3UMRKAIAwEQHR8ZPJCeKZFGiQClUxObkuhOG4SUyIiIiLazjG9ISILcpAppTRfsPr3+YObLIC1n3NeEmZ3qpqeM4TVv88f32gB6vbtbfSdumebIaz+fX4I5/gYpf0fsJKbnz1Q/6/547umN+B2GpSIqKofIJT+e/mDuwF7dj4gb9hPPAAAAABJRU5ErkJggg==")
|
||
|
|
||
|
char_select = to_image_key("iVBORw0KGgoAAAANSUhEUgAAAQAAAAAgCAIAAAByyzGzAAAAjklEQVR4nO3W0QlCMRAEwCiWpL3kKkx60aL8CMorIK7wmGlguT0upDUAAAAAAAAAAAAAAAAAAAAAAAAAgL+5xJJ677GsvDlnOFGfW4QOYG1rjJGJC6uqlr0Bfe6SOIDjttZsZ3KcK7MzfW50/XXActZttc9Q4cdYn7vcMjHte9PPeywxoz9eVZX/jehzizf4UD4gJtsg3gAAAABJRU5ErkJggg==")
|
||
|
|
||
|
empty_orb = to_image_key("iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAdUlEQVR4nJVSwRGAMAijPTdxBd1FdnKPuIsO5cM7jIjU5lcuITnSIuMqPRjeo2U++Lnt06fAqADuqSrLikVyi1mppKl54ovKhjVZzxrjNBxctg6BIThrkuqvAwAfybXj2MxpR6I8zx4SEwmbNuR/KRDk6O7hBC14K/+LWlBvAAAAAElFTkSuQmCC")
|
||
|
|
||
|
item_sub_menu = to_image_key("iVBORw0KGgoAAAANSUhEUgAAAQAAAABcCAIAAAAOK/wJAAAAuklEQVR4nO3WsQ0CMQwF0IAYCXaJJ0x2gaEorrkqvuKIdOS92rJc/K+kFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABggls6UWudcAf8Qu99PJAUYEt/a+20i2CWiChZB0YF2Kd/2wVXsc/toAP341vgQrbQpp+Xx8FF/f085SyYo74+EZEWIHkB4L8pAEtTAJamACztC+hvHx3TeOZ7AAAAAElFTkSuQmCC")
|
||
|
|
||
|
formation_menu = to_image_key("iVBORw0KGgoAAAANSUhEUgAAAQAAAAAwCAIAAABxHTMoAAAAqElEQVR4nO3VwQ0CIRRFUTSWpL1AhdCLFuUCF7OcmEl+4J9TwQvDHUoBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALjcLXpAmFpr9ISFjTGiJ1wjaQDz9vfeo4csqbVWdmkgYwDH2z+/Jecdz22DBu7RA2K4/X+bh7bN4/mIHhDm9w97P6OHLKa+Pq21bQJI+gLAJABSEwCpCYDUBEBqAiA1AZCaAEjtC0NpHyXvFRJOAAAAAElFTkSuQmCC")
|
||
|
|
||
|
empty_battle_char = to_image_key("iVBORw0KGgoAAAANSUhEUgAAABAAAAAYCAIAAAB8wupbAAAAEklEQVR4nGNgGAWjYBSMgsEFAASYAAHgYt7ZAAAAAElFTkSuQmCC")
|
||
|
empty_battle_char = to_image_key("iVBORw0KGgoAAAANSUhEUgAAAAgAAAAYCAIAAABIuytHAAAAD0lEQVR4nGNgGAWjgPoAAAJYAAGgxYwDAAAAAElFTkSuQmCC")
|
||
|
|
||
|
|
||
|
|
||
|
battle_enemies_dict = dict()
|
||
|
font_dict = dict()
|
||
|
luds = dict()
|
||
|
|
||
|
@classmethod
|
||
|
def _load_content(cls, fonts, tilesets, spritesets, filename_lud, enemy_filename):
|
||
|
if enemy_filename:
|
||
|
cls.battle_enemies_dict = json.loads(open(enemy_filename).read())
|
||
|
else:
|
||
|
for filename in os.listdir("./"):
|
||
|
if filename.startswith("enemy_") and filename.count("_") > 1:
|
||
|
n = filename.partition("enemy_")[2].partition(".png")[0].partition("_")[0]
|
||
|
key = to_image_key(Image.open(filename))
|
||
|
cls.battle_enemies_dict[key] = cls._parse_enemy_name(n)
|
||
|
ff = open("./enemy_lookup.dat", "w")
|
||
|
ff.write(json.dumps(cls.battle_enemies_dict))
|
||
|
ff.close()
|
||
|
|
||
|
cls.luds = json.loads(open(filename_lud).read())
|
||
|
|
||
|
#images have different bmp headers sometimes, so reformat them here.
|
||
|
new_dict = dict()
|
||
|
for key, val in cls.luds['plud']['person_dict'].items():
|
||
|
new_dict[image_to_string_format(load_image(key),"BMP")] = val
|
||
|
cls.luds['plud']['person_dict'] = new_dict
|
||
|
new_dict = dict()
|
||
|
for key, val in cls.luds['lud'].items():
|
||
|
new_dict[image_to_string_format(load_image(key), "BMP")] = val
|
||
|
cls.luds['lud'] = new_dict
|
||
|
|
||
|
image_list = [Image.open("text"+str(i)+".png") for i in range(7)]
|
||
|
cls.font_dict = ParseScreenText.get_font(image_list)
|
||
|
|
||
|
cls._load_worldmap()
|
||
|
|
||
|
@classmethod
|
||
|
def _parse_enemy_name(cls, n):
|
||
|
n = n.lower()
|
||
|
if n == "blue d":
|
||
|
return "blue dragon"
|
||
|
elif n == "frost d":
|
||
|
return "frost dragon"
|
||
|
elif n[:2] == "fr" and len(n)>4:
|
||
|
return "frost "+n[2:]
|
||
|
elif n == "gas d":
|
||
|
return "gas dragon"
|
||
|
elif n == "grey w":
|
||
|
return "grey worm"
|
||
|
elif n[:2] == "gr" and len(n)>4:
|
||
|
return "greater "+n[2:]
|
||
|
elif n == "irongol":
|
||
|
return "iron golem"
|
||
|
elif n == "manticor":
|
||
|
return "manticore"
|
||
|
elif n == "mudgol":
|
||
|
return "mud golem"
|
||
|
elif n == "r.goyle":
|
||
|
return "red gargoyle"
|
||
|
elif n == "red d":
|
||
|
return "red dragon"
|
||
|
elif n[:2] == "r." and len(n)>4:
|
||
|
return "red "+n[2:]
|
||
|
elif n == "rockgol":
|
||
|
return "rock golem"
|
||
|
elif n == "saber t":
|
||
|
return "saber tooth"
|
||
|
elif n == "sand w":
|
||
|
return "sand worm"
|
||
|
elif n == "tyro":
|
||
|
return "t rex"
|
||
|
elif n == "wzvamp":
|
||
|
return "vampire wizard"
|
||
|
elif n[:2] == "wz" and len(n)>4:
|
||
|
return n[2:]+" wizard"
|
||
|
elif n == "zombied":
|
||
|
return "zombie dragon"
|
||
|
elif n == "zombull":
|
||
|
return "zombie bull"
|
||
|
else:
|
||
|
return n
|
||
|
|
||
|
@classmethod
|
||
|
def parse_whole_screen(cls, image):
|
||
|
#image_list = [Image.open("text"+str(i)+".png") for i in range(7)]
|
||
|
#f = ParseScreenText.get_font(image_list)
|
||
|
map_data = dict()
|
||
|
text = ParseScreenText.parse_screen(image, cls.font_dict)
|
||
|
if text:
|
||
|
if cls.is_shop(image):
|
||
|
return 'shop', cls.shop_parse(image, text), map_data
|
||
|
elif cls.is_battle(image):
|
||
|
return 'battle', cls.battle_parse(image, text), map_data
|
||
|
elif cls.is_menu(image, text):
|
||
|
return 'menu', cls.menu_parse(image, text), map_data
|
||
|
else:
|
||
|
return 'text', cls.text_box(image, text), map_data
|
||
|
else:
|
||
|
if cls.is_world_map(image):
|
||
|
return 'world', cls.world_map_parse(image), map_data
|
||
|
else:
|
||
|
k, map_data=ParseScreenObstructions.parse_screen(image,
|
||
|
cls.luds['tile_info'],
|
||
|
cls.luds['lud'],
|
||
|
cls.luds['plud'],
|
||
|
partial_center=True)
|
||
|
return 'map', k, map_data
|
||
|
|
||
|
world_map_title = to_image_key('iVBORw0KGgoAAAANSUhEUgAAAIAAAAAgCAIAAABVQOdyAAAD80lEQVR4nO1avXHzMAxFfGlTaRAtoMqdh/B5sK/SaQh3rryABnHl3vcVjJFn/JGiLKbJuxQ5EgRIgCLAR39Q94+2x/F2jgWm7mCKpXatB9vFKLNL6MnOypTfAp8NbKR1jvOAjaf++tLYn9Oax3k49VduH+m+238Zep7y3MgKp71hlxvjWf3gqX9r7LY24Hl/nAds1I5IDvX0jPPA+zc1JoU8KuNfyyhajAe+EZsHgJ7bE/+ClWf1EHw9ycs8/NRfcdvqeAjglHRX4epWokUACI5UdD17c+oOJQsOZFKXODRejjK1o6fuYB4yKR7NckCLAOz2X8GBkJaaXbB2rqeQIXr1R2DOygvMRtg8AObeZ5z66+NyF42BW3VXOvo95fiPGY9mZ72HRkeQiazjYqB/9ZAUeDOT4wTKZ7sRfjMApuPeC+HibK3VHu0CYC51nAcu88uViGPH3Mi42VEA23/d+9S4Clq5YE4nQfmISH4XkhyMxsnWQ7ubcMKaGHi1vMgl2tzUHY63M1elScAsq4jocbnjJLcO0sfWXJAoNtgLvEhB3eg7mqAcRC82evWu2R4XxyhWvNYaNLoJi/+TW8UhEHhf68Fe8VWZQRKS+kTSaFAjUJsjyKsRs5LeKaF7v7useJhKMJ14026TITY/gv4QY9UXUMjyC2FvZ5Vz/d4DgGei3LQ3eXJSd1ZzFvUB0Ec2vfJfRAZrTxY1LwRirt/InL2836KJZaYRvfT4OA/4TmDOeSkqj6Ai7xORVWzoukK7ICVYYcVs1MDUnTXtrQXnL8S8Z4O6eqmmCkpTERR/zPJnqfmlXD+pG5YnljUttPE0dvsv4VOsesX7T3W9VF+GYhHpsfy8gJiap3ABom7hxwN+wiQoGfU5kDXtdR1v5zjJveW+tuoekE3CjJiaX8r16wecYP2xaUEZ8aWa/8cwaGqPWx6Xu+bVS1CZhHlre9tZZEL2KTMHOh+aXL9WblYjAbKmMcnr4Yku9HIewSdI9H0RWYSaLyBevGb5Kz7PmOvHF/kYhb9G0XNe+lBcTe29n4rwbvBihXUfrKdtkXDJTwLilwM8psqnYWJtAEpY/hJqnuCLznL95nBuxPZFpk14uf1dWBWA8mnF1Dy9kjMlXD8Oj8m47KuAKWOStdrWerZu1U2YXqtsTyYhoOY9aK4f21EtFiqn/krdYZFp062sitv59hPMeSkqA4A3zBF+TPizfdSV1SQDcBRrS10l6zRjMz29L86xrGlTlbZoJ+f294BClh8RUPOFXL8ebo4yFRaa1qoEOEvx17kmQ9RzQbrRYwq1AHZNr8cFSgqx2Lqnf6lpcy2kaKWE9Sn67z1gAbK/nq/Afw+oxUTPNFf0AAAAAElFTkSuQmCC')
|
||
|
|
||
|
@classmethod
|
||
|
def is_world_map(cls, image):
|
||
|
if to_image_key(image.crop((64,16,192,48))) == cls.world_map_title:
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
@classmethod
|
||
|
def _load_worldmap(cls):
|
||
|
cls.world_mask = load_image("iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAIAAABMXPacAAAAxklEQVR4nO3cMQ6DMAwFUNT739kduiCVoQ0h/IT3dkSIDRgD2TYAAAAAgOlU1b+bvBIGsYbHHjgAAAxXVQpwZnOYsxI5gjAAXahPftG/Hd3sO1oh8QsZBsDTuRwDAAAAAABxfJkAAACw5xEJOEmzBQAAAADW16UJGLRayly0YLmS/GJ1I3Pc+XRg2KvEz17E4DamHgA4L3ZxWwC4ilsdrZpzR9KRR1YCACxPyQcAQDqr5tzM7M+ag/4RAwCAnRmLegAAAPK9Aa6QfYsCj718AAAAAElFTkSuQmCC").convert("RGB")
|
||
|
cls.locals = list()
|
||
|
|
||
|
for i in range(cls.world_mask.width):
|
||
|
for j in range(cls.world_mask.height):
|
||
|
if cls.world_mask.getpixel((i,j)) == (255,255,255):
|
||
|
cls.locals.append((i,j))
|
||
|
|
||
|
new_output = list()
|
||
|
for x1,y1 in cls.locals:
|
||
|
for tup in new_output:
|
||
|
for x,y in tup:
|
||
|
if abs(x1-x)+abs(y-y1) < 3:
|
||
|
tup.append((x1,y1))
|
||
|
break
|
||
|
else:
|
||
|
continue
|
||
|
break
|
||
|
else:
|
||
|
new_output.append([(x1,y1)])
|
||
|
new_output2 = list()
|
||
|
for tup in new_output:
|
||
|
cx = 0
|
||
|
cy = 0
|
||
|
cc = 0
|
||
|
for x,y in tup:
|
||
|
cx+=x
|
||
|
cy+=y
|
||
|
cc+=1
|
||
|
cx = int(cx/float(cc))
|
||
|
cy = int(cy/float(cc))
|
||
|
new_output2.append([cx,cy,cc])
|
||
|
landmark_types = ["Gaint's cave", "Sage's cave", "Gaint's cave", "Waterfall", "Onrac", "Earth cave", "Cardia", "Melmond", "Cardia", "Cardia", "Cardia", "Dwarf cave", "Northwest castle", "Marsh cave", "Cardia", "Cardia", "Castle of Ordeal", "Temple of Fiends", "Elfhland","Corneria", "Matoya's cave", "Guru volcano", "Mirage Tower", "Ice cave", "Pravoka", "Crescent lake", "Gaia", "Lefein"
|
||
|
]
|
||
|
for i, tup in enumerate(new_output2):
|
||
|
tup.append(landmark_types[i])
|
||
|
tup.extend([[110, 118, "Desert"], [108, 25, "Landing spot"], [20,39,"Landing spot"], [60,18,"Landing spot"]])
|
||
|
cls.world_landmarks = new_output2
|
||
|
|
||
|
|
||
|
@classmethod
|
||
|
def world_map_parse(cls, image):
|
||
|
cropped = image.crop((64, 48, 192, 176)).convert("P", palette=Image.ADAPTIVE)
|
||
|
p = cropped.getpalette()
|
||
|
new_palette = list()
|
||
|
default_color = (0,0,0)
|
||
|
threshold = 32
|
||
|
for i in range(256):
|
||
|
r = p[3*i]
|
||
|
g = p[3*i+1]
|
||
|
b = p[3*i+2]
|
||
|
for cc in [(0,19,155), (0, 120,82),
|
||
|
(17, 209, 164), (233,211,134)]:
|
||
|
val = (cc[0]-r)**2+(cc[1]-g)**2+(cc[2]-b)**2
|
||
|
if val <= threshold**2:
|
||
|
new_palette.extend(default_color)
|
||
|
break
|
||
|
else:
|
||
|
new_palette.extend((255,255,255))
|
||
|
cropped.putpalette(new_palette)
|
||
|
cropped = cropped.convert("RGB")
|
||
|
outputi = ImageChops.difference(cropped.convert("RGB"), cls.world_mask.convert("RGB"))
|
||
|
for c in outputi.convert("RGB").getcolors():
|
||
|
if c[1] == (255,255,255):
|
||
|
if c[0] > 0:
|
||
|
break
|
||
|
else:
|
||
|
return []
|
||
|
cx = 0
|
||
|
cy = 0
|
||
|
n = 0
|
||
|
for i in range(outputi.width):
|
||
|
for j in range(outputi.height):
|
||
|
if outputi.getpixel((i,j)) == (255,255,255):
|
||
|
cx+=i
|
||
|
cy+=j
|
||
|
n+=1
|
||
|
cx = int(cx/float(n))
|
||
|
cy = int(cy/float(n))
|
||
|
output = list()
|
||
|
output.append("location: "+str(cx*2)+", "+str((outputi.height-cy)*2)+", ")
|
||
|
for entry in cls.world_landmarks:
|
||
|
if abs(entry[0]-cx)+abs(entry[1]-cy) < 32:
|
||
|
zx = entry[0]-cx
|
||
|
zy = cy-entry[1]
|
||
|
zc = entry[2]
|
||
|
z_name = entry[3]
|
||
|
|
||
|
#if zc > 1:
|
||
|
# typ = "major"
|
||
|
#else:
|
||
|
# typ = "minor"
|
||
|
typ = z_name
|
||
|
string = typ+", "+str(zx*2)+", "+str(zy*2)+","
|
||
|
output.append(string)
|
||
|
print(output)
|
||
|
return output
|
||
|
|
||
|
@classmethod
|
||
|
def is_battle(cls, image):
|
||
|
#check for battle backgrounds
|
||
|
color1 = image.getpixel((0,0))
|
||
|
crop = image.crop((0,0,256, 8))
|
||
|
crop = replace_color(crop, color1, (0,0,0))
|
||
|
key = to_image_key(crop)
|
||
|
|
||
|
if key == cls.battle_image:
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
@classmethod
|
||
|
def battle_parse(cls, image, text):
|
||
|
textbox = list()
|
||
|
player_names = ["" for x in range(4)]
|
||
|
player_hps = ["" for x in range(4)]
|
||
|
for tup, string in text:
|
||
|
x,y = tup
|
||
|
if x >= 26 and y< 26:
|
||
|
textbox.append(string)
|
||
|
if y == 4:
|
||
|
player_names[0] = string.strip()
|
||
|
elif y == 7:
|
||
|
player_hps[0] = string.strip()
|
||
|
elif y == 10:
|
||
|
player_names[1] = string.strip()
|
||
|
elif y == 13:
|
||
|
player_hps[1] = string.strip()
|
||
|
elif y == 16:
|
||
|
player_names[2] = string.strip()
|
||
|
elif y == 19:
|
||
|
player_hps[2] = string.strip()
|
||
|
elif y == 22:
|
||
|
player_names[3] = string.strip()
|
||
|
elif y == 25:
|
||
|
player_hps[3] = string.strip()
|
||
|
textbox = " ".join(textbox)
|
||
|
enemy_names = list()
|
||
|
for tup, string in text:
|
||
|
x,y = tup
|
||
|
if x == 3 and y >= 19:
|
||
|
enemy_names.append(string.strip())
|
||
|
enemies = list()
|
||
|
|
||
|
coords = [(16, 40, 32, 32)]
|
||
|
enemy_count = OrderedDict()
|
||
|
boxes_to_check = list()
|
||
|
for i in range(3):
|
||
|
for j in range(3):
|
||
|
x = 16+32*i
|
||
|
y = 40+32*j
|
||
|
w = 32
|
||
|
h = 32
|
||
|
boxes_to_check.append(((x,y,w, h), (i,j), i*3+j+1))
|
||
|
|
||
|
#check for big enemy plus 3 small
|
||
|
for i in range(3):
|
||
|
for j in range(3):
|
||
|
x = 32+32*i
|
||
|
y = 40+32*j
|
||
|
w = 32
|
||
|
h = 32
|
||
|
boxes_to_check.append(((x,y,w,h), (i,j), j+1))
|
||
|
|
||
|
#check for garland box
|
||
|
#boxes_to_check.append(((64, 72, 32, 32), (1,1), 1))
|
||
|
#check for big enemies v1
|
||
|
for i in range(2):
|
||
|
for j in range(2):
|
||
|
x = 16+64*i
|
||
|
y = 40+48*j
|
||
|
w = 48
|
||
|
h = 48
|
||
|
boxes_to_check.append(((x,y,w,h), (i*2,j), i*2+j+1))
|
||
|
|
||
|
#check for big enemies v2
|
||
|
for i in range(1):
|
||
|
for j in range(2):
|
||
|
x = 16+48*1
|
||
|
y = 40+48*j
|
||
|
w = 48
|
||
|
h = 48
|
||
|
boxes_to_check.append(((x,y,w,h), (i,j), i*2+j+1))
|
||
|
|
||
|
#boss box check
|
||
|
boxes_to_check.append(((16+24, 40+24, 48, 48), (1,1), 1))
|
||
|
#chaos box check
|
||
|
boxes_to_check.append(((16, 40, 96, 96), (1,1), 1))
|
||
|
|
||
|
for box, coord, num in boxes_to_check:
|
||
|
x,y,w,h = box
|
||
|
subi = image.crop((x,y,x+w,y+h))
|
||
|
|
||
|
res = cls.battle_enemies_dict.get(to_image_key(subi))
|
||
|
if res:
|
||
|
i,j = coord
|
||
|
enemies.append((i,j, res, num))
|
||
|
enemy_count[res] = enemy_count.get(res,0)+1
|
||
|
|
||
|
enemy_string = ""
|
||
|
for ekey in enemy_count:
|
||
|
enemy_string = enemy_string+" "+str(enemy_count[ekey])+" "+ekey
|
||
|
enemy_string = enemy_string.strip()
|
||
|
|
||
|
|
||
|
status = []
|
||
|
attacker = ""
|
||
|
defender = ""
|
||
|
attack_type = ""
|
||
|
exp_string = ""
|
||
|
status_text = ""
|
||
|
for tup, string in text:
|
||
|
x,y = tup
|
||
|
if (2,20) == tup:
|
||
|
attacker = cls._parse_enemy_name(string.strip())
|
||
|
elif (2,23) == tup:
|
||
|
defender = cls._parse_enemy_name(string.strip())
|
||
|
elif (2,26) == tup:
|
||
|
status_text = string.strip()
|
||
|
elif (12,23) == tup:
|
||
|
attack_type = string.strip()
|
||
|
elif (12,20) == tup:
|
||
|
exp_string = string.strip()
|
||
|
|
||
|
if "DMG" in attack_type:
|
||
|
attack_type = attack_type.partition("DMG")[0]+" Damage"
|
||
|
|
||
|
if attacker and defender:
|
||
|
if attacker.lower().strip() == "exp up" and\
|
||
|
defender.lower().strip() == "gold":
|
||
|
status = ["Exp Up: "+exp_string]
|
||
|
if attack_type:
|
||
|
status.append("Gold gained: "+attack_type)
|
||
|
elif attacker.lower().startswith("lev. up!") and\
|
||
|
defender.lower().strip() == "hp max":
|
||
|
if attack_type.strip():
|
||
|
status = ["Level up! "+attacker[8:]+" ", "HP Max: "+attack_type.partition("pts.")[0]+" points."]
|
||
|
else:
|
||
|
status = ["Level up! "+attacker[8:]+" "]
|
||
|
else:
|
||
|
if exp_string.strip() and not "hits" in exp_string.lower():
|
||
|
status = [attacker+" uses "+exp_string+" on "+defender]
|
||
|
if attack_type:
|
||
|
if "DMG" in attack_type:
|
||
|
status.append(attack_type.partition("DMG")[0]+" Damage")
|
||
|
else:
|
||
|
status.append(attack_type)
|
||
|
else:
|
||
|
status = [attacker+" attacks "+defender]
|
||
|
if attack_type:
|
||
|
status.append(attack_type)
|
||
|
|
||
|
elif attacker and exp_string and attacker.strip() in player_names:
|
||
|
status = [attacker+" uses "+exp_string]
|
||
|
|
||
|
if status_text:
|
||
|
lookup = {
|
||
|
"str. up": "Strength up.",
|
||
|
"agi. up": "Agility up.",
|
||
|
"vit. up": "Vitality up.",
|
||
|
"int. up": "Intelligence up."
|
||
|
}
|
||
|
status.append(lookup.get(status_text.lower(), status_text))
|
||
|
|
||
|
menu = ""
|
||
|
#print(text)
|
||
|
|
||
|
magic = False
|
||
|
for tup, string in text:
|
||
|
x,y = tup
|
||
|
if 2 <= x <= 21 and 19 <= y <= 25:
|
||
|
if ">" in string:
|
||
|
menu = string.partition(">")[2].strip().split(" ")[0]
|
||
|
for tup2, string2 in text:
|
||
|
x2,y2 = tup2
|
||
|
if y2 == y and x2 == 21 and menu:
|
||
|
menu += " left "+string2
|
||
|
elif y2 == y and x2 <= 21 and menu and (string2.strip().split(" ")[-1].isdigit() or string2.strip().split(" ")[-1] == "O"):
|
||
|
menu += " left "+string2.strip().split(" ")[-1]
|
||
|
elif 0 <= x <= 8 and 5 <= y <= 13:
|
||
|
i = int(x/4)
|
||
|
j = int((y-5)/4)
|
||
|
c = (3*i+j)+1
|
||
|
for tup_x, tup_y, enemy, num in enemies:
|
||
|
if (tup_x, tup_y) == (i,j):
|
||
|
menu = enemy+" "+str(num)
|
||
|
enemy_string = ""
|
||
|
break
|
||
|
elif 15 <= x <= 20 and 6 <= y <= 18:
|
||
|
if ">" in string:
|
||
|
if y == 6:
|
||
|
menu = player_names[0]+" hp "+player_hps[0]
|
||
|
elif y == 9:
|
||
|
menu = player_names[1]+" hp "+player_hps[1]
|
||
|
elif y == 12:
|
||
|
menu = player_names[2]+" hp "+player_hps[2]
|
||
|
elif y == 15:
|
||
|
menu = player_names[3]+" hp "+player_hps[3]
|
||
|
|
||
|
curr_selected = -1
|
||
|
for i in range(4):
|
||
|
ii = image.crop((160, 41+i*24, 168, 41+(i+1)*24))
|
||
|
if image_to_string_format(ii, "BMP") != cls.empty_battle_char:
|
||
|
curr_selected = i
|
||
|
|
||
|
character = ""
|
||
|
if curr_selected >=0 and menu.replace(">","").strip() in ["Fight", "Magic", "Drink", "ITEM", "RUN"]:
|
||
|
character = player_names[curr_selected]
|
||
|
|
||
|
#print(enemy_names, ":::")
|
||
|
if not menu.strip() or not " ".join(enemy_names).strip() or ">" in " ".join(enemy_names):
|
||
|
enemy_string = ""
|
||
|
if status:
|
||
|
enemy_string = ""
|
||
|
res = {"textbox": textbox, "enemies": enemies,
|
||
|
"status": status, "enemy_string": enemy_string,
|
||
|
"menu": menu, "enemy_names": enemy_names,
|
||
|
"character": character}
|
||
|
#print(res)
|
||
|
return res
|
||
|
|
||
|
@classmethod
|
||
|
def is_menu(cls, image, text):
|
||
|
raw_text = " ".join([x[1] for x in text])
|
||
|
|
||
|
#test main menu
|
||
|
if not raw_text:
|
||
|
return False
|
||
|
elif "CONTINUE" in raw_text and "NEW GAME" in raw_text\
|
||
|
and "RESPOND RATE" in raw_text:
|
||
|
return "main_menu"
|
||
|
elif cls.char_select == image_to_string_format(image.crop((0,0,image.width, 32)), "BMP"):
|
||
|
return "char_select"
|
||
|
elif ("A B C D E F G H I J" in raw_text \
|
||
|
or "K L M N O P Q R S T" in raw_text)\
|
||
|
and "SELECT NAME" in raw_text:
|
||
|
return "name_select"
|
||
|
elif "ARMOR" in raw_text and "Weapon" in raw_text and\
|
||
|
"Status" in raw_text:
|
||
|
return "player_menu"
|
||
|
elif "ITEM" in raw_text and text[0][0] == (2,2):
|
||
|
return "item_menu"
|
||
|
elif cls.item_sub_menu == image_to_string_format(image.crop((0,0,image.width, 92)), "BMP"):
|
||
|
return "item_sub_menu"
|
||
|
elif "L1" in raw_text and "L2" in raw_text and\
|
||
|
"L3" in raw_text and "L4" in raw_text and "L5" in raw_text and\
|
||
|
"L6" in raw_text and "L7" in raw_text and "L8" in raw_text and\
|
||
|
raw_text.count("/") > 7:
|
||
|
return "magic_menu"
|
||
|
elif text and text[0][0] == (2,2) and text[0][1].strip() == "Weapon":
|
||
|
return "weapon_menu"
|
||
|
elif text and text[0][0] == (2,2) and text[0][1].strip() == "ARMOR":
|
||
|
return "armor_menu"
|
||
|
elif "EXP.POINTS" in raw_text and "FOR LEV UP" in raw_text:
|
||
|
return "status_menu"
|
||
|
elif cls.formation_menu == image_to_string_format(image.crop((0,0,image.width, 48)), "BMP"):
|
||
|
return "formation_menu"
|
||
|
else:
|
||
|
pass
|
||
|
#import pdb
|
||
|
#pdb.set_trace()
|
||
|
return False
|
||
|
|
||
|
@classmethod
|
||
|
def menu_parse(cls, image, text):
|
||
|
menu_type = cls.is_menu(image, text)
|
||
|
output = list()
|
||
|
if menu_type == "main_menu":
|
||
|
for i, (pos, entry) in enumerate(text):
|
||
|
if ">" in entry:
|
||
|
output.append(text[i+1][1])
|
||
|
if entry.strip() not in ['CONTINUE', 'NEW GAME']:
|
||
|
output.append(entry)
|
||
|
elif menu_type == "char_select":
|
||
|
output = list()
|
||
|
cursor = 0
|
||
|
trans_dict = {"Bl.BELT": "black belt",
|
||
|
"RedMAGE": "red mage",
|
||
|
"Wh.MAGE": "white mage",
|
||
|
"Bl.MAGE": "black mage"}
|
||
|
|
||
|
for pos, entry in text:
|
||
|
if ">>" in entry:
|
||
|
if pos == (6,7):
|
||
|
cursor = 1
|
||
|
elif pos == (20, 7):
|
||
|
cursor = 2
|
||
|
elif pos == (6,19):
|
||
|
cursor = 3
|
||
|
elif pos == (20, 19):
|
||
|
cursor = 4
|
||
|
if cursor > 0:
|
||
|
cc = 0
|
||
|
char_type = 0
|
||
|
for pos, entry in text:
|
||
|
if entry.strip() in ["FIGHTER", "THIEF", "Bl.BELT",
|
||
|
"RedMAGE", "Wh.MAGE", "Bl.MAGE"]:
|
||
|
cc+=1
|
||
|
if cursor == cc:
|
||
|
char_type = trans_dict.get(entry.strip(), entry)
|
||
|
char_type = char_type.strip().lower()
|
||
|
output.append("Character "+str(cursor))
|
||
|
output.append(char_type)
|
||
|
else:
|
||
|
chars = list()
|
||
|
pos_names = list()
|
||
|
for pos, entry in text:
|
||
|
if entry.strip() in ["FIGHTER", "THIEF", "Bl.BELT",
|
||
|
"RedMAGE", "Wh.MAGE", "Bl.MAGE"]:
|
||
|
char_type = trans_dict.get(entry.strip(), entry)
|
||
|
char_type = char_type.strip().lower()
|
||
|
chars.append(char_type)
|
||
|
else:
|
||
|
the_name = entry.strip()
|
||
|
if pos[1] == 11 and pos[0] < 20:
|
||
|
pos_names.append([the_name, 1])
|
||
|
elif pos[1] == 11 and pos[0] > 20:
|
||
|
pos_names.append([the_name, 2])
|
||
|
elif pos[0] < 20:
|
||
|
pos_names.append([the_name, 3])
|
||
|
else:
|
||
|
pos_names.append([the_name, 4])
|
||
|
for i in range(4):
|
||
|
for _, c in pos_names:
|
||
|
if i+1 == c:
|
||
|
break
|
||
|
else:
|
||
|
pos_names.append(["blank", i+1])
|
||
|
pos_names.sort(key=lambda x: x[1])
|
||
|
names = [x[0] for x in pos_names]
|
||
|
|
||
|
for i in range(len(names)):
|
||
|
output.append(chars[i]+" "+names[i])
|
||
|
elif menu_type == "name_select":
|
||
|
name = ""
|
||
|
current_char = ""
|
||
|
lookup = {"'": "apostrophe", ",": "comma", ".": "period",
|
||
|
"": "space", "-": "dash", "..": "dot dot",
|
||
|
"!": "exclamation mark", "?": "question mark"}
|
||
|
for pos, entry in text:
|
||
|
if pos[1] == 3:
|
||
|
name = entry[:-2]
|
||
|
if ">" in entry:
|
||
|
char = entry.split(">")[-1].split(" ")[0]
|
||
|
if char == "O":
|
||
|
if pos[1] == 15:
|
||
|
char = "0"
|
||
|
if char.isupper():
|
||
|
char = "uppercase "+char.lower()
|
||
|
elif char.islower():
|
||
|
char = "lowercase "+char.lower()
|
||
|
elif char.isdigit():
|
||
|
pass
|
||
|
else:
|
||
|
char = lookup.get(char, char)
|
||
|
current_char = char
|
||
|
output.append("Input character name")
|
||
|
output.append(name)
|
||
|
output.append("selected character: ")
|
||
|
output.append(current_char)
|
||
|
elif menu_type == "player_menu":
|
||
|
orbs = 0
|
||
|
for x in range(2):
|
||
|
for y in range(2):
|
||
|
orb=image.crop((32+x*16,24+y*16, 32+16*(x+1), 24+(y+1)*16))
|
||
|
orb_bmp = image_to_string_format(orb, "BMP")
|
||
|
if orb_bmp != cls.empty_orb:
|
||
|
orbs+=1
|
||
|
orbs = str(orbs)+" orbs"
|
||
|
gold = ""
|
||
|
menu = ""
|
||
|
curr = -1
|
||
|
names = ["" for x in range(4)]
|
||
|
for pos,string in text:
|
||
|
if pos[1] == 11 and pos[0] < 8:
|
||
|
gold = string.replace("G", "Gold")
|
||
|
if ">" in string and string.replace(">","").strip():
|
||
|
menu = string.replace(">", "")
|
||
|
elif ">" in string:
|
||
|
if pos == (10, 1):
|
||
|
curr = 0
|
||
|
elif pos == (19, 1):
|
||
|
curr = 1
|
||
|
elif pos == (10,15):
|
||
|
curr = 2
|
||
|
elif pos == (19,15):
|
||
|
curr = 3
|
||
|
elif pos[1] == 2:
|
||
|
if 12 <= pos[0] <= 16:
|
||
|
names[0] = string.strip()
|
||
|
elif 22<= pos[0] <= 26:
|
||
|
names[1] = string.strip()
|
||
|
elif pos[1] == 16:
|
||
|
if 12 <= pos[0] <= 16:
|
||
|
names[2] = string.strip()
|
||
|
elif 22<=pos[0]<=26:
|
||
|
names[3] = string.strip()
|
||
|
if not menu:
|
||
|
if curr>= 0:
|
||
|
menu = names[curr]
|
||
|
output.extend(["Player Menu", orbs, gold, menu])
|
||
|
elif menu_type == "item_menu":
|
||
|
menu = ""
|
||
|
for pos, string in text:
|
||
|
if ">>" in string:
|
||
|
menu = string.partition(">>")[2].split(" ")[:2]
|
||
|
menu = " ".join(menu).strip()
|
||
|
output.extend(['Item Menu', menu])
|
||
|
elif menu_type == "item_sub_menu":
|
||
|
des = ""
|
||
|
seek = None
|
||
|
names = list()
|
||
|
hp1 = list()
|
||
|
hp2 = list()
|
||
|
curr = -1
|
||
|
for pos, string in text:
|
||
|
if pos[1] == 12:
|
||
|
if ">" in string:
|
||
|
curr = len(names)
|
||
|
names.append(string.strip())
|
||
|
elif pos[1] == 15:
|
||
|
hp1.append(string.strip())
|
||
|
elif pos[1] == 16:
|
||
|
hp2.append(string.strip().replace("/", "of "))
|
||
|
|
||
|
if pos[1] >= 22:
|
||
|
des+=string+" "
|
||
|
if des:
|
||
|
output.append(des)
|
||
|
if curr>= 0:
|
||
|
output.append(names[curr]+" hp "+hp1[curr]+" "+hp2[curr])
|
||
|
else:
|
||
|
for i in range(4):
|
||
|
output.append(names[i]+" "+hp1[i])
|
||
|
elif menu_type == "magic_menu":
|
||
|
name = ""
|
||
|
curr = -1
|
||
|
levels = ["" for x in range(8)]
|
||
|
des = ""
|
||
|
for pos, string in text:
|
||
|
if pos[0] == 3:
|
||
|
if pos[1] == 2:
|
||
|
name = string.strip()
|
||
|
elif "/" in string and string[0] == "L":
|
||
|
num = (pos[1]-4)/2
|
||
|
levels[num] = string.partition(" ")[2].strip()
|
||
|
elif ">" in string:
|
||
|
curr = (pos[1]-4)/2
|
||
|
magic = string.replace(">","").strip()
|
||
|
elif pos[1] >= 23:
|
||
|
des+=string.strip()+" "
|
||
|
des = des.strip()
|
||
|
output.append(name)
|
||
|
if des:
|
||
|
output.append(des)
|
||
|
if curr >= 0:
|
||
|
output.append(magic+" "+levels[curr].replace("/", " of "))
|
||
|
else:
|
||
|
output.append("no spells available")
|
||
|
elif menu_type in ["weapon_menu", "armor_menu"]:
|
||
|
names = ["" for x in range(4)]
|
||
|
menu = ""
|
||
|
curr = -1
|
||
|
for pos,string in text:
|
||
|
if pos[0] <= 7 and pos[1] in [6,12,18,24]:
|
||
|
names[(pos[1]-6)/6] = string
|
||
|
elif pos[1] == 2 and pos[0] >= 9 and ">" in string:
|
||
|
menu = string.partition(">>")[2].split(" ")[0].strip()
|
||
|
elif ">" in string:
|
||
|
if 6 <= pos[1] < 12:
|
||
|
curr = 0
|
||
|
elif 12 <= pos[1] < 18:
|
||
|
curr = 1
|
||
|
elif 18 <= pos[1] < 24:
|
||
|
curr = 2
|
||
|
elif 24 <= pos[1]:
|
||
|
curr = 3
|
||
|
if string.replace(">", "")[:2] == "E-":
|
||
|
menu = "equiped "+string.replace(">", "")[2:].strip()
|
||
|
else:
|
||
|
menu = string.replace(">", "").strip()
|
||
|
output.append(menu_type.replace("_", " "))
|
||
|
if curr>=0:
|
||
|
output.append(names[curr])
|
||
|
if menu:
|
||
|
output.append(menu)
|
||
|
elif menu_type == "status_menu":
|
||
|
lud = {"STR.": "strength", "AGL.": "agility",
|
||
|
"INT.": "Intelligence", "VIT.": "vitality"}
|
||
|
lud2 = {"Wh.MAGE": "white mage", "Bl.MAGE": "black mage",
|
||
|
"Bl.BELT": "black belt", "RedMAGE": "red mage",
|
||
|
"FOR LEV UP": "for level up",
|
||
|
"EXP.POINTS": "experience points"}
|
||
|
for pos, string in text:
|
||
|
if pos[0] == 24 and pos[1] == 4:
|
||
|
output.append(string.strip().replace("LEV", "Level "))
|
||
|
elif pos[1]<12:
|
||
|
output.append(lud2.get(string.strip(), string.strip()))
|
||
|
elif pos[0] < 16:
|
||
|
output.append(lud.get(string.strip(), string.strip()))
|
||
|
for pos, string in text:
|
||
|
if pos[1] >= 12 and pos[0] >= 16:
|
||
|
if "HIT" in string:
|
||
|
output.append("Hit percent")
|
||
|
elif "EVADE" in string:
|
||
|
output.append("Evade percent")
|
||
|
else:
|
||
|
output.append(string.strip())
|
||
|
elif menu_type == "formation_menu":
|
||
|
names = ["" for x in range(4)]
|
||
|
curr = -1
|
||
|
for pos, string in text:
|
||
|
this_curr = -1
|
||
|
if pos[1] == 7:
|
||
|
this_curr = 0
|
||
|
if pos[1] == 11:
|
||
|
this_curr = 1
|
||
|
if pos[1] == 15:
|
||
|
this_curr = 2
|
||
|
if pos[1] == 19:
|
||
|
this_curr = 3
|
||
|
if this_curr >= 0:
|
||
|
names[this_curr] = string.replace(">","").strip()
|
||
|
if ">" in string:
|
||
|
curr = this_curr
|
||
|
output.append("formation menu")
|
||
|
if curr > -1:
|
||
|
output.append("position "+str(curr+1)+" "+names[curr])
|
||
|
|
||
|
return output
|
||
|
|
||
|
@classmethod
|
||
|
def is_shop(cls, image):
|
||
|
dd = ImageChops.difference(image, cls.shop_image).convert("RGB")
|
||
|
p = dd.resize((1,1), resample=Image.BILINEAR).getpixel((0,0))
|
||
|
|
||
|
if p[0] == 0 and p[1] == 0 and p[2] == 0:
|
||
|
return True
|
||
|
return False
|
||
|
|
||
|
@classmethod
|
||
|
def shop_parse(cls, image, text):
|
||
|
title = text[0][1].strip().title()
|
||
|
textbox = list()
|
||
|
for box, l in text:
|
||
|
if box[0] < 7 and box[1] < 18:
|
||
|
textbox.append(l.strip())
|
||
|
textbox = " ".join(textbox).replace(" ", " ")
|
||
|
if text[0][1].strip() in ["INN", "CLINIC"]:
|
||
|
if len(text) > 2 and text[2][1].strip() == "Gold":
|
||
|
textbox+=" Current "+text[-1][1].strip()
|
||
|
elif text[0][1].strip() in ['WEAPON', "ARMOR", "WMAGIC", "BMAGIC",
|
||
|
"ITEM"]:
|
||
|
if textbox.endswith("Gold OK?"):
|
||
|
textbox+=" Current "+text[-1][1].strip()
|
||
|
|
||
|
select_menu = ""
|
||
|
sx = 0
|
||
|
sy = 0
|
||
|
print(text)
|
||
|
for box, l in text:
|
||
|
if 20 < box[0] < 30 and 2 < box[1] < 24:
|
||
|
if ">" in l:
|
||
|
select_menu = l.replace(">", "").strip()
|
||
|
sx, sy = box[0], box[1]
|
||
|
elif select_menu != "" and sx==0 and sy == 0:
|
||
|
sx, sy = box
|
||
|
select_menu = (select_menu+" "+l).strip()
|
||
|
if (sx,sy) != (0,0):
|
||
|
for box, l in text:
|
||
|
if box[1] == sy+2 and sx< box[0] <= 29:
|
||
|
select_menu = select_menu + " "+l.strip()
|
||
|
|
||
|
menu = ""
|
||
|
for box, l in text:
|
||
|
if 4 < box[0] < 8 and 18 < box[1] < 26:
|
||
|
if ">" in l:
|
||
|
menu = l.replace(">", "").strip()
|
||
|
|
||
|
result = {"title": title, "text": textbox, "menu": select_menu+" "+menu}
|
||
|
print(result)
|
||
|
return result
|
||
|
bridge_scene = to_image_key('iVBORw0KGgoAAAANSUhEUgAAAFgAAAAgCAIAAAAZhijPAAADBUlEQVR4nM1ZO47CMBCdjVIgyoiU1BwoZ1hFkU+QE3CCCCHOkANRU7JyuaJCWzg4zviTGceEfaKA2LGfx+OZ8eOr+7kCGU27Px1v9P7J0bT7TD4AAPqCxXwWuZ6A0juTj87VP7tsFS3zudNkuoPZKurSMVnqpYaRg2nmWfQFnK9Nu88uWwB4fv9m8qEZ43F2B7QSZQX1bnccmkRdQl+MnSq5ZD3RyAFALUb91mtz9lYL0/uf1Q9z39SLwwgAUEmxw7uqmiYPjRGUazyLDXVj0iE3qZhbGnDL7ueq9lbAlK4ap+UxmFhhGIF0TtMig+CaQ29am+YYp5Jid4gitjYyYj9iNB3hOVw+jO7wIeTOp8/vX+Th2WWrwxsR3fku6tIZKRCadt8UAGhSwosJ4TYEdvt37hUjZ70TbkMATHw72gqzTiHqUvRbAIBKfjaJegyxynHVccEOEE27dgalBstodOc7gDt9dOe7z9yn4+1ZbNZMOssM0ReqptB0hwPvdCiPtyfPFyYfOvwxgoJKUnx4iBSu0oMIUZfd+W6GVTuvacTNEuMRJiH3XaOSoi7NbRkOCOD6YrhuVdK+d42nA11GXvP6PnH+FeMR6takMd41PM+Hny+/QBcN/VX0nvT0Whga34e4U/Y1jdWJb/sf1y8QAnwiYwRXv1Cg6w4RugaFEqqPTT4xhuDqF+OstJIpQtcgUZpaHPHJhTXN7Lng6hf2sGHdgatraKHIhE0ssExRl7meJlQCIDD1C9RhXndg6hpaKNKgrAXxyQBUOUC2woKrBxFcXcNtBSaGOiI6/frgC13sOpKpa3Ch+eTPYjNEnQVWIOoXcboDXdfgwuSTn443ruJig6Jf/BPdQQPxWXbXMBHULxbqDsmdwuaTyBDBY/+vdAcfn7frEZBIdwjoGhSYRaSTzxqGGKmQ80WEroGB6jcr+yA+6WJECijdwdfK0zUqKerXd8IGMP7XQBIDCyzdIULXMHnqC3SgBrH5kDyCVXe6sUB3IOkaL5yON9gddKvYFe6eFp8/JVyxsafgBGkAAAAASUVORK5CYII=')
|
||
|
bridge_credits = [
|
||
|
(to_image_key("iVBORw0KGgoAAAANSUhEUgAAAIAAAABQCAIAAABeYuqzAAABjklEQVR4nO3Y25KDIAyAYXD6/q/MXnSboUmAoGjt9P+utAshKCc3JQAAAAAAAAAAAAAAAADAUlmuSin/P+XcKOx41pqqcqWbp5dS2j6dwDKlFBlD9wk19Khvcs6q4fpWjaPZFFV5ibZv5rWCx4d8p137i4RdPqU2lU3ynuyzPVsmnkfd2ycbx777+DuWgHXwTihp1445t7xk2Kqy29sSdN68q5/4ZbNbtR550Nfb0vtwaOV6nB34w/LLc7BNuDMmUnFVDjs3YfWehg+0vNTVVRy7x0z1c2roSOE7TALcxvcOh+/NXB9DP5XH9YYn7Guexrhh97xsj4/qWoWKfE9E4rfMxk+vPSa408S/h2Zf22AT7pzTXf3zcud7QhWuN8kU7lU8fv1Xq7WgteJLEyrtyPUt/hXhdlidlNbGnx1YLce/bx5S/4wlb2rkKgsX4lNX8/otytR3m3avN7l3O9xahfctEZ3s1QjaF7afp7vEHUneRv6pUwwAAAAAAAAAAAAAAAAAAAAAAAAAAADwu/4AM1mC7+a34rIAAAAASUVORK5CYII="), "And so, their journey begins..."),
|
||
|
(to_image_key('iVBORw0KGgoAAAANSUhEUgAAAIAAAABQCAIAAABeYuqzAAABz0lEQVR4nO3Z0XaDIAyAYejp+78yu2iHEQIGjMp2/u9ix1UlCAKhDQEAAAAAcLuUUkpJ/bc4hcL59nl5VSV7sM/U0F71uei53kWMGKO9Qp8DeYscOsUpezn5XnlQnFULrz/p1KdozX5VXZ5LZRoBaufHGD9Fy1M5WD57SC1n7vq6nq36yNaxVLX/XHXc3E/5NWrZOuBznXq1+sBPDW2XuHI8eZU2N/vtRsDo/GO/3qscr7hh/y5ftGhZhtcr/D5P/bdfdKhmRvXURDn5w+KgH9cYIt8oX09Lj849F2nk6pq96jLM3TlOQYsE2tLQ1Vr8tiZ41rv+qNgNdPJ9OS0WxyebzyvvbtXTUo6l/PN2aWgnn+3UTJLLZpECDy1HXnm3XAyDufVbG7qhddho6wDjlmQFQ3l3kUGtRpmCHCsqizrcE/qGyxZfSw6+imjNnqNDOwx+0RQGx3sr7x5t/dY+Y2gVASpsCFvmfw+gTV18F+E6dcs6+XWYmhZbKd1h3HqTMbquLEj5NrS1iKmNNZq5qh1mj/v/+P8k2UEWUbu1Ay56o//0ajS5DwizrWm8S43b+Z0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgOj9pHOL9uqLofgAAAABJRU5ErkJggg=='), "What awaits the Four, they do not know."),
|
||
|
(to_image_key('iVBORw0KGgoAAAANSUhEUgAAAIAAAABQCAIAAABeYuqzAAADsElEQVR4nO2Z0ZbrIAhFTVf//5czD5k6BAFBMUnvPfuptQqIimBLAQAAAAAAAABwKVspZd934YdtGxB3iPKPjfbvDhkQeC/v+umLjI4SWhW6HS/wybtt2vedKq4GMWu09iyi8sVzrEmwvbxtG3NC1E7/Kr7omIPWmkME/YnuqXaIKMeeA+tvyxclFDMuGWFWtN9l90eIJsdj/98CbB9aa+zNJe6gruKZ/uuILnyJ7zbGq21qj5JxiCbVfzvzd74QgqhP2V4Q21fcAVH5mp3fohfcxu8is6WL3irph2B1Oi/ON7E9bA3LcI6v0fYxxOEDMv1Dsuab4gehDrgSFj09O4jdQ8NyHkJ/AeiqemqNkAuOkkfrL/5Uw+BOaiVbTqt0zNoVCGkog06StRs1SAqi8KzEty7hvcelvwAlWJgsnU/Whr1941f6WRC78ethb/vXbtGJte5gurTQp43yqGOIm+yiLAiAp5B1wfgV3ZyGDqBlX5epzlX6bkWLob9VbOTj0dgtoumt8if/nxgI36H/Fbp++/3VlsUWRrNAuwnrkKh3uvI1pdF72PBOaLJawlLOfmv7n/4PMBS3kTEULqkFzlGa0kIm5tQetSeruPFM9vQcXZS90/5X49xotAOV0DXrgjw9ZM+MCnsWwpFheJ4iinL6up0Nuqn3zB3QNd6YxcCdZ/gN/FtE8+jL8u4UVljreguav4RvJMtO4yVmhlPiTz/YkTR0ATjlRPNoI/dln207Q5mrdit40mUx3Ro8ATRndaatBq2z6nzaHVc1elRodlYJ0bpB9MP+edZm3exNcPR3LUCUpXl0Vkgx6p7JziEe/RZk1KIpqyuqmGFA2quczxH94FGWe7+1wtl+Z0pZnBVDimjn6kIvdLuAO0lenFvWXHvM+QourQOWlg704cWj5SF1zLs46gDtMizBLW/I8QsJ0a0Pomlo21nL95111aV1gNaecp/TG7vrUNt+e5RYrxS3/cwJj64DokpDIeghLFmASR4SnRfBDtwj6oAUxBAUrQ+iiPm+7U+ne8HjyQ0Uk9K+N2o98Q74r/h7jGvz2WLmvyJa3t0dYrSL7/6GcC017Obvoj3aa35WHH/ZRlNlnjM+9s4udhNzSu393RZo5O9MCF0VWiJo7fPkh6Csp/Oxp46QXqPAZD9p7fPkL0DUCzNCuju9O7zdzuLGF9tTFuNVpZcM30UliC8zRntUYLcbcyJrYRtfuzYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgPIDXn3QrSWoYQgAAAAASUVORK5CYII='), "Each holding an Orb, that 2000 years ago shined with beauty from within. But now, only darkness."),
|
||
|
(to_image_key('iVBORw0KGgoAAAANSUhEUgAAAIAAAABQCAIAAABeYuqzAAACx0lEQVR4nO2b3ZqEIAiGqWfu/5bbgxqX5EcsLWu+92RnzZARQbCGCAAAAAAAAADApUzrn2VZdq3T1GOwZVlUyVb7LzDTd/anLyTsAfrxKfZIxkiLVJqHr1/ZHzjMsin5ATHnIDtMTdOULnFnghtFUDyAT/oxMPVxyiHoAJbxatt/gZlYhFmhfXihGp+QojiWZ8BjwG1cWgcAnSxc+P+2GgWsFEK84xlqvp9EZTJrPUymv1KUOq71+Xxq14nyBPmqy6vZ91dLighcJSlEtYpjMKnPIGxpaDaDEUV7x5ORl21DtrOg2tkMTs35aq7t7A9oy1CMVufCuqW4o0RmIbItOfrEQygAjKdkio9Q8s28yQC7wzg/1p/Ju60AXSv/fSjPAzjO8wAVnm7LRwJSjvX8gB/q0Xtnn4oGuAZ178lOZN/KFoI6lYhBmbU565tMsnmAVXZaUbhViLCeH0TOPwBogL67Ps7HG+7VTUTFhfynoTxljB/GXW+qG/Oi4pHMgVOWI+8F8cbgsfCB+sBXpvZYKdjZx3mpIJjFSP1nfk1uqn6eni4FVY/XB74ca1yZzlr6H8M6qrEky/5S/1m9Fhx4NCxD9tPfL1QjC2sXgtZlIr2pecC9OIKPnFPklXBmNCtPlz1lf+rzzePxilz9mytTVXU+IqKAL0/ZA95Jmv2H2mDw1VN4z4cqA5yT1/vyz7cX9cluqa0PnHooXvdIZktQNmrVIoqf+6dGq39cjqMJH8WXb1Hb3697OIVKOGJDX13ZHmnkCtTe8ixu/n1A5qoS1ZYj5/UqjsJd9oDislVjcXapuAec1KrJHuDo068SAmPjp32DJ4XXM8RD+V/mQ1rSuojXyskIcPFIh4WvcvC9oHieK+UADkLQzbQxwLGljQ2Zst8JZx9oH3zOBJAsiGHeAQAAAAAAAAAAAAAAAAAAAAAAAAAAAC/mD4+4CUHYQSVTAAAAAElFTkSuQmCC'), "Come!! Start your journey! Return the light of peace to our world."),
|
||
|
|
||
|
|
||
|
(to_image_key("iVBORw0KGgoAAAANSUhEUgAAAIAAAABQCAIAAABeYuqzAAABoUlEQVR4nO3c25KDIAyAYd3Z939l9qKzGYaQGJGDTP/vqiKmgohVpMcBAAAAAAAAAACAoc6OsVJKZfTzdNL1Kj/diZOvzYPkGSTFSdeFqqYXm79FSqnY18/iw3RZtPIXq6qJThwnvl+uLn57BRon2Nxe2iqvzDsAeasJVlZ1E52o+yvpZORz0clY6dVosfI16n8ArIqWyooXya/0eByrx7A6/WDYLvofAL8A1Wtg27cUcaxatr6x1548tOAaICX/fNCt20q34ug8wW6kmh75Ybb8sAEAAAAAmu10R+ePNxS3rLvcrG7wOLpQPHLYpaItP6t34Nvt1Hwuhzblyf7up8VL+UOD6d/0/XqELmix/S7CPJcHAAAAAAAAAADAHf3nCd99bUTP741kbtvEz7/NfGCLHha/HCKvzu+NZNaL8Q3j2SYM8a8fE25uZZs1T8OQWZLBF9ac+b1O5NGD8pMH/Ye8lmL970KXyOIY00VI8Dln2KguKH4M4pU48623abOIB76YFf+Ph7xRXwbML/W3Orq7p8u48xgAAAAAAAAAAHyXP9LOhecc41GgAAAAAElFTkSuQmCC"), "Programmed by Nasir"),
|
||
|
(to_image_key("iVBORw0KGgoAAAANSUhEUgAAAIAAAABQCAIAAABeYuqzAAAB+ElEQVR4nO3b23KDIBCAYez0/V+ZXjBlKHvgHBP7f1dRN4sBQxsXQwAAAAAAAAAAAMBR1950McY/2a8r70yvc1jezG+Re6o8Vrzfbs/+dMhv9wPEGKvPkDat/dUhdedivHVUHQM/zyFfpxtoGr3KPuyqbPk+mt2ZJeSeNAmoE5E6dVTxVrsWddZS2z3q7ACUHeQPhpQ7faIXet5lBay0O+HsAPTwB0Ne5i+Yl9V2D9k5AOmkR7/Czc6t+kLGz7VrTUFWuwAAAACAZ3jFz7zR+/LykPVr2Soh9NQh/pH+OoEa37yhb23GX1W7b+X+m3FNzy4Y3D8AcvaYu7kWjNnpze+p3T8AzYpKGoyhG6v9pZvb3V+SlKy/DSvUmvs74L8gAAAAAAAAAAAAPJtXHqoqSuVmzxNuoVXJsiplVbx6AtZmGK/glxmq96oPDVonUMY3H7/JZoryVsOyR6pHi6oAq3AYxGA3+3RXvNrjfn512EJ3KfTgqojF6qv/dvkhTy8fOlRM9lZFlFeoep1a8XJJ2hB1UUl51Jp81Pih/Pm19VWQ+RfXWzSWpTizhBWfBXHqW+T855aZjGZeOZmdU1D/OPVnc1z2k/Ur+a1VXH7+6TGYGQBr6aC/pDDvH13mFvo6d2N8z2I9NSBfgnNLKwEAAAAAAAAAwDP9AKeVNvQLISpVAAAAAElFTkSuQmCC"), "Character Design by Yositaka Amano"),
|
||
|
(to_image_key("iVBORw0KGgoAAAANSUhEUgAAAIAAAABQCAIAAABeYuqzAAABrElEQVR4nO3c23KDIBCAYe30/V+ZXjhh6LK7gAiK+b+rFpFDUEgE3DYAAAAAAAAAAAAMtc/JJoTwL9d9d8JFYDx0hMdzj5h5Ulbi+bmV5VleCCGtWPxXhG+f+ufh6YkiqTwLNVAc8gtmxR/hd3QGuUGX1aJX64wGOHoP9ZbPY8a/rd7gSM2PqXZNTr43mnQHiM9LfILpofSDdlKzUrCyro8/2YwGyAfPfnFMFrn48R/YBm/4FtQanmf98m9BAAAAAIDESr/0rOf74hfviCcf49zwOLqT9WhhUT93F+DbrXT5OFOMsdtZq/9ZjD9lmE9YLoEu6GbrDcIPn2IEAAAAAAAAAADAw5yZUbLW4Zzb3+snGxMplkdkqoZb5VS3/LXuNz43PXf9lKRVjtY1PPVLHNTlWcXyqBdEmogocGv8Sr2T8u9bBtJal866n78DrFuvdX/v6Mar2R+odlnFjZWt8VXnGyCtiXWr5qfMX0zod0G3L268YAxo3Tb9qLVTxX33RZ3VuX4QLm61TUdX5xUG6Ts3ei7SyvKoO/TVF4OIOD2NBwAAAAAAAAAAvsIfw9p6L1hAGSoAAAAASUVORK5CYII="), "Scenario by Kenji Terada"),
|
||
|
(to_image_key("iVBORw0KGgoAAAANSUhEUgAAAIAAAABQCAIAAABeYuqzAAABoklEQVR4nO3c0Y6DIBBAUdj0/3+ZPpgSAgyMwGDp3vOwsaiDihJbmHUOAAAAAAAAAAAApvzCWCGEPLr3jfJyVXv7qzzddyxOuYsmTrZv+vFbhBCyE7g+GpXHZWl7aa20ql1vtep5f6sCYcxrW03VR96IRXzvvUXPs74BpAsd+9MNvadRLRZtsL4B2sdndB9tcx3/yoALY5VvC1J5bIO7by/S41WNozmqRnx33FsQAAAAAEDhsK9zym/Ozv73vv9IP35wEMYDHrZvPMDazvGGhX6nAQ666Cm6oIcddtcof68HAAAAAAAAAAAAPjqjSFLmiWZkKksjibtIQZzNPJ+y3u6Wt46nel5ZXYMZNVIa7d083mxVN7934Tyfar36XaSSdvxu+nHqxqyIyUHXp8ZsvzwlttUAV0bg/Hybsr8Kwn8ZUObdzdc7ELwaTYofl+NfKWznCciuiEV2oJQ/bHrnDgSfvwOqWg2gme6hnxLSPhq7/GHraaNSfOUZjXRBaXlc9t5n2zfuaOm9Quqaymh63XqVpONZ220CAAAAAAAAAIAf9AaQOdOneYrlMwAAAABJRU5ErkJggg=="), "Production of Square A-Team")
|
||
|
]
|
||
|
@classmethod
|
||
|
def text_box(cls, image, text):
|
||
|
#print([x[1] for x in text])
|
||
|
#res =
|
||
|
raw_text = " ".join([x[1] for x in text])
|
||
|
output = list()
|
||
|
bridge_test = image_to_string_format(image.crop((40,128,128,160)), "BMP")
|
||
|
if bridge_test == cls.bridge_scene:
|
||
|
cropped = image_to_string_format(image.crop((40,32,168, 112)),"BMP")
|
||
|
#import pdb
|
||
|
#pdb.set_trace()
|
||
|
for cred, t in cls.bridge_credits:
|
||
|
if cred == cropped:
|
||
|
output = [((1,1), t)]
|
||
|
break
|
||
|
else:
|
||
|
for pos, entry in text:
|
||
|
for r1,r2 in [("ORBS", "Orbs"), ("ORB", "Orb"), ("G0", "Go"),
|
||
|
("g0", "go")]:
|
||
|
entry = entry.replace(r1, r2)
|
||
|
output.append((pos, entry))
|
||
|
return [x[1] for x in output]
|
||
|
|
||
|
|
||
|
def main3():
|
||
|
import os
|
||
|
screen_test_list = list()
|
||
|
ScreenSelector._load_content(None, None, None, None)
|
||
|
for filename in os.listdir("./"):
|
||
|
if filename.startswith("test_"):
|
||
|
if "battle" in filename:
|
||
|
screen_test_list.append(filename)
|
||
|
for i, name in enumerate(sorted(screen_test_list, key=lambda x: int(x.partition("battle")[2].partition(".")[0]))):
|
||
|
if i < 50:
|
||
|
continue
|
||
|
image = Image.open(name)
|
||
|
print(name)
|
||
|
ScreenSelector.parse_whole_screen(image)
|
||
|
import pdb
|
||
|
pdb.set_trace()
|
||
|
|
||
|
def main2():
|
||
|
image_list = [Image.open("text"+str(i)+".png") for i in range(7)]
|
||
|
f = ParseScreenText.get_font(image_list)
|
||
|
|
||
|
start_image_id = ObjectId("5df9d8208ac3d956387c0941")
|
||
|
doc = db.ocr_images.find_one({"_id": start_image_id})
|
||
|
game_id = doc['game_id']
|
||
|
user_id = doc['user_id']
|
||
|
|
||
|
for image in db.ocr_images.find({"user_id": user_id,
|
||
|
"game_id": game_id},
|
||
|
sort=[("_id", pymongo.ASCENDING)]):
|
||
|
im = load_image(image['image_data'])
|
||
|
t = time.time()
|
||
|
tex = ParseScreenText.parse_screen(im, f)
|
||
|
print (time.time()-t)
|
||
|
for coord, line in tex:
|
||
|
print(coord, line)
|
||
|
if tex:
|
||
|
import pdb
|
||
|
pdb.set_trace()
|
||
|
|
||
|
def main4():
|
||
|
image_list = [Image.open("text"+str(i)+".png") for i in range(7)]
|
||
|
f = ParseScreenText.get_font(image_list)
|
||
|
|
||
|
start_image_id = ObjectId("5df9d8208ac3d956387c0941")
|
||
|
doc = db.ocr_images.find_one({"_id": start_image_id})
|
||
|
game_id = doc['game_id']
|
||
|
user_id = doc['user_id']
|
||
|
c =0
|
||
|
enemy_data = {
|
||
|
"iguana": {"w": 48},
|
||
|
"garland": {"x": 64, "y": 72, "ratio": 0.5},
|
||
|
"asp": {"ratio": 0.5},
|
||
|
"agama": {"w": 48},
|
||
|
"badman": {"x": 64},
|
||
|
"evilman": {"x": 64},
|
||
|
"bull": {"x": 16, "y": 40, "w": 48, "h": 48},
|
||
|
"hyena": {"x": 80},
|
||
|
"seasnake": {"w": 32, "ratio": 0.5},
|
||
|
"naga": {"w": 48, "ratio": 0.5},
|
||
|
"grnaga": {"w": 48, "ratio": 0.5},
|
||
|
"wzvamp": {"w": 48, "w": 32, "ratio": 0.25},
|
||
|
"kary": {"ratio": 0.05, "ratio2": 0.95,"w": 96},
|
||
|
"kraken": {"ratio": 0.05, "ratio2": 0.95, "w": 96},
|
||
|
"tiamat": {"ratio": 0.05, "ratio2": 0.95, "w": 96},
|
||
|
"medusa": {"x": 64},
|
||
|
"warmech": {"w": 48},
|
||
|
"vampire": {"x": 64, "w": 32},
|
||
|
"wzvamp": {"x": 64, "w": 32},
|
||
|
"zombull": {"x": 16, "y": 40, "w":48, "h":48},
|
||
|
"r.ankylo": {"w": 48},
|
||
|
"r.giant": {"w": 48},
|
||
|
"r.hydra": {"w": 48},
|
||
|
"wrwolf": {"x": 96, "ratio": 0.5},
|
||
|
}
|
||
|
|
||
|
for filename in os.listdir("./"):
|
||
|
if "enemy" in filename:
|
||
|
if filename.split(".")[0].split("_")[-1].isdigit():
|
||
|
os.remove(filename)
|
||
|
found = dict()
|
||
|
saved = dict()
|
||
|
for image in db.ocr_images.find({"user_id": user_id,
|
||
|
"game_id": game_id},
|
||
|
sort=[("_id", pymongo.ASCENDING)]):
|
||
|
im = load_image(image['image_data'])
|
||
|
if ScreenSelector.is_battle(im):
|
||
|
text = ParseScreenText.parse_screen(im, f)
|
||
|
res = ScreenSelector.battle_parse(im, text)
|
||
|
if not res.get("status") and res.get("menu").lower() in ['fight', 'magic', 'item', 'drink', 'run'] and len(res.get("enemy_names",[])) == 1:
|
||
|
name = res['enemy_names'][0].strip().lower()
|
||
|
found[name] = 1
|
||
|
|
||
|
boxes_to_check = list()
|
||
|
#check 3x3
|
||
|
for i in range(3):
|
||
|
for j in range(3):
|
||
|
x = 16+32*i
|
||
|
y = 40+32*j
|
||
|
w = 32
|
||
|
h = 32
|
||
|
boxes_to_check.append((x,y,w,h))
|
||
|
#check for big enemy plus 3 small
|
||
|
for i in range(1):
|
||
|
for j in range(3):
|
||
|
x = 16+48
|
||
|
y = 40+32*j
|
||
|
w = 32
|
||
|
h = 32
|
||
|
boxes_to_check.append((x,y,w,h))
|
||
|
for i in range(3):
|
||
|
for j in range(3):
|
||
|
x = 32+32*i
|
||
|
y = 40+32*j
|
||
|
w = 32
|
||
|
h = 32
|
||
|
boxes_to_check.append((x,y,w,h))
|
||
|
#check for big enemies
|
||
|
for i in range(2):
|
||
|
for j in range(2):
|
||
|
x = 16+48*i
|
||
|
y = 40+48*j
|
||
|
w = 48
|
||
|
h = 48
|
||
|
boxes_to_check.append((x,y,w,h))
|
||
|
for i in range(1):
|
||
|
for j in range(2):
|
||
|
x = 80
|
||
|
y = 40+48*j
|
||
|
w = 48
|
||
|
h = 48
|
||
|
boxes_to_check.append((x,y,w,h))
|
||
|
|
||
|
#boss box check
|
||
|
boxes_to_check.append((16+24, 40+24, 48, 48))
|
||
|
#chaos box check
|
||
|
boxes_to_check.append((16, 40, 96, 96))
|
||
|
|
||
|
for i in range(2):
|
||
|
if i == 1:
|
||
|
ratio = 0.25
|
||
|
else:
|
||
|
ratio = 0.75
|
||
|
for x,y,w,h in boxes_to_check:
|
||
|
flag = False
|
||
|
for ch in "xywh":
|
||
|
var = locals()[ch]
|
||
|
if enemy_data.get(name, {}).get(ch, var) != var:
|
||
|
break
|
||
|
else:
|
||
|
flag = True
|
||
|
if flag is False:
|
||
|
continue
|
||
|
|
||
|
subi = im.crop((x,y,x+w,y+h))
|
||
|
lines = [subi.crop((0,0, 1, h)),
|
||
|
subi.crop((0,0, w, 1)),
|
||
|
subi.crop((w-1, 0, w,h)),
|
||
|
subi.crop((0, h-1, w,h))]
|
||
|
|
||
|
flag = False
|
||
|
|
||
|
for line in lines:
|
||
|
for cc in line.convert("RGBA").getcolors():
|
||
|
amt = h*enemy_data.get(name, {}).get("ratio", ratio)
|
||
|
if cc[1] == (0,0,0,255) and cc[0] > amt:
|
||
|
break
|
||
|
else:
|
||
|
#this line did not have enough black pixels
|
||
|
print("not enough black pixels")
|
||
|
break
|
||
|
else:
|
||
|
#all the lines had enough black pixels.
|
||
|
flag = True
|
||
|
|
||
|
if flag is False:
|
||
|
continue
|
||
|
|
||
|
p = subi.convert("RGB").resize((1,1), resample=Image.BILINEAR).getpixel((0,0))
|
||
|
if not p[0] and not p[1] and not p[2]:
|
||
|
continue
|
||
|
|
||
|
ratio2 = 85/100.0
|
||
|
if enemy_data.get(name, {}).get("ratio2"):
|
||
|
ratio2 = enemy_data[name]['ratio2']
|
||
|
for cc in subi.convert("RGB").getcolors():
|
||
|
if cc[1] == (0,0,0):
|
||
|
if cc[0] < ratio2*w*h:
|
||
|
#succ
|
||
|
break
|
||
|
else:
|
||
|
#fail
|
||
|
continue
|
||
|
else:
|
||
|
#fail
|
||
|
continue
|
||
|
|
||
|
i = 0
|
||
|
saved[name] = 1
|
||
|
while True:
|
||
|
filename = "enemy_"+name+"_"+str(i)+".png"
|
||
|
try:
|
||
|
old_im = Image.open(filename)
|
||
|
if image_to_string_format(old_im, "BMP") == image_to_string_format(subi, "BMP"):
|
||
|
break
|
||
|
else:
|
||
|
i+=1
|
||
|
except:
|
||
|
subi.save(filename)
|
||
|
break
|
||
|
break
|
||
|
if name in saved:
|
||
|
break
|
||
|
im.save("test_battle"+str(c)+".png")
|
||
|
c+=1
|
||
|
|
||
|
for key in found:
|
||
|
if key not in saved:
|
||
|
print(['not found', key])
|
||
|
|
||
|
def test_person():
|
||
|
im = Image.open("person_test.png")
|
||
|
po = PackageOutput("ff1_data.lud", "enemy_lookup.dat")
|
||
|
import pdb
|
||
|
pdb.set_trace()
|
||
|
print ("--", po.memory)
|
||
|
print (po.run(im, {"paused": 1}))
|
||
|
|
||
|
|
||
|
if __name__=='__main__':
|
||
|
#main4()
|
||
|
#main3()
|
||
|
#main2()
|
||
|
main()
|
||
|
#main_c()
|
||
|
#test_person()
|