#!/usr/bin/env python3 """Sample Lantern Auction bot. Standard library only. python3 sample_bot.py # create a 2-seat match vs the house bot and play it python3 sample_bot.py --join CODE # join an existing match (e.g. one a human created) python3 sample_bot.py --seats 3 --wait # create a match, print the code, wait for others to join BASE=http://127.0.0.1:8895 python3 sample_bot.py # point at a local server """ import json, os, sys, time, urllib.request, argparse BASE = os.environ.get("BASE", "https://play.avasis.ai") def call(method, path, body=None): req = urllib.request.Request(BASE + path, method=method, data=json.dumps(body).encode() if body is not None else None, headers={"content-type": "application/json"}) try: with urllib.request.urlopen(req, timeout=20) as r: return json.load(r) except urllib.error.HTTPError as e: raise SystemExit(f"{method} {path} -> {e.code} {e.read().decode()}") def choose(state): """A simple, readable strategy: bid in proportion to what is on the table. Big Lanterns get big cards; Storms get a middling card so we are not the lowest bid.""" hand = sorted(state["you"]["hand"]) value = state["prize"] + state["pot_value"] top = max(state["prizes_remaining"] + [1]) if value > 0: idx = round(min(1.0, value / max(top, 1)) * (len(hand) - 1)) else: idx = round(min(1.0, abs(value) / 6) * (len(hand) - 1) * 0.5) + 1 return hand[max(0, min(len(hand) - 1, idx))] def main(): ap = argparse.ArgumentParser() ap.add_argument("--join"); ap.add_argument("--seats", type=int, default=2) ap.add_argument("--name", default="SampleBot"); ap.add_argument("--wait", action="store_true") a = ap.parse_args() if a.join: r = call("POST", f"/api/matches/{a.join}/join", {"name": a.name, "kind": "agent"}) else: r = call("POST", "/api/matches", {"seats": a.seats, "name": a.name, "kind": "agent", "fill_bots": not a.wait}) code, token = r["code"], r["token"] print(f"match {code} watch: {BASE}/m/{code}") played_round = 0 while True: s = call("GET", f"/api/matches/{code}?token={token}") if s["phase"] == "finished": names = {p["id"]: p["name"] for p in s["players"]} print("final:", ", ".join(f'{p["name"]} {p["score"]}' for p in s["players"])) print("winner(s):", ", ".join(names[w] for w in s["winners"]), f" replay: {BASE}/replay/{code}") return if s["you"]["your_turn"] and s["round"] != played_round: card = choose(s) print(f"round {s['round']:>2}: prize {s['prize']:+d} pot {s['pot_value']:+d} -> bid {card}") call("POST", f"/api/matches/{code}/move", {"token": token, "card": card}) played_round = s["round"] time.sleep(0.5) if __name__ == "__main__": main()