RealTimeBattle

サンプルプログラム

rotate_and_fire.cc を改造した。

ファイル raf.lzh ダウンロード。 主要プログラムリストダウンロード

構成

Message.h
付録のサンプルプログラムに入っているプロトコルに使われるメッセージ の定義
IntlDefs.h
Native Language Support(NLS)対応メッセージ処理マクロの定義
robo.h
サーバであるシミュレータとの通信や、メッセージの解釈などを定義した 抽象クラス Robo の定義。 メッセージを受けた時の動作は virtual とし、仮実装としてなにもしない ({}) としている。
robo.cc
robo.h の基本部分の実装
raf.h
Robo の派生クラス RotateAndFire クラスの定義。 Robo の virtual メソッドのうち実装するものだけプロトタイプを書く。
raf.cc
RotateAndFire のメソッドの定義。 コンストラクタでは Robo のコンストラクタを指定する。

詳細

robo.h


class Robo
{
  char* robot_name;
  char* robot_colour;

名前と色は Robo 内だけで処理するため、 private


 public:
  Robo                        (const char* name, const char* colour);
  virtual ~Robo                       ();
  void initValue              ();

コンストラクタで名前と色を指定する。 派生クラスを前提としているのでデストラクタは仮想にする。


  void robot_option           ( const int option_nr, const int value );
  void name                   ( const char* name );
  void colour                 ( const char* home, const char* away );
  void rotate                 ( const int what, const double vel );
...

シミュレータとやりとりする部分は派生クラスでオーバーライドする必要ない ので virtual 指定しない。


  void check_messages  ( );

check_messages が主メソッド シミュレータからのメッセージを受けとり、解析して各メソッドを呼び出す。


  virtual void game_starts            (){}
  virtual void radar_noobject ( const double dist, const double angle ){}
  virtual void radar_robot    ( const double dist, const double angle ){}
...

各呼び出されるメソッドは virtual 指定だが、デフォルトでなにもしない関 数として定義される。


  bool is_quitting () { return quitting; }
 protected:
  bool quitting;
  // Boolean variables to control if it is allowed to change robot
  // rotation and acceleration.
  bool rotate_allowed;
  bool acceleration_change_allowed;

派生クラスで読み出す可能性のある変数は protected で宣言

robo.cc


void
Robo::robot_option( const int option, const int value )
{
  cout << "RobotOption " << option << " " << value << endl;
}
...

サーバ(シミュレータ)へは標準出力でメッセージを送る


void
Robo::check_messages( )
{
  quitting = false;

  char msg_name[81];
  message_to_robot_type msg_t;

  cin.clear();
  while( !cin.eof() && !quitting )
    {
      pre_checking_messages();

      cin >> msg_name;
      msg_t = name2msg_to_robot_type(msg_name);

      switch(msg_t)
        {
        case INITIALIZE:
          {
            int init;
            cin >> init;
            initialize( init );
          }
          break;
        case YOUR_NAME:
          {
            char name[81];
            cin >> name;
            your_name( name );
          }
          break;
        case YOUR_COLOUR:
          {
            char col[81];
            cin >> col;
            your_colour( col );
          }
          break;
        case GAME_OPTION:
          {
            int nr;
            double value;
            cin >> nr >> value;
            game_option( nr, value );
          }
          break;
        case GAME_STARTS:
          game_starts();
          break;
        case RADAR:
          {
            double dist, angle;
            int object;

            cin >> dist >> object >> angle;
            switch(object)
              {
              case NOOBJECT:
                radar_noobject( dist, angle );
                break;
              case ROBOT:
                radar_robot( dist, angle );
                break;
              case WALL:
                radar_wall( dist, angle );
                break;
              case SHOT:
                radar_shot( dist, angle );
                break;
              case COOKIE:
                radar_cookie( dist, angle );
                break;
              case MINE:
                radar_mine( dist, angle );
                break;
              default:
                cout << "Print" << _("Unknown Object seen!") << endl;
                break;
              }
          }
          break;          
        case COORDINATES:
          {
            double x, y, rotation;
            cin >> x >> y >> rotation;
            coordinates( x, y, rotation );
          }
          break;
        case INFO:
          {
            double time, speed, cannon_angle;
            cin >> time >> speed >> cannon_angle;
            info( time, speed, cannon_angle );
          }
          break;
        case ROBOT_INFO:
          {
            double energy;
            int enemy;
            cin >> energy >> enemy;
            robot_info( energy, enemy );
          }
          break;
        case ROTATION_REACHED:
          {
            int what;
            cin >> what;
            rotation_reached( what );
          }
          break;
        case ENERGY:
          {
            double en;
            cin >> en;
            energy( en );
          }
          break;
        case ROBOTS_LEFT:
          {
            int nr;
            cin >> nr;
            robots_left( nr );
          }
          break;
        case COLLISION:
          {
            int object;
            double angle;

            cin >> object >> angle;
            switch( object )
              {
              case NOOBJECT:
                collision_noobject( angle );
                break;
              case ROBOT:
                collision_robot( angle );
                break;
              case WALL:
                collision_wall( angle );
                break;
              case SHOT:
                collision_shot( angle );
                break;
              case COOKIE:
                collision_cookie( angle );
                break;
              case MINE:
                collision_mine( angle );
                break;
              default:
                cout << "Print " << _("Collided with Unknown Object!") << endl;
                break;
              }
          }
          break;
        case WARNING:
          {
            int type;
            char text[81];
            cin >> type;
            cin.getline(text,80,'\n');
            warning( type, text );
          }
          break;
        case DEAD:
          dead();
          break;
        case GAME_FINISHES:
          game_finishes();
          break;
        case EXIT_ROBOT:
          exit_robot();
          break;
        default:
          break;
        }
    }
}

サーバからのメッセージを受けて、対応するメソッドを呼び出す。

raf.h


class RotateAndFire :public Robo
{
public:
  RotateAndFire               (const char* name, const char* colour);
  //  ~RotateAndFire              ();

