コンピュータ将棋の指し手の差分更新

まず　指し手　って何なんだが、駒を動かすことだと思えばいい。

# 将棋のようなゲーム、将棋じゃないようなゲーム

将棋のようなゲームなら、将棋じゃなくても役に立つ記事だろう。

ここでいう将棋じゃないゲームとは、１手指すと　連鎖的に盤面全体に変更が及ぶようなゲームだ。

オセロとか　ぷよぷよ　とか　１手で盤面が変わってしまう。
将棋は　１手動かしても　せいぜい

- 動かした駒
- 取られた駒

の２つぐらいしか変化がない。

# 全・再計算

![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429a1.png?raw=true)

将棋盤がある。とくに　こだわりが無ければ、長方形に作っておくのがよい。
日本列島みたいにナナメに伸びた陸地だと　かなり無駄になるが　しかたない。

![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429a1b1.png?raw=true)

なんかマップに　ユニットが初期配置されたとしよう。
初期配置では差分更新しない。

全部の駒を置き終わったタイミングで　何だか知らないが「全・再計算」を走らせる。

この「全・再計算」の結果は　「初期局面」　として記憶しておいて、いつでも　ここに戻せるようにしておく。

これで、「全・再計算」の出番は終わり。あとは「部分・再計算」（＝差分更新）があるだけ。

# 部分・再計算

![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429b1.png?raw=true)

駒を　なんか動かすのを　Do Move （ドゥー・ムーブ）　と呼ぶ。（コンピューター・チェス由来）

![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429c1.png?raw=true)

あっ、待った！　今の無し、と戻すのを　Undo Move（アンドゥ―・ムーブ）　と呼ぶ。

アンドゥは単に **逆向きに動くこと** なんだから　ドゥーも　アンドゥ―も同じじゃないか、というと　けっこう動きが違う。

「盤外から駒が飛んできて　その駒に下敷きにされた駒は進む」という動きは　ゲームのルールにないし、

「成っている駒が　成る前の駒に戻りながら進む」という動きも　ゲームのルールにない。

逆向き将棋は　けっこう　正向き将棋　とは違う。

Do と Undo、両方　組んで、片方だけできていてもダメで、両方のテストが終わらないと「指し手の差分更新」とかいうやつはできない。

# 昇格

|動き|通称|名前|
|---|---|---|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429d1.png?raw=true)|そのまんま|aa|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429d2.png?raw=true)|昇格|ab|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429d3.png?raw=true)|そのまんま|bb|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429d4.png?raw=true)|降格|ba|

ゲームでは、成る　とか　プロモーション　とか言ったりして、駒が強くなる動きがある。

しかし「差分更新」の世界では「逆向き将棋」も　やらなければならないので
降格（デモーション）もある。

呼び分けるのがめんどくさいので　aa, ab, bb, ba の４つの動かし方があるものとしよう。

# 指し手に記録されているフラグ

なにが煩わしいかというと、棋譜には「成った」しか情報がないことだ。
「そのままだ」「降格だ」とか　書いてない。

「成った」じゃないから　成ってない駒だな、というと **わたしと同じ間違い** で、「成っている駒」は　成ってなくても「成っている駒」だ。

# キャプチャー

また、取られる駒が、有ったり無かったりする。

|有るとき|
|---|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429d5.png?raw=true)|

|無いとき|
|---|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429d6.png?raw=true)|

ここで　おおまかにいって、差分更新では　「**３つの駒のようなもの**」　が登場する。

![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429d7.png?raw=true)

t0（ティー・ゼロ）、t1（ティー・いち）、c（シー）だ。

タイム０、タイム１、キャプチャーの略。

持ち駒を打つような場合もあるが、単に駒台は t0 としておく。

# DoMove

|図|なまえ|
|---|---|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429e1.png?raw=true)||
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429e2.png?raw=true)|Ｃ＋|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429e3.png?raw=true)|Ｔ２Ｃ－|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429e4.png?raw=true)|Ｔ２＋|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429e5.png?raw=true)|Ｔ１－|

上図のように、駒を１個進めるのに、５ステップある。
（順番はこの通りでなくてもよい）

盤の上から　駒を進める例で示したが、べつに　駒台から打つときも　このステップでいける。（盤上の駒を指すのと、駒台から駒を打つのは、if文で分ける）

- 駒台に駒が増えた
- 相手の駒が盤上から消えた
- 移動先に駒が増えた
- 移動元から駒が消えた

といった感じで、**何が増えた**、**何が減った** を　追いかけるのが**「差分更新」** だ。

# UndoMove

|図|なまえ|
|---|---|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429e5.png?raw=true)||
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429e4.png?raw=true)|Ｔ１＋|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429e3.png?raw=true)|Ｔ２－|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429e2.png?raw=true)|Ｔ２Ｃ＋|
|![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-04/20170429e1.png?raw=true)|Ｃ－|

アンドゥ・ムーブは　さっきの画像を　逆さに並べる。

人間は　ひょい　っと駒を　取って、打つだけなので、
こんな図解を　置いておいても　**なにを　わざわざ当たり前なことを　書いているのか、** と捉える向きもあるかもしれない。

それは **目の前に駒があって、駒を掴む指を持っている人間** だから **当たり前** なわけだ。
じゃあ、パソコンの前に駒があって、パソコンに指は付いているのか。駒は無いし、指もない。**当たり前** とは別の状況が　そこにあり、プログラマーがいるわけだ。


# 急ぎなので、話しをすっとばそう。ディスカバード・アタック

攻撃が届く範囲を、**「利き」** という。

動かした駒は　利き　も動くんだが、
駒を動かしたことで　遮られていた　利き　が復活することがある。

![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-05/20170501a1.png?raw=true)

これ、ディスカバード・アタック。（塞ぎものを外してアタック）

そして　要点は

![Gazo](https://github.com/muzudho/HowToMakeGame/blob/master/img/2017-05/20170501a2.png?raw=true)

じゃあ、カバー（塞ぐ）だってあるんじゃないの、ということだ。

どうも　わたしのプログラムは　ディスカバーも、カバーも　忘れているのか　貫通して駒が飛んでいく。

どこに飛び利きがあるのか、記憶して置いて　踏んづけたのか、離れたのか　判定した方がいいのだろうか？


／／つづく