亀場サーバー操作マニュアル
このページでは、UNIX系のシステムでC言語を使って亀場を操る方法と、亀場サーバーの基本的な使い方を説明する。
1. 亀場サーバーを使ったプログラミング
亀場サーバー
Linux(64bit)用実行ファイル
tfield3d-linux64.zip
Linux用実行ファイル
tfield3d-linux.zip
Windows用実行ファイル
tfield-win32.zip
Macintosh用実行ファイル
TField.app.zip
各種言語用API
C言語用インクルードファイル
turtle.h
Windows用インクルードファイル
turtlew.h
C言語分割コンパイル用ファイル
turtle-def.h, turtle-func.c
VisualStudio10用スターター
turtle-vs10-c-starter.zip(C)
turtle-vs10-cpp-starter.zip(C++)
Java用Turtleクラス
Turtle.class
Ruby用Turtleクラス
turtle.rb
Python用Turtleクラス
turtle.py
turtle3.py (Python 3)
亀場サーバーは、タートルグラフィックスなどを行うための独立したアプリケーションで、あなたがこれから作成する(あるいはしている) Cのプログラムは、サーバーと通信しながら、亀場に指令を発することで、「亀」を操る。 そのための手順(関数)をまとめたファイルがturtle.hになる。 このturtle.hの内容を少しでも変更すると、コンパイルできなくなったり、予期せぬ動作を引き起こす可能性があるので、 中身は覗くだけにして、決して編集、保存しないこと。
このturtle.hは、作成中のCのソースファイル(何々.c)と同じディレクトリ(フォルダー)に置いておく。 そしてCのプログラムのはじまりの箇所に、必ず
#include "turtle.h"
の行が必要。
なお、Windows環境では、turtle.hの代わりにturtlew.hをダウンロードの上、#include "turtlew.h"と記入。
ヘッダーファイル turtle.h は、初学者用に、プログラム全体が1つのソースプログラム(何々.c)で構成されているCプログラムから使われる状況を想定している。 turtle.hの中に関数定義が含まれているので(本当はよい作法ではないが)、複数のソースファイルからインクルードすると、名前が衝突してしまう。
そのような場合のために、ヘッダー定義ファイルturtle-def.h、および 関数定義ファイル(プログラム)turtle-func.cも用意しておいたので、 分割コンパイル+リンクを行う場合は、こちらを使用すること。
WindowsのVisual C++を使う場合は、こちらのページの一番下あたりに書かれている方法を参照のこと。
2. 亀を操るための機能(C言語用)
基本的に、亀場関係の関数名は全て大文字で記述するようになっている。
例えば FD(100.0);のつもりでfd(100.0);と記述しても、コンパイルエラーになるので注意。
亀や亀場から情報を得るための関数名はQ_で始まる。
 Command me with the functions described in this page. I'll follow your order to the letter.
	
