def fly_tick(self): " Iterate one flight tick " addx, addy = utils.components(self.speed * self.layout.dt, self.angle) self.x += addx self.y += addy # Check for out of bounds oob = False if self.x < 0: self.x = 0 oob = True elif self.x > self.layout.xsize: self.x = self.layout.xsize oob = True if self.y < 0: self.y = 0 oob = True elif self.y > self.layout.ysize: self.y = self.layout.ysize oob = True if oob: self.flying = False self.vspeed = 0 self.speed = 0 self.z = 0 self.xland = self.x self.yland = self.y else: self.vspeed += -self.g * self.layout.dt self.z += self.vspeed * self.layout.dt if self.z <= 0.: self.flying = False
def fly_tick(self): " Iterate one flight tick " addx, addy = utils.components(self.speed*self.layout.dt,self.angle) self.x += addx self.y += addy # Check for out of bounds oob=False if self.x < 0: self.x = 0 oob = True elif self.x > self.layout.xsize: self.x = self.layout.xsize oob = True if self.y < 0: self.y = 0 oob = True elif self.y > self.layout.ysize: self.y = self.layout.ysize oob = True if oob: self.flying = False self.vspeed=0 self.speed=0 self.z=0 self.xland=self.x self.yland=self.y else: self.vspeed += -self.g * self.layout.dt self.z += self.vspeed * self.layout.dt if self.z <= 0.: self.flying = False
def makeislands(seq,gaplength): L = list(utils.components(seq,rel=lambda x,y: s_distance(x,y)<=gaplength)) L.sort(key=lambda L: L[0].SSTART) for i,island in enumerate(L,1): suff = '_{}'.format(i) for hit in island: hit['SSEQID'] += suff return L
def prevent_friendly_collisions(self): """ Ensure objective locations of same team players are spaced. """ # Change objectives to pointing just in front of player, rather than # potentially a long way away. for p in self.players.values(): angle = math.atan2(p.y_objective - p.y, p.x_objective - p.x) xadd, yadd = utils.components(p.top_speed * self.dt, angle) p.x_objective = p.x + xadd p.y_objective = p.y + yadd for thisP, thatP in itertools.combinations(self.players.values(), 2): if thisP.state == 0 or thatP.state == 0: continue # Prone players don't count elif thisP.team != thatP.team: continue # Different teams, probably WANT to collide... else: dist = np.sqrt( (thisP.x_objective-thatP.x_objective)**2 +\ (thisP.y_objective-thatP.y_objective)**2 )\ - thisP.size - thatP.size if dist < 0: # We need to adjust the objectives. # Find mid-point of current positions cx = (thisP.x + thatP.x) / 2. cy = (thisP.y + thatP.y) / 2. # Find mid-point of objectives ox = (thisP.x_objective + thatP.x_objective) / 2. oy = (thisP.y_objective + thatP.y_objective) / 2. # Find angle of line between two objectives. hpi = 2 * math.atan(1.) angle = math.atan2(cy - oy, cx - ox) # Find angle of p.b. of this line pb_angle = -1 / angle # Project along the p.b. line enough to seperate the two objectives pdist = -dist / 2. thisx_delta, thisy_delta = utils.components( pdist, pb_angle) thatx_delta, thaty_delta = utils.components( pdist, pb_angle + hpi) thisP.x_objective += thisx_delta thisP.y_objective += thisy_delta thatP.x_objective += thatx_delta thatP.y_objective += thaty_delta
def project_move(self, acc_angle): """ Projects player one tick by applying max acceleration at the given angle. Returns ------- Tuple of the projected phase (x,y, angle, speed) """ vx, vy = utils.components(self.current_speed, self.angle) ax, ay = utils.components(self.acc * self.layout.dt, acc_angle) vx_new, vy_new = (vx + ax, vy + ay) angle_new = math.atan2(vy_new, vx_new) speed_new = min(np.sqrt(vx_new ** 2 + vy_new ** 2), self.top_speed) # Speed limited components vx_new, vy_new = utils.components(speed_new, angle_new) return (self.x + vx_new * self.layout.dt, self.y + vy_new * self.layout.dt, angle_new, speed_new)
def project_move(self,acc_angle): """ Projects player one tick by applying max acceleration at the given angle. Returns ------- Tuple of the projected phase (x,y, angle, speed) """ vx, vy = utils.components(self.current_speed,self.angle) ax, ay = utils.components(self.acc*self.layout.dt,acc_angle) vx_new, vy_new = (vx + ax,vy + ay) angle_new = math.atan2(vy_new,vx_new) speed_new = min(np.sqrt( vx_new**2 + vy_new**2),self.top_speed) # Speed limited components vx_new, vy_new = utils.components(speed_new,angle_new) return (self.x + vx_new*self.layout.dt, self.y + vy_new*self.layout.dt, angle_new, speed_new)
def unproject_move(self, acc_angle): """ Reverses the effect of a projection at the specified angle. Returns ------- Tuple of the projected phase (x,y, angle, speed) """ hpi = 2 * math.atan(1.0) vx, vy = utils.components(self.current_speed, self.angle + hpi) ax, ay = utils.components(self.acc * self.layout.dt, acc_angle + hpi) vx_new, vy_new = (vx + ax, vy + ay) angle_new = math.atan2(vy_new, vx_new) speed_new = min(np.sqrt(vx_new ** 2 + vy_new ** 2), self.top_speed) # Speed limited components vx_new, vy_new = utils.components(speed_new, angle_new) return (self.x + vx_new, self.y + vy_new, angle_new, speed_new)
def unproject_move(self,acc_angle): """ Reverses the effect of a projection at the specified angle. Returns ------- Tuple of the projected phase (x,y, angle, speed) """ hpi = 2*math.atan(1.) vx, vy = utils.components(self.current_speed,self.angle+hpi) ax, ay = utils.components(self.acc*self.layout.dt,acc_angle+hpi) vx_new, vy_new = (vx + ax,vy + ay) angle_new = math.atan2(vy_new,vx_new) speed_new = min(np.sqrt( vx_new**2 + vy_new**2),self.top_speed) # Speed limited components vx_new, vy_new = utils.components(speed_new,angle_new) return (self.x + vx_new, self.y + vy_new, angle_new, speed_new)
def prevent_friendly_collisions(self): """ Ensure objective locations of same team players are spaced. """ # Change objectives to pointing just in front of player, rather than # potentially a long way away. for p in self.players.values(): angle = math.atan2(p.y_objective-p.y,p.x_objective-p.x) xadd, yadd = utils.components(p.top_speed*self.dt,angle) p.x_objective = p.x + xadd p.y_objective = p.y + yadd for thisP, thatP in itertools.combinations(self.players.values(), 2): if thisP.state == 0 or thatP.state == 0: continue # Prone players don't count elif thisP.team != thatP.team: continue # Different teams, probably WANT to collide... else: dist = np.sqrt( (thisP.x_objective-thatP.x_objective)**2 +\ (thisP.y_objective-thatP.y_objective)**2 )\ - thisP.size - thatP.size if dist < 0: # We need to adjust the objectives. # Find mid-point of current positions cx = (thisP.x + thatP.x)/2. cy = (thisP.y + thatP.y)/2. # Find mid-point of objectives ox = (thisP.x_objective + thatP.x_objective)/2. oy = (thisP.y_objective + thatP.y_objective)/2. # Find angle of line between two objectives. hpi=2*math.atan(1.) angle = math.atan2(cy-oy,cx-ox) # Find angle of p.b. of this line pb_angle = -1/angle # Project along the p.b. line enough to seperate the two objectives pdist = -dist/2. thisx_delta, thisy_delta = utils.components(pdist,pb_angle) thatx_delta, thaty_delta = utils.components(pdist,pb_angle+hpi) thisP.x_objective += thisx_delta thisP.y_objective += thisy_delta thatP.x_objective += thatx_delta thatP.y_objective += thaty_delta
def launch(self,elv,power,target_x,target_y): """ Initialise throw with given angle and power from current ball position. """ self.carrier=0 self.z=2. # Assume passes start 2m off the ground. self.angle = math.atan2(target_y-self.y,target_x-self.x) self.speed = power*math.cos(elv) self.vspeed = power*math.sin(elv) self.flying = True dist = power**2 * math.sin(2.*elv)/self.g dx, dy = utils.components(dist,self.angle) self.xland = self.x + dx self.yland = self.y + dy
def launch(self, elv, power, target_x, target_y): """ Initialise throw with given angle and power from current ball position. """ self.carrier = 0 self.z = 2. # Assume passes start 2m off the ground. self.angle = math.atan2(target_y - self.y, target_x - self.x) self.speed = power * math.cos(elv) self.vspeed = power * math.sin(elv) self.flying = True dist = power**2 * math.sin(2. * elv) / self.g dx, dy = utils.components(dist, self.angle) self.xland = self.x + dx self.yland = self.y + dy
def classifyrecords(seq,overlap): '''Takes a sequence of blast hits; picks out as 'nests' sequences of adjacent hits that overlap with a neighbor. Returns a pair of lists: the first contains records that were not part of a nest, and the second contains nests, i.e. lists of the resulting 'extracted' hits from that nest. This function does not stratify those nests - for use in the final algorithm, they must go through the function stratify(). ''' sings,nests = utils.bifilter( utils.components(seq,lambda x,y: s_overlap(x,y)>=overlap), key=lambda x: len(x)==1) return (map(_itemget(0),sings),nests)
def featurize(self): features = [ ] # list of np.array[nfeatures, xsize, ysize] or np.array[xsize, ysize] feature_names = [] # list of strings deltas = (-1, 0, 1) neigh = np.zeros((len(deltas)**2, *self.in_image.shape), dtype=np.int8) for ox, oy in product(*map(range, self.in_image.shape)): # absolute neighbourhood color for k, (i, j) in enumerate(product(*[deltas] * 2)): x = (ox + i) # % self.in_image.shape[0] y = (oy + j) # % self.in_image.shape[1] if 0 <= x < self.in_image.shape[ 0] and 0 <= y < self.in_image.shape[1]: neigh[k, ox, oy] = self.in_image[x, y] else: neigh[k, ox, oy] = 0 k += 1 features.append(neigh) feature_names.extend( ['Neigh{}'.format(i) for i in product(*[deltas] * 2)]) # unique = np.zeros((3, *self.in_image.shape), dtype=np.int8) # 3 because row, column, neighborhood # unique_names = [] # for ox, oy in product(*map(range, self.in_image.shape)): # # absolute neighbourhood color # unique[0, ox, oy] = len(np.unique(self.in_image[:, oy])) # unique[1, ox, oy] = len(np.unique(self.in_image[ox, :])) # unique[2, ox, oy] = len(np.unique(self.in_image[max(ox - 1, 0) : ox + 2, # max(oy - 1, 0) : oy + 2])) # features.append(unique) # feature_names.extend(['UniqueInRow', 'UniqueInCol', 'UniqueInNeigh']) if self.task_featurizer is None or self.task_featurizer.use_rot_90: rotations = (False, True) else: rotations = (False, ) for use_rot in rotations: sym = np.zeros((4, *self.in_image.shape), dtype=np.int8) for ox, oy in product(*map(range, self.in_image.shape)): for k, (i, j) in enumerate(product(*([[0, 1]] * 2))): x, y = ox, oy if i: x = self.in_image.shape[0] - x - 1 if j: y = self.in_image.shape[1] - y - 1 if use_rot: if y >= self.in_image.shape[ 0] or x >= self.in_image.shape[1]: sym[k, ox, oy] = -1 else: sym[k, ox, oy] = self.in_image[y, x] else: sym[k, ox, oy] = self.in_image[x, y] features.append(sym) feature_names.extend( f'SymRot90_{i}{j}' if use_rot else f'Sym_{i}{j}' for i, j in product(*([[0, 1]] * 2))) deltas = [[1, 0], [-1, 0], [0, 1], [0, -1], [1, 1], [-1, -1], [-1, 1], [1, -1]] for di, d in enumerate(deltas): col_opts = [0, None] targets = [raycast(self.in_image, d, col) for col in col_opts] for t1, col in zip(targets, col_opts): cols, dists = Offset.get_cols_dists(t1, self.in_image) features.extend([dists % 2, dists % 3]) dists = dists.astype(np.float32) features.extend([cols, dists]) ray_type_label = 'Same' if col is None else 'Notbg' feature_names.extend([ f'RayCol{ray_type_label}_{d}_mod2', f'RayCol{ray_type_label}_{d}_mod3' ]) feature_names.extend([ f'RayCol{ray_type_label}_{d}', f'RayDist{ray_type_label}_{d}' ]) for t2, col2 in zip(targets, col_opts): off = Offset.compose(t1, t2) cols2, dists2 = Offset.get_cols_dists( off, self.in_image) dists2 = dists2.astype(np.float32) features.extend([cols2, dists2 - dists]) ray_type_label2 = 'Same' if col2 is None else 'Notbg' feature_names.extend([ f'RayCol{ray_type_label}_{ray_type_label2}_{d}', f'RayDist{ray_type_label}_{ray_type_label2}_{d}' ]) sizes, borders = components(self.in_image) sizes = sizes.astype(np.float32) border_exclusive = ((borders == borders.sum(2, keepdims=True)) * np.arange(1, COLORS + 1)).sum(2) - 1 features.extend([sizes, border_exclusive]) feature_names.extend(['ComponentSize', 'ComponentBorderExclusive']) features = np.concatenate( list( map( lambda x: (x if len(x.shape) == 3 else x.reshape( (-1, *x.shape))).astype(object), features))) features = features.reshape( (features.shape[0], -1)).transpose([1, 0]) return pd.DataFrame(features, columns=feature_names)
def fly_tick(self): " Iterate one flight tick " # Check for potential catchers # Assume we can only catch if z <= 2 metres. # TODO: Player heights and jumping?? addx, addy = utils.components(self.speed*self.layout.dt,self.angle) if self.z <= 2: # Ball at catchable height # Eqn of ball travelling line as ax + bx + c = 0 x2 = self.x + addx y2 = self.y + addy a = self.y - y2 b = x2 - self.x c = (self.x - x2)*self.y + (y2 - self.y)*self.x midx = (self.x + x2)/2. midy = (self.y + y2)/2. dflight = self.speed*self.layout.dt def catch_score(p): # Returns postion along flight path of ball for given player # Returns None if the player can't catch ball from their position if not p.want_to_catch: return None dist = abs(a*p.x + b* p.y + c)/np.sqrt(a**2 + b**2) if dist > p.size: return None # Check the position is bracketted in the flight delta elif np.sqrt( (midx-p.x)**2 + (midy-p.y)**2) > dflight/2. + p.size: return None else: return np.sqrt((p.x-self.x)**2 + (p.y-self.y)**2) # TODO: At the moment, first eligble catcher automatically catches. Need to implement skill # based chance, constested catches, etc. best_score=1000. pcatch=None for p in self.layout.players.values(): s = catch_score(p) if s != None: if s < best_score: best_score=s pcatch=p if pcatch != None: # Player had made catch print("caught it",pcatch.pid) self.carrier=pcatch.pid self.flying=False self.x = pcatch.x self.y = pcatch.y return self.x += addx self.y += addy # Check for out of bounds oob=False if self.x < 0: self.x = 0 oob = True elif self.x > self.layout.xsize: self.x = self.layout.xsize oob = True if self.y < 0: self.y = 0 oob = True elif self.y > self.layout.ysize: self.y = self.layout.ysize oob = True if oob: self.flying = False self.vspeed=0 self.speed=0 self.z=0 self.xland=self.x self.yland=self.y else: self.vspeed += -self.g * self.layout.dt self.z += self.vspeed * self.layout.dt if self.z <= 0.: self.flying = False
def fly_tick(self): " Iterate one flight tick " # Check for potential catchers # Assume we can only catch if z <= 2 metres. # TODO: Player heights and jumping?? addx, addy = utils.components(self.speed * self.layout.dt, self.angle) if self.z <= 2: # Ball at catchable height # Eqn of ball travelling line as ax + bx + c = 0 x2 = self.x + addx y2 = self.y + addy a = self.y - y2 b = x2 - self.x c = (self.x - x2) * self.y + (y2 - self.y) * self.x midx = (self.x + x2) / 2. midy = (self.y + y2) / 2. dflight = self.speed * self.layout.dt def catch_score(p): # Returns postion along flight path of ball for given player # Returns None if the player can't catch ball from their position if not p.want_to_catch: return None dist = abs(a * p.x + b * p.y + c) / np.sqrt(a**2 + b**2) if dist > p.size: return None # Check the position is bracketted in the flight delta elif np.sqrt((midx - p.x)**2 + (midy - p.y)**2) > dflight / 2. + p.size: return None else: return np.sqrt((p.x - self.x)**2 + (p.y - self.y)**2) # TODO: At the moment, first eligble catcher automatically catches. Need to implement skill # based chance, constested catches, etc. best_score = 1000. pcatch = None for p in self.layout.players.values(): s = catch_score(p) if s != None: if s < best_score: best_score = s pcatch = p if pcatch != None: # Player had made catch print("caught it", pcatch.pid) self.carrier = pcatch.pid self.flying = False self.x = pcatch.x self.y = pcatch.y return self.x += addx self.y += addy # Check for out of bounds oob = False if self.x < 0: self.x = 0 oob = True elif self.x > self.layout.xsize: self.x = self.layout.xsize oob = True if self.y < 0: self.y = 0 oob = True elif self.y > self.layout.ysize: self.y = self.layout.ysize oob = True if oob: self.flying = False self.vspeed = 0 self.speed = 0 self.z = 0 self.xland = self.x self.yland = self.y else: self.vspeed += -self.g * self.layout.dt self.z += self.vspeed * self.layout.dt if self.z <= 0.: self.flying = False