def executeMovement(self, move: DiscreteMove, targetPosition: np.ndarray, restrictedDuration: int = None, acceptableSinguityCount: int = None): def getLastingMoveDuration(moveDuration: int) -> int: minimumBoundDuration = moveDuration if move.minimumMoveTime is None else max( moveDuration, move.minimumMoveTime) maximumBoundDuration = minimumBoundDuration if restrictedDuration is None else min( minimumBoundDuration, restrictedDuration) return maximumBoundDuration originalMovementDuration = PhysicsEstimator.estimateMovementDuration( self.singuitiesMeanPosition, targetPosition, clusterStd=self.singuitiesStd, acceptableSinguityCount=None if acceptableSinguityCount is None else (self.singuityCount, acceptableSinguityCount)) constrainedMovementDuration = getLastingMoveDuration( originalMovementDuration) if constrainedMovementDuration == 0: return 0, self targetIsWithinStd = PhysicsEstimator.distance2( self.singuitiesMeanPosition, targetPosition) <= self.singuitiesStd**2 if targetIsWithinStd: ratioOfTimeSpentInside = min( constrainedMovementDuration * Singuity.MAXIMUM_SPEED_UNITS_PER_FRAME, self.singuitiesStd * 2) / (self.singuitiesStd * 2) newStd = min( PhysicsEstimator.getMinimumStd(self.singuityCount) * ratioOfTimeSpentInside + self.singuitiesStd * (1 - ratioOfTimeSpentInside), self.singuitiesStd) else: # maximum duration on a 5000 unit map newStd = self.singuitiesStd * (1 + constrainedMovementDuration / 1768) return constrainedMovementDuration,\ DiscretePlayer( self.isCurrentPlayer, self.id, self.singuityCount, self.singuitiesMeanPosition + (targetPosition - self.singuitiesMeanPosition) * (constrainedMovementDuration / constrainedMovementDuration), newStd, self.singuitiesAverageHealth )
def appendNewSpawned(self, spawners: List[Tuple[np.ndarray, int]], anteMoveFrameCount: int, postMoveFrameCount: int) -> DiscretePlayer: spawnerLastClaimedFrames = np.array([s[1] for s in spawners]) spawnerPositions = np.array([s[0] for s in spawners]) matureSpawnerDurations = np.maximum( 0, postMoveFrameCount - np.maximum(anteMoveFrameCount, spawnerLastClaimedFrames + Spawner.GESTATION_FRAME_LAG)) newSinguityCounts = np.round(matureSpawnerDurations / Spawner.SPAWN_FRAME_LAG) usefulSpawnersMask = newSinguityCounts > 0 if np.count_nonzero(usefulSpawnersMask) <= 0: return self spawnerPositions = spawnerPositions[usefulSpawnersMask] matureSpawnerDurations = matureSpawnerDurations[usefulSpawnersMask] newSinguityCounts = newSinguityCounts[usefulSpawnersMask] distanceFromSpawnersToMeanPosition = PhysicsEstimator.distance( self.singuitiesMeanPosition, spawnerPositions) durationsToTarget = distanceFromSpawnersToMeanPosition / Singuity.MAXIMUM_SPEED_UNITS_PER_FRAME atTargetCounts = np.round( np.maximum((matureSpawnerDurations - durationsToTarget) * PhysicsEstimator.SPAWNER_SPAWN_PER_FRAME, 0)) atTargetCount = np.sum(atTargetCounts) furthestSinguityRatios = np.ones_like( distanceFromSpawnersToMeanPosition) matureSpawnerDurationIsLowerThanTargetDurationMask = matureSpawnerDurations < atTargetCounts furthestSinguityRatios[ matureSpawnerDurationIsLowerThanTargetDurationMask] = matureSpawnerDurations[ matureSpawnerDurationIsLowerThanTargetDurationMask] / atTargetCounts[ matureSpawnerDurationIsLowerThanTargetDurationMask] inLineCounts = newSinguityCounts - atTargetCounts inLineMeanPositions = spawnerPositions + ( spawnerPositions - self.singuitiesMeanPosition ) * furthestSinguityRatios[:, np.newaxis] / 2 inLineStds = distanceFromSpawnersToMeanPosition * furthestSinguityRatios / 4 lineUsageMask = PhysicsEstimator.distance2( spawnerPositions, self.singuitiesMeanPosition) <= (self.singuitiesStd * 2)**2 means = np.concatenate( [[self.singuitiesMeanPosition, self.singuitiesMeanPosition], inLineMeanPositions[lineUsageMask]]) stds = np.concatenate([[ self.singuitiesStd, PhysicsEstimator.getMinimumStd(atTargetCount) ], inLineStds[lineUsageMask]]) counts = np.concatenate([[self.singuityCount, atTargetCount], inLineCounts[lineUsageMask]]) mean, std, count = arrays.combineMeanStdAndCount(means, stds, counts, minStd=np.ones(2)) return DiscretePlayer( self.isCurrentPlayer, self.id, count, mean, np.mean(std), 0 if count == 0 else (self.singuitiesAverageHealth * self.singuityCount + Singuity.MAX_HEALTH_POINT * (count - self.singuityCount)) / count)