Runtime Contract

  • Export a single object as const bot = { ... };.
  • Include metadata: botName, botAuthor, botLore, version, lastUpdated.
  • Implement chooseAction(gameState, myPlayerId, rng).
  • For Draft API v3 bots, also implement chooseBanCharacter(draftState, myPlayerId, rng) and choosePickCharacter(draftState, myPlayerId, rng).
  • Use deterministic RNG from rng only.
  • Only god heroes initiate attacks. Altars are move-only defenders.
  • Read gameState.chaordic, activeBounds, and voidTiles every turn so your bot reacts before Chaordic pressure becomes lethal.

Ranked Draft Flow

  • Ranked PvP and Arena Duel now use a two-step draft: one ban per side, then two picks per side.
  • A random side starts the Ban Phase, then the same starting side starts the Pick Phase.
  • Draft API v3 bots should return their preferred god from the current available roster only.
  • Older bots below 3.0.0 fall back to random ban/pick behavior in ranked draft.
  • If a side times out during draft, Raksha also uses a random fallback so the match can continue safely.

Policy Rules

  • No AI/LLM calls and no external libraries.
  • No network APIs (`fetch`, `WebSocket`, `XMLHttpRequest`, etc.).
  • No `import`/`require`, no `eval`, no `Function`, no string timers.
  • No `Math.random`, no `Date.now`, no `window`/`document`/`globalThis` access.
  • Upload size limit: 200KB.

Action Shapes

Normalized actions accepted by the uploader runtime: `MOVE`, `ATTACK`, `SKILL`.

  • Move: `{ type: "MOVE", pieceId, toTile | targetTile }`
  • Attack: `{ type: "ATTACK", pieceId | attackerId, targetId }`
  • Skill: `{ type: "SKILL", pieceId | heroId, toTile | targetTile }`
  • Legal attack lists are hero-only, so altar entries expose moves but no attacks.
const bot = {
  botName: "My Deterministic Bot",
  botAuthor: "You",
  botLore: "A concise strategy description",
  version: "3.0.0",
  lastUpdated: "2026-03-28",

  DRAFT_PRIORITY: {
    bans: ["kidu", "jumka", "anika", "faros", "mahui", "sajik"],
    picks: ["anika", "faros", "mahui", "sajik", "jumka", "kidu"],
  },

  chooseBanCharacter(draftState, myPlayerId, rng) {
    return this.DRAFT_PRIORITY.bans.find((id) =>
      draftState.availableCharacters.includes(id),
    ) ?? null;
  },

  choosePickCharacter(draftState, myPlayerId, rng) {
    return this.DRAFT_PRIORITY.picks.find((id) =>
      draftState.availableCharacters.includes(id),
    ) ?? null;
  },

  chooseAction(gameState, myPlayerId, rng) {
    const myHero = gameState.pieces
      .filter((p) => p.owner === myPlayerId && p.type === "CHARACTER")
      .sort((a, b) => a.id.localeCompare(b.id))[0];
    if (!myHero) return null;

    const legal = gameState.legalByPieceId[myHero.id];
    if (!legal) return null;

    const move = legal.moves
      .slice()
      .sort((a, b) => a.y - b.y || a.x - b.x)[0];
    if (move) return { type: "MOVE", pieceId: myHero.id, toTile: move };

    const targetId = legal.attacks.slice().sort()[0];
    if (targetId) return { type: "ATTACK", attackerId: myHero.id, targetId };

    const tile = legal.skills
      .slice()
      .sort((a, b) => a.y - b.y || a.x - b.x)[0];
    if (tile) return { type: "SKILL", heroId: myHero.id, targetTile: tile };

    return null;
  },
};

Duel Buff Reminders

  • Base initiated attack duel chance is 50%.
  • Skill triggers can buff the owning god's next duel to 60%, 70%, or 80%, whether that god is attacking or defending.
  • Chaos blessing sets the next initiated attack duel to at least 75%.
  • Buff-vs-buff duels resolve from the net difference over 50/50: 75% vs 80% becomes 45% vs 55%, and 80% vs 80% stays 50% vs 50%.
  • For the attacker side only, Chaos blessing is still a floor, not a stack.
  • Check each piece's live duelChance field when you score attacks or shrine routes.
  • Draft decisions are stored in ranked match metadata, so your ban and pick choices should be deliberate and deterministic.

Chaordic Reminders

  • The main Chaordic Event advances only while HP stays tied. If the tie breaks, the countdown resets.
  • On the standard 9x9 board, Chaordic I compresses to 7x7, Chaordic II compresses to 5x5, and Chaordic III resets the board to full size with rotating center void tiles.
  • Chaordic I warns at 9 and 5 rounds remaining. Chaordic II and III warn at 9 and 6 rounds remaining.
  • Chaordic X is separate: repetitive MOVE or SKILL target loops of up to three steps escalate through three warnings, then the acting player loses 1 HP if the same loop keeps continuing.
  • Use gameState.voidTiles plus gameState.chaordic.voidPattern to avoid the rotating center void shape during Chaordic III. The pattern values rotate through 1ST, 2ND, and 3RD.
  • Good prevention heuristics are simple: break tied HP, stop shuffling the same piece through the same one-, two-, or three-step targets, and vary repeated skill targets when pressure is not improving.