せっかく書いたので・・・
このプログラムがどう動くのか、少し考えてみました。
https://othelloq.com/programming/bit-board
原理はきいて知ってたけど、どう動くか追ってみたことはなかった。
reverseで8方向の石を返す。
for k in range(8): は1方向の石を返すのを8方向やるループ。
transferはマスクパターン。
初期配置からF5に石を置いたらどう動くんだろうな?
初期配置
self.playerBoard = 0x0000000810000000 黒のビットマップ
00000000
00000000
00000000
00001000 ←E4に黒石がある
00010000 ←D5に黒石がある
00000000
00000000
00000000
self.opponentBoard = 0x0000001008000000 白のビットマップ
00000000
00000000
00000000
00010000 ←D4に白石がある
00001000 ←E5に白石がある
00000000
00000000
00000000
F5は 0x0000000004000000
00000000
00000000
00000000
00000000
00000100 ←F5の位置だけ1
00000000
00000000
00000000
上方向の白石をチェック:F3をチェック
mask = 0x0000000040000000 & 0xffffffffffffff00 = 0x0000000040000000
mask & self.opponentBoard = 0x0000000040000000 & 0x0000001008000000 = 0 F3に白石がないから何も動かない
途中省略
左方向の白石をチェック:E5をチェック
mask = 0x0000000008000000 & 0xfefefefefefefefe = 0x0000000008000000
mask & self.opponentBoard = 0x0000000008000000 & 0x0000001008000000 = 0x000000008000000 E5に白石がある
rev_ |= mask → rev_ = 0x000000008000000 E5のbitのみ1
それをwhileでmaskが0になるまで繰り返す・・・今回は1回でループを抜けて、rev_ = 0x000000008000000 ←E5
mask = transfer(mask,k)
第1パラメータにE5を渡すので、今度はその1つ左のD5の黒石をチェックする。
if (mask & self.playerBoard) != 0:
mask = 0x000000040000000 & 0xfefefefefefefefe = 0x000000040000000 0x000000008000000 D5に黒石がある
つまり、黒がF5に打って、E5に白石があって、D5に黒石があるので
rev |= rev_ → rev = 0x000000008000000 E5の石が返る
石を返す
self.playerBoard ^= put | rev
0x0000000004000000 | 0x000000008000000 = 0x00000000C000000 ←E5とF5
黒はF5とE5の石が増える
self.opponentBoard ^= rev
0x000000008000000 ←E5
白はE5の石が減る
左方向の石を返すときに使うマスク 0xfefefefefefefefe の意味
0xfefefefefefefefe
11111110
11111110
11111110
11111110
11111110
11111110
11111110
11111110
左方向をチェックするとき、右端の石を返すことはない。左側に「ハミ出す」と右端の0に当たって止まる(えー・・・)。A1が白だったらH8にハミ出すのか・・・。
まとめ:要するに、どの石が返るかを表すbitmapを一生懸命作って、最後にXORで一気に石を返す仕組み。
◆気付いた点
1.一列で考えると、打った位置から左側の石を返すときに、相手の左端の石を見る必要ないから、相手の石のチェックは11111110ではなくて01111110にすると少し早くなると思う。自分の石を見る用には、11111110ではなくて11111100で良いのか。そんな感じでマスクの数が2倍になるけど。
2.返らないと分かってる方向の探索は省略できる。例えば、A1のときは右、右下、下方向だけ探索すれば済む。これを考慮すれば少し速くなるはず。
3.transferの中に条件分岐を入れるのは遅くなる要素なので、8種類のbitmapが入った配列入れておいて参照すれば早くなりそうに思う。
もっとも、棋譜を再生するくらいならそこまで速度を気にする必要はなくて、オセロAIを作る場合に必要になる話。