Чтобы не ждать, пока кто-то что-то напишет (форум не даст разместить второе сообщение, надо апдейтить первое), напишу под дочерним акком.
TL;DR — под катами ниже катастрофическая стена текста!
Азы теории вероятности.
Во-первых, с самых азов: как считать вероятности. Если у вас две стороны монеты, то вероятность выпадения одной из них это одна вторая, а если шесть сторон кубика, то одна шестая. Одна вторая это 50%, поэтому вероятность 1/2 это то же самое, что 50% или 0.5
Если у вас есть две вероятности, то они применяются мультипликативно: допустим, вы бросаете монету два раза. Наприме, какой будет вероятность выпадения двух орлов? Для этого надо перемножить цепочку: 0.5 x 0.5 = 0.25 или 1/4. И так далее. Всё довольно просто.
Как это применяется на практике и в диабло-три?
Например, вы хотите посчитать вероятность выпадения предмета с максимальным критшансом и критуроном. Сначала считаете, сколько вариантов есть у критшанса. Он может меняться от 8.5 до 10.0 через каждые 0.5. Делаете то же самое с критуроном (от 50% до 100% через каждые 5%).
КШ: (8.5 - 9.0 - 9.5 - 10.0)%: это всего четыре варианта.
Меньше критшанса на 70-том уровне игра не кидает.
Критурон: (50, 55, 60, 65, 70, 75, 80, 85, 90, 95 и 100)%.
Это 11 вариантов.
Дальше просто перемножаете на калькуляторе 1/4-тую и 1/11-тую: 1 / (4x11)= 1/44 — это и есть ваша вероятность получить 10% кш и 100% критдамага, если нет никаких других условий.
Я специально это всё написал, чтобы кто-нибудь мог просто взять и посчитать вероятность выпадения полного предмета (со всеми свойствами, сколько там у него есть). Пример расчёта смотрите в разделе демон-хантеров в теме «Даже не надейтесь получить нужный колчан»:
Про айтем-серверы.
В реальном мире вы можете бросать кубик или кидать монету. А в программировании рандомное число выдаёт какая-нибудь функция, например RAND. Выглядит это так — программа исполняется построчно и каждый раз когда вы написали RAND, это считается вызовом и вы получаете новое рандомное число. Нюансы (вроде тех, что числа на самом деле псевдослучайные) я сейчас сознательно опускаю:
A = RAND;
B = RAND;
C = RAND;
Все три числа: A, B и C, получатся разными и случайными. Т.о. каждый вызов этой функции аналогичен виртуальному бросанию кубика или монеты.
Но есть одна загвоздка. Очень большая на самом деле! Она состоит в том, где вы бросаете кубик.
В самом деле: есть вы (за своим компьютером) и есть сервер (где-то там далеко). С какой стороны вызывать функцию RAND?
Фишка в том, что если делать это на компьютере игрока, то игру быстро сломают. Поэтому делается это всегда на сервере.
Дальше следующий тонкий момент. На самом ли деле на сервере вызывается функция RAND?
Давайте продолжим пример с критшансом и критуроном выше и представим, что у нас есть 44 сервера вместо одного. В самом деле: игроков-то в игре много — и это вам кажется, будто сервер всего один, а на самом деле их там целый дата-центр!
Получается, что бросание кубика можно реализовать не вызовом функции, а моментом подключения к одному из серверов.
Первый будет давать всегда 8.5% критшанса и 50% критурона, второй 9% кш и 50% ку, третий 8.5% и 55% ку — и так далее. Причём вероятности у них будут неизменными!
Таким способом достигается ситуация, при которой какой-нибудь местный сисадмин (или кто там следит за серверами) ничего не сможет “подкрутить” в свою пользу. Все серверы у вас вообще одинаковые! Даже вероятности на них. Просто когда каждый из серверов втыкают в свою собственную розетку, он получает адрес и в зависимости от этого адреса сервер меняет свою вероятность выдачи. Получается (в нашем примере) 44 интернет-розетки и 44 одинаковых сервера, на каждом из которых прописаны все 44 возможных адреса — вместе с вероятностями, которые нужно выдавать, когда сервер получит один из этих адресов.
Я очень надеюсь, что этот тонкий момент стал понятен.
Потому что отсюда возникает ситуация, когда один сервер выдаёт мемпы, а второй скорны. но не наоборот — а это и есть пресловутые «таблицы дропа», которые связаны со «счастливыми серверами».
Что такое дорвей-сервер.
Должен быть ещё один, координирущий сервер, который раздаёт, «кому куда пойти». Он же, скорее всего, отвечает за ввод логина и пароля. А после захода на него вы оказываетесь в меню. И только после захода в игру этот дорвей-сервер решает, на сервер с какими шансами вас направить. Например, если вы давно не играли и вам надо дать двухчасовой баф МФ-а, то он направит вас на «частливый сервер». А если нет, то на обычный. Отличаются эти сервера таблицами дропа, в которых написано то-нибудь вроде этого —
Первый обычный сервер:
мемпа = вероятность 10%
скорн = вероятность 0%
Второй обычный сервер:
мемпа = вероятность 0%
скорн = вероятность 10%
Бафнутый сервер:
мемпа = вероятность 20%
скорн = вероятность 20%
Понятно? Когда-то сервер был перманентным до перелогина, а сейчас он, просто-напросто, меняется каждый раз, когда игрок заново заходит в рифт. Теоретически, счастливые сервера можно вычислить, но делать это уже придётся не руками (как раньше), какой-нибудь софтиной (которая будет анализоровать сетевые адреса и верещать при каждом заходе в рифт не на тот сервер до тех пор, пока не перезайдёшь в рифт на нужный).
Как устроен игровой сервер.
На практике, не надо думать, будто каждый сервер это кондовая железка где-то в сервачной. Они давно виртуальные. Т.е. на одном аппаратном сервере крутится, скажем, десяток виртуальных игровых серверов, каждый из которых имеет десяток так называемых каналов (или слайсов), каждый из которых обслуживает, допустим, до 100 игроков.
10x10x100 = 10.000 игроков на одной желязке.
И бафнутыми или «счастливыми» могут быть каналы (слайсы), а не сервера целиком.
Это, разумеется, чистой воды оптимизация, которая нужна в частности, для того, что все 10 млн игроков Диаблы-три не писали что-то одновременно в один-единственный чат. Банально, отсортировать десять тысяч игроков по какому-нибудь параметру гораздо быстрее, нежели десять миллионов.
В итоге вы играете в неком локальном “междусобойчике”, куда попали чисто случайно (с поправкой на коррекцию этой случайности в зависимости от направления дорвей-сервера).
Вот эту работу по исправлению дропа, которую начал дорвей, продолжает основной сервер. Или точнее, может продолжать… я же не знаю, как конкретно устроена именно Диабла-три, но принципы у неё явно общие, потому что ничего более удобного просто не изобрели. С поправкой на какие-то отличия и ноу-хау уже конкретно в Близзард.
Итак, вот эту работу по исправлению дропа, которую начал дорвей, продолжает основной сервер. Если дорвей направил вас на сервер с определёнными таблицами дропа, то этот сервер потом направит уже в конкретный канал — и сделает это, допустим, проанализоровав вашего персонажа.
Простейший пример: при заходе в сетевую игру вам подбирают примерно равную по парагону пати (насколько это возможно). Это вот оно и есть.
И тут ещё один тонкий нюанс.
Например, если вы только что достигли 70-го уровня, то игра может засунуть вас в канал к очень хорошо одетым игрокам. Ну просто в расчёте на то, что с вами хоть чем-нибудь поделятся. И так оно на практике обычно и бывает…
Что такое очередь игроков.
Но это ещё опять не всё. Канал же можно отсортировать. Ну хотя бы уровню парагона… или каждый раз пересортировывать игроков при получении любым из них легендарного предмета.
Получается «эффект трубы» или очередь игроков.
Легендарка выдаётся в начало очереди и первый персонаж анализируется: надо тебе? хорошо одет или не очень? давно вообще легендарку получал?
Если первому давать не нужно, то анализируется второй в очереди. И так далее.
В результате легендарка может проехать всю трубу из хай-левельных персонажей и достаться нубику в самом конце. Причём так будет автоматически продолжаться до тех пор, пока нубик более-менее во что-нибудь не оденется. А потом «краник закрылся»: у него повысится некий внутренний коэффициент и легендарки начнут доставаться снова другим участникам канала в сервере.
Там что же такое айтем-сервер.
Дорвей-сервер занимается только логинами и распределением игроков, а игровые сервера — только локациями и собственно, игрой. Весь дроп скорее всего вынесен на ещё один, третий сервер. Который собственно, и называется айтем-сервер.
Он очень специализированный и поэтому всё, что он делает — это отвечает на запросы типа “дай легендарку” ответами типа “на, держи”. То есть к нему приходят сетевые запросы от игровых серверов на запросы предметов, а он выдаёт сетевые ответы, соответствующие предметам.
И я конечно, не знаю как конкретно у Близзард и в Диабло-три (единственное, о чём можно достоверно догадаться, это о физическом расположении айтем-сервера: он совершенно точно находится под подушкой у Бобби Котика), но при работе с айтем-сервером было бы разумно использовать несимметричную криптографию. Пару слов, что это такое для те, кто не знает.
В обычной криптографии вы можете что-то зашифровать и расшифровать одни и тем же паролем. А в несимметричной паролей два: так называемые закрытый и открытый. Закрытым можно только расшифровать. А открытым только расшифровать. Реализация — чистая математика. Но очень удобно: если закрытый пароль есть только на айтем-сервере, то его нет на игровых серверах. Читай — там ничего не сломает никакая уборщица. А расшифровывая на стороне игры (даже например, клиента, то есть у вас на компьютере), можно быть уверенным, что предмет — настоящий. В смысле, в игру не получится подсунуть какие-нибудь левые сервера, который вводят в неё со стороны левые предметы. Всё только из одного источника.
И вот процесс разгадывания легендарок в Д3 очень похож на расшифровку посылки с легендаркой открытым ключом. Разумеется, это можно сделать мгновенно, но почему бы не добавить шарма игре? Это клёвая пользовательская фишка.
Добавлю, что отдельный айтем сервер позволяет решать дополнительные полезные задачи. Например, глобально отслеживать весь дроп в игре. Например, это может понадобиться для контроля насыщенности аукциона (чтобы чисто случайно не получилось затоваривания какими-нибудь одними шапками, etc). Мне давно кажется, что дроп в Д3 меняется циклически: типа там, понедельник — день колец, вторник — штаном и и так далее. Тоже решается на айтем-сервере.
Ну и, в качестве послесловия добавлю, в что реальном программировании задачка где-то приблизительно раз в 100 сложнее того, что я здесь написал. Со всякими вычурными схемами, костылями где не получилось, даже забытыми ветками алгоритма (которые создают баги) и т.д. и т.п.
В частности, напрашиваются ещё и отдельные сервера для расчётов урона, для ИИ монстров и другие. Помните, что происходит с вашим персонажем при отвале интернет-соединения? Всё, что он может делать, это только бегать по карте — и больше ничего. Всё остальное распределено по разным вычислительным мощностям.
Завершить этот длинный рассказа хочется исправлением опечаток (я кажется, часто глотал окончания слов, чтобы не потратить вообще весь день на написание этого текста). Ео вместо этого закончу цитатой о разработке игры, взятой с сайта https://habr.com/ru/post/474466/
:
«Мы знали, что люди смогут взламывать игру или читерить», — рассказывает Бревик, но студия полагала, что это будут отдельные случаи. «Но потом игра вышла и мы подумали „боже мой… читы загружают в Интернет и теперь читерить могут ВСЕ!“ Мы об этом даже не думали!»
Бревик вспоминает, что это был один из самых обескураживающих моментов в жизни Diablo и он сильно мотивировал Blizzard переделать клиент-серверную архитектуру для Diablo II.