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