Bazaar-AI is a Python-based library built on top of Arelai that faithfully recreates the strategic card game Jaipur. It provides:
- 🎮 a complete game implementation, accurately modeling all Jaipur rules
- 🤖 a plug-and-play agent interface, allowing custom agents to be created by extending a single class
- 📊 a serializable game state, making it easy to convert states into observations for RL algorithms
- 🎯 support for custom reward functions, so you can define your own training signals
- 🖥️ a visual simulator, featuring a polished web-based UI for watching agents compete in real time
With Bazaar-AI, students can experiment with different RL approaches—from simple heuristics to Monte Carlo Tree Search to deep reinforcement learning—all within a rich, strategic environment.
Jaipur is an ideal game for AI research and education because it captures many challenges found in real-world decision-making, including:
-
partial observability, where players cannot see the deck or their opponent’s full hand, requiring decisions to be made under uncertainty.
-
delayed rewards, in which actions taken now may only pay off several turns later, testing an agent’s ability to plan ahead.
-
strategic depth, where a relatively small action space still produces surprising complexity and multiple viable strategies.
-
competitive dynamics, as optimal play depends on anticipating and responding to an opponent’s strategy, introducing game-theoretic considerations.
-
fast episodes, with games typically lasting 20 to 40 turns, enabling rapid iteration during development.
These characteristics make Jaipur an excellent stepping stone between toy problems and complex real-world applications—challenging enough to be interesting, but tractable enough for a semester project.
The framework is built on Arelai, providing a clean object-oriented structure for game states, actions, and observations. The core game loop handles all the mechanics automatically, so you can focus entirely on developing your agent's decision-making logic.
Implementing your own agent is straightforward. Just extend the Trader class and override two key methods:
from backend.trader import Trader, TraderAction
from backend.market import MarketObservation
from typing import Optional, Callable
class MyCustomAgent(Trader):
def __init__(self, seed, name):
super().__init__(seed, name)
# Initialize any agent-specific data structures
self.memory = []
def select_action(self,
actions: list[TraderAction],
observation: MarketObservation,
simulate_action_fnc: Callable[[TraderAction], MarketObservation]) -> TraderAction:
"""
Choose an action based on the current market state.
Args:
actions: List of legal actions available
observation: Current view of the market (your hand, market cards, etc.)
simulate_action_fnc: Function to simulate what happens if you take an action
Returns:
The action you want to take
"""
# Implement your decision logic here
# You can use simulate_action_fnc to look ahead!
for action in actions:
future_state = simulate_action_fnc(action)
# Evaluate this future state...
return best_action
def calculate_reward(self,
old_observation: MarketObservation,
new_observation: MarketObservation,
has_acted: bool,
environment_reward: Optional[float]):
"""
Calculate rewards and update any internal state.
This is called after every turn (yours and your opponent's).
Use it to update value estimates, store experiences, etc.
Args:
old_observation: Market state before the action
new_observation: Market state after the action
has_acted: True if this was your turn
environment_reward: Optional reward from the game (e.g., points scored)
"""
# Update your agent's learning signals
reward = self._compute_reward(old_observation, new_observation)
self.memory.append((old_observation, new_observation, reward))The MarketObservation provides everything an agent needs to make decisions, including:
- the agent’s current hand of goods, representing available resources
- the cards currently in the market, defining the set of immediate trade options
- the number of camels held, which affects both trading capacity and scoring
- the available bonus tokens, indicating potential future rewards
- the current score, reflecting overall progress in the game
- the opponent’s visible information, including their score, camel count, and hand size
One of the best features for teaching is the real-time visualization. The included web UI lets you:
- watch agents compete step by step or at variable speeds
- see the full game state at each turn
- compare different agent strategies visually
- debug agent behavior in real time
This makes it easy to identify where an agent's strategy succeeds or fails, and helps students build intuition about what makes a good trading strategy.
First, clone the repository.
git clone https://github.com/chandra-gummaluru/bazaar-ai.gitRun a game between the built-in agents:
For Linux-Based Systems:
cd bazaar-ai
bash launch-bazaar-aiFor Windows-Based Systems:
cd bazaar-ai
.\launch-bazaar-ai.bat
This will start a local web server and open your browser to the UI. You can select different agents and watch them compete.
Within the agents directory, create a new file in my_agent.py:
from backend.trader import Trader, TraderAction
from backend.market import MarketObservation
class MyAgent(Trader):
def __init__(self, seed, name):
super().__init__(seed, name)
def select_action(self, actions, observation, simulate_action_fnc):
# Start simple - maybe just pick randomly?
import random
return random.choice(actions)
def calculate_reward(self, old_obs, new_obs, has_acted, env_reward):
pass # No learning yetThen test it in the simulator by selecting it from the dropdown menu.
The complete project is open source and available on GitHub:
Whether you're teaching a course on AI, or just want to build a game-playing agent for fun, Bazaar-AI provides an accessible and engaging platform to get started.
Have ideas for improvements or new features? Found a bug? I'd love to hear from you—feel free to open an issue or reach out directly!