IBM ROBO-CODE2007. 7. 11. 13:52

[Robocode]반중력 운동(Anti-gravity movement)

Posted 2006/10/12 18:40 by 수연
피할 수 있는 지점을 설정하고, 움직임 패턴을 만들어 적의 총알을 피한다!

Alisdair Owens
Student, University of Southampton
2002년 5월

반중력 운동(Anti-gravity movement)은 대부분의 Robocoder 전문가들이 선택하는 움직임 유형이다. 이를 사용하여 지도상에서 피할 수 있는 지점을 설정하고 움직임 패턴을 만들며 적의 총알을 피할 수 있다. Alisdair Owens는 이 유용한 기술의 구현 방법을 설명하고 테스트 구동을 위해 로봇 예제도 제공한다.

반중력 운동(Anti-gravity movement)은 유연성이 뛰어난 기술로서 전투장 내에서 피신할 수 있는 특별한 지점 (중력 지점-gravity points)을 정의하여 패턴 분석 로봇을 혼란에 빠트린다. 각각의 중력 지점(gravity point)은 세기(strength)에 따라 할당된다. x와 y의 방향에서 세기의 요소를 결정하여 모든 적군 로봇을 피할 수 있다. ("반중력(Anti-gravity) 용어정리" 참조)

반중력(Anti-gravity) 용어정리

중력 지점(Gravity points): 공격하기 원하는 장소로 정의된 Robocode 전투장 내의 장소들.

힘(Forces): 각각의 중력 지점은 힘(force) 또는 세기(strength)를 할당 받는다. 값이 클수록 로봇은 그 지점에서 힘을 만들어 내면서 공격할 수 있다.

힘의 컴포넌트: 각각의 힘은 x (수평) 방향과 , y (수직) 방향에서 작동하는 컴포넌트를 갖고있다. 45도 각도는 x와 y 방향에서 동등한 컴포넌트를 갖고있다. 90도 각도는 x 방향에서 전적으로 작동한다.

힘 결정하기: 여러 힘들이 작동할 때 만들어진 모든 힘을 산정하는 과정이다. 예를 들어 x 방향에서 작동하는 -200의 힘이 있고 또한 x 방향에서 300의 힘이 있다면 만들어진 힘의 전체는 100이다.

반중력 운동의 수학원리
반중력에 내포된 수학은 실제로 매우 간단하다. 삼각법만 알면 된다.

그림 1에서 "F"라는 화살은 Crazy로 부터 AntiGravityBot에 가해지는 힘의 방향을 나타낸다. 힘은 다른 두 개의 화살에서 보이듯이 x와 y에 있는 컴포넌트로 간주될 수 있다. 힘을 결정하여 x와 y 방향의 모든 중력 지점에서 모든 힘을 한데 모을 수 있다 .

그림 1. 힘 결정하기
Resolving forces

로봇이 멀리있는 로봇에 의해 영향받지 않도록 하려면, 세기(strength)가 중력 지점의 힘이고 거리(distance)가 중력 지점과 로봇 사이의 거리인 곳에서 force = strength/Math.pow(distance,2) 함수를 사용하여 중력 지점으로부터 로봇에 가해지는 힘을 계산해야한다.

코드
다음 코드는 기본적인 시스템 코드이다. Listing 1은 반중력의 주요 함수를 보여주고 있다. 한 벡터 내에서 모든 중력 지점을 통해 순환하고 힘을 결정하며 정확한 방향으로 로봇을 움직인다. 적군 로봇들이 격퇴 지점에 가있도록 할 것을 권장하는 바이다. 이렇게 하려면 전투장 모양을 항상 업데이트 해야한다.

Listing 1.반중력의 일꾼: antiGravMove()

void antiGravMove() {
   double xforce = 0;
   double yforce = 0;
   double force;
   double ang;
   GravPoint p;
  
   for(int i = 0;i<gravpoints.size();i++) {
       p = (GravPoint)gravpoints.elementAt(i);
       //Calculate the total force from this point on us
       force = p.power/Math.pow(getRange(getX(),getY(),p.x,p.y),2);
       //Find the bearing from the point to us
       ang =
   normaliseBearing(Math.PI/2 - Math.atan2(getY() - p.y, getX() - p.x));
       //Add the components of this force to the total force in their
       //respective directions
       xforce += Math.sin(ang) * force;
       yforce += Math.cos(ang) * force;
   }
  
   /**The following four lines add wall avoidance.  They will only
   affect us if the bot is close to the walls due to the
   force from the walls decreasing at a power 3.**/
   xforce += 5000/Math.pow(getRange(getX(),
     getY(), getBattleFieldWidth(), getY()), 3);
   xforce -= 5000/Math.pow(getRange(getX(),
     getY(), 0, getY()), 3);
   yforce += 5000/Math.pow(getRange(getX(),
     getY(), getX(), getBattleFieldHeight()), 3);
   yforce -= 5000/Math.pow(getRange(getX(),
     getY(), getX(), 0), 3);
  
   //Move in the direction of our resolved force.
   goTo(getX()-xforce,getY()-yforce);
}

