def save(handle, model, position=None, flip=False): """ Saves the game from GameModel to .pgn """ processed_tags = [] def write_tag(tag, value, roster=False): nonlocal processed_tags if tag in processed_tags or (not roster and not value): return try: pval = str(value) pval = pval.replace("\\", "\\\\") pval = pval.replace("\"", "\\\"") print('[%s "%s"]' % (tag, pval), file=handle) except UnicodeEncodeError: pval = bytes(pval, "utf-8").decode(PGN_ENCODING, errors="ignore") print('[%s "%s"]' % (tag, pval), file=handle) processed_tags = processed_tags + [tag] # Mandatory ordered seven-tag roster status = reprResult[model.status] for tag in mandatory_tags: value = model.tags[tag] if tag == "Date": y, m, d = parseDateTag(value) y = "%04d" % y if y is not None else "????" m = "%02d" % m if m is not None else "??" d = "%02d" % d if d is not None else "??" value = "%s.%s.%s" % (y, m, d) elif value == "": value = "?" write_tag(tag, value, roster=True) write_tag("Result", reprResult[model.status], roster=True) # Variant if model.variant.variant != NORMALCHESS: write_tag("Variant", model.variant.cecp_name.capitalize()) # Initial position if model.boards[0].asFen() != FEN_START: write_tag("SetUp", "1") write_tag("FEN", model.boards[0].asFen()) # Number of moves write_tag("PlyCount", model.ply - model.lowply) # Final position if model.reason in ABORTED_REASONS: value = "abandoned" elif model.reason == WON_ADJUDICATION and model.isEngine2EngineGame(): value = "rules infraction" elif model.reason in ADJUDICATION_REASONS: value = "adjudication" elif model.reason in DEATH_REASONS: value = "death" elif model.reason in CALLFLAG_REASONS: value = "time forfeit" elif model.reason in ADJOURNED_REASONS or status == "*": value = "unterminated" else: value = "normal" write_tag("Termination", value) # ELO and its variation if conf.get("saveRatingChange"): welo = model.tags["WhiteElo"] belo = model.tags["BlackElo"] if welo != "" and belo != "": write_tag("WhiteRatingDiff", get_elo_rating_change_pgn(model, WHITE)) # Unofficial write_tag("BlackRatingDiff", get_elo_rating_change_pgn(model, BLACK)) # Unofficial # Time if model.timed: write_tag( 'WhiteClock', msToClockTimeTag(int(model.timemodel.getPlayerTime(WHITE) * 1000))) write_tag( 'BlackClock', msToClockTimeTag(int(model.timemodel.getPlayerTime(BLACK) * 1000))) # Write all the unprocessed tags for tag in model.tags: # Debug: print(">> %s = %s" % (tag, str(model.tags[tag]))) write_tag(tag, model.tags[tag]) # Discovery of the moves and comments save_emt = conf.get("saveEmt") save_eval = conf.get("saveEval") result = [] walk(model.boards[0].board, result, model, save_emt, save_eval) # Alignment of the fetched elements indented = conf.get("indentPgn") if indented: buffer = "" depth = 0 crlf = False for text in result: # De/Indentation crlf = (buffer[-1:] if len(buffer) > 0 else "") in ["\r", "\n"] if text == "(": depth += 1 if indented and not crlf: buffer += os.linesep crlf = True # Space between each term last = buffer[-1:] if len(buffer) > 0 else "" crlf = last in ["\r", "\n"] if not crlf and last != " " and last != "\t" and last != "(" and not text.startswith( "\r") and not text.startswith( "\n") and text != ")" and len(buffer) > 0: buffer += " " # New line for a new main move if len(buffer) == 0 or (indented and depth == 0 and last != "\r" and last != "\n" and re.match( r"^[0-9]+\.", text) is not None): buffer += os.linesep crlf = True # Alignment if crlf and depth > 0: for j in range(0, depth): buffer += " " # Term buffer += text if indented and text == ")": buffer += os.linesep crlf = True depth -= 1 else: # Add new line to separate tag section and movetext print('', file=handle) buffer = textwrap.fill(" ".join(result), width=80) # Final status = reprResult[model.status] print(buffer, status, file=handle) # Add new line to separate next game print('', file=handle) output = handle.getvalue() if isinstance(handle, StringIO) else "" handle.close() return output
def save(handle, model, position=None): """ Saves the game from GameModel to .pgn """ # Header status = "%s" % reprResult[model.status] print('[Event "%s"]' % model.getTagExport("Event", ""), file=handle) print('[Site "%s"]' % model.getTagExport("Site", ""), file=handle) print('[Date "%04d.%02d.%02d"]' % (int( model.tags["Year"]), int(model.tags["Month"]), int(model.tags["Day"])), file=handle) print('[Round "%s"]' % model.getTagExport("Round", "?"), file=handle) print('[White "%s"]' % repr(model.players[WHITE]), file=handle) print('[Black "%s"]' % repr(model.players[BLACK]), file=handle) print('[Result "%s"]' % status, file=handle) tag = model.getTagExport("ECO", "") if tag != "": print('[ECO "%s"]' % tag, file=handle) tag = model.getTagExport("Opening", "") if tag != "": print('[Opening "%s"]' % tag, file=handle) # Unofficial tag = model.getTagExport("Variation", "") if tag != "": print('[Variation "%s"]' % tag, file=handle) # Unofficial welo = model.getTagExport("WhiteElo", "") if welo != "": print('[WhiteElo "%s"]' % welo, file=handle) belo = model.getTagExport("BlackElo", "") if belo != "": print('[BlackElo "%s"]' % belo, file=handle) if welo != "" and belo != "" and conf.get("saveRatingChange", False): diff = str(get_elo_rating_change_pgn(model, WHITE)) if diff != "": print('[WhiteRatingDiff "%s"]' % diff, file=handle) # Unofficial diff = str(get_elo_rating_change_pgn(model, BLACK)) if diff != "": print('[BlackRatingDiff "%s"]' % diff, file=handle) # Unofficial tag = model.getTagExport("TimeControl", "") if tag != "": print('[TimeControl "%s"]' % tag, file=handle) if model.timed: print( '[WhiteClock "%s"]' % msToClockTimeTag(int(model.timemodel.getPlayerTime(WHITE) * 1000)), file=handle) print( '[BlackClock "%s"]' % msToClockTimeTag(int(model.timemodel.getPlayerTime(BLACK) * 1000)), file=handle) if model.variant.variant != NORMALCHESS: print('[Variant "%s"]' % model.variant.cecp_name.capitalize(), file=handle) if model.boards[0].asFen() != FEN_START: print('[SetUp "1"]', file=handle) print('[FEN "%s"]' % model.boards[0].asFen(), file=handle) print('[PlyCount "%s"]' % (model.ply - model.lowply), file=handle) tag = model.getTagExport("Annotator", "") if tag != "": print('[Annotator "%s"]' % tag, file=handle) if model.reason == WON_CALLFLAG: termination = "time forfeit" elif model.reason == WON_ADJUDICATION and model.isEngine2EngineGame(): termination = "rules infraction" elif model.reason in (DRAW_ADJUDICATION, WON_ADJUDICATION): termination = "adjudication" elif model.reason == WHITE_ENGINE_DIED: termination = "white engine died" elif model.reason == BLACK_ENGINE_DIED: termination = "black engine died" elif model.reason in ABORTED_REASONS: termination = "abandoned" elif model.reason in ADJOURNED_REASONS: termination = "unterminated" else: termination = "normal" print('[Termination "%s"]' % termination, file=handle) save_emt = conf.get("saveEmt", False) save_eval = conf.get("saveEval", False) # Discovery of the moves and comments result = [] walk(model.boards[0].board, result, model, save_emt, save_eval) # Alignment of the fetched elements indented = conf.get("indentPgn", False) buffer = "" depth = 0 crlf = False for text in result: # De/Indentation crlf = (buffer[-1:] if len(buffer) > 0 else "") in ["\r", "\n"] if text == "(": depth += 1 if indented and not crlf: buffer += os.linesep crlf = True # Space between each term last = buffer[-1:] if len(buffer) > 0 else "" crlf = last in ["\r", "\n"] if not crlf and last != " " and last != "\t" and last != "(" and not text.startswith( "\r") and not text.startswith( "\n") and text != ")" and len(buffer) > 0: buffer += " " # New line for a new main move if len(buffer) == 0 or (indented and depth == 0 and last != "\r" and last != "\n" and re.match("^[0-9]+\.", text) is not None): buffer += os.linesep crlf = True # Alignment if crlf and depth > 0: for j in range(0, depth): buffer += " " # Term buffer += text if indented and text == ")": buffer += os.linesep crlf = True depth -= 1 # Status of the game buffer += ("" if crlf else (os.linesep if indented else " ")) + status if not indented: buffer = wrap(buffer, 80) # Final print(buffer, "", file=handle) output = handle.getvalue() if isinstance(handle, StringIO) else "" handle.close() return output
def save(handle, model, position=None): """ Saves the game from GameModel to .pgn """ status = "%s" % reprResult[model.status] print('[Event "%s"]' % model.getTagExport("Event", ""), file=handle) print('[Site "%s"]' % model.getTagExport("Site", ""), file=handle) print('[Date "%04d.%02d.%02d"]' % (int(model.tags["Year"]), int(model.tags["Month"]), int(model.tags["Day"])), file=handle) print('[Round "%s"]' % model.getTagExport("Round", "?"), file=handle) print('[White "%s"]' % repr(model.players[WHITE]), file=handle) print('[Black "%s"]' % repr(model.players[BLACK]), file=handle) print('[Result "%s"]' % status, file=handle) tag = model.getTagExport("ECO", "") if tag != "": print('[ECO "%s"]' % tag, file=handle) tag = model.getTagExport("Opening", "") if tag != "": print('[Opening "%s"]' % tag, file=handle) # Unofficial tag = model.getTagExport("Variation", "") if tag != "": print('[Variation "%s"]' % tag, file=handle) # Unofficial welo = model.getTagExport("WhiteElo", "") if welo != "": print('[WhiteElo "%s"]' % welo, file=handle) belo = model.getTagExport("BlackElo", "") if belo != "": print('[BlackElo "%s"]' % belo, file=handle) if welo != "" and belo != "" and conf.get("saveRatingChange", False): diff = str(get_elo_rating_change_pgn(model, WHITE)) if diff != "": print('[WhiteRatingDiff "%s"]' % diff, file=handle) # Unofficial diff = str(get_elo_rating_change_pgn(model, BLACK)) if diff != "": print('[BlackRatingDiff "%s"]' % diff, file=handle) # Unofficial tag = model.getTagExport("TimeControl", "") if tag != "": print('[TimeControl "%s"]' % tag, file=handle) if model.timed: print('[WhiteClock "%s"]' % msToClockTimeTag(int(model.timemodel.getPlayerTime(WHITE) * 1000)), file=handle) print('[BlackClock "%s"]' % msToClockTimeTag(int(model.timemodel.getPlayerTime(BLACK) * 1000)), file=handle) if model.variant.variant != NORMALCHESS: print('[Variant "%s"]' % model.variant.cecp_name.capitalize(), file=handle) if model.boards[0].asFen() != FEN_START: print('[SetUp "1"]', file=handle) print('[FEN "%s"]' % model.boards[0].asFen(), file=handle) print('[PlyCount "%s"]' % (model.ply - model.lowply), file=handle) tag = model.getTagExport("Annotator", "") if tag != "": print('[Annotator "%s"]' % tag, file=handle) if model.reason == WON_CALLFLAG: termination = "time forfeit" elif model.reason == WON_ADJUDICATION and model.isEngine2EngineGame(): termination = "rules infraction" elif model.reason in (DRAW_ADJUDICATION, WON_ADJUDICATION): termination = "adjudication" elif model.reason == WHITE_ENGINE_DIED: termination = "white engine died" elif model.reason == BLACK_ENGINE_DIED: termination = "black engine died" elif model.reason in ABORTED_REASONS: termination = "abandoned" elif model.reason in ADJOURNED_REASONS: termination = "unterminated" else: termination = "normal" print('[Termination "%s"]' % termination, file=handle) print("", file=handle) save_emt = conf.get("saveEmt", False) save_eval = conf.get("saveEval", False) result = [] walk(model.boards[0].board, result, model, save_emt, save_eval) result = " ".join(result) result = wrap(result, 80) print(result, status, file=handle) print("", file=handle) output = handle.getvalue() if isinstance(handle, StringIO) else "" handle.close() return output
def save(handle, model, position=None): """ Saves the game from GameModel to .pgn """ processed_tags = [] def write_tag(tag, value, roster=False): nonlocal processed_tags if tag in processed_tags or (not roster and not value): return try: pval = str(value) pval = pval.replace("\\", "\\\\") pval = pval.replace("\"", "\\\"") print('[%s "%s"]' % (tag, pval), file=handle) processed_tags = processed_tags + [tag] except Exception: pass # Mandatory ordered seven-tag roster status = reprResult[model.status] for tag in mandatory_tags: value = model.tags[tag] if tag == "Date": y, m, d = parseDateTag(value) y = "%04d" % y if y is not None else "????" m = "%02d" % m if m is not None else "??" d = "%02d" % d if d is not None else "??" value = "%s.%s.%s" % (y, m, d) elif value == "": value = "?" write_tag(tag, value, roster=True) write_tag("Result", reprResult[model.status], roster=True) # Variant if model.variant.variant != NORMALCHESS: write_tag("Variant", model.variant.cecp_name.capitalize()) # Initial position if model.boards[0].asFen() != FEN_START: write_tag("SetUp", "1") write_tag("FEN", model.boards[0].asFen()) # Number of moves write_tag("PlyCount", model.ply - model.lowply) # Final position if model.reason == WON_CALLFLAG: value = "time forfeit" elif model.reason == WON_ADJUDICATION and model.isEngine2EngineGame(): value = "rules infraction" elif model.reason in (DRAW_ADJUDICATION, WON_ADJUDICATION): value = "adjudication" elif model.reason == WHITE_ENGINE_DIED: value = "white engine died" elif model.reason == BLACK_ENGINE_DIED: value = "black engine died" elif model.reason in ABORTED_REASONS: value = "abandoned" elif model.reason in ADJOURNED_REASONS: value = "unterminated" else: value = "unterminated" if status == "*" else None if value is not None: write_tag("Termination", value) # ELO and its variation if conf.get("saveRatingChange", False): welo = model.tags["WhiteElo"] belo = model.tags["BlackElo"] if welo != "" and belo != "": write_tag("WhiteRatingDiff", get_elo_rating_change_pgn(model, WHITE)) # Unofficial write_tag("BlackRatingDiff", get_elo_rating_change_pgn(model, BLACK)) # Unofficial # Time if model.timed: write_tag('WhiteClock', msToClockTimeTag(int(model.timemodel.getPlayerTime(WHITE) * 1000))) write_tag('BlackClock', msToClockTimeTag(int(model.timemodel.getPlayerTime(BLACK) * 1000))) # Write all the unprocessed tags for tag in model.tags: # Debug: print(">> %s = %s" % (tag, str(model.tags[tag]))) write_tag(tag, model.tags[tag]) # Discovery of the moves and comments save_emt = conf.get("saveEmt", False) save_eval = conf.get("saveEval", False) result = [] walk(model.boards[0].board, result, model, save_emt, save_eval) # Alignment of the fetched elements indented = conf.get("indentPgn", False) if indented: buffer = "" depth = 0 crlf = False for text in result: # De/Indentation crlf = (buffer[-1:] if len(buffer) > 0 else "") in ["\r", "\n"] if text == "(": depth += 1 if indented and not crlf: buffer += os.linesep crlf = True # Space between each term last = buffer[-1:] if len(buffer) > 0 else "" crlf = last in ["\r", "\n"] if not crlf and last != " " and last != "\t" and last != "(" and not text.startswith("\r") and not text.startswith("\n") and text != ")" and len(buffer) > 0: buffer += " " # New line for a new main move if len(buffer) == 0 or (indented and depth == 0 and last != "\r" and last != "\n" and re.match("^[0-9]+\.", text) is not None): buffer += os.linesep crlf = True # Alignment if crlf and depth > 0: for j in range(0, depth): buffer += " " # Term buffer += text if indented and text == ")": buffer += os.linesep crlf = True depth -= 1 else: # Add new line to separate tag section and movetext print('', file=handle) buffer = textwrap.fill(" ".join(result), width=80) # Final status = reprResult[model.status] print(buffer, status, file=handle) # Add new line to separate next game print('', file=handle) output = handle.getvalue() if isinstance(handle, StringIO) else "" handle.close() return output