From b1492078b6b23d2ead2aeddeca3fd0f4f69df0ef Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Wed, 26 Aug 2015 22:51:02 +0200 Subject: mechanics.py contains the reverse-engineered formulas for the game mechanics --- mechanics.py | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 mechanics.py (limited to 'mechanics.py') diff --git a/mechanics.py b/mechanics.py new file mode 100644 index 0000000..d242493 --- /dev/null +++ b/mechanics.py @@ -0,0 +1,3 @@ +def speed(size): + return 86 / (size**0.45) + -- cgit v1.2.3 From f13b8a44441206a4f761002ed3adabd129601ba1 Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Fri, 28 Aug 2015 00:29:04 +0200 Subject: use new zoom formula --- game_mechanics.txt | 1 + gui.py | 47 +++++++++++++++++++--- mechanics.py | 3 ++ reversing_game_mechanics/zoomlevel/README | 2 + reversing_game_mechanics/zoomlevel/fit.log | 46 --------------------- .../zoomlevel/win.size.gnuplot | 5 ++- 6 files changed, 51 insertions(+), 53 deletions(-) delete mode 100644 reversing_game_mechanics/zoomlevel/fit.log (limited to 'mechanics.py') diff --git a/game_mechanics.txt b/game_mechanics.txt index 1bb5987..9c64805 100644 --- a/game_mechanics.txt +++ b/game_mechanics.txt @@ -5,3 +5,4 @@ can eat ejected mass if mass >= 18 i.e. size >= 43 cell can eat us, if their size/mass(??) is at least 1.25* our size/mass +zoom level is 369.399 * sum(own_cells.size) ** 0.431776 diff --git a/gui.py b/gui.py index ed5c9d3..f4654ef 100644 --- a/gui.py +++ b/gui.py @@ -6,6 +6,7 @@ from pygame.locals import * import sys import math import time +import mechanics from agarnet.agarnet.vec import Vec running = True @@ -136,12 +137,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) / 2 -zoom = calc_zoom() def world_to_win_length(l): return int(l*zoom) @@ -238,6 +258,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) @@ -291,8 +324,10 @@ def draw_frame(): 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())) @@ -327,7 +362,7 @@ 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() diff --git a/mechanics.py b/mechanics.py index d242493..1f9d5cc 100644 --- a/mechanics.py +++ b/mechanics.py @@ -1,3 +1,6 @@ def speed(size): return 86 / (size**0.45) +def viewport_diag(sizesum): + return 370 * max(sizesum,70)**0.431776 + diff --git a/reversing_game_mechanics/zoomlevel/README b/reversing_game_mechanics/zoomlevel/README index 7845ea3..a2acc90 100644 --- a/reversing_game_mechanics/zoomlevel/README +++ b/reversing_game_mechanics/zoomlevel/README @@ -28,3 +28,5 @@ 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/fit.log b/reversing_game_mechanics/zoomlevel/fit.log deleted file mode 100644 index 10e4639..0000000 --- a/reversing_game_mechanics/zoomlevel/fit.log +++ /dev/null @@ -1,46 +0,0 @@ - - -******************************************************************************* -Thu Aug 27 21:04:27 2015 - - -FIT: data read from "win.size.all.filtered" using 1:2 - format = x:z - #datapoints = 227 - residuals are weighted equally (unit weight) - -function used for fitting: f(x) -fitted parameters initialized with current variable values - - - - Iteration 0 - WSSR : 1.99006e+09 delta(WSSR)/WSSR : 0 - delta(WSSR) : 0 limit for stopping : 1e-05 - lambda : 543.709 - -initial set of free parameter values - -a = 1 -b = 1 - -After 187 iterations the fit converged. -final sum of squares of residuals : 316175 -rel. change during last iteration : -9.20903e-11 - -degrees of freedom (FIT_NDF) : 225 -rms of residuals (FIT_STDFIT) = sqrt(WSSR/ndf) : 37.4863 -variance of residuals (reduced chisquare) = WSSR/ndf : 1405.22 - -Final set of parameters Asymptotic Standard Error -======================= ========================== - -a = 369.399 +/- 4.401 (1.191%) -b = 0.431776 +/- 0.002383 (0.5519%) - - -correlation matrix of the fit parameters: - - a b -a 1.000 -b -0.998 1.000 diff --git a/reversing_game_mechanics/zoomlevel/win.size.gnuplot b/reversing_game_mechanics/zoomlevel/win.size.gnuplot index 90886c3..aa5499c 100644 --- a/reversing_game_mechanics/zoomlevel/win.size.gnuplot +++ b/reversing_game_mechanics/zoomlevel/win.size.gnuplot @@ -2,7 +2,9 @@ min(a,b)=(ab)?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, \ @@ -12,5 +14,6 @@ plot "win.size.1" using 1:2:(min(1,$3/100)) lt rgb "red" 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" + f(x) lt rgb "black", \ + g(x) lt rgb "black" pause -1 -- cgit v1.2.3 From 738d057c6da4aaca7516158db55f3553a03cf189 Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Tue, 1 Sep 2015 18:14:37 +0200 Subject: better "can i safely feed" estimation --- gui.py | 4 ++-- mechanics.py | 1 + strategy.py | 9 +++++---- 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'mechanics.py') diff --git a/gui.py b/gui.py index 001fc80..2a8460c 100644 --- a/gui.py +++ b/gui.py @@ -209,8 +209,8 @@ def draw_cell(cell): 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 + 26*math.pi/180), math.sin(mov_ang + 26*math.pi/180) ) * (cell.size+700) - p3 = cell.pos + Vec( math.cos(mov_ang - 26*math.pi/180), math.sin(mov_ang - 26*math.pi/180) ) * (cell.size+700) + 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) diff --git a/mechanics.py b/mechanics.py index 1f9d5cc..5f2254b 100644 --- a/mechanics.py +++ b/mechanics.py @@ -4,3 +4,4 @@ def speed(size): 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/strategy.py b/strategy.py index 900cf8f..bbbe07d 100644 --- a/strategy.py +++ b/strategy.py @@ -2,6 +2,7 @@ import math from interval_utils import * 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"] +\ @@ -181,12 +182,12 @@ class Strategy: 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 - 10*math.pi/180, my_cell.movement_angle + 10*math.pi/180))) ) - success_rate += area / (2*10*math.pi/180) / len(list(self.c.player.own_cells)) + 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=.98, color=(0,0,127)) - if success_rate >= 0.98: + 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() -- cgit v1.2.3 From 7c1180a7b58e7b8c17c8dab297058d0c001386c6 Mon Sep 17 00:00:00 2001 From: Florian Jung Date: Tue, 1 Sep 2015 20:40:10 +0200 Subject: try to chase less --- mechanics.py | 12 ++++++++++-- strategy.py | 9 ++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'mechanics.py') diff --git a/mechanics.py b/mechanics.py index 5f2254b..3aaa405 100644 --- a/mechanics.py +++ b/mechanics.py @@ -1,5 +1,13 @@ -def speed(size): - return 86 / (size**0.45) +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 diff --git a/strategy.py b/strategy.py index eeacc4f..3d5721a 100644 --- a/strategy.py +++ b/strategy.py @@ -53,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()) @@ -283,7 +286,7 @@ class Strategy: 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]) -- cgit v1.2.3