全国高校生プログラミングコンテスト

CHaserOnline

ステップアップヒント２

今回のヒントは、「プログラムを動かしてみる」から、「プログラムをレベルアップさせる」ための知識や内容についての解説です。
少しでも自分流にプログラムを変えるだけで、他と差をつけることができるぞ！

9 プログラムの流れ（コマンド実行までの流れ）□
ヒント１では、主にクライアントプログラムの動かし方を解説しました。そのプログラムと通信をしている競技サーバのやりとりは以下のようになっています。
サーバへの接続、コマンドの送信、サーバからのリターンメッセージの受信、サーバからの切断。以上がサーバとの細かいやりとりの流れになります。
Ａ：準備コマンド（GetReadyMove）をサーバへ送信して周囲情報を取得するやりとり。
Ｂ：動作コマンドを選んで送信して周囲情報を取得するやりとり。
Ｃ：終了コマンドを送るターン終了のやりとり。
以上３つのやりとりが一つのセットとなり、このセットを繰り返します。
クライアントプログラムは図 1 のフローチャートのようになります。

さて、今回のヒント２では、プログラムがサーバから得た周囲情報をもとに、「どのようなコマンドを実行しようか。
」と考える（判断する）部分を作成することになります。

1

if(ActionReturnNumber[5]==2){GetReadyMode=7;
ターン開始}
else{
GetReadyMode=5;

周囲情報をもとにGetReadyMove を決定}
switch(GetReadyMode){
中略

GetReadyMove を送信し}サーバから戻り値を取得}while(strchr(ReturnCode, ',')==NULL);Y

GetReadyMove は受付られたか？

if(returnNumber[5]==2){Nmode = 7;}
else{
mode = 5;

周囲情報をもとにアク}ションを決定switch(mode){中略}

アクションを送信しサーバから戻り値を取得

アクションは受付
けられたか？

Y

send_cmd("CommandCheck", param,ReturnCode);N}while(strchr(ReturnCode, ',')==NULL&&strcmp(ReturnCode,"user=")!=0);

