Игры Профиль Чат ? Бонус Еще
Режим
Server seed
Client seed
Salt
+

Перевод сидов в байты


Перевод байтов в числа


Перевод чисел в результат


Доказуемая честность


Основополагающая концепция доказуемой честности заключается в том, что игроки имеют возможность доказать и подтвердить, что результаты их игр являются честными и не подвергались манипуляциям со стороны сайта. Это достигается за счет использования так называемой схемы обязательства, где случайные результаты игр генерируются на основе набора параметров, часть которых известна игроку перед началом раунда. Схема обязательства используется, чтобы гарантировать, что игрок оказывает влияние на все полученные результаты, вместе с тем параметры подобраны таким образом, чтобы игрок не мог предугадать результат той или иной игры наперед, но всегда мог детерминированным образом подтвердить факт честности данной игры.

Параметры генератора случайных чисел


В предложенной системе в качестве входных параметров генератора случайных чисел используется следующий набор из четырех параметров

Server seed

Серверный сид генерируется нашей системой и представляет собой 32 байта, представленные в виде 64-символьной строки. Для режимов, в которых в одном раунде участвует только один игрок, у игрока есть возможность запросить у системы генерацию нового серверного сида, новое значение которого будет сразу же показано. К этим режимам относятся:

  • Mines
  • Dice
  • Overgo
  • Tower
  • Slot
  • Plinko

Для режимов, в которых в одном раунде участвуют несколько игроков, у отдельного игрока нет возможности запросить у системы генерацию нового серверного сида (это вызвано тем, что системе неясно, запрос какого из игроков удовлетворить), однако гарантией честности в данных режимах является тот факт, что серверный сид является постоянным, то есть не меняется от раунда к раунду. В качестве значения серверного сида взят заранее посчитанный хеш определенного bitcoin-блока. Режимы и соответствующие им постоянные серверные сиды приведены ниже:

Client seed

Клиентский сид принадлежит игроку и используется для того, чтобы игрок имел возможность оказывать влияние на генерируемые числа. Изначально клиентский сид генерируется системой при регистрации на сайте, однако в любой момент у пользователя есть возможность сменить свой клиентский сид (обратите внимание, что, в отличие от серверного сида, есть возможность ввести значение желаемого клиентского сида). Для режимов, в которых в одном раунде участвует только один игрок, в качестве клиентского сида используется пользовательский клиентский сид. Эти режимы приведены ниже:

  • Mines
  • Dice
  • Overgo
  • Tower
  • Slot
  • Plinko

Для режимов, в которых в одном раунде участвуют несколько игроков, в качестве клиентского сида не может использоваться пользовательский клиентский сид (это вызвано тем, что системе неясно, сид какого из игроков использовать), однако гарантией честности в данных режимах является тот факт, что клиентский сид является постоянным, то есть не меняется от раунда к раунду. В качестве значения клиентского сида взят заранее посчитанный хеш определенного bitcoin-блока. Режимы и соответствующие им постоянные клиентские сиды приведены ниже:

Salt

Поскольку серверный сид и клиентский сид постоянны и известны пользователю, параметр salt (соль) используется в схеме для того, чтобы получать разные результаты с одной и той же парой client seed + server seed. Соль представляет собой случайные 32 байта, представленные в виде 64-символьной строки. Данный параметр уникален для каждого раунда и недоступен игроку перед началом игры, однако отображается в конце игры (так называемая фаза раскрытия в схеме обязательства).

Cursor

Генератор случайных чисел, используя в качестве входных параметров server seed, client seed и salt, генерирует случайные 64 байта, представленные в виде 128-символьной строки. Эта строка используется для генерации 8 случайных чисел. Однако некоторые режимы требуют генерации большего количества чисел. Для этого вводится дополнительный параметр cursor, который изначательно равен 0 и увеличивается на единицу каждый раз, когда необходимо сгенерировать очередные 8 чисел в рамках одного раунда. Режимы, которые используют больше одного курсора:

  • Mines (3 курсора)
  • Tower (5 курсоров)
  • Slot (от 1 до 180 курсоров)
  • Plinko (от 2 до 200 курсоров)

