Modification for reversi.py

This commit is contained in:
JialianLee 2017-12-23 15:43:45 +08:00
parent d0e150f090
commit 84208a7ac9

View File

@ -25,6 +25,7 @@ def find_correct_moves(own, enemy):
mobility |= search_offset_right(own, enemy, mask, 7) # Left bottom mobility |= search_offset_right(own, enemy, mask, 7) # Left bottom
return mobility return mobility
def calc_flip(pos, own, enemy): def calc_flip(pos, own, enemy):
"""return flip stones of enemy by bitboard when I place stone at pos. """return flip stones of enemy by bitboard when I place stone at pos.
@ -123,8 +124,9 @@ class Reversi:
self.board = None # 8 * 8 board with 1 for black, -1 for white and 0 for blank self.board = None # 8 * 8 board with 1 for black, -1 for white and 0 for blank
self.color = None # 1 for black and -1 for white self.color = None # 1 for black and -1 for white
self.action = None # number in 0~63 self.action = None # number in 0~63
# self.winner = None self.winner = None
self.black_win = None self.black_win = None
self.size = 8
def get_board(self, black=None, white=None): def get_board(self, black=None, white=None):
self.black = black or (0b00001000 << 24 | 0b00010000 << 32) self.black = black or (0b00001000 << 24 | 0b00010000 << 32)
@ -132,18 +134,25 @@ class Reversi:
self.board = self.bitboard2board() self.board = self.bitboard2board()
return self.board return self.board
def is_valid(self, is_next=False):
self.board2bitboard()
own, enemy = self.get_own_and_enemy(is_next)
mobility = find_correct_moves(own, enemy)
valid_moves = bit_to_array(mobility, 64)
valid_moves = np.argwhere(valid_moves)
valid_moves = list(np.reshape(valid_moves, len(valid_moves)))
return valid_moves
def simulate_get_mask(self, state, action_set): def simulate_get_mask(self, state, action_set):
history_boards, color = state history_boards, color = state
board = history_boards[-1] board = history_boards[-1]
self.board = board self.board = board
self.color = color self.color = color
self.board2bitboard() valid_moves = self.is_valid()
own, enemy = self.get_own_and_enemy()
mobility = find_correct_moves(own, enemy)
valid_moves = bit_to_array(mobility, 64)
valid_moves = np.argwhere(valid_moves)
valid_moves = list(np.reshape(valid_moves, len(valid_moves)))
# TODO it seems that the pass move is not considered # TODO it seems that the pass move is not considered
if not len(valid_moves):
invalid_action_mask = action_set[0:-1]
else:
invalid_action_mask = [] invalid_action_mask = []
for action in action_set: for action in action_set:
if action not in valid_moves: if action not in valid_moves:
@ -155,8 +164,14 @@ class Reversi:
self.color = state[1] self.color = state[1]
self.board2bitboard() self.board2bitboard()
self.action = action self.action = action
step_forward = self.step() if self.action == 64:
if step_forward: valid_moves = self.is_valid(is_next=True)
if not len(valid_moves):
self._game_over()
return None, self.winner * self.color
else:
return [self.board, 0 - self.color], 0
self.step()
new_board = self.bitboard2board() new_board = self.bitboard2board()
return [new_board, 0 - self.color], 0 return [new_board, 0 - self.color], 0
@ -164,12 +179,19 @@ class Reversi:
self.board = board self.board = board
self.color = color self.color = color
self.board2bitboard() self.board2bitboard()
self.vertex2action(vertex) self.action = self._flatten(vertex)
step_forward = self.step() if self.action == 64:
if step_forward: valid_moves = self.is_valid(is_next=True)
if not len(valid_moves):
return False
else:
return True
else:
self.step()
new_board = self.bitboard2board() new_board = self.bitboard2board()
for i in range(64): for i in range(64):
board[i] = new_board[i] board[i] = new_board[i]
return True
def executor_get_score(self, board): def executor_get_score(self, board):
self.board = board self.board = board
@ -191,13 +213,14 @@ class Reversi:
elif self.board[i] == -1: elif self.board[i] == -1:
self.white |= count self.white |= count
count *= 2 count *= 2
'''
def vertex2action(self, vertex): def vertex2action(self, vertex):
x, y = vertex x, y = vertex
if x == 0 and y == 0: if x == 0 and y == 0:
self.action = None self.action = None
else: else:
self.action = 8 * (x - 1) + y - 1 self.action = 8 * (x - 1) + y - 1
'''
def bitboard2board(self): def bitboard2board(self):
board = [] board = []
@ -214,46 +237,45 @@ class Reversi:
def step(self): def step(self):
if self.action < 0 or self.action > 63: if self.action < 0 or self.action > 63:
raise ValueError("Wrong action!") raise ValueError("Action not in the range of [0,63]!")
if self.action is None: if self.action is None:
return False raise ValueError("Action is None!")
own, enemy = self.get_own_and_enemy() own, enemy = self.get_own_and_enemy()
flipped = calc_flip(self.action, own, enemy) flipped = calc_flip(self.action, own, enemy)
if bit_count(flipped) == 0: if bit_count(flipped) == 0:
self.illegal_move_to_lose(self.action) # self.illegal_move_to_lose(self.action)
return False raise ValueError("Illegal action!")
own ^= flipped own ^= flipped
own |= 1 << self.action own |= 1 << self.action
enemy ^= flipped enemy ^= flipped
self.set_own_and_enemy(own, enemy) self.set_own_and_enemy(own, enemy)
return True
def _game_over(self): def _game_over(self):
# self.done = True # self.done = True
'''
if self.winner is None: if self.winner is None:
black_num, white_num = self.number_of_black_and_white black_num, white_num = self.number_of_black_and_white
if black_num > white_num: self.black_win = black_num - white_num
if self.black_win > 0:
self.winner = 1 self.winner = 1
elif black_num < white_num: elif self.black_win < 0:
self.winner = -1 self.winner = -1
else: else:
self.winner = 0 self.winner = 0
'''
if self.black_win is None:
black_num, white_num = self.number_of_black_and_white
self.black_win = black_num - white_num
def illegal_move_to_lose(self, action): def illegal_move_to_lose(self, action):
self._game_over() self._game_over()
def get_own_and_enemy(self): def get_own_and_enemy(self, is_next=False):
if self.color == 1: if is_next:
color = 0 - self.color
else:
color = self.color
if color == 1:
own, enemy = self.black, self.white own, enemy = self.black, self.white
elif self.color == -1: elif color == -1:
own, enemy = self.white, self.black own, enemy = self.white, self.black
else: else:
own, enemy = None, None own, enemy = None, None
@ -265,6 +287,17 @@ class Reversi:
else: else:
self.white, self.black = own, enemy self.white, self.black = own, enemy
def _deflatten(self, idx):
x = idx // self.size + 1
y = idx % self.size + 1
return (x, y)
def _flatten(self, vertex):
x, y = vertex
if (x == 0) and (y == 0):
return 64
return (x - 1) * self.size + (y - 1)
@property @property
def number_of_black_and_white(self): def number_of_black_and_white(self):
return bit_count(self.black), bit_count(self.white) return bit_count(self.black), bit_count(self.white)