cgfthink.dll の解説
--------------------------------------------------------------------------
                            cgfthink.dll の解説                 2005/07/17
                                                  山下 宏
--------------------------------------------------------------------------

0. はじめに

これはCGF碁盤(cgfgoban.exe)用の思考DLL(cgfthink.dll)の解説です。
cgfthink.dllは cgfthink.c と cgfthink.h から構成されます。
乱数で適当な手を返すサンプルプログラムが付属しています。
サンプルのデータ構造などは強制するものではありません。


1. 座標

左上を(1,1)、右下を(19,19)とする座標を用います。

DLLに渡される座標は1つの16進数で表され、
座標 = (Y座標)*256 + X座標
となります。
(x,y)=(9,12) の場合、12*256 + 9 = 3081 = 0x1209 となります。
(C言語では先頭に0xがつくと16進数を意味します)

「19路盤」
         1      2      3   ...       9     10   ...     18      19  (X座標)

 1  0x0101 0x0102 0x0103   ...  0x0109 0x010a   ...  0x0112 0x0113
 2  0x0201 0x0202 0x0203   ...  0x0209 0x020a   ...  0x0212 0x0213
 3  0x0301 0x0302 0x0303   ...  0x0309 0x030a   ...  0x0312 0x0313
...
15  0x0f01 0x0f02 0x0f03   ...  0x0f09 0x0f0a   ...  0x0f12 0x0f13
16  0x1001 0x1002 0x1003   ...  0x1009 0x100a   ...  0x1012 0x1013
17  0x1101 0x1102 0x1103   ...  0x1109 0x110a   ...  0x1112 0x1113
18  0x1201 0x1202 0x1203   ...  0x1209 0x120a   ...  0x1212 0x1213
19  0x1301 0x1302 0x1303   ...  0x1309 0x130a   ...  0x1312 0x1313

「13路盤」
         1      2      3   ...       9     10     11     12     13

 1  0x0101 0x0102 0x0103   ...  0x0109 0x010a 0x010b 0x010c 0x010d
 2  0x0201 0x0202 0x0203   ...  0x0209 0x020a 0x020b 0x020c 0x020d
 3  0x0301 0x0302 0x0303   ...  0x0309 0x030a 0x030b 0x030c 0x030d
...
11  0x0b01 0x0b02 0x0b03   ...  0x0b09 0x0b0a 0x0b0b 0x0b0c 0x0b0d
12  0x0c01 0x0c02 0x0c03   ...  0x0c09 0x0c0a 0x0c0b 0x0c0c 0x0c0d
13  0x0d01 0x0d02 0x0d03   ...  0x0d09 0x0d0a 0x0d0b 0x0d0c 0x0d0d

「9路盤」
         1      2      3      4      5      6      7      8      9

 1  0x0101 0x0102 0x0103 0x0104 0x0105 0x0106 0x0107 0x0108 0x0109
 2  0x0201 0x0202 0x0203 0x0204 0x0205 0x0206 0x0207 0x0208 0x0209
 3  0x0301 0x0302 0x0303 0x0304 0x0305 0x0306 0x0307 0x0308 0x0309
 4  0x0401 0x0402 0x0403 0x0404 0x0405 0x0406 0x0407 0x0408 0x0409
 5  0x0501 0x0502 0x0503 0x0504 0x0505 0x0506 0x0507 0x0508 0x0509
 6  0x0601 0x0602 0x0603 0x0604 0x0605 0x0606 0x0607 0x0608 0x0609
 7  0x0701 0x0702 0x0703 0x0704 0x0705 0x0706 0x0707 0x0708 0x0709
 8  0x0801 0x0802 0x0803 0x0804 0x0805 0x0806 0x0807 0x0808 0x0809
 9  0x0901 0x0902 0x0903 0x0904 0x0905 0x0906 0x0907 0x0908 0x0909


2. 初期盤面

対局開始前(手数=0)の局面は下の配列で渡されます。

    int init_board[(19+2)*256];

これは現在手数の局面ではありません。
現在の局面はこの盤面と棋譜から作る必要があります。

盤上の位置以外の場所は盤外を示す 3 で埋められています。黒石は1、白石は2です。
置き碁の場合以外は、盤上の位置は全て 0 です。

