gnugo (3)

『猫を抱いて象と泳ぐ』(文藝春秋)なんて本を読んだ。著者は小川洋子さん。『博士の愛した数式』 や『ミーナの行進』等を書かれたあおの方だ。きっとほんわかした本だろうと思って手に した次第。

チェス指し少年(人形)の物語であった。生まれた時、唇が癒着していたという奇形の為、手術するも おかしな部分が残ってしまう。やがて、小学校へ行くようになると、いじめに遭う。いじめっ子 に合わないように早朝にプール脇を通って登校すると、プールには死体が。。。

それはバスの運転手だったと判明。どうやら、深夜に勝手に泳いでいて、心臓麻痺を起こした らしい。その運転手が勤めていたバス会社に行ってみると、そこには野ざらしのバスが。 近寄ってみると、そこには人が住んでいる気配が。やがて、その住人と知り合い、死んだ 運転手の所業が知れた。住人も運転手もチェスを趣味とする人だった。

そして、いつしかその少年もチェスに目覚めていく。それがどう巡ってチェス人形に 繋がるかは、読んでみれ。

チェス人形をモチーフにした小説だけど、ちゃんとモデルが有ったのね。

トルコ人 (チェス)

チェス対決・第1回 産業革命のあだ花・オートマトン「ターク」

上記を見てて、ふと ライフゲーム なんてのが頭の中に湧いてきた。初期パターンによって、面白い動きをする。 ライフゲームの物体一覧 がなかなか優れているぞ。

fedoraでライフゲーム出来ないかと、探してみたぞ。

[sakae@fedora ~]$ dnf info lucidlife
Last metadata expiration check performed 0:12:00 ago on Mon Nov 23 13:27:21 2015.
Available Packages
Name        : lucidlife
Arch        : i686
Epoch       : 0
Version     : 0.9.2
Release     : 17.fc23
Size        : 727 k
Repo        : fedora
Summary     : A Conway's Life simulator
URL         : http://linux.softpedia.com/get/GAMES-ENTERTAINMENT/Simulation/LucidLife-26633.shtml
License     : GPLv2+
Description : LucidLife is a Conway's Life simulator. The rules are rather
            : simple. The game is started with a large grid of cell locations,
            : and an arbitrary set of living cells. On each turn, each cell
            : thrives or dies based on the number of cells which surround it. A
            : dead (empty) cell with three live cells around it becomes a living
            : cell (a birth); a living cell with two or three neighbors
            : survives; otherwise the cell dies (due to overcrowding) or remains
            : dead (due to loneliness). It is based on the the GtkLife project,
            : but with a more modern user interface and other enhancements.

FreeBSDなら上記のものとgtklifeと、もう一つ有った。

xlife is an X implementation of John Horton Conway's Game of Life.

WWW: http://litwr2.atspace.eu/xlife.php

遊んでみれ。あるいは手なぐさみに、自分でコードを書いてみれ。名前は事前に決めておく。 mylifeなんてのはどうだ。あれ? 保険商品と被ってるか。

red

前回のGNUedの続きを少し。。 って、後に尾を引く納豆みたい。納豆の磯辺揚げ大好き!!

展開したソースツリーの中に、red ってのが出来てた。これは何? 開いてみると

#! /bin/sh
bindir=`echo "$0" | sed -e 's,[^/]*$,,'`
exec "${bindir}"ed --restricted "$@"

こんな代物。何やらedにオプションを渡してる。制限オプション。その前にbindirを作ってる sedの動きが分からん。米印にダラーマークが付いてたら、そりゃ前回覚えた、有り難い gdbで構造体を次々に辿って行く、便利機能に見えるぞ。

悩んでいてもしょうがないので、コードをちょっと改変して、結果を教えて貰おう。

[sakae@fedora ed-1.12]$ /home/sakae/ed-1.12/red
/home/sakae/ed-1.12/

ふむ、起動dirを抽出してくれてる。で、その効能は?

制限付きってオプション名だけど、どんな制限を付加してる。想像するに、わざわざsedなんて 付けてるからには、redをedにすげ替えているんだな。もう一つは、edの中から危ないコマンドの実行禁止かな。 危ないコマンドって、edの機能からすれば、shellスクリプトかな。きっと機能制限付きの bashから使うんだろうけど、更に厳しい制限を付けてる?

