Разработка игры Limbo на блокчейне
Limbo — игра где случайное число генерируется в диапазоне от 1.00x до очень высокого значения (теоретически бесконечность). Игрок выбирает target multiplier (например 2x, 10x, 100x), ставит ставку. Если сгенерированное число >= target — выигрыш в target раз. Простая механика с большим диапазоном риска/награды.
Математика
При target multiplier M: вероятность выигрыша = 1/M × (1 - houseEdge).
Target 2x: win_prob = 50% × 0.99 = 49.5%. Реальный payout = 2x. Target 10x: win_prob = 10% × 0.99 = 9.9%. Payout = 10x. Target 1000x: win_prob = 0.1% × 0.99 = 0.099%. Payout = 1000x.
Smart contract
contract BlockchainLimbo is VRFConsumerBaseV2Plus {
uint256 public houseEdge = 100; // 1%
uint256 public maxMultiplier = 1_000_000; // 1,000,000x максимум
struct LimboBet {
address player;
uint256 amount;
uint256 targetMultiplier; // в basis points (20000 = 2.00x)
}
mapping(uint256 => LimboBet) public bets;
event LimboResult(
uint256 indexed requestId,
address player,
uint256 resultMultiplier,
uint256 targetMultiplier,
bool win,
uint256 payout
);
function bet(uint256 targetMultiplier) external payable returns (uint256 requestId) {
require(targetMultiplier >= 10100, "Min target 1.01x"); // минимум 1.01x
require(targetMultiplier <= maxMultiplier * 100, "Too high target");
require(msg.value >= MIN_BET && msg.value <= getMaxBet(targetMultiplier));
requestId = _requestVRF();
bets[requestId] = LimboBet(msg.sender, msg.value, targetMultiplier);
}
function fulfillRandomWords(uint256 requestId, uint256[] calldata randomWords)
internal override
{
LimboBet memory b = bets[requestId];
delete bets[requestId];
// Генерируем multiplier результата
// Используем формулу: result = 100 * MAX / (random % MAX + 1)
// Это создаёт распределение: P(result >= X) = 1/X (равновесие)
uint256 MAX = 1_000_000;
uint256 resultRaw = (randomWords[0] % MAX) + 1;
uint256 resultMultiplier = (MAX * 10000) / resultRaw; // в basis points
// Применяем house edge: казино "обрезает" 1% случаев
// Если resultRaw в нижнем 1% диапазоне — house wins
bool houseTakes = resultRaw > MAX * (10000 - houseEdge) / 10000;
bool win = !houseTakes && resultMultiplier >= b.targetMultiplier;
uint256 payout = 0;
if (win) {
payout = (b.amount * b.targetMultiplier) / 10000;
payable(b.player).transfer(payout);
}
emit LimboResult(requestId, b.player, resultMultiplier, b.targetMultiplier, win, payout);
}
// Максимальная ставка ограничена bankroll / targetMultiplier
function getMaxBet(uint256 targetMultiplier) public view returns (uint256) {
return (address(this).balance * 10000) / targetMultiplier;
}
}
Limbo — простая реализация, 2-3 недели с frontend. Основная работа в frontend: slider для выбора multiplier с real-time отображением вероятности и потенциального выигрыша.







