[PYTHON] Use BitBoard to seek legal reversi moves

Implement reversi (Isn't the era when you shouldn't call it Othello over ...) with BitBoard? For the idea itself, please refer to articles such as Implementing Othello on Bitboard.

xxxx
xWBx
xBWx
xxxx

(For the sake of simplicity, we will use a 4x4 example, but the implementation is 8x8. W: Shiraishi, B: Kuroishi, x: No stone.) Kuroishi is placed on this board in BitBoard

0000
0010
0100
0000

And the arrangement of Shiroishi

0000
0100
0010
0000

It is represented by two bit strings of.

This time, we will consider how to find all legal moves. The legal hand of the black number is always in one of the eight directions diagonally up, down, left, and right of the black stone with the board surface. First of all, let's start with the search to the left (that is, the hand that holds the white stone from the left side of the black stone on the board).

In the search to the left, one of the black legal moves on this board

0000
1000
0000
0000

Should be required.

First, find the white stone adjacent to the left of the black stone on the board. This is the same as shifting the arrangement of black stones to the left by 1 bit and finding the product with the arrangement of white stones.

0000   0000   0000
0100 & 0100 = 0100
1000   0010   0000
0000   0000   0000

If you shift it further to the left by 1 bit, you can find the legal hand of the black number, but you can not consider the case where Shiraishi continues. Change the board a little.

xWWB
xWBB
xWBW
xBWB
```
 First, shift the arrangement of Kuroishi to the left by 1 bit and take the product with the arrangement of Shiroishi. So far the same.

```
0010   0110   0010
0110 & 0100 = 0100
0100   0101   0100
1010   0010   0010
```
 Find the Shiroishi to the left of Kuroishi, and the Shiroishi to the left of Kuroishi. In other words, this is the same as shifting the placement of the white stone to the left of the black stone to the left by 1 bit and finding the product with the placement of the white stone.

```
0100   0110   0100
1000 & 0100 = 0000
1000   0101   0000
0100   0010   0000
```
 As a result, the arrangement of continuous white stones to the left of Kuroishi

```
0010   0100   0110
0100 | 0000 = 0100
0100   0000   0100
0010   0000   0010
```
 Can be asked. In 4x4, only two white stones are adjacent to the left side of Kuroishi, so no further calculation is necessary, but in 8x8, by repeating a total of 6 times, all consecutive white stones adjacent to the left side of Kuroishi can be obtained.

 The black legitimate hand can be found by shifting it further 1 bit to the left. However, in order to eliminate the case where there is a stone in that position and it is not possible to start, it is multiplied by the position without stone.

```
1100   1000   1000
1000 & 1000 = 1000
1000   1000   1000
0100   1000   0000
```
 I was able to find all the legal moves of the black turn.

 Finally, consider the handling of the leftmost stone, which was previously ignored. The leftmost stone is adjacent to the rightmost stone on the upper level. Consider the following board as an example.

```
WBxW
BWBx
WWBx
WBxx
```
 The white stone on the far left is a white stone that cannot be turned over by searching to the left, so remove it from ʻopponent_board` in advance.
 Also, remove the rightmost white stone from ʻopponent_board` so that it is not judged that the leftmost black stone is adjacent to the rightmost white stone in the upper row.

```
1001   0110   0000
0100 & 0110 = 0100
1100   0110   0100
1000   0110   0000
```

 The following is an implementation of the above in python.


#### **`board.py`**
```python

class Board:
    BLACK, WHITE = True, False

    def __init__(self, black=0x000010080000, white=0x000008100000):
        self.board = {Board.BLACK: black, Board.WHITE: white}

    def legal_moves(self, player):
        self_board = self.board[player]
        opponent_board = self.board[not player]
        blank_board = ~(self_board | opponent_board)
        opponent_board = opponent_board & 0x7e7e7e7e7e7e7e7e

        temp = self_board << 1 & opponent_board
        temp |= temp << 1 & opponent_board
        temp |= temp << 1 & opponent_board
        temp |= temp << 1 & opponent_board
        temp |= temp << 1 & opponent_board
        temp |= temp << 1 & opponent_board

        temp = temp << 1 & blank_board

        return temp
```


Recommended Posts

Use BitBoard to seek legal reversi moves
How to use xml.etree.ElementTree
How to use Python-shell
How to use tf.data
How to use virtualenv
How to use Seaboan
How to use image-match
How to use Pandas 2
How to use Virtualenv
How to use pytest_report_header
How to use Bio.Phylo
How to use SymPy
How to use x-means
How to use WikiExtractor.py
How to use IPython
How to use virtualenv
How to use Matplotlib
How to use iptables
How to use numpy
Reasons to use logarithm
How to use TokyoTechFes2015
How to use venv
How to use dictionary {}
How to use Pyenv
Easy to use SQLite3
How to use python-kabusapi
Python-How to use pyinstaller
How to use return
How to use dotenv
How to use pyenv-virtualenv
How to use Go.mod
How to use imutils
How to use import