120 lines
4.3 KiB
Python
120 lines
4.3 KiB
Python
from douzero.env.utils import *
|
|
import collections
|
|
|
|
# check if move is a continuous sequence
|
|
def is_continuous_seq(move):
|
|
i = 0
|
|
while i < len(move) - 1:
|
|
if move[i+1] - move[i] != 1:
|
|
return False
|
|
i += 1
|
|
return True
|
|
|
|
# return the type of the move
|
|
def get_move_type(move):
|
|
move_size = len(move)
|
|
move_dict = collections.Counter(move)
|
|
|
|
if move_size == 0:
|
|
return {'type': TYPE_0_PASS}
|
|
|
|
if move_size == 1:
|
|
return {'type': TYPE_1_SINGLE, 'rank': move[0]}
|
|
|
|
if move_size == 2:
|
|
if move[0] == move[1]:
|
|
return {'type': TYPE_2_PAIR, 'rank': move[0]}
|
|
# elif move == [20, 30]: # Kings
|
|
# return {'type': TYPE_5_KING_BOMB}
|
|
else:
|
|
return {'type': TYPE_15_WRONG}
|
|
|
|
if move_size == 3:
|
|
if len(move_dict) == 1:
|
|
return {'type': TYPE_3_TRIPLE, 'rank': move[0]}
|
|
else:
|
|
return {'type': TYPE_15_WRONG}
|
|
|
|
if move_size == 4:
|
|
if len(move_dict) == 1:
|
|
return {'type': TYPE_4_BOMB, 'rank': move[0]}
|
|
elif len(move_dict) == 2:
|
|
if move[0] == 20 and move[2] == 30: # Kings
|
|
return {'type': TYPE_5_KING_BOMB}
|
|
# if move[0] == move[1] == move[2] or move[1] == move[2] == move[3]:
|
|
# return {'type': TYPE_6_3_1, 'rank': move[1]}
|
|
else:
|
|
return {'type': TYPE_15_WRONG}
|
|
else:
|
|
return {'type': TYPE_15_WRONG}
|
|
|
|
if is_continuous_seq(move):
|
|
return {'type': TYPE_8_SERIAL_SINGLE, 'rank': move[0], 'len': len(move)}
|
|
|
|
if move_size == 5:
|
|
if len(move_dict) == 1:
|
|
return {'type': TYPE_4_BOMB5, 'rank': move[0]}
|
|
elif len(move_dict) == 2:
|
|
return {'type': TYPE_7_3_2, 'rank': move[2]}
|
|
else:
|
|
return {'type': TYPE_15_WRONG}
|
|
|
|
count_dict = collections.defaultdict(int)
|
|
for c, n in move_dict.items():
|
|
count_dict[n] += 1
|
|
|
|
if move_size == 6:
|
|
if len(move_dict) == 1:
|
|
return {'type': TYPE_4_BOMB6, 'rank': move[0]}
|
|
# if (len(move_dict) == 2 or len(move_dict) == 3) and count_dict.get(4) == 1 and \
|
|
# (count_dict.get(2) == 1 or count_dict.get(1) == 2):
|
|
# return {'type': TYPE_13_4_2, 'rank': move[2]}
|
|
|
|
# if move_size == 8 and (((len(move_dict) == 3 or len(move_dict) == 2) and
|
|
# (count_dict.get(4) == 1 and count_dict.get(2) == 2)) or count_dict.get(4) == 2):
|
|
# return {'type': TYPE_14_4_22, 'rank': max([c for c, n in move_dict.items() if n == 4])}
|
|
|
|
if move_size == 7 and len(move_dict) == 1:
|
|
return {'type': TYPE_4_BOMB7, 'rank': move[0]}
|
|
|
|
if move_size == 8 and len(move_dict) == 1:
|
|
return {'type': TYPE_4_BOMB8, 'rank': move[0]}
|
|
|
|
mdkeys = sorted(move_dict.keys())
|
|
if len(move_dict) == count_dict.get(2) and is_continuous_seq(mdkeys):
|
|
return {'type': TYPE_9_SERIAL_PAIR, 'rank': mdkeys[0], 'len': len(mdkeys)}
|
|
|
|
if len(move_dict) == count_dict.get(3) and is_continuous_seq(mdkeys):
|
|
return {'type': TYPE_10_SERIAL_TRIPLE, 'rank': mdkeys[0], 'len': len(mdkeys)}
|
|
|
|
# Check Type 11 (serial 3+1) and Type 12 (serial 3+2)
|
|
if count_dict.get(3, 0) >= MIN_TRIPLES:
|
|
serial_3 = list()
|
|
single = list()
|
|
pair = list()
|
|
|
|
for k, v in move_dict.items():
|
|
if v == 3:
|
|
serial_3.append(k)
|
|
elif v == 1:
|
|
single.append(k)
|
|
elif v == 2:
|
|
pair.append(k)
|
|
else: # no other possibilities
|
|
return {'type': TYPE_15_WRONG}
|
|
|
|
serial_3.sort()
|
|
if is_continuous_seq(serial_3):
|
|
# if len(serial_3) == len(single)+len(pair)*2:
|
|
# return {'type': TYPE_11_SERIAL_3_1, 'rank': serial_3[0], 'len': len(serial_3)}
|
|
if len(serial_3) == len(pair) and len(move_dict) == len(serial_3) * 2:
|
|
return {'type': TYPE_12_SERIAL_3_2, 'rank': serial_3[0], 'len': len(serial_3)}
|
|
|
|
# if len(serial_3) == 4:
|
|
# if is_continuous_seq(serial_3[1:]):
|
|
# return {'type': TYPE_11_SERIAL_3_1, 'rank': serial_3[1], 'len': len(serial_3) - 1}
|
|
# if is_continuous_seq(serial_3[:-1]):
|
|
# return {'type': TYPE_11_SERIAL_3_1, 'rank': serial_3[0], 'len': len(serial_3) - 1}
|
|
|
|
return {'type': TYPE_15_WRONG}
|