※ 本文に掲載されているサンプルは board[y][x] のような2次元の配列ですが
   これは1次元の配列です。board[y][x] は init_board[ y*256 + x ] という形に
   なります。


3. 棋譜

現在局面までの棋譜は下の形式で渡されます。

    int kifu[2048][3];

最大2048手まで保持されます。

kifu[][0] ... 石を置いた座標が入ります。0x0101〜0x1313まで。パスは0です。
kifu[][1] ... 石の色が入ります。黒が1、白が2です。
kifu[][2] ... この手を打つのにかかった時間(秒)が入ります。

例えば19路盤で、初手に黒が(16,3)、白が(4,4)に打った場合は
kifu[0][0] = 0x0310
kifu[0][1] = 1

kifu[1][0] = 0x0404
kifu[1][1] = 2
が入っています。


4. 手数

    int tesuu;

現在の手数が渡されます。0から始まります。
10手後の局面ではtesuu=10が入り、11手目を打つことになります。


5. 手番

    int black_turn;

黒番の時には1、白番は0が入ります。


6. 盤面の大きさ

    int board_size;

盤面のサイズが入ります。19路盤では19、9路盤では9が入ります。


7. コミ

    double komi;

実数で渡されます。6目半の時は 6.5、コミなしの時は 0 が入ります。


8. 思考をするか、終局処理をするか

    int endgame_type;

思考するのか、終局処理をするのか示します。以下の4種類があります。

0...通常の思考
1...終局処理
2...図形を表示
3...数値を表示

0の場合は通常の思考です。
1の場合は現在の石の死活情報を endgame_board[] に代入して下さい。
石のある場所はそれが「活」か「死」か、空点では「ダメ」「黒地」「白地」かを
代入します。
思考ルーチンが完成していない間は全ての石は活き、全ての空点はダメ、などとして
返して下さい。

2はGUIの盤面上に丸、三角、四角、?、×、などを表示します。
endgame_board[] に値を設定して下さい。
思考ルーチンがこの石の死活は不明と判定している、などのテスト用にご利用ください。

3はGUIの盤面上に数値を表示します。
endgame_board[] に値を設定して下さい。
これもテスト用です。
設定する値の実際はソースを見てください。


9. 初期化ルーチン

    void cgfgui_thinking_init(int *p)

この関数はGUIから最初に一度だけ呼ばれます。
メモリを取得する場合などはこの部分に記述してください。
int *p には思考を中断するときのポインタが入っています。
思考ルーチンが長考する場合は、このポインタの値を調べて0以外の場合は
思考を中断するようにしてください。長考しない場合は無視してかまいません。
情報表示用のコンソールもここで作成しています。


10. 思考ルーチン

    int cgfgui_thinking( int    init_board[],
                         int    kifu[][3],
                         int    tesuu,
                         int    black_turn,
                         int    board_size,
                         double komi,
                         int    endgame_type,
                         int    endgame_board[] )

GUIから現在までの手数とそれまでの棋譜が入った状態で呼ばれます。
打った場所を返します。

int init_board[];     初期盤面(置き碁の場合は、ここに置石が入る)
int kifu[][3];        棋譜  [][0]...座標、[][1]...石の色、[][2]...消費時間(秒)
int tesuu;            手数
int black_turn;       手番(黒番...1、白番...0)
int board_size;       盤面のサイズ
double komi;          コミ
int endgame_type;     0...通常の思考、1...終局処理、2...図形を表示、3...数値を表示
int endgame_board[];  終局処理の結果を代入する(図形、数値表示の場合も)


11. 終了ルーチン

    void cgfgui_thinking_close(void)

対局終了時に一度だけ呼ばれます。
メモリの解放などが必要な場合にここに記述してください。


12. printf()の代用関数

    void PRT(const char *fmt, ...);

printf()関数の代わりに使えます。
出力先は初期化ルーチンで作成されるコンソールです。


13. 中断フラグをチェックするための関数

    void PassWindowsSystem(void);

