Tongits RL Champions & Persona Archetypes

Reinforcement learning policies trained for Tongits.io, an online implementation of Tongits (a 3-player imperfect-information card game popular in the Philippines).

This repository contains 9 policy checkpoints: the base production champion (Carolina Reaper) and 8 fine-tuned persona archetypes trained with reward shaping to produce distinct tactical styles.

All models are exported in ONNX format for inference across Python (onnxruntime), Node.js (onnxruntime-node), and browsers (onnxruntime-web). A PyTorch state dict (policy-champion.pt) is also provided.


Model Roster & Persona Archetypes

File Pepper / Persona Archetype Win Rate vs Control Money Delta / Hand Characteristic Tactical Behavior Size
policy-champion.onnx Carolina Reaper (Champion) Champion Tier 28.3% Baseline (Control) Balanced baseline play 2.84 MB
policy-tongits-hunter.onnx Serrano (Tongits Hunter) Tongits Hunter 29.4% vs 28.3% +0.085 ± 0.074 / hand Fast hand clearance and early melds 2.84 MB
policy-aggressive-fighter.onnx Habanero (Aggressive Fighter) Aggressive Fighter 31.2% vs 28.3% +0.103 ± 0.076 / hand Frequent fight calls (+57% fight rate) 2.84 MB
policy-secret-hunter.onnx Sili Labuyo (Secret Hunter) Secret Hunter 28.9% vs 28.3% +0.072 ± 0.071 / hand Retains concealed melds for Secret/Sagasa wins 2.84 MB
policy-safe-grinder.onnx Poblano (Defensive Grinder) Defensive Grinder 28.5% vs 28.3% +0.041 ± 0.068 / hand Deadwood minimization and burn avoidance 2.84 MB
policy-wild-bluffer.onnx Ghost Pepper (Wild Bluffer) Wild Bluffer 32.6% vs 28.3% +0.092 ± 0.075 / hand Wide-range fight caller (+128% fight rate) 2.84 MB
policy-chow-fiend.onnx Jalapeño (Chow Fiend) Chow Fiend 30.5% vs 28.3% +0.071 ± 0.071 / hand High discard pickup and open meld frequency 2.84 MB
policy-deep-cover.onnx Cayenne (Deep-Cover Hoarder) Deep-Cover Hoarder 27.5% vs 28.3% +0.124 ± 0.071 / hand Conceals melds until endgame (644 deck-empty wins) 2.84 MB
policy-sapaw-saboteur.onnx Scotch Bonnet (Sapaw Saboteur) Sapaw Saboteur 27.7% vs 28.3% -0.017 ± 0.075 / hand High sapaw rate onto opponent melds 2.84 MB

Game Overview

Tongits (or Tong-its) is a 3-player rummy-type card game played with a standard 52-card deck. For detailed game rules, see Pagat:

  • Imperfect Information: Players conceal hand cards while tracking discards, public melds, and opponent declarations.
  • Board Mechanics:
    • Chow / Meld: Forming sets (3 or 4 cards of same rank) or sequences (3 or more consecutive cards of same suit).
    • Sapaw: Laying off cards from hand onto any existing exposed meld on the table.
    • Fight / Showdown: Challenging table opponents when holding low deadwood points.
    • Sunog (Burn): Players without any exposed meld by the end of the round forfeit stakes and pay dues.
  • Instant Wins: Special instant-win conditions include Tongits (emptying hand), Secret (concealed 4-of-a-kind), Sagasa (drawing the 4th card to an exposed set), and Bisaklat (perfect initial deal).

Model Architecture & Wire Contract

All models share a multi-layer perceptron architecture:

graph LR
    OBS["Observation Vector (349 floats)"] --> T1["Trunk Layer 1 (512, Mish)"]
    T1 --> T2["Trunk Layer 2 (512, Mish)"]
    T2 --> T3["Trunk Layer 3 (512, Mish)"]
    T3 --> POL["Policy Head (75 logits)"]
    T3 --> VAL["Value Head (1 float)"]
    POL --> MASK["Action Mask (75 bools)"]
    MASK --> ACT["Sampled / Greedy Action"]

