Astar Island Quickstart
Authentication
All endpoints require authentication. Log in at app.ainm.no, then inspect cookies in your browser to grab your access_token JWT.
You can authenticate using either a cookie or a Bearer token header:
import requests
BASE = "https://api.ainm.no"
# Option 1: Cookie-based auth
session = requests.Session()
session.cookies.set("access_token", "YOUR_JWT_TOKEN")
# Option 2: Bearer token auth
session = requests.Session()
session.headers["Authorization"] = "Bearer YOUR_JWT_TOKEN"Step 1: Get the Active Round
rounds = session.get(f"{BASE}/astar-island/rounds").json()
active = next((r for r in rounds if r["status"] == "active"), None)
if active:
round_id = active["id"]
print(f"Active round: {active['round_number']}")Step 2: Get Round Details
Fetch the detail endpoint to get full round info including seeds_count and initial states:
detail = session.get(f"{BASE}/astar-island/rounds/{round_id}").json()
width = detail["map_width"] # 40
height = detail["map_height"] # 40
seeds = detail["seeds_count"] # 5
print(f"Round: {width}x{height}, {seeds} seeds")
for i, state in enumerate(detail["initial_states"]):
grid = state["grid"] # height x width terrain codes
settlements = state["settlements"] # [{x, y, has_port, alive}, ...]
print(f"Seed {i}: {len(settlements)} settlements")Step 3: Query the Simulator
You have 50 queries per round, shared across all seeds. Each query reveals a 5-15 cell wide viewport:
result = session.post(f"{BASE}/astar-island/simulate", json={
"round_id": round_id,
"seed_index": 0,
"viewport_x": 10,
"viewport_y": 5,
"viewport_w": 15,
"viewport_h": 15,
}).json()
grid = result["grid"] # 15x15 terrain after simulation
settlements = result["settlements"] # settlements in viewport with full stats
viewport = result["viewport"] # {x, y, w, h}Step 4: Build and Submit Predictions
For each seed, submit a height x width x 6 probability tensor. Each cell has 6 values representing the probability of each terrain class (Empty, Settlement, Port, Ruin, Forest, Mountain). They must sum to 1.0:
import numpy as np
for seed_idx in range(seeds):
prediction = np.full((height, width, 6), 1/6) # uniform baseline
# TODO: replace with your model's predictions
# prediction[y][x] = [p_empty, p_settlement, p_port, p_ruin, p_forest, p_mountain]
resp = session.post(f"{BASE}/astar-island/submit", json={
"round_id": round_id,
"seed_index": seed_idx,
"prediction": prediction.tolist(),
})
print(f"Seed {seed_idx}: {resp.status_code}")A uniform prediction scores ~1-5. Use your queries to build better predictions.
Warning: Never assign probability 0.0 to any class. If the ground truth has any non-zero probability for a class you marked as zero, KL divergence becomes infinite and your score for that cell is destroyed. Always enforce a minimum floor (e.g., 0.01) and renormalize. See the scoring docs for details.
Using the MCP Server
Add the documentation server to Claude Code for AI-assisted development:
claude mcp add --transport http nmiai https://mcp-docs.ainm.no/mcp