500万局の詰将棋

やねうらおさんの233万局面の定跡ファイルを最近使わせてもらったのだが、そのとき、彼のブログで5年も前に3手詰めから11手詰めまでの実戦詰将棋局面を500万例ほど生成して、これをテキストファイルを圧縮した形で無償公開されていることに気が付いた。で、 将棋盤に表示できるようなユーティリティーが欲しい旨のコメントをしている読者もいるみたいだし, これも早速自分のサイトのページに応用させてもらおうかと思った次第である。

で、まずは提供されている圧縮ファイルだが、解凍するとmate3.sfen, mate5.sfen, mate7.sfen, mate9.sfen, mate11.sfen の5つのファイルがでてくる。 それぞれテキストファイルであり、中身はsfen 書式で書かれた局面情報が1行1局面で記述されている。

これをweb siteのページにランダム、あるいは手数と行番号を指定して将棋盤のグラフィックスとして表示させたいわけである。

すべてのデータをブラウザに読み込ませるわけにはいかないので、データ自体はサーバー側に持たせ、ブラウザからは手数と行番号を指定してサーバーに問い合わせ、該当するSFEN一行を取得させて将棋盤上の駒として描画させる、という手法で実現させる。 サーバーでのデータ検索を最適化させるためにmysqlデータベースのテーブルにデータを格納して使う。

データテーブルは一つとして、コラムは手数と問題、各手数の問題カウント、および 通し番号として記録するとしてテーブル構成は以下となる。

FieldTypeNullKeydefaultextra
idINTNOPRIMARYnullauto increment
sfenvarchar(120)YESnull
moveintYESMULnull
rowintYESMULnull

このテーブルをまず作っておき、ここにテキストファイルからデータを流し込むわけだ。 で、今度こそPythonを使って見ようとPyCharmを立ち上げ(個人で使う分には無料なんだよね)ブラウザの検索機能で情報を拾いまくりながら、以下のプログラムを作った。

move と counterで検索することになるので、これらのフィールドはインデックスを作成しておく。

20行以上のパイソンを書いたのはおそらく初めてだが、 なるほどユーザーが多いわけだ。

このパイソンスクリプトを走らせてみる。 上のコードでは各行にスラッシュが8個ある、のと、スペースで分解したアレイ素子の因子が4つになる、というのを valid SFENの簡易判定基準とし、それ以外の行はスキップする構造にしてあったのだが、なんとここで10件近くのスキップが発生した。 テキスト行の情報も表示するようになっていたので ファイルをのぞいてみると、sfenが2行くっついた、つまり改行が抜けている個所が何件かあるのが分かった。 プログラムで生成したはずのファイルに何故にこのようなイレギュラリティが発生するのか不思議ではある。 とにかく手作業でこれらの行を分割し、テーブルをいったん削除して再度の挑戦を行った。Pythonのmysql connectorが優秀なのか、パソコンのハードを更新したからなのかはよくわからないが、500万件10分もかからず終わってしまった。

実は500万件なかったのである。mysqlのデータベースが言うには実際には以下の件数の局面が入っていた。ただこれで目くじら立てるのは野暮というものだ。

3手 998,405件
5 手998,827件
7 手999,071件
9 手999,673件
11 手999,998件

サーバーにPHPでAPIポイントをつくり、例えば /api/mate/3/1245というようなHTTPリクエストをサーバーに送れば、3手詰め、1245行目のsfenがjson formatでかえってくるような仕組みを作る。

ブラウザ側のほうはReactとほぼ同じように使えるPREACTをViteとTypeScriptのTool chainを使用しバタバタと書き上げて、出来上がったのがこのページ。 上の数字をもう一度よく見てもらいたいが、 200問くらいの問題集でも一冊全部解くのはなかなか根気がいるのに、いったい誰がこの圧倒的な数の暴力に立ち向かうというのだ?(ちなみに私は高校時代に買った内藤詰将棋200選をまだ全部解いてない)

やねうらおさんのブログにもかいてあるのだが、これは妙手が入った詰将棋とは違って実戦詰将棋的な問題集になる。 ほとんど並べ詰めのようなものもあれば、少し考える必要のあるものもある。 しかしなのだ。 例えば、この局面 ランダムにピックアップしたものだが、

