diff options
author | Florian Jung <flo@windfisch.org> | 2015-09-01 20:47:11 +0200 |
---|---|---|
committer | Florian Jung <flo@windfisch.org> | 2015-09-01 20:48:03 +0200 |
commit | 7a836f4a0a68188a1486b669c4cd437b5f592a5d (patch) | |
tree | 666d7867967e8d6fdc04aca6b18d8a95a077f33c | |
parent | f99e10cff97afdc3e6ef07db22cf5f7fd442e067 (diff) | |
parent | 7c1180a7b58e7b8c17c8dab297058d0c001386c6 (diff) |
Merge branch 'master' into pathfinding
34 files changed, 3404 insertions, 99 deletions
@@ -3,9 +3,13 @@ prerequisites: python3, pygame and websocket-client git submodule update --init python3 main.py -move mouse = move -left click, space = split -right click, w = eject some mass +space = split +w = eject some mass r = respawn -s = lock input. cycles through: user lock -> user and bot lock -> bot lock -> no lock +s = lock input. toggle between "user controls" and "bot controls". hold shift for "nobody controls" +move mouse = move +mouse left/mid/right click: set markers (currently unused) esc = quit + +the stats.py module automatically creates/overwrites the stats.pickle file (roughly 1MB per 5 minutes currently) +which can be loaded using Stats.load() and analyzed using the Stats.analyze_* functions, or using analyze.py diff --git a/analyze.py b/analyze.py new file mode 100644 index 0000000..c9c3ac8 --- /dev/null +++ b/analyze.py @@ -0,0 +1,24 @@ +from stats import * +import sys + +if len(sys.argv) >= 2: + files = sys.argv[1:] +else: + files = ["stats.pickle"] + + +s = Stats.load(files[0]) +for f in files[1:]: + s.merge(f) + +s.analyze_speed() +print("\n" + "-"*40 + "\n") +s.analyze_visible_window(False) +for i in ["split cell", "ejected mass", "virus", "virus2", "virus3"]: + s.analyze_deviations(i) +print("") +for i in ["split cell", "ejected mass", "virus"]: + s.analyze_distances(i) + +s.analyze_virus_sizes() +s.analyze_remerge() diff --git a/geometry.py b/geometry.py new file mode 100644 index 0000000..d69add8 --- /dev/null +++ b/geometry.py @@ -0,0 +1,27 @@ +import math +def distance_point_line(p, l1, l2): + # (x - l1.x) * (l2.y-l1.y)/(l2.x-l1.x) + l1.y = y + # x * (l2.y-l1.y)/(l2.x-l1.x) - l1.x * (l2.y-l1.y)/(l2.x-l1.x) + l1.y - y = 0 + # x * (l2.y-l1.y) - l1.x * (l2.y-l1.y) + l1.y * (l2.x-l1.x) - y * (l2.x-l1.x) = 0 + # ax + by + c = 0 + # with a = (l2.y-l1.y), b = -(l2.x-l1.x), c = l1.y * (l2.x-l1.x) - l1.x * (l2.y-l1.y) + a = (l2.y-l1.y) + b = -(l2.x-l1.x) + c = l1.y * (l2.x-l1.x) - l1.x * (l2.y-l1.y) + + d = math.sqrt(a**2 + b**2) + a/=d + b/=d + c/=d + + assert (abs(a*l1.x + b*l1.y + c) < 0.001) + assert (abs(a*l2.x + b*l2.y + c) < 0.001) + + return abs(a*p.x + b*p.y + c) + +def is_colinear(points, epsilon=1): + for point in points: + if distance_point_line(point, points[0], points[-1]) > epsilon: + return False + return True + @@ -6,6 +6,10 @@ from pygame.locals import * import sys import math import time +import mechanics +from agarnet.agarnet.vec import Vec + +running = True font_fallback = False try: @@ -28,13 +32,47 @@ marker_updated = [True, True, True] screensize=(1280, 800) screen=pygame.display.set_mode(screensize,HWSURFACE|DOUBLEBUF|RESIZABLE) + +vignette = 1. + +def enable_vignette(factor=0.15): + global vignette + if factor: + vignette = 1+factor + else: + vignette = 1 + +def draw_bar(rect, val, thresh=None, min=0, max=1, color=(0,0,0), barcolor=None, exceedcolor=(255,0,0), threshcolor=None): + v = (val-min)/(max-min) + t = (thresh-min)/(max-min) + + if barcolor == None: + barcolor_=color + else: + barcolor_=barcolor + if thresh != None and threshcolor==None: + threshcolor_ = ((128+color[0])//2, (128+color[1])//2, (128+color[2])//2) + else: + threshcolor_ = threshcolor + + for i in range(0, 1 if v<t else 3): + draw_box( ((rect[0][0]-i,rect[0][1]-i),(rect[1][0]+2*i, rect[1][1]+2*i)) , color if v<t or exceedcolor==None else exceedcolor, False, False) + + draw_box(((rect[0][0]+2,rect[0][1]+2), ((rect[1][0]-4)*v, rect[1][1]-4)), barcolor_, True, False) + if thresh != None: + if exceedcolor != None and v >= t: + draw_box(((rect[0][0]+2 + (rect[1][0]-4)*t , rect[0][1]+2) , ((rect[1][0]-4)*(v-t) , rect[1][1]-4)), exceedcolor, True, False) + + draw_line((rect[0][0]+2+(rect[1][0]-4)*t, rect[0][1]+1), (rect[0][0]+2+(rect[1][0]-4)*t, rect[0][1]+rect[1][1]-1), threshcolor_, False) + + def draw_line(p1, p2, color, global_coords=True): if global_coords: p1 = world_to_win_pt(p1, c.player.center) p2 = world_to_win_pt(p2, c.player.center) - gfxdraw.line(screen, p1[0], p1[1], p2[0], p2[1], color) + gfxdraw.line(screen, int(p1[0]), int(p1[1]), int(p2[0]), int(p2[1]), color) def draw_box(rect, color, filled=False, global_coords=True): if global_coords: @@ -60,6 +98,11 @@ def draw_circle(pos, r, color, filled=False, global_coords=True): gfxdraw.circle(screen, pos[0], pos[1], r, color) gfxdraw.aacircle(screen, pos[0], pos[1], r, color) +def hilight_cell(cell, color_inner, color_outer, r=20): + draw_circle(cell.pos, cell.size+r, color_outer, True) + draw_circle(cell.pos, cell.size+r/2, color_inner, True) + draw_cell(cell) + def draw_polygon(polygon, color, filled=False, global_coords=True): if len(polygon) > 2: if global_coords: @@ -103,12 +146,31 @@ def draw_text(pos, text, color, font_size=16, global_coords=True, draw_centered= def update(): pygame.display.update() -def calc_zoom(): - zoom1 = screensize[0] / 2051. - zoom2 = screensize[1] / 1216. - return max(zoom1,zoom2) +def update_zoom(): + global zoom + global calculated_visible_width, calculated_visible_height + + ratio = 1.7 # reverse engineered value. + + size = sum(map(lambda cell : cell.size, c.player.own_cells)) + + # reverse engineered formula + diag_server = mechanics.viewport_diag(size) if size > 0 else 10000 + + # calculate screen diag, if we would have a screen with our width, but correct ratio + diag1 = math.sqrt(screensize[0]**2 * (1 + 1/1.7**2)) + # calculate screen diag, if we would have a screen with our height, but correct ratio + diag2 = math.sqrt(screensize[1]**2 * (1 + 1.7**2)) + + # what we expect to be visible from server + calculated_visible_width = diag_server / math.sqrt(1+1/ratio**2) + calculated_visible_height = diag_server / math.sqrt(1+ ratio**2) + + zoom1 = screensize[0] / calculated_visible_width + zoom2 = screensize[1] / calculated_visible_height + + zoom = min(zoom1,zoom2) / vignette -zoom = calc_zoom() def world_to_win_length(l): return int(l*zoom) @@ -141,7 +203,21 @@ def generate_virus(spikes, spike_length, radius, global_coords): return points def draw_cell(cell): + font_size = 16 + virus_sizes = {100:1, 106:2, 113:3, 119:4, 125:5, 131:6, 136:7} + cx,cy = world_to_win_pt(cell.pos,c.player.center) + try: + mov_ang = cell.movement_angle + p2 = cell.pos + Vec( math.cos(mov_ang + mechanics.eject_delta*math.pi/180), math.sin(mov_ang + mechanics.eject_delta*math.pi/180) ) * (cell.size+700) + p3 = cell.pos + Vec( math.cos(mov_ang - mechanics.eject_delta*math.pi/180), math.sin(mov_ang - mechanics.eject_delta*math.pi/180) ) * (cell.size+700) + + cx2,cy2 = world_to_win_pt(p2,c.player.center) + cx3,cy3 = world_to_win_pt(p3,c.player.center) + except (AttributeError, TypeError): + cx2,cy2=cx,cy + cx3,cy3=cx,cy + radius = world_to_win_length(cell.size) if cell.is_virus: @@ -156,19 +232,24 @@ def draw_cell(cell): gfxdraw.filled_polygon(screen, polygon2, color) gfxdraw.aapolygon(screen, polygon2, color) + + draw_text((cx, cy), "%s / 7" % virus_sizes.get(cell.size, "?"), (64,0,0), font_size*2, False, True) + draw_text((cx, cy + radius + 10), str(cell.cid), (0,0,0), font_size, False, True) else: color=(int(cell.color[0]*255), int(cell.color[1]*255), int(cell.color[2]*255)) + if not (cell.is_ejected_mass or cell.is_food): + gfxdraw.aapolygon(screen, [(cx,cy),(cx2,cy2),(cx3,cy3),(cx,cy)] ,(255,127,127)) + gfxdraw.filled_circle(screen, cx, cy, radius, color) gfxdraw.aacircle(screen, cx, cy, radius, (0,0,0)) gfxdraw.aacircle(screen, cx, cy, int(radius/2), (255,255,255)) gfxdraw.circle(screen, cx, cy, int(radius/2), (255,255,255)) - font_size = 16 - draw_text((cx, cy + radius + 10), cell.name, (0, 0, 0), font_size, False, True) + draw_text((cx, cy + radius + 10 + font_size), str(cell.cid), (0,0,0), font_size, False, True) # surface = draw_text(cell.name, (0, 0, 0), font_size) # screen.blit(surface, (cx - (surface.get_width()/2), cy + radius + 5)) @@ -191,6 +272,19 @@ def draw_leaderboard(): # screen.blit(surface, (5, next_y)) next_y += surface.get_height()+5 +def draw_visible_window_borders(): + global screen + + vignette_color=(192,192,192) + vignette_width = int(max(0, (screensize[0]-world_to_win_length(calculated_visible_width))/2)) + vignette_height = int(max(0, (screensize[1]-world_to_win_length(calculated_visible_height))/2)) + + screen.fill(vignette_color, rect=((0,0),(vignette_width,screensize[1]))) + screen.fill(vignette_color, rect=((screensize[0]-vignette_width,0),(vignette_width,screensize[1]))) + screen.fill(vignette_color, rect=((0,0),(screensize[0],vignette_height))) + screen.fill(vignette_color, rect=((0,screensize[1]-vignette_height),(screensize[0],vignette_height))) + + def draw_world_borders(): top = int((c.world.top_left[0] - c.player.center[1])*zoom + screensize[1]/2) left = int((c.world.top_left[1] - c.player.center[0])*zoom + screensize[0]/2) @@ -226,13 +320,37 @@ def draw_markers(): for i in [0, 1, 2]: draw_marker(marker[i], colors[i], marker_updated[i]) +def draw_debug(): + for cell in c.world.cells.values(): + parent = None + shoot_vec = None + settled = None + try: + parent = cell.parent + shoot_vec = cell.shoot_vec + settled = cell.calmed_down + except AttributeError: + pass + + if parent != None: + draw_line(cell.pos, parent.pos,(255,0,0)) + draw_circle(parent.pos,3,(255,0,0),True) + + + if shoot_vec != None and settled != True: + shoot_vec = 400 * shoot_vec / shoot_vec.len() + draw_line(cell.pos, cell.pos+shoot_vec, (0,255,255)) + + def draw_frame(): - global screen, movement, zoom, screensize, input, bot_input, marker, marker_updated + global screen, movement, zoom, screensize, input, bot_input, marker, marker_updated, running pygame.event.pump() clock.tick() + update_zoom() clear_screen() + draw_visible_window_borders() draw_world_borders() food = list(filter(lambda x: x.is_food, c.world.cells.values())) @@ -267,23 +385,23 @@ def draw_frame(): if event.type == VIDEORESIZE: screensize = event.dict['size'] screen=pygame.display.set_mode(screensize, HWSURFACE|DOUBLEBUF|RESIZABLE) - zoom = calc_zoom() + update_zoom() pygame.display.update() if event.type == QUIT: pygame.display.quit() if event.type == KEYDOWN: if event.key == K_s: - if not input and bot_input: + if event.mod & KMOD_SHIFT and (input or bot_input): input = False bot_input = False - elif not input and not bot_input: + elif not input and bot_input: input = True bot_input = False else: input = False bot_input = True if event.key == K_ESCAPE: - pygame.quit() + running = False if event.key == K_r: c.send_respawn() if event.type == MOUSEBUTTONDOWN: @@ -291,11 +409,11 @@ def draw_frame(): marker[event.button-1] = win_to_world_pt(event.pos, c.player.center) marker_updated[event.button-1] = True print("set marker "+str(event.button-1)+" to "+str(event.pos)) + if event.type == KEYDOWN: + if event.key == K_w: + c.send_shoot() + if event.key == K_SPACE: + c.send_split() if input: - if event.type == KEYDOWN: - if event.key == K_w: - c.send_shoot() - if event.key == K_SPACE: - c.send_split() if event.type == MOUSEMOTION: c.send_target(*win_to_world_pt(event.pos, c.player.center)) diff --git a/interval_utils.py b/interval_utils.py index 0095c06..7123893 100644 --- a/interval_utils.py +++ b/interval_utils.py @@ -70,13 +70,37 @@ def intervals_intersect(int1_, int2_): return False -def check_cell_in_interval(origin, cell, interval): +def intersection(int1s, int2s): + #expects merged, canonicalized intervals, returns overlap-free canonicalized intervals + + result = [] + + for int1 in int1s: + for int2 in int2s: + if (max(int1[0],int2[0]) <= min(int1[1],int2[1])): + result += [(max(int1[0],int2[0]), min(int1[1],int2[1]))] + + return result + +def interval_area(ints): + result = 0 + for i in merge_intervals(ints): + result += i[1]-i[0] + return result + +def interval_occupied_by_cell(origin, cell): ang = get_point_angle(origin, cell.pos) dist = math.sqrt( (cell.pos[0]-origin[0])**2 + (cell.pos[1]-origin[1])**2 ) - corridor_halfwidth = math.asin(cell.size / dist) + if cell.size >= dist: + corridor_halfwidth = math.pi/2 + else: + corridor_halfwidth = math.asin(cell.size / dist) + + return (ang-corridor_halfwidth, ang+corridor_halfwidth) - return intervals_intersect(interval, (ang-corridor_halfwidth, ang+corridor_halfwidth)) +def check_cell_in_interval(origin, cell, interval): + return intervals_intersect(interval, interval_occupied_by_cell(origin,cell)) def get_cells_in_interval(origin, interval, cells): return list(filter(lambda x: check_point_in_interval(origin, x.pos, interval), cells)) @@ -7,16 +7,79 @@ import sys import math import time import random -import gui +import nogui as gui # might be overridden later. import stats -from subscriber import DummySubscriber +from subscriber import EnhancingSubscriber from interval_utils import * from pathfinding import PathfindingTesterStrategy +import time + +class Clock: + def __init__(self): + self.t = time.time() + self.fps_t = time.time() + self.fps = 27 + self.cnt = 0 + self.newfps = False + + def tic(self): + t = time.time() + result = t-self.t + self.t=t + return result + + def getfps(self): + self.cnt+=1 + if time.time() > self.fps_t + 1: + self.fps_t += 1 + self.fps = self.cnt + self.cnt = 0 + self.newfps = True + else: + self.newfps = False + return self.fps + +class ProblemException(BaseException): + pass + +class ProblemManager: + def __init__(self, setup): + self.setup = setup + self.problems = {} + for t in setup: + self.problems[t] = [] + + def report(self, prob): + self.problems[prob] += [time.time()] + self.problems[prob] = list(filter(lambda t : time.time() < t + self.setup[prob][1], self.problems[prob])) + + if len(self.problems[prob]) > self.setup[prob][0]: + print("PROBLEM: "+prob) + if self.setup[prob][2]: + raise ProblemException + +probs = ProblemManager({"network lag":(100,5,True), "strategy lag":(5,2,False), "gui lag":(5,2,False), "high fps":(5,6,True), "low fps":(5,6,True)}) + + +if "--nogui" in sys.argv: + sys.argv.remove("--nogui") +else: + try: + import gui + except: + print("ERROR: could not import gui... running without gui.") + # global vars -sub = DummySubscriber() +sub = EnhancingSubscriber() c = client.Client(sub) -stats = stats.Stats() +sub.set_client(c) +stats = stats.Stats(c) + +try: + nick = sys.argv[2] +except: + nick = "" for i in range(1,10): # 10 connection attempts print("trying to connect, attempt "+str(i)) @@ -25,8 +88,11 @@ for i in range(1,10): # 10 connection attempts try: token = sys.argv[1] addr, *_ = utils.get_party_address(token) + print("using party token") + except: addr, token, *_ = utils.find_server() + print("joining random game") # connect c.connect(addr,token) @@ -37,27 +103,64 @@ for i in range(1,10): # 10 connection attempts c.disconnect() -c.player.nick="test cell pls ignore" +c.player.nick=nick # initialize GUI gui.set_client(c) # initialize strategy -strategy = PathfindingTesterStrategy(c) - -# main loop -while True: - c.on_message() - - gui.draw_frame() - - if len(list(c.player.own_cells)) > 0: - target = strategy.process_frame() - - if gui.bot_input and target != None: - c.send_target(target[0], target[1]) - - stats.log_pos(c.player.center) - stats.log_mass(c.player.total_mass) - gui.update() +strategy = PathfindingTesterStrategy(c, gui) + +autorespawn_counter = 60 + +clock = Clock() + +try: + # main loop + while gui.running: + c.on_message() + if clock.tic() > 1./20: + print("NETWORK LAG") + probs.report("network lag") + + gui.draw_frame() + if clock.tic() > 1./40: + print("GUI SLOW") + probs.report("gui lag") + + if len(list(c.player.own_cells)) > 0: + target = strategy.process_frame() + + if gui.bot_input: + c.send_target(target[0], target[1]) + + stats.process_frame() + + if clock.tic() > 1./25.: + print("STRATEGY LAG") + probs.report("strategy lag") + + gui.draw_debug() + gui.update() + + if not c.player.is_alive: + if autorespawn_counter == 0: + c.send_respawn() + autorespawn_counter = 60 + else: + autorespawn_counter-=1 + + fps = clock.getfps() + if clock.newfps: + print("FPS: %3d" % fps) + if fps < 24: + probs.report("low fps") + if fps > 50: + probs.report("high fps") +except ProblemException: + print("Exiting due to a problem such as low/high fps, network lags etc") + +stats.save("stats.pickle") + +print("bye") diff --git a/mechanics.py b/mechanics.py new file mode 100644 index 0000000..3aaa405 --- /dev/null +++ b/mechanics.py @@ -0,0 +1,15 @@ +from agarnet.agarnet.world import Cell + +def speed(size_or_cell): + if isinstance(size_or_cell, Cell): + if size_or_cell.is_virus or size_or_cell.is_ejected_mass or size_or_cell.is_food: + return 0 + else: + return speed(size_or_cell.size) + else: + return 86 / (size_or_cell**0.45) + +def viewport_diag(sizesum): + return 370 * max(sizesum,70)**0.431776 + +eject_delta = 22 # how many degrees do ejects deviate from the original direction (maximum) diff --git a/nogui.py b/nogui.py new file mode 100644 index 0000000..b2989de --- /dev/null +++ b/nogui.py @@ -0,0 +1,41 @@ +running = True +bot_input = True + +def draw_bar(rect, val, thresh=None, min=0, max=1, color=(0,0,0), barcolor=None, exceedcolor=(255,0,0), threshcolor=None): + pass + +def draw_line(p1, p2, color, global_coords=True): + pass + +def draw_box(rect, color, filled=False, global_coords=True): + pass + +def draw_circle(pos, r, color, filled=False, global_coords=True): + pass + +def hilight_cell(cell, color_inner, color_outer, r=20): + pass + +def draw_polygon(polygon, color, filled=False, global_coords=True): + pass + +def draw_path(path, color, global_coords=True): + pass + +def draw_arc(pos, r, bounds, color, global_coords=True): + pass + +def draw_text(pos, text, color, font_size=16, global_coords=True, draw_centered=False): + pass + +def update(): + pass + +def set_client(cl): + pass + +def draw_debug(): + pass + +def draw_frame(): + pass diff --git a/pathfinding.py b/pathfinding.py index beec89a..9386275 100644 --- a/pathfinding.py +++ b/pathfinding.py @@ -1,5 +1,3 @@ -from gui import marker, marker_updated -import gui import math @@ -75,9 +73,10 @@ grid_radius=int(1100/30)*30 grid_density=30 class PathfindingTesterStrategy: - def __init__(self, c): + def __init__(self, c, gui): self.c = c self.path = None + self.gui = gui def build_grid(self): grid = [[0 for x in range(int(2*grid_radius//grid_density+1))] for x in range(int(2*grid_radius//grid_density+1))] @@ -110,8 +109,8 @@ class PathfindingTesterStrategy: return grid def plan_path(self): - goalx = int((marker[0][0] - self.c.player.center[0] + grid_radius)/grid_density) - goaly = int((marker[0][1] - self.c.player.center[1] + grid_radius)/grid_density) + goalx = int((self.gui.marker[0][0] - self.c.player.center[0] + grid_radius)/grid_density) + goaly = int((self.gui.marker[0][1] - self.c.player.center[1] + grid_radius)/grid_density) grid = self.build_grid() @@ -130,8 +129,8 @@ class PathfindingTesterStrategy: return True def process_frame(self): - if marker_updated[0]: - marker_updated[0]=False + if self.gui.marker_updated[0]: + self.gui.marker_updated[0]=False self.path = self.plan_path() for node in self.path: @@ -140,7 +139,7 @@ class PathfindingTesterStrategy: for (node1,node2) in zip(self.path,self.path[1:]): - gui.draw_line(node1.point, node2.point, (0,0,0)) + self.gui.draw_line(node1.point, node2.point, (0,0,0)) if self.path: relx, rely = self.path[0].point[0]-self.c.player.center.x, self.path[0].point[1]-self.c.player.center.y @@ -153,4 +152,4 @@ class PathfindingTesterStrategy: if self.path: return self.path[0].point - return marker[0] + return self.gui.marker[0] diff --git a/reversing_game_mechanics/game_mechanics.txt b/reversing_game_mechanics/game_mechanics.txt new file mode 100644 index 0000000..2488481 --- /dev/null +++ b/reversing_game_mechanics/game_mechanics.txt @@ -0,0 +1,54 @@ +Created 2015-09-01, with data between 0 and 2 weeks old. + +Units used: + distances, sizes are measured in raw agar.io coordinates. + times are measured in frames. The game ran at 27-28 FPS at the time + where this document was created + speeds are measured in distance / number of frames + + + +cellspeed = 86.05 / cellsize**0.45 + +zoom level is 369.399 * sum(own_cells.size) ** 0.431776 + +ejecting mass: + prerequisite: size >= 60, i.e. mass >= 35 + you will lose 16 mass, but only gain 12 mass if you eat the blob + one can eat ejected mass if mass >= 18 i.e. size >= 43 + + 75% of the ejects had a deviation smaller than 0.39 rad = 22.16 deg + from the original moving direction of the shooting cell + + they fly 44-45px, starting from shooting cell's border. + +splitting: + 75% of the splits had a deviation smaller than 0.02 rad = 1.19 deg + from the original moving direction of the parent + + flight distance: unknown, somewhere between 100 - 650, max = 1205 + + re-union will usually become possible somewhere after 745 - 790 frames + this means that your cells are possible to glide into each + other. depending on your movement pattern they will actually + merge sooner or later. + +feeding viruses: + 75% of the splits had a deviation smaller than 0.00 rad = 0.11 deg + from the ejected mass movement vector. + + maximum distance is 580 from the midpoint of the parent virus. + not sure about the minimum (too few data), but probably also 580? + + Viruses can have the following sizes: + 100, 106, 113, 119, 125, 131, 136. + Sometimes 141 is also observed, but those viruses will split + almost instantly (bug in the server software?) + i.e., feed a virus with size 100 6 times to maximum size, and one more + time to make it duplicate. + +eating: + a cell can eat us, if their size/mass(??) is at least 1.25* our size/mass + a cell eats another, if the smaller one's midpoint is within the + larger one's circle (with radius = size) + diff --git a/reversing_game_mechanics/splits_and_ejects/README b/reversing_game_mechanics/splits_and_ejects/README new file mode 100644 index 0000000..14fa5ad --- /dev/null +++ b/reversing_game_mechanics/splits_and_ejects/README @@ -0,0 +1,50 @@ +Data collected with revision 165dd41, four parallel instances, 30-45 minutes each, on +2015-08-28. Analyzed with analyze.py + +split cell eject/split direction deviations: mean = -0.04179961392956227, stddev=0.4556678701725402, ndata=159 + 75% of the splits had a deviation smaller than 0.02 rad = 1.31 deg + +ejected mass eject/split direction deviations: mean = -0.0016847086620534303, stddev=0.872858965604425, ndata=352 + 75% of the splits had a deviation smaller than 0.46 rad = 26.47 deg + + +split cell eject/split distances: mean = 388.2279635920042, stddev=222.71465106976927, ndata=314 + 75% of the values lie in the interval 381.25 plusminus 225.53 + +ejected mass eject/split distances: mean = 442.90229450857305, stddev=189.2221703217239, ndata=252 + 75% of the values lie in the interval 535.71 plusminus 8.61 + +distances are measured between "spawn point of cell" and "end point of movement". +Spawnpoint is usually near "parentcell.midpoint + parentcell.size". + + + +Now if we measure distances between "midpoint of parent cell" and "end point of movement" by +applying the following patch: + +diff --git a/stats.py b/stats.py +index bb88c3e..1c0a196 100644 +--- a/stats.py ++++ b/stats.py +@@ -338,7 +338,7 @@ class Stats: + # print(str(n) + "\t" + str(x)) + + def analyze_distances(self, celltype): +- ds = [v[0] for v in self.data.eject_distlogs[celltype]] ++ ds = [v[1] for v in self.data.eject_distlogs[celltype]] + + try: + mean, stddev = fit_gaussian(ds) + +we get this: + +split cell eject/split distances: mean = 560.4528176561469, stddev=276.25260008531626, ndata=314 + 75% of the values lie in the interval 556.62 plusminus 322.76 + +ejected mass eject/split distances: mean = 767.2502438544719, stddev=168.80422060053823, ndata=252 + 75% of the values lie in the interval 732.30 plusminus 86.28 + + +As one can see, the "plusminus" values are much larger than above. So measuring between "spawnpoint" and +"endpoint" is more appropriate. + diff --git a/reversing_game_mechanics/stuff.txt b/reversing_game_mechanics/stuff.txt new file mode 100644 index 0000000..fbbddc4 --- /dev/null +++ b/reversing_game_mechanics/stuff.txt @@ -0,0 +1,117 @@ +as of 2015-08-30 + +CELL SIZE VS SPEED + + size**0.45 * speed = 86.05616001328154 + + + + +SIZE VS VIEWPORT + + with 1 cells, depending on sum(size) + median ratio = 1.7025611175785798 + diag / size**0.33 = 608.971483054539 + + with 2 cells, depending on sum(size) + median ratio = 1.6963503649635037 + diag / size**0.33 = 585.5509541758322 + + with 3 cells, depending on sum(size) + median ratio = 1.6898326898326899 + diag / size**0.58 = 170.29929514108093 + + with 4 cells, depending on sum(size) + median ratio = 1.650784427658338 + diag / size**0.0 = 3158.567553889486 + + with 1 cells, depending on sum(mass) + median ratio = 1.7025611175785798 + diag / size**0.17 = 1270.6199859482824 + + with 2 cells, depending on sum(mass) + median ratio = 1.6972934472934473 + diag / size**0.16 = 1407.4522241811242 + + with 3 cells, depending on sum(mass) + median ratio = 1.6975546975546976 + diag / size**0.28 = 910.623966202271 + + with 4 cells, depending on sum(mass) + median ratio = 1.6625734116390818 + diag / size**0.0 = 3141.1700855829763 + + + + +EJECT/SPLIT DIRECTIONS + + split cell eject/split direction deviations: mean = 0.0009390500296252917, stddev=0.31212271930689983, ndata=621 + 75% of the splits had a deviation smaller than 0.02 rad = 1.19 deg + + ejected mass eject/split direction deviations: mean = -0.021378484138331356, stddev=0.730695490707546, ndata=1585 + 75% of the splits had a deviation smaller than 0.39 rad = 22.16 deg + + virus eject/split direction deviations: mean = -0.16497762078310707, stddev=0.07294211158929148, ndata=5 + 75% of the splits had a deviation smaller than 0.25 rad = 14.41 deg + (wrt "emitted mass begin -- parent virus") + + virus2 eject/split direction deviations: mean = -0.001211356391619578, stddev=0.0038334565337591105, ndata=5 + 75% of the splits had a deviation smaller than 0.00 rad = 0.11 deg + (wrt "emitted mass flight direction") + + virus3 eject/split direction deviations: mean = -0.13739240722341658, stddev=0.056773374975376475, ndata=5 + 75% of the splits had a deviation smaller than 0.21 rad = 11.82 deg + (wrt "emitter of the mass -- parent virus") + + + + +EJECT/SPLIT DISTANCES + + split cell eject/split distances: mean = 378.6264099585539, stddev =214.15995855502896, ndata=1226 + split cell meann = 23.37846655791191, stddevn =17.23260859398865 + 75% of the distances lie in the interval 370.30 plusminus 218.60 + 80% of the distances lie in the interval 370.30 plusminus 262.32 + max = 1205.46 + 75% of the flight lengths lie in the interval 20.00 plusminus 9.00 + 78% of the flight lengths lie in the interval 20.00 plusminus 10.80 + + ejected mass eject/split distances: mean = 473.3307839719213, stddev =159.4625848157587, ndata=1121 + ejected mass meann = 42.015165031222125, stddevn =8.5656796143937 + 75% of the distances lie in the interval 534.64 plusminus 2.10 + 77% of the distances lie in the interval 534.64 plusminus 2.52 + max = 637.28 + 75% of the flight lengths lie in the interval 44.00 plusminus 1.00 + 79% of the flight lengths lie in the interval 44.00 plusminus 1.20 + + virus eject/split distances: mean = 396.47928995805, stddev =219.79929069475193, ndata=9 + virus meann = 42.666666666666664, stddevn =6.879922480183431 + 75% of the distances lie in the interval 510.53 plusminus 363.80 + 88% of the distances lie in the interval 510.53 plusminus 436.56 + max = 580.08 (ndata = 13) + 75% of the flight lengths lie in the interval 45.00 plusminus 10.00 + 77% of the flight lengths lie in the interval 45.00 plusminus 12.00 + + + + +VIRUS SIZES + + I've seen the following 7 virus sizes: + 100: 386018 times + 106: 124015 times + 113: 72084 times + 119: 41825 times + 125: 24954 times + 131: 373398 times + 136: 11550 times + + + + +REMERGES + + 75% of the remerge durations lie at 32.00 plusminus 30.00 frames + 75% of the remerges were started after 767.00 plusminus 20.00 frames + diff --git a/reversing_game_mechanics/zoomlevel/README b/reversing_game_mechanics/zoomlevel/README new file mode 100644 index 0000000..a2acc90 --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/README @@ -0,0 +1,32 @@ +The goal is to find out the formula to calculate the appropriate zoom level, +or equivalent: to calculate the size of the world viewport depending on, well, +dunno. + +Data collected using bea9a124317, on 2015-08-25 *iirc*. (-> stats.pickle.xz) + +Data analyzed using ea4515d0516, with: + + python analyze.py stats.pickle > temp + +then manually, create win.{size,mass}.{1,2,3,4,5,6} by cutting the +analyze.py output into pieces (depending on number of cells). + +view with + + gnuplot win.{size,mass}.gnuplot + +the gray lines in win.size.gnuplot denote the filtering conditions of +filter_data.py + +Then merge and filter the data using + + cat win.size.[123456] | python filter_data.py > win.size.all.filtered + +win.size.gnuplot will automatically fit a "a * size**b" - like function. + +Result: visible diagonal = 369.399 * sum(sizes)**0.431776 + +Also, analyze.py tells us that the viewport ratio is 1.7 : 1 + +Additionally, if size<70, then the value 70 instead of "size" is used (found +out by tinkering around manually) diff --git a/reversing_game_mechanics/zoomlevel/filter_data.py b/reversing_game_mechanics/zoomlevel/filter_data.py new file mode 100644 index 0000000..e801d78 --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/filter_data.py @@ -0,0 +1,10 @@ +import sys + +for line in sys.stdin: + line = line.split() + size, diag = int(line[0]), float(line[1]) + upper = size**0.4 * 460 + 50 + lower = size**0.407 * 460 - 400 + if lower < diag and diag < upper: + print(str(size) + "\t" + str(diag) + "\t\t" + line[2]) + diff --git a/reversing_game_mechanics/zoomlevel/stats.pickle.xz b/reversing_game_mechanics/zoomlevel/stats.pickle.xz Binary files differnew file mode 100644 index 0000000..c915674 --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/stats.pickle.xz diff --git a/reversing_game_mechanics/zoomlevel/win.mass.1 b/reversing_game_mechanics/zoomlevel/win.mass.1 new file mode 100644 index 0000000..1bac0fb --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.mass.1 @@ -0,0 +1,116 @@ +0.0 9957.478596512272 16 +24.01 2120.5192760265113 245 +25.0 1969.829688069504 88 +26.01 1907.5106814904077 196 +27.04 1652.2645066695586 49 +28.09 1860.7818249327352 96 +29.16 1851.8933554608375 58 +30.25 1468.638825579659 70 +31.36 2251.943604977709 106 +32.49 2004.575765592311 166 +33.64 2109.127781809343 362 +34.81 2126.4564420650613 137 +36.0 1994.1740144731602 91 +37.21 2173.5730951592127 58 +38.44 1940.5630626186824 52 +39.69 2232.8013794334684 39 +40.96 2133.3471353720192 71 +42.25 2239.5713875650404 100 +43.56 2259.5827048373335 868 +44.89 2240.224319125208 818 +46.24 2307.553032976707 443 +47.61 2226.5634956138124 579 +49.0 2356.425258734085 336 +50.41 2293.2538019155227 397 +51.84 2249.2098612623945 273 +53.29 2331.4519081465096 451 +54.76 2392.639755583778 300 +56.25 2404.2996901384818 277 +57.76 2403.8011565019265 161 +59.29 2357.5313359529287 262 +60.84 2377.4242364374095 157 +62.41 2339.8472172344927 145 +64.0 2438.0258407162137 228 +65.61 2488.3331770484433 301 +67.24 2489.7003835803216 352 +68.89 2499.0544211761376 291 +70.56 2455.6426857342253 304 +72.25 2498.9455776386967 154 +73.96 2378.6727391551785 346 +75.69 2474.5797623030867 702 +77.44 2366.7634017788937 727 +79.21 2442.546417163858 373 +81.0 2515.553616999646 238 +82.81 2614.3163542310635 207 +84.64 2594.101771326638 66 +86.49 2544.643000501249 67 +88.36 2651.225377066235 95 +90.25 2681.96290056369 148 +92.16 2685.0344504307577 170 +94.09 2679.5546271722096 426 +96.04 2693.4938277263605 569 +98.01 2726.821592990638 54 +100.0 2696.036349903317 53 +102.01 2704.8558187082726 56 +104.04 2754.743726737571 88 +106.09 2719.114010114324 180 +108.16 2791.1581825471662 122 +110.25 2794.8023185907086 84 +112.36 2803.209767391659 133 +114.49 2805.824121358999 90 +116.64 2796.2517769328283 250 +118.81 2803.5384784232942 261 +121.0 2837.5144052497776 142 +123.21 2835.092414719492 107 +125.44 2846.737255174773 63 +127.69 2877.452345391666 63 +129.96 2851.5078467365297 53 +132.25 2780.2778638114573 113 +134.56 2891.1260781916794 242 +136.89 2870.733878296628 69 +139.24 2892.3390188565377 88 +141.61 2730.286798122131 145 +144.0 2715.363695713707 389 +146.41 2238.8311682661556 281 +148.84 2913.41998345587 61 +151.29 2955.795155283938 28 +153.76 2385.1079640133694 322 +156.25 3029.202205201891 67 +158.76 3015.162516349658 39 +161.29 3024.4353191959653 64 +163.84 3046.6238691377707 139 +166.41 3020.514029101669 40 +169.0 3015.3225366451265 112 +171.61 3021.6586504765887 92 +174.24 3040.8763539479864 73 +176.89 3065.0941257977706 58 +179.56 2976.10500486794 66 +182.25 3026.624522467232 98 +184.96 3013.2540550043236 84 +187.69 2927.263910206936 80 +190.44 2981.869380103696 80 +193.21 2977.177354475208 52 +196.0 3049.6730972351775 42 +198.81 2354.0403564934904 65 +201.64 2332.625130620006 4 +219.04 3144.616033794905 7 +222.01 3228.400223020684 11 +225.0 3220.1863300125974 71 +228.01 3248.3468103021264 119 +231.04 3253.712494981694 66 +234.09 3238.846245192877 57 +237.16 3176.819950831334 43 +240.25 3301.4617974467005 36 +243.36 3296.8477368541 132 +246.49 3316.3596005258537 113 +249.64 3286.2537942161434 155 +252.81 3083.007946794818 110 +256.0 2909.176000175995 64 +259.21 2641.6837433727756 35 +262.44 2646.5972492995606 65 +265.69 2727.742106578259 49 +268.96 2692.4384858339845 44 +272.25 2498.7140692764347 49 +275.56 2352.3938870860893 36 +278.89 2375.1743093928917 57 +282.24 2304.796954180563 121 diff --git a/reversing_game_mechanics/zoomlevel/win.mass.2 b/reversing_game_mechanics/zoomlevel/win.mass.2 new file mode 100644 index 0000000..8c08b58 --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.mass.2 @@ -0,0 +1,455 @@ +40.5 2459.633306003153 36 +40.96 7513.947364734464 1 +41.41 2471.8181567421175 53 +42.34 2602.3854441646417 92 +43.25 2635.398451847462 1 +43.29 2641.4407053727327 15 +43.56 8967.320224013414 2 +44.18 2311.2580989582275 2 +44.2 2693.2903668189956 8 +44.260000000000005 2490.116463139827 12 +45.129999999999995 2369.7818464997995 3 +45.17 2718.7594597536577 30 +45.25 2628.344345781199 17 +46.08 2604.0188171363125 7 +46.1 2714.2109350601327 145 +46.16 2705.3711390491326 30 +46.24 9047.885167264227 3 +46.260000000000005 2529.635546872316 4 +47.05 2559.953905835025 100 +47.09 2748.116627801666 7 +47.29 2672.3012554725187 14 +48.04 2696.738771182704 64 +48.2 2656.4521452493736 2 +49.010000000000005 2747.4096891435756 35 +49.05 1728.9814920929605 28 +49.129999999999995 2674.728023556788 33 +50.0 2718.0345840331024 25 +50.02 1517.5836056046467 115 +50.18 2718.969290006785 29 +50.41 5962.59423405618 1 +51.010000000000005 2762.8052772499186 111 +51.25 2680.7913010900347 24 +52.02 2694.0736812492714 74 +52.04 2728.1513887612614 26 +52.2 2111.7618236912986 65 +52.34 2760.7872065771385 4 +53.05 2689.30344141378 18 +53.09 2777.4263266556686 37 +53.29 2745.1777720213313 68 +54.08 2724.0163362212056 132 +54.1 2821.2488369514663 28 +54.16 2788.0634856473407 51 +54.4 2800.803456153252 243 +54.76 9453.725720582335 1 +55.129999999999995 2814.639586163742 45 +55.17 2818.2379246614364 28 +55.25 2750.93911237599 213 +55.370000000000005 2803.9293857014304 140 +55.53 2788.3961339809666 16 +56.18 2337.0556262100395 51 +56.2 2843.388295678239 34 +56.25 9562.746467411964 1 +56.260000000000005 2824.395333518309 23 +56.36 2756.9746099665117 22 +56.68 2844.9411241711136 10 +57.25 2762.5328957317415 12 +57.29 2829.027394706527 12 +57.370000000000005 2757.496328193385 54 +57.49 2056.103110254931 16 +57.650000000000006 2840.9859204156573 76 +58.34 2798.28965620073 189 +58.5 2573.206948537175 148 +58.82000000000001 2401.801199100375 7 +59.41 2654.4522975559385 20 +59.45 2790.700270541428 8 +59.53 2643.41162137114 5 +59.650000000000006 2746.3783424721364 20 +59.81 2307.9033775268845 17 +60.5 2822.01009920234 2 +60.519999999999996 2569.880347409194 21 +60.68 2517.190894628375 44 +60.82000000000001 2588.53163009456 46 +60.84 4983.02087091756 1 +61.61 2886.1119174418723 20 +61.650000000000006 2569.880347409194 15 +61.85 2246.855580583674 57 +62.010000000000005 2406.397514958823 14 +62.120000000000005 2831.1287501630864 138 +62.72 2905.0335626288384 16 +62.8 2513.3963077875324 18 +63.04 1903.5934439895511 3 +63.05 2840.752893160544 44 +63.22 2224.2942701000693 34 +63.7 2887.0635600900787 158 +63.81 2721.133771059409 9 +63.85 2906.4015551881334 10 +63.97 2513.3963077875324 8 +64.0 2783.724483493293 31 +64.25 2190.683226758264 40 +64.45 2511.4816344142355 32 +64.97 2819.3029280302603 91 +65.0 2905.691828119424 50 +65.16 2769.544727929123 26 +65.3 2769.2159540201988 110 +65.7 2169.302652927894 1 +66.13 2917.1830590485747 32 +66.17 1978.7786637216402 36 +66.37 2866.9461104108673 26 +66.53 2828.3638379812455 176 +66.97 2169.302652927894 2 +67.28 2914.5826459374935 4 +67.30000000000001 1456.4751971798216 33 +67.6 2892.723630075988 18 +68.26 2169.302652927894 1 +68.45 2870.029442357691 68 +68.49000000000001 1493.238427043719 9 +68.56 3071.149133467797 1 +68.85 2876.960201323612 40 +68.89 8841.674502038626 2 +69.62 2759.3203873417815 37 +69.64 2934.570667065286 37 +69.7 1503.1999201703013 20 +70.12 2944.063178669914 15 +70.56 6246.4982190023875 1 +70.81 2861.632051819381 66 +70.85 2948.546930269213 16 +70.93 1951.1483798009826 158 +71.21000000000001 2883.3539498299547 18 +72.0 2895.3979001166663 37 +72.02000000000001 2944.6481963046112 6 +72.08 2900.384802056444 30 +72.18 2046.8927670984624 2 +72.32 2937.0192372539886 65 +73.21000000000001 2890.895017118401 34 +73.25 2878.285079695894 36 +73.45 2660.3768530041 49 +74.42 2244.9518925803286 5 +74.44 2922.8884686214083 47 +74.6 2709.7276615925816 7 +74.74000000000001 2194.8769897194693 16 +75.65 2959.984628338465 37 +75.69 2994.2386344444894 15 +75.77000000000001 2779.7426139842514 10 +76.05000000000001 2211.8340805765697 4 +76.88 2980.0191274553927 13 +76.9 2640.6423460968736 21 +76.96000000000001 3009.2705096085997 39 +77.12 2918.4278301852864 123 +77.38 2188.1373357264392 6 +77.6 2235.5270072177614 9 +78.00999999999999 2934.982112381607 84 +78.13 2953.3900859859336 45 +78.17 2975.29695996887 29 +78.73 2162.7568055609026 8 +78.97 2329.121937555009 16 +79.21 9939.87610586772 1 +79.38 2913.7070889161114 56 +79.4 3010.1975018260846 33 +79.46000000000001 2199.218497557712 8 +79.53999999999999 2982.9921220144047 45 +80.1 2333.552227827781 6 +80.45 2793.836072499602 9 +80.65 2684.162811753415 43 +80.69 2939.1537897837193 6 +81.25 2526.8612941750484 23 +81.92 3014.607768848213 4 +81.94 2141.8881856903736 105 +82.0 2930.1754213698537 36 +82.42 2628.9505510754666 21 +82.81 6944.246107389916 1 +82.93 2891.7330443870505 17 +83.21000000000001 2881.0282886497316 60 +83.25 2973.785466371103 36 +83.3 2722.2448457109804 21 +83.81 2954.6356797412436 40 +83.88 2832.668000313485 2 +84.5 3021.231536972961 13 +84.52000000000001 2897.546720934798 92 +84.58 3001.166606504877 12 +84.85000000000001 2906.164654660847 113 +85.0 3019.600139091267 2 +85.00999999999999 2457.3501988931084 1 +85.81 3025.457651331448 112 +85.93 3023.894178042611 27 +86.05 2289.4422901658822 17 +86.21000000000001 3080.046265886277 21 +86.42 2991.139080684815 148 +87.12 2650.2371591991537 58 +87.14 3061.160890903972 40 +87.2 2986.7247948212434 14 +87.3 2296.176386952884 65 +87.41 2866.022505145415 36 +88.01 2712.7950530771764 36 +88.45 3071.8894836891513 42 +88.49000000000001 3028.9313296936925 21 +88.57 3061.068114237251 33 +88.69 3102.4778806624877 32 +89.78 3057.227829259704 10 +89.80000000000001 3014.607768848213 61 +89.86 2269.5003855474447 32 +89.96000000000001 3097.339826367136 48 +91.13 2865.656120332654 23 +91.17 3106.295060035347 30 +91.25 3075.8616678908043 57 +91.37 3118.5017235845808 22 +92.48 2388.5782381994522 258 +92.56 3017.995692508523 37 +92.66 3129.7420021465027 8 +92.80000000000001 3128.0374038684386 8 +92.97999999999999 3120.59817983668 1 +93.85 2621.0017169013836 65 +93.89 3152.9827148273425 16 +93.97 3112.9114989025948 81 +94.09 9051.577210630201 1 +94.25 3144.593614443685 7 +94.44999999999999 3136.026307287616 39 +95.22 2358.5930127938564 67 +95.24000000000001 2628.2302030073392 75 +95.3 3157.6879199819605 6 +95.4 3069.05881338237 46 +95.72 3148.735619260531 4 +96.61 3138.517643729281 30 +96.65 3154.2341384240963 35 +96.73 3104.341637126945 3 +96.85 2934.527219161547 16 +97.00999999999999 3145.1621579816833 4 +98.0 3169.7397369500227 12 +98.02 3173.4405619138356 51 +98.08000000000001 2803.5762875299115 29 +98.18 3156.589456993101 6 +98.32 2872.565578015583 43 +99.41 3167.053520229805 51 +99.53 2792.167616745098 19 +99.65 3192.3842187305713 50 +99.81 2941.8161057414854 13 +100.82 3106.0143270757785 4 +100.84 3196.712842905975 42 +101.0 2792.6850878679465 45 +101.14 3075.295758134492 67 +101.32 2934.527219161547 73 +102.25 3169.335577057122 11 +102.28999999999999 3064.378077196089 1 +102.37 2867.3070990042206 13 +102.49000000000001 2972.5687544613666 78 +102.65 2899.1883346895556 9 +103.69999999999999 3107.673084479769 14 +103.75999999999999 3107.5662502994205 20 +103.86 3207.86486623112 147 +104.89 3004.323051870421 19 +105.16999999999999 3062.840674929076 13 +105.25 3115.385208926819 37 +105.37 3124.894398215722 47 +105.85 2480.4487497225173 1 +106.58 2407.431203586096 4 +106.6 3050.954276943527 19 +106.66 3204.720580643498 57 +106.9 2971.6609833559414 9 +107.68 2869.1868185951225 90 +108.05 2715.207542711975 40 +108.09 3034.582837887277 35 +108.16 8923.322083170595 1 +108.16999999999999 3132.7657109972333 42 +108.45 3206.7556813701913 41 +108.65 2434.9080064758095 21 +109.52 2983.3921968122127 42 +109.53999999999999 3021.7852339304327 68 +109.6 3228.6035681080452 52 +109.69999999999999 2382.238443145438 26 +110.02 3201.5621187164243 16 +110.65 2278.747462971709 143 +111.00999999999999 3198.4935516583428 24 +111.13 3270.7872141122234 2 +111.25 2250.734324614969 1 +111.41 2266.3973614527526 19 +111.61 3248.176873262908 16 +112.5 3209.6263022351995 52 +112.52 3236.8775077225273 21 +112.58 3265.214388060913 9 +112.68 3261.2028455770733 27 +112.82 2247.8979069343873 12 +113.0 3248.630788501519 44 +114.00999999999999 3246.263698469365 7 +114.05 3283.7113149605584 11 +114.13 3138.9547623372973 9 +114.25 3212.693107036525 19 +114.61 3167.6016163652903 14 +115.53999999999999 3279.512158843141 30 +115.69999999999999 3252.1334535962696 27 +116.02 3175.914986267737 15 +117.09 3308.273416753821 12 +117.16999999999999 3253.6510261550793 13 +117.28999999999999 3282.2183047445214 52 +117.45 3194.5548985735086 48 +118.58 3271.134359820764 28 +118.6 3166.3411060718017 2 +118.66 3274.657997409806 12 +118.75999999999999 3276.1114144668522 71 +118.81 8069.929987304723 2 +118.9 3058.5586474677907 6 +119.08 3124.7374289690324 33 +120.13 3299.07865926231 7 +120.25 3283.969549188908 169 +120.37 3282.865364281636 18 +120.53 3209.4538476195603 85 +121.75999999999999 3202.652026055906 19 +122.0 3247.845439672276 63 +123.28999999999999 2896.068024062971 10 +123.49 3257.744618597351 2 +123.65 3335.6368207585188 17 +124.82 3061.1470072507136 3 +124.84 2652.874101799782 137 +125.32 3291.808317627258 3 +125.44 7472.861366304074 1 +126.41 3291.879098630446 96 +126.45 2954.865309959153 30 +126.81 3347.0017926496544 16 +128.0 2969.6642907911323 30 +128.01999999999998 3156.169355405378 113 +128.5 3339.6354591481986 10 +129.61 3133.040216786245 36 +130.01 3337.7336622325033 8 +131.22 3179.471811480643 3 +131.24 3020.9197275002193 42 +131.72 3079.234482789513 4 +132.25 5694.3046107492355 1 +132.85 3265.6763464862834 6 +132.89 2765.289315785963 54 +133.25 3299.167319188283 1 +133.45 3240.6210824470054 39 +134.5 3285.5763573534555 75 +135.2 3389.542299485286 8 +135.49 2913.1991006451995 84 +136.17000000000002 3337.108329077736 61 +136.97 3390.6201497661164 15 +137.86 2278.6425783786276 15 +138.5 3412.359887233467 24 +139.49 2278.6425783786276 7 +139.57 3314.6464366505215 12 +140.05 3394.3603226528558 10 +141.2 2268.637696945019 37 +141.3 3211.592906954429 16 +141.62 3412.2980526325655 9 +142.93 2764.389625215664 104 +143.20999999999998 3397.420492079248 31 +144.57999999999998 3046.709700644287 25 +144.82 3239.8902759198495 12 +145.0 3390.017846560693 4 +146.20999999999998 3388.321118194083 1 +146.25 3230.394712724747 5 +146.41 6656.233319227925 1 +146.45 3202.770831639379 19 +147.65 3406.1809993011234 1 +147.92 2490.0461843106445 65 +147.94 3282.4850342385416 38 +148.1 3091.0713353140204 13 +148.84 8177.841524509998 1 +149.64999999999998 3420.9264826944177 59 +149.89 2971.110398487407 7 +151.38 3450.2268041391135 48 +151.39999999999998 3435.114699686169 27 +151.56 2916.207468613987 33 +153.13 3376.8393506354428 53 +153.25 2747.6792025271075 6 +154.89999999999998 3029.6093807618167 19 +156.64999999999998 3184.1678661779124 13 +156.69 2963.002024973996 6 +158.44 3278.1976755528335 43 +158.5 2984.3982643072286 41 +160.32999999999998 2929.2353951159334 19 +161.3 3395.699927849927 140 +162.18 2900.2127508167396 26 +164.05 2828.9547539683276 18 +165.94 2834.0869781995048 17 +167.85 2761.479675825987 42 +169.78 2820.7943916563645 30 +182.25 9562.855274446016 1 +182.41 3317.3273881243617 4 +184.34 3322.925969683947 1 +186.29000000000002 3360.9024085801716 3 +188.26 3392.7009888877624 14 +192.08 3491.7183448840774 81 +192.16 3420.003654968807 17 +193.21 9577.942211143269 1 +194.05 3640.672602693079 29 +194.09 3480.2909361143934 84 +198.01 3485.7327780539918 20 +198.25 2896.212181453562 2 +200.0 3494.622726418404 38 +200.18 2942.880901429754 38 +201.64 9784.782930653086 1 +202.01 3437.9077939933177 13 +202.25 2967.623291457324 18 +204.04000000000002 3296.5171014268985 26 +204.2 2866.873035207524 20 +204.34 2955.8289869341224 7 +206.09 3148.6176331844426 31 +206.17000000000002 2744.5052377432257 80 +208.16 3158.060955713173 41 +208.26 2737.0440259520856 26 +210.17000000000002 2736.23335993113 43 +210.25 2968.037904070634 10 +212.26 2868.054567123854 99 +212.36 2936.9548855915373 9 +214.29000000000002 3114.007867684345 21 +214.49 2857.8037021461078 22 +216.4 3288.7281736257864 22 +216.64 2758.698424982332 10 +218.53 3553.019701605945 81 +218.81 2711.7280468365557 27 +220.68 3634.7426318791818 43 +221.0 2744.636952312637 21 +221.22 2778.7531376500506 16 +222.73000000000002 3435.003639008262 25 +223.20999999999998 2813.6142237343056 32 +225.44 2884.218091615126 33 +227.45 2920.3643608289703 13 +229.48000000000002 2901.059806346639 1 +229.7 2872.4863794281077 1 +231.04 4566.623698094688 1 +231.13 3745.4198696541353 4 +231.97000000000003 2805.2536427211 23 +233.3 3798.324367402026 6 +234.26 2917.5335473649657 54 +235.49 3780.4034176262194 43 +236.29000000000002 3127.261581639758 26 +237.7 3790.5283272915926 21 +238.34 3509.404507890192 65 +239.93 3780.8000476089715 23 +240.41 3691.2167370665193 62 +242.18 3810.5668869605215 12 +242.5 3690.6977660057723 7 +242.72 3783.2076337415056 103 +244.45 3796.823145736446 88 +244.61 3815.123720143293 18 +245.04999999999998 3808.475941895918 66 +246.74 3792.3610060225014 23 +248.89 3815.631009413777 26 +249.64 7526.270258235482 1 +250.88 3824.0011767780616 2 +251.06 3777.8631526300683 14 +253.13 3826.4825884877614 43 +253.25 3750.3314520186077 26 +255.38 3834.963624338567 11 +255.45999999999998 3795.2923471058193 13 +257.65 3861.3113057612954 13 +257.69 3831.301214992108 83 +259.88 3807.41697217418 30 +259.94 3846.839351987551 55 +260.0 3830.0822445477593 38 +262.25 3857.996630376963 115 +262.33 3867.2832841673235 26 +262.45 3831.658257204053 60 +264.42 3542.066346075409 27 +264.52 3801.982772186113 32 +264.68 3832.571069138836 36 +264.82 3437.7121752700587 18 +266.81 3789.4339946751943 30 +267.05 3784.653220573848 128 +269.12 3747.1441125208944 93 +269.44 3049.4078113627243 51 +269.62 2788.9302608706444 40 +271.85 2863.6000069842157 18 +272.05 2737.5529218628817 19 +278.48 2678.195287875774 32 +278.89 9754.961199307765 1 diff --git a/reversing_game_mechanics/zoomlevel/win.mass.3 b/reversing_game_mechanics/zoomlevel/win.mass.3 new file mode 100644 index 0000000..ba343eb --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.mass.3 @@ -0,0 +1,126 @@ +60.769999999999996 2830.58244889634 7 +65.46000000000001 3420.4585949840116 1 +66.53 7887.098642720275 1 +66.81 2838.9575551599924 6 +67.7 3143.764145097402 42 +68.26 9958.89833264704 1 +68.33 2134.831609284442 24 +68.59 3184.6464481948383 18 +69.26 1980.0426763077608 8 +69.66 3112.852389690202 14 +70.17 1914.7461972804647 7 +70.75 3137.9294128453557 3 +71.10000000000001 1793.7293552818942 4 +71.18 1948.351354350647 3 +71.86 3120.9783722416278 17 +72.99000000000001 3145.5927899205262 21 +73.14 1833.039006677163 12 +73.9 3145.5927899205262 4 +74.13 1833.8105136572863 8 +74.83 3056.016361212747 21 +75.14 1914.4221060152852 8 +75.78 2881.213980252074 7 +76.16999999999999 1943.2395632036726 13 +76.75 2829.041180329477 6 +76.96000000000001 5461.392679527814 1 +77.14 2411.4835682624916 11 +77.22 2287.895102490497 30 +77.9 2809.5213115404554 26 +78.0 3147.2827963181194 58 +78.17 2468.258090232867 21 +79.24 2355.969651757 20 +79.4 8508.168428046074 1 +80.21 2702.4124407647328 32 +81.2 2982.131452501717 24 +82.25 3122.2384598233366 19 +83.32 3265.692269642074 28 +84.33 3261.3567728784287 5 +84.97 3468.918707609044 1 +85.42 3261.3567728784287 5 +86.45 3274.0054978573266 11 +87.53999999999999 3332.2054258403696 15 +88.65 3361.016661666526 3 +89.78 3355.109089135553 14 +90.83 3373.971102425153 20 +91.98 3259.075482402947 7 +93.05 3265.9854561831717 10 +95.31 3411.079741079062 17 +96.38 2931.623611584543 7 +96.42 3402.4616088943603 17 +96.75999999999999 3406.882592635091 13 +97.61 3376.63575175055 7 +97.85 3455.7640255086862 3 +98.74000000000001 3323.912303295621 14 +98.94 3456.7860795831725 45 +99.65 6587.192725281385 1 +99.89 3373.551392820332 8 +101.06 3336.6609057559326 7 +101.14 7665.473892721832 1 +103.30000000000001 3425.875800434102 11 +104.45 3329.9831831407196 10 +104.75 3409.622413112631 38 +104.89 4313.037096988617 1 +105.30000000000001 3410.078298221318 28 +105.62 3299.869694397038 6 +105.66 3416.254235269969 37 +105.69999999999999 3447.78842158274 23 +106.59 3479.379973501026 105 +106.61000000000001 3463.3119986510023 47 +106.81 3258.0682927157927 5 +106.85000000000001 3271.244564382186 8 +106.97 3457.1297343316464 86 +107.00999999999999 3471.528913893704 33 +107.9 3448.322055725074 8 +107.94 3347.817946065765 4 +108.02000000000001 3247.0983970308016 1 +108.06 3240.0327158842083 8 +108.36000000000001 3461.478441359992 20 +109.29 3211.9752489706393 6 +110.51 2842.601801167374 8 +110.81 3206.3019196575983 20 +111.41 9875.263895208067 1 +111.82000000000001 3040.0726964992136 77 +112.04999999999998 2418.4798944791746 26 +112.5 7247.468592550091 1 +113.04 3227.447288492873 11 +115.4 3130.8784709726438 1 +116.61000000000001 3295.738460497131 2 +117.84 3356.7450007410453 26 +118.6 7029.594867415903 1 +119.09 3271.6653251822686 40 +119.13 3291.6629535844036 39 +120.38 3236.8164915546263 19 +121.63 3177.624899197512 3 +122.9 3060.851025450275 21 +122.99 3527.7692668313784 35 +123.49 7155.990497478319 1 +124.14 3476.978573416868 10 +124.19 2975.672697055239 40 +124.73 2989.411982313579 27 +125.5 3051.0473611532157 4 +125.9 2898.4592458752977 3 +126.41 7350.145372712025 1 +126.83 3049.9652457036295 25 +127.01 2860.5029278083252 25 +128.2 2748.142099673887 18 +129.41 2691.989970263634 1 +130.98 2670.9842755059417 25 +134.3 2809.3913931668544 10 +135.17000000000002 2945.6654596202875 13 +136.98000000000002 2946.8554426710516 4 +137.87 3046.0080433249022 11 +139.7 3122.5574454283465 14 +139.71 3321.6188824126107 59 +140.37 3465.600669436685 28 +140.61 3162.9835598687514 22 +141.32 3303.806289720994 4 +141.54000000000002 3590.769416155819 43 +141.63 3137.2424197055607 2 +142.49 3182.529968437061 1 +143.46 3185.424932406978 15 +168.81 2838.9635432671553 12 +202.01 9721.27075026717 1 +216.49 3464.951947718756 23 +216.91000000000003 3738.3038934789665 3 +218.3 3524.6476419636615 4 +264.42 9773.704773523703 1 diff --git a/reversing_game_mechanics/zoomlevel/win.mass.4 b/reversing_game_mechanics/zoomlevel/win.mass.4 new file mode 100644 index 0000000..aa0de62 --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.mass.4 @@ -0,0 +1,130 @@ +75.78 3431.546152975361 6 +76.63 3497.8764986774477 14 +76.96000000000001 5461.392679527814 1 +77.5 3311.0096647397454 23 +78.35 3389.6768282536905 36 +79.24 3468.8963662813567 13 +79.4 8508.168428046074 1 +80.13 3486.8789769649306 21 +80.14999999999999 3507.4472198452254 16 +81.03999999999999 3426.4974828533 11 +81.08 3490.3886603070437 102 +81.93 3354.6057890607653 35 +82.03 3519.1081256477473 63 +82.86 3395.7847399386196 11 +83.0 3404.603501143709 4 +83.87 3419.91418020979 18 +84.78 3187.2913265028033 64 +85.71000000000001 3413.126719007075 8 +85.77 3115.806476660577 49 +96.38999999999999 3615.2654121101536 87 +97.25999999999999 3652.2186407716613 3 +97.47999999999999 3627.734279133465 58 +98.26 3649.020964587625 1 +98.36999999999999 3593.768078215399 9 +98.58999999999999 3627.231726813163 147 +98.94 5135.193180397404 1 +99.21000000000001 3664.0061408245483 74 +99.24 3584.0772871131003 3 +99.65 6587.192725281385 1 +100.13 3584.0772871131003 2 +100.18 3573.493808585654 1 +100.38 2493.193935497197 1 +101.02 3677.116261420082 10 +101.14 7665.473892721832 1 +101.17 3670.228875696991 45 +101.32999999999998 2823.253796597111 33 +101.42999999999999 2493.193935497197 53 +102.12 3707.9920442201596 9 +102.15 3654.805603585504 14 +102.26 2755.466203748469 1 +103.06 3683.1563909234155 43 +103.09 3675.8706451669377 16 +103.33 2441.627530971913 36 +103.99000000000001 3684.5929218843157 4 +105.09 3716.556605246313 8 +106.10000000000001 3684.0620244507286 15 +107.13 3732.4611183507322 7 +107.15 3715.699799499416 23 +109.23 3690.992549437075 16 +110.3 3509.5711988788603 21 +110.5 2476.2915821849415 5 +110.98 3468.918707609044 5 +111.32999999999998 3555.6774319389547 25 +111.41 9875.263895208067 1 +111.51 2465.023326461638 1 +112.41999999999999 3459.260036481791 17 +112.53999999999999 2540.530850039023 35 +113.52999999999999 3586.7179983935175 15 +114.66 3585.6561463698663 10 +115.80999999999999 3670.9509667114867 23 +115.85000000000001 3782.2038548973005 17 +116.86 3734.5910083970375 112 +116.88000000000001 3796.5963704349715 139 +116.97999999999999 3743.2312244904133 16 +117.92999999999999 3784.865915722775 12 +117.97 3800.631526470305 29 +118.03 3744.2478550437872 29 +118.6 7029.594867415903 1 +118.82 3733.0740683784993 1 +119.02 3689.460258628625 9 +119.91 3723.439404636525 3 +120.13 3625.2627490983327 4 +121.2 3526.8682992139074 20 +122.13 3630.5692391138887 8 +122.33 3313.4086678223075 20 +123.26 3661.392221546334 13 +123.46000000000001 3634.4388837893534 11 +123.49 7155.990497478319 1 +124.41 3814.323662197533 12 +124.57000000000001 3220.6027386189685 5 +124.63000000000001 3634.4388837893534 40 +125.53999999999999 3831.4364147144606 11 +125.60000000000001 3827.5533961004385 69 +126.41 7350.145372712025 1 +126.63000000000001 3590.791834679365 5 +126.71000000000001 3812.6926180850196 47 +126.77 3832.2616038052515 5 +126.77000000000001 3832.5211023554716 6 +126.83 9346.260482139367 1 +127.70000000000002 3814.195852338996 13 +127.72 3636.3681056790715 28 +127.80000000000001 3813.7278350716115 66 +127.86 3826.231827790888 3 +127.96000000000001 3856.772873789692 16 +128.85000000000002 3768.2490628938 180 +128.95 3838.2737005065183 19 +129.13 3854.4753209743085 28 +130.34 3835.5570651471216 1 +130.98 7269.414075425887 1 +131.57 3876.429542762257 43 +132.76 3793.3906996248093 27 +135.07 2951.3117422597024 5 +202.01 9721.27075026717 1 +204.5 3049.217932519747 3 +205.93 2999.563301549077 1 +207.38 2918.4139528175233 2 +208.85 2928.8649678672455 1 +210.34 2923.3942601024582 1 +211.79 2926.6731966517887 1 +213.29999999999998 2921.918034442445 3 +213.39999999999998 3027.5617252171755 7 +213.42 3092.014553652683 2 +214.82999999999998 3092.7083599977545 25 +214.86999999999998 3098.9601481787404 28 +216.29999999999998 3112.9012191201955 7 +216.35999999999999 2853.4514188960707 21 +217.86999999999998 2832.8236796525125 40 +219.29999999999998 2666.3600657075553 5 +220.82999999999998 2658.3432810681165 14 +222.27999999999997 2840.7354681490497 2 +223.74999999999997 2840.7354681490497 9 +225.17999999999998 2840.7354681490497 2 +226.63 2840.7354681490497 4 +228.1 2840.7354681490497 63 +264.42 9773.704773523703 1 +264.52 3771.882951524344 154 +265.45 3702.6188029555515 4 +266.39 3661.2525179233403 51 +267.3 3601.816902620121 2 +269.17 3550.685708423093 49 diff --git a/reversing_game_mechanics/zoomlevel/win.mass.5 b/reversing_game_mechanics/zoomlevel/win.mass.5 new file mode 100644 index 0000000..f4b686e --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.mass.5 @@ -0,0 +1,8 @@ +126.83 9346.260482139367 1 +129.32999999999998 3926.380139517823 7 +130.22 3995.193362028927 19 +130.98 7269.414075425887 1 +131.06 2999.2432378851836 13 +131.23000000000002 3979.0382003695313 11 +133.33999999999997 3046.871510254412 16 +134.51 3030.115674359644 1 diff --git a/reversing_game_mechanics/zoomlevel/win.mass.6 b/reversing_game_mechanics/zoomlevel/win.mass.6 new file mode 100644 index 0000000..7994d85 --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.mass.6 @@ -0,0 +1,4 @@ +126.83 9346.260482139367 1 +127.14 3564.1046561513876 2 +128.13 3713.46266980025 16 +129.01999999999998 3981.4374288691265 52 diff --git a/reversing_game_mechanics/zoomlevel/win.mass.gnuplot b/reversing_game_mechanics/zoomlevel/win.mass.gnuplot new file mode 100644 index 0000000..a948115 --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.mass.gnuplot @@ -0,0 +1,9 @@ +min(a,b)=(a<b)?a:b +max(a,b)=(a>b)?a:b +plot "win.mass.1" using 1:2:(min(1,$3/100)) lt rgb "red" pt 2 ps variable, \ + "win.mass.2" using 1:2:(min(1,$3/100)) lt rgb "blue" pt 2 ps variable, \ + "win.mass.3" using 1:2:(min(1,$3/100)) lt rgb "green" pt 2 ps variable, \ + "win.mass.4" using 1:2:(1) lt rgb "purple" pt 2 ps variable, \ + "win.mass.5" using 1:2:(1) lt rgb "cyan" pt 2 ps variable, \ + "win.mass.6" using 1:2:(1) lt rgb "orange" pt 2 ps variable +pause -1 diff --git a/reversing_game_mechanics/zoomlevel/win.size.1 b/reversing_game_mechanics/zoomlevel/win.size.1 new file mode 100644 index 0000000..8357f6a --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.size.1 @@ -0,0 +1,116 @@ +0 9957.478596512272 16 +49 2120.5192760265113 245 +50 1969.829688069504 88 +51 1907.5106814904077 196 +52 1652.2645066695586 49 +53 1860.7818249327352 96 +54 1851.8933554608375 58 +55 1468.638825579659 70 +56 2251.943604977709 106 +57 2004.575765592311 166 +58 2109.127781809343 362 +59 2126.4564420650613 137 +60 1994.1740144731602 91 +61 2173.5730951592127 58 +62 1940.5630626186824 52 +63 2232.8013794334684 39 +64 2133.3471353720192 71 +65 2239.5713875650404 100 +66 2259.5827048373335 868 +67 2240.224319125208 818 +68 2307.553032976707 443 +69 2226.5634956138124 579 +70 2356.425258734085 336 +71 2293.2538019155227 397 +72 2249.2098612623945 273 +73 2331.4519081465096 451 +74 2392.639755583778 300 +75 2404.2996901384818 277 +76 2403.8011565019265 161 +77 2357.5313359529287 262 +78 2377.4242364374095 157 +79 2339.8472172344927 145 +80 2438.0258407162137 228 +81 2488.3331770484433 301 +82 2489.7003835803216 352 +83 2499.0544211761376 291 +84 2455.6426857342253 304 +85 2498.9455776386967 154 +86 2378.6727391551785 346 +87 2474.5797623030867 702 +88 2366.7634017788937 727 +89 2442.546417163858 373 +90 2515.553616999646 238 +91 2614.3163542310635 207 +92 2594.101771326638 66 +93 2544.643000501249 67 +94 2651.225377066235 95 +95 2681.96290056369 148 +96 2685.0344504307577 170 +97 2679.5546271722096 426 +98 2693.4938277263605 569 +99 2726.821592990638 54 +100 2696.036349903317 53 +101 2704.8558187082726 56 +102 2754.743726737571 88 +103 2719.114010114324 180 +104 2791.1581825471662 122 +105 2794.8023185907086 84 +106 2803.209767391659 133 +107 2805.824121358999 90 +108 2796.2517769328283 250 +109 2803.5384784232942 261 +110 2837.5144052497776 142 +111 2835.092414719492 107 +112 2846.737255174773 63 +113 2877.452345391666 63 +114 2851.5078467365297 53 +115 2780.2778638114573 113 +116 2891.1260781916794 242 +117 2870.733878296628 69 +118 2892.3390188565377 88 +119 2730.286798122131 145 +120 2715.363695713707 389 +121 2238.8311682661556 281 +122 2913.41998345587 61 +123 2955.795155283938 28 +124 2385.1079640133694 322 +125 3029.202205201891 67 +126 3015.162516349658 39 +127 3024.4353191959653 64 +128 3046.6238691377707 139 +129 3020.514029101669 40 +130 3015.3225366451265 112 +131 3021.6586504765887 92 +132 3040.8763539479864 73 +133 3065.0941257977706 58 +134 2976.10500486794 66 +135 3026.624522467232 98 +136 3013.2540550043236 84 +137 2927.263910206936 80 +138 2981.869380103696 80 +139 2977.177354475208 52 +140 3049.6730972351775 42 +141 2354.0403564934904 65 +142 2332.625130620006 4 +148 3144.616033794905 7 +149 3228.400223020684 11 +150 3220.1863300125974 71 +151 3248.3468103021264 119 +152 3253.712494981694 66 +153 3238.846245192877 57 +154 3176.819950831334 43 +155 3301.4617974467005 36 +156 3296.8477368541 132 +157 3316.3596005258537 113 +158 3286.2537942161434 155 +159 3083.007946794818 110 +160 2909.176000175995 64 +161 2641.6837433727756 35 +162 2646.5972492995606 65 +163 2727.742106578259 49 +164 2692.4384858339845 44 +165 2498.7140692764347 49 +166 2352.3938870860893 36 +167 2375.1743093928917 57 +168 2304.796954180563 121 diff --git a/reversing_game_mechanics/zoomlevel/win.size.2 b/reversing_game_mechanics/zoomlevel/win.size.2 new file mode 100644 index 0000000..6168704 --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.size.2 @@ -0,0 +1,150 @@ +64 7513.947364734464 1 +66 8967.320224013414 2 +68 9047.885167264227 3 +71 5962.59423405618 1 +73 6812.90341924792 1 +74 9453.725720582335 1 +75 9562.746467411964 1 +78 4983.02087091756 1 +80 7724.4858728591125 1 +83 8841.674502038626 2 +84 6246.4982190023875 1 +87 9393.411414390408 1 +89 9939.87610586772 1 +90 2459.633306003153 36 +91 2476.9733547214432 54 +92 2602.3854441646417 92 +93 2641.4407053727327 16 +94 2490.116463139827 22 +95 2708.966592632696 50 +96 2712.70344859146 186 +97 2601.976556389392 122 +98 2696.738771182704 66 +99 2717.4488035655795 96 +100 2664.1535241047955 169 +101 2756.752618571351 135 +102 2690.486944774124 169 +103 2757.303936819443 122 +104 2788.0634856473407 455 +105 2799.2456126606685 442 +106 2824.3450568229086 140 +107 2810.7694676013543 170 +108 2763.8178304656767 344 +109 2737.670725269933 72 +110 2784.720632307665 251 +111 2785.9047004519016 159 +112 2875.0377388827437 260 +113 2811.6308434785674 181 +114 2870.785606763417 187 +115 2835.5659047181393 273 +116 2866.9461104108673 57 +117 2881.5004771819836 117 +118 2909.6427615774414 109 +119 2619.34037497993 258 +120 2939.450458844306 263 +121 2906.4929038275664 204 +122 2948.7314221542797 121 +123 2953.9094434325502 74 +124 2985.440838469254 88 +125 2975.29695996887 115 +126 2954.414493601059 126 +127 2896.9544352647317 185 +128 2949.3024599047144 314 +129 2910.3683615652503 209 +130 2979.817444072707 119 +131 3028.992076582572 177 +132 2808.3669632012125 177 +133 3073.615623333536 128 +134 3060.4393475447278 151 +135 3086.498663534459 133 +136 2561.4052783579564 312 +137 3126.1601046651467 227 +138 2979.8711381534604 198 +139 3155.1700429612347 90 +140 3151.571195451564 231 +141 3164.168927222439 154 +142 3129.1259162903625 232 +143 2847.00140498736 255 +144 3187.418077378617 219 +145 3138.7672739468912 97 +146 3195.2003067100504 89 +147 3194.6325297285757 158 +148 3195.955099809758 204 +149 3237.0166820700815 62 +150 3255.597180242052 127 +151 3254.93502239292 60 +152 3281.352160314403 73 +153 3279.3377380196753 125 +154 3255.6776560341473 152 +155 3271.2471627805808 279 +156 3247.845439672276 82 +157 3326.7739628655268 29 +158 2729.1090121136604 144 +159 3286.8233904485955 142 +160 3261.8871838247255 153 +161 3328.385344277312 44 +162 3046.827366294323 49 +163 3154.2986542177646 184 +164 3295.002427920198 83 +165 3357.799874918099 76 +166 3378.6307877600357 39 +167 3370.5692397575813 30 +168 3195.0414707793702 62 +169 2902.5402667318845 135 +170 3258.0098219618676 41 +171 3262.259952854769 26 +172 3422.502739224616 116 +173 3417.901402907931 66 +174 3439.523368142743 108 +175 3349.7058079777694 59 +176 3029.6093807618167 19 +177 3441.201679646225 19 +178 3409.1941863144143 224 +179 2929.2353951159334 19 +180 2900.2127508167396 26 +181 2828.9547539683276 18 +182 2834.0869781995048 17 +183 2761.479675825987 42 +184 2820.7943916563645 30 +191 3317.3273881243617 4 +192 3322.925969683947 1 +193 3360.9024085801716 3 +194 3392.7009888877624 14 +196 3491.7183448840774 98 +197 3560.370767209505 113 +199 3481.1977823731877 22 +200 3588.148547649609 76 +201 3452.222617387239 31 +202 3451.376536977674 53 +203 3230.5573822484566 111 +204 3113.641758455844 67 +205 2726.8489140397933 53 +206 2873.5044805950797 108 +207 3104.405418111494 43 +208 3249.613515481495 32 +209 3475.2795571004067 108 +210 3639.9057680110345 80 +211 3325.2151810070877 57 +212 2884.218091615126 33 +213 2920.3643608289703 13 +214 2906.8321244956683 2 +215 2813.3490718359144 27 +216 2939.36336644519 60 +217 3755.401043830073 69 +218 3585.3395933997663 86 +219 3758.964219036941 85 +220 3790.129945001886 122 +221 3810.992521640524 172 +222 3792.3610060225014 23 +223 3815.631009413777 26 +224 3795.2923471058193 16 +225 3826.4825884877614 69 +226 3831.510668130783 54 +227 3832.1638795855274 156 +228 3833.123269606653 120 +229 3859.508388383163 141 +230 3830.84912258366 86 +231 3783.793995449541 158 +232 3746.1261324199963 184 +233 2863.6000069842157 37 +236 2678.195287875774 32 diff --git a/reversing_game_mechanics/zoomlevel/win.size.3 b/reversing_game_mechanics/zoomlevel/win.size.3 new file mode 100644 index 0000000..564d37c --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.size.3 @@ -0,0 +1,69 @@ +115 7887.098642720275 1 +116 9958.89833264704 1 +124 5461.392679527814 1 +126 8508.168428046074 1 +135 2830.58244889634 7 +137 4313.037096988617 1 +140 3420.4585949840116 1 +141 3163.25923692637 7 +142 3149.401212929213 43 +143 3176.547339486695 42 +144 3058.668010752393 23 +145 3126.600230282087 10 +146 3120.9783722416278 24 +147 3145.5927899205262 21 +148 3099.849351178215 16 +149 3050.773016794268 30 +150 2843.040801676965 15 +151 2624.4180307260503 19 +152 3056.6098867863398 125 +153 2468.258090232867 21 +154 2355.969651757 21 +155 2702.4124407647328 32 +156 2982.131452501717 24 +157 3142.504256162591 21 +158 3265.692269642074 28 +159 3282.8310952590905 6 +160 3261.3567728784287 5 +161 3274.0054978573266 11 +162 3332.2054258403696 15 +163 3361.016661666526 3 +164 3355.109089135553 14 +165 3373.971102425153 20 +166 3259.075482402947 7 +167 3265.9854561831717 10 +169 3411.079741079062 17 +170 3398.256611852613 37 +171 3409.9420816195693 33 +172 3456.7860795831725 82 +173 3373.551392820332 8 +174 3336.6609057559326 7 +175 3430.284244782056 15 +176 3437.843510109208 76 +177 3458.1489268104115 281 +178 3477.0933263287598 38 +179 3252.7631330916183 13 +180 3240.0327158842083 9 +181 3159.548227199579 60 +182 3040.0726964992136 77 +184 3227.447288492873 11 +186 3130.8784709726438 1 +187 3295.738460497131 2 +188 3356.7450007410453 26 +189 3489.3794577259723 114 +190 3467.191514756576 29 +191 3003.702382061179 30 +192 3060.0434637436115 34 +193 2897.203134058777 78 +194 2949.2990692705275 26 +195 3061.7589715717336 37 +196 3085.414720908682 39 +197 3373.3670123483453 109 +198 3590.769416155819 47 +199 3188.3251088933825 3 +200 3185.424932406978 15 +201 9721.27075026717 1 +225 2838.9635432671553 12 +228 9773.704773523703 1 +253 3503.388645297578 26 +254 3524.6476419636615 4 diff --git a/reversing_game_mechanics/zoomlevel/win.size.4 b/reversing_game_mechanics/zoomlevel/win.size.4 new file mode 100644 index 0000000..69a1ad2 --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.size.4 @@ -0,0 +1,77 @@ +124 5461.392679527814 1 +126 8508.168428046074 1 +141 6587.192725281385 1 +142 7665.473892721832 1 +149 9875.263895208067 1 +154 7029.594867415903 1 +157 7155.990497478319 1 +159 7350.145372712025 1 +172 5135.193180397404 1 +174 3431.546152975361 6 +175 3497.8764986774477 14 +176 3311.0096647397454 23 +177 3389.6768282536905 36 +178 3468.8963662813567 13 +179 3485.865889560297 37 +180 3490.3886603070437 113 +181 3515.5905620535505 98 +182 3499.1920496023076 15 +183 3419.91418020979 18 +184 3187.2913265028033 64 +185 3123.9286163419292 57 +195 3615.2654121101536 88 +196 3637.733635108541 62 +197 3628.236210612534 156 +198 3661.8806643581383 4 +199 3664.0061408245483 76 +200 3677.116261420082 12 +201 3637.3748775731106 146 +202 3685.892700554372 53 +203 3635.77777098656 56 +205 3716.556605246313 8 +206 3684.0620244507286 15 +207 3715.699799499416 30 +208 3468.918707609044 5 +209 3690.992549437075 16 +210 3509.5711988788603 26 +211 3555.6774319389547 26 +212 3433.242199437727 52 +213 3586.7179983935175 15 +214 3585.6561463698663 10 +215 3746.0168179013826 40 +216 3784.0027748404204 267 +217 3786.887112127849 70 +218 3689.460258628625 10 +219 3681.7335590724106 7 +220 3526.8682992139074 20 +221 3674.9727890149065 28 +222 3664.5142925086266 24 +223 3634.4388837893534 57 +224 3824.525199289449 80 +225 3828.2075440080307 63 +226 3813.7278350716115 126 +227 3816.3041021386125 227 +228 9773.704773523703 2 +229 3870.390807140798 48 +230 3793.3906996248093 27 +286 3049.217932519747 3 +287 2999.563301549077 1 +288 2918.4139528175233 2 +289 2928.8649678672455 1 +290 2923.3942601024582 1 +291 2926.6731966517887 1 +292 3092.7083599977545 12 +293 3092.7083599977545 53 +294 3101.7430583463874 28 +295 2832.8236796525125 40 +296 2666.3600657075553 5 +297 2658.3432810681165 14 +298 2840.7354681490497 2 +299 2840.7354681490497 9 +300 2840.7354681490497 2 +301 2840.7354681490497 4 +302 2840.7354681490497 63 +322 3771.882951524344 154 +323 3668.3926998073694 55 +324 3601.816902620121 2 +325 3550.685708423093 49 diff --git a/reversing_game_mechanics/zoomlevel/win.size.5 b/reversing_game_mechanics/zoomlevel/win.size.5 new file mode 100644 index 0000000..537d012 --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.size.5 @@ -0,0 +1,8 @@ +195 9346.260482139367 1 +196 7269.414075425887 1 +251 3926.380139517823 7 +252 3995.193362028927 19 +253 3979.0382003695313 11 +254 2999.2432378851836 13 +256 3046.871510254412 16 +257 3030.115674359644 1 diff --git a/reversing_game_mechanics/zoomlevel/win.size.6 b/reversing_game_mechanics/zoomlevel/win.size.6 new file mode 100644 index 0000000..1e93f8a --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.size.6 @@ -0,0 +1,4 @@ +195 9346.260482139367 1 +276 3564.1046561513876 2 +277 3713.46266980025 16 +278 3981.4374288691265 52 diff --git a/reversing_game_mechanics/zoomlevel/win.size.all b/reversing_game_mechanics/zoomlevel/win.size.all new file mode 100644 index 0000000..e4520ab --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.size.all @@ -0,0 +1,424 @@ +0 9957.478596512272 16 +49 2120.5192760265113 245 +50 1969.829688069504 88 +51 1907.5106814904077 196 +52 1652.2645066695586 49 +53 1860.7818249327352 96 +54 1851.8933554608375 58 +55 1468.638825579659 70 +56 2251.943604977709 106 +57 2004.575765592311 166 +58 2109.127781809343 362 +59 2126.4564420650613 137 +60 1994.1740144731602 91 +61 2173.5730951592127 58 +62 1940.5630626186824 52 +63 2232.8013794334684 39 +64 2133.3471353720192 71 +65 2239.5713875650404 100 +66 2259.5827048373335 868 +67 2240.224319125208 818 +68 2307.553032976707 443 +69 2226.5634956138124 579 +70 2356.425258734085 336 +71 2293.2538019155227 397 +72 2249.2098612623945 273 +73 2331.4519081465096 451 +74 2392.639755583778 300 +75 2404.2996901384818 277 +76 2403.8011565019265 161 +77 2357.5313359529287 262 +78 2377.4242364374095 157 +79 2339.8472172344927 145 +80 2438.0258407162137 228 +81 2488.3331770484433 301 +82 2489.7003835803216 352 +83 2499.0544211761376 291 +84 2455.6426857342253 304 +85 2498.9455776386967 154 +86 2378.6727391551785 346 +87 2474.5797623030867 702 +88 2366.7634017788937 727 +89 2442.546417163858 373 +90 2515.553616999646 238 +91 2614.3163542310635 207 +92 2594.101771326638 66 +93 2544.643000501249 67 +94 2651.225377066235 95 +95 2681.96290056369 148 +96 2685.0344504307577 170 +97 2679.5546271722096 426 +98 2693.4938277263605 569 +99 2726.821592990638 54 +100 2696.036349903317 53 +101 2704.8558187082726 56 +102 2754.743726737571 88 +103 2719.114010114324 180 +104 2791.1581825471662 122 +105 2794.8023185907086 84 +106 2803.209767391659 133 +107 2805.824121358999 90 +108 2796.2517769328283 250 +109 2803.5384784232942 261 +110 2837.5144052497776 142 +111 2835.092414719492 107 +112 2846.737255174773 63 +113 2877.452345391666 63 +114 2851.5078467365297 53 +115 2780.2778638114573 113 +116 2891.1260781916794 242 +117 2870.733878296628 69 +118 2892.3390188565377 88 +119 2730.286798122131 145 +120 2715.363695713707 389 +121 2238.8311682661556 281 +122 2913.41998345587 61 +123 2955.795155283938 28 +124 2385.1079640133694 322 +125 3029.202205201891 67 +126 3015.162516349658 39 +127 3024.4353191959653 64 +128 3046.6238691377707 139 +129 3020.514029101669 40 +130 3015.3225366451265 112 +131 3021.6586504765887 92 +132 3040.8763539479864 73 +133 3065.0941257977706 58 +134 2976.10500486794 66 +135 3026.624522467232 98 +136 3013.2540550043236 84 +137 2927.263910206936 80 +138 2981.869380103696 80 +139 2977.177354475208 52 +140 3049.6730972351775 42 +141 2354.0403564934904 65 +142 2332.625130620006 4 +148 3144.616033794905 7 +149 3228.400223020684 11 +150 3220.1863300125974 71 +151 3248.3468103021264 119 +152 3253.712494981694 66 +153 3238.846245192877 57 +154 3176.819950831334 43 +155 3301.4617974467005 36 +156 3296.8477368541 132 +157 3316.3596005258537 113 +158 3286.2537942161434 155 +159 3083.007946794818 110 +160 2909.176000175995 64 +161 2641.6837433727756 35 +162 2646.5972492995606 65 +163 2727.742106578259 49 +164 2692.4384858339845 44 +165 2498.7140692764347 49 +166 2352.3938870860893 36 +167 2375.1743093928917 57 +168 2304.796954180563 121 +64 7513.947364734464 1 +66 8967.320224013414 2 +68 9047.885167264227 3 +71 5962.59423405618 1 +73 6812.90341924792 1 +74 9453.725720582335 1 +75 9562.746467411964 1 +78 4983.02087091756 1 +80 7724.4858728591125 1 +83 8841.674502038626 2 +84 6246.4982190023875 1 +87 9393.411414390408 1 +89 9939.87610586772 1 +90 2459.633306003153 36 +91 2476.9733547214432 54 +92 2602.3854441646417 92 +93 2641.4407053727327 16 +94 2490.116463139827 22 +95 2708.966592632696 50 +96 2712.70344859146 186 +97 2601.976556389392 122 +98 2696.738771182704 66 +99 2717.4488035655795 96 +100 2664.1535241047955 169 +101 2756.752618571351 135 +102 2690.486944774124 169 +103 2757.303936819443 122 +104 2788.0634856473407 455 +105 2799.2456126606685 442 +106 2824.3450568229086 140 +107 2810.7694676013543 170 +108 2763.8178304656767 344 +109 2737.670725269933 72 +110 2784.720632307665 251 +111 2785.9047004519016 159 +112 2875.0377388827437 260 +113 2811.6308434785674 181 +114 2870.785606763417 187 +115 2835.5659047181393 273 +116 2866.9461104108673 57 +117 2881.5004771819836 117 +118 2909.6427615774414 109 +119 2619.34037497993 258 +120 2939.450458844306 263 +121 2906.4929038275664 204 +122 2948.7314221542797 121 +123 2953.9094434325502 74 +124 2985.440838469254 88 +125 2975.29695996887 115 +126 2954.414493601059 126 +127 2896.9544352647317 185 +128 2949.3024599047144 314 +129 2910.3683615652503 209 +130 2979.817444072707 119 +131 3028.992076582572 177 +132 2808.3669632012125 177 +133 3073.615623333536 128 +134 3060.4393475447278 151 +135 3086.498663534459 133 +136 2561.4052783579564 312 +137 3126.1601046651467 227 +138 2979.8711381534604 198 +139 3155.1700429612347 90 +140 3151.571195451564 231 +141 3164.168927222439 154 +142 3129.1259162903625 232 +143 2847.00140498736 255 +144 3187.418077378617 219 +145 3138.7672739468912 97 +146 3195.2003067100504 89 +147 3194.6325297285757 158 +148 3195.955099809758 204 +149 3237.0166820700815 62 +150 3255.597180242052 127 +151 3254.93502239292 60 +152 3281.352160314403 73 +153 3279.3377380196753 125 +154 3255.6776560341473 152 +155 3271.2471627805808 279 +156 3247.845439672276 82 +157 3326.7739628655268 29 +158 2729.1090121136604 144 +159 3286.8233904485955 142 +160 3261.8871838247255 153 +161 3328.385344277312 44 +162 3046.827366294323 49 +163 3154.2986542177646 184 +164 3295.002427920198 83 +165 3357.799874918099 76 +166 3378.6307877600357 39 +167 3370.5692397575813 30 +168 3195.0414707793702 62 +169 2902.5402667318845 135 +170 3258.0098219618676 41 +171 3262.259952854769 26 +172 3422.502739224616 116 +173 3417.901402907931 66 +174 3439.523368142743 108 +175 3349.7058079777694 59 +176 3029.6093807618167 19 +177 3441.201679646225 19 +178 3409.1941863144143 224 +179 2929.2353951159334 19 +180 2900.2127508167396 26 +181 2828.9547539683276 18 +182 2834.0869781995048 17 +183 2761.479675825987 42 +184 2820.7943916563645 30 +191 3317.3273881243617 4 +192 3322.925969683947 1 +193 3360.9024085801716 3 +194 3392.7009888877624 14 +196 3491.7183448840774 98 +197 3560.370767209505 113 +199 3481.1977823731877 22 +200 3588.148547649609 76 +201 3452.222617387239 31 +202 3451.376536977674 53 +203 3230.5573822484566 111 +204 3113.641758455844 67 +205 2726.8489140397933 53 +206 2873.5044805950797 108 +207 3104.405418111494 43 +208 3249.613515481495 32 +209 3475.2795571004067 108 +210 3639.9057680110345 80 +211 3325.2151810070877 57 +212 2884.218091615126 33 +213 2920.3643608289703 13 +214 2906.8321244956683 2 +215 2813.3490718359144 27 +216 2939.36336644519 60 +217 3755.401043830073 69 +218 3585.3395933997663 86 +219 3758.964219036941 85 +220 3790.129945001886 122 +221 3810.992521640524 172 +222 3792.3610060225014 23 +223 3815.631009413777 26 +224 3795.2923471058193 16 +225 3826.4825884877614 69 +226 3831.510668130783 54 +227 3832.1638795855274 156 +228 3833.123269606653 120 +229 3859.508388383163 141 +230 3830.84912258366 86 +231 3783.793995449541 158 +232 3746.1261324199963 184 +233 2863.6000069842157 37 +236 2678.195287875774 32 +115 7887.098642720275 1 +116 9958.89833264704 1 +124 5461.392679527814 1 +126 8508.168428046074 1 +135 2830.58244889634 7 +137 4313.037096988617 1 +140 3420.4585949840116 1 +141 3163.25923692637 7 +142 3149.401212929213 43 +143 3176.547339486695 42 +144 3058.668010752393 23 +145 3126.600230282087 10 +146 3120.9783722416278 24 +147 3145.5927899205262 21 +148 3099.849351178215 16 +149 3050.773016794268 30 +150 2843.040801676965 15 +151 2624.4180307260503 19 +152 3056.6098867863398 125 +153 2468.258090232867 21 +154 2355.969651757 21 +155 2702.4124407647328 32 +156 2982.131452501717 24 +157 3142.504256162591 21 +158 3265.692269642074 28 +159 3282.8310952590905 6 +160 3261.3567728784287 5 +161 3274.0054978573266 11 +162 3332.2054258403696 15 +163 3361.016661666526 3 +164 3355.109089135553 14 +165 3373.971102425153 20 +166 3259.075482402947 7 +167 3265.9854561831717 10 +169 3411.079741079062 17 +170 3398.256611852613 37 +171 3409.9420816195693 33 +172 3456.7860795831725 82 +173 3373.551392820332 8 +174 3336.6609057559326 7 +175 3430.284244782056 15 +176 3437.843510109208 76 +177 3458.1489268104115 281 +178 3477.0933263287598 38 +179 3252.7631330916183 13 +180 3240.0327158842083 9 +181 3159.548227199579 60 +182 3040.0726964992136 77 +184 3227.447288492873 11 +186 3130.8784709726438 1 +187 3295.738460497131 2 +188 3356.7450007410453 26 +189 3489.3794577259723 114 +190 3467.191514756576 29 +191 3003.702382061179 30 +192 3060.0434637436115 34 +193 2897.203134058777 78 +194 2949.2990692705275 26 +195 3061.7589715717336 37 +196 3085.414720908682 39 +197 3373.3670123483453 109 +198 3590.769416155819 47 +199 3188.3251088933825 3 +200 3185.424932406978 15 +201 9721.27075026717 1 +225 2838.9635432671553 12 +228 9773.704773523703 1 +253 3503.388645297578 26 +254 3524.6476419636615 4 +124 5461.392679527814 1 +126 8508.168428046074 1 +141 6587.192725281385 1 +142 7665.473892721832 1 +149 9875.263895208067 1 +154 7029.594867415903 1 +157 7155.990497478319 1 +159 7350.145372712025 1 +172 5135.193180397404 1 +174 3431.546152975361 6 +175 3497.8764986774477 14 +176 3311.0096647397454 23 +177 3389.6768282536905 36 +178 3468.8963662813567 13 +179 3485.865889560297 37 +180 3490.3886603070437 113 +181 3515.5905620535505 98 +182 3499.1920496023076 15 +183 3419.91418020979 18 +184 3187.2913265028033 64 +185 3123.9286163419292 57 +195 3615.2654121101536 88 +196 3637.733635108541 62 +197 3628.236210612534 156 +198 3661.8806643581383 4 +199 3664.0061408245483 76 +200 3677.116261420082 12 +201 3637.3748775731106 146 +202 3685.892700554372 53 +203 3635.77777098656 56 +205 3716.556605246313 8 +206 3684.0620244507286 15 +207 3715.699799499416 30 +208 3468.918707609044 5 +209 3690.992549437075 16 +210 3509.5711988788603 26 +211 3555.6774319389547 26 +212 3433.242199437727 52 +213 3586.7179983935175 15 +214 3585.6561463698663 10 +215 3746.0168179013826 40 +216 3784.0027748404204 267 +217 3786.887112127849 70 +218 3689.460258628625 10 +219 3681.7335590724106 7 +220 3526.8682992139074 20 +221 3674.9727890149065 28 +222 3664.5142925086266 24 +223 3634.4388837893534 57 +224 3824.525199289449 80 +225 3828.2075440080307 63 +226 3813.7278350716115 126 +227 3816.3041021386125 227 +228 9773.704773523703 2 +229 3870.390807140798 48 +230 3793.3906996248093 27 +286 3049.217932519747 3 +287 2999.563301549077 1 +288 2918.4139528175233 2 +289 2928.8649678672455 1 +290 2923.3942601024582 1 +291 2926.6731966517887 1 +292 3092.7083599977545 12 +293 3092.7083599977545 53 +294 3101.7430583463874 28 +295 2832.8236796525125 40 +296 2666.3600657075553 5 +297 2658.3432810681165 14 +298 2840.7354681490497 2 +299 2840.7354681490497 9 +300 2840.7354681490497 2 +301 2840.7354681490497 4 +302 2840.7354681490497 63 +322 3771.882951524344 154 +323 3668.3926998073694 55 +324 3601.816902620121 2 +325 3550.685708423093 49 +195 9346.260482139367 1 +196 7269.414075425887 1 +251 3926.380139517823 7 +252 3995.193362028927 19 +253 3979.0382003695313 11 +254 2999.2432378851836 13 +256 3046.871510254412 16 +257 3030.115674359644 1 +195 9346.260482139367 1 +276 3564.1046561513876 2 +277 3713.46266980025 16 +278 3981.4374288691265 52 diff --git a/reversing_game_mechanics/zoomlevel/win.size.all.filtered b/reversing_game_mechanics/zoomlevel/win.size.all.filtered new file mode 100644 index 0000000..b1abb5b --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.size.all.filtered @@ -0,0 +1,227 @@ +49 2120.5192760265113 245 +50 1969.829688069504 88 +51 1907.5106814904077 196 +56 2251.943604977709 106 +57 2004.575765592311 166 +58 2109.127781809343 362 +59 2126.4564420650613 137 +61 2173.5730951592127 58 +63 2232.8013794334684 39 +64 2133.3471353720192 71 +65 2239.5713875650404 100 +66 2259.5827048373335 868 +67 2240.224319125208 818 +68 2307.553032976707 443 +69 2226.5634956138124 579 +70 2356.425258734085 336 +71 2293.2538019155227 397 +72 2249.2098612623945 273 +73 2331.4519081465096 451 +74 2392.639755583778 300 +75 2404.2996901384818 277 +76 2403.8011565019265 161 +77 2357.5313359529287 262 +78 2377.4242364374095 157 +79 2339.8472172344927 145 +80 2438.0258407162137 228 +81 2488.3331770484433 301 +82 2489.7003835803216 352 +83 2499.0544211761376 291 +84 2455.6426857342253 304 +85 2498.9455776386967 154 +87 2474.5797623030867 702 +90 2515.553616999646 238 +91 2614.3163542310635 207 +92 2594.101771326638 66 +93 2544.643000501249 67 +94 2651.225377066235 95 +95 2681.96290056369 148 +96 2685.0344504307577 170 +97 2679.5546271722096 426 +98 2693.4938277263605 569 +99 2726.821592990638 54 +100 2696.036349903317 53 +101 2704.8558187082726 56 +102 2754.743726737571 88 +103 2719.114010114324 180 +104 2791.1581825471662 122 +105 2794.8023185907086 84 +106 2803.209767391659 133 +107 2805.824121358999 90 +108 2796.2517769328283 250 +109 2803.5384784232942 261 +110 2837.5144052497776 142 +111 2835.092414719492 107 +112 2846.737255174773 63 +113 2877.452345391666 63 +114 2851.5078467365297 53 +115 2780.2778638114573 113 +116 2891.1260781916794 242 +117 2870.733878296628 69 +118 2892.3390188565377 88 +122 2913.41998345587 61 +123 2955.795155283938 28 +125 3029.202205201891 67 +126 3015.162516349658 39 +127 3024.4353191959653 64 +128 3046.6238691377707 139 +129 3020.514029101669 40 +130 3015.3225366451265 112 +131 3021.6586504765887 92 +132 3040.8763539479864 73 +133 3065.0941257977706 58 +135 3026.624522467232 98 +136 3013.2540550043236 84 +140 3049.6730972351775 42 +148 3144.616033794905 7 +149 3228.400223020684 11 +150 3220.1863300125974 71 +151 3248.3468103021264 119 +152 3253.712494981694 66 +153 3238.846245192877 57 +154 3176.819950831334 43 +155 3301.4617974467005 36 +156 3296.8477368541 132 +157 3316.3596005258537 113 +158 3286.2537942161434 155 +92 2602.3854441646417 92 +93 2641.4407053727327 16 +95 2708.966592632696 50 +96 2712.70344859146 186 +97 2601.976556389392 122 +98 2696.738771182704 66 +99 2717.4488035655795 96 +100 2664.1535241047955 169 +101 2756.752618571351 135 +102 2690.486944774124 169 +103 2757.303936819443 122 +104 2788.0634856473407 455 +105 2799.2456126606685 442 +106 2824.3450568229086 140 +107 2810.7694676013543 170 +108 2763.8178304656767 344 +109 2737.670725269933 72 +110 2784.720632307665 251 +111 2785.9047004519016 159 +112 2875.0377388827437 260 +113 2811.6308434785674 181 +114 2870.785606763417 187 +115 2835.5659047181393 273 +116 2866.9461104108673 57 +117 2881.5004771819836 117 +118 2909.6427615774414 109 +120 2939.450458844306 263 +121 2906.4929038275664 204 +122 2948.7314221542797 121 +123 2953.9094434325502 74 +124 2985.440838469254 88 +125 2975.29695996887 115 +126 2954.414493601059 126 +128 2949.3024599047144 314 +130 2979.817444072707 119 +131 3028.992076582572 177 +133 3073.615623333536 128 +134 3060.4393475447278 151 +135 3086.498663534459 133 +137 3126.1601046651467 227 +139 3155.1700429612347 90 +140 3151.571195451564 231 +141 3164.168927222439 154 +142 3129.1259162903625 232 +144 3187.418077378617 219 +145 3138.7672739468912 97 +146 3195.2003067100504 89 +147 3194.6325297285757 158 +148 3195.955099809758 204 +149 3237.0166820700815 62 +150 3255.597180242052 127 +151 3254.93502239292 60 +152 3281.352160314403 73 +153 3279.3377380196753 125 +154 3255.6776560341473 152 +155 3271.2471627805808 279 +156 3247.845439672276 82 +157 3326.7739628655268 29 +159 3286.8233904485955 142 +160 3261.8871838247255 153 +161 3328.385344277312 44 +164 3295.002427920198 83 +165 3357.799874918099 76 +166 3378.6307877600357 39 +167 3370.5692397575813 30 +172 3422.502739224616 116 +173 3417.901402907931 66 +174 3439.523368142743 108 +177 3441.201679646225 19 +178 3409.1941863144143 224 +197 3560.370767209505 113 +200 3588.148547649609 76 +217 3755.401043830073 69 +219 3758.964219036941 85 +220 3790.129945001886 122 +221 3810.992521640524 172 +222 3792.3610060225014 23 +223 3815.631009413777 26 +224 3795.2923471058193 16 +225 3826.4825884877614 69 +226 3831.510668130783 54 +227 3832.1638795855274 156 +228 3833.123269606653 120 +229 3859.508388383163 141 +230 3830.84912258366 86 +141 3163.25923692637 7 +142 3149.401212929213 43 +143 3176.547339486695 42 +145 3126.600230282087 10 +146 3120.9783722416278 24 +147 3145.5927899205262 21 +158 3265.692269642074 28 +159 3282.8310952590905 6 +160 3261.3567728784287 5 +161 3274.0054978573266 11 +162 3332.2054258403696 15 +163 3361.016661666526 3 +164 3355.109089135553 14 +165 3373.971102425153 20 +169 3411.079741079062 17 +170 3398.256611852613 37 +171 3409.9420816195693 33 +172 3456.7860795831725 82 +173 3373.551392820332 8 +175 3430.284244782056 15 +176 3437.843510109208 76 +177 3458.1489268104115 281 +178 3477.0933263287598 38 +189 3489.3794577259723 114 +198 3590.769416155819 47 +174 3431.546152975361 6 +175 3497.8764986774477 14 +177 3389.6768282536905 36 +178 3468.8963662813567 13 +179 3485.865889560297 37 +180 3490.3886603070437 113 +181 3515.5905620535505 98 +182 3499.1920496023076 15 +195 3615.2654121101536 88 +196 3637.733635108541 62 +197 3628.236210612534 156 +198 3661.8806643581383 4 +199 3664.0061408245483 76 +200 3677.116261420082 12 +201 3637.3748775731106 146 +202 3685.892700554372 53 +203 3635.77777098656 56 +205 3716.556605246313 8 +206 3684.0620244507286 15 +207 3715.699799499416 30 +209 3690.992549437075 16 +215 3746.0168179013826 40 +216 3784.0027748404204 267 +217 3786.887112127849 70 +224 3824.525199289449 80 +225 3828.2075440080307 63 +226 3813.7278350716115 126 +227 3816.3041021386125 227 +229 3870.390807140798 48 +252 3995.193362028927 19 +253 3979.0382003695313 11 diff --git a/reversing_game_mechanics/zoomlevel/win.size.gnuplot b/reversing_game_mechanics/zoomlevel/win.size.gnuplot new file mode 100644 index 0000000..aa5499c --- /dev/null +++ b/reversing_game_mechanics/zoomlevel/win.size.gnuplot @@ -0,0 +1,19 @@ +min(a,b)=(a<b)?a:b +max(a,b)=(a>b)?a:b + +f(x) = a* x**b +g(x) = aa* x**bb + cc +fit f(x) "win.size.all.filtered" using 1:2 via a,b +fit g(x) "win.size.all.filtered" using 1:2 via aa,bb,cc + +plot "win.size.1" using 1:2:(min(1,$3/100)) lt rgb "red" pt 2 ps variable, \ + "win.size.2" using 1:2:(min(1,$3/100)) lt rgb "blue" pt 2 ps variable, \ + "win.size.3" using 1:2:(min(1,$3/100)) lt rgb "green" pt 2 ps variable, \ + "win.size.4" using 1:2:(1) lt rgb "purple" pt 2 ps variable, \ + "win.size.5" using 1:2:(1) lt rgb "cyan" pt 2 ps variable, \ + "win.size.6" using 1:2:(1) lt rgb "orange" pt 2 ps variable, \ + x**0.4*460+50 lt rgb "gray", \ + x**0.407*460-400 lt rgb "gray", \ + f(x) lt rgb "black", \ + g(x) lt rgb "black" +pause -1 @@ -1,36 +1,475 @@ import time +import math +import random +from collections import defaultdict +import pickle +from functools import reduce +import mechanics +import geometry +#import numpy + +def fit_gaussian(l): + mean = sum(l) / len(l) + stddev = math.sqrt(sum(map(lambda v : (v-mean)**2, l)) / len(l)) + return mean, stddev + +def flatten(l): + return reduce(lambda a,b:a+b, l) + +def quantile(values, q): + if isinstance(values, dict): + return quantile(flatten(map(lambda x : [x[0]]*x[1], sorted(values.items(),key=lambda x:x[0]))), q) + else: + try: + return sorted(values)[ int(len(values)*q) ] + except: + return 0 + +def find_smallest_q_confidence_area(values, q): + """Calculates the (mid, delta) with the smallest delta, such that at least q * len(values) + lie within the interval [mid-delta, mid+delta].""" + try: + mid = min(values, key = lambda value : quantile(list(map(lambda x : abs(x-value), values)), q)) + deviation = quantile(list(map(lambda x : abs(x-mid), values)),q) + #print(list(map(lambda x : abs(x-mid), values))) + return mid,deviation + except: + return 0,0 + +def get_delta_confidence(values, mid, delta): + #"""Calculates which fraction of the values lie within [mid-delta, mid+delta]""" + #try: + return len(list(filter(lambda v : (mid-delta <= v and v <= mid+delta), values))) / len(values) + #except: + # raise + # return 0 + +def avg(values): + if not isinstance(values, dict): + return sum(values)/len(values) + else: + return int(sum(map( lambda x : x[0]*x[1], values.items() )) / sum(map(lambda x : x[1], values.items()))) + +def stddev(values): + a=avg(values) + return avg(list(map(lambda v : (v-a)**2, values))) + +def normalize(values): + a=avg(values) + return [x/a for x in values] + +class StatData(): + pass + +def return_empty_list(): + return [] + +def return_defaultdict_with_empty_list(): + return defaultdict(return_empty_list) + +def return_zero(): + return 0 + +def return_defaultdict_with_zeros(): + return defaultdict(return_zero) + +class ReMerging: + def __init__(self, size1, size2, birth1, birth2, is_parent_child, begin_time): + self.size1 = size1 + self.size2 = size2 + self.birth1 = birth1 + self.birth2 = birth2 + self.is_parent_child = is_parent_child + self.begin_time = begin_time + self.end_time = None class Stats: - def __init__(self): - self.min_mass = 0 - self.max_mass = 0 - self.current_mass = 0 + def __init__(self,c,data=None): + self.c = c + + self.countdown = 27*20 + + if data == None: + self.data = StatData() + self.data.version = 4 + + self.data.min_mass = 0 + self.data.max_mass = 0 + self.data.current_mass = 0 + + self.data.mass_history = [] + self.data.pos_history = [] + self.data.cell_aggressivity = {} + self.data.cell_split_frequency = {} + self.data.cell_defensiveness = {} + + self.data.size_vs_speed = defaultdict(return_defaultdict_with_zeros) + self.data.size_vs_visible_window = defaultdict(return_defaultdict_with_empty_list) + self.data.mass_vs_visible_window = defaultdict(return_defaultdict_with_empty_list) + + self.data.eject_distlogs = {"virus" : [], "split cell" : [], "ejected mass" : []} + self.data.eject_deviations = {"virus" : [], "virus2" : [], "virus3" : [], "split cell" : [], "ejected mass" : []} + + self.data.observed_virus_sizes = defaultdict(return_zero) + self.data.remerging = {} + else: + self.data = data - self.mass_history = [] - self.pos_history = [] - self.cell_aggressivity = {} - self.cell_split_frequency = {} - self.cell_defensiveness = {} + def save(self,filename): + pickle.dump(self.data, open(filename,"wb")) + + def load(filename): + return Stats(None, pickle.load(open(filename,"rb"))) + + def merge(self, filename): + data2 = pickle.load(open(filename,"rb")) + self.data.min_mass = min(self.data.min_mass, data2.min_mass) + self.data.max_mass = max(self.data.max_mass, data2.max_mass) + for i in data2.size_vs_visible_window: + for j in data2.size_vs_visible_window[i]: + self.data.size_vs_visible_window[i][j] += data2.size_vs_visible_window[i][j] + for i in data2.mass_vs_visible_window: + for j in data2.mass_vs_visible_window[i]: + self.data.mass_vs_visible_window[i][j] += data2.mass_vs_visible_window[i][j] + + for i in data2.size_vs_speed: + for j in data2.size_vs_speed[i]: + self.data.size_vs_speed[i][j] += data2.size_vs_speed[i][j] + + for i in data2.eject_deviations: + self.data.eject_deviations[i] += data2.eject_deviations[i] + + for i in data2.eject_distlogs: + self.data.eject_distlogs[i] += data2.eject_distlogs[i] + + for i in self.data.observed_virus_sizes: + self.data.observed_virus_sizes[i] += data2.observed_virus_sizes[i] + + self.data.remerging.update(data2.remerging) + def log_mass(self, mass): - self.mass_history.append((time.time(), mass)) - self.current_mass = mass - if mass > self.max_mass: - self.max_mass = mass - if mass < self.min_mass: - self.min_mass = mass + self.data.mass_history.append((time.time(), mass)) + self.data.current_mass = mass + if mass > self.data.max_mass: + self.data.max_mass = mass + if mass < self.data.min_mass: + self.data.min_mass = mass def log_pos(self, pos): - self.pos_history.append((time.time(), (pos[0], pos[1]))) + self.data.pos_history.append((time.time(), (pos[0], pos[1]))) def update_cell_aggressivity(self, cell, value): - self.cell_aggressivity[cell] = value + self.data.cell_aggressivity[cell] = value def update_cell_split_frequency(self, cell, value): - self.cell_split_frequency[cell] = value + self.data.cell_split_frequency[cell] = value def update_cell_defensiveness(self, cell, value): - self.cell_defensiveness[cell] = value + self.data.cell_defensiveness[cell] = value def get_last_steps(self, list, steps = 10): - return list[-steps:]
\ No newline at end of file + return list[-steps:] + + def process_frame(self): + self.countdown -= 1 + if False and (self.countdown <= 0): + quick_followup = (random.random() < 0.1) + + if quick_followup: + self.countdown = 7 + else: + self.countdown = int(27* (random.random() * 15)) + + what_to_do = random.random() + if what_to_do < 0.2: + self.c.send_split() + else: + self.c.send_shoot() + + self.log_pos(self.c.player.center) + self.log_mass(self.c.player.total_mass) + + cells = self.c.world.cells.values() + own_cells = list(self.c.player.own_cells) + + own_total_size = sum( map(lambda cell : cell.size, own_cells) ) + own_total_mass = sum( map(lambda cell : cell.mass, own_cells) ) + n_own_cells = len(own_cells) + + n = 3 + for cell in filter(lambda cell : not cell.is_food and not cell.is_virus and not cell.is_ejected_mass, cells): + if hasattr(cell,'poslog') and len(cell.poslog) > n+1: + cellspeed = 0 + for i in range(1,n+1): + cellspeed += (cell.poslog[-i] - cell.poslog[-i-1]).len() / n + + cellspeed = int(cellspeed*10)/10 + self.data.size_vs_speed[cell.size][cellspeed] += 1 + + visible_width = max( map(lambda cell : cell.pos.x - cell.size, cells) ) - min( map(lambda cell : cell.pos.x + cell.size, cells) ) + visible_height = max( map(lambda cell : cell.pos.y - cell.size, cells) ) - min( map(lambda cell : cell.pos.y + cell.size, cells) ) + + self.data.size_vs_visible_window[n_own_cells][own_total_size].append((visible_width,visible_height)) + self.data.mass_vs_visible_window[n_own_cells][own_total_mass].append((visible_width,visible_height)) + + + # log virus sizes + for cell in cells: + if cell.is_virus: + self.data.observed_virus_sizes[cell.size] += 1 + + # detect re-merging cells + for cell in own_cells: + for cell2 in own_cells: + if cell2 != cell: + dist = (cell.pos - cell2.pos).len() + expected_dist = cell.size + cell2.size + min_dist = max(cell.size, cell2.size) + + if (dist < (0.9 * expected_dist + 0.1 * min_dist)): + is_parent_child = (cell == cell2.parent or cell2 == cell.parent) + print("cells seem to be merging! they are "+ ("" if is_parent_child else "NOT ") + "parent and child") + pair_id = (min(cell.cid,cell2.cid), max(cell.cid,cell2.cid)) + + if pair_id not in self.data.remerging: + self.data.remerging[pair_id] = ReMerging(cell.size, cell2.size, cell.spawntime, cell2.spawntime, is_parent_child, self.c.world.time) + else: + self.data.remerging[pair_id].end_time = self.c.world.time + + + + # find ejected mass, split cells or viruses that have come to rest + for cell in cells: + if hasattr(cell,"parent") and cell.parent != None and not cell.calmed_down: + # we're only interested in cells with a parent set, because + # this also implies that we have tracked them since their + # creation. + # also, we're only interested in cells that are still flying + # as a result of being ejected/split. + + if not cell.is_food and not cell.is_ejected_mass and not cell.is_virus: + expected_speed = mechanics.speed(cell.size) + celltype = "split cell" + elif cell.is_virus: + expected_speed = 1 + celltype = "virus" + elif cell.is_ejected_mass: + expected_speed = 1 + celltype = "ejected mass" + + + if cell.movement.len() < expected_speed * 1.1: + print(celltype+" has come to rest, nframes="+str(len(cell.poslog))) + cell.calmed_down = True + # TODO: speed log + + # distance is calculated naively + distance = (cell.spawnpoint - cell.pos).len() + + # distance2 is calculated along the cell's path (will differ if the flight was not colinear) + poslog = list(cell.poslog) + speeds = list(map(lambda vecs : (vecs[0]-vecs[1]).len(), zip(poslog, poslog[1:]))) + distance2 = sum(speeds) + + distance_from_parent = (cell.parentpos_when_spawned - cell.pos).len() + + self.data.eject_distlogs[celltype] += [(distance, distance2, distance_from_parent, cell.parentsize_when_spawned, len(cell.poslog), speeds)] + print(" flown distance = %.2f / %.2f"%(distance,distance2)) + + if len(cell.poslog) == 5: + # calculate movement direction from the first 5 samples + + # first check whether they're on a straight line + if geometry.is_colinear(cell.poslog) and cell.shoot_vec != None: + print(celltype+" direction available!") + fly_direction = cell.poslog[-1] - cell.poslog[0] + fly_angle = math.atan2(fly_direction.y, fly_direction.x) + + shoot_angle = math.atan2(cell.shoot_vec.y, cell.shoot_vec.x) + + + deviation = (fly_angle - shoot_angle) % (2*math.pi) + if deviation > math.pi: deviation -= 2*math.pi + print(" deviation = "+str(deviation*180/math.pi)) + + self.data.eject_deviations[celltype] += [deviation] + + if (celltype == 'virus'): + # FIXME so ugly + try: + shoot_angle = math.atan2(cell.shoot_vec2.y, cell.shoot_vec2.x) + + deviation = (fly_angle - shoot_angle) % (2*math.pi) + if deviation > math.pi: deviation -= 2*math.pi + print(" deviation2= "+str(deviation*180/math.pi)) + + self.data.eject_deviations['virus2'] += [deviation] + except AttributeError: + print("virus2 not available, wtf?!") + + try: + shoot_angle = math.atan2(cell.shoot_vec3.y, cell.shoot_vec3.x) + + deviation = (fly_angle - shoot_angle) % (2*math.pi) + if deviation > math.pi: deviation -= 2*math.pi + print(" deviation3= "+str(deviation*180/math.pi)) + + self.data.eject_deviations['virus3'] += [deviation] + except AttributeError: + print("virus3 not available") + + else: + print(celltype+" did NOT fly in a straight line, ignoring...") + + + + def analyze_speed(self): + results=[] + for size, values in sorted(self.data.size_vs_speed.items(), key=lambda x : x[0]): + minimum = quantile(values, 0.2) + average = quantile(values, 0.5) + maximum = quantile(values, 0.8) + + results += [(size,maximum,average,minimum,False,False,False,sum(values.values()))] + + # mark outliers + for i in range(1, len(results)-1): + for j in range(1,4): + if abs(results[i][j] - results[i-1][j]) > 2 and abs(results[i][j] - results[i+1][j]) > 2: + tmp = list(results[i]) + tmp[j+3] = True + results[i] = tuple(tmp) + + coeff_vs_stddev = [] + for coeff in [x/100 for x in range(10,100,1)]: + products = [] + for size, maximum, average, minimum, maxoutlier, avgoutlier, minoutlier, ndata in results: + if not maxoutlier: + products += [size**coeff * maximum] + + coeff_vs_stddev += [(coeff, avg(products), stddev(normalize(products)))] + + best = min(coeff_vs_stddev, key=lambda v:v[2]) + + print("size\tcalc\tmax\tavg\tmin\t\tndata") + for size, maximum, average, minimum, maxoutlier, avgoutlier, minoutlier, ndata in results: + print(str(size) + ":\t" + "%.1f" % (best[1] / size**best[0]) + "\t" + ("*" if maxoutlier else "") + str(maximum) + "\t" + ("*" if avgoutlier else "") + str(average) + "\t" + ("*" if minoutlier else "") + str(minimum) + "\t\t" + str(ndata)) + + print("size**"+str(best[0])+" * speed = "+str(best[1]) ) + + def analyze_visible_window_helper(self, foo_vs_visible_window, verbose=False): + svw = {} + ratios = [] + if verbose: print("size\tdiag") + for size, rects in sorted(foo_vs_visible_window.items(), key=lambda x:x[0]): + maxwidth = quantile(sorted(map(lambda x:x[0], rects)), 0.75) + maxheight = quantile(sorted(map(lambda x:x[1], rects)), 0.75) + + if math.sqrt(maxwidth**2+maxheight**2) < 4000: + # TODO FIXME + svw[size] = (maxwidth,maxheight) + ratios += [maxwidth/maxheight] + + if verbose: print(str(size)+"\t"+str(math.sqrt(maxwidth**2+maxheight**2))+"\t\t"+str(len(rects))) + + print ("median ratio = "+str(quantile(sorted(ratios),0.5))) + + coeff_vs_stddev=[] + for coeff in [x/100 for x in range(0,100,1)]: + quotients = [] + for size, rect in svw.items(): + if size != 0: + diag = math.sqrt(rect[0]**2+rect[1]**2) + quotients += [diag / size**coeff] + + coeff_vs_stddev += [(coeff, avg(quotients), stddev(normalize(quotients)))] + + best = min(coeff_vs_stddev, key=lambda v:v[2]) + + print("diag / size**"+str(best[0])+" = "+str(best[1])) + + def analyze_visible_window(self, verbose=False): + for ncells in sorted(self.data.size_vs_visible_window.keys()): + if len(self.data.size_vs_visible_window[ncells]) > 0: + print("\nwith "+str(ncells)+" cells, depending on sum(size)") + try: + self.analyze_visible_window_helper(self.data.size_vs_visible_window[ncells], verbose) + except ZeroDivisionError: + print("\toops.") + for ncells in sorted(self.data.mass_vs_visible_window.keys()): + if len(self.data.mass_vs_visible_window[ncells]) > 0: + print("\nwith "+str(ncells)+" cells, depending on sum(mass)") + try: + self.analyze_visible_window_helper(self.data.mass_vs_visible_window[ncells], verbose) + except ZeroDivisionError: + print("\toops.") + + def analyze_deviations(self, celltype): + ds = self.data.eject_deviations[celltype] + + try: + mean, stddev = fit_gaussian(ds) + except: + mean, stddev = "???", "???" + + + quant = quantile(list(map(abs, ds)), 0.75) + + print(celltype+" eject/split direction deviations: mean = "+str(mean)+", stddev="+str(stddev)+", ndata="+str(len(ds))) + print("\t75%% of the splits had a deviation smaller than %.2f rad = %.2f deg" % (quant, quant*180/math.pi)) + print("") + + + #a,b = numpy.histogram(ds, bins=100) + #midpoints = map(lambda x : (x[0]+x[1])/2, zip(b, b[1:])) + #for n,x in zip(a,midpoints): + # print(str(n) + "\t" + str(x)) + + def analyze_distances(self, celltype): + ds = [v[0] for v in self.data.eject_distlogs[celltype]] + ns = [v[4] for v in self.data.eject_distlogs[celltype]] + + try: + mean, stddev = fit_gaussian(ds) + meann, stddevn = fit_gaussian(ns) + except: + mean, stddev = "???", "???" + meann, stddevn = "???", "???" + + print(celltype+" eject/split distances: mean = "+str(mean) +", stddev ="+str(stddev) +", ndata="+str(len(ds))) + print(celltype+" meann = "+str(meann)+", stddevn ="+str(stddevn)) + + #a,b = numpy.histogram(ds, bins=100) + #midpoints = list(map(lambda x : (x[0]+x[1])/2, zip(b, b[1:]))) + #for n,x in zip(a,midpoints): + # print(str(n) + "\t" + str(x)) + + #maxidx = max(range(0,len(a)), key = lambda i : a[i]) + #print("\tmaximum at "+str(midpoints[maxidx])) + + #q = 75 if celltype == "ejected mass" else 75 + #quant = quantile(list(map(lambda v : abs(v-midpoints[maxidx]), ds)), q/100) + #print("\t"+str(q)+"% of values lie have a distance of at most "+str(quant)+" from the maximum") + + mid, delta = find_smallest_q_confidence_area(ds, 0.75) + print("\t75%% of the distances lie in the interval %.2f plusminus %.2f" % (mid,delta)) + print("\t%2d%% of the distances lie in the interval %.2f plusminus %.2f" % (100*get_delta_confidence(ds, mid, delta*1.2), mid, delta*1.2) ) + print("\tmax = %.2f" % (max(ds))) + mid, delta = find_smallest_q_confidence_area(ns, 0.75) + print("\t75%% of the flight lengths lie in the interval %.2f plusminus %.2f" % (mid,delta)) + print("\t%2d%% of the flight lengths lie in the interval %.2f plusminus %.2f" % (100*get_delta_confidence(ns,mid,delta*1.2),mid,delta*1.2)) + print("") + + def analyze_virus_sizes(self): + print("\nI've seen the following %d virus sizes:" % len(self.data.observed_virus_sizes)) + for size, ndata in sorted(self.data.observed_virus_sizes.items(), key=lambda x:x[0]): + print("\t%4d: %7d times" % (size, ndata)) + + def analyze_remerge(self): + relevant = list(filter(lambda r : r.is_parent_child, self.data.remerging.values())) + durations = list(map(lambda r : r.end_time - r.begin_time, relevant)) + print("75%% of the remerge durations lie at %.2f plusminus %.2f frames" % find_smallest_q_confidence_area(durations,0.75)) + waittimes = list(map(lambda r : r.begin_time - max(r.birth1, r.birth2), relevant)) + print("75%% of the remerges were started after %.2f plusminus %.2f frames" % find_smallest_q_confidence_area(waittimes,0.75)) + diff --git a/strategy.py b/strategy.py index 0d2d8f0..3d5721a 100644 --- a/strategy.py +++ b/strategy.py @@ -1,15 +1,25 @@ import math from interval_utils import * -import gui import random +import nogui +import mechanics + +friendly_players=["Windfisch","windfisch","Cyanide","cyanide"] +\ + ["Midna","Nayru","Farore","Din","Ezelo","Navi","Zelda","Tetra","Link","Ciela","Linebeck","Salia","Epona","Shiek"] +\ + ["Vaati","Ganon","Ganondorf","Ghirahim","Agahnim"] class Strategy: - def __init__(self, c): + def __init__(self, c, gui=None): self.target = (0,0) self.has_target = False self.target_cell = None self.color = (0,0,0) self.c = c + self.do_approach_friends = True + if gui != None: + self.gui = gui + else: + self.gui = nogui def get_my_smallest(self): return sorted(self.c.player.own_cells, key = lambda x: x.mass)[0] @@ -43,9 +53,12 @@ class Strategy: def nonsplitkiller(self, cell): return not cell.is_virus and not cell.is_food and 1.20*self.get_my_smallest().mass < cell.mass and cell.mass < 1.25*2*self.get_my_smallest().mass - def quality(self, cell): + def quality(self, cell, myspeed): dd_sq = max((cell.pos[0]-self.c.player.center[0])**2 + (cell.pos[1]-self.c.player.center[1])**2,0.001) - sigma = 500 + sigma = 500 * max(cell.mass,1) # TODO FIXME don't try to eat running away cells + if mechanics.speed(cell) - myspeed >= 0: + sigma = sigma / 3 / math.exp((mechanics.speed(cell)-myspeed)/10) + dist_score = -math.exp(-dd_sq/(2*sigma**2)) rivals = filter(lambda r : self.rival(r,cell), self.c.world.cells.values()) @@ -105,21 +118,123 @@ class Strategy: def process_frame(self): runaway = False - my_smallest = min(map(lambda cell : cell.mass, self.c.player.own_cells)) - my_largest = max(map(lambda cell : cell.mass, self.c.player.own_cells)) + my_smallest = min(self.c.player.own_cells, key=lambda cell : cell.mass) + my_largest = max(self.c.player.own_cells, key=lambda cell : cell.mass) + + friendly_cells = list(filter(lambda c : c.is_virus or c.name in friendly_players, self.c.world.cells.values())) + + if friendly_cells: + dist_to_friend = min(map(lambda c : (self.c.player.center-c.pos).len() - max(my_largest.size, c.size), friendly_cells)) + else: + dist_to_friend = float('inf') + + if dist_to_friend < 20 or my_largest.mass < 36: + if self.do_approach_friends: print("not approaching friends") + self.do_approach_friends = False + elif dist_to_friend > 200 and my_largest.mass > 36 + 10*16: + if not self.do_approach_friends: print("approaching friends") + self.do_approach_friends = True + + if friendly_cells and self.do_approach_friends: + friend_to_feed = max(friendly_cells, key=lambda c:c.mass) + if friend_to_feed.mass < 1.25 * my_largest.mass: + print("friend too small") + friend_to_feed = None + if friend_to_feed: + self.gui.hilight_cell(friend_to_feed, (255,255,255),(255,127,127),30) + + self.target_cell = friend_to_feed + self.has_target = True + + if self.do_approach_friends: + for c in self.c.player.own_cells: + self.gui.hilight_cell(c, (255,255,255), (255,127,127), 20) + + # can this cell feed that cell? + # "False" means "No, definitely not" + # "True" means "Maybe" + def can_feed(this, that): + if that.is_food or that.is_ejected_mass or that.size < 43: # too small cells cannot eat the ejected mass + return False + + relpos = this.pos-that.pos + dist = relpos.len() + if dist == 0 or dist >= 700 + this.size + that.size: + return False + + return check_cell_in_interval(this.pos, that, (this.movement_angle - 10*math.pi/180, this.movement_angle + 10*math.pi/180)) + + + success_rate = 0 + for my_cell in self.c.player.own_cells: + try: + my_cell.movement_angle + except AttributeError: + print("cannot calculate shoot angle, too few backlog") + continue + # check if ejecting mass would feed a friend + possibly_feedable_cells = list(filter(lambda c : can_feed(my_cell, c), self.c.world.cells.values())) + possibly_feedable_cells.sort(key = lambda c : (my_cell.pos - c.pos).len()) + good_intervals = [] + for feedable in possibly_feedable_cells: + self.gui.hilight_cell(feedable, (255,192,127), (127,127,255)) + if feedable not in friendly_cells: + break - # enemy/virus avoidance + good_intervals += canonicalize_angle_interval( interval_occupied_by_cell(my_cell.pos, feedable) ) + + good_intervals = merge_intervals(good_intervals) + area = interval_area( intersection(good_intervals, canonicalize_angle_interval((my_cell.movement_angle - mechanics.eject_delta*math.pi/180, my_cell.movement_angle + mechanics.eject_delta*math.pi/180))) ) + success_rate += area / (2*mechanics.eject_delta*math.pi/180) / len(list(self.c.player.own_cells)) + + + self.gui.draw_bar(((100,40),(500,24)), success_rate, thresh=.80, color=(0,0,127)) + if success_rate >= 0.80: + self.c.send_shoot() + + + + # enemy/virus/friend-we-would-kill avoidance forbidden_intervals = [] for cell in self.c.world.cells.values(): relpos = ((cell.pos[0]-self.c.player.center[0]),(cell.pos[1]-self.c.player.center[1])) dist = math.sqrt(relpos[0]**2+relpos[1]**2) - if (not cell.is_virus and dist < ((500+2*cell.size) if cell.mass > 1.25*my_smallest*2 else (300+cell.size)) and cell.mass > 1.25 * my_smallest) or (cell.is_virus and dist < my_largest and cell.mass < my_largest): - angle = math.atan2(relpos[1],relpos[0]) - corridor_halfwidth = math.asin(cell.size / dist) - forbidden_intervals += canonicalize_angle_interval((angle-corridor_halfwidth, angle+corridor_halfwidth)) - runaway = True + # find out the allowed minimum distance + allowed_dist = None + + if cell.is_virus: + if cell.mass < my_largest.mass: + allowed_dist = cell.size+2 + else: + allowed_dist = "don't care" + elif cell in friendly_cells: + if 1.25 * my_largest.mass > cell.mass: # we're dangerous to our friends + allowed_dist = my_largest.size + 40 + elif (cell not in self.c.player.own_cells and not cell.is_virus and not cell.is_ejected_mass and not cell.is_food) and cell.mass + 20 > 1.25 * my_smallest.mass: # our enemy is, or will be dangerous to us + if (cell.mass + 20) / 2 < 1.25 * my_smallest.mass: + # they can't splitkill us (soon) + allowed_dist = cell.size + 75 + elif cell.mass / 15. < self.c.player.total_mass: + # they can and they will splitkill us + allowed_dist = 650 + cell.size + else: + # we're too small, not worth a splitkill. they have absolutely no + # chance to chase us + allowed_dist = cell.size + 10 + else: + allowed_dist = "don't care" + + if allowed_dist != "don't care" and dist < allowed_dist: + try: + angle = math.atan2(relpos[1],relpos[0]) + corridor_halfwidth = math.asin(min(1, cell.size / dist)) + forbidden_intervals += canonicalize_angle_interval((angle-corridor_halfwidth, angle+corridor_halfwidth)) + runaway = True + except: + print("TODO FIXME: need to handle enemy cell which is in our centerpoint!") + print("dist=%.2f, allowed_dist=%.2f" % (dist, allowed_dist)) # wall avoidance if self.c.player.center[0] < self.c.world.top_left[1]+(self.c.player.total_size*2): @@ -138,8 +253,13 @@ class Strategy: forbidden_intervals = merge_intervals(forbidden_intervals) allowed_intervals = invert_angle_intervals(forbidden_intervals) + + try: + (a,b) = find_largest_angle_interval(allowed_intervals) + except: + print("TODO FIXME: need to handle no runaway direction being available!") + (a,b) = (0,0) - (a,b) = find_largest_angle_interval(allowed_intervals) runaway_angle = (a+b)/2 runaway_x, runaway_y = (self.c.player.center[0]+int(100*math.cos(runaway_angle))), (self.c.player.center[1]+int(100*math.sin(runaway_angle))) @@ -148,27 +268,25 @@ class Strategy: self.target_cell = None self.color = (255,0,0) - print ("Running away: " + str((runaway_x-self.c.player.center[0], runaway_y-self.c.player.center[1]))) # a bit of debugging information for i in forbidden_intervals: - gui.draw_arc(self.c.player.center, self.c.player.total_size+10, i, (255,0,255)) + self.gui.draw_arc(self.c.player.center, self.c.player.total_size+10, i, (255,0,255)) - # if however there's no enemy to avoid, chase food or jizz randomly around - else: + # if however there's no enemy to avoid, try to feed a friend. or chase food or jizz randomly around + else: if self.target_cell != None: self.target = tuple(self.target_cell.pos) - if self.target_cell not in self.c.world.cells.values() or not self.edible(self.target_cell): + if self.target_cell not in self.c.world.cells.values() or (not self.edible(self.target_cell) and not self.target_cell in friendly_cells): self.target_cell = None self.has_target = False - print("target_cell does not exist any more") elif self.target == tuple(self.c.player.center): self.has_target = False print("Reached random destination") if not self.has_target: food = list(filter(self.edible, self.c.world.cells.values())) - food = sorted(food, key = self.quality) + food = sorted(food, key = lambda c : self.quality(c, mechanics.speed(my_largest))) if len(food) > 0: self.target = (food[0].pos[0], food[0].pos[1]) @@ -176,8 +294,6 @@ class Strategy: self.has_target = True self.color = (0,0,255) - print("weight: ", self.weight_cell(self.target_cell)) - print("Found food at: " + str(food[0].pos)) else: rx = self.c.player.center[0] + random.randrange(-400, 401) ry = self.c.player.center[1] + random.randrange(-400, 401) @@ -188,6 +304,6 @@ class Strategy: # more debugging - gui.draw_line(self.c.player.center, self.target, self.color) + self.gui.draw_line(self.c.player.center, self.target, self.color) return self.target diff --git a/subscriber.py b/subscriber.py index a637e67..b89a6a9 100644 --- a/subscriber.py +++ b/subscriber.py @@ -1,5 +1,7 @@ from log import log +from collections import deque import sys +import mechanics class DummySubscriber: def on_connect_error(self,s): @@ -65,3 +67,191 @@ class DummySubscriber: def on_debug_line(self,x,y): log("debug line") +class CellHistory: + def __init__(self): + self.poslog = deque(maxlen=300) + self.stale = False + +class OtherPlayer: + def __init__(self, playerid): + self.playerid = playerid + self.cells = set() + +class EnhancingSubscriber(DummySubscriber): + def __init__(self): + self.c = None + self.history = {} + self.time = 0 + self.victims = {} + + def set_client(self,c): + self.c = c + + def cleanup_victims(self): + delete = [] + + for eater in self.victims: + self.victims[eater] = list(filter(lambda v : v[1] < self.time - 100, self.victims[eater])) + if len(self.victims[eater]) == 0: + delete += [eater] + + for eater in delete: + del self.victims[eater] + + def on_cell_eaten(self, eater_id, eaten_id): + if eater_id in self.c.world.cells and self.c.world.cells[eater_id].is_virus: + print("virus ate something!") + + if eater_id not in self.victims: + self.victims[eater_id] = [] + + self.victims[eater_id] += [(self.c.world.cells[eaten_id], self.time)] + + def on_world_update_post(self): + self.c.world.time = self.time + self.time += 1 + + if self.time % 100 == 0: + self.cleanup_victims() + + # create and purge poslog history, movement and movement_angle + for cid in self.history: + self.history[cid].stale = True + + for cid in self.c.world.cells: + if cid not in self.history: + self.history[cid] = CellHistory() + + self.history[cid].poslog.append(self.c.world.cells[cid].pos.copy()) + self.c.world.cells[cid].poslog = self.history[cid].poslog + + self.history[cid].stale = False + + self.history = {k: v for k, v in self.history.items() if v.stale == False} + + + for cid in self.c.world.cells: + cell = self.c.world.cells[cid] + + if not hasattr(cell, "spawntime"): + cell.spawntime = self.c.world.time + + try: + oldpos = cell.poslog[-3-1] + cell.movement = (cell.pos - oldpos)/3 + cell.movement_angle = cell.movement.angle() + except (AttributeError, IndexError): + pass + + + # create OtherPlayer entries + otherplayers = {} + for cell in self.c.world.cells.values(): + playerid = None + if not cell.is_food and not cell.is_ejected_mass and not cell.is_virus: + playerid = (cell.name, cell.color) + elif cell.is_virus: + playerid = "virus" + elif cell.is_food: + playerid = "food" + elif cell.is_ejected_mass: + playerid = "ejected mass" + else: + playerid = "???" + + if playerid not in otherplayers: + otherplayers[playerid] = OtherPlayer(playerid) + + cell.player = otherplayers[playerid] + cell.player.cells.add(cell) + + # detect split cells and clean up obsolete parent references + for cell in self.c.world.cells.values(): + # create attribute if not already there + try: + cell.parent = cell.parent + except: + cell.parent = None + cell.calmed_down = True + + # clean up obsolete parent references + if cell.parent and cell.parent.cid not in self.c.world.cells: + cell.parent = None + + # find split cells + is_split = False + if not cell.is_food and not cell.is_ejected_mass and not cell.is_virus: + try: + if cell.parent == None and cell.movement.len() > 2 * mechanics.speed(cell.size): + print("looks like a split!"+str(cell.movement.len() / mechanics.speed(cell.size))) + is_split = True + except AttributeError: + pass + + if is_split: + history_len = len(cell.poslog) + cell.parent = min(cell.player.cells, key=lambda c : (c.poslog[-history_len] - cell.poslog[-history_len]).len() if c != cell and len(c.poslog) >= history_len else float('inf')) + try: + cell.shoot_vec = cell.parent.movement.copy() + except: + cell.shoot_vec = None + cell.calmed_down = False + + elif cell.is_virus: + try: + if cell.parent == None and cell.movement.len() > 0: + print("split virus!") + is_split = True + except AttributeError: + pass + + if is_split: + cell.parent = min(cell.player.cells, key=lambda c : (c.pos - cell.poslog[0]).len() if c != cell else float('inf')) + try: + last_feed = self.victims[cell.parent.cid][-1][0] + if not last_feed.is_ejected_mass: + print("wtf, last virus feed was not ejected mass?!") + raise KeyError + else: + cell.shoot_vec = cell.parent.pos - last_feed.poslog[0] + cell.shoot_vec2 = last_feed.poslog[-1] - last_feed.poslog[0] + try: + pos_when_shot = last_feed.parent.poslog[-len(last_feed.poslog)] + cell.shoot_vec3 = cell.parent.pos - pos_when_shot + except: + print("MOAAAHH") + cell.shoot_vec3 = None + except KeyError: + print("wtf, no last virus feed?!") + cell.shoot_vec = None + cell.shoot_vec2 = None + cell.shoot_vec3 = None + + cell.calmed_down = False + + elif cell.is_ejected_mass: + try: + if cell.parent == None and cell.movement.len() > 0: + print("ejected mass!") + is_split = True + except AttributeError: + pass + + if is_split: + history_len = len(cell.poslog) + try: + cell.parent = min(filter(lambda c : not c.is_ejected_mass and not c.is_food and not c.is_virus and c.color == cell.color, self.c.world.cells.values()), key=lambda c : (c.poslog[-history_len] - cell.poslog[-history_len]).len() if len(c.poslog) >= history_len else float('inf')) + try: + cell.shoot_vec = cell.parent.movement.copy() + except: + cell.shoot_vec = None + cell.calmed_down = False + except ValueError: + # if no possible parents are found, min will raise a ValueError. ignore that. + pass + + if is_split: + cell.spawnpoint = cell.pos.copy() + cell.parentsize_when_spawned = cell.parent.size if cell.parent != None else None + cell.parentpos_when_spawned = cell.parent.pos.copy() if cell.parent != None else None + |