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からやるかと思ったけど、ちとソースの在り処を探すのに迷ってしまったので、 ここに記しておく。
そうそう、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