Всё началось вот с этой темы. Но, думаю, сделать тут обсуждение будет намного лучше. Предлагаю разобраться в механике работы GetRandomInt/Real. Для анализа через Preload Exploit я вынул значения случайных чисел при конкретных Random Seed - от 0 до 5999 (могу дополнить аж до 2147483647.
Доподлинно известно, что Варкрафт применяет псевдослучайные числа, генерируемые в определённой последовательности. Сама последовательность - математическая рекуррентная формула, которая состоит из определённых действий и из предыдущего члена выводит следующий. Первым членом такой последовательности является некое значение Random Seed. В Варкрафте им управляют функции SetRandomSeed и GetRandomSeed (изменение и получение).
Задача - вывести данную рекуррентную формулу. Если у кого-то есть какие-то соображения о том, что стоит попробовать или сделать - обсудим. Всё-таки, этот вопрос в варкрафте ещё открыт.
Upd.: Из интересного материала на эту тему - распределение случайных чисел варкрафта, которое используется в атаках, уже исследовали в далёком 2008 году и прочитать об этом можно в теме на плейдоте. Статья на английском языке, но содержит неплохие табличные данные, основанные на математике.
Не зли других и сам не злись. Мы - гости в этом мире. И если что не так - смирись, Будь поумнее - улыбнись, Ведь в мире всё закономерно. Зло, излучённое тобой, К тебе вернётся непременно.
Сообщение отредактировал Duosora - Среда, 18 Марта 2015, 18:55:36
Из интересного материала на эту тему - распределение случайных чисел варкрафта, которое используется в атаках, уже исследовали в далёком 2008 году и прочитать об этом можно в теме на плейдоте. Статья на английском языке, но содержит неплохие табличные данные, основанные на математике.
Добавлено (18 Марта 2015, 18:54:54) --------------------------------------------- SirNikolas, Спасибо.)
Не зли других и сам не злись. Мы - гости в этом мире. И если что не так - смирись, Будь поумнее - улыбнись, Ведь в мире всё закономерно. Зло, излучённое тобой, К тебе вернётся непременно.
Duosora, если не ошибаюсь, вар написан на С++, а там есть такая прекрасная функция как randomaze(A); random(B);
"История нашего народа знает немало светлых страниц. Темных было тоже достаточно. И все с белыми пятнами. От белых пятен истории нужно избавляться, но нельзя же всё мазать черной краской!"(с) Рохан.
если не ошибаюсь, вар написан на С++, а там есть такая прекрасная функция как randomaze(A); random(B);
Если так, то что за формула лежит в основе плюсичной функции rand()?
Не зли других и сам не злись. Мы - гости в этом мире. И если что не так - смирись, Будь поумнее - улыбнись, Ведь в мире всё закономерно. Зло, излучённое тобой, К тебе вернётся непременно.
Кристофер, откуда уверенность в том, что Warcraft использует дефолтный rand()? Хотя и это вероятно. Можно предположить, что seed задается через srand(), а сама генерация происходит через rand(). Duosora, в C/C++ используется довольно простой линейный конгруэнтный метод:
Код
/* Reentrant random function from POSIX.1c. Copyright (C) 1996-2015 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see <http://www.gnu.org/licenses/>. */
#include <stdlib.h>
/*This algorithm is mentioned in the ISO C standard, here extended for 32 bits. */ int rand_r (unsigned int *seed) { unsigned int next = *seed; int result;
next *= 1103515245; next += 12345; result = (unsigned int) (next / 65536) % 2048;
next *= 1103515245; next += 12345; result <<= 10; result ^= (unsigned int) (next / 65536) % 1024;
next *= 1103515245; next += 12345; result <<= 10; result ^= (unsigned int) (next / 65536) % 1024;
*seed = next;
return result; }
Добавлено (18 Марта 2015, 21:55:47) --------------------------------------------- Кстати, если займешься этим, было бы интересно увидеть разницу в производительности Warcraft'овского генератора и какой-нибудь пользовательской функции, основанной, например, на приведенной выше.
Сообщение отредактировал Bru - Среда, 18 Марта 2015, 21:56:38
function RandInt takes integer seed returns integer local integer next = GetRandomSeed()*1103515245+12345 local integer result = ModuloInteger(R2I(next/65536),2048)
set next = next*1103515245+12345 set result = result*1024 set result = Pow(result,ModuloInteger(R2I(next/65536),1024))
set next = next*1103515245+12345 set result = result*1024 set result = Pow(result,ModuloInteger(R2I(next/65536),1024))
call SetRandomSeed(next)
return result endfunction
Вроде бы, я верно переписал эту штуковину на JASS. Поддерживаются 32-битные числа.
Не зли других и сам не злись. Мы - гости в этом мире. И если что не так - смирись, Будь поумнее - улыбнись, Ведь в мире всё закономерно. Зло, излучённое тобой, К тебе вернётся непременно.
Сообщение отредактировал Duosora - Пятница, 20 Марта 2015, 21:59:45
Даа? >takes integer seed Не вижу что-то упоминаний переменной seed в теле функции. А в остальном, кажется, верно.
Добавлено (21 Марта 2015, 13:55:11) --------------------------------------------- Тестировал ее, кстати?
Добавлено (21 Марта 2015, 14:15:49) --------------------------------------------- local integer next=GetRandomSeed() * 1103515245 + 12345 //Undeclared function GetRandomSeed() local integer next=GetRandomSeed() * 1103515245 + 12345 //Bad types for binary operator local integer next=GetRandomSeed() * 1103515245 + 12345 //Cannot convert real to integer set result=Pow(result, ModuloInteger(R2I(next / 65536), 1024)) //Cannot convert real to integer set result=Pow(result, ModuloInteger(R2I(next / 65536), 1024)) //Cannot convert real to integer
Добавлено (21 Марта 2015, 15:02:01) --------------------------------------------- Оп, прошу прощения. Да, функция не работает из-за того, что нет xor'a.
Добавлено (21 Марта 2015, 19:13:41) --------------------------------------------- В общем, функция должна иметь такой вид:
Код
function rand_r takes integer seed returns integer local integer next = seed local integer result
set next = next * 1103515245 set next = next + 12345; set result = ModuloInteger(R2I(next/65536),2048)
set next = next * 1103515245 set next = next + 12345; set result = ShiftLeft(result, 10); set result = xor(ModuloInteger(R2I(next/65536),1024))
set next = next * 1103515245 set next = next + 12345; set result = ShiftLeft(result, 10); set result = xor(ModuloInteger(R2I(next/65536),1024))
set seed = next
return result endfunction
Использован ShiftLeft из библиотеки дуоса из соседней темы, но еще нужно реализовать xor.
Сообщение отредактировал Bru - Суббота, 21 Марта 2015, 19:14:10
Прошу прощения, тупанул с xor. А в ShiftLeft и надобности особой нет, я написал это умножение напрямую.
Кстати, через Return Bug xor можно реализовать довольно просто, написав B2I-функцию, которая бы сравнивала именно побитово. А в 1.24+... Даже не знаю.
Не зли других и сам не злись. Мы - гости в этом мире. И если что не так - смирись, Будь поумнее - улыбнись, Ведь в мире всё закономерно. Зло, излучённое тобой, К тебе вернётся непременно.
1vann, Благодарю. Это пролило свет на многие вещи. Поверчусь вокруг них.
Не зли других и сам не злись. Мы - гости в этом мире. И если что не так - смирись, Будь поумнее - улыбнись, Ведь в мире всё закономерно. Зло, излучённое тобой, К тебе вернётся непременно.