How should I model entities choosing an optimal counterparty in specs?

I am new to Rust and new to coding with an ECS.
I am building a simulated economy, and using it as an opportunity to learn Rust and ECS.
The core idea is that you have all these economic agents (people, food stores, farms, etc) interacting by engaging in transactions (trading food, trading labor etc).

The cycle I want to use is that at each iteration of the main loop

  1. Some entities advertise a passive offer. For example, each food store will advertise the prices and quantities it is willing to trade food at.
  2. Some entities will browse available offers and select an optimal offer to to try and trade with. Optimality can be based on any arbitrary function of the offer such as proximity and price.
  3. Trades are matched with offers in random order for each offerer and are accepted for as long as the offerer has stock to satisfy the trade.

Then Offerers update their offers based on new stock levels or some other information and we loop back.

So what is an effective way to model this? My thoughts so far, focusing on the case of a Person buying Food from a FoodStore.

It seems clear the following components are required

#[derive(Component)]
struct Money(f64);

#[derive(Component)]
struct Food(f64);

I probably need a marker component to identify a Person or a FoodStore

#[derive(Default)]
#[derive(Component, Debug)]
#[storage(NullStorage)]
struct Person;

#[derive(Default)]
#[derive(Component, Debug)]
#[storage(NullStorage)]
struct FoodStore;

It bothers me that these 2 aren't mutually exclusive so that already suggests a design failure.

And I expect I need a system for each of the elements of the above mentioned loop.

Thinking about the first system: setting offers. An offer could, in principle, be a component of a food store.
So the first system will focus on those entities that have FoodStore markers and (maybe) food offers. It then adds a new offer component, or mutates an existing one, or deletes an existing one as deemed necessary.

Moving on to the second system. This will focus on those entities that have Person markers and for each person, it needs to get all available offers and choose the best one. But how does each Person get a list of available food offers?

If FoodOffer is a component attached to a FoodStore then I can't think of how this can be easily accomplished. Should FoodOffer be it's own entity? I don't immediately see how that would help. The only solution I can think of is to have a Billboard resource that FoodStores advertise to and Persons browse. Not sure if this is considered best practice here. I would expect there to be an idiomatic ECS way to model this kind of interaction where one entity choose some other entity from a list of candidate entities.

Any advice would be greatly appreciated.

Disclaimer: I don't use specs and there are multiple ways to do what you want.

To me components represent what an entity can do.
In my opinion Money and Food are too generic and Person and FoodStore too specific.
Money for example: Is it the money the entity currently has? A price? The amount of a transaction?
You'll need other components to make the distinction and it'll complicate your program.

What I'd do is have two components Buyer and Seller. It doesn't solve your exclusivity problem but ECS in general doesn't to allow entities to be both Buyers and Sellers.

If stores can only have a single FoodOffer at a time, making it a component will make things easier. If they can have multiple, something else might be a better idea.

struct FoodOffer {
    price: f64,
    quantity: f64,
}

For each cycle:

  • iterate all Sellers and manage their FoodOffer
  • for all Buyers, iterate all FoodOffer and buy what they want

Also making money a float is likely not a good idea.

This forum is probably not the best place to ask questions on this subject, amethyst discord, rust gamedev discord or other places specialized in ECS or gamedev should get you more answers.