Режимы, которые используют ровно один курсор:

  • Dice
  • Double
  • x50
  • Jackpot
  • Crash
  • Overgo

Генератор случайных чисел


Генерация случайных байт на основе входных параметров осуществляется с использованием функций HMAC-SHA512 и SHA256

bytes = HMAC-SHA512(SHA256(server_seed:salt), client_seed:cursor)

Результатом генерации являются случайные 64 байта, которые затем делятся на 8 блоков по 8 байт, и каждый блок используется для генерации случайного числа в диапазоне [0, 1). Алгоритм конвертации блока в число приведен в разделе "Реализация", а также графически демонстрируется при проверке игры.

Батарея тестов Dieharder


Батарея тестов Dieharder — это набор статистических тестов для измерения качества генератора случайных чисел. Она состоит из множества тестов (включая набор тестов Diehard и набор тестов NIST Test Suite), которые вместе рассматриваются как один из наиболее строгих существующих наборов тестов. Мы сгенерировали 1 миллиард случайных чисел с помощью вышеприведенного генератора и протестировали этот набор с помощью Dieharder со следующими опциями

dieharder -g 202 -f ./rng_output_test_random_CS -a |& tee -a output_dh_random_CS.txt

Для большей статистической значимости мы запустили тест дважды на разных наборах. Результаты тестирования показывают, что приведенный генератор случайных чисел действительно генерирует несмещенные случайные последовательности, в которых отсутствуют статистически значимые закономерности. Отчеты в виде текстовых файлов доступны по ссылкам:
output_dh_random_CS_1.txt
output_dh_random_CS_2.txt

Генерация случайных чисел


Для любого раунда, client seed, server seed, salt и cursor служат единственными входными параметрами генератора. Генератор преобразует эти параметры в последовательность случайных байтов с помощью хеш-функций HMAC-SHA512 и SHA256, используя свойство лавинного эффекта

function seedsToBytes(serverSeed, clientSeed, salt, cursor) {
    // SHA-256 calculation
    const hmacKey = createHash(serverSeed + ":" + salt);
    const hmacMessage = clientSeed + ":" + cursor;
    // HMAC calculation
    return createHmac(hmacKey, hmacMessage);
}

Перевод байтов в числа


Результатом работы генератора являются 64 случайных байта (128-символьная строка), которые разбиваются на 8 блоков по 8 байт каждый, и каждый блок используется для получения одного числа в интервале [0, 1) с помощью нижеприведенного алгоритма.

function numbersFromBytes(bytes) {
    for (let t = 0; t < 8; t++) {
        let value = 0;
        let pw = 256;
        for (let i = t * 8; i < t * 8 + 8; i++) {
            value += bytes[i] / pw;
            pw *= 256;
        }
        result.push(value);
    }
    return result;
}

Генерация результата Mines


Для генерации результата в режиме Mines требуется 24 случайных числа в интервале [0..1), поэтому генерируется 3 массива из 8 чисел, которые затем объединяются в один массив, называемый индексным. Данный массив используется для выбора позиций мин на поле с помощью алгоритма Фишера-Йетса

// numbers - index array
function minesShuffling(numbers, minesCount) {
    // Initial array
    let range = [];
    // Resulting array
    let permutation = [];
    for (var i = 0; i <= 24; i++) range.push(i);
    for (var i = 0; i < numbers.length; i++) { 
        let index = Math.floor(numbers[i] * range.length);
        permutation.push(range.splice(index, 1)[0]);
    }
    return permutation;
}

Генерация результата Tower


Для генерации результата в режиме Tower требуются 40 случайных чисел в интервале [0..1), поэтому генерируется 5 массивов из 8 чисел, которые затем объединяются в один массив, называемый индексным. Затем этот массив разбивается на 10 подмассивов из 4 элементов, и каждый подмассив используется для генерации перестановки в соответствующем ряду башни с помощью алгоритма Фишера-Йетса