Listing 2의 helper 메소드는 가장 효율적인 방법으로 어떤 지점으로 움직일 수 있도록 하면서 로봇과 적군로봇 사이의 거리를 두도록 한다.

Listing 2. Helper 메소드

/**Move in the direction of an x and y coordinate**/
void goTo(double x, double y) {
   double dist = 20;
   double angle = Math.toDegrees(absbearing(getX(),getY(),x,y));
   double r = turnTo(angle);
   setAhead(dist * r);
}

/**Turns the shortest angle possible to come to a heading, then returns
the direction the bot needs to move in.**/
int turnTo(double angle) {
   double ang;
   int dir;
   ang = normalisebearing(getHeading() - angle);
   if (ang > 90) {
       ang -= 180;
       dir = -1;
   }
   else if (ang < -90) {
       ang += 180;
       dir = -1;
   }
   else {
       dir = 1;
   }
   setTurnLeft(ang);
   return dir;
}

/**/Returns the distance between two points**/
double getRange(double x1,double y1, double x2,double y2) {
   double x = x2-x1;
   double y = y2-y1;
   double range = Math.sqrt(x*x + y*y);
   return range;
}

마지막으로, Listing 3에서 GravPoint 클래스를 볼 수 있는데 이것은 중력 지점에 대해 우리가 필요로하는 모든 데이터를 보유하고 있다. 격퇴하기 위해서는 power는 마이너스(-)가 되어야한다.

Listing 3. GravPoint class

class GravPoint {
   public double x,y,power;
   public GravPoint(double pX,double pY,double pPower) {
       x = pX;
       y = pY;
       power = pPower;
   }
}

전체 소스 다운로드.

작동 향상
Listings 1 부터 3의 코드는 합리적인 작동을 만들어낸다. 하지만 전투 퍼포먼스에는 미치지 못한다. 로봇이 다른 로봇과 일반적으로 멀리 떨어져있으면 벽에 밀착할 경향이 크다. 예를 들어 일단 로봇이 밑쪽 벽에 다다르면 이 보다 아래에 있는 로봇은 없다. 따라서 벽 자체에서 만들어진 반발력을 제외하고는 이것을 밀어낼 힘이 없는 것이다. 벽의 반발력은 제한된 범위이기 때문에 형편없는 작동만 만들어내는 것이다.

이 문제를 해결하기위해서 전투장 주변의 일련의 지점들에 모든 힘을 모으는 시스템을 사용한다. 그런다음 평균보다 큰 힘을 가진 지점들에 반발력 값을 할당하고 평균 힘보다 낮은 값을 가진 지점에 견인력 값을 할당한다. 그런 다음 로봇에 새로운 지점들의 힘을 할당한다. 견인 지점을 할당할 때 조심해야한다. 로봇이 견인 지점에 가까이 갈 때 근방을 배회하면서 결코 떠나지 않을 것이다. 이런 문제 때문에 중간 지점에 무작위로 위치를 할당하고 위치를 정기적으로 바꾼다.

추가적인 작동 향상
반중력은 놀랍도록 융통성이 있는 기술이다. 우리가 만들 수 있는 전체 작동 범위를 논하는 것은 불가능하다. 다음은 그 중 흥미로운 것들이다:

목표 선택: 공격하기 편하거나 힘이 약한 목표물에 낮은 반발력 값을 할당하여 그 목표물에 가까이 가서 공격할 수 있다.

불규칙성(Randomisation): 규칙성을 기본으로 하고, x와 y 힘에서 임의의 수를 더하거나 빼어서 좀더 임의적인 움직임을 만들어내고 때때로 멈추기도 하며 적군의 타겟 시스템을 속일 수도 있다.

총알 피하기 : 적군이 자신에게 발사할 때를 안다면 반중력 지점으로 발사되는 총알을 모델링할 수 있다. 예를 들어 선형 타케팅으로 발사된다면 매 순서마다 중력 지점의 위치를 업데이트 하여 총알을 피할 수 있다.

리더(leader)를 따르기: 자신의 로봇이 따라갈 "매력적인" 지점을 만드는 것이다. 이 지점을 움직여서 원하는 모든 패턴을 만들 수 있다.



Posted by BAGE