veloren_world/civ/
econ.rs

1#![expect(dead_code)]
2
3use super::GenCtx;
4use rand::prelude::*;
5
6pub struct SellOrder {
7    pub quantity: f32,
8    pub price: f32,
9
10    // The money returned to the seller
11    pub q_sold: f32,
12}
13
14pub struct BuyOrder {
15    quantity: f32,
16    max_price: f32,
17}
18
19#[derive(Clone, Debug)]
20pub struct Belief {
21    pub price: f32,
22    pub confidence: f32,
23}
24
25impl Belief {
26    pub fn choose_price(&self, ctx: &mut GenCtx<impl Rng>) -> f32 {
27        self.price + ctx.rng.gen_range(-1.0..1.0) * self.confidence
28    }
29
30    pub fn update_buyer(&mut self, _years: f32, new_price: f32) {
31        if (self.price - new_price).abs() < self.confidence {
32            self.confidence *= 0.8;
33        } else {
34            self.price += (new_price - self.price) * 0.5; // TODO: Make this vary with `years`
35            self.confidence = (self.price - new_price).abs();
36        }
37    }
38
39    pub fn update_seller(&mut self, proportion: f32) {
40        self.price *= 1.0 + (proportion - 0.5) * 0.25;
41        self.confidence /= 1.0 + (proportion - 0.5) * 0.25;
42    }
43}
44
45pub fn buy_units<'a>(
46    _ctx: &mut GenCtx<impl Rng>,
47    sellers: impl Iterator<Item = &'a mut SellOrder>,
48    max_quantity: f32,
49    max_price: f32,
50    max_spend: f32,
51) -> (f32, f32) {
52    let mut sell_orders = sellers.filter(|so| so.quantity > 0.0).collect::<Vec<_>>();
53    // Sort sell orders by price, cheapest first
54    sell_orders.sort_by(|a, b| {
55        a.price
56            .partial_cmp(&b.price)
57            .unwrap_or_else(|| panic!("{} and {}", a.price, b.price))
58    });
59
60    let mut quantity = 0.0;
61    let mut spent = 0.0;
62
63    for order in sell_orders {
64        if quantity >= max_quantity || // We've purchased enough
65            spent >= max_spend || // We've spent enough
66            order.price > max_price
67        // Price is too high
68        {
69            break;
70        } else {
71            let q = (max_quantity - quantity)
72                .min(order.quantity - order.q_sold)
73                .min((max_spend - spent) / order.price);
74            order.q_sold += q;
75            quantity += q;
76            spent += q * order.price;
77        }
78    }
79
80    (quantity, spent)
81}