// numbers - index array
function minesShuffling(numbers, minesCount) {
    let field = [];
    for (var i = 0; i < 10; i++) {
        // Initial array
        let range = [];
        // Resulting array
        let permutation = [];
        for (var j = 0; j <= 4; j++) range.push(j);
        for (var j = 0; j < 4; j++) {
            permutation.push(range.splice(numbers[i * 4 + j], 1)[0]);
        }
        field.push(permutation);
    }
    return field;
}

Генерация результата Slot


Для генерации одного вращения в режиме Slot требуются 5 случайных чисел в интервале [0..1), поэтому генерируется 1 массив из 8 чисел, из которых берутся первые 5, которые преобразуются во вращения каждого барабана с помощью умножения на его длину по следующему алгоритму

// numbers - index array
function slotSpin(numbers) {
    let spin_positions = [];
    for (var i = 0; i < 5; i++) {
        spin_positions.push(Math.floor(numbers[i] * (i == 4 ? 41 : 30)))
    }
    return spin_positions;
}

Массив spin_positions содержит позиции символов в центральном ряду, таблица соответствия номеров символам приведена на странице "Проверить игру". Остальные символы на барабане определяются соседями центральных символов в их столбцах. Если центральный символ является первым (или последним) в колонке таблицы, его верхний (или нижний) сосед является последним (или первым) символом из данного столбца.

Генерация результата Plinko


Для генерации номера выигрышной корзины в режиме Plinko требуются, в зависимости от количества пинов, от 8 до 16 случайных чисел в интервале [0..1), поэтому генерируется 2 массива из 8 чисел, которые затем объединяются в один. Из данного массива берутся первые n чисел, где n - количество пинов. Полученный массив преобразуется следующим образом: если элемент массива больше 0.5, он заменяется на 1, иначе он заменяется на 0. Номер выигрышной корзины равен сумме всех элементов преобразованного массива.

// numbers - array of n elements in [0..1)
function plinkoBucket(numbers) {
    return numbers.map((number) => Math.floor(number * 2)).reduce((acc, item) => acc + item, 0);
}

Полученное значение принадлежит биномиальному распределению, которое является математической моделью доски Гальтона.

Генерация результата Dice


Для генерации результата в режиме Dice требуется 1 случайное число в интервале [0..1), которое затем переводится в результат Dice в интервале [0..100] по следующему алгоритму.

// number has interval [0..1)
function diceOutcome(number) {
    return Math.floor(number * 10001) / 100;
}

Генерация результата Double


Для генерации результата в режиме Double требуется 1 случайное число в интервале [0..1), которое затем переводится в сектор колеса в интервале [0..14] по следующему алгоритму.

// number has interval [0..1)
function doubleOutcome(number) {
    return Math.floor(number * 15);
}

Генерация результата Jackpot


Для генерации результата в режиме Jackpot требуется 1 случайное число в интервале [0..1), которое затем переводится в выигрышный билет путем арифметического умножения на общее число билетов, округленного вниз, с поправкой на единицу (поскольку нумерация билетов начинается с 1).

// number has interval [0..1)
function jackpotOutcome(number, ticketsCount) {
    return Math.floor(number * ticketsCount) + 1;
}

Генерация результата Crash


Для генерации результата в режиме Crash требуется 1 случайное число в интервале [0..1), которое затем переводится в коэффициент Crash, имеющий экспоненциальное распределение, по следующему алгоритму.

// number has interval [0..1)
function crashOutcome(number) {
    return max(1, 1000000 / (Math.floor(number * 1000000) + 1) * (1 - 0.05)).toFixed(2);
}

Генерация результата Overgo


Для генерации результата в режиме Overgo требуется 1 случайное число в интервале [0..1), которое затем переводится в коэффициент Overgo, имеющий экспоненциальное распределение, по следующему алгоритму.

// number has interval [0..1)
function overgoOutcome(number) {
    return max(1, 1000000 / (Math.floor(number * 1000000) + 1) * (1 - 0.03)).toFixed(2);
}

Генерация результата x50


Для генерации результата в режиме x50 требуется 1 случайное число в интервале [0..1), которое затем переводится в сектор колеса в интервале [0..53] по следующему алгоритму.