9手詰め 第88,592問目

最初に2二金打ち、同金としてから4二桂成 同玉以下は 尻にと金をすべらせていってからの飛車成りまでの送り詰めで9手と言っても難しい詰めではない。 詰将棋だと言って出されれば級位者でも解ける問題だ。 ただ実戦となるとこの局面で4五の桂馬が5三と3三を封鎖しており、さらに金を捨てて、3一の金をどかせれば尻金で詰む、そして4一と金のとき5二玉と逃げれば6一飛成で早く詰む、と局面の駒配置がよく見えなければ詰めようとも思わないわけで、実際これくらいの局面で3切れのShogi warsでは初段、下手すると2段レベルとの対戦でも手駒の金は温存したいと、初手から4二桂成と角を取ってくる可能性は自分の経験から言ってかなり高い。

だとすると、この類の局面を大量にながめて勘を鍛えておくことは棋力向上の役に立つのかもしれない。

それはさておき、ここまでできたなら将棋エンジンもつけて回答も導きだせるようにしたらどうだと言われそうだが、残念ながらそちらのほうの知見は自分はまったく持っていないのであった。思うにサーバーにエンジンを実装してというかバーチャルマシンを一台、それもパーフォーマンスの高いやつを立ち上げて将棋エンジンを常駐させ、これのAPIをたたいて正解を求めるというようなイメージなんだが、いかにもリソース費用がかかりそうだ。lishogiのサイトなどは実現しているみたいだが、どうしているのだろうか。 そのうちだれかが無料のAPIサービスを提供してくれないかと無想するわけである。

わかったつもりになってはいけない

地下室においてあるPCのWEBServerはIISで動いている。 いや、Windwos7がはいっていたので、気軽な気持ちでIISを導入し、うごかしてみたら、設定が簡単だったのと、PHPのサポートが意外と充実していたので、サーバーとして使うことにしたのだ。すでに2年ほど支障なく動いている。

もっとも、アプリケーションはPHPで動くModXだ。 asp、aspx ベースではない。Visual Studioも(タダだし)起動画面までは見てみたのだが、C#もVBも覚えるつもりがなく、 結局JavaScriptやCSSだけでWEBサイトを構築できるPHPベースのModXでうごかしている。

ひとつだけ問題があるとしたら、IISベースではFriendly URLがサポートされていないこと。 IIS自体はFURLはサポートしているのだが、別途設定しなければならない。これがApache ベースのサーバーではModXに付属してくる.htaccess ファイルで簡単に対応できる。

世の中よくしたもので、IISでこの.htaccess をそのまま使えるツールが存在する。 Helicon Ape というユーティリティなのだが、サーバー3本までは無料バージョンでサポートされている。 これを入れて、ModX側のFriendly URLのシステム設定をOnにするだけで、FURLが有効になる。 するとそれまでは
http://mysite.org/index.php? id=36
などという味気ないURLが
http://mysite.org/this_pabe.html
という”読みやすく覚えやすいFriendlyな”アドレスに書き換わる。

この組み合わせで半年ほど快適に使ってきたのだが、ある日突然うごかなくなってしまった。 なぜか、最初はわからなかった。
で、いろいろ調べた結果わかったのが、IISの設定。このサイト、.net frameworkをつかっていないのだからいらないだろうと、.netのサポートをIISのメニューから前の日に外していた。外した途端に動かなくなったわけで、ホームページ自体はPHPがきちんと動いて表示するが、リンクが全部だめになったのは、要するにApeが作動していなかったので、
http:/mysite.org/this.page.html
を Apeが以下に変換、
http://mysite.org/index.php ?q=”this page.html”
さらにこれをModXが読み込んで
http://mysite.org/index.php ?id=36 に変換
という書き換えができなくなっていたわけ。 つまりApe 自体はIISの.net frameworkの上で動いていたわけだ。

で、あらためてHeliconのページを読んでみれば

Helicon Ape is implemented as managed IIS 7 module and can be installed as .NET module on any ASP.NET-compatible IIS version. It works transparently for both server and client and can even be installed on a shared hosting account without administrative access.

.NET module だと、しっかり書いてある。(おい)

わかったつもりになっていてはいけません。

