|
|
import numpy as np |
|
|
import torch |
|
|
|
|
|
move = np.arange(1, 8) |
|
|
|
|
|
diag = np.array([ |
|
|
move + move*8, |
|
|
move - move*8, |
|
|
move*-1 - move*8, |
|
|
move*-1 + move*8 |
|
|
]) |
|
|
|
|
|
orthog = np.array([ |
|
|
move, |
|
|
move*-8, |
|
|
move*-1, |
|
|
move*8 |
|
|
]) |
|
|
|
|
|
knight = np.array([ |
|
|
[2 + 1*8], |
|
|
[2 - 1*8], |
|
|
[1 - 2*8], |
|
|
[-1 - 2*8], |
|
|
[-2 - 1*8], |
|
|
[-2 + 1*8], |
|
|
[-1 + 2*8], |
|
|
[1 + 2*8] |
|
|
]) |
|
|
|
|
|
promos = np.array([2*8, 3*8, 4*8]) |
|
|
pawn_promotion = np.array([ |
|
|
-1 + promos, |
|
|
0 + promos, |
|
|
1 + promos |
|
|
]) |
|
|
|
|
|
def make_map(): |
|
|
"""theoretically possible put-down squares (numpy array) for each pick-up square (list element). |
|
|
squares are [0, 1, ..., 63] for [a1, b1, ..., h8]. squares after 63 are for promotion squares. |
|
|
each successive "row" beyond 63 (ie. 64:72, 72:80, 80:88) are for over-promotions to queen, rook, and bishop; |
|
|
respectively. a pawn traverse to row 56:64 signifies a "default" promotion to a knight.""" |
|
|
traversable = [] |
|
|
for i in range(8): |
|
|
for j in range(8): |
|
|
sq = (8*i + j) |
|
|
traversable.append( |
|
|
sq + |
|
|
np.sort( |
|
|
np.int32( |
|
|
np.concatenate(( |
|
|
orthog[0][:7-j], orthog[2][:j], orthog[1][:i], orthog[3][:7-i], |
|
|
diag[0][:np.min((7-i, 7-j))], diag[3][:np.min((7-i, j))], |
|
|
diag[1][:np.min((i, 7-j))], diag[2][:np.min((i, j))], |
|
|
knight[0] if i < 7 and j < 6 else [], knight[1] if i > 0 and j < 6 else [], |
|
|
knight[2] if i > 1 and j < 7 else [], knight[3] if i > 1 and j > 0 else [], |
|
|
knight[4] if i > 0 and j > 1 else [], knight[5] if i < 7 and j > 1 else [], |
|
|
knight[6] if i < 6 and j > 0 else [], knight[7] if i < 6 and j < 7 else [], |
|
|
pawn_promotion[0] if i == 6 and j > 0 else [], |
|
|
pawn_promotion[1] if i == 6 else [], |
|
|
pawn_promotion[2] if i == 6 and j < 7 else [], |
|
|
)) |
|
|
) |
|
|
) |
|
|
) |
|
|
z = np.zeros((64*64+8*24, 1858), dtype=np.int32) |
|
|
apm_out = np.zeros((1858,), dtype=np.int32) |
|
|
apm_in = np.zeros((64*64+8*24), dtype=np.int32) |
|
|
|
|
|
i = 0 |
|
|
for pickup_index, putdown_indices in enumerate(traversable): |
|
|
for putdown_index in putdown_indices: |
|
|
if putdown_index < 64: |
|
|
du_idx = putdown_index + (64*pickup_index) |
|
|
z[du_idx, i] = 1 |
|
|
apm_out[i] = du_idx |
|
|
apm_in[du_idx] = i |
|
|
i += 1 |
|
|
|
|
|
j = 0 |
|
|
j1 = np.array([3, -2, 3, -2, 3]) |
|
|
j2 = np.array([3, 3, -5, 3, 3, -5, 3, 3, 1]) |
|
|
ls = np.append(j1, 1) |
|
|
for k in range(6): |
|
|
ls = np.append(ls, j2) |
|
|
ls = np.append(ls, j1) |
|
|
ls = np.append(ls, 0) |
|
|
for pickup_index, putdown_indices in enumerate(traversable): |
|
|
for putdown_index in putdown_indices: |
|
|
if putdown_index >= 64: |
|
|
pickup_file = pickup_index % 8 |
|
|
promotion_file = putdown_index % 8 |
|
|
promotion_rank = (putdown_index // 8) - 8 |
|
|
du_idx = 4096 + pickup_file*24 + (promotion_file*3+promotion_rank) |
|
|
z[du_idx, i] = 1 |
|
|
apm_out[i] = du_idx |
|
|
apm_in[du_idx] = i |
|
|
i += ls[j] |
|
|
j += 1 |
|
|
|
|
|
return z, apm_out, apm_in |
|
|
|
|
|
apm_map, apm_out, apm_in = make_map() |
|
|
|
|
|
def set_zero_sum(x): |
|
|
x = x + (1 - torch.sum(x, dim=1, keepdim=True)) * (1.0 / 64) |
|
|
return x |
|
|
|
|
|
def get_up_down(moves): |
|
|
apm_map_tensor = torch.from_numpy(apm_map) |
|
|
out = torch.matmul(moves, apm_map_tensor.T.float()) |
|
|
out = out[..., :64*64] |
|
|
out = out.view(-1, 64, 64) |
|
|
pu = set_zero_sum(torch.sum(out, dim=-1)) |
|
|
pd = set_zero_sum(torch.sum(out, dim=-2)) |
|
|
return pu, pd |
|
|
|