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.