Monday, June 22, 2026
MODIFICATION - Import chess games, catalog them, list from first variation move and by frequency. / Chess and Music brainstorming
Check previous post for Chess and Music brainstorming, https://1a2b3c4d5e6f7g8h9i10j11k12l13m14n.blogspot.com/2026/06/import-chess-games-catalog-them-list.html
"""
chessopenings2.py
Interactive Opening Catalog + Continuation Analyzer
- Loads existing opening catalog (JSON)
- Processes ONE PGN at a time
- Extracts continuations (moves AFTER opening)
- Displays full interactive catalog in PyCharm
- Allows manual reordering like chessopenings1.py
Requires:
pip install python-chess
"""
import chess.pgn
import os
import json
JSON_FILE = "personal_openings.json"
OPENING_SKIP_PLIES = 6 # skip first ~3 full moves
MAX_PLIES = 30 # up to 15 full moves
# ----------------------------
# LOAD / SAVE
# ----------------------------
def load_data():
if os.path.exists(JSON_FILE):
with open(JSON_FILE, "r", encoding="utf-8") as f:
return json.load(f)
return {}
def save_data(data):
with open(JSON_FILE, "w", encoding="utf-8") as f:
json.dump(data, f, indent=4)
# ----------------------------
# FORMAT CONTINUATIONS (MOVE NUMBERED)
# ----------------------------
def format_continuation(san_moves, start_ply):
lines = []
i = 0
ply = start_ply
while i < len(san_moves) and ply < MAX_PLIES:
move_number = (ply // 2) + 1
white = san_moves[i]
i += 1
ply += 1
line = f"{move_number}. {white}"
if i < len(san_moves) and ply < MAX_PLIES:
black = san_moves[i]
i += 1
ply += 1
line += f" {black}"
lines.append(line)
return lines
# ----------------------------
# PROCESS PGN
# ----------------------------
def process_pgn(filename, data):
game_count = 0
with open(filename, "r", encoding="utf-8", errors="ignore") as pgn:
while True:
game = chess.pgn.read_game(pgn)
if game is None:
break
game_count += 1
eco = game.headers.get("ECO", "").strip()
opening = game.headers.get("Opening", "").strip()
variation = game.headers.get("Variation", "").strip()
white_elo = game.headers.get("WhiteElo", "")
black_elo = game.headers.get("BlackElo", "")
try:
white_elo = int(white_elo)
black_elo = int(black_elo)
except ValueError:
continue
if white_elo < 2100 and black_elo < 2100:
continue
if not opening:
opening = "Unknown Opening"
key = f"{eco} | {opening}"
if variation:
key += f" | {variation}"
board = game.board()
san_moves = []
for move in game.mainline_moves():
san_moves.append(board.san(move))
board.push(move)
continuation_moves = san_moves[
OPENING_SKIP_PLIES:OPENING_SKIP_PLIES + MAX_PLIES
]
start_ply = OPENING_SKIP_PLIES
continuation_lines = format_continuation(
continuation_moves,
start_ply
)
continuation_str = " | ".join(continuation_lines)
if key not in data:
data[key] = {}
if continuation_str not in data[key]:
data[key][continuation_str] = 1
else:
data[key][continuation_str] += 1
print("\nGames processed:", game_count)
# ----------------------------
# DISPLAY
# ----------------------------
def display(data):
print("\nOPENING CATALOG (WITH CONTINUATIONS)")
print("=" * 100)
items = sorted(
data.items(),
key=lambda item: sum(item[1].values()),
reverse=True
)
for i, (key, variations) in enumerate(items, start=1):
print(f"\n{i:3} {key}")
if not variations:
print(" (no continuation data yet)")
continue
sorted_variations = sorted(
variations.items(),
key=lambda x: x[1],
reverse=True
)
for j, (cont, freq) in enumerate(sorted_variations[:5], start=1):
print(f"\n [{j}] freq={freq}")
print(f" {cont}")
print("-" * 100)
# ----------------------------
# REORDER SYSTEM
# ----------------------------
def reorder(data):
items = list(data.items())
while True:
display(dict(items))
print("\nCommands:")
print(" X=Y move item X to position Y")
print(" s save")
print(" q quit")
cmd = input("\nCommand: ").strip().lower()
if cmd == "s":
save_data(dict(items))
print("\nSaved.")
continue
if cmd == "q":
return dict(items)
if "=" in cmd:
try:
a, b = cmd.split("=")
a = int(a) - 1
b = int(b) - 1
item = items.pop(a)
items.insert(b, item)
except:
print("Invalid command")
# ----------------------------
# MAIN
# ----------------------------
def main():
data = load_data()
print("\nChessOpenings2 - Interactive Continuation System")
print("------------------------------------------------")
filename = input("\nPGN filename (WITHOUT .pgn): ").strip()
if not filename:
return
filename = filename + ".pgn"
if not os.path.exists(filename):
print("File not found:", filename)
return
process_pgn(filename, data)
data = reorder(data)
save_data(data)
print("\nDone.")
if __name__ == "__main__":
main()
Subscribe to:
Post Comments (Atom)
-
**See 6/22 post for adjustments.** Code can be tested at https://www.programiz.com/python-programming/online-compiler/ (Remove the 3 lines ...
-
The code below starts the bidding process. It's possible now to add graphics, that might be next as well as continuing with picking up. ...
No comments:
Post a Comment