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[int(-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[int(-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 = list(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 list(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, str):
|
|
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 list(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 list(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()
|