思考用のGUI側に送られたメッセージを処理します。
(画面の再描画や中断ボタンが押された判定など)
思考ルーチンが長考する場合に中断処理を入れたい場合は、この関数がある程度の
間隔(1秒に100回程度)で呼ばれるようにして、なおかつ思考中断フラグの状態を
調べて下さい。中断フラグが0以外の場合は中断してください。


14. Visual C++6.0での開発環境の作り方

以下は Visual C++6.0 を使う場合の手順です。
サンプル用の
cgfthink.c
cgfthink.h
の2つのソースだけが
C:\test\cgfthink\
というフォルダに置いてある、とします。

VC++6.0を起動後、「ファイル(F)」「新規作成(N)」を選びます。
「プロジェクト」タブの中の「Win32 Dynamic-Link Library」を選択します。
C:\test\cgfthink\ の下にサンプルソースを置いた場合は「位置(C)」
には C:\test\ を指定します。「プロジェクト名(N)」には cgfthink と入力して
「OK」を押してください。
作成するDLLの種類は「空のDLLプロジェクト(E)」を選び「終了」を押します。

新規プロジェクト情報が出ますので「OK」を押します。

次に、今作ったプロジェクトにサンプルソースを追加します。
メニューの「プロジェクト(P)」から「プロジェクトへ追加(A)」「ファイル(F)」
を選択します。ファイルを選択するダイアログが出ますので cgfthink.c を選んで
「OK」を押します。

基本で作られるDLLはデバッグ用になっていますので
メニューの「ビルド(B)」「アクティブな構成の設定(O)」から
「cgfthink - Win32 Release」を選択して「OK」を押します。

コンパイルしてDLLを作成するには、「ビルド(B)」「ビルド(B) cgfthink.dll」を
選択します。
ここで、cgfgoban.exe を新しく作られた \Release フォルダの下に
コピーしておいて下さい。

碁盤GUIからDLLを実行するには、「ビルド(B)」「実行(X)」を選びます。
「実行可能ファイルを選択してください」と聞かれますので
「>」から「参照」を選び、先ほどコピーした
C:\test\cgfthink\Release\cgfgoban.exe を選択してください。


15. Visual C++ .NET 2003での開発環境の作り方

以下は Visual C++ .NET 2003 を使う場合の手順です。
サンプル用の
cgfthink.c
cgfthink.h
の2つのソースだけが
C:\test\cgfthink\
というフォルダに置いてある、とします。

VC++ .NETを起動後、「ファイル(F)」「新規作成(N)」「プロジェクト(P)」を
選びます。
「新しいプロジェクト」ウィンドウの中で「プロジェクトの種類(P)」は
「Visual C++ プロジェクト」、「テンプレート(T)」は「Win32 プロジェクト」
を選択します。
C:\test\cgfthink\ の下にサンプルソースを置いた場合は「プロジェクト名(N)」
に cgfthink と入力します。「場所(L)」には C:\test\ を指定して「OK」を押してください。

「Win32 アプリケーションウィザード」のウィンドウが開きますので、
「アプリケーション設定」メニューを選択して、アプリケーションの種類として
「DLL(D)」、追加のオプションでは「空のプロジェクト(E)」を選択して「完了」
ボタンを押してください。

次に、今作ったプロジェクトにサンプルソースを追加します。
メニューの「プロジェクト(P)」から「既存項目の追加(G)」を選択します。
ファイルを選択するダイアログが出ますので cgfthink.c を選んで「開く」
を押します。

基本で作られるDLLはデバッグ用になっていますので、リリース用に変更します。
メニューの「ビルド(B)」「構成マネージャ(O)」を選択して構成マネージャウィン
ドウを開きます。「アクティブソリューション構成(A)」で「Release」を選択して
「閉じる」ボタンを押します。

コンパイルしてDLLを作成するには、「ビルド(B)」「ソリューションのビルド(B) 」
を選択します。
ここで、cgfgoban.exe を新しく作られた \Release フォルダの下に
コピーしておいて下さい。
碁盤GUIからDLLを実行するには、「デバッグ(D)」「デバッグなしで開始(G)」を選びます。
「デバッグで使用する実行可能ファイルを指定してください」と聞かれますので
C:\test\cgfthink\Release\cgfgoban.exe を入力してください。
--------------------------------------------------------------------------