Selaa lähdekoodia

Add fully configurable rollcoin marketplace

Kirk Trombley 4 vuotta sitten
vanhempi
commit
ffe3305c8b
2 muutettua tiedostoa jossa 77 lisäystä ja 9 poistoa
  1. 16 4
      config/secrets.toml.template
  2. 61 5
      src/plugins/rollcoin.py

+ 16 - 4
config/secrets.toml.template

@@ -36,9 +36,21 @@ api_key = "KEY"
 beg_chance = 100
 force_initial = []
 
-[rollcoin.cooldown]
-seconds = 5
+    [rollcoin.cooldown]
+    seconds = 5
 
-[rollcoin.initial]
+    [rollcoin.initial]
 
-[rollcoin.wallets]
+    [rollcoin.wallets]
+
+    [[rollcoin.market.state.buy]]
+    weight=1
+    message=""
+    new_state="state"
+    multiplier=1
+
+    [[rollcoin.market.state.sell]]
+    weight=1
+    message=""
+    new_state="state"
+    multiplier=1

+ 61 - 5
src/plugins/rollcoin.py

@@ -1,4 +1,4 @@
-from random import randint, gauss, shuffle
+from random import randint, gauss, shuffle, choices
 from datetime import datetime, timedelta
 import pickle
 
@@ -33,6 +33,16 @@ class RollcoinBlockchain:
         self.puzzle = None
 
 
+@as_sender_singleton
+class RollcoinGamblingWallet:
+    balance: float = 0.0
+
+
+@as_group_singleton
+class RollcoinMarket:
+    state: str = "neutral"
+
+
 def setup_initial_balances(plugin, db):
     bot = plugin.bot
     bot.logger.info("Setting up rollcoin wallets")
@@ -56,8 +66,8 @@ def setup_initial_balances(plugin, db):
 @with_startup(setup_initial_balances)
 @with_help("Check your balance of Rollcoins")
 @as_plugin
-def balance(wallet_data: RollcoinWallet):
-    return f"You have {wallet_data.balance} Rollcoins"
+def balance(wallet_data: RollcoinWallet, gambling_data: RollcoinGamblingWallet):
+    return f"You have {wallet_data.balance} Rollcoins in your wallet and {gambling_data.balance} Rollcoins in the market"
 
 
 @with_help("Tip someone else some Rollcoins: !tip target amount")
@@ -73,12 +83,15 @@ def tip(msg, db, sender_wallet_data: RollcoinWallet, wallet_cfg: "rollcoin.walle
     except ValueError:
         return RollbotFailure.INVALID_ARGUMENTS.with_reason(f"Amount should be a number - not {raw_amount}")
 
+    if amount <= 0:
+        return RollbotFailure.INVALID_ARGUMENTS.with_reason(f"Amount should be positive")
+
     target_id = wallet_cfg.get(target.lower(), None)
     if target_id is None:
         return RollbotFailure.INVALID_ARGUMENTS.with_reason(f"Could not find wallet-holder {target}")
 
     if sender_wallet_data.balance < amount:
-        return f"Insufficient funds! You need {round(amount - sender_wallet_data.balance, 2)} more Rollcoins. Have you tried to !mine or !beg?"
+        return f"Insufficient funds! You need {round(amount - sender_wallet_data.balance, 2)} more Rollcoins. Have you tried to !mine, !beg, or !gamble?"
     
     target_wallet = db.query(RollcoinWallet).get(target_id)
     if target_wallet is None:
@@ -161,4 +174,47 @@ def beg(wallet_data: RollcoinWallet, cooldown_data: RollcoinBegCooldown, cooldow
     increase = round(abs(gauss(1, 1)), 2)
     wallet_data.balance = wallet_data.balance + increase
     return f"Fine, I've given you {increase} Rollcoins, which brings your balance to {wallet_data.balance}"
-    
+
+
+@with_help("Gamble some Rollcoins")
+@as_plugin
+def gamble(db, msg, wallet_data: RollcoinWallet, gambling_data: RollcoinGamblingWallet, market_data: RollcoinMarket, market_cfg: "rollcoin.market"):
+    # pos moves money wallet -> gambling, neg moves money gambling -> wallet
+    # market has a current state (neutral, bull, bear, boom, bust, collapse, etc.)
+    # after a transfer is made, the market evolves based on
+    #   - direction of transfer (buy vs sell)
+    #   - current market state
+    #   - rng
+    # market enters new state and affects all gambling wallets, multiplying their balances
+    args = msg.arg_list()
+    if len(args) != 1:
+        return RollbotFailure.INVALID_ARGUMENTS.with_reason("Gambling requires exactly one argument: the amount to transfer (can be positive or negative)")
+
+    try:
+        amount = float(args[0])
+    except ValueError:
+        return RollbotFailure.INVALID_ARGUMENTS.with_reason(f"Amount should be a number - not {args[0]}")
+
+    if amount == 0:
+        return RollbotFailure.INVALID_ARGUMENTS.with_reason(f"Amount should be nonzero")
+
+    buying = amount > 0
+    abs_amount = abs(amount)
+    if buying and abs_amount > wallet_data.balance:
+        return f"Insufficient funds! You need {round(abs_amount - wallet_data.balance, 2)} more Rollcoins. Have you tried to !mine, !beg, or !gamble?"
+    elif not buying and abs_amount > gambling_data.balance:
+        return f"Insufficient holdings! You would need {round(abs_amount - gambling_data.balance, 2)} more Rollcoins in the market."
+
+    options = market_cfg[market_data.state]["buy" if buying else "sell"]
+    transition = choices(options, weights=tuple(x["weight"] for x in options))[0]
+    multiplier = transition["multiplier"]
+    market_data.state = transition["new_state"]
+    wallet_data.balance = wallet_data.balance - amount
+    gambling_data.balance = multiplier * (gambling_data.balance + amount)
+
+    for holdings in db.query(RollcoinGamblingWallet
+                            ).filter(RollcoinGamblingWallet.sender_id != gambling_data.sender_id
+                            ).all():
+        holdings.balance = multiplier * holdings.balance
+
+    return f"{transition['message']}\nYour current holdings: {gambling_data.balance}"