From 5ce58b375d29c1b255e143c28e6c99ecac8a5394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maximilian=20Ke=C3=9Fler?= Date: Sat, 11 Nov 2023 01:38:37 +0100 Subject: [PATCH] add endgames.py --- endgames.py | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 endgames.py diff --git a/endgames.py b/endgames.py new file mode 100644 index 0000000..614611f --- /dev/null +++ b/endgames.py @@ -0,0 +1,63 @@ +import json +import re +import subprocess +from typing import Dict + +from pathlib import Path +DATA_FILE = Path('endgame-data.json') + +if not DATA_FILE.exists(): + DATA_FILE.write_text('{}') + + +with open(DATA_FILE, 'r') as f: + DATA: Dict = json.loads(f.read()) + + +def analyze_game(game_id: int): + probabilities = {} + for deck_size in range(1, 16): + try: + result = subprocess.run(['./endgame-analyzer', '-g', str(game_id), '-d', str(deck_size), '-i', '0'], stdout=subprocess.PIPE, timeout=30) + except subprocess.TimeoutExpired: + return probabilities + output = result.stdout.decode('utf-8') + m = re.search('Probability with optimal play: .*/.* ~ ([0-9.]+)', output) + if not m: + raise ValueError("Invalid program output: {}".format(output)) + probabilities[str(deck_size)] = m.group(1) + return probabilities + +def full_analyze_game(game_id: int): + probabilities = {} + try: + result = subprocess.run(['./endgame-analyzer', '-g', str(game_id), '-d', str(deck_size), '-i', '0', '--all-clues', '-r'], stdout=subprocess.PIPE, timeout=180) + except subproces.TimeoutExpired: + return probabilities + output = result.stdout.decode('utf-8') + for m in re.finditer('Probability with (\d+) cards left in deck and (\d) clues (+|-\d): .*/.* ~ ([0-9.]+)', output): + probabilities[m.group(1)][m.group(3)] = m.group(4) + return probabilities + +def full_analyze_game_cached(game_id: int): + cached = DATA.get('all', {}).get(str(game_id), None) + if cached is not None: + return cached + result = full_analyze_game(game_id) + DATA['all'][game_id] = result + save_cache() + return result + +def analyze_game_cached(game_id: int): + cached = DATA['normal'].get(str(game_id), None) + if cached is not None: + return cached + result = analyze_game(game_id) + DATA['normal'][game_id] = result + save_cache() + return result + + +def save_cache(): + with open(DATA_FILE, 'w') as f: + f.writelines(json.dumps(DATA, indent=2))