Good question. The simulation logic is deterministic with the random seed created at race time, and the entire thing runs on the backend in the canister. The entire project is open source, and is on prometheus so you can verify the wasm matches the code: Prometheus Protocol | App Store
The simulation takes the bots stats which are a combination of base stats which are derived from the nfts properties (check market to see all bots derived stats). For each stat, the bots properties are derived from the the NFTs properties (wings, body, legs, etc.), where rarer and faster values are scored higher. So turbo jet wings are very fast and butterfly wings are a bit slower. Here is function to derive accel from wings:
// Wings contribution to acceleration (20% weight)
function categorizeWingsForAccel(wings) {
if (!wings) return 40;
const lower = wings.toLowerCase();
// Legendary (75-80): Only 1-of-1s
if (contains(lower, 'master gold') || contains(lower, 'golden triple') ||
contains(lower, 'black double angel')) {
return 62 + (hashText(wings) % 6);
}
// High (67-70): Massive engines, power cells - highest thrust
else if (contains(lower, 'massive engine') || contains(lower, 'power cell')) {
return 57 + (hashText(wings) % 4);
}
// Medium-High (55-58): Rockets, jets, triangle up - quick acceleration
else if (contains(lower, 'rocket') || contains(lower, 'jet') || contains(lower, 'triangle up')) {
return 51 + (hashText(wings) % 4);
}
// Medium (49-54): Ultimates, terminators, double wings
else if (contains(lower, 'ultimate') || contains(lower, 'terminator') || contains(lower, 'double')) {
return 47 + (hashText(wings) % 6);
}
// Medium-Low (43-48): Butterfly, angels, antennas - moderate flap acceleration
else if (contains(lower, 'butterfly') || contains(lower, 'angel') ||
contains(lower, 'antenna') || contains(lower, 'bear')) {
return 42 + (hashText(wings) % 6);
}
// Low (37-42): 8 bit, bird, decorative
else if (contains(lower, '8 bit') || contains(lower, 'bird') ||
contains(lower, 'bee') || contains(lower, 'bone')) {
return 41 + (hashText(wings) % 6);
}
// Very Low (31-36): Blank, inflatable - no thrust
else {
return 40 + (hashText(wings) % 6);
}
}
Base stats can be upgraded permanently in game using ‘parts’ that you can scavenge for. The more upgrades you get the harder they become to get, so there is about a +10 cap per stat before it starts becoming very difficult to succeed.
If your bot is at 100% charge and 100% condition then its stats are at 100% (base + upgrade). However, if they are depleted then your stats are reduced.
So once the simulation has all the bots current stats (with penalties and bonuses) then it generates a random seed, and plugs in the stats and random seed into the simulator. This makes it deterministic and you can play back the simulations and even run your own simulation to verify that they match (we have a simulator on the frontend and one on the backend and verify that they both match up, though the one on the backend is the source of truth and is used for the results that are used for prize distribution and betting ofc). The simulation adds a bit of randomness to all of the bots (to simulate race day conditions), and then during the simulation each segment of track uses the seed to add randomness to the segments time, weighted by condition. So lower condition will have more unlucky streaks and hit some -5% speed segments more often then a perfectly maintained bot.
I probably missed something, let me know if I did so I can add the info to the website.
In terms of platform fees, $0 of the pot goes to the platform fees. atm, 2% of the betting pool goes to cycles and upkeep, hopefully betting volume can increase so that covers the fees. You can see the financial details here: PokedBots Racing.