instance_finder: find hard instances on hanab.live
searches for instances with no known full score in hanab.live database and tackles these with SAT solver
This commit is contained in:
parent
f8c2919a85
commit
a90ff5d451
1 changed files with 95 additions and 0 deletions
95
instance_finder.py
Normal file
95
instance_finder.py
Normal file
|
@ -0,0 +1,95 @@
|
|||
import requests
|
||||
import requests_cache
|
||||
import json
|
||||
from sat import COLORS, solve
|
||||
|
||||
session = requests_cache.CachedSession('hanab.live')
|
||||
|
||||
def get(url):
|
||||
print("sending request for " + url)
|
||||
response = session.get("https://hanab.live/" + url)
|
||||
if not response.status_code == 200:
|
||||
return None
|
||||
if "application/json" in response.headers['content-type']:
|
||||
return json.loads(response.text)
|
||||
|
||||
def api(url):
|
||||
link = "api/v1/" + url
|
||||
if "?" in url:
|
||||
link += "&"
|
||||
else:
|
||||
link += "?"
|
||||
link += "size=100"
|
||||
return get(link)
|
||||
|
||||
#r = api("variants/0")
|
||||
#print(json.dumps(r, indent=4))
|
||||
|
||||
def replay(seed):
|
||||
r = api("seed/" + str(seed))
|
||||
try:
|
||||
game_id = r['rows'][0]['id']
|
||||
except TypeError:
|
||||
return None
|
||||
return get("export/" + str(game_id))
|
||||
|
||||
|
||||
def known_solvable(seed):
|
||||
link = "seed/" + seed
|
||||
r = api(link)
|
||||
rows = r['rows']
|
||||
if not rows:
|
||||
print("invalid response to seed {}".format(seed))
|
||||
return False
|
||||
for row in rows:
|
||||
if row["score"] == 25:
|
||||
return True, row["id"]
|
||||
for i in range(1, (r['total_rows'] + 99) // 100):
|
||||
page = api(link + "?page=" + str(i))
|
||||
rows = page['rows']
|
||||
for row in rows:
|
||||
if row["score"] == 25:
|
||||
return True, row["id"]
|
||||
# print("No solution found in database for seed {}".format(seed))
|
||||
return False
|
||||
|
||||
|
||||
def solvable(replay):
|
||||
deck = replay["deck"]
|
||||
deck_str = " ".join(COLORS[c["suitIndex"]] + str(c["rank"]) for c in deck)
|
||||
return solve(deck_str, len(replay["players"]))
|
||||
|
||||
|
||||
seeds = {2: [], 3: [], 4: [], 5: [], 6: []}
|
||||
num_games = 0
|
||||
for i in range(0,1000):
|
||||
r = api("variants/0?page=" + str(i))
|
||||
for row in r['rows']:
|
||||
num_games += 1
|
||||
if row['seed'] not in seeds[row['num_players']]:
|
||||
seeds[row['num_players']].append(row['seed'])
|
||||
# print('found new non-max-game in 5p: ' + row['seed'])
|
||||
print('looked at {} games'.format(num_games))
|
||||
for i in range(2,7):
|
||||
print("Found {} seeds in {}-player in database".format(len(seeds[i]), i))
|
||||
|
||||
hard_seeds = []
|
||||
for seed in seeds[3]:
|
||||
if not known_solvable(seed):
|
||||
# print("seed {} has no solve in online database".format(seed))
|
||||
hard_seeds.append(seed)
|
||||
print("Found {} seeds with no solve in database, attacking each with SAT solver"
|
||||
.format(len(hard_seeds)))
|
||||
|
||||
for seed in hard_seeds:
|
||||
r = replay(seed)
|
||||
if not r:
|
||||
continue
|
||||
s, sol = solvable(r)
|
||||
if s:
|
||||
print("Seed {} was found to be solvable".format(seed))
|
||||
print(sol)
|
||||
else:
|
||||
print("==============================")
|
||||
print("Found non-solvable seed {}", seed)
|
||||
print("==============================")
|
Loading…
Reference in a new issue