00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "soccerruleaspect.h"
00023 #include <salt/random.h>
00024 #include <zeitgeist/logserver/logserver.h>
00025 #include <oxygen/agentaspect/agentaspect.h>
00026 #include <oxygen/physicsserver/body.h>
00027 #include <oxygen/sceneserver/scene.h>
00028 #include <oxygen/gamecontrolserver/gamecontrolserver.h>
00029 #include <soccer/soccerbase/soccerbase.h>
00030 #include <soccer/gamestateaspect/gamestateaspect.h>
00031 #include <soccer/ballstateaspect/ballstateaspect.h>
00032 #include <soccer/agentstate/agentstate.h>
00033
00034 using namespace oxygen;
00035 using namespace boost;
00036 using namespace std;
00037 using salt::Vector2f;
00038 using salt::Vector3f;
00039
00040 SoccerRuleAspect::SoccerRuleAspect() :
00041 mBallRadius(0.111),
00042 mGoalPauseTime(3),
00043 mKickInPauseTime(1),
00044 mHalfTime(2.25 * 60),
00045 mFreeKickDist(9.15),
00046 mFreeKickMoveDist(15.15),
00047 mAutomaticKickOff(false),
00048 mWaitBeforeKickOff(1.0),
00049 mSingleHalfTime(false),
00050 mSayMsgSize(512),
00051 mAudioCutDist(50.0),
00052 mUseOffside(true),
00053 mFirstCollidingAgent(true),
00054 mNotOffside(false)
00055 {
00056 }
00057
00058 SoccerRuleAspect::~SoccerRuleAspect()
00059 {
00060 }
00061
00062 void
00063 SoccerRuleAspect::MoveBall(const Vector3f& pos)
00064 {
00065 mBallBody->SetPosition(pos);
00066 mBallBody->SetVelocity(Vector3f(0,0,0));
00067 mBallBody->SetAngularVelocity(Vector3f(0,0,0));
00068 }
00069
00070 void
00071 SoccerRuleAspect::MoveAgent(shared_ptr<Body> agent_body, const Vector3f& pos)
00072 {
00073 agent_body->SetPosition(pos);
00074 agent_body->SetVelocity(Vector3f(0,0,0));
00075 agent_body->SetAngularVelocity(Vector3f(0,0,0));
00076 }
00077
00078 void
00079 SoccerRuleAspect::ClearPlayers(const salt::Vector3f& pos, float radius,
00080 float min_dist, TTeamIndex idx)
00081 {
00082 if (idx == TI_NONE || mBallState.get() == 0) return;
00083 std::list<boost::shared_ptr<AgentState> > agent_states;
00084 if (! SoccerBase::GetAgentStates(*mBallState, agent_states, idx))
00085 return;
00086
00087 salt::BoundingSphere sphere(pos, radius);
00088 boost::shared_ptr<oxygen::Transform> transform_parent;
00089 boost::shared_ptr<oxygen::Body> agent_body;
00090 std::list<boost::shared_ptr<AgentState> >::const_iterator i;
00091 for (i = agent_states.begin(); i != agent_states.end(); ++i)
00092 {
00093 SoccerBase::GetTransformParent(*(*i), transform_parent);
00094
00095 SoccerBase::GetAgentBody(transform_parent, agent_body);
00096
00097 Vector3f new_pos = agent_body->GetPosition();
00098 if (sphere.Contains(new_pos))
00099 {
00100 float dist = salt::UniformRNG<>(min_dist, min_dist + 2.0)();
00101
00102 if (idx == TI_LEFT)
00103 {
00104 if (pos[0] - dist < -mFieldLength/2.0)
00105 {
00106 new_pos[1] = pos[1] < 0 ? pos[1] + dist : pos[1] - dist;
00107 } else {
00108 new_pos[0] = pos[0] - dist;
00109 }
00110 } else {
00111 if (pos[0] + dist > mFieldLength/2.0)
00112 {
00113 new_pos[1] = pos[1] < 0 ? pos[1] + dist : pos[1] - dist;
00114 } else {
00115 new_pos[0] = pos[0] + dist;
00116 }
00117 }
00118 new_pos[2] = 1.0;
00119 MoveAgent(agent_body, new_pos);
00120 }
00121 }
00122 }
00123
00124 void
00125 SoccerRuleAspect::ClearPlayers(const salt::AABB2& box,
00126 float min_dist, TTeamIndex idx)
00127 {
00128 if (idx == TI_NONE || mBallState.get() == 0) return;
00129 std::list<boost::shared_ptr<AgentState> > agent_states;
00130 if (! SoccerBase::GetAgentStates(*mBallState, agent_states, idx))
00131 return;
00132
00133 boost::shared_ptr<oxygen::Transform> transform_parent;
00134 boost::shared_ptr<oxygen::Body> agent_body;
00135
00136 std::list<boost::shared_ptr<AgentState> >::const_iterator i;
00137 for (i = agent_states.begin(); i != agent_states.end(); ++i)
00138 {
00139 SoccerBase::GetTransformParent(*(*i), transform_parent);
00140
00141 SoccerBase::GetAgentBody(transform_parent, agent_body);
00142
00143 Vector3f new_pos = agent_body->GetPosition();
00144 if (box.Contains(Vector2f(new_pos[0], new_pos[1])))
00145 {
00146 if (idx == TI_LEFT)
00147 {
00148 new_pos[0] = box.minVec[0] -
00149 salt::UniformRNG<>(min_dist, min_dist + 2.0)();
00150 } else {
00151 new_pos[0] = box.maxVec[0] +
00152 salt::UniformRNG<>(min_dist, min_dist + 2.0)();
00153 }
00154 new_pos[2] = 1.0;
00155 MoveAgent(agent_body, new_pos);
00156 }
00157 }
00158 }
00159
00160 void
00161 SoccerRuleAspect::DropBall()
00162 {
00163 DropBall(mBallBody->GetPosition());
00164 }
00165
00166 void
00167 SoccerRuleAspect::DropBall(Vector3f pos)
00168 {
00169 salt::Vector2f ball_pos(pos.x(), pos.y());
00170
00171
00172 if (mLeftPenaltyArea.Contains(ball_pos))
00173 {
00174 pos[0] = mLeftPenaltyArea.maxVec[0];
00175 pos[1] = pos.y() < 0 ?
00176 mLeftPenaltyArea.minVec[1] : mLeftPenaltyArea.maxVec[1];
00177 }
00178 else if (mRightPenaltyArea.Contains(ball_pos))
00179 {
00180 pos[0] = mRightPenaltyArea.minVec[0];
00181 pos[1] = pos.y() < 0 ?
00182 mRightPenaltyArea.minVec[1] : mRightPenaltyArea.maxVec[1];
00183 }
00184
00185 MoveBall(pos);
00186 ClearPlayers(pos, mFreeKickDist, mFreeKickMoveDist, TI_LEFT);
00187 ClearPlayers(pos, mFreeKickDist, mFreeKickMoveDist, TI_RIGHT);
00188 mGameState->SetPlayMode(PM_PlayOn);
00189 }
00190
00191 void
00192 SoccerRuleAspect::UpdateBeforeKickOff()
00193 {
00194
00195
00196 Vector3f pos(0,0,mBallRadius);
00197 MoveBall(pos);
00198 ClearPlayers(mRightHalf, 1.0, TI_LEFT);
00199 ClearPlayers(mLeftHalf, 1.0, TI_RIGHT);
00200
00201 if (mAutomaticKickOff && mGameState->GetModeTime() > mWaitBeforeKickOff)
00202 {
00203 mGameState->KickOff();
00204 }
00205 }
00206
00207 void
00208 SoccerRuleAspect::UpdateKickOff(TTeamIndex idx)
00209 {
00210 ClearPlayers(mRightHalf, 1.0, TI_LEFT);
00211 ClearPlayers(mLeftHalf, 1.0, TI_RIGHT);
00212 ClearPlayers(Vector3f(0,0,0), mFreeKickDist, mFreeKickMoveDist,
00213 SoccerBase::OpponentTeam(idx));
00214
00215
00216
00217 if (mDropBallTime > 0 &&
00218 mGameState->GetModeTime() > mDropBallTime)
00219 {
00220 DropBall(mFreeKickPos);
00221 return;
00222 }
00223
00224
00225 shared_ptr<AgentAspect> agent;
00226 TTime time;
00227 if (! mBallState->GetLastCollidingAgent(agent,time))
00228 {
00229 return;
00230 }
00231 if (time > mGameState->GetLastModeChange())
00232 {
00233 mGameState->SetPlayMode(PM_PlayOn);
00234 }
00235 }
00236
00237 void
00238 SoccerRuleAspect::UpdateKickIn(TTeamIndex idx)
00239 {
00240
00241 if (mGameState->GetModeTime() < mKickInPauseTime)
00242 {
00243 return;
00244 }
00245
00246 ClearPlayers(mFreeKickPos, mFreeKickDist, mFreeKickMoveDist,
00247 SoccerBase::OpponentTeam(idx));
00248
00249
00250
00251 if (mDropBallTime > 0 &&
00252 mGameState->GetModeTime() > mDropBallTime)
00253 {
00254 DropBall(mFreeKickPos);
00255 return;
00256 }
00257
00258
00259
00260
00261 shared_ptr<AgentAspect> agent;
00262 TTime time;
00263 if (! mBallState->GetLastCollidingAgent(agent,time))
00264 {
00265 GetLog()->Error() << "ERROR: (SoccerRuleAspect) " << "no agent collided yet\n";
00266 return;
00267 }
00268
00269 TTime lastChange = mGameState->GetLastModeChange();
00270 if (time > lastChange)
00271 {
00272 mGameState->SetPlayMode(PM_PlayOn);
00273 GetLog()->Error() << "ERROR: (SoccerRuleAspect) " << "Set Playmode to playon\n";
00274 } else
00275 {
00276
00277
00278 MoveBall(mFreeKickPos);
00279 }
00280 }
00281
00282 void
00283 SoccerRuleAspect::UpdateGoalKick(TTeamIndex idx)
00284 {
00285
00286 if (mGameState->GetModeTime() < mKickInPauseTime)
00287 {
00288 return;
00289 }
00290
00291 ClearPlayers(idx == TI_LEFT ? mLeftPenaltyArea : mRightPenaltyArea,
00292 1.0, SoccerBase::OpponentTeam(idx));
00293
00294
00295
00296 if (mDropBallTime > 0 &&
00297 mGameState->GetModeTime() > mDropBallTime)
00298 {
00299 DropBall(mFreeKickPos);
00300 return;
00301 }
00302
00303
00304
00305 shared_ptr<AgentAspect> agent;
00306 TTime time;
00307 if (! mBallState->GetLastCollidingAgent(agent,time))
00308 {
00309 return;
00310 }
00311
00312 TTime lastChange = mGameState->GetLastModeChange();
00313
00314
00315 if (time > lastChange)
00316 {
00317 Vector2f pos(mBallBody->GetPosition().x(),
00318 mBallBody->GetPosition().y());
00319 if ((idx == TI_RIGHT && !mRightPenaltyArea.Contains(pos)) ||
00320 (idx == TI_LEFT && !mLeftPenaltyArea.Contains(pos)) ||
00321 (idx == TI_NONE))
00322 {
00323
00324
00325
00326 mGameState->SetPlayMode(PM_PlayOn);
00327 }
00328 return;
00329 }
00330
00331 else
00332 {
00333
00334 MoveBall(mFreeKickPos);
00335 }
00336 }
00337
00338 void
00339 SoccerRuleAspect::UpdateCornerKick(TTeamIndex idx)
00340 {
00341
00342 if (mGameState->GetModeTime() < mKickInPauseTime)
00343 {
00344 return;
00345 }
00346
00347 ClearPlayers(mFreeKickPos, mFreeKickDist, mFreeKickMoveDist,
00348 SoccerBase::OpponentTeam(idx));
00349
00350
00351
00352 if (mDropBallTime > 0 &&
00353 mGameState->GetModeTime() > mDropBallTime)
00354 {
00355 DropBall(mFreeKickPos);
00356 return;
00357 }
00358
00359
00360
00361
00362 shared_ptr<AgentAspect> agent;
00363 TTime time;
00364 if (! mBallState->GetLastCollidingAgent(agent,time))
00365 {
00366 return;
00367 }
00368
00369 TTime lastChange = mGameState->GetLastModeChange();
00370 if (time > lastChange)
00371 {
00372 mGameState->SetPlayMode(PM_PlayOn);
00373 } else
00374 {
00375
00376
00377 MoveBall(mFreeKickPos);
00378 }
00379 }
00380
00381 bool
00382 SoccerRuleAspect::CheckBallLeftField()
00383 {
00384 if (mBallState->GetBallOnField())
00385 {
00386 return false;
00387 }
00388
00389
00390
00391 shared_ptr<AgentAspect> agent;
00392 shared_ptr<AgentState> agentState;
00393 TTime time;
00394
00395 if (mBallState->GetLastCollidingAgent(agent,time) &&
00396 SoccerBase::GetAgentState(agent,agentState))
00397 {
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 Vector3f ball_pos = mBallBody->GetPosition();
00412 bool last_touch_left = (agentState->GetTeamIndex() == TI_LEFT);
00413 bool ball_left = (ball_pos[0] < 0);
00414 bool ball_up = (ball_pos[1] < 0);
00415
00416
00417 if (salt::gAbs(ball_pos.x()) >= mFieldLength / 2)
00418 {
00419
00420 if (last_touch_left && !ball_left)
00421 {
00422 mFreeKickPos[0] = mFieldLength / 2 - 5.0;
00423 mFreeKickPos[1] = 0.0;
00424 mFreeKickPos[2] = mBallRadius;
00425 mGameState->SetPlayMode(PM_GOAL_KICK_RIGHT);
00426 }
00427
00428 else if (!last_touch_left && ball_left)
00429 {
00430 mFreeKickPos[0] = -mFieldLength / 2 + 5.0;
00431 mFreeKickPos[1] = 0.0;
00432 mFreeKickPos[2] = mBallRadius;
00433 mGameState->SetPlayMode(PM_GOAL_KICK_LEFT);
00434 }
00435
00436 else if (last_touch_left && ball_left)
00437 {
00438 mFreeKickPos[0] = -mFieldLength / 2 + 0.05;
00439 mFreeKickPos[1] = ball_pos[1] > 0 ?
00440 mFieldWidth / 2 - 0.05 : -mFieldWidth / 2 + 0.05;
00441 mFreeKickPos[2] = mBallRadius;
00442 mGameState->SetPlayMode(PM_CORNER_KICK_RIGHT);
00443 }
00444
00445 else
00446 {
00447 mFreeKickPos[0] = mFieldLength / 2 - 0.05;
00448 mFreeKickPos[1] = ball_pos[1] > 0 ?
00449 mFieldWidth / 2 - 0.05 : -mFieldWidth / 2 + 0.05;
00450 mFreeKickPos[2] = mBallRadius;
00451 mGameState->SetPlayMode(PM_CORNER_KICK_LEFT);
00452 }
00453 }
00454
00455 else if (salt::gAbs(ball_pos.y()) >= mFieldWidth / 2)
00456 {
00457 mFreeKickPos = mBallState->GetLastValidBallPosition();
00458 mFreeKickPos[1] = mFreeKickPos[1] > 0 ?
00459 mFieldWidth / 2 : -mFieldWidth / 2;
00460 mFreeKickPos[2] = mBallRadius;
00461 mGameState->SetPlayMode((agentState->GetTeamIndex() == TI_LEFT) ?
00462 PM_KickIn_Right : PM_KickIn_Left);
00463 }
00464
00465 else {
00466
00467 MoveBall(mBallState->GetLastValidBallPosition());
00468
00469
00470 return false;
00471 }
00472 }
00473
00474 return true;
00475 }
00476
00477 bool
00478 SoccerRuleAspect::CheckGoal()
00479 {
00480
00481 TTeamIndex idx = mBallState->GetGoalState();
00482 if (idx == TI_NONE)
00483 {
00484 return false;
00485 }
00486
00487
00488 mGameState->ScoreTeam((idx == TI_LEFT) ? TI_RIGHT : TI_LEFT);
00489 mGameState->SetPlayMode((idx == TI_LEFT) ? PM_Goal_Right : PM_Goal_Left);
00490
00491 return true;
00492 }
00493
00494 void
00495 SoccerRuleAspect::UpdatePlayOn()
00496 {
00497
00498 if (CheckGoal())
00499 {
00500 return;
00501 }
00502
00503
00504 if (CheckBallLeftField())
00505 {
00506 return;
00507 }
00508
00509
00510 if (mUseOffside && CheckOffside())
00511 {
00512 return;
00513 }
00514
00515
00516 }
00517
00518 void
00519 SoccerRuleAspect::UpdateGoal()
00520 {
00521
00522 if (mGameState->GetModeTime() < mGoalPauseTime)
00523 {
00524 return;
00525 }
00526
00527
00528 Vector3f pos(0,0,mBallRadius);
00529 MoveBall(pos);
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539 mGameState->KickOff(
00540 mGameState->GetPlayMode() == PM_Goal_Left ?
00541 TI_RIGHT : TI_LEFT
00542 );
00543 }
00544
00545 void
00546 SoccerRuleAspect::UpdateGameOver()
00547 {
00548
00549 if (mGameState->GetModeTime() < 9)
00550 {
00551 return;
00552 }
00553 mGameState->Finish();
00554
00555 if (mGameState->GetModeTime() >= 10)
00556 {
00557 boost::shared_ptr<GameControlServer> gameControlServer =
00558 shared_dynamic_cast<GameControlServer>(GetCore()->Get("/sys/server/gamecontrol"));
00559 gameControlServer->Quit();
00560 }
00561 }
00562
00563 void
00564 SoccerRuleAspect::CheckTime()
00565 {
00566 TTime now = mGameState->GetTime();
00567 TGameHalf half = mGameState->GetGameHalf();
00568
00569 if ((half == GH_FIRST) && (now >= mHalfTime))
00570 {
00571 if (mSingleHalfTime)
00572 {
00573
00574 mGameState->SetPlayMode(PM_GameOver);
00575 } else {
00576
00577 mGameState->SetPlayMode(PM_BeforeKickOff);
00578 mGameState->SetGameHalf(GH_SECOND);
00579 }
00580 }
00581 else if ((half == GH_SECOND) && (now >= 2 * mHalfTime))
00582 {
00583
00584 mGameState->SetPlayMode(PM_GameOver);
00585 }
00586 }
00587
00588 void
00589 SoccerRuleAspect::Update(float deltaTime)
00590 {
00591 if (
00592 (mGameState.get() == 0) ||
00593 (mBallState.get() == 0) ||
00594 (mBallBody.get() == 0)
00595 )
00596 {
00597 return;
00598 }
00599
00600 CheckTime();
00601
00602 TPlayMode playMode = mGameState->GetPlayMode();
00603
00604 static bool updated = false;
00605
00606 switch (playMode)
00607 {
00608 case PM_BeforeKickOff:
00609
00610
00611
00612 if (! updated)
00613 {
00614 UpdateCachedInternal();
00615 updated = true;
00616 }
00617
00618 UpdateBeforeKickOff();
00619 break;
00620
00621 case PM_PlayOn:
00622 UpdatePlayOn();
00623 break;
00624
00625 case PM_KickOff_Left:
00626 UpdateKickOff(TI_LEFT);
00627 break;
00628 case PM_KickOff_Right:
00629 UpdateKickOff(TI_RIGHT);
00630 break;
00631
00632 case PM_KickIn_Left:
00633 UpdateKickIn(TI_LEFT);
00634 break;
00635 case PM_KickIn_Right:
00636 UpdateKickIn(TI_RIGHT);
00637 break;
00638
00639 case PM_GOAL_KICK_LEFT:
00640 UpdateGoalKick(TI_LEFT);
00641 break;
00642 case PM_GOAL_KICK_RIGHT:
00643 UpdateGoalKick(TI_RIGHT);
00644 break;
00645
00646 case PM_CORNER_KICK_LEFT:
00647 UpdateCornerKick(TI_LEFT);
00648 break;
00649
00650 case PM_CORNER_KICK_RIGHT:
00651 UpdateCornerKick(TI_RIGHT);
00652 break;
00653
00654 case PM_Goal_Left:
00655 case PM_Goal_Right:
00656 UpdateGoal();
00657 break;
00658
00659 case PM_OFFSIDE_LEFT:
00660 UpdateOffside(TI_LEFT);
00661 break;
00662 case PM_OFFSIDE_RIGHT:
00663 UpdateOffside(TI_RIGHT);
00664 break;
00665
00666 case PM_GameOver:
00667 UpdateGameOver();
00668 break;
00669
00670 default:
00671 GetLog()->Error()
00672 << "ERROR: (SoccerRuleAspect) unknown play mode "
00673 << playMode << "\n";
00674 break;
00675 }
00676 }
00677
00678 void
00679 SoccerRuleAspect::OnLink()
00680 {
00681 SoccerControlAspect::OnLink();
00682
00683 mGameState = shared_dynamic_cast<GameStateAspect>
00684 (GetControlAspect("GameStateAspect"));
00685
00686 mBallState = shared_dynamic_cast<BallStateAspect>
00687 (GetControlAspect("BallStateAspect"));
00688
00689 SoccerBase::GetBallBody(*this,mBallBody);
00690 }
00691
00692 void
00693 SoccerRuleAspect::OnUnlink()
00694 {
00695 SoccerControlAspect::OnUnlink();
00696
00697 mGameState.reset();
00698 mBallState.reset();
00699 mBallBody.reset();
00700 }
00701
00702
00703 void
00704 SoccerRuleAspect::UpdateCachedInternal()
00705 {
00706 SoccerBase::GetSoccerVar(*this,"BallRadius",mBallRadius);
00707 SoccerBase::GetSoccerVar(*this,"RuleGoalPauseTime",mGoalPauseTime);
00708 SoccerBase::GetSoccerVar(*this,"RuleKickInPauseTime",mKickInPauseTime);
00709 SoccerBase::GetSoccerVar(*this,"RuleHalfTime",mHalfTime);
00710 SoccerBase::GetSoccerVar(*this,"RuleDropBallTime",mDropBallTime);
00711 SoccerBase::GetSoccerVar(*this,"FieldLength",mFieldLength);
00712 SoccerBase::GetSoccerVar(*this,"FieldWidth",mFieldWidth);
00713 SoccerBase::GetSoccerVar(*this,"GoalWidth",mGoalWidth);
00714 SoccerBase::GetSoccerVar(*this,"FreeKickDistance",mFreeKickDist);
00715 SoccerBase::GetSoccerVar(*this,"AutomaticKickOff",mAutomaticKickOff);
00716 SoccerBase::GetSoccerVar(*this,"WaitBeforeKickOff",mWaitBeforeKickOff);
00717 SoccerBase::GetSoccerVar(*this,"SingleHalfTime",mSingleHalfTime);
00718 SoccerBase::GetSoccerVar(*this,"UseOffside",mUseOffside);
00719
00720
00721
00722
00723
00724 mRightHalf = salt::AABB2(Vector2f(0, -mFieldWidth/2.0 - 10.0),
00725 Vector2f(mFieldLength/2.0 + 10, mFieldWidth/2.0 + 10.0));
00726 mLeftHalf = salt::AABB2(Vector2f(0, -mFieldWidth/2.0 - 10.0),
00727 Vector2f(-mFieldLength/2.0 - 10, mFieldWidth/2.0 + 10.0));
00728
00729
00730 mRightPenaltyArea = salt::AABB2(Vector2f(mFieldLength/2.0 - 16.5, -16.5 - mGoalWidth/2.0),
00731 Vector2f(mFieldLength/2.0 , 16.5 + mGoalWidth/2.0));
00732 mLeftPenaltyArea = salt::AABB2(Vector2f(-mFieldLength/2.0 + 16.5, -16.5 - mGoalWidth/2.0),
00733 Vector2f(-mFieldLength/2.0, 16.5 + mGoalWidth/2.0));
00734 }
00735
00736 void
00737 SoccerRuleAspect::Broadcast(const string& message, const Vector3f& pos,
00738 int number, TTeamIndex idx)
00739 {
00740 TAgentStateList agent_states;
00741 if (! SoccerBase::GetAgentStates(*mBallState, agent_states, idx))
00742 {
00743 return;
00744 }
00745
00746 TAgentStateList opponent_agent_states;
00747 if (! SoccerBase::GetAgentStates(*mBallState, opponent_agent_states,
00748 SoccerBase::OpponentTeam(idx)))
00749 {
00750 return;
00751 }
00752
00753 if (message.size() > mSayMsgSize)
00754 {
00755 return;
00756 }
00757
00758 salt::BoundingSphere sphere(pos, mAudioCutDist);
00759
00760 shared_ptr<Transform> transform_parent;
00761 shared_ptr<Body> agent_body;
00762
00763 for (
00764 TAgentStateList::const_iterator it = agent_states.begin();
00765 it != agent_states.end();
00766 it++
00767 )
00768 {
00769 if ( (*it)->GetUniformNumber() == number)
00770 {
00771 (*it)->AddSelfMessage(message);
00772 continue;
00773 }
00774 SoccerBase::GetTransformParent(*(*it), transform_parent);
00775
00776
00777 SoccerBase::GetAgentBody(transform_parent, agent_body);
00778
00779
00780 Vector3f new_pos = agent_body->GetPosition();
00781 if (sphere.Contains(new_pos))
00782 {
00783 Vector3f relPos = pos - new_pos;
00784 relPos = SoccerBase::FlipView(relPos, idx);
00785 float direction = salt::gRadToDeg(salt::gArcTan2(relPos[1], relPos[0]));
00786 (*it)->AddMessage(message, direction, true);
00787 }
00788 }
00789
00790 for (
00791 SoccerBase::TAgentStateList::const_iterator it = opponent_agent_states.begin();
00792 it != opponent_agent_states.end();
00793 it++
00794 )
00795 {
00796 SoccerBase::GetTransformParent(*(*it), transform_parent);
00797
00798
00799 SoccerBase::GetAgentBody(transform_parent, agent_body);
00800
00801
00802 Vector3f new_pos = agent_body->GetPosition();
00803 if (sphere.Contains(new_pos))
00804 {
00805 Vector3f relPos = pos - new_pos;
00806 relPos = SoccerBase::FlipView(relPos, SoccerBase::OpponentTeam(idx));
00807 float direction = salt::gRadToDeg(salt::gArcTan2(relPos[1], relPos[0]));
00808 (*it)->AddMessage(message, direction, false);
00809 }
00810 }
00811 }
00812
00813 bool
00814 SoccerRuleAspect::CheckOffside()
00815 {
00816 shared_ptr<AgentAspect> agent;
00817 shared_ptr<AgentState> agentState;
00818 TTime time;
00819
00820 if (! mBallState->GetLastCollidingAgent(agent,time))
00821 {
00822 return false;
00823 }
00824
00825 TTime lastModeChange = mGameState->GetLastModeChange();
00826
00827 if (time == lastModeChange)
00828 {
00829 mFirstCollidingAgent = true;
00830 }
00831
00832
00833
00834 if (mGameState->GetTime() == time)
00835 {
00836 if (mPreLastCollidingAgent == agent)
00837 {
00838 mNotOffside = true;
00839 }
00840 else
00841 {
00842 mPreLastCollidingAgent = agent;
00843 mNotOffside = false;
00844 }
00845 }
00846
00847
00848 if (! SoccerBase::GetAgentState(agent,agentState))
00849 {
00850 return false;
00851 }
00852
00853 TTeamIndex idx = agentState->GetTeamIndex();
00854
00855 list<shared_ptr<AgentState> > opp_agent_states;
00856 if (! SoccerBase::GetAgentStates(*mBallState, opp_agent_states,
00857 SoccerBase::OpponentTeam(idx)))
00858 {
00859 return false;
00860 }
00861
00862 float opp_goalkeeper_pos;
00863 float opp_defender_pos;
00864
00865 opp_goalkeeper_pos = 0.0;
00866 opp_defender_pos = 0.0;
00867
00868 shared_ptr<Transform> transform_parent;
00869 shared_ptr<Body> agent_body;
00870
00871 list<shared_ptr<AgentState> >::const_iterator it;
00872 for (it = opp_agent_states.begin(); it != opp_agent_states.end(); it++)
00873 {
00874 SoccerBase::GetTransformParent(*(*it), transform_parent);
00875 SoccerBase::GetAgentBody(transform_parent, agent_body);
00876
00877 Vector3f opp_agent_pos = agent_body->GetPosition();
00878
00879 if (SoccerBase::OpponentTeam(idx) == TI_LEFT)
00880 {
00881 if (opp_agent_pos[0] <= opp_goalkeeper_pos)
00882 {
00883 opp_defender_pos = opp_goalkeeper_pos;
00884 opp_goalkeeper_pos = opp_agent_pos[0];
00885 }
00886 else if (opp_agent_pos[0] <= opp_defender_pos)
00887 {
00888 opp_defender_pos = opp_agent_pos[0];
00889 }
00890 }
00891 else
00892 {
00893 if (opp_agent_pos[0] >= opp_goalkeeper_pos)
00894 {
00895 opp_defender_pos = opp_goalkeeper_pos;
00896 opp_goalkeeper_pos = opp_agent_pos[0];
00897 }
00898 else if (opp_agent_pos[0] >= opp_defender_pos)
00899 {
00900 opp_defender_pos = opp_agent_pos[0];
00901 }
00902 }
00903 }
00904
00905 Vector3f ball_pos = mBallBody->GetPosition();
00906
00907 SoccerBase::GetTransformParent(*agentState, transform_parent);
00908 SoccerBase::GetAgentBody(transform_parent, agent_body);
00909 Vector3f agent_pos = agent_body->GetPosition();
00910
00911 if ( (mGameState->GetTime() == time) && mFirstCollidingAgent )
00912 {
00913 if (((idx == TI_LEFT) && (agent_pos[0] > opp_defender_pos)
00914 && (agent_pos[0] > ball_pos[0])) ||
00915 ((idx == TI_RIGHT) && (agent_pos[0] < opp_defender_pos)
00916 && (agent_pos[0] < ball_pos[0])))
00917 {
00918 mFirstCollidingAgent = true;
00919 }
00920 else
00921 {
00922 mFirstCollidingAgent = false;
00923 }
00924 }
00925
00926
00927
00928 bool offside = false;
00929
00930 if ((idx == TI_LEFT) && !mFirstCollidingAgent && !mNotOffside)
00931 {
00932 vector<int>::const_iterator it_offside;
00933 for (
00934 it_offside = mInOffsideLeftPlayers.begin();
00935 it_offside != mInOffsideLeftPlayers.end();
00936 it_offside++)
00937 {
00938 if (agentState->GetUniformNumber() == *it_offside)
00939 {
00940 mGameState->SetPlayMode(PM_OFFSIDE_RIGHT);
00941 offside = true;
00942 }
00943 }
00944 if (!offside && (agent_pos[0] > opp_defender_pos))
00945 mFirstCollidingAgent = true;
00946 }
00947 else if (!mFirstCollidingAgent && !mNotOffside)
00948 {
00949 vector<int>::const_iterator it_offside;
00950 for (
00951 it_offside = mInOffsideRightPlayers.begin();
00952 it_offside != mInOffsideRightPlayers.end();
00953 it_offside++
00954 )
00955 {
00956 if (agentState->GetUniformNumber() == *it_offside)
00957 {
00958 mGameState->SetPlayMode(PM_OFFSIDE_LEFT);
00959 offside = true;
00960 }
00961 }
00962 if (!offside && (agent_pos[0] < opp_defender_pos))
00963 mFirstCollidingAgent = true;
00964 }
00965
00966
00967 if ( mGameState->GetTime() == time)
00968 {
00969 mInOffsideLeftPlayers.clear();
00970 mInOffsideRightPlayers.clear();
00971
00972 mFreeKickPos = mBallState->GetLastValidBallPosition();
00973 mFreeKickPos[2] = mBallRadius;
00974
00975 list<shared_ptr<AgentState> > agent_states;
00976 if (! SoccerBase::GetAgentStates(*mBallState, agent_states, idx))
00977 {
00978 return false;
00979 }
00980
00981 for (it = agent_states.begin(); it != agent_states.end(); it++)
00982 {
00983 SoccerBase::GetTransformParent(*(*it), transform_parent);
00984 SoccerBase::GetAgentBody(transform_parent, agent_body);
00985
00986 Vector3f agent_pos = agent_body->GetPosition();
00987
00988 if (idx == TI_LEFT)
00989 {
00990 if ((agent_pos[0] > opp_defender_pos)
00991 && (agent_pos[0] > ball_pos[0]))
00992 {
00993 mInOffsideLeftPlayers.push_back((*it)->GetUniformNumber());
00994 }
00995 }
00996 else
00997 {
00998 if ((agent_pos[0] < opp_defender_pos)
00999 && (agent_pos[0] < ball_pos[0]))
01000 {
01001 mInOffsideRightPlayers.push_back((*it)->GetUniformNumber());
01002 }
01003 }
01004 }
01005
01006 }
01007
01008 return true;
01009 }
01010
01011 void
01012 SoccerRuleAspect::UpdateOffside(TTeamIndex idx)
01013 {
01014
01015 if (mGameState->GetModeTime() < mKickInPauseTime)
01016 {
01017 return;
01018 }
01019
01020
01021 Vector3f ball_pos = mBallBody->GetPosition();
01022 ClearPlayers(mFreeKickPos, mFreeKickDist, mFreeKickMoveDist,
01023 SoccerBase::OpponentTeam(idx));
01024
01025
01026
01027 if (mDropBallTime > 0 &&
01028 mGameState->GetModeTime() > mDropBallTime)
01029 {
01030 DropBall(mFreeKickPos);
01031 return;
01032 }
01033
01034
01035
01036
01037 shared_ptr<AgentAspect> agent;
01038 shared_ptr<AgentState> agentState;
01039 TTime time;
01040 if (! mBallState->GetLastCollidingAgent(agent,time))
01041 {
01042 GetLog()->Error()
01043 << "ERROR: (SoccerRuleAspect) no agent collided yet\n";
01044 return;
01045 }
01046
01047 if (! SoccerBase::GetAgentState(agent,agentState))
01048 {
01049 return;
01050 }
01051
01052 TTeamIndex collidingAgentIdx = agentState->GetTeamIndex();
01053
01054 TTime lastChange = mGameState->GetLastModeChange();
01055 if (time > lastChange && collidingAgentIdx==idx)
01056 {
01057 mGameState->SetPlayMode(PM_PlayOn);
01058 }
01059 else
01060 {
01061
01062 MoveBall(mFreeKickPos);
01063 }
01064 }
01065
01066 void
01067 SoccerRuleAspect::ClearPlayersWithException(const salt::Vector3f& pos,
01068 float radius, float min_dist, TTeamIndex idx,
01069 shared_ptr<AgentState> agentState)
01070 {
01071 if (idx == TI_NONE || mBallState.get() == 0) return;
01072 std::list<boost::shared_ptr<AgentState> > agent_states;
01073 if (! SoccerBase::GetAgentStates(*mBallState, agent_states, idx))
01074 return;
01075
01076 salt::BoundingSphere sphere(pos, radius);
01077 boost::shared_ptr<oxygen::Transform> transform_parent;
01078 boost::shared_ptr<oxygen::Body> agent_body;
01079 std::list<boost::shared_ptr<AgentState> >::const_iterator i;
01080 for (i = agent_states.begin(); i != agent_states.end(); ++i)
01081 {
01082 if (agentState == (*i))
01083 continue;
01084
01085 SoccerBase::GetTransformParent(*(*i), transform_parent);
01086
01087 SoccerBase::GetAgentBody(transform_parent, agent_body);
01088
01089 Vector3f new_pos = agent_body->GetPosition();
01090 if (sphere.Contains(new_pos))
01091 {
01092 float dist = salt::UniformRNG<>(min_dist, min_dist + 2.0)();
01093
01094 if (idx == TI_LEFT)
01095 {
01096 if (pos[0] - dist < -mFieldLength/2.0)
01097 {
01098 new_pos[1] = pos[1] < 0 ? pos[1] + dist : pos[1] - dist;
01099 } else {
01100 new_pos[0] = pos[0] - dist;
01101 }
01102 } else {
01103 if (pos[0] + dist > mFieldLength/2.0)
01104 {
01105 new_pos[1] = pos[1] < 0 ? pos[1] + dist : pos[1] - dist;
01106 } else {
01107 new_pos[0] = pos[0] + dist;
01108 }
01109 }
01110 new_pos[2] = 1.0;
01111 MoveAgent(agent_body, new_pos);
01112 }
01113 }
01114 }