WRT 54G の退場

過去10年ほど、家庭内のネットワークハブにLinksysの WRT54Gを使ってきた。 Bestbuyのカタログを見ると、いまだに後期モデルの54GLを販売している。 最近の大勢として、802.11Nが安価で販売されているのにもかかわらず、802.11Gで頑張っている、かなりのロングセラーである。

我が家でも、何の不自由も感じないで使ってきたわけだが、 最近とうとうNラウターに買い替えることになった。 なぜか、どうも本体が故障してしまったようなのだ。

故障したといってもまったくインターネットがつかえなくなったわけではなく、設定したはずのポートフォワードが効かなくなった、という不具合現象。
自宅でWebserver をホストしている関係上、Incomingのポート80をLinux baseのNASにフォワードしている。このNAS自体はSquidを稼働していて、ここからリバースプロキシで複数のWEBサーバーにTrafficを振り分けていた。このNASのIPアドレスが192.168.1.99なのだが、先週突然Websiteにつながらなくなった。いろいろ調べてみると、どうも192.168.1.98にフォワードされている。 ルーターのポートフォワードをセーブしなおすと、一時的に復活するが2時間もするとまた駄目になる。

さんざん他のところをチェック(Web server のセッティング、Squidのセッティング、DDNS Clientの確認、Local DNSの設定など)しなおした後でたどりついたのが、「結局これって、ラウターのメモリーか内部ICの出力が不安定になっていないか」 という結論。

LinksysのNラウターを近くのOfficeMaxで購入。 ラウターの設定画面が10年前の製品とほとんど変わっていない事に感銘(?)をうけながら、交換し、初期設定をすませて運用中。 過去3日間問題が発生しないところをみると、やはりルーターの故障だったようだ。

今回購入したのはCiscoのEA2700。 D-linkやNetgear の同等の製品に比べると割高感があるが、Cisco/LinksysのネームバリューとWRT54Gが予想以上に長く使えたことを考慮して購入。 こいつも10年持ってくれるとよいのだが。

End of life for my WRT54G

Last week, I had a strange phenomena. my home web server was not accessible.

I looked at all kinds of setting I had configured with my home network for the last few years. Local DNS, squid/reverse proxy setup, IIS web server set up (I run my website on Windows 7 PC) and ddns setup. Although nothing was supposed to have changed, I looked at them again and made sure everything is what it supposed to be.

I finally turned my eyes on my trusty router. Linksys WRT54G was servicing me well, for almost 10 years (mine is WRT54G V2.2.)

I looked at port forward option. the port 80 is forwarded to 192.168.1.99. This is a linux based NAS that also runs squid in reverse proxy mode, but for some reason, the traffic appears to be reaching 192.168.1.98, another linux based NAS.
I re-saved the setting and voila! for a while, the web site was accessible. Then after one hour or so, connection was again lost.

I did a factory reset and then updated the firmware. These did not improve the situation. I concluded that the router can no longer retain the port forward information. Maybe one bit of memory chip got bad. Hard to tell. I bit a bullet and bought an N-band router. although a little pricey compared to D-link and/or Netgear, I decided to stick with Cisco/Linksys brand.

After initial setup, everything was back to normal. So here they are, it was indeed my router.

Hopefully my new router can serve me another 10 years. That’s why I paid extra for gigabit ports with this router. Looking at this router, the most striking is a small size of a power brick that comes with it, compared to the power brick from 10 years ago. This is where I see the advancement of technology.

JQueryの.load()を使ってみて complete: にはまった、という話