Command me with the functions described in this page. I'll follow your order to the letter.
描画関数一覧
| 関数名 | 気持ち | 機能 | 使用例 | 
|---|---|---|---|
| CON(接続先) | CONnect | 亀場サーバーに接続する。 「接続先」は相手のIPアドレスまたはドメイン名 描画のはじめに1回だけ実行 自分のPCの亀場サーバーを使うときは接続先 として"localhost"を指定 | CON("localhost"); | 
| CLR() | CLeaR | 描かれてあった内容とゾンビ亀を消去する | CLR(); | 
| RST() | ReSeT | 亀を原点に移動し、方向を0度にセットする 亀の状態もリセットされる 対戦モード中は使えない | RST(); | 
| HOME() | HOME | 亀を原点(0,0)に移動し、方向を0度にセット 亀の状態(ペンの上下等)は変化なし 対戦モード中は使えない | HOME(); | 
| FD(距離) | ForwarD | 亀を指定の距離だけ前進させる 経路上に障害物(他の亀)が居るときは移動できない 距離はfloat型で渡す | FD(100.0); | 
| BK(距離) | BacKward | 亀を指定の距離だけ後退させる 経路上に障害物(他の亀)が居るときは移動できない 距離はfloat型で渡す | BK(i*3); | 
| JUMP(x座標,y座標) | JUMP to | 指定の座標に亀を移動 亀の向きは変わらない 対戦モード中は使えない 座標値はfloat型で渡す | JUMP(x+10,y-10); | 
| RJUMP(x移動,y移動) | Relative JUMP to | 現在地からの相対移動 亀の向きは変わらない 対戦モード中は使えない 座標値はfloat型で渡す | RJUMP(dx,dy); | 
| RT(角度) | turn RightT | その場で角度(°)だけ右(時計回り)回転 角度はfloat型で渡す | RT(90.0); | 
| LT(角度) | turn LefT | その場で角度(°)だけ左(反時計回り)回転 角度はfloat型で渡す | LT(rad*180/M_PI); | 
| EAST()NORTH()WEST()SOUTH() | turn to (direction) | 右(EAST)、上(NORTH)、左(WEST)、 下(SOUTH)に頭の方向を向ける 対戦モード中は無効 | SOUTH(); | 
| LW(線の太さ) | set Line Width | 描画する線の太さを指定 機種によって指定できる最大値は異なる 太さはfloat型で渡す | LW(2.0); | 
| PD() | Pen Down | ペンを下ろす | PD(); | 
| PU() | Pen Up | ペンを上げる PD( )とPU( )の間が線で結ばれる | PU(); | 
| SAY(文字列) | SAY | 現在地に"文字列"をプリント 半角英数字のみ対応 | SAY("I'm smart."); | 
| TPRINTF(書式,変数リスト) | Turtle's PRINTF | printf()関数の要領で数値などをプリント 半角英数字のみ対応 「改行」はできない | TPRINTF("x=%f y=%f",x,y); | 
| COL(赤,緑,青) | set COLor | 描画する線の色を変更(初期値は赤) ペンダウン(PD( ))する前に指定する 光の三原色をfloat型で指定。各値の最小は0、最大は1( 例えば (1.0,1.0,0.0)は黄色 | COL(0.7,1.0,0.0); | 
| BGC(赤,緑,青) | set BackGround Color | 「亀場」の背景色を設定(初期値は黒) | BGC(1.0,1.0,0.0); | 
| FILL() | set FILLing mode | 線分で囲まれた凸領域を塗りつぶす (ただし、頂点の数は6以下) | FILL(); | 
| BRUSH() | set BRUSH mode | 毛筆のような線で描く LW( )で線を太くしないと効果は現れない 線の末端にはPU( )を忘れずに入れること | BRUSH(); | 
| POINT() | set POINT mode | 移動地点に(区間を線分で結ばず)点を打つ LW( )の設定値が点の大きさとなる | POINT(); | 
| LINE() | set LINE mode | 塗りつぶしとブラシモードを止め、 通常の線描画に戻る(初期設定) | LINE(); | 
| CARD(種類,X座標,Y座標) | set playing CARD | 座標(x,y)にトランプのカードを置く 種類は整数値で指定し、1がclub-A、2がclub-2,...13がclub-king, 14がheart-A, ..., 52がdiamond-king,53がJokerを表す 負数を指定すると、そのカードを亀場から消去する | CARD(16,100,-20); | 
| CLRCARD() | CLeaR all CARDs | カードを全て消去する | CLRCARD(); | 
| Q_POS(&x,&y) | Query POSition | 現在地の座標を問い合わせる 座標値はfloat型で受ける | float x,y ; ... Q_POS(&x,&y); | 
| Q_DIR(&a) | Query heading DIRection | 現在の方向角(度)を問い合わせる 角度はfloat型で受ける | float a ; ... Q_DIR(&a); | 
「対戦」のための機能
この対戦機能についてはrobocodeを参考にさせていただいた。 Java言語に興味のある学生は、是非、robocodeで遊んで(学んで)みてほしい。
亀場には亀同士が「対戦」を行うための隠し機能がある。それを対戦モード、と呼ぶことにしよう。
亀は持ち点100をあらかじめ持っている。亀は前方に砲弾を発射することができて(FIRE()関数を使用)、 その砲弾が他の亀に命中すると10点が得られる。ただし砲弾を打つ毎に1点を失うので、無駄打ちはすべきでない。 また、自分の撃った砲弾が亀場から消える(壁に当たるか、亀に命中する)まで、再び砲弾を撃つことはできない。
被弾すると30点を失い、持ち点が0を下回った時点でその亀は消滅する。 エネルギー切れで持ち点が0になると、その亀は(消滅はしないけれども)、動くことも、砲弾を撃つこともできなくなる。
対戦モード中は、亀の動作にいくつかの制限が課される。 まず、1回あたりの移動量は最大でも距離2[ピクセル]、回転角は3[度]までとなる。 また、亀場の周囲には「壁」が設けられ、そこから外にはみ出すことはできなくなる。
亀は、いくつかの関数(Q_で始まる)を使って、周囲の状況を探知することができる。 その情報を活用して、移動、転回、砲弾発射の手順をプログラムする。
こうして、持ち点をキープしながら、最後まで生き残った亀が勝者というわけだ。
| 関数名 | 気持ち | 機能 | 使用例 | 
|---|---|---|---|
| BMODE() | Battle MODE | 亀場を対戦モードに切り換える 背景が黒っぽいコルクボード状の柄に変わる 亀場の四方には壁ができ、外に出られなくなる 砲弾発射は-1点、相手に命中すると+10点、被弾は-30点 最初の持ち点は100。持ち点が0になると動けなくなる | BMODE(); | 
| GMODE() | Graphics MODE | 亀場を通常のタートルグラフィックス用に切り換える 背景が無地になる 亀は「外」にも移動できるようになり、 点数や名前の表示は消える | GMODE(); | 
| FIRE() | FIRE | 前方に「大砲」を発射する 一発発射ごとに持ち点が1ポイント減る ただし、他の亀に命中すると10ポイントをゲット 一方、被弾した亀は30ポイントを失う また、至近距離でドーナッツに命中すると10ポイント 大砲は1発ずつしか打てない(自分が発射した 砲弾は「亀場」に最大でも1つだけ)。 | FIRE(); | 
| NM(文字列) | NaMe | 亀にニックネームをつける 文字列は "ダブルクォーテーションで囲む" | NM("KAME"); | 
| TM(チーム番号) | TeaM | 自分の属するチームを設定する チーム番号は1〜4の範囲の整数 これを設定していない亀のチーム番号は0 | TM(3); | 
| Q_NT(&亀数) | Query N Turtle | 亀場の亀とドーナッツを合わせた数(自分も含める) 障害物(石)は勘定に入らない。値はint型の変数で受け取る。 | 
int n;
...
Q_NT(&n);
printf("%d alive turtles\n",n) ;
 | 
| Q_RADAR(&角度) | Query to RADAR | 自分に一番近い物体の方向角を問い合わせる 角度は自分の頭の方向を0とした相対値(度)で、 -180から+180の範囲 ただし、角度の計測結果には約±20度の誤差を含む 角度はfloat型の変数で受け取る | 
float angle ;
...
Q_RADAR(&angle);
printf("angle= %f\n",angle) ;
 | 
| Q_FINDER(&結果) | Query to FINDER | 自分の正面の距離20(亀のサイズ)の範囲内に 他の亀や障害物、壁があるかどうか問い合わせる ただし砲弾には反応しない 結果はint型の変数で受ける。 0は障害物無し、1は亀、2はドーナッツ, 3は障害物、4は壁を検出 | 
int yn ;
...
Q_FINDER(&yn);
if (yn==1) printf("found!¥n") ;
 | 
| RF(長さ) | set Range Finder | Q_FINDER()の探索範囲を変更する 長さはfloat型で渡す 初期値は20(亀のサイズ)になっている | RF(100.0); | 
| Q_TM(&チーム番号) | Query TeaE | FINDERとRADARセンサーが検出した亀の チーム番号を問い合わせる。 Q_FINDER(),Q_RADAR()の後に呼び出す 結果はint型の変数で受ける | int team ; ... Q_TM(&team); | 
| BCAS(メッセージ) | BroadCAST | 同じチーム番号の亀に文字列を送信する 文字数は最大で128。 メッセージを受けると、GOT_MESSAGEイベントが発生する | 
BCAS("COME ALL") ; | 
| Q_BCAS(&時間,内容) | Query BroadCAST | 同じチーム番号の亀が送信したメッセージ内容を確認する。 送信時刻(int型)と内容(charの配列)が返される。 | int tm ; char msg[129] ; ... Q_BCAS(&tim,msg) ; | 
| Q_TIME(&時間) | Query TIME | 亀場が出来てからの経過時間を問い合わせる 自分の生存した時間、ではない点に注意 結果はint型の変数で受ける | int now ; ... Q_TIME(&now); | 
| Q_SONAR(&左, &前, &右) | Query to SONAR | 自分の斜め左、正面、斜め右の距離20(亀のサイズ)の 範囲内に障害物があるかどうか問い合わせる ただし、障害物の種類は区別できない。また、砲弾には反応しない 結果はint型の変数で受ける。 0は障害物無し、1は障害物有り | int left,front,right ; ... Q_SONAR(&left, &front, &right); | 
| Q_SCORE(&スコア) | Query my SCORE | 自分の持ち点を問い合わせる 最初に持ち点100から出発し、砲弾を発射する毎に-1点 ただし亀に命中すると+10点が加算される スコアはint型変数で受ける | int score ; ... Q_SCORE(&score); | 
| Q_ID(&チーム番号) | Query my team ID | 自分のチーム番号を問い合わせる 結果はint型の変数で受ける | int myid ; ... Q_ID(&myid); | 
| IDLE(時間長) | IDLE | 指定した時間長だけ動作を停止 ここで時間数は秒(float型)で指定 「ちょっと待ってから・・」に使うとよい | IDLE(1.0); | 
| ROBOT() | generate ROBOT | 亀場に「ロボット亀」を登場させる ロボットは大砲を発射してくるのでとても「危険」 | ROBOT(); | 
| DONUT() | put DONUT | 亀場の中のランダムな位置に「ドーナッツ」をひとつ出す 一匹の亀が出せるドーナッツは最大10個 至近距離でドーナッツに砲弾が命中すると10ポイント | DONUT(); | 
| COIN() | scatter COIN | 亀場の中のランダムな位置にコイン(金貨)を1枚出す コインは亀の行動の邪魔にはならない また、RADAR, FINDER, SONARにも反応しない | COIN(); | 
| BORROWCOIN() | BORROW ten COINs | コインを10枚(亀場の主から)借りる コインは何回も借りられるが、亀場のコインの総数は 300枚に制限されている 亀のはじめの所持金は0(コイン0枚) | BORROWCOIN(); | 
| DROPCOIN() | DROP a COIN | 現在位置にコイン(金貨)を1枚落とす 手持ちのコインが無ければ、落とせない(落ちない) | DROPCOIN(); | 
| PICKCOIN() | PICK a COIN | 現在位置の周りからコインを1枚拾う 近くにコインが無ければ拾えない | PICKCOIN(); | 
| Q_COIN(&枚数) | Query number of COIN | 現在位置の周りのコインの枚数を検知する 結果はint型変数で受ける | int ncoin ; ... Q_COIN(&ncoin); | 
| Q_MYCOIN(&枚数) | Query MY COIN | 手持ちのコインの枚数を問い合わせる 結果はint型変数で受ける | int nmycoin ; ... Q_MYCOIN(&nmycoin); | 
3. さらに進んだ使い方のヒント
ここでは、腕に覚えのある諸君に向けて、少しマニアックな説明をしたい。
亀場サーバーとの通信
亀場のプログラム(tfield-*)はTCP/IPのサーバーとして動作していて、外部からのコネクションを待ち受けている状態になっている。 一方で、ファイル"turtle.h"の中には、このサーバーと通信するためのプログラム(関数)が記述してある。 あなたが書いたCのプログラムは、TCP/IPのクライアントとして動作することになる。 そして、両者がプロトコルを交換しながら、描画が進むという仕掛けだ。
ウィンドウのタイトルに、ホスト名が表示される。
	 
パブリックモードで亀場を共有
亀場サーバーは他のパソコンからの接続を受け付けることができるように設定できる。 亀場ウィンドウのタイトルのところは、 "Private Turtle Field @ 何々"のように表示されているはずだ。この「何々」にはそのサーバーのアドレス(正確には、アドレスに対応する xxx.ac.jp のような「ホスト名」)が表示される。
そこで、クライアント側(描画を行うソフト)の最初のところの、いつもは"localhost"にしている箇所を
CON("そのホスト名") ;
と変更するだけで、そのアドレスの亀場に対して描画や操作を行うことができる。 ただし、迷惑行為の防止のため、事前に接続先の亀場サーバーを「パブリックモード(誰でも接続可能なモード)」 に変更しておく(してもらう)必要がある。変更は、亀場サーバーのメニューかキーボードで行う(以下の「亀場サーバーの機能」を参照)。
通信ポート
ユーザープログラムが亀を操るためにTCP 2222番ポート、亀場の様子をモニターするためにTCP 2280番ポートが使われる。 セキュリティー対策ソフトやパソコンのファイアウォールから警告が出る場合があるので、そのときは、これらの ポートの使用を「許可」する必要がある。
亀場サーバーの機能
亀場サーバーの動作は、メニューやキーボードから直接操ることができる。 亀場のウィンドウがアクティブ(全面に出ている)状態で、マウスの右クリック、またはキーボードから半角文字をタイプする。
| 機能 | メニュー(右クリック) | キーボード | 等価なC関数 | コメント | 描画内容をクリアする | Clear Field | c | CLR(); | 
|---|---|---|---|---|
| ゾンビを消去する | Clear Zombie | z | CLR(); | |
| 対戦モードとグラフィックスモードを 交互に切り換える | Toggle Graphics/Battle Mode | ! | BMODE(); GMODE(); | 対戦モード中は、背景が色の濃い コルクボード状の絵柄に切り替わる | 
| プライベートモードとパブリックモードを 交互に切り換える | Toggle Private/Public Mode | @ | ウィンドウのタイトル表示が 連動して切り替わる | |
| 亀場のスクリーンショットをファイルに保存する 下の説明を参照のこと | Capture Screen | p | OSによっては、メニューの部分が保存画像 から消えることがある。その場合はpキーを使う | |
| 三次元表示モードに切り換える | 3 | 三次元版の機能 < > で視点回転, + - でズーム | ||
| 迷路モードに切り換える | M (大文字) | 亀や物体は一旦全て消去される | ||
| ヘルプ表示 | About Turtle Field | h | ESCキーで消去 | |
| すべての亀とドーナッツ、障害物を亀場から除く | Kill All Turtles | K (大文字) | ||
| 亀場サーバーを終了する | Exit | Q (大文字) | 
亀場のスクリーンショットを画像ファイルに保存することができる。 亀場のウィンドウを選択しておいて、その上で p キーを押す。 一見何も起こっていないように見えるが、ホームディレクトリに tfield-capture-数字.png という ファイルが出来ているはずだ (win32版の場合は、デスクトップにtfield-capture-数字.bmpというファイルが作成される)。 数字のところは、亀場サーバーを起動してからの経過時間に対応している。 レポート課題などでスクリーンショットの提出を求められた場合はこの機能を使うこと。
基本的な数値
| 内容 | 値 | コメント | 
|---|---|---|
| 亀場の広さ | 512×512ピクセル | 対戦モード(BMODE())中は、亀はこの亀場の範囲 から外には出られない ウィンドウのサイズは変更不可 | 
| 亀の大きさ | 20ピクセル | 亀は半径10ピクセルの円として扱われている | 
| 砲弾の速度 | 2ピクセル/画面更新 | |
| 砲弾の影響範囲 | 周囲10ピクセル | 亀の中心が砲弾の中心の10ピクセル 圏内に入ったときに被弾する かすった程度では亀は死なない | 
| 対戦モード中の最大移動量 | 2ピクセル/コマンド | それを超えた移動量を指定して FD(BK)しても、移動量は2ピクセルとみなされる | 
| 対戦モード中の最大回転角 | 3°/コマンド | それを超えた回転角を指定して LT(RT)しても、回転角は3°とみなされる | 
| 対戦モード中のスコア | 砲弾の発射 -1点 亀に命中 +10点 ドーナツに至近距離で命中 +10点 被弾 -30点 | スコアが0になると動けなくなる 0を下回ると「退場」 | 
| 生成できるドーナッツの数 | 亀あたり最大で10個 | DONUT()関数で1個生成 | 
| 亀場のコインの総数 | 最大で300枚 | |
| 借りられるコインの枚数 | 1回あたり10枚 | BORROWCOIN()を使う 亀の最初の所持金は0(コイン0枚) | 
| 亀場の亀・物体の総数 | 最大で30 | |
| 同時接続可能なクライント数 | 最大で10 | これ以上接続しようとしても、切断される |