Skip to content

Commit

Permalink
KIF.ParserをCSAの仕様に合わせる
Browse files Browse the repository at this point in the history
  • Loading branch information
TadaoYamaoka committed Jan 18, 2023
1 parent efcb5ad commit 2ca4671
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 34 deletions.
84 changes: 53 additions & 31 deletions cshogi/KIF.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import math

import cshogi
from cshogi import Board, BLACK_WIN, WHITE_WIN, DRAW, move_to

KIFU_TO_SQUARE_NAMES = [
'1一', '1二', '1三', '1四', '1五', '1六', '1七', '1八', '1九',
Expand Down Expand Up @@ -70,7 +71,7 @@ class Parser:
'その他': None
}

RESULT_RE = re.compile(r' *まで(\d+)手で((先|下|後|上)手の(勝ち|反則勝ち|反則負け)|千日手|持将棋|中断)')
RESULT_RE = re.compile(r' *まで、?(\d+)手で((先|下|後|上)手の(勝ち|入玉勝ち|反則勝ち|反則負け)|千日手|持将棋|中断)')

@staticmethod
def parse_file(path):
Expand Down Expand Up @@ -98,7 +99,7 @@ def parse_pieces_in_hand(target):
return result

@staticmethod
def parse_move_str(line, last_to_square):
def parse_move_str(line, board):
# Normalize king/promoted kanji
line = line.replace('王', '玉')
line = line.replace('竜', '龍')
Expand All @@ -108,6 +109,7 @@ def parse_move_str(line, last_to_square):

m = Parser.MOVE_RE.match(line)
if m and m.group(1) not in [
'入玉勝ち',
'中断',
'投了',
'持将棋',
Expand All @@ -120,25 +122,23 @@ def parse_move_str(line, last_to_square):
piece_type = cshogi.PIECE_JAPANESE_SYMBOLS.index(m.group(5))
if m.group(2) == '同 ':
# same position
to_square = last_to_square
to_square = move_to(board.peek())
else:
to_field = cshogi.NUMBER_JAPANESE_NUMBER_SYMBOLS.index(m.group(3)) - 1
to_rank = cshogi.NUMBER_JAPANESE_KANJI_SYMBOLS.index(m.group(4)) - 1
to_square = to_rank + to_field * 9
last_to_square = to_square

if m.group(6) == '打':
if m.group(6) == '打' or (m.group(8) == '0' and m.group(9) == '0'):
# piece drop
return ('{0}*{1}'.format(cshogi.PIECE_SYMBOLS[piece_type].upper(),
cshogi.SQUARE_NAMES[to_square]), last_to_square)
return board.drop_move(to_square, piece_type)
else:
from_field = int(m.group(8)) - 1
from_rank = int(m.group(9)) - 1
from_square = from_rank + from_field * 9

promotion = (m.group(7) == '成')
return (cshogi.SQUARE_NAMES[from_square] + cshogi.SQUARE_NAMES[to_square] + ('+' if promotion else ''), last_to_square)
return (None, last_to_square)
return board.move(from_square, to_square, promotion)
return None

@staticmethod
def parse_str(kif_str):
Expand All @@ -147,15 +147,27 @@ def parse_str(kif_str):
starttime = None
names = [None, None]
pieces_in_hand = [{}, {}]
current_turn = cshogi.BLACK
sfen = cshogi.STARTING_SFEN
var_info = {}
header_comments = []
moves = []
last_to_square = None
comments = []
win = None
board = Board()
kif_str = kif_str.replace('\r\n', '\n').replace('\r', '\n')
for line in kif_str.split('\n'):
if len(line) == 0 or line[0] == "*":
if len(line) == 0:
pass
elif line[0] == "*":
if len(moves) > 0:
if len(moves) - len(comments) > 1:
comments.extend([None]*(len(moves) - len(comments) - 1))
if line[:2] == "**":
comments.append(line[2:])
else:
comments.append(line[1:])
else:
header_comments.append(line[1:])
elif ':' in line:
(key, value) = line.split(':', 1)
value = value.rstrip(' ')
Expand Down Expand Up @@ -185,44 +197,54 @@ def parse_str(kif_str):
sfen = Parser.HANDYCAP_SFENS[value]
if sfen is None:
raise ParserException('Cannot support handycap type "other"')
elif line == '後手番':
# Current turn is white
current_turn = cshogi.WHITE
board.set_sfen(sfen)
else:
var_info[key] = value
else:
(move, last_to_square) = Parser.parse_move_str(line, last_to_square)
move = Parser.parse_move_str(line, board)
if move is not None:
moves.append(move)
if board.is_legal(move):
board.push(move)
else:
m = Parser.RESULT_RE.match(line)
if m:
win_side_str = m.group(3)
if win_side_str == '先' or win_side_str == '下':
if m.group(4) == '反則負け':
win = 'w'
win = WHITE_WIN
endgame = '%ILLEGAL_MOVE'
else:
win = 'b'
win = BLACK_WIN
endgame = '%+ILLEGAL_ACTION' if m.group(4) == '反則勝ち' else ('%KACHI' if m.group(4) == '入玉勝ち' else '%TORYO')
elif win_side_str == '後' or win_side_str == '上':
if m.group(4) == '反則負け':
win = 'b'
win = BLACK_WIN
endgame = '%ILLEGAL_MOVE'
else:
win = 'w'
win = WHITE_WIN
endgame = '%-ILLEGAL_ACTION' if m.group(4) == '反則勝ち' else ('%KACHI' if m.group(4) == '入玉勝ち' else '%TORYO')
elif m.group(2) == '中断':
win = None
endgame = '%CHUDAN'
else:
# TODO: repetition of moves with continuous check
win = '-'
win = DRAW
endgame = '%SENNICHITE'
line_no += 1

summary = {
'starttime': starttime,
'names': names,
'sfen': sfen,
'moves': moves,
'win': win
}

# NOTE: for the same interface with CSA parser
return [summary]
parser = Parser()
parser.starttime = starttime
parser.names = names
parser.sfen = sfen
parser.var_info = var_info
parser.comment = '\n'.join(header_comments)
parser.moves = moves
parser.comments = comments
parser.win = win
parser.endgame = endgame

return parser

def sec_to_time(sec):
h, m_ = divmod(math.ceil(sec), 60*60)
Expand Down
7 changes: 6 additions & 1 deletion test/read_kif.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@
args = parser.parse_args()

kif = KIF.Parser.parse_file(args.path)
print(kif)
print(kif.names)
print(kif.comment)
print(kif.moves)
print(kif.comments)
print(kif.win)
print(kif.endgame)
4 changes: 2 additions & 2 deletions test/test_py.pyproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>c3734095-4012-4a90-a409-4b7047378794</ProjectGuid>
<ProjectHome>.</ProjectHome>
<StartupFile>ki2_test.py</StartupFile>
<StartupFile>read_kif.py</StartupFile>
<SearchPath>
</SearchPath>
<WorkingDirectory>.</WorkingDirectory>
<OutputPath>.</OutputPath>
<Name>test_py</Name>
<RootNamespace>test_py</RootNamespace>
<LaunchProvider>Standard Python launcher</LaunchProvider>
<CommandLineArguments>"R:\wdoor+floodgate-300-10F+4t4t4t+SQMZ-pearl_763_ymkbook_2000k+20221008000012.ki2" R:\a.ki2</CommandLineArguments>
<CommandLineArguments>"R:\kif\4416.kif"</CommandLineArguments>
<EnableNativeCodeDebugging>False</EnableNativeCodeDebugging>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
Expand Down

0 comments on commit 2ca4671

Please sign in to comment.