Adapting the Code - Initial Improvements

What does it take to turn a program into a smart contract? Well, first we need to have an idea of what our program does (see the First Code post). Now we have that, so we can start to shine some light in the dark places.



As I rambled about in Design Considerations, one of the main things we need to think about is how to make sure our code performs well. A big part of this is making sure we don't block our keys.

So let's take a look at all of our interactions (functions) and which keys (objects) they touch:

In the past I've used charts to identify "hot keys", but now I think it's easier to do in a table.

W = Write
R = Read

v0 - MVP Objects

 PlayerCharacterPackTileDungeonDungeon Match
New PlayerW     
New CharacterWW    
Buy PacksW WW  

Open Packs

W WW  
Make DungeonW  WW 
Run Dungeon W RWW

It's obvious that the Player is pretty "hot"; it is being written on almost every operation. This means that a player would not be able to host dungeons and play dungeons simultaneously without having key collisions. Perhaps if our round times are long (2-3 minutes) then this would not be a problem. But what if we have some mega player who has 100 dungeons, or 1,000? Do we want to exclude such a big contributor to our network? No, we don't. So we shouldn't rely on "it'll probably be OK" and deal with this problem now.

v0.1 - Optimize Player

The dividing line I can see is between the creation of assets and using those assets. Let's take a look at how it would look to split the player object apart:

erDiagram PlayerProfile { WalletAddress ExternalAddress string Name int Gold map Characters map Dungeons } PlayerVault { WalletAddress ExternalAddress array Tiles array Packs }
 Player ProfilePlayer VaultCharacterPackTileDungeonDungeon Match
New PlayerW W     
New CharacterW W    
Buy Packs  W WW  

Open Packs

  W WW  
Make DungeonW R  WW 
Run Dungeon  W RWW

That's starting to look better. It's clear that we can now Buy and Open packs at the same time we are running dungeons.

v0.2 - Optimize Dungeon

There's still a bit of ambiguity around the Dungeon though: how often does one "make" a dungeon? Is it every time it's ran? Two options come to mind:

  1. Make the dungeon a long-lived object
    • We assume a dungeon will be ran multiple times before it's edited
    • Mark the tiles as "in use" when they're assigned to a dungeon to prevent over-use of assets
    • Make the listing of a dungeon a separate action, further separate the key space
  2. Make the dungeon a one-time thing
    • We assume a dungeon will only be created once and ran once
    • We still need to track tiles as "in use" during a dungeon match, and will need to read/write all the tiles every time we start the dungeon again

I think Option 1 is a better fit for how dungeons will be used in the game. As a dungeon owner I may fine tune my dungeon from time to time, but otherwise just let it run. As I gather more tiles I can make more dungeons; there's no need for the game to keep throwing tile data around if the dungeon is not being modified.

So this will add a new class:

erDiagram DungeonListing { string Name WalletAddress Owner ObjectStatus Status }
And now the interactions look like this:
 Player ProfilePlayer VaultCharacterPackTileDungeonDungeon ListingDungeon Match
New PlayerW W      
New CharacterW W     
Buy Packs  W WW   

Open Packs

  W WW   
Make DungeonW   WW  
List Dungeon     RW 
Run Dungeon  W RRR/WW

I'm biased, but that's starting to look real nice:

  • The Player's Profile is only edited when making characters or dungeons.
  • The Player's Vault is only edited when making purchases.
  • Dungeons are written once, listed once, and ran many times

Next we will take a look at Key Considerations.