More work on the megadungeon bot
Today I've been doing more work on the Mörk Borg megadungeon bot. A core part of megadungeon play is in managing equipment. Since I want to do all character management inside the bot, I decided that I need an inventory management system that lets players move items around. The next logical step was to build a shop into the bot. As well as letting players spend their starting silver and equip themselves as they see fit, I also figured this would be a good way to let them sell items that they pull out of the dungeon and convert them into silver. I'm not sure how this interacts with scoring yet, but I'll cross that bridge when I come to it.
The result of today's development session is that players can now buy and sell items, the shop has a dynamic back room inventory system, and I've implemented consumables with limited uses, scroll parsing, and randomized starting equipment. I'll go over each of these in a little more detail below.
1. Complete Shop System
The shop system is now fully functional with a fairly complex inventory management system built on the back of a couple of different databases. There's a master catalogue of all available items at the start of the game, a shop inventory that functions as a sort of "back room" to track overall inventory for the shop, a shop stock database that keeps track of inventory on the "shop floor", and a config database that lets me adjust things like how much money the shop is holding, how many SKUs are on display on the shop floor at any given time, and the chances that items of different rarities will actually appear for sale.
I also have tracking for unique items that logs who first sold the item to the shop and who first bought it.
Here's a bullet point overview of some key features:
- Three quantity types:
- Infinite: Always available
- Limited: Finite quantity with restocking
- Unique: One-time items that track who bought them
- Hybrid inventory system:
- Items sold by players go to back room
- Server owner (me) manually restocks shop floor from back room
- Max shop capacity configurable (default: 25 lines)
- Rarity-based restocking:
- Common: 70% chance to appear
- Uncommon: 40% chance
- Rare: 15% chance
- Unique: 5% chance
- All percentages configurable by server owner
Player Commands:
/shop category:[all]- View shop floor inventory (filterable by category)/buy item_name:X- Purchase items from shop/sell slot:X- Sell items back to shop, with the price you get calculated as a percentage of the base value modified by your Presence
Server Owner Commands:
/set_shop_channel channel:#channel- Designate shop location/set_shop_budget budget:X- Set shop's starting silver/shop_balance- View current shop balance/shop_restock- Restock shop floor from back room (respects capacity and rarity)/shop_clear- Clear shop floor, return items to back room/shop_inventory show_all:[True/False]- View back room inventory/shop_sold_uniques- View log of unique items sold/shop_config- View shop configuration/shop_set_lines max_lines:X- Adjust shop floor capacity/shop_set_rarity rarity:X chance:Y- Adjust restock probabilities/shop_add_item item_name:X quantity:Y- Manually add item to floor/shop_add_database_item- Add new item to master database/shop_edit_item- Edit existing database item/shop_remove_item- Remove item from database
2. Consumables System
Items can now have limited uses with automatic tracking. I feel like this is currently a little janky and might need some finessing, but it works and that's the important thing.
Features:
- Items have
current_usesandmax_usesfields - Uses can be modified by character stats (e.g., "Presence + 4 uses")
- Auto-removes items when uses reach zero
/use slot:Xcommand to consume items- Displays remaining uses in inventory
Example Items:
- Medicine Box: Presence + 4 uses (heals d6 HP, stops bleeding/infection)
- Poison: 3 uses (Toughness DR12 or d10 damage)
- Lantern Oil: Presence + 6 uses (burns for Presence + 6 hours)
With most of these items I'm not actually implementing any mechanical effects of using them other than depleting the inventory, because that would be silly. Instead it just prints the effect, which is stored as flavour text, and players and GMs can apply the results as you would when running the game normally. Here's a quick example of use:
- Player uses
/use slot:5on Medicine Box - Bot displays: "PlayerName used Medicine box! Effect: Stops bleeding/infection and +d6 HP. Medicine box has 3/4 uses remaining."
- Player rolls a d6 (just types
roll 1d6) - GM applies the effect manually using
/heal - When uses reach 0, item automatically removed from inventory
3. Smart Scroll System
Scrolls are in the game now. They don't appear in the shop by default but can be generated at character creation or when doing Getting Better with the /better command, and can be sold back into the shop.
During chargen the bot initially generates a result of either "Random Unclean Scroll" or "Random Sacred Scroll". Individual scrolls are defined as tuples (text, price, rarity), and automatic parsing extracts the scroll name and effect and inserts it into the player's inventory. These can then be used like any other item - expended, transferred to other players, or sold back into the shop.
The benefit of doing it this way is that I can always add new scrolls to the database during the game that will then organically filter through into the economy without me having to restart the bot.
These also tie into the...
4. Starting Items System
New characters now receive randomized starting equipment:
Structure:
- Two CSV tables:
starting_items_table1.csvandstarting_items_table2.csv - Characters receive one random item from each table (if inventory space allows)
- Full shop item format (price, rarity, quantity type, etc.)
- Items can include "Random Sacred Scroll" or "Random Unclean Scroll"
- Scrolls automatically parsed when rolled
Character Creation Flow:
- Character created with starting weapon in slot 1
- Random item from table 1 added to slot 2
- Random item from table 2 added to slot 3
- If scroll rolled, parsed and stored with proper name/effect
- Displayed in character creation message
5. Armour Swapping System
Players can now manage armour as inventory items, swapping pieces out and buying and selling it.
Commands:
/equip_armor slot:X- Equip armour from inventory/unequip_armor- Remove armour to inventory
Features:
- Buying armour auto-equips it, old armor goes to inventory
- Armour tracks tier and max tier
- Occupies inventory slots when unequipped
- Heavy armour uses 2 slots, light/medium use 1 slot
- Auto-swapping when purchasing new armour
6. Shield Mechanics
Shields in Mörk Borg allow you to sacrifice them in order to prevent all damage. They are a consumable item, functionally. I could probably have just made use of my existing item consumption system for them, or else just instruct players to unequip/drop shields when they're used, but I liked the idea of having a bespoke /block command. So I built one.
/block Command:
- Only usable while on delve
- Must have shield equipped
- Public announcement of shield sacrifice
- Shield removed from inventory and unequipped
7. Misery Tracking
The /refresh command now tracks Miseries:
- Rolls d10 on each refresh
- 1 in 10 chance of Misery occurring
- Tracks total Miseries rolled across campaign
- Displays count in refresh results
I might add something to my configuration commands to let me change the die size rolled for the Miseries, just to make the bot a little more functional.
New Commands:
/misery_count- View total Miseries rolled (owner only)/set_misery_count count:X- Adjust Misery count (owner only)
8. Help Command
Role-based command documentation:
/help category:[all] Command:
- Shows only commands available to the user
- Regular players: see 15 player commands
- GMs: see player + 11 GM commands
- Server owner: see all commands
- Optional filtering by category
- Ephemeral responses (private)
- Auto-splits long messages
Improvements
I implemented a few improvements to old systems while I was working on these new ones, too.
- Inventory display now shows uses for consumables
- Ammo automatically added to weapons when purchased
- Error messages more descriptive
Current Command Count
I said on Bluesky that this bot currently has over 50 working commands but I was wrong. There are 39.
Total Commands: 39
Player Commands (15):
- Character:
/create_character,/character,/retire - Economy:
/balance,/transfer,/better,/repair - Combat:
/omen,/power,/shoot,/block,/use - Inventory:
/inventory,/equip,/unequip,/equip_armor,/unequip_armor,/give_item - Shop:
/shop,/buy,/sell - Rolling:
roll XdY [stat](message-based)
GM Commands (11):
- Character Management:
/set_stat,/kill,/view_inventory,/add_item,/remove_item - Combat:
/damage,/heal,/damage_armor - Delves:
/delve_start,/delve_end,/delve_add_player
Server Owner Commands (13):
- Configuration:
/set_better_cost,/toggle_cooldowns,/set_creation_channel,/clear_creation_channel,/pause - Delve:
/set_delve_log,/clear_delve_log - GM:
/make_gm,/fire_gm - Shop:
/set_shop_channel,/set_shop_budget,/shop_balance,/shop_restock,/shop_clear,/shop_inventory,/shop_sold_uniques,/shop_config,/shop_set_lines,/shop_set_rarity,/shop_add_item,/shop_add_database_item,/shop_edit_item,/shop_remove_item - System:
/refresh,/misery_count,/set_misery_count - Help:
/help
Remaining Roadmap
Reporting Commands
These are a crucial part of the bot but I don't intend to implement them until everything else is working as intended.
/delve_report delve_id:X- Detailed report of specific delve/player_stats player:@user- Player statistics/gm_stats gm:@user- GM statistics/server_stats- Overall server statistics
Utility Commands
/list_characters- View all active characters/view_character player:@user- GM views any character sheet
Dungeon Treasure System
This is a really big one. Since every GM is going to be running the same megadungeon and since we have a robust inventory system, it makes sense that GMs should be able to award treasure from the dungeon directly into player inventories. The original version (i.e. the /add_item command) will allow GMs to add items to a player's inventory but they have to type in values for each column of the item tracking CSV, and that's slow and tedious.
My idea for this is that, once I've written the dungeon, I'll implement a treasure database. Each room of the dungeon will be represented and will contain every lootable item. GMs will then be able to pull up the treasure for the room they're currently in with a slash command, and assign that treasure to players. If players have to drop items to make inventory space, those items will go into the dungeon room treasure table. This means that treasure locations will persist across delves and GMs won't need to worry about awarding duplicates etc.
Alongside this I probably need to build some procedures for dungeon restocking, although I guess I can just manually restock rooms as part of my upkeep while the game is ongoing. I should also implement a similar treasure distribution system for pocket treasures from wandering monsters, too.
The final thing that I should probably do is to split this into a GM bot and a player bot. Right now players can see all of the GM and server owner commands in Discord even though they can't use them, and aside from anything else that's just ugly. It also means that it can be hard to find the command you want to use. So at some point I may see about splitting it into two bots that talk to the same databases, which I think should be fairly straightforward.
At the time of writing this the bot is feature-complete for basic gameplay with economy, combat, inventory, and progression systems all functional. Future work focuses on polish, reporting, and some advanced features specific to Return Of The Troll King. At some point soon I'll probably drop it into the public Loot The Room discord server and run some test games just to see how it actually plays. I also find myself wondering how easily I could convert this into a bot for running A Dungeon Game and I think it should be fairly straightforward.
This is by far the largest Python project I've worked on but it's actually been fairly straightforward so far - certainly much easier than the hex map generator I was working on earlier this year. At its heart it's just a database application, but it's one that I'm really proud of.