ターン終了コマンド送信
send_cmd("EndCommandCheck","command3

ターン終了は受付けられたか？

Y=%23", ReturnCode);}while(strcmp(ReturnCode, "command1=")!=0N&&strcmp(ReturnCode,"user=")!=0);

ターン終了【図 1】プログラムの大まかな流れ2

10 コマンド一覧（2021.6.5）□
では、具体的にクライアント（プレイヤ）はどのようなコマンドを実行できるのか。一覧を以下に示します。表内の C や H はプレイヤを示しています。
周囲情報を得るコマンドの返り値は、整数型の配列 returnNumber[10]に入ります。
また、各コマンドを実行するたび、コマンド毎に設定された疲労（減点）があります。
効率よく得点を稼ぐには、プログラムによく考えさせる必要があります。
※一連のコマンド発行後に「user=」メッセージを受け取った場合はゲーム終了となりますので、クライアントプログラムを終了してください。
Ａ 準備コマンド GetReadyMove（サーバに接続し、プレイヤの周囲情報を得る）
コマンド名
機能
サーバに接続し、自分のターンであればプレイヤの周囲情報を得gr
る。
gru
gr・・・移動せずに、周囲情報を得る
grd
gru・・・上に１マス移動して、周囲情報を得る。
grl
grd・・・下に１マス移動して、周囲情報を得る。
grr
grl・・・左に１マス移動して、周囲情報を得る。
grr・・・右に１マス移動して、周囲情報を得る。
0

1

3

Ｃ

6

7

2

5

8

マス目にある数字は returnNumber[]の添え字と一致する。
また、数字の並びは移動先の周囲 9 マスの左上が 0 となる。

3

Ｂ

動作コマンド walk 系（指定した方向へ 1 マス移動する）

コマンド名
wu
wdwlwr

機能指定した方向へ 1 マス移動する。
wu・・・上wd・・・下wl・・・左wr・・・右※各種のアイテム等を探しに歩くので、アイテムを獲ない限り疲労がたまっていきます。
wr の例
0361Ｃ7258マス目にある数字は returnNumber[]の添え字と一致する。
また、数字の並びは wu, wd, wl の場合も移動先の周囲 9 マスの左上が 0 となる。
wl の例
0361Ｃ74258

Ｂ 動作コマンド Put＆Search 系（指定した方向へアイテムを置き、右方向のマスに移動し、真っすぐ 9 マスの情報を得る）
コマンド名
機能
指定した方向、真っすぐ 9 マスの情報を得る。
pu3su
pd3sd
pu3su・・・上
pl3sl
pd3sd・・・下
pr3sr
pl3sl・・・左
pr3sr・・・右※アイテムを置いた分、疲労していきます。
pr3sr の動作例
Ｃ↓アイテムを置いたら↓指定方向右マスに移動↓真っすぐ９マスの情報を得る

Ｃ ０ １ ２ ３ ４ ５ ６７

８マス目にある数字は returnNumber[]の添え字と一致する。
また、数字の並びはどの方向でも左上のマスが 0 となる。

5

Ｂ 動作コマンド Put＆Look 系（指定した方向へアイテムを置き、右方向のマスに移動し周囲情報を得る）
コマンド名
機能
指定した方向へアイテムを置く。
pu3lu
pd3ld
pu3lu・・・上
pl3ll
pd3ld・・・下
pr3lr
pl3ll・・・左
pr3lr・・・右※アイテムを置いた分、疲労していきます。
pr3lr の例
03

12Ｃ

6

78

↓指定方向右マスに移動↓周囲９マスの情報を得る

Ｃ

０１２３

４

５

６

７

８

マス目にある数字は returnNumber[]の添え字と一致する。

6

Ｂ 動作コマンド put&walk 系（指定した方向へ土を置き、逆向きに１マス移動する）
コマンド名
機能
指定した方向へ土を置き、逆向きに１マス移動する。
pu2wd
pd2wupu2wd・・・上に土を置き、下へ移動
pl2wr
pd2wu・・・下に土を置き、上へ移動
pr2wl
pl2wr・・・左に土を置き、右へ移動
pru2wld
pr2wl・・・右に土を置き、左へ移動
plu2wrdpru2wld・・・右上に土を置き、左下へ移動
prd2wlu
plu2wrd・・・左上に土を置き、右下へ移動
pld2wru
prd2wlu・・・右下に土を置き、左上へ移動
pld2wru・・・左下に土を置き、右上へ移動※土を置きなおかつ一歩下がるので、ｐｕｔよりも疲労します。
しかし、土を相手に命中させたときには、かなりの得点を奪うことができます。
pld2wru の例
03

6

※

1Ｃ
7

2

5

8は土

マス目にある数字は returnNumber[]の添え字と一致する。

7Ｂ 動作コマンド kei 系（桂馬に似た動き）
コマンド名機能指定した方向へ桂馬に似た動きをする。
（縦２マス・横１マス）
keiru
keird
keiru・・・右上へ桂馬のような動きをする
keilu
keird・・・右下へ桂馬のような動きをする
keild
keilu・・・左上へ桂馬のような動きをする
keild・・・左下へ桂馬のような動きをする
keird の例

0361Ｃ
72

5

8

マス目にある数字は returnNumber[]の添え字と一致する。

8

Ｂ 動作コマンド put 系（砕く動作）
コマンド名
機能
指定した方向の土を砕きます。
pr0
pl0
pr0・・・右にある土を砕きます。
pu0
pl0・・・左にある土を砕きます。
pd0
pu0・・・上にある土を砕きます。
pd0・・・下にある土を砕きます。
※ 砕く動作ですので、疲労がたまりやすいですが先に進めるようになります。
pu0 の例

01

32C6758

マス目にある数字は returnNumber[]の添え字と一致する。

9Ｂ 動作コマンド系（砕く動作）
コマンド名機能
指定した方向の土を砕きつつ、その逆方向に移動します。
pu0wd
pd0wu
pu0wd・・・上の土を砕いて下に移動します。
pl0wr
pd0wu・・・下の土を砕いて上に移動します。
pr0wl
pl0wr・・・左の土を砕いて右に移動します。
pru0wld
pr0wl・・・右の土を砕いて左に移動します。
plu0wrdpru0wld・・右上の土を砕いて左下に移動する。
prd0wlu
plu0wrd・・左上の土を砕いて右下に移動する。
pld0wru
prd0wlu・・右下の土を砕いて左上に移動する。
pld0wru・・左下の土を砕いて右上に移動する。
※ 砕く動作ですので、疲労がたまりやすいです。
pu0wd の例

023465C8マス目にある数字は returnNumber[]の添え字と一致する。

10Ｂ 動作コマンド dig 系（1 歩歩いて指定した方向の周囲９マスの情報を得る）
コマンド名 機能
指定した方向の周囲９マスの情報を得る。
dudd
du・・・一歩上に移動して、上を探査します。
dl
dd・・・一歩下に移動して、下を探査します。
drdl・・・一歩左に移動して、左を探査します。
dru
dr・・・一歩右に移動して、右を探査します。
drd
dru・・一歩右上に移動して、右上を探査します。
dlu
drd・・一歩右下に移動して、右下を探査します。
dlddlu・・一歩左上に移動して、左上を探査します。
dld・・一歩左上に移動して、左下を探査します。
※一歩歩いて見えない位置を広く見るので、だいぶ疲労します。
dr の例

Ｃ012345678012345678dru の例

ＣＣ
マス目にある数字は returnNumber[]の添え字と一致する。

11

Ｃ 終了コマンド（自分のターンを終了させる）
コマンド名機能#自分のターンを終了させる※周囲情報なし

参考動画

Puppy750 053 全国審判長 ppt03
https://www.youtube.com/watch?v=6CGbNTj8hkc
Puppy750 053 全国審判長 ppt03 long part1
https://www.youtube.com/watch?v=s7kO0BfCojw
Puppy750 053 全国審判長 ppt03 long part2
https://www.youtube.com/watch?v=5Ss6at2wuco

12

11 コマンドの動作・MAP の機能について□
各種コマンド等について、使い方のヒントや注意点について説明します。
①

GetReadyMove コマンドについて
このコマンドは準備段階から移動することができるコマンドです。前ターンの戻り値を利用して移動できるので倍速で移動できます。
参考動画（cool が倍速で動きます）

Puppy750 042 TestVs サンプル 14 Room2037 1
https://www.youtube.com/watch?v=i0odNIusFhs&t=86s② Put3&Look および Put3&Serch コマンドについて
このコマンドはアイテムをおとりにして、離れた場所を探査できます。
参考動画

Puppy750 025 サンプル 3 Room1702 1
https://www.youtube.com/watch?v=jHH4eDgVKKo13

③

ワープについてこのワープは、コマンドではなく MAP に配置されているものです。
ステップアップヒント 1 にもありますが、このワープマスへ移動すると上下左右１０マス分または５マス分移動することができます。つまり、walk や put&walkの１０ターン分を１ターンで移動することができます。
ある程度探索を終えた時など、違うエリアに移動したいときに使うと良いでしょう。ただし、移動先に他クライアントがいる可能性も考えられますので注意が必要です。
参考動画ワープの戻り値は？002 1
https://www.youtube.com/watch?v=6VjHRaUH--014

④ put&walk 系コマンドについて
これらのコマンドは、１ターンで put と walk の２つの動作を実行できる効率のよいコマンドです。上下左右の動きに加えて斜め方向にも動くことができるため、walk のみでの移動よりも早く動くことができます。
しかし、必ずアイテムを Put してから逆方向に移動するので、アイテムをつぶしてしまう危険性や、アイテムを相手に取られてしまう可能性もあります。
参考動画

Puppy750_058 手動による Put2andWalk
https://www.youtube.com/watch?v=QYkSRelCxyM⑤ kei 系コマンドについて
このコマンドは walk の３ターン分を１ターンで移動することができます。うまく活用すれば少ないターン数で広範囲の移動や探査が可能になります。
低ポイントのマスに囲まれてしまい身動きがとれないときにも効果を発揮できます。しかし、移動先は GetReadyMove で見えない場所なので注意が必要です。
参考動画

Puppy750 037 サンプル 13 Room1702 1
https://www.youtube.com/watch?v=hlh8EmASQ0Q

15

⑥ ブラックスターについて
ブラックスターもコマンドではなくアイテム類となっています。
ブラックスターもワープのような移動をするマスですが、ワープとは違い移動先の距離が固定されています。どのようにこのマスが配置されているかがわかれば、マップの形状を知る大きな手掛かりになるでしょう。
参考動画

Puppy750_059 手動によるブラックスター
https://www.youtube.com/watch?v=hsHrMjBbGOA

16

12 サンプルプログラムの解説□
ホームページには様々なサンプルプログラムがアップされています。ダウンロードして稼働練習を行ったり、改造して自分だけのプログラムに近づけていったり、上手に利用してください。

17

フィールドから落ちないようにするには…？
①場外についてフィールド外に近づいた場合の例
フィールド内右上にいる場合
PutDown3＆search down の範囲がはみ出してしまった場合
0Ｃ

2

3

1

01223450

1

Ｃ0

フィールド右端にいる場合

Ｃ

45Ｃ
場外に出てしまった場合
マス目にある数字は returnNumber[]の添え字と一致する

18

参考動画

Puppy750 056 手動クライアント 3 フィールド端、サーチ
https://www.youtube.com/watch?v=lJCD2_oakJ0
Puppy750 056 手動クライアント 2 フィールド端の戻り値、GRMove、桂馬、サーチ
https://www.youtube.com/watch?v=KzMmNssWe3M
Puppy750 056 手動クライアント 1 接続、桂馬
https://www.youtube.com/watch?v=Sb6wF6m6UmI★プログラムを動作させる方法（ヒント１を参照）と内容の解説※このクライアントはターン終了までフィールドを右回りに進みます。アイテム類を判定しないので、得点は増えません。足りない部分は各自で改良していくことが大事です。
① プログラムの保存
サンプルプログラム２をダウンロードするか、自身のプログラムを打ち直します。
サンプルプログラムの名は「CHaserOnlineClient2021public002.c」です。
② サンプルプログラムの動作解説
・まず WalkUp を使って移動します。
・ホワイトシールドまでたどり着いたら右へ移動します。
（WalkRight）
・以降は角まで行き右回りに移動します。
・mode(モード)、GetReadyMode、count、ActionCount、CountBuff という変数を作り、動作の種類を記憶させています。
③ 自分だけの対戦(１台のパソコンで二つのクライアントを起動する場合)
・端末（terminal やコマンドプロンプト）を２つ起動する。
・二つの画面でそれぞれ対戦するときのコマンドを入力すると対戦が始まる。
（片方は自分の ID で起動し、もう片方は cool や hot 等の練習用 ID で起動する。
）

19

④ サンプルプログラム（変数宣言部分）
int main(int argc, char *argv[]){inti;
intRetsu, Gyou;
int
RoomNumber = -1;
char command[20];char param[BUF_LEN];
char buff[10];char ProxyAddress[256];
int ProxyPort;
char UserName[20];char PassWord[20];char ReturnCode[BUF_LEN];
int returnNumber[10];int ActionReturnNumber[10];int HoseiReturnNumber[19][19];char *pivo;
int count;
int mode=1;
int GetReadyMode=5;
int ActionCount = 9;
int wait_flag = 1;
int wait_time = 0;
int BreakLimitMax = 0;
int BreakLimit = 0;
int OutSide=1;
int ViewMode=0;
int MyNumber=-1;
strcpy(ProxyAddress, "");//初期化
ActionReturnNumber[0]=-10000;

各種動作を行うための変数です。
⑤ プログラム解説（変数宣言部分）１
int main(int argc, char *argv[]){
・・・・
int ActionCount = 9;
戻り値の個数の初期値を９にします。
20

⑥ プログラム解説（変数宣言部分）２
int main(int argc, char *argv[]){
・・
int mode=1;
int GetReadyMode=5;
GetReadyMove、アクションの初期動作を右移動に設定する。
⑦
サンプルプログラム（GetReady を発行する）
do{//printf("¥n¥n¥ndeb191 GetReady¥n");//デバッグ用この行を削除するとセグメントエラーになる

strcpy(param, "command1=");//↓↓↓↓↓↓ GetReadyMove の作戦を記入 ↓↓↓↓↓↓↓GetReadyMode = 4;//↑↑↑↑↑↑ GetReadyMove の作戦を記入 ↑↑↑↑↑↑↑switch(GetReadyMode){case 4:
strcat(param, "gr");
break;
case 1:
strcat(param, "gru");break;
case 3:
strcat(param, "grl");break;
case 5:strcat(param, "grr");
break;
case 7:
strcat(param, "grd");break;
default:}

strcat(param, "gr");・・・21

⑧ プログラム解説（GetReady を発行する）
GetReadyMode = 4;
GetReadyMode の動作を「移動せずに周囲情報を確認する」に設定します⑨ プログラム解説２（GetReady を発行する）
switch(GetReadyMode){case 0:strcat(param, "gr");
break;
case 1:
strcat(param, "gru");break;
case 3:
strcat(param, "grl");break;
case 5:strcat(param, "grr");
break;
case 7:strcat(param, "grd");break;
default:strcat(param, "gr");}
GetReadyMode を GetReadyMove に変換します。

22

⑩ サンプルプログラム（Action を発行する）/*----------------------Action を発行する-------------------------*/
do{strcpy(param, "command2=");//↓↓↓↓↓↓ Action の作戦を記入 ↓↓↓↓↓↓↓switch(mode){case 1: //ホワイトシールドにぶつかるまで上に移動する
if(returnNumber[1] == 12){//上がホワイトだったら
mode = 5;//右に移動する}
else{
mode = 1;}
break;
case 5: //ホワイトシールドにぶつかるまで右に移動
if(returnNumber[5] == 12){//右がホワイトだったら
mode = 7;//下に移動する}
else{
mode = 5;}
break;
case 7: //ホワイトシールドにぶつかるまで下に移動
if(returnNumber[7] == 12){//下がホワイトだったら
mode = 3;//左に移動する}
else{
mode = 7;}
break;
case 3: //ホワイトシールドにぶつかるまで左に移動
if(returnNumber[3] == 12){//左がホワイトだったら
mode = 1;//上に移動する}
else{
mode = 3;}
break;

23

default:break;}//↑↑↑↑↑↑ Action の作戦を記入 ↑↑↑↑↑↑↑switch(mode){case 1:strcat(param, "wu");break;
case 3:strcat(param, "wl");
break;
case 5:strcat(param, "wr");
break;
case 7:
strcat(param, "wd");
break;
・・・
default:
strcat(param, "wr");}
send_cmd("CommandCheck", param, ReturnCode);
if(strchr(ReturnCode, ',')!=NULL){//Action が受け付けられたら}
else{
return -1;//異常終了}}while(strchr(ReturnCode, ',')==NULL&&strcmp(ReturnCode, "user=")!=0);//Action が受け付けられるまでループ
ActionCount = returnCode2int(ReturnCode, ActionReturnNumber);

各種動作をここで書きます。
前のターンの進行方向にホワイトシールドがないかを判断して、進む方向をそのままにするか、右回りに方向転換させます。
（上→右→下→左）24

⑪ プログラム説明３（Action を発行する）
switch(mode){case 1:strcat(param, "wu");break;
case 3:strcat(param, "wl");
break;
case 5:strcat(param, "wr");
break;
case 7:
strcat(param, "wd");
break;
・・・
default:strcat(param, "wr");}
mode をアクションコマンドに変換します。
⑫ プログラム説明４（Action を発行する）
ActionCount = returnCode2int(ReturnCode, ActionReturnNumber);
アクションの戻り値を取り出し個数を代入する

25

参考動画

Puppy750_063 サンプルプログラム 2 の動作_ルーム 2416
https://www.youtube.com/watch?v=TH10t_QqX_Q26