pythonrandomcalculatorprobability

Simple Scaling Probability With Outliers in Python


I'm creating a virtual auction game, and I need more complex NPC behavior than I have now. Basically, every item has a base price (bp), and the starting bid (sb) for that item will be calculated with this range (or something very similar): 0.8bp <= sb <= 1.1bp. The opposing NPC bidders need to judge how reasonable the current bid is, compared to the base price and/or starting value, and, with some outlying behavior (i.e. betting when it seems a little irrational), bid reasonably on the current item. Put simply, it should bid aggressively on the item when the bid is lower or around the base price, and frugally bid on the item if it's high above the base price, or just give up.

The issue is, I really have no idea how to do this. Not only that, this is going to mainly be run on a TI-84 Plus CE calculator, so the external libraries and modules have to be pretty limited (essentially just random). It'd be great if you attach a brief (or long) explanation of any formulas/code you provide, because I'd love to learn more about this.


Solution

  • Here's an answer for you to get started:

    import random
    from dataclasses import dataclass
    
    
    @dataclass
    class Npc:
        i: int
        alpha = 2
        beta = 0.25
        bid_percent_increase_min = 1.01
        bid_percent_increase_max = 1.03
        percent_thresh_for_mandatory_bid = 0.75
    
        def bet(self, cb, bp):
            r = (
                random.gammavariate(self.alpha, self.beta)
                + self.percent_thresh_for_mandatory_bid
            )
            if r >= cb / bp:
                return (
                    random.uniform(
                        self.bid_percent_increase_min, self.bid_percent_increase_max
                    )
                    * cb
                )
            return 0
    
    
    @dataclass
    class Auction:
        item_name: str
        bp: float
        npcs: int = 5
        starting_bid_percent_min = 0.8
        starting_bid_percent_max = 1.1
    
        def __call__(self, *args, **kwargs):
            # 0.8bp <= sb <= 1.1bp
            cb = (
                random.uniform(self.starting_bid_percent_min, self.starting_bid_percent_max)
                * self.bp
            )
            print(f"Auction starting for {self.item_name.title()} (BP: ${self.bp:.2f})")
            print(f"\tStarting bid: ${cb:.2f}")
            bettors = [Npc(i) for i in range(self.npcs)]
            random.shuffle(bettors)
            while len(bettors) > 1:
                for j, bettor in enumerate(bettors):
                    b = bettor.bet(cb, self.bp)
                    if b > cb:
                        print(
                            f"\t\tCurrent bid: ${cb:.2f} | Bettor {bettor.i} bids ${b:.2f}"
                        )
                        cb = b
                    else:
                        print(f"\tBettor {bettor.i} left")
                        bettors.pop(j)
                random.shuffle(bettors)
            print(
                f"Winning bid: ${cb:.2f} | Bettor {bettors[0].i} won the {self.item_name.title()}!"
            )
    
    
    if __name__ == "__main__":
        items = [
            ("apple", 1.30),
            ("water bottle", 9.99),
            ("tv", 189.99),
            ("laptop", 1499.99),
        ]
        for item_name, bp in items:
            Auction(item_name, bp)()
            print("\n")
    

    Example Output:

    Auction starting for Apple (BP: $1.30)
        Starting bid: $1.23
        Bettor 0 left
            Current bid: $1.23 | Bettor 2 bids $1.25
            Current bid: $1.25 | Bettor 3 bids $1.28
            Current bid: $1.28 | Bettor 4 bids $1.30
            Current bid: $1.30 | Bettor 1 bids $1.32
        Bettor 2 left
        Bettor 4 left
            Current bid: $1.32 | Bettor 1 bids $1.34
            Current bid: $1.34 | Bettor 3 bids $1.35
            Current bid: $1.35 | Bettor 1 bids $1.39
            Current bid: $1.39 | Bettor 3 bids $1.43
            Current bid: $1.43 | Bettor 1 bids $1.47
        Bettor 3 left
    Winning bid: $1.47 | Bettor 1 won the Apple!
    
    
    Auction starting for Water Bottle (BP: $9.99)
        Starting bid: $10.63
        Bettor 0 left
            Current bid: $10.63 | Bettor 2 bids $10.77
            Current bid: $10.77 | Bettor 3 bids $11.00
        Bettor 4 left
            Current bid: $11.00 | Bettor 1 bids $11.27
            Current bid: $11.27 | Bettor 2 bids $11.50
            Current bid: $11.50 | Bettor 3 bids $11.75
        Bettor 1 left
            Current bid: $11.75 | Bettor 3 bids $11.92
            Current bid: $11.92 | Bettor 2 bids $12.20
            Current bid: $12.20 | Bettor 3 bids $12.36
        Bettor 2 left
    Winning bid: $12.36 | Bettor 3 won the Water Bottle!
    
    
    Auction starting for Tv (BP: $189.99)
        Starting bid: $171.10
            Current bid: $171.10 | Bettor 0 bids $174.12
            Current bid: $174.12 | Bettor 1 bids $177.67
            Current bid: $177.67 | Bettor 2 bids $180.92
            Current bid: $180.92 | Bettor 3 bids $183.20
            Current bid: $183.20 | Bettor 4 bids $186.78
        Bettor 0 left
            Current bid: $186.78 | Bettor 2 bids $189.89
        Bettor 3 left
            Current bid: $189.89 | Bettor 1 bids $192.56
        Bettor 2 left
            Current bid: $192.56 | Bettor 1 bids $196.38
            Current bid: $196.38 | Bettor 4 bids $200.25
            Current bid: $200.25 | Bettor 1 bids $206.24
        Bettor 4 left
    Winning bid: $206.24 | Bettor 1 won the Tv!
    
    
    Auction starting for Laptop (BP: $1499.99)
        Starting bid: $1404.03
        Bettor 0 left
            Current bid: $1404.03 | Bettor 2 bids $1431.79
            Current bid: $1431.79 | Bettor 3 bids $1450.59
            Current bid: $1450.59 | Bettor 4 bids $1491.00
            Current bid: $1491.00 | Bettor 1 bids $1508.36
        Bettor 2 left
            Current bid: $1508.36 | Bettor 4 bids $1550.88
            Current bid: $1550.88 | Bettor 1 bids $1589.62
            Current bid: $1589.62 | Bettor 3 bids $1613.55
            Current bid: $1613.55 | Bettor 4 bids $1650.92
        Bettor 1 left
            Current bid: $1650.92 | Bettor 4 bids $1684.26
            Current bid: $1684.26 | Bettor 3 bids $1715.78
            Current bid: $1715.78 | Bettor 4 bids $1750.79
        Bettor 3 left
    Winning bid: $1750.79 | Bettor 4 won the Laptop!
    

    Here I used the gamma distribution, the PDF looks like this (offset by 0.75):

    enter image description here

    An NPC makes a bet if a random value drawn from this distribution is greater than (current bid / base price). What this means:

    You can obviously play with the alpha and beta values along with some of the other parameters to better suit your particular situation.