ええい、面倒だ。ソース嫁。

static bool restricted_ = false;        /* if set, run in restricted mode */
  :
bool may_access_filename( const char * const name )
  {
  if( restricted_ &&
      ( *name == '!' || !strcmp( name, ".." ) || strchr( name, '/' ) ) )
    {
    set_error_msg( "Shell access restricted" );
    return false;
    }
  return true;
  }

main.cを開いたら、変数定義に遭遇。後は、grep一発で、目的場所を発見。扱えるファイルに 制限を設けてる。びっくりマークを含むのは駄目って、shellスクリプト禁止。dir外の ファイルアクセス禁止か。redスクリプトを、何処かに放り込んで、そのdir内に あるファイルだけ(shellスクリプトは除いて)扱って宜しいとな。

[sakae@fedora ~]$ red -p'red> ' ed-1.12/main.c
?
red> H
Invalid filename
red> q

ネットをgrepしてたら、前回がらみの面白いのを見つけた。

C言語系/「デーモン君のソース探検」読書メモ/15, mktemp(3),mkstemp(3)

unix群の整理

をしようと思った。仮想環境はVMWARE PlayerとVBOXが有るんだけど、BSD陣をVBOX側に いれようと妄想。で、OpenBSDにVBOXで動かない悪夢を思い出した。NetBSDは、どうか? 試したら、boot中にpanicで撃沈。

しょうがないので、FreeBSD10.2だけをVBOXに入れた。残りはvmware側だわな。いえね、 発想を逆にして、VBOX側にlinuxって手も考えたんだけど、インストールにめちゃ時間が かかる悪夢を思い出して、踏み止まったよ。

んな訳で、vmwareの方で、fedora23がやっと動き出した。netbsdもね。で、netbsdでも pkgsrcからやるかと思ったけど、ちとソースの在り処を探すのに迷ってしまったので、 ここに記しておく。

pkgsrc

そうそう、vboxの方には元々FreeBSD10.1が入っていたんで、追加した10.2の方にrsyncを 使って引越し、rsync /home/sakae fb102: とかで、簡単引越しでした。

それにしても、vboxで2つのOSを起動すると2個目のOSの準備が出来るまで、多大な時間が かかる。そして、何より不思議なのが、dhcpでIPaddressを振っているはずなのに、同一IPを 割り当ててしまう事。みなさん、どうやってVBOXを手懐けておられるのでしょうか?

fedora23は今回server版を選んでみた。だってXなんて余り使わないから。開発環境はどうやって入れる? 群で選べば良いみたい。

[sakae@fedora ~]$ dnf group list
   C Development Tools and Libraries
   Development Tools
     :
[sakae@fedora ~]$ sudo dnf group install "Development Tools"
     :

X関係のグループは無いので、xorg-x11で必要最低限のものを取りあえず入れた。ひょっと したら余分な物が有るかも知れない。twmが立ち上がるように適当に入れて行ったから。

[sakae@fedora ~]$ dnf list installed | grep x11
xorg-x11-drv-dummy.i686                0.3.6-24.fc23                   @fedora
xorg-x11-drv-evdev.i686                2.9.99-2.20150807git66c997886.fc23
xorg-x11-drv-fbdev.i686                0.4.3-23.fc23                   @fedora
xorg-x11-drv-libinput.i686             0.14.0-2.fc23                   @fedora
xorg-x11-drv-vesa.i686                 2.3.2-23.fc23                   @fedora
xorg-x11-drv-vmmouse.i686              13.1.0-2.fc23                   @fedora
xorg-x11-drv-vmware.i686               13.0.2-10.20150211git8f0cf7c.fc23
xorg-x11-font-utils.i686               1:7.5-29.fc23                   @fedora
xorg-x11-fonts-ISO8859-1-100dpi.noarch 7.5-15.fc23                     @fedora
xorg-x11-resutils.i686                 7.5-12.fc23                     @fedora
xorg-x11-server-Xorg.i686              1.18.0-2.fc23                   @updates
xorg-x11-server-common.i686            1.18.0-2.fc23                   @updates
xorg-x11-server-utils.i686             7.7-17.fc23                     @updates
xorg-x11-twm.i686                      1:1.0.9-2.fc23                  @fedora
xorg-x11-utils.i686                    7.5-20.fc23                     @fedora
xorg-x11-xauth.i686                    1:1.0.9-4.fc23                  @fedora
xorg-x11-xinit.i686                    1.3.4-10.fc23                   @fedora
xorg-x11-xkb-extras.i686               7.7-16.fc23                     @updates
xorg-x11-xkb-utils.i686                7.7-16.fc23                     @updates

