def update(self, game): if (self.currentTick == game.current_tick): return self.currentTick = game.current_tick currentPointIx = 0 found = False # в штатной ситуации цикл завершается на второй итерации for tp in self.trajectoryPoints: if (tp.tick == self.currentTick): found = True break currentPointIx += 1 if (found == False): # список пуст или произошла невообразимо кошмарная ошибка, исправление которой # начнется с очистки списка #self.trajectoryPoints.clear() self.recalculateTrajectory(game) else: self.trajectoryPoints = self.trajectoryPoints[currentPointIx:] currentPt = self.trajectoryPoints[0] realPos = Vector3D(game.ball.x, game.ball.y, game.ball.z) predictedPos = Vector3D(currentPt.x, currentPt.y, currentPt.z) delta = (realPos - predictedPos).len() if (delta > ALLOWED_POSITION_DIVERGENCE): # перестраиваем прогноз заново, с текущего состояния #self.trajectoryPoints.clear() self.recalculateTrajectory(game) self.fillTrajectory()
def getStrikePoint(game): # (game: Game) ''' dstDelta = miscInfo.gameRules.ROBOT_MIN_RADIUS + \ miscInfo.gameRules.BALL_RADIUS - \ 0.20 # в лучших традициях подбирается экспертным путем (( ''' dstDelta = miscInfo.touchDst2d - 0.1 if ( game.ball.z < miscInfo.aimPoint.z ): pt2 = Vector3D(game.ball.x, game.ball.y, game.ball.z) pt1 = miscInfo.aimPoint else: pt2 = miscInfo.aimPoint pt1 = Vector3D(game.ball.x, game.ball.y, game.ball.z) kx = pt2.x - pt1.x ky = pt2.y - pt1.y kz = pt2.z - pt1.z ts = ( (dstDelta ** 2) / ( kx**2 + ky**2 + kz**2 ) ) ** 0.5 xs = kx * ts + game.ball.x ys = ky * ts + game.ball.y zs = kz * ts + game.ball.z #print(pt2.z, pt1.z) #print(dstDelta, miscInfo.aimPoint.x, miscInfo.aimPoint.y, miscInfo.aimPoint.z, \ #kx,ky,kz,ts, sep = '\n' ) #if ( game.current_tick == 5 ): #return None return Vector3D(xs, ys, zs)
def predictedBall(self, ball, ticks=1): # предсказывает положение (и скорость мяча на ticks вперед) newBall = copy.copy(ball) # здесь было дробление тика, и я специально его оставляю в виде комментария # чтобы оно напоминало, что эта штука неэффективна ''' tick_split = 10 dt = self.tik / tick_split ''' for i in range(1, ticks + 1): #for i in range(1, (ticks * tick_split + 1)): ballPt = Vector3D(newBall.x, newBall.y, newBall.z) dst, norm = self.distanceToArena(ballPt) penetration = self.rules.BALL_RADIUS - dst #if (ticks == 8): #pdb.set_trace() if (penetration > 0): ballPt += norm * penetration ballVelocity = Vector3D(newBall.velocity_x, newBall.velocity_y, newBall.velocity_z) vlcModule = ballVelocity.scalarMul(norm) if (vlcModule < 0): ballVelocity -= norm * ( 1.0 + self.rules.BALL_ARENA_E) * vlcModule newBall.velocity_x = ballVelocity.x newBall.velocity_y = ballVelocity.y newBall.velocity_z = ballVelocity.z newBall.x = ballPt.x + newBall.velocity_x * self.tik newBall.y = ballPt.y + newBall.velocity_y * self.tik - \ self.rules.GRAVITY * self.tik**2 / 2 newBall.z = ballPt.z + newBall.velocity_z * self.tik else: newBall.x += newBall.velocity_x * self.tik newBall.y += newBall.velocity_y * self.tik - \ self.rules.GRAVITY * self.tik**2 / 2 newBall.z += newBall.velocity_z * self.tik newBall.velocity_y -= self.rules.GRAVITY * self.tik return newBall
def getAimPoint(self, game): # точка в воротах противника, траектория полета мяча к которой # из его текущего положения максимально удалена от роботов противника # TODO пока используется сильно упрощенный вариант enemyBots = [] for bot in game.robots: if (bot.is_teammate == False and bot.z > game.ball.z): enemyBots.append(bot) ballRVec = Vector3D(game.ball.x, game.ball.y, game.ball.z) # базовые значения - работают, если на пути роботов противника нет px = 0 # obviously py = self.rules.arena.goal_height / 2 pz = self.rules.arena.depth / 2 # и не меняется return Vector3D(px, py, pz) topY = self.rules.arena.goal_height - self.rules.BALL_RADIUS bottomY = self.rules.BALL_RADIUS rightX = self.rules.arena.goal_width / 2 - self.rules.BALL_RADIUS leftX = -rightX vects = [[Vector3D(px, py, pz) - ballRVec, 0.0], [Vector3D(rightX, topY, pz) - ballRVec, 0.0], [Vector3D(leftX, topY, pz) - ballRVec, 0.0], [Vector3D(rightX, bottomY, pz) - ballRVec, 0.0], [Vector3D(leftX, bottomY, pz) - ballRVec, 0.0]] def elemVal(elem): return elem[1] for bot in enemyBots: botVec = Vector3D(bot.x, bot.y, bot.z) - ballRVec for v in vects: projection = botVec.projectOn(v[0]) v[1] = (projection - botVec).len() vects.sort(key=elemVal) try: vects.pop() vects.pop() except IndexError: pass return vects[0][0]
def getStrikePoint(self, game): # (game: Game) dstDelta = self.rules.ROBOT_MIN_RADIUS + \ self.rules.BALL_RADIUS - \ 0.15 # в лучших традициях подбирается экспертным путем (( aimPoint = self.getAimPoint(game) if (game.ball.z < aimPoint.z): pt2 = Vector3D(game.ball.x, game.ball.y, game.ball.z) pt1 = aimPoint else: pt2 = aimPoint pt1 = Vector3D(game.ball.x, game.ball.y, game.ball.z) kx = pt2.x - pt1.x ky = pt2.y - pt1.y kz = pt2.z - pt1.z ts = ((dstDelta**2) / (kx**2 + ky**2 + kz**2))**0.5 xs = kx * ts + game.ball.x ys = ky * ts + game.ball.y zs = kz * ts + game.ball.z return Vector3D(xs, ys, zs)
def getDefencePoint(rules): # точка стояния защитника в воротах px = 0 # obviously py = robot.radius pz = 0.0 - rules.arena.depth / 2 return Vector3D(px, py, pz)
def doDefend(me, game, action): prTrajectory = ballPred.getPredictedTrajectory() # если все спокойно, стоять в центре ворот waitPt = Vector2D(0.0, -(miscInfo.gameRules.arena.depth / 2.0) - 1.5 ) defAreaWidth = miscInfo.gameRules.arena.goal_width defAreaDepth = 13.0 # эмпирически, как и всегда (( defAreaZeroZ = - (miscInfo.gameRules.arena.depth / 2.0) defAreaZ = defAreaZeroZ + defAreaDepth interceptionPoint = None goodHeight = miscInfo.gameRules.BALL_RADIUS + \ miscInfo.gameRules.ROBOT_MIN_RADIUS - 0.5 # max BALL CENTER height при которой до мяча еще дотянется робот maxRH = miscInfo.reachableZ + \ miscInfo.gameRules.ROBOT_MIN_RADIUS + \ miscInfo.gameRules.BALL_RADIUS lineCrossX = None # если мяч в ближайшее время попадает на площадку перед воротами for b in prTrajectory: if ( b.z < (- miscInfo.gameRules.arena.depth / 2) - \ miscInfo.gameRules.BALL_RADIUS ): lineCrossX = b.x break if ( abs(b.x) < defAreaWidth / 2 and b.z < defAreaZ ): #ballNearGoal = True #print(game.current_tick, ' detected') ticksLeft = b.tick - game.current_tick bPt = Vector2D(b.x, b.z) ticksNeed = botControl.approxTimeToPoint(bPt, game, me) #if (ticksNeed < 0): #pdb.set_trace() ticksNeedToJump, v0 = \ botControl.calculateJump(b.y - \ miscInfo.gameRules.BALL_RADIUS - \ miscInfo.gameRules.ROBOT_MIN_RADIUS) if (ticksNeedToJump == 0 and interceptionPoint == None): interceptionPoint = b #break ''' if (ticksNeed + ticksNeedToJump < ticksLeft): if (interceptionPoint == None): interceptionPoint = b else: if (b.y < interceptionPoint.y): interceptionPoint = b ''' # TODO REMOVE ''' readyPt = copy.copy(waitPt) if (goalAlert == True): readyPt.x = lineCrossX print('cross', lineCrossX) botControl.botToPointAndStop(readyPt, me, action) return ''' #if (lineCrossX != None and interceptionPoint == None): #print(game.current_tick, ' F**K, GOAL IMMINENT') # прочие случаи if (me.z > game.ball.z or interceptionPoint == None ): botControl.botToPointAndStop(waitPt, me, action) if ( interceptionPoint != None ): tgtPt = Vector2D(interceptionPoint.x, interceptionPoint.z - 1.0) ticksLeft = interceptionPoint.tick - game.current_tick ticksNeedToRoll = botControl.approxTimeToPoint(tgtPt, game, me) h = min(interceptionPoint.y, miscInfo.reachableZ) ticksNeedToJump, v0 = \ botControl.calculateJump(h) #print(game.current_tick, ticksNeedToJump, ticksNeedToRoll, ticksLeft) if ( ticksLeft - ticksNeedToRoll <= 0 ): botControl.botToPoint(tgtPt, me, action) #botControl.botToPointAndStop(tgtPt, me, action) else: readyPt = copy.copy(waitPt) if (lineCrossX != None): readyPt.x = lineCrossX botControl.botToPointAndStop(readyPt, me, action) #botControl.botToPointAndStop(waitPt, me, action) ''' if ( ticksLeft - ticksNeedToJump <= 0 and me.touch == True ): action.jump_speed = v0 ''' botControl.doDecideJump(prTrajectory, game, me, action) kickBall = ( Vector3D(game.ball.x, game.ball.y, game.ball.z) - \ Vector3D(me.x, me.y, me.z) ).len() <= \ ( miscInfo.gameRules.ROBOT_MAX_RADIUS + \ miscInfo.gameRules.BALL_RADIUS ) and \ me.z < game.ball.z if ( kickBall ): action.jump_speed = miscInfo.gameRules.ROBOT_MAX_JUMP_SPEED return
def getAimPoint(rules): # точка в центре ворот противника, куда целится робод px = 0 # obviously py = rules.arena.goal_height / 2 pz = rules.arena.depth / 2 return Vector3D(px, py, pz)
def doAttack(bot, game, action): botVec = Vector2D(bot.x, bot.z) ballVec = Vector2D(game.ball.x, game.ball.z) # если мяч позади нас, отрабатываем возвращение if (bot.z > game.ball.z): botControl.pursueBall(bot, game, action) return prTrajectory = ballPred.getPredictedTrajectory() # da cannon shootz! enemyBotsVecs = [Vector3D(b.x, b.y, b.z) for b in game.robots if b.is_teammate == False] minEnemyDst = min([(Vector3D(game.ball.x, game.ball.y, game.ball.z) - \ v).len() for v in enemyBotsVecs]) kickBall = ( bot.z < game.ball.z and ( Vector3D(game.ball.x, game.ball.y, game.ball.z) - \ Vector3D(bot.x, bot.y, bot.z) ).len() <= \ ( miscInfo.gameRules.ROBOT_MAX_RADIUS + \ miscInfo.gameRules.BALL_RADIUS ) and minEnemyDst < 6.0) ''' kickBall = ( bot.z > miscInfo.gameRules.arena.depth / 2 - \ miscInfo.gameRules.arena.corner_radius and abs(bot.x) < miscInfo.gameRules.arena.goal_width / 2 and ( Vector3D(game.ball.x, game.ball.y, game.ball.z) - \ Vector3D(bot.x, bot.y, bot.z) ).len() <= \ ( miscInfo.gameRules.ROBOT_MAX_RADIUS + \ miscInfo.gameRules.BALL_RADIUS ) and bot.z < game.ball.z and game.ball.z - bot.z > 2.0 and abs(bot.x - game.ball.x) < 1.0 ) ''' if ( kickBall ): #pdb.set_trace() action.jump_speed = miscInfo.gameRules.ROBOT_MAX_JUMP_SPEED # частный случай - робот вблизи мяча, который катится (не прыгает) flatTrajectory = True for b in prTrajectory[:30]: if ( b.y > miscInfo.gameRules.BALL_RADIUS + 1 ): flatTrajectory = False break if ( flatTrajectory == True and (botVec - ballVec).len() < miscInfo.touchDst2d * 2 ): # точка удара по мячу gateToBallVec = ballVec - \ Vector2D(0.0, miscInfo.gameRules.arena.depth / 2 - \ miscInfo.gameRules.BALL_RADIUS) ballVelocVec = Vector2D(game.ball.velocity_x, game.ball.velocity_z) ''' correctionVec = ( gateToBallVec.normalize() + \ ballVelocVec.normalize() * 0.3 ).normalize() * \ ( miscInfo.touchDst2d * 0.9 ) tgtPt = ballVec + correctionVec ''' tgtPt = ballVec + gateToBallVec.normalize() * miscInfo.touchDst2d * 0.5 botControl.botToPoint(tgtPt, bot, action) return # общий случай - мяч где-то летает ballInterceptionPos = None ptsCount = len(prTrajectory) for i in range(1, ptsCount - 1): if (prTrajectory[i].y < prTrajectory[i-1].y and prTrajectory[i].y < prTrajectory[i+1].y): ballInterceptionPos = prTrajectory[i] break if (ballInterceptionPos == None): return # точка удара по мячу ballVelocVec = Vector2D(game.ball.velocity_x, game.ball.velocity_z) ballToGateVec = Vector2D(0.0, miscInfo.gameRules.arena.depth / 2 - \ miscInfo.gameRules.BALL_RADIUS) - \ ballVec if ( ballVelocVec.scalarProjectOn(ballToGateVec) <= 0 ): correctionVec = ( (Vector2D(0,0) - ballToGateVec).normalize() + \ ballVelocVec.normalize() ).normalize() * \ ( miscInfo.touchDst2d / 2 ) else: # чет я не уверен correctionVec = ( (Vector2D(0,0) - ballToGateVec).normalize() * 2.0 + \ ballVelocVec.normalize() ).normalize() * \ ( miscInfo.touchDst2d / 2) intcptPt = Vector2D(ballInterceptionPos.x + correctionVec.x, ballInterceptionPos.z + correctionVec.z) # # t = 5 ticks, s = 0.35, v = 8.3 # t = 10 ticks, s = 1.4, v = 16.6 readyPt = Vector2D(ballInterceptionPos.x, ballInterceptionPos.z) + \ (Vector2D(0,0) - ballToGateVec).normalize() * \ (1.0 + miscInfo.touchDst2d) if (ballInterceptionPos.tick - game.current_tick > 10): botControl.botToPointAndStop(readyPt, bot, action) else: botControl.botToPoint(intcptPt, bot, action)
def nextCollision(self, ball): # роботов не учитываем, только стены # TODO пока не учитываются ворота и все изгибы rules = self.rules #print('ball.y', ball.y) # пользуясь симметрией арены по X и Z, будем считать в рамках одной # четверти арены, для чего приведем координаты и скорости # TODO не требует ли это вдумчивого рефакторинга? #ball = copy.copy(inBall) # TODO REMOVE? #print('befor', ball.x,ball.velocity_x) signX = 1.0 if (ball.x < 0): signX = -1.0 signZ = 1.0 if (ball.z < 0): signZ = -1.0 ball.x = abs(ball.x) ball.z = abs(ball.z) ball.velocity_x = ball.velocity_x * signX ball.velocity_z = ball.velocity_z * signZ #print('aftar',ball.x,ball.velocity_x, signX) ''' итого имеем возможные времена пересечения интересующих нас линий: txWall ty (обрабатывает и пол, и потолок в плоской их части) по осям - отражения НЕ происходит!!! txAxis tzAxis ''' # по X xMax = rules.arena.width - rules.BALL_RADIUS try: txWall = xMax / ball.velocity_x #if (tx < 0): #print('nextCollision() tx calculation error') except ZeroDivisionError: txWall = -1 xMin = 0.0 try: txAxis = xMin / ball.velocity_x except ZeroDivisionError: txAxis = -1 # по Z zMax = rules.arena.depth - rules.BALL_RADIUS zMin = -rules.arena.depth + rules.BALL_RADIUS try: tz1 = zMin / ball.velocity_z tz2 = zMax / ball.velocity_z tz = max([tz1, tz2]) if (tz < 0): print('nextCollision() tz calculation error') except ZeroDivisionError: tz = -1 # по Y if (ball.y - self.rules.BALL_RADIUS <= AXIS_VELOCITY_THRESHOLD and abs(ball.velocity_y) <= AXIS_VELOCITY_THRESHOLD): # мяч лежит на полу (или катится по полу) ty = -1 #print('vel_y',ball.velocity_y) else: # есть смысл что-то считать yMax = rules.arena.height - rules.BALL_RADIUS yMin = rules.BALL_RADIUS tys1 = solveSquareEquation(rules.GRAVITY / 2, -ball.velocity_y, yMin - ball.y) tys2 = solveSquareEquation(rules.GRAVITY / 2, -ball.velocity_y, yMax - ball.y) tys1.extend(tys2) try: ty = min([e for e in tys1 if e > ALLOWED_CALCULATIONS_ERROR]) except ValueError: print('nextCollision() ty calculation error') ty = -1 # в плоскости XY при столкновении с нижним радиусом brcX = (rules.arena.width / 2 - rules.arena.bottom_radius) # bottom radius center x brcY = rules.arena.bottom_radius radius = rules.arena.bottom_radius - rules.BALL_RADIUS ct4 = rules.GRAVITY**2 / 4 ct3 = -rules.GRAVITY * ball.velocity_y ct2 = rules.GRAVITY * brcY - \ rules.GRAVITY * ball.y + \ ball.velocity_x ** 2 + \ ball.velocity_y ** 2 ct = - 2 * ball.velocity_x * brcX + \ 2 * ball.velocity_x * ball.x - \ 2 * ball.velocity_y * brcY + \ 2 * ball.velocity_y * ball.y c = - radius ** 2 + \ brcX ** 2 - \ 2 * brcX * ball.x + \ ball.x ** 2 + \ brcY ** 2 - \ 2 * brcY * ball.y + \ ball.y ** 2 txys = solvePower4Equation(ct4, ct3, ct2, ct, c) txys = [ttc for ttc in txys if ttc > ALLOWED_CALCULATIONS_ERROR] xyBallStates = [self.predictedBallWoColls(ball, ttc) for ttc in txys] print(txys) filteredTxys = [] for i in range(len(txys)): if (xyBallStates[i].x > brcX and xyBallStates[i].y < brcY): filteredTxys.append(txys[i]) b = xyBallStates[i] print('state', b.x, b.y, b.z) #txys = filteredTxys try: txy = min(filteredTxys) except ValueError: txy = -1 try: timeToColl = min([e for e in [txWall, ty, tz, txy] if e > 0]) except ValueError: # не можем посчитать ни одну коллизию - сильно похоже на то, что мяч # просто лежит на полу #print('nextCollision() collision time calculation error: assuming ball is not moving') #print([tx, ty, tz]) #print(ball.x, ball.y, ball.z) #print(ball.velocity_x, ball.velocity_y, ball.velocity_z) newBall = copy.copy(ball) #print(newBall.y) #newBall.velocity_y = 0.0 return (1.0, newBall) #print('t', timeToColl) #b = ball #print('b', b.x, b.velocity_x) newBall = self.predictedBallWoColls(ball, timeToColl) #b = newBall #print('nb', b.x, b.velocity_x) # пересчитать скорости в newBall # для чего сначала получить нормаль к поверхности if (timeToColl == txWall): print('onxW') newBall.velocity_x = -0.7 * newBall.velocity_x # по Z и Y - без изменений elif (timeToColl == tz): print('onz') newBall.velocity_z = -0.7 * newBall.velocity_z # по Y и X - без изменений elif (timeToColl == txy): print('onxy') bVel = Vector3D(newBall.velocity_x, newBall.velocity_y, newBall.velocity_z) normal = Vector3D(ball.x - brcX, ball.y - brcY, 0) bVelNorm = bVel.projectOn(normal) bVelOrto = bVel - bVelNorm bVelNorm = Vector3D(0.0, 0.0, 0.0) - bVelNorm * rules.BALL_ARENA_E bVel = bVelNorm + bVelOrto newBall.velocity_x = bVel.x newBall.velocity_y = bVel.y newBall.velocity_z = bVel.z else: #( timeToColl == ty): print('ony') newBall.velocity_y = -0.7 * newBall.velocity_y # по Z и X - без изменений # не забываем обратно поменять знак newBall.x = newBall.x * signX newBall.z = newBall.z * signZ newBall.velocity_x = newBall.velocity_x * signX newBall.velocity_z = newBall.velocity_z * signZ #print('new vel_y',newBall.velocity_y) return (timeToColl, newBall)
def distanceBetweenCenters(entity1, entity2): # расстояние между роботом и мячом (или двумя роботами) rVec1 = Vector3D(entity1.x, entity1.y, entity1.z) rVec2 = Vector3D(entity2.x, entity2.y, entity2.z) return (rVec2 - rVec1).len()
def distanceToArenaQuarter(self, point): arena = self.rules.arena # element for comparison def dstCompEl(e): return e[0] # Ground dst = distanceToPlane(point, Vector3D(0, 0, 0), Vector3D(0, 1, 0)) # Ceiling dst = min(dst, distanceToPlane(point, Vector3D(0, arena.height, 0), Vector3D(0, -1, 0)), key=dstCompEl) # X side dst = min(dst, distanceToPlane(point, Vector3D(self.halfWidth, 0, 0), Vector3D(-1, 0, 0)), key=dstCompEl) # Z side, goal area dst = min(dst, distanceToPlane( point, Vector3D(0, 0, self.halfDepth + arena.goal_depth), Vector3D(0, 0, -1)), key=dstCompEl) # Z side v = Vector2D(point.x, point.y) - \ Vector2D(arena.goal_width / 2 - arena.goal_top_radius, arena.goal_height - arena.goal_top_radius) if (point.x >= arena.goal_width / 2 + arena.goal_side_radius or point.y >= arena.goal_height + arena.goal_side_radius or (v.x > 0 and v.z > 0 and v.len() >= arena.goal_top_radius + arena.goal_side_radius)): dst = min(dst, distanceToPlane(point, Vector3D(0, 0, self.halfDepth), Vector3D(0, 0, -1)), key=dstCompEl) # Goal X side and Ceiling if (point.z >= self.halfDepth + arena.goal_side_radius): # X side dst = min(dst, distanceToPlane(point, Vector3D(self.halfWidth, 0, 0), Vector3D(-1, 0, 0)), key=dstCompEl) # Y side dst = min(dst, distanceToPlane(point, Vector3D(0, arena.goal_height, 0), Vector3D(0, -1, 0)), key=dstCompEl) # Goal back corners if (point.z > self.halfDepth + arena.goal_depth - arena.bottom_radius): dst = min(dst, distanceToSphereInner( point, Vector3D( clamp(point.x, arena.bottom_radius - self.halfWidth, self.halfWidth - arena.bottom_radius), clamp(point.y, arena.bottom_radius, arena.goal_height - arena.goal_top_radius), self.halfDepth + arena.goal_depth - arena.bottom_radius), arena.bottom_radius), key=dstCompEl) # Corner if (point.x > self.halfWidth - arena.corner_radius and point.z > self.halfDepth - arena.corner_radius): dst = min(dst, distanceToSphereInner( point, Vector3D(self.halfWidth - arena.corner_radius, point.y, self.halfDepth - arena.corner_radius), arena.corner_radius), key=dstCompEl) # Goal outer corner if (point.z < self.halfDepth + arena.goal_side_radius): # X side if (point.x < self.halfWidth + arena.goal_side_radius): dst = min(dst, distanceToSphereOuter( point, Vector3D(self.halfWidth + arena.goal_side_radius, point.y, self.halfDepth + arena.goal_side_radius), arena.goal_side_radius), key=dstCompEl) # Ceiling if (point.y < arena.goal_height + arena.goal_side_radius): dst = min(dst, distanceToSphereOuter( point, Vector3D( point.x, arena.goal_height + arena.goal_side_radius, self.halfDepth + arena.goal_side_radius), arena.goal_side_radius), key=dstCompEl) # Top corner o = Vector2D(self.halfWidth - arena.goal_top_radius, arena.goal_height - arena.goal_top_radius) v = Vector2D(point.x, point.y) - o if (v.x > 0 and v.z > 0): o = o + v.normalize() * (arena.goal_top_radius + arena.goal_side_radius) dst = min(dst, distanceToSphereOuter( point, Vector3D(o.x, o.z, self.halfDepth + arena.goal_side_radius), arena.goal_side_radius), key=dstCompEl) # Goal inside top corners if (point.z > self.halfDepth + arena.goal_side_radius and point.y > arena.goal_height - arena.goal_top_radius): # X side if (point.x > self.halfWidth - arena.goal_top_radius): dst = min(dst, distanceToSphereInner( point, Vector3D( self.halfWidth - arena.goal_top_radius, arena.goal_height - arena.goal_top_radius, point.z), arena.goal_top_radius), key=dstCompEl) # Z side if (point.z > self.halfDepth + arena.goal_depth - arena.goal_top_radius): dst = min(dst, distanceToSphereInner( point, Vector3D( point.x, arena.goal_height - arena.goal_top_radius, self.halfDepth + arena.goal_depth - arena.goal_top_radius), arena.goal_top_radius), key=dstCompEl) # Bottom corners if (point.y < arena.bottom_radius): # X side if (point.x > self.halfWidth - arena.bottom_radius): dst = min(dst, distanceToSphereInner( point, Vector3D(self.halfWidth - arena.bottom_radius, arena.bottom_radius, point.z), arena.bottom_radius), key=dstCompEl) # Z side if (point.z > self.halfDepth - arena.bottom_radius and point.x >= self.halfWidth + arena.goal_side_radius): dst = min(dst, distanceToSphereInner( point, Vector3D(point.x, arena.bottom_radius, self.halfDepth - arena.bottom_radius), arena.bottom_radius), key=dstCompEl) # Z side (goal) if (point.z > self.halfDepth + arena.goal_depth - arena.bottom_radius): dst = min(dst, distanceToSphereInner( point, Vector3D( point.x, arena.bottom_radius, self.halfDepth + arena.goal_depth - arena.bottom_radius), arena.bottom_radius), key=dstCompEl) # Goal outer corner o = Vector2D(self.halfWidth + arena.goal_side_radius, self.halfDepth + arena.goal_side_radius) v = Vector2D(point.x, point.z) - o if (v.x < 0 and v.z < 0 and v.len() < arena.goal_side_radius + arena.bottom_radius): o = o + v.normalize() * (arena.goal_side_radius + arena.bottom_radius) dst = min(dst, distanceToSphereInner( point, Vector3D(o.x, arena.bottom_radius, o.z), arena.bottom_radius), key=dstCompEl) # X side (goal) if (point.z >= self.halfDepth + arena.goal_side_radius and point.x > self.halfWidth - arena.bottom_radius): dst = min(dst, distanceToSphereInner( point, Vector3D(self.halfWidth - arena.bottom_radius, arena.bottom_radius, point.z), arena.bottom_radius), key=dstCompEl) # Corner if (point.x > self.halfWidth - arena.corner_radius and point.z > self.halfDepth - arena.corner_radius): corner_o = Vector2D(self.halfWidth - arena.corner_radius, self.halfDepth - arena.corner_radius) n = Vector2D(point.x, point.z) - corner_o dist = n.len() if (dist > arena.corner_radius - arena.bottom_radius): n = n / dist o2 = corner_o + n * (arena.corner_radius - arena.bottom_radius) dst = min(dst, distanceToSphereInner( point, Vector3D(o2.x, arena.bottom_radius, o2.z), arena.bottom_radius), key=dstCompEl) # Ceiling corners if (point.y > arena.height - arena.top_radius): # X side if (point.x > self.halfWidth - arena.top_radius): dst = min(dst, distanceToSphereInner( point, Vector3D(self.halfWidth - arena.top_radius, arena.height - arena.top_radius, point.z), arena.top_radius), key=dstCompEl) # Z side if (point.z > self.halfDepth - arena.top_radius): dst = min(dst, distanceToSphereInner( point, Vector3D(point.x, arena.height - arena.top_radius, self.halfDepth - arena.top_radius), arena.top_radius), key=dstCompEl) # Corner if (point.x > self.halfWidth - arena.corner_radius and point.z > self.halfDepth - arena.corner_radius): corner_o = Vector2D(self.halfWidth - arena.corner_radius, self.halfDepth - arena.corner_radius) dv = Vector2D(point.x, point.z) - corner_o if (dv.len() > arena.corner_radius - arena.top_radius): n = dv.normalize() o2 = corner_o + n * (arena.corner_radius - arena.top_radius) dst = min(dst, distanceToSphereInner( point, Vector3D(o2.x, arena.height - arena.top_radius, o2.z), arena.top_radius), key=dstCompEl) return dst
#traced = list(range(45, 196)) #traced.extend(list(range(370, 469))) for e in gameLog[1:]: ball = ballFromLog(e['ball']) gameStub = GameStub() gameStub.ball = ball gameStub.current_tick = e['current_tick'] trajectory = ballPred.getPredictedTrajectory() found = False for b in trajectory: if (b.tick == e['current_tick']): found = True delta = (Vector3D(b.x, b.y, b.z) - Vector3D(ball.x, ball.y, ball.z)).len() break if (found == False): print('tick', e['current_tick'], 'NOT FOUND') if (delta > ALLOWED_POSITION_DIVERGENCE): print(e['current_tick'], 'LARGE DIVERGENCE') if (e['current_tick'] in traced): print(e['current_tick'], 'DELTA', delta) ballPred.update(gameStub) # total calculs! ''' ballPred.update(gameStub) ticks = e['current_tick'] - basicMoment['current_tick']