// number has interval [0..1)
function doubleOutcome(number) {
    return Math.floor(number * 54);
}
Онлайн чат
Quiz
Приз:
дал правильный ответ:
Max Tikhy
Ну, сольет это факт, главное что он пытался
Max Tikhy
Хахаха ебать чат во что превратился
Andrey Chugunov
чё тут?
Yan Berezin
А на зуму есть какой нибудь промо
Max Tikhy
Andrey Chugunov, всё сразу
Max Tikhy
Yan Berezin, лучше сходи поработай, закинь бабок и кайфуф мой тебе совет
Max Tikhy
Кайфуй
Vitaly Kotenev
А лудчше на эти бабки покуражиться
Vitaly Kotenev
И не кидать ни куда чисто в реале оторваться)
Max Tikhy
Там типа жёстко побрило на краше...
Max Tikhy
Зря он вывел, надо было держать
Vitaly Kotenev
Да там держать начнёшь тебя зразу хлопнут
Max Tikhy
Факт
Max Tikhy
Но хоть попытается
Vitaly Kotenev
Еденицам везёт
Vitaly Kotenev
Но они наверняка создатели
Vitaly Kotenev
Этого сайта
Vitaly Kotenev
Чисто для народа показуха
Max Tikhy
Жаль я в эти "единицы" не вхожу, эхх....
Vitaly Kotenev
Ну да там филки крутятся
Egor Safin
мне за все время один раз повезло бонуска дала 1600 рублей и все теперь сайт сожрал 5к уже
Vitaly Kotenev
Вот за ночь просто трёшку оставил эта последний капля была))
ウィッチブレイド 空気のような悲しみ
так не депай
ウィッチブレイド 空気のような悲しみ
в чем проблема
ウィッチブレイド 空気のような悲しみ
сам депаешь сам проебываешь
Max Tikhy
Egor Safin, хах, я каждый день покупаю бонусам за 25-50к монет, они даже на половину не окупаются
ウィッチブレイド 空気のような悲しみ
если ты думаешь что этот сайт сдеалан для поднимания денег, то ты ошибаешься
ウィッチブレイド 空気のような悲しみ
это просто развлечение
Denis Ivanov
ウィッチブレイド 空気のような悲しみ, ну ебать ты умный
Max Tikhy
Зато бонуска за 1600 монет даёт 5-6к
Denis Ivanov
Нобелевку тебе за ум
Vitaly Kotenev
Конечно сюда ненадо ложить не рубля
Max Tikhy
ウィッチブレイド 空気のような悲しみ, гений в чате
ウィッチブレイド 空気のような悲しみ
да
Max Tikhy
Сайт должен хоть что то давать и привлекать
ウィッチブレイド 空気のような悲しみ
только олухи депают сюда ласт деньги
Egor Safin
почему так много умников в чате у которых тем временем ранг за 10к+ депа
Max Tikhy
А он делает наоборот
Max Tikhy
ウィッチブレイド 空気のような悲しみ, слава богу я не олух
ウィッチブレイド 空気のような悲しみ
Egor Safin, ну лудычи
Vitaly Kotenev
Чисто на азарте время провести в итоге остаться не с чем
Max Tikhy
Но -25к сложно пережить
Max Tikhy
Vitaly Kotenev, фааакт
ウィッチブレイド 空気のような悲しみ
Max Tikhy, ну спрыгни с крыши хз
Max Tikhy
Лучше с тротуара
Max Tikhy
Или повеситься на туалетной бумаге
Ilya Krylov
3.65 некст краш нужно
ウィッチブレイド 空気のような悲しみ
да
Max Tikhy
А лучше вскрыть вены ложкой
Lego Zombie
Я всрываю вены бумажкой от дошика
Lego Zombie
Удобно получается
Lego Zombie
И покушаешь и сдохнешь
Lego Zombie
Выгода
Lego Zombie
дай х3
Egor Safin
сайт фулл скам
Egor Safin
0 выдачи
Max Tikhy
Нихуя придумал
Max Tikhy
Надо опробовать
Egor Safin
мне нравится как тут модеры банят чат
Egor Safin
типо оправдать сайт не могут
Max Tikhy
Было бы за что
0