gdb attachするなら

dnf debuginfo-install glibc-2.22-5.fc23.i686
vi /etc/sysconfig/selinux
SELINUX=disabled

しとく事。ちょっと焦ったぞ。そして要らないサービスを止めるか。何が イネーブルになってるかだな。

[sakae@fedora ~]$ sudo systemctl list-unit-files | grep enable
rsyslog.service                             enabled
smartd.service                              enabled
  :

止めるぞ。

[sakae@fedora ~]$ sudo systemctl disable smartd.service
Removed symlink /etc/systemd/system/multi-user.target.wants/smartd.service.

consoleに出て来る案内に従って、ブラウザーから、https://IPadr:9090 にアクセスすると 大変な事に。。これを止めるにはどうすれば良いの??? cockpit.socketか。 これは、ドッカーな人用かな?

gnugo コンピュータの頭の中

前回は、ゲーム全体の流れを見たけど、今回は、コンピュータの頭の中、碁脳がどうなってるか 見てく。ソースはgenmove.c 動きを作るってか。READMEには

endgame.c - bookkeeping at end of game
eval.c - evaluate liberty
exambord.c - update game board
findcolr.c - find connected pieces of the same color
findnext.c - find move to defense against attack and function to evaluate move
findopen.c - find opponent liberty and choose move to attack
findpatn.c - match play patterns for next move
findsavr.c - check own weakness to defense
findwinr.c - find opponent weakness to attack
fioe.c - check if fill in its own eye
genmove.c - main function to generate computer move
initmark.c - initialize marking array
main.c - GNUGO main program
matchpat.c - match play pattern
opening.c - generate game opening moves
openregn.c - check open region
patterns.h - playing patterns

上記は、今回関係しそうな所だけを選び出した。

コンピュータの戦略は、まず相手がどうだか、よく知る事から始める。それにはevalを 呼んで、相手の目の数を配列 l に残す事から始める。

次にfindwinnerを呼んで、相手の目で3以下の目を持つものを探す。見つかれば価値を 設定、成功(true)。同様にfindsaverで、自分の目についても調査。これは脅威になる。

次は、これらを勘案の上、脅威を跳ね除けて有利な手をfindpathで捜す。この時、 定石を利用するとな。

価値が芳しくないなら、ランダムに手を打とう。但し、サイコロを振ったんでは、 アインシュタイン先生の信義に反するので(量子力学が発展して、不確実性原理が 定着したけど、個人的には、神はサイコロを振らないと思ったとか)、有利な手を 勘案した上で、知的に手を決定。

周辺か中央付近を除外した場所、周辺を除外した場所、そしてその位置で、何目 取れるか、胸算用。fioeでコーナーを特別扱い。

そして、決められた試行回数以下なら、移動位置を決定。試行回数に達したら、 コンピュータはpassする。細かい関数が沢山あるけど、今回はfindpath()を見ておくかな。

(gdb) bt
#0  matchpat (m=2, n=13, i=0xbfffefa4, j=0xbfffefa0, val=0xbfffef9c) at matchpat.c:36
#1  0x0804a7e1 in findpatn (i=0xbfffefdc, j=0xbfffefd8, val=0xbfffefd4) at findpatn.c:135
#2  0x0804b06e in genmove (i=0xbffff034, j=0xbffff030) at genmove.c:49
#3  0x0804babb in main (argc=1, argv=0xbffff0f4) at main.c:120

genmoveの中で、一通り敵の有利さと自軍の脅威を評価した後(評価結果は、位置と得点と して得られる)、その位置と値より有利な手をfindpathで捜す事になる。確かに、解説通りに 事が運んでいるよ。