Technical Specification

  • Observation Space: 349 float features normalized to [0.0, 1.0] or standard normal:
    • 0..51: Card locations (hand, discard, table, concealed).
    • 52..103: Discard history and opponent draw patterns.
    • 104..259: Meld compositions and sapaw attachment surfaces.
    • 260..309: Hand size counts, opponent exposed card counts, and relative deadwood estimates.
    • 310..344: Economy and betting parameters (ante, fight fee, secret bonus multipliers).
    • 345..348: Match pool streak features (streak_len, streak_won, opp_streak_len, opp_streak_won).
  • Action Space: 75 discrete action slots covering Draw from Deck, Chow from Discard, Expose Meld, Sapaw on Target, Call Fight, Accept Challenge, Fold, and Discard.
  • Action Masking: A companion boolean mask vector ([75]) marks legal actions. Illegal actions are masked to -1e9 prior to softmax sampling.

Quickstart: Python (onnxruntime)

import numpy as np
import onnxruntime as ort
from huggingface_hub import hf_hub_download

# 1. Download model from Hugging Face Hub
model_path = hf_hub_download(
    repo_id="ricoz/tongits-rl-champions",
    filename="policy-wild-bluffer.onnx"
)

# 2. Initialize ONNX Runtime session
session = ort.InferenceSession(model_path, providers=["CPUExecutionProvider"])

# 3. Prepare inputs (batch_size=1)
obs = np.zeros((1, 349), dtype=np.float32)       # 349-dim state vector
mask = np.ones((1, 75), dtype=np.float32)        # 75-dim boolean legal action mask

# 4. Run inference
logits, value = session.run(["logits", "value"], {"obs": obs, "mask": mask})

# 5. Select action (greedy or temperature-sampled)
action = int(np.argmax(logits[0]))
print(f"Selected action index: {action}, estimated state value: {value[0][0]:.3f}")

Quickstart: Node.js / TypeScript (onnxruntime-node)

import * as ort from 'onnxruntime-node';

async function main() {
  // 1. Load the ONNX model
  const session = await ort.InferenceSession.create('./policy-deep-cover.onnx');

  // 2. Wrap state & mask into tensors
  const obsTensor = new ort.Tensor('float32', new Float32Array(349), [1, 349]);
  const maskTensor = new ort.Tensor('float32', new Float32Array(75).fill(1), [1, 75]);

  // 3. Execute model
  const feeds = { obs: obsTensor, mask: maskTensor };
  const results = await session.run(feeds);

  const logits = results.logits.data as Float32Array;
  const bestAction = logits.indexOf(Math.max(...Array.from(logits)));
  console.log('Optimal action:', bestAction);
}

main();

Quickstart: Browser / WebAssembly (onnxruntime-web)

<script src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js"></script>
<script>
async function run() {
  const session = await ort.InferenceSession.create(
    'https://huggingface.co/ricoz/tongits-rl-champions/resolve/main/policy-champion.onnx'
  );
  const obs = new ort.Tensor('float32', new Float32Array(349), [1, 349]);
  const mask = new ort.Tensor('float32', new Float32Array(75).fill(1), [1, 75]);
  const output = await session.run({ obs, mask });
  console.log('Action logits:', output.logits.data);
}
run();
</script>

Training Pipeline & Reproducibility

  1. Warm Start via Behavioral Cloning (BC): Pretrained on 50,000 expert heuristic hands to establish rule adherence and baseline card counting.
  2. PPO Self-Play League: Trained over 176 checkpoint iterations (352,000 hands) with Generalized Advantage Estimation (GAE lambda = 0.95), PPO clip ratio epsilon = 0.2, and entropy schedule decay.
  3. Constrained Reward Shaping: Persona fine-tuning applies linear reward additives (fee units * stake) on top of the zero-sum economy payoff, steering policies into specialized tactical behaviors without destabilizing game-theoretic baseline play.
  4. Anti-Collusion Drift Guard: Candidates must maintain positive expected value against an anchored heuristic pool (>= 0.0 drift margin) to ensure self-play policies do not degenerate into mutually exploitative loops.

License & Attribution

All model weights, architectures, and cards in this repository are licensed under the Apache 2.0 License.

If you use these models, benchmark data, or environment specifications in research, cite:

@misc{tongits_rl_2026,
  title={Tongits RL: Multi-Agent Reinforcement Learning for 3-Player Imperfect-Information Filipino Card Games},
  author={Rico Zuñiga},
  year={2026},
  howpublished={\url{https://huggingface.co/ricoz/tongits-rl-champions}},
  publisher={Hugging Face}
}
Downloads last month

-

Downloads are not tracked for this model. How to track
Video Preview
loading

Space using ricoz/tongits-rl-champions 1