Najlepší tím sveta – UA Austin Villa má riešenie svojej pozície a transformácií zverejnené. Kód na menenie pozícií ich vektorov sa nachádza v súboroch utaustinvilla.cc a utaustinvilla.h. Ďalej používajú rôzne geometrické výpočty, ktoré som nahrala na dokumentový server ako súbory: utaustinvillageom.cc, utaustinvillageom.h, utaustinvillamat.cc a utaustinvillamat.h.
Vektory na otáčanie majú riešené nasledovne
VecPosition VecPosition::rotateAboutX(double angle) { double cos = cosDeg(angle); double sin = sinDeg(angle); double newX, newY, newZ; newX = m_x; newY = m_y * cos + m_z * sin; newZ = -m_y * sin + m_z * cos; return VecPosition(newX, newY, newZ); } VecPosition VecPosition::rotateAboutY(double angle) { double cos = cosDeg(angle); double sin = sinDeg(angle); double newX, newY, newZ; newX = m_x * cos - m_z * sin; newY = m_y; newZ = m_x * sin + m_z * cos; return VecPosition(newX, newY, newZ); } VecPosition VecPosition::rotateAboutZ(double angle) { double cos = cosDeg(angle); double sin = sinDeg(angle); double newX, newY, newZ; newX = m_x * cos + m_y * sin; newY = -m_x * sin + m_y * cos; newZ = m_z; return VecPosition(newX, newY, newZ); }
Tím FC Portugal má zverejnené pár publikácií, ako napríklad Situation Based Strategic Positioning for Coordinating a Team of Homogeneous Agents, kde je opísané, ako riešia svoje pozície. Publikáciu som stiahla a pripojila na dokumentový server TFS pod názvom FCPortugal.pdf. Našla som ich jeden zdrojový súbor hráča z roku 2000, kde sa nachádzajú nasledovná implementácia menenia pozície:
ActionQueueRes go_to_point(Vector p, float buffer, float dash_power, DodgeType dodge) {
Mem -> LogAction5(30, "go_to_point %d (%.1f %.1f)", dodge, p.x, p.y); \\ if (!Mem -> MyConf()) my_error("Can't go to a point if not localized"); \\ /* if ( Mem->DistanceTo(p) <buffer && Mem->BallPositionValid() ){ //LPR BallPositionValid! if ( Mem->SP_use_offside && fabs(Mem->MyX() - Mem->my_offside_line) <5 ){ // hack Unum opp = Mem->FurthestForwardOpponent(); if ( opp != Unum_Unknown && Mem->OpponentPositionValid(opp) <.9 ){ // hack Mem->LogAction2(40, "go_to_point: looking for offsides line"); return face_neck_to_opponent(opp); } } Mem->LogAction2(40, "go_to_point: already at the point"); return AQ_ActionNotQueued; }*/ \\ if (Mem -> PlayMode == PM_Their_Goal_Kick && Mem -> MyPos() != p) { \\ /* if ( Mem->TheirPenaltyArea.IsWithin(p) ){ my_error("Can't go into their penalty area on a goal kick!"); */ \\ Line l = LineFromTwoPoints(Mem -> MyPos(), p); \\ Vector intersection = AdjustPtToRectOnLine(Mem -> MyPos(), Mem -> TheirPenaltyArea, l); \\ if (intersection != Mem -> MyPos() && l.InBetween(intersection, Mem -> MyPos(), p)) { /* Need to go around the rectangle */ \\ Mem -> LogAction2(40, "go_to_point: moving around penalty area"); \\ Vector target; \\ if (Mem -> MyX() <Mem -> TheirPenaltyArea.LeftX()) target = Vector(Mem -> TheirPenaltyArea.LeftX() - 3, p.y); \\ else if (Mem -> MyY()> 0) target = Vector(Mem -> TheirPenaltyArea.LeftX() - 3, Mem -> TheirPenaltyArea.BottomY() + 3); \\ else target = Vector(Mem -> TheirPenaltyArea.LeftX() - 3, Mem -> TheirPenaltyArea.TopY() - 3); \\ go_to_point(target, 0, dash_power, dodge); \\ return AQ_ActionQueued; \\ } \\ } \\ if (Mem -> PlayMode != PM_Play_On && Mem -> TeamInPossession() == Mem -> TheirSide && !Mem -> OffsidePosition(p, Mem -> MySide) && //p.dist(Mem->BallAbsolutePosition())> Mem->SP_free_kick_buffer && \\ Mem -> InOffsidePosition() && Mem -> BallDistance() <Mem -> SP_free_kick_buffer + 1) { \\ Mem -> LogAction2(40, "go_to_point: moving around free_kick area"); \\ if (Mem -> BallY()> Mem -> MyY()) go_to_point(Vector(Mem -> MyX(), Mem -> BallY() - (Mem -> SP_free_kick_buffer + 1))); \\ else go_to_point(Vector(Mem -> MyX(), Mem -> BallY() + (Mem -> SP_free_kick_buffer + 1))); \\ return AQ_ActionQueued; \\ } \\ float target_ang = GetNormalizeAngleDeg((p - Mem -> MyPredictedPosition()).dir() - Mem -> MyBodyAng()); \\ float target_dist = Mem -> DistanceTo(p); \\ if (dodge != DT_none) { /* dodge players */ \\ PlayerObject * player; \\ float dodge_dist = Min(Mem -> CP_dodge_distance_buffer, target_dist); \\ AngleDeg dodge_ang = Mem -> CP_dodge_angle_buffer; \\ if ((player = Mem -> GetPlayerWithin(dodge_dist, dodge_ang, 0, target_ang - dodge_ang)) != NULL && (dodge != DT_unless_with_ball || (Mem -> BallPositionValid() && player -> get_abs_pos().dist(Mem -> BallAbsolutePosition())> Mem -> SP_kickable_area)) && (dodge != DT_only_with_ball || (Mem -> BallPositionValid() && player -> get_abs_pos().dist(Mem -> BallAbsolutePosition()) <= Mem -> SP_kickable_area))) { \\ Mem -> LogAction2(40, "go_to_point: dodging right"); /*if ( Mem->NumPlayersWithin( dodge_dist, 2*dodge_ang) ){*/ /* Target at dist player_size, so no players will be within in the next iteration ==> dash */ \\ Vector new_target = Mem -> BodyPolar2Gpos(Mem -> SP_player_size, player -> get_ang_from_body() + Mem -> CP_dodge_angle); \\ if (new_target == p) my_error("Dodging isn't changing the point!"); \\ go_to_point(new_target, 0, Mem -> CP_dodge_power, DT_none); \\ /*} else{ dash(Mem->CorrectDashPowerForStamina(Min(dash_power,Mem->CP_dodge_power))); }*/ \\ return AQ_ActionQueued; \\ } \\ if ((player = Mem -> GetPlayerWithin(dodge_dist, dodge_ang, 0, target_ang + dodge_ang)) != NULL && (dodge != DT_unless_with_ball || (Mem -> BallPositionValid() && player -> get_abs_pos().dist(Mem -> BallAbsolutePosition())> Mem -> SP_kickable_area)) && (dodge != DT_only_with_ball || (Mem -> BallPositionValid() && player -> get_abs_pos().dist(Mem -> BallAbsolutePosition()) <= Mem -> SP_kickable_area))) { \\ Mem -> LogAction2(40, "go_to_point: dodging left"); /*if ( Mem->NumPlayersWithin( dodge_dist, 2*dodge_ang) ){*/ /* Target at dist player_size, so no players will be within in the next iteration ==> dash */ \\ Vector new_target = Mem -> BodyPolar2Gpos(Mem -> SP_player_size, player -> get_ang_from_body() - Mem -> CP_dodge_angle); \\ if (new_target == p) my_error("Dodging isn't changing the point!"); \\ go_to_point(new_target, 0, Mem -> CP_dodge_power, DT_none); \\ /*} else{ dash(Mem->CorrectDashPowerForStamina(Min(dash_power,Mem->CP_dodge_power))); }*/ \\ return AQ_ActionQueued; \\ } \\ } \\ if (fabs(target_ang)> Mem -> CP_max_go_to_point_angle_err || (Mem -> PlayMode == PM_Their_Goal_Kick && Mem -> TheirPenaltyArea.IsWithin(Mem -> MyPredictedPosition(1, dash_power)))) { \\ Mem -> LogAction3(50, "go_to_point: turning %f", target_ang); \\ turn(target_ang); \\ return AQ_ActionQueued; \\ } // LPR - Vou tirar isto // dash_power = Mem->CorrectDashPowerForStamina(dash_power); \\ if (dash_power> 0) { \\ Mem -> LogAction3(50, "go_to_point: dashing %f", dash_power); \\ dash(dash_power); \\ return AQ_ActionQueued; \\ } else { \\ my_stamp; \\ printf("recovering\n"); \\ } \\ /* if ( Mem->DistanceTo(p) <buffer && !Mem->BallPositionValid() ) test_face_ball(); // LPR*/ \\ Mem -> LogAction2(50, "go_to_point: doing nothing?"); \\ return AQ_ActionNotQueued; \\
}
Tím magmaOffenburg taktiež podľa prístupných kódov nepoužíva euklidovské transformácie. V kóde som našla iba výpočty zmien videnia lopty pri behu.
@ Override protected RunInformation createRunInformation(Random rand, int runID) { double radius = (runID + 3); double angle = Math.toRadians(noise(rand, BEAM_ANGLE)); double ballX = -radius * Math.cos(angle); double ballY = radius * Math.sin(angle); double beamX = ballX - DISTANCE_BEHIND_BALL + noise(rand, BEAM_NOISE); double beamY = ballY + noise(rand, BEAM_NOISE); return new RunInformation(runID, beamX, beamY, ballX, ballY); }
Tento dokument obsahuje informácie, ako jednotlivé zahraničné tímy majú riešené pozície a zmeny pozície hráča v kóde. Taktiež obsahuje informácie, kde sa jednotlivé časti zdrojových kódov zahraničných tímov uložili na náš dokumentový server TFS.