Changed calculate_legal_states to allow for possible face_value of 0
This commit is contained in:
parent
c08e7fe540
commit
7764a70799
225
board.py
225
board.py
|
@ -55,116 +55,151 @@ class Board:
|
||||||
|
|
||||||
|
|
||||||
# tesauro
|
# tesauro
|
||||||
|
# @staticmethod
|
||||||
|
# def board_features_tesauro(board, cur_player):
|
||||||
|
# def ordinary_trans(val, player):
|
||||||
|
# abs_val = val * player
|
||||||
|
# if abs_val <= 0: return (0,0,0,0)
|
||||||
|
# elif abs_val == 1: return (1,0,0,0)
|
||||||
|
# elif abs_val == 2: return (1,1,0,0)
|
||||||
|
# elif abs_val == 3: return (1,1,1,0)
|
||||||
|
# else: return (1,1,1, (abs_val - 3) / 2)
|
||||||
|
|
||||||
|
# def bar_trans(board, player):
|
||||||
|
# if player == 1: return (abs(board[0]/2),)
|
||||||
|
# elif player == -1: return (abs(board[25]/2),)
|
||||||
|
|
||||||
|
# # def ordinary_trans_board(board, player):
|
||||||
|
# # return np.array(
|
||||||
|
# # [ordinary_trans(x, player) for x in board[1:25]]
|
||||||
|
# # ).flatten()
|
||||||
|
|
||||||
|
# board_rep = []
|
||||||
|
# for player in [1,-1]:
|
||||||
|
# for x in board[1:25]:
|
||||||
|
# board_rep += ordinary_trans(x, player)
|
||||||
|
# board_rep += bar_trans(board, player)
|
||||||
|
# board_rep += (15 - Board.num_of_checkers_for_player(board, player),)
|
||||||
|
|
||||||
|
# board_rep += ([1,0] if cur_player == 1 else [1,0])
|
||||||
|
|
||||||
|
# return np.array(board_rep).reshape(1,198)
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def board_features_tesauro(board, cur_player):
|
def board_features_tesauro(board, cur_player):
|
||||||
def ordinary_trans(val, player):
|
features = []
|
||||||
abs_val = val * player
|
for player in [-1,1]:
|
||||||
if abs_val <= 0: return (0,0,0,0)
|
sum = 0.0
|
||||||
elif abs_val == 1: return (1,0,0,0)
|
for board_range in range(1,25):
|
||||||
elif abs_val == 2: return (1,1,0,0)
|
pin = board[board_range]
|
||||||
elif abs_val == 3: return (1,1,1,0)
|
#print("PIIIN:",pin)
|
||||||
else: return (1,1,1, (abs_val - 3) / 2)
|
feature = [0.0]*4
|
||||||
|
if np.sign(pin) == np.sign(player):
|
||||||
|
sum += abs(pin)
|
||||||
|
for i in range(min(abs(pin), 3)):
|
||||||
|
feature[i] = 1
|
||||||
|
if (abs(pin) > 3):
|
||||||
|
feature[3] = (abs(pin)-3)/2
|
||||||
|
features += feature
|
||||||
|
#print("SUUUM:",sum)
|
||||||
|
# Append the amount of men on the bar of the current player divided by 2
|
||||||
|
features.append((board[0] if np.sign(player) < 0 else board[25]) / 2.0)
|
||||||
|
# Calculate how many pieces there must be in the home state and divide it by 15
|
||||||
|
features.append((15 - sum) / 15)
|
||||||
|
features += ([1,0] if np.sign(cur_player) > 0 else [0,1])
|
||||||
|
test = np.array(features).reshape(1,-1)
|
||||||
|
#print("TEST:",test)
|
||||||
|
return test
|
||||||
|
|
||||||
def bar_trans(board, player):
|
|
||||||
if player == 1: return (abs(board[0]/2),)
|
|
||||||
elif player == -1: return (abs(board[25]/2),)
|
|
||||||
|
|
||||||
# def ordinary_trans_board(board, player):
|
|
||||||
# return np.array(
|
|
||||||
# [ordinary_trans(x, player) for x in board[1:25]]
|
|
||||||
# ).flatten()
|
|
||||||
|
|
||||||
board_rep = []
|
|
||||||
for player in [1,-1]:
|
|
||||||
for x in board[1:25]:
|
|
||||||
board_rep += ordinary_trans(x, player)
|
|
||||||
board_rep += bar_trans(board, player)
|
|
||||||
board_rep += (15 - Board.num_of_checkers_for_player(board, player),)
|
|
||||||
|
|
||||||
board_rep += ([1,0] if cur_player == 1 else [0,1])
|
|
||||||
|
|
||||||
return np.array(board_rep).reshape(1,198)
|
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_move_valid(board, player, face_value, move):
|
def is_move_valid(board, player, face_value, move):
|
||||||
def sign(a):
|
if face_value == 0:
|
||||||
return (a > 0) - (a < 0)
|
return True
|
||||||
|
else:
|
||||||
|
def sign(a):
|
||||||
|
return (a > 0) - (a < 0)
|
||||||
|
|
||||||
from_idx = move[0]
|
from_idx = move[0]
|
||||||
to_idx = move[1]
|
to_idx = move[1]
|
||||||
to_state = None
|
to_state = None
|
||||||
from_state = board[from_idx]
|
from_state = board[from_idx]
|
||||||
delta = to_idx - from_idx
|
delta = to_idx - from_idx
|
||||||
direction = sign(delta)
|
direction = sign(delta)
|
||||||
bearing_off = None
|
bearing_off = None
|
||||||
|
|
||||||
# FIXME: Use get instead of array-like indexing
|
# FIXME: Use get instead of array-like indexing
|
||||||
if to_idx >= 1 and to_idx <= 24:
|
if to_idx >= 1 and to_idx <= 24:
|
||||||
to_state = board[to_idx]
|
to_state = board[to_idx]
|
||||||
bearing_off = False
|
bearing_off = False
|
||||||
else: # Bearing off
|
else: # Bearing off
|
||||||
to_state = 0
|
to_state = 0
|
||||||
bearing_off = True
|
bearing_off = True
|
||||||
|
|
||||||
# print("_"*20)
|
# print("_"*20)
|
||||||
# print("board:", board)
|
# print("board:", board)
|
||||||
# print("to_idx:", to_idx, "board[to_idx]:", board[to_idx], "to_state:", to_state)
|
# print("to_idx:", to_idx, "board[to_idx]:", board[to_idx], "to_state:", to_state)
|
||||||
# print("+"*20)
|
# print("+"*20)
|
||||||
|
|
||||||
def is_forward_move():
|
def is_forward_move():
|
||||||
return direction == player
|
return direction == player
|
||||||
|
|
||||||
def face_value_match_move_length():
|
def face_value_match_move_length():
|
||||||
return abs(delta) == face_value
|
return abs(delta) == face_value
|
||||||
|
|
||||||
def bear_in_if_checker_on_bar():
|
def bear_in_if_checker_on_bar():
|
||||||
if player == 1:
|
|
||||||
bar = 0
|
|
||||||
else:
|
|
||||||
bar = 25
|
|
||||||
|
|
||||||
bar_state = board[bar]
|
|
||||||
|
|
||||||
if bar_state != 0:
|
|
||||||
return from_idx == bar
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def checkers_at_from_idx():
|
|
||||||
return sign(from_state) == player
|
|
||||||
|
|
||||||
def no_block_at_to_idx():
|
|
||||||
if -sign(to_state) == player:
|
|
||||||
return abs(to_state) == 1
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def can_bear_off():
|
|
||||||
checker_idxs = Board.idxs_with_checkers_of_player(board, player)
|
|
||||||
def is_moving_backmost_checker():
|
|
||||||
if player == 1:
|
if player == 1:
|
||||||
return all([(idx >= from_idx) for idx in checker_idxs])
|
bar = 0
|
||||||
else:
|
else:
|
||||||
return all([(idx <= from_idx) for idx in checker_idxs])
|
bar = 25
|
||||||
|
|
||||||
def all_checkers_in_last_quadrant():
|
bar_state = board[bar]
|
||||||
if player == 1:
|
|
||||||
return all([(idx >= 19) for idx in checker_idxs])
|
if bar_state != 0:
|
||||||
|
return from_idx == bar
|
||||||
else:
|
else:
|
||||||
return all([(idx <= 6) for idx in checker_idxs])
|
return True
|
||||||
|
|
||||||
return all([ is_moving_backmost_checker(),
|
def checkers_at_from_idx():
|
||||||
all_checkers_in_last_quadrant() ])
|
return sign(from_state) == player
|
||||||
|
|
||||||
|
def no_block_at_to_idx():
|
||||||
|
if -sign(to_state) == player:
|
||||||
|
return abs(to_state) == 1
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def can_bear_off():
|
||||||
|
checker_idxs = Board.idxs_with_checkers_of_player(board, player)
|
||||||
|
def is_moving_backmost_checker():
|
||||||
|
if player == 1:
|
||||||
|
return all([(idx >= from_idx) for idx in checker_idxs])
|
||||||
|
else:
|
||||||
|
return all([(idx <= from_idx) for idx in checker_idxs])
|
||||||
|
|
||||||
|
def all_checkers_in_last_quadrant():
|
||||||
|
if player == 1:
|
||||||
|
return all([(idx >= 19) for idx in checker_idxs])
|
||||||
|
else:
|
||||||
|
return all([(idx <= 6) for idx in checker_idxs])
|
||||||
|
|
||||||
|
return all([ is_moving_backmost_checker(),
|
||||||
|
all_checkers_in_last_quadrant() ])
|
||||||
|
|
||||||
# TODO: add switch here instead of wonky ternary in all
|
# TODO: add switch here instead of wonky ternary in all
|
||||||
|
# print("is_forward:",is_forward_move())
|
||||||
return all([ is_forward_move(),
|
# print("face_value:",face_value_match_move_length())
|
||||||
face_value_match_move_length(),
|
# print("Checkes_at_from:",checkers_at_from_idx())
|
||||||
bear_in_if_checker_on_bar(),
|
# print("no_block:",no_block_at_to_idx())
|
||||||
checkers_at_from_idx(),
|
|
||||||
no_block_at_to_idx(),
|
return all([ is_forward_move(),
|
||||||
can_bear_off() if bearing_off else True ])
|
face_value_match_move_length(),
|
||||||
|
bear_in_if_checker_on_bar(),
|
||||||
|
checkers_at_from_idx(),
|
||||||
|
no_block_at_to_idx(),
|
||||||
|
can_bear_off() if bearing_off else True ])
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def any_move_valid(board, player, roll):
|
def any_move_valid(board, player, roll):
|
||||||
|
@ -232,11 +267,11 @@ class Board:
|
||||||
(idx, idx + (face_value * player)))
|
(idx, idx + (face_value * player)))
|
||||||
else None)
|
else None)
|
||||||
for idx in idxs_with_checkers]
|
for idx in idxs_with_checkers]
|
||||||
|
# print("pls:",boards)
|
||||||
board_list = list(filter(None, boards)) # Remove None-values
|
board_list = list(filter(None, boards)) # Remove None-values
|
||||||
# if len(board_list) == 0:
|
# if len(board_list) == 0:
|
||||||
# return [board]
|
# return [board]
|
||||||
|
# print("board list:", board_list)
|
||||||
return board_list
|
return board_list
|
||||||
|
|
||||||
# Problem with cal_moves: Method can return empty list (should always contain at least same board).
|
# Problem with cal_moves: Method can return empty list (should always contain at least same board).
|
||||||
|
@ -247,12 +282,11 @@ class Board:
|
||||||
# 2. Iterate through remaining dice
|
# 2. Iterate through remaining dice
|
||||||
|
|
||||||
legal_moves = set()
|
legal_moves = set()
|
||||||
|
|
||||||
if not Board.any_move_valid(board, player, roll):
|
if not Board.any_move_valid(board, player, roll):
|
||||||
return { board }
|
return { board }
|
||||||
|
|
||||||
dice_permutations = list(itertools.permutations(roll)) if roll[0] != roll[1] else [[roll[0]]*4]
|
dice_permutations = list(itertools.permutations(roll)) if roll[0] != roll[1] else [[roll[0]]*4]
|
||||||
|
print("Dice permuts:",dice_permutations)
|
||||||
for roll in dice_permutations:
|
for roll in dice_permutations:
|
||||||
# Calculate boards resulting from first move
|
# Calculate boards resulting from first move
|
||||||
#print("initial board: ", board)
|
#print("initial board: ", board)
|
||||||
|
@ -265,7 +299,6 @@ class Board:
|
||||||
nested_boards = [calc_moves(board, die) for board in boards]
|
nested_boards = [calc_moves(board, die) for board in boards]
|
||||||
#print("nested boards: ", nested_boards)
|
#print("nested boards: ", nested_boards)
|
||||||
boards = [board for boards in nested_boards for board in boards]
|
boards = [board for boards in nested_boards for board in boards]
|
||||||
|
|
||||||
# What the fuck
|
# What the fuck
|
||||||
#for board in boards:
|
#for board in boards:
|
||||||
# print(board)
|
# print(board)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user