Core Python API¶
Create A Game¶
from PolyEnv import GameEnv, Bardur, Imperius, Lakes
env = GameEnv(seed=1234, map_size=11, players=(Bardur, Imperius), map_type=Lakes)
seed=0 chooses a random seed. Tribe constants, strings, and get_tribe()
are accepted:
from PolyEnv import GameEnv, get_tribe
env = GameEnv(players=(get_tribe("Bardur"), "Imperius"))
Only the 12 regular tribes are supported.
High-Throughput Training¶
Use VectorGameEnv when training over many games at once. It executes a
batch of independent C++ games on a persistent worker pool and returns dense
NumPy arrays rather than one Python packet per game:
from PolyEnv import VectorGameEnv
env = VectorGameEnv(num_envs=256, num_threads=8, max_actions=512)
batch = env.reset()
batch = env.step(batch["action_id"][:, 0])
See VectorGameEnv: Native Batched Training for its complete
API and tensor layouts. Use GameEnv for a single game, debugging, replays,
or MCTS cloning. For a pinned-memory, allocation-free rollout loop, use
env.batch_spec() to allocate caller-owned arrays and then
env.reset_into(buffers) / env.step_into(action_ids, buffers); the detailed
CUDA stream and double-buffering protocol is in that guide.
Batched MCTS¶
MctsPool keeps many native PUCT trees in C++ and exchanges only dense leaf
batches with a policy/value model. It supports 2--16 players: two-player pools
use scalar values, while larger pools require a player-indexed value vector.
Construct it from one root plus num_trees, or from a sequence of independent
roots:
from PolyEnv import MctsPool
pool = MctsPool(env, num_trees=256, num_threads=8)
leaves = pool.select_leaves()
# Run one GPU policy/value forward pass for leaves.
pool.expand_and_backup(leaves["leaf_id"], policy_logits, values)
root_policy = pool.root_policy()
See MctsPool: Native Batched PUCT for evaluator shapes,
value-perspective rules, fog-of-war requirements, and search-loop details.
For allocation-free GPU batches, use leaf_batch_spec() plus
select_leaves_into() (which returns a valid-prefix length), and use
root_policy_spec() plus root_policy_into() for root results.
Native Belief-MCTS Self-Play¶
Use SelfPlayPool when an external repository owns both a hidden-map belief
model and a policy/value model, but needs PolyEnv to run many live games and
MCTS searches without Python loops:
from PolyEnv import SelfPlayPool
pool = SelfPlayPool(num_envs=256, num_threads=8, max_actions=512)
request = pool.reset()
completed_map_tokens = external_belief_model(request)
pool.submit_beliefs(request["state_id"], completed_map_tokens)
leaves = pool.select_leaves()
The pool exposes only visible player data and takes a checked, detached belief
completion as its MCTS root. It has no model-framework dependency. See
SelfPlayPool: Native Belief-MCTS Self-Play for the full
lifecycle, batch contract, stale-id rules, and fog-of-war limitations.
belief_batch_spec() with reset_into() / belief_requests_into() /
step_into() makes the live belief-request boundary reusable as well; its MCTS
leaf and root *_into() APIs follow the same contracts as MctsPool.
Map Type¶
The supported map types are Lakes and Drylands. Pass either the exported
constant or its lower-case string form:
from PolyEnv import Drylands, GameEnv
dry_game = GameEnv(map_type=Drylands)
same_game = GameEnv(map_type="drylands")
reset() accepts the same map_type argument. Every observation contains a
map_type field whose value is either "lakes" or "drylands".
Everyday Methods¶
| Method | Purpose |
|---|---|
model_request_numpy() |
Fast NumPy packet for a policy/model |
model_request() |
Readable Python packet for debugging |
step_fast(action_id) |
Execute one legal action efficiently |
step(action_id) |
Execute one action with detailed metadata |
legal_action_ids_fast() |
Return current legal action ids |
decode_action(action_id) |
Inspect an action id while debugging |
observation() |
Current player's visible observation |
player_map_numpy() |
Current player's visible map |
full_map_numpy() |
Complete map for labels/debugging |
current_player() / is_done() |
Read turn and terminal state |
step_fast() returns:
ok, done, reward, winner, current_player = env.step_fast(action_id)
The engine returns terminal reward only: win 1.0, loss -1.0, otherwise
0.0. Add reward shaping in the training project, not in PolyEnv.
Reset And Branch¶
env.reset(seed=4321, players=(Bardur, Imperius), map_type="lakes")
branch = env.clone() # independent copy for MCTS
branch2 = env.copy() # alias for clone()
snapshot = env.save_state()
# ... inspect or modify env ...
env.load_state(snapshot)
clone() and copy() do not mutate the original environment.
Replays¶
env.save("match.polygame")
replayed = GameEnv()
replayed.load("match.polygame")
Replay files are portable action histories. Use save_state() and
load_state() only for in-memory snapshots. See Replays for
compatibility rules.
Advanced Helpers¶
legal_param_actions(), action_param_spec(), step_param(), and
step_param_vec() are lower-level action APIs. The recommended integration
for new model code is model_request_numpy() plus step_fast(action_id).
Hidden-Map Prediction Worlds¶
For MCTS rollouts under fog of war, use
env.make_belief_env(completed_map_tokens). It constructs a detached world
from the current observation plus a full predicted token map. See
Hidden-Map Predictions.
Visible Event History¶
visible_events_numpy(since=0) returns only events observable by the current
player. It uses compact NumPy arrays and a private cursor; no global event id,
hidden source position, hidden unit type, or hidden owner is exported. See
Visible event history for the packet layout and event ids.
For batched GPU training, use
VectorGameEnv(visible_event_history=K) instead of collecting these variable
length packets in Python. It returns a bounded, masked dense history window
with the same visibility rules; see the
VectorGameEnv event window.