  void game_starts            ();

  // These functions are called when the robot gets a message
  // of the corresponding type. There are several radar and
  // collision functions. These functions corresponds to each
  // object that the robot has collided with or found with the radar.
  void radar_robot            ( const double dist, const double angle );
  void radar_shot             ( const double dist, const double angle );
...

実装するメソッドだけ、プロトタイプを記述する。 なにもする必要のないメッセージは親クラス Robo で既になにもしないと 定義されているのでここでは記入しない。

raf.cc


RotateAndFire::RotateAndFire (const char* name, const char* colour)
    :Robo (name, colour)
{}

コンストラクタでは親クラス Robo のコンストラクタに名前と色が伝わるよう に指定する。


void
RotateAndFire::radar_robot( const double dist, const double angle )
{
  if( radar_and_cannon_rotate != - robot_rotate )
    {
      radar_and_cannon_rotate = - robot_rotate;
      rotate( 6, radar_and_cannon_rotate );
    }

  if( dist < 2 && acceleration != 0.0 )
    {
      acceleration = 0.0;
      accelerate( acceleration );
      brake_value = 1.0;
      brake( brake_value );
      if( debug_level >= 1 )
        std::cout << "Debug "<< _("Brakes locked: Robot found and at distance")
             << " " << dist << std::endl;
    }
  shoot( 2 );
}

レーダに弾が映った時呼び出されるメソッド。

  1. ロボットの回転と逆向きにレーダとキャノンを回す。
  2. 弾との距離が近く、しかも加速している時、加速を止め、ブレーキをかけ る。
  3. 2 の強さで弾を撃つ

main.cc


#include "robo.h"
#include "raf.h"

必要なヘッダファイルを記述する


int 
main(int argc, char * argv[])
{
  class Robo *raf_obj= new RotateAndFire("Rotate&Fire(new)", "9977dd");
  raf_obj->robot_option( USE_NON_BLOCKING, false );
  raf_obj->check_messages();

  return(0);
}

オブジェクトをコンストラクタで生成したあとは、オプションを指定して check_message()メソッドを呼び出すだけである。

Makefile


raf.robot: robo.o raf.o main.o
	$(CXX) -o $@ $^
robo.o:	robo.h
robo.o: Messagetypes.h
robo.o: IntlDefs.h
raf.o: raf.h robo.h
raf.o: IntlDefs.h
main.o: raf.h robo.h

gcc-2.95.2 でエラーが出る時

MAX_RAND が undefined というエラーが出る
とりあえず #include <cstdlib>をしてみる。
rint が暗黙の定義になっていると言うエラー
#define rint(arg) ((int)(arg))と定義する。
str... が undefined というエラー
#include <cstring> を加え、さらにエラーが出るよ うだったら、 using std::str(該当関数); を付け加える。
M_PI が undefined
# define M_PI 3.14159265358979323846など適 当な精度で定義する。

坂本直志 <[email protected]>
東京電機大学工学部情報通信工学科