# LM: Experiment with translating kifu - File extensions .kif and .ki2 # https://creativecommons.org/licenses/by/4.0/ # import argparse # Parse command line arguments parser = argparse.ArgumentParser() numK = ['一', '二', '三', '四', '五', '六', '七', '八', '九'] # Kanji 1 through 9 - Rank from top ltrE = ['i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a'] miscK = ['同', '右', '直', '左', '寄', '引', '行', '上', '+', '成', '成り', '不成り', '打', '投了', ''] miscE = ['takes', '(right)', '(straight)', '(left)', '(side)', '(back)', 'go', 'rise', '+', '+', '+', 'not promoting', 'drop', 'end of game', ''] pieceK = ['歩', '香', '桂', '銀', '角', '飛', '金', '玉'] pieceE = ['P', 'L', 'N', 'S', 'B', 'R', 'G', 'K'] pPieceK = ['と', '成香', '成桂', '成銀', '馬', '龍', '竜'] pPieceE = ['+P', '+L', '+N', '+S', '+B', '+R', '+R'] genK = ['先手', '後手', '開始日時', '手合割:平手', '手数', '指手', '時', '消費時間', '切れ負け', '打', '勝', '投了'] genE = ['Sente', 'Gote', 'Start date and time', 'Handicap: Even game', 'Ply#', 'Play', 'Time', 'Time', 'Loss on time', 'Drop', 'wins', '\tResigns'] bk = '▲' wt = '△' # Test redefine black and white symbols by the characters' unicode values (no difference) bk = chr(9650) # U+25B2 wt = chr(9651) # U+25B3 plyCounter = 0 gameRecordEncoding = 'Shift_JIS' def pos(k): # Returns square in western algebraic notation - file letter + rank number e = '' # Return for i in range(0, len(k)-1): if k[i].isdigit() and k[i+1] in numK: # File from right e += ltrE[int(k[i])-1] # File number to subscript (reversed in ltrE array) e += str(9-(numK.index(k[i+1]))) # Rank from top - Reverse to rank from bottom # Else ignore. This is position-only function return e def piece(k): # Unpromoted or promoted piece single-character abbreviation global plyCounter e = '' # Return for i in range(0, len(k)-1): if k[i:i+2] in pPieceK: e = pPieceE[pPieceK.index(k[i:i+2])] if e == '': for i in range(0, len(k)): if k[i] in pPieceK: e = pPieceE[pPieceK.index(k[i])] elif k[i] in pieceK: e = pieceE[pieceK.index(k[i])] if len(e) > 0: plyCounter += 1 return e # Empty string if fail to resolve def misc(k): e = '' for i in range(0, len(k)): if k[i] in miscK: e += miscE[miscK.index(k[i])] + ' ' return e[0:len(e)-1] def k2e(k): # Translate one-play (wrapper) pName = piece(k) aPos = pos(k) if len(aPos) == 0 and len(pName) == 0: return '' # Not interpretable return pName + pos(k) + ' ' + misc(k) def translate(s): # Translate one line (or row) - parameter s is Kanji or English or mixed string e = k2e(s) if len(e) > 0: return str(plyCounter).rjust(4) + '\t' + e t = '' for i in range(0, len(genK)): if genK[i] in s: s = t = s.replace(genK[i], genE[i]) if len(t) > 0: return t return '' gameRecord = list() def uFilter(s, l, h, c): # Bandpass filter - Cosmetic # Pass characters between unicode values l and h inclusive # Change filtered characters to c (can be empty character or space, etc) t = '' for i in range(0, len(s)): o = ord(s[i]) if o < l or o > h: t += c else: t += s[i] return t def hor2ver(): # ki2 multi-ply rows to single-ply kif-like vertical format global gameRecord verRecord = list() tmp = list() U = '^' L = len(gameRecord) for i in range(0, L): s = gameRecord[i] if bk in s: s = s.replace(bk, U+bk) if wt in s: s = s.replace(wt, U+wt) else: verRecord.append(s) continue tmp = s.split(U) for j in range(0, len(tmp)): verRecord.append(tmp[j]) gameRecord.clear() gameRecord = verRecord def file2List(fileSpec): # Load game record file global gameRecord try: with open(fileSpec, encoding=gameRecordEncoding, errors='ignore', mode="rt") as f0: gameRecord = f0.read().splitlines() except: print("\nFailed to load '" + fileSpec + "' to game record list!") hor2ver() return def processKifFile(file): global gameRecord gameRecord.clear() file2List(file) if len(gameRecord) > 0: lastRow = len(gameRecord)-1 print() for i in range (0, len(gameRecord)): x = translate(gameRecord[i]) if i == lastRow: x = uFilter(x, 0, 127, ' ') # Lower bound 0 to pass the tab character print(x) # Print translated record # print(gameRecord[i], '\t', x) # Alternatively print original and translated record return if __name__ == "__main__": # Parse command line parameters, etc. parser.add_argument('-enc', type=str, required=False) # override default encoding parser.add_argument('-file', type=str, required=False) # kifu file args = parser.parse_args() if args.enc is not None: # Specify different encoding than default Shift_JIS gameRecordEncoding = args.enc # Other command line parameters here if args.file is not None: # -file parameter last processKifFile(args.file) print() # Cosmetic exit(0)