← Policies

V0 — Choose completely randomly

lesson_7/policies/v0 · rule bot · the floor

Every agent on this site is a policy: a function from the current game state and the list of legal actions to a probability distribution over those actions. The engine (written in Rust, exposed to Python as star_engine) enumerates what's legal; the policy only chooses. V0 is the degenerate case — uniform probability over every legal action, End Turn included. It exists to be beaten: any policy worth anything must outscore a coin flip.

This is the entire policy:

lesson_7/policies/v0/__init__.py

"""V0 -- choose completely randomly (uniform over every legal action)."""

from __future__ import annotations

from random import Random

import star_engine as se

from ..base import Actions, Policy
from ..common import uniform


class V0(Policy):
    def __init__(self) -> None:
        super().__init__("V0 Choose completely randomly")

    def get_action_probabilities(
        self, game: se.Game, actions: Actions, rng: Random
    ) -> list[float]:
        return uniform(actions)

The one helper it uses:

lesson_7/policies/common.py (excerpt)

def uniform(actions: Actions) -> list[float]:
    """Uniform over every legal action."""
    p = 1.0 / len(actions)
    return [p] * len(actions)

The interface it implements is shared by every policy V0–V7. Note the design decision: the single abstract primitive is the distribution, not the choice. A deterministic bot returns a one-hot vector; a random bot returns a spread; and the same distribution later doubles as an AlphaZero-style policy target for the learned agents.

lesson_7/policies/base.py (excerpt)

class Policy(ABC):
    """Base class for every policy. Subclasses implement
    `get_action_probabilities`; `get_action` is derived."""

    def __init__(self, name: str) -> None:
        self.name = name

    @abstractmethod
    def get_action_probabilities(
        self, game: se.Game, actions: Actions, rng: Random
    ) -> list[float]:
        """Probabilities over `actions`, aligned to the list and summing to 1."""

    def get_action(
        self, game: se.Game, actions: Actions, rng: Random
    ) -> se.LegalAction:
        """Sample one action from `get_action_probabilities`. Deterministic
        whenever that distribution is one-hot."""
        probs = self.get_action_probabilities(game, actions, rng)
        return rng.choices(actions, weights=probs, k=1)[0]

    def __repr__(self) -> str:
        return f"{type(self).__name__}({self.name!r})"

← Policies · Home