findpathの中では、中央、4隅、4辺のそれぞれで、評価にあたいするかを調べる。 その結果はopn配列に入れられた後、matchpatを呼んで、有利な手が見つかったか報告する。 有利な手が有れば、位置と得点を得た後にtrueで返る。 見つからなかったら、サイコロを振る事になる。(我ながらしつこいと言うか、忘れっぽいので、 何度でも)

matchpatの冒頭付近に

  /* transformation matrice */
      static int trf[8][2][2] = {
          {{1, 0}, {0, 1}},       /* linear transfomation matrix */
          {{1, 0}, {0, -1}},      /* invert */
          {{0, 1}, {-1, 0}},      /* rotate 90 */
          {{0, -1}, {-1, 0}},     /* rotate 90 and invert */
          {{-1, 0}, {0, 1}},      /* flip left */
          {{-1, 0}, {0, -1}},     /* flip left and invert */
          {{0, 1}, {1, 0}},       /* rotate 90 and flip left */
          {{0, -1}, {1, 0}}       /* rotate 90, flip left and invert */
      };

こんなのが有るけど、これって行列演算の結果テーブルかな? 線型写像 に、それらしいのが有る。

で、登録してある全てのパターンで、それぞれのパターンの長さについて、先の座標変換を 行う。

  /* transform pattern real coordinate */
                  nx = n + trf[ll][0][0] * pat[r].patn[k].x
                      + trf[ll][0][1] * pat[r].patn[k].y;
                  my = m + trf[ll][1][0] * pat[r].patn[k].x
                      + trf[ll][1][1] * pat[r].patn[k].y;

調査位置が欄外で無い事を確かめた後、何処に注目するか(patternにあらかじめ定義済み)で場合分けする。

                  switch (pat[r].patn[k].att) {
                  case 0:
                      if (p[my][nx] == EMPTY)     /* open */
                     :
                  case 6:
                      if ((p[my][nx] == mymove)   /* my piece on edge */
                      :
}

attは、pattern.hで次のように宣言されてた。

/* att = 0 - empty,
         1 - your piece,
         2 - my piece,
         3 - my next move
         4 - empty on edge,
         5 - your piece on edge,
         6 - my piece on edge
*/

こうして、対象のパターンにマッチしたら(contがイネーブルになる)、その得点を 登録パターンから抽出。後は、パターン番号8から13の場合、その位置によって、得点を微調整する。 (泥臭いけど、重要なんだろうね)

              if (cont) {         /* match pattern */
                  tval = pat[r].patwt;
                  if ((r >= 8) && (r <= 13)) {    /* patterns for expand region */
                      if (line(ti) > 7)   /* penalty on line 1, 2 */
                          tval--;
                      else if ((line(ti) == 6) || (line(ti) == 7))
                          tval++; /* reward on line 3, 4 */

                      if (line(tj) > 7)   /* penalty on line 1, 2 */
                          tval--;
                      else if ((line(tj) == 6) || (line(tj) == 7))
                          tval++; /* reward on line 3, 4 */
                  }
  #define line(x) (abs(x - 9))

これを見ると、辺に近い所は損するぞ。中央寄りは有利だよって、脳に教え込まれている。 碁が始まって既に3000年は経過してるって話だけど、その知恵が生かされているんですなあ。 碁の本を何冊か読んでみたけど、そんな事が書かれていたな。

なお囲碁の本は著者によって力点が違うので、色々読んでみるといいぞ。今は、 梅沢由香里先生の本を読んでる。

ゲームの終焉

やがて陣取りゲームは終盤を迎え、領土確定の段階に至る。そのものズバリのenggameに 終焉の方法が記されている。

位置の入力の時、stopって宣言すると、その処理がスタートする。自動判定は出来ないので こうなっているのだ。

最初に、死に石を置き、次にアゲハマ(ゲーム中に取った石)を置く。この処理を 終了すると、最終的に領土の大きさを計測してくれる。

今日の読み物

QEMUのなかみ(QEMU internals) part1

QEMUのなかみ(QEMU internals) part2

jump tableとは何か