Skip to content

Fruit Market

fruit_market/concentric_rivers is a native PettingZoo port of Melting Pot's fruit_market__concentric_rivers substrate. Sixteen players harvest apples and bananas, eat fruit for role-dependent rewards, manage hunger and stamina, and trade fruit with nearby partners.

Screenshot

Fruit Market Concentric Rivers global state

API

See the generated Fruit Market API reference for signatures and public objects.

Use the family dispatcher:

from mp.fruit_market import env, parallel_env

parallel = parallel_env("concentric_rivers", render_mode="rgb_array")
aec = env("fruit_market__concentric_rivers")

Or import the variant directly:

from mp.fruit_market.concentric_rivers import (
    FruitMarketConcentricRiversConfig,
    parallel_env,
)

config = FruitMarketConcentricRiversConfig(observation_mode="global")
env = parallel_env(config=config)

Agents are named player_0 through player_15.

Actions and observations

The action space is Discrete(25). Actions 0 through 12 are no-op, movement, turning, eating, grappling, and offer cancellation; actions 13 through 24 are the valid apple/banana offer pairs.

Default per-agent observations are:

Key Shape Type
RGB (88, 88, 3) uint8
READY_TO_SHOOT () float64
STAMINA () float64
INVENTORY (2,) int64
MY_OFFER (2,) int64
OFFERS (102,) int64
HUNGER () float64

state() and render_mode="rgb_array" return the global world RGB frame with shape (248, 248, 3). Pass observation_mode="global" to return a global RGB observation for each agent.

Mechanics

Apple farmers harvest apples reliably but value bananas more; banana farmers harvest bananas reliably but value apples more. Trees become unripe after a successful harvest and regrow after 50 frames. Eating fruit resets hunger.

Offers use positive quantities for fruit requested and negative quantities for fruit given. Nearby compatible public offers within radius 4 trade the minimal matching quantities and clear both offers. Invalid offers, including offers the player cannot afford, are hidden from MY_OFFER and OFFERS.

Movement, rivers, and hunger affect stamina. Low stamina can briefly freeze movement. Hold, shove, and pull use a short grappling beam.

Reward strategy and failure modes

The highest rewards come from specialization plus trade. Apple farmers should harvest apples and trade for bananas they value more; banana farmers should do the reverse. Good policies maintain affordable public offers, stay within trade radius of compatible partners, eat before hunger becomes costly, and avoid exhausting stamina in river crossings.

Bad equilibria include autarky, where each role eats only its own low-value fruit; offer spam with unaffordable or incompatible trades; and market freezes where players wait near partners but never post matching quantities. Grappling or river congestion can also create local monopolies that stop fruit from moving between roles.

Playable notebook

Launch the playable notebook with:

uv run marimo run notebooks/fruit_market/concentric_rivers_mo.py

Controls:

  • WASD or arrow keys move the active player.
  • Q/E turn the active player.
  • C/V eat an apple or banana.
  • Shift holds another player.
  • F shoves and R pulls a held player.
  • X or Backspace cancels the current offer.
  • 1-6 choose common offer presets.
  • TAB switches the controlled player.
  • ESC closes the pygame window.