Query ライブラリーの中に.load()というmethodがあり、これを使うと、WEBページの一部に他のページをはめ込む、ということが簡単にできる。 たとえばmain.html というページがあり、 そこに<div id=”sections”></div> というセクションをつくっておき、 この部分にcontent1.htmlというページを差し込むためには
$(‘#sections’).load(‘content1.html’);
というjavascript 一行で済む。

これを使えば、content2.html, content3.html などというページを用意しておいて、Javascriptを使ってインターアクティブに(ページを全部ロードしなおすのではなく)ページの一部だけを差し替えることができるようになるわけだ。

これって、巷にいうAjaxだが、jQuery のAjax サポートは ajaxSetup というobjectががあって、この中で、Ajax関係の諸パラメーターを前もって設定することが可能、 で、とりあえず
$.ajaxSetup({
beforeSend: function() {
$(‘#sections’).css(‘visibility’,’hidden’);
$(‘#aContainer’).css(‘background’, ‘url(images/ajax-loader.gif) no-repeat center’);
},
complete:
$(‘#aContainer’).css(‘background’,’none’);
}
});
とやって、 ページをロードしたときに、前のページの表示を消し、バックグランドにロード中お待ちくださいのイメージをはっておき、ロードし終わったときに、これを取り除く、という 動作を付け加えた。

ところが実際に動かしてみると、ロードが完了して新しいページが表示された後でもイメージが消えない。 ブラウザの開発ツールで見ると、スタイルシート上、バックグランドイメージがそのまま残っている。つまり、complete: の部分が動いていない。

これで2時間ほどハマったわけだが、 結論からかいてしまう。
実は.load()というコマンドにはコールバック機能があり、 これを使って、ロードされた画面の初期化を行うためのjavascriptを指定していた($(‘#sections’).load(‘content1.html’,’doSomething’)) のだが、これがcomplete: に指定された処理を無効化してしまうようである。 jQueryの.load と complete: の部分のマニュアルをじっくり読んでそういう結論に達した。

というわけで、Complete: event ではなく Success:event に動作をぶら下げて解決。.load()ではなく、.get()を使うとすっきりしそうだが、詳しく調べてないのでこれでよしとする。

jQuery.ajaxSetup({
beforeSend: function() {
$(‘#sections’).css(‘visibility’,’hidden’);
$(‘#aContainer’).css(‘background’, ‘url(images/ajax-loader.gif) no-repeat center’);
},
success:
$(‘#aContainer’).css(‘background’,’none’);
}
});

$ajax を使うと、もっときめ細かいAjax操作ができるそうだが、現状ではこれで十分。

一応動いている証拠は ここに
http://shogishack.net/modx/pages/assess-the-situation/exchanging-pieces/

ModX/WayFinderで作ったメニュのa href部分をjqueryで一括加工し、それぞれのアイテムをクリックすると、Jumpではなく、.loadが呼び出されるようになっている。

ModXと jQuery を使ったAjax, なかなか相性がよさそうである。

100円ドメインと無料ホスト

専用ドメインを取った。Godaddy は SuperBowl で流した宣伝が品が無いとか女性蔑視だとか物議をかもしているが、info ドメインに関しては97セントで(一年目は)レジスターしてくれるので文句はありません。はい。
無料サイトも提供してくれるが、広告用のバナーがついてくる。これが結構うるさい。マークアップで消してしまうことも可能だがそれは厳密なことをいうとTOS(契約)に違反する。 そこでWEBを徘徊すること2日目にして000Webhostなるサービスを見つけた。 MySQLは2本まで、SSL はさすがについてこないが、PHP と MySQL を試してみるにはちょうどよさそう、ということでお世話になることにした。

レジスタラはgodaddy, Webホスティングは 000Webhost ということで、しばらく様子を見てみることにする。

レジスタラとホストの業者が違う場合(昔はこれが一般的だったらしい)はホストの設定をしたあと、レジスタラのサイトに行って、ドメインネームサーバーのアドレスをホスト側から供給されるURLに変更する必要がある。 面倒なのはdomain name serverというメニューにたどり着くくらいで作業そのもの自体はあっけないほど簡単に終わる

前後するが、このプロバイダーの無料サイトをアクティベートするときに、TOS をよく読んでね、サイトの使い方に寄っては一方的にシャットダウンすることもあるので変な使い方を考えているのなら最初からやめたほうが良いよ、という警告文が出る。  中身を呼んでみると、へんな使い方とは成人向けのコンテンツ(有料サービスにアップグレードするとその限りではないそうな。)などのことだが、「ファイルの格納だけに使った場合」というのもあった。  まあ、突然サイトをシャットダウンされる可能性がゼロではない、ということで、これは無料サイトの宿命か。 バックアップをしっかり取っておけば、ドメイン自体は Godaddy にあるので、他のプロバイダーでの再構築もできる。 このあたりが、独自ドメインを登録しておくことの長所かな?