вы наверное смоделировали не все ситуации
почитайте как в игре рассчитываются верующие: http://civgames.com/4435
Как видно из исходника функция SetPopulation не добавляет очков ни одной религии.
Изменение числа последователей происходит только из-за нового размера города, новый чел причисляется одной из представленных религий на основе существующего соотношения очков.
ps вообще этот исходник какой-то подозрительный, сейчас скачаю со стима посмотрю в подлиннике так сказать..
Последний раз редактировалось Peter; 05.03.2016 в 18:47.
EC2 - разработка игры
Мастерская Steam - мои моды для Civilization V
Last Citadel - сайт игроков Warlords III
Давайте определимся как в итоге делать будем, а дальше я реализую, иначе мы долго спорить будем.
Вы хотите, чтобы мигрант был полностью представителем одной из религий (1 последователь уезжает). Тогда если в городе с 10 жителями 7 православных, 2 мусульманина и 1 атеист, то шанс того, что в новый город приедет 1 православный - 70%, 1 мусульманин - 20%, и 1 атеист - 10%. Так делаем?
Tomahawk's Collection for Civilization V - сборник модификаций. Качественный перевод и совместимость между собой.
R.E.D. World War II - масштабный сценарий Второй мировой войны.
Война Судного дня - сценарий войны на Ближнем Востоке, произошедшей в 1973 году.
я бы сделал равные шансы для всех религий. мне кажется это и правдоподобно (т.к. эмигрируют обычно меньшинства) и интересно - так слабые религии получат дополнительную возможность распространиться. т.е. генерируем случайное число от 1 до #Religions и берем эту религию.
дальше в целевом городе перебираем все религии и делаем ConvertPercentFollowers (1/newCitySize)*100 для каждой
обратите внимание на пантеон, мне кажется может возникнуть ошибка, если целевая цивилизация не сгенерировала пантеон. т.е. мигрант не должен переносить пантеон.
ConvertPercentFollowers в dll:
ps подождите, давайте разберемся с пантеоном...
EC2 - разработка игры
Мастерская Steam - мои моды для Civilization V
Last Citadel - сайт игроков Warlords III
Шанс могу сделать равным, если мы рассматриваем 3 религии, значит у каждой вероятность будет треть для переезда. Пойдёт? По коду так даже проще.
Пантеон это как бы язычники, будет интересно их перемещать. Всё равно это максимум для античности, а потом их другие религии задавят. Насчёт ошибки протестируем.
Tomahawk's Collection for Civilization V - сборник модификаций. Качественный перевод и совместимость между собой.
R.E.D. World War II - масштабный сценарий Второй мировой войны.
Война Судного дня - сценарий войны на Ближнем Востоке, произошедшей в 1973 году.
да, хорошо.
инфа по работе религиозных функций и пантеона:
ConvertPercentFollowers
берет очки eFromReligion, умножает на iPercent/100
получается iPressureConverting
это значение вычитается из очков eFromReligion
и затем делается вызов AddReligiousPressure(eToReligion, iPressureConverting)
AddReligiousPressure
в цикле проходим религии
нашли нужную религию - добавляем ей очки
нашли пантеон - убавляем ему очки, если eReligion > 0 - не атеизм и не пантеон
если нужной религии в городе нет, добавляем - здесь может возникнуть ошибка с пантеоном
в общем, когда распространяются религии, они съедают очки пантеона.
и сам пантеон нельзя так просто распространять между разными цивами, т.к. целевая цива может не иметь пантеон - тут будет глюк, вероятно крэш.
в связи с этим может быть два решения -
1) или вообще не распространять пантеон, т.е. исключать его из списка возможных религий мигранта
2) или если мигранту достался пантеон смотреть создала ли целевая цива пантеон.
если создала - распространяем пантеон.
если нет - распространяем атеизм.
я так понял вам больше нравится второй вариант, и мне тоже.
емнип функция определения наличия пантеона должна быть у объекта Player
(в городе пантеона может не быть, но это не важно - главное чтобы у Player он был)
Последний раз редактировалось Peter; 05.03.2016 в 20:46.
EC2 - разработка игры
Мастерская Steam - мои моды для Civilization V
Last Citadel - сайт игроков Warlords III
Задумка ведь какая была, взяли из города 1 последователя и переместили в другой город, не меняя таким образом баланс последователей на карте. А единственная доступная нам функция для внешнего вмешательства ConvertPercentFollowers изменяет в конечном счёте очки, на основе которых потом пересчитываются последователи. Тогда получается такая плохая ситуация: в городе было 3 индуиста (75%) и 1 синтоист (25%), уезжает один индуист, остаётся 2 индуиста (66%) и 1 синтоист (33%), новые проценты мы добросовестно пересчитаем, чтобы игроки видели: осталось сколько нужно последователей. Но мы будем вмешиваться в изменение баланса в родном городе, изменять очки в нём, перебрасывая их с одной религии на другую. Когда родной город вырастет до 15 (считаем, что внешнего давления не идёт), мы увидим 10 индуистов и 5 синтоистов, хотя без изменения процентов последователей бы было где-то 12 и 3.
Теперь другая проблема про разное кол-во очков в 2 городах, напрямую мы передавать без DLL их не сможем. В родном городе было например 100 очков буддизма, но он их увезти не сможет, будет только метка "буддист". Приехал мигрант в город с 15 населением, тогда 1 житель от 15 = 6,25%, на столько мы должны увеличить буддизм в городе, но если общее кол-во очков всех религий в нём 12000, то мы увеличим буддизм в городе на 750 очков (6% от 12К), обмен неравноценный получается. Правильно понимаю? Тогда из мигранта выйдет тихий миссионер, а это нам не нужно... тут дело не в коде уже, а в самом принципе.
Последний раз редактировалось Tomahawk; 06.03.2016 в 07:42.
Tomahawk's Collection for Civilization V - сборник модификаций. Качественный перевод и совместимость между собой.
R.E.D. World War II - масштабный сценарий Второй мировой войны.
Война Судного дня - сценарий войны на Ближнем Востоке, произошедшей в 1973 году.
да, если помните, я в первом же комменте написал, что функций для управления религией разрабы нам в луа почти не дали
кроме "очковой" неравноценности есть еще такая вещь как атеизм, в норме ни пророки ни инквизиторы его не берут, а тут мы его потихоньку конвертируем миграциями, получается непоследовательность в игровой механике. хотя юзеру это не видно, может не так уж страшно.
давайте рассмотрим предложенные ситуации.
в городе размера 4 если верующие распределены в соотношении 3:1, это может быть обусловлено например миссионером (1000) и накопленным давлением (333), при отъезде индуиста перелив составит 1/3/3=11% или 110 очков - вроде, не так уж много? При том что такая картина вообще не типична, скорее в таком маленьком городе будет 300 атеизма и скажем 100 буддизма, и при отъезде атеиста перелив в буддизм составит всего 33 очка. В старом же городе и население будет большое, например город размера 10, 400 атеизма, 600 буддизма и 1000 индуизма = 2 атеиста, 3 буддиста, 5 индуистов. При отъезде индуиста перелив в другие религии составит 1/5/9=6% или 60 очков (24а и 36б) - опять же не много. при естественном росте города добавляется по 100 очков доминирующей религии, как видим цифры вполне сопоставимые. да, при росте игра тупо добавляет 100 очков, т.е. ранняя миграция не создаст таких искажений как вы предположили.
с приездом "тихого миссионера" - примерно та же ситуация на самом деле с едой при переезде из маленького города в большой. и вроде люди не жалуются, у меня из тысяч комментов всего пара была об этом, мол может лучше еду переносить вместо жителей (аналог очки vs последователи). можно представить что мигранты в более продуктивной среде дико размножаются, и религиозно также укрепляются т.к. религия в новом обществе составляет их идентичность.
ps надо будет еще добавить запрет иммиграции при включенном avoid growth (на экране города). все давно хотят такую фичу.
Последний раз редактировалось Peter; 06.03.2016 в 10:00.
EC2 - разработка игры
Мастерская Steam - мои моды для Civilization V
Last Citadel - сайт игроков Warlords III
зацените кавер
e6.jpg
EC2 - разработка игры
Мастерская Steam - мои моды для Civilization V
Last Citadel - сайт игроков Warlords III
Сверху в Emigration.lua в переменных -- const factors добавьте переменные
А перед строкой local destCity = GetDestinationCity(destList, n - 1, maxDist); добавьте эти строки, print потом можно удалитьКод:local gridWidth, gridHeight = Map.GetGridSize();
Итого всего 2-3 новые строки решат вопросКод:if maxDist > 100 then maxDist = 100; end -- защита от кривой настройки print("MaxDistance стоит в настройках: " .. maxDist .. "% от диагонали"); print(string.format("Размер карты: ширина = %d, высота = %d", gridWidth, gridHeight)); maxDist = math.floor((math.sqrt((gridWidth * gridWidth) + (gridHeight * gridHeight))) * (maxDist/100)); -- от длины гипотенузы берётся указанное число процентов. print("Итого макс. дистанция для переезда: " .. maxDist .. " клеток");
Теперь по настройкам в разные эпохи, я пока поставил так:
Древний мир: Д - 5%
Античность: Д - 10%
Средневековье: Д - 15%
Новое время: Д - 30%
Новейшее время: Д - 45%
Современность: Д - 80%
Эпоха Атома: Д - 100%
Информационный век: Д - 100%
Будущее: Д - 100%
Здесь надо вспомнить какие расстояния люди были способны преодолевать в разные эпохи в зависимости от технологий, сначала появились лошади с дорогами, потом мореплавание, потом железные дороги, а к современному времени государства уже сняли практически все барьеры и путешествовать стало совсем свободно.
Tomahawk's Collection for Civilization V - сборник модификаций. Качественный перевод и совместимость между собой.
R.E.D. World War II - масштабный сценарий Второй мировой войны.
Война Судного дня - сценарий войны на Ближнем Востоке, произошедшей в 1973 году.
хорошо
я сделаю 10-15-25-35-50-70-100 для более плавного изменения
35 хватит чтобы пересечь атлантику
70 уже практически везде достает
вообще расстояния лучше сразу посчитать для всех эр и сохранить в массив
чтобы уменьшить вычисления между ходами
EC2 - разработка игры
Мастерская Steam - мои моды для Civilization V
Last Citadel - сайт игроков Warlords III
Перепишем тогда так. Сверху в Emigration.lua перед local notifications = {}; добавьте
И строку local maxDist = GameInfo.EmigrationEraModifiers("EraType = '" .. currentEraType .. "'")().MaxDistance; замените этимКод:local gridWidth, gridHeight = Map.GetGridSize(); --print(string.format("Размер карты: ширина = %d, высота = %d", gridWidth, gridHeight)); local DistanceInfo = {}; for row in GameInfo.EmigrationEraModifiers() do local maxDist = row.MaxDistance; if maxDist > 100 then maxDist = 100; end --защита от дурака --if maxDist ~= nil then print("MaxDistance стоит в настройках: " .. maxDist .. "% от диагонали"); end maxDist = math.floor((math.sqrt((gridWidth * gridWidth) + (gridHeight * gridHeight))) * (maxDist/100)); -- от длины гипотенузы берётся указанное число процентов if maxDist ~= nil then table.insert(DistanceInfo, maxDist); --print("В таблицу DistanceInfo поместили макс. дистанцию для переезда: " .. maxDist); end end
Дистанция будет зависеть от процентов по диагонали, расчёт будет происходить один раз.Код:local currentEraID = Game.GetCurrentEra(); local maxDist = DistanceInfo[currentEraID + 1]; --print("Макс. дистанция в клетках = " .. maxDist);
ну или 10-15-20-35-50-70-100 Тут они открыли Астрономию и понеслось...))я сделаю 10-15-25-35-50-70-100 для более плавного изменения
Посмотрите ещё, файл ScriptDataUtils.lua в строке 89 выдаёт ошибку синтаксиса - это в оригинале мода версии 5. Не знаю что это такое, но на вылеты вроде не влияет.
Syntax Error: C:\Users\Tomahawk\Documents\My Games\Sid Meier's Civilization 5\MODS\Emigration (v 5)\Lua\ScriptDataUtils.lua:89: chunk has too many syntax levels
Последний раз редактировалось Tomahawk; 06.03.2016 в 14:17.
Tomahawk's Collection for Civilization V - сборник модификаций. Качественный перевод и совместимость между собой.
R.E.D. World War II - масштабный сценарий Второй мировой войны.
Война Судного дня - сценарий войны на Ближнем Востоке, произошедшей в 1973 году.
ок
эта ошибка синтаксиса ни на что не влияет. особенность моего сериализатора..
с 3й версии она вроде
EC2 - разработка игры
Мастерская Steam - мои моды для Civilization V
Last Citadel - сайт игроков Warlords III
Нашёл баг, необходимо подправить тип Эпохи атома. Вот таким образом:
Модификаторы у вас наверное лучше получится проставить... это шанс на переезд или как?) Не понял пока.
Последний раз редактировалось Tomahawk; 07.03.2016 в 19:59.
Tomahawk's Collection for Civilization V - сборник модификаций. Качественный перевод и совместимость между собой.
R.E.D. World War II - масштабный сценарий Второй мировой войны.
Война Судного дня - сценарий войны на Ближнем Востоке, произошедшей в 1973 году.
EC2 - разработка игры
Мастерская Steam - мои моды для Civilization V
Last Citadel - сайт игроков Warlords III
скопирую сюда из ЛС, для удобства
определение перелива при миграциях
величина перелива x определяется из отношения числа последователей после миграции:
(f-x)/(p-f+x)=(f-1)/(p-f), где f - число верующих религии мигранта до отъезда, p - размер города до отъезда
(f-x)(p-f) = (f-1)(p-f+x)
[pf-ff]-px+[fx] = [pf-ff]+[fx]-p+f-x
x-px = f-p
x = (f-p)/(1-p)
это величина в верующих.
доля перелива определяется как x' = x/f.
рассмотрим прмиер: было 300 индуизма (3п), всего население = 5 (5п); 1 индуист уехал.
f = 3, p = 5
x = (3-5) / (1-5) = -4/-2 = 0.5
x' = 0.5/3 = 17%
и действительно, если мы из идуизма (300) перельем 17% в другие религии (200), у них станет по 250 очков или по 2 верующих в городе размера 4.
т.е. в вашем примере в Рио из религии 5 нужно было переливать
x' = (f-p)/(1-p)/f = (3-8)/(1-8)/3 = -5/-7/3 = 23.8%
если религий всего две, больше ничего рассчитывать не требуется.
если больше 2 - все становится несколько сложнее.
для каждой религии, в которую мы будем делать перелив, нужно определить вес.
в Рио это 4/5 для религии (13) и 1/5 для религии (-1).
т.о. в религию (13) пойдет 80% перелива или 19% очков религии (5).
на религию (-1) остается 20% перелива или 4.76% очков религии (5).
тут нужно учесть, что религия 5 уже уменьшилась на 19% из-за перелива в (13), поэтому долю религии (-1) нужно увеличить на столько же. скорректированная доля религии (-1) составляет 4.76*1.19=5.66%, округляем до 6%.
если была бы еще одна религия, ее долю нужно было бы увеличить уже на 1.19*1.06, и т.д.
проверим наш алгоритм на Рио:
рио 8 жителей
(очки заданы условно, может быть сколько угодно, главное пропорция)
религия последователи очки 5 3 300 13 4 400 -1 1 100
отъезжает последователь религии 5, перелив по формуле составляет 23.8%
перелив в религию 13 = 23.8*4/5 = 19% = 57 очков. после перелива (5)=243, (13)=457
перелив в религию -1 = 23.8*1/5 = 4.76%, *1.19 = 6%, в очках 243*0.06 = 15. после перелива (5)=228, (-1)=115
результат:
рио 7 жителей
все сходится!
религия последователи очки 5 2 228 13 4 457 -1 1 115
т.е. вам надо было делать перелив на 19 и 6 процентов, а не на 6 и 2, поэтому у вас число верующих не менялось.
теперь верующий приезжает в копенгаген..
здесь все просто, мы берем долю новой религии равной 1/(p+1), и выполняем конвертацию из всех представленных религий.
копенгаген 2 жителя
x = 1/(2+1) = 33%, выполняем конверсии. Кол-во религий роли не играет, ничего делить не надо - из всех берем по 33% и переводим в целевую
религия последователи очки 13 1 100 -1 1 100
результат:
копенгаген 3 жителя
т.е. тут все гораздо проще
религия последователи очки 13 1 67 -1 1 67 5 1 66
НО как вы наверное заметили, я вместо пантеона (0) взял атеизм (-1)
при наличии пантеона все осложняется тем, что при распространении других религий пантеон "поедается" ими, и чтобы это учесть требуется внести поправки.
давайте подумаем какие именно, или как эту проблему можно обойти..
Последний раз редактировалось Peter; 08.03.2016 в 13:34.
EC2 - разработка игры
Мастерская Steam - мои моды для Civilization V
Last Citadel - сайт игроков Warlords III
Для этого в начале функции function MoveCitizen(fromCity, toCity) можно было бы добавить
Но это работает для игрока-человека, я пока не видел, чтобы ИИ эту галочку нажимал. Проверял в обзоре города шпионом-дипломатом. Раз ИИ не умеет галку ставить, как я думаю, то не баланс получается. Лучшим решение будет такой код:Код:if city:IsForcedAvoidGrowth() then print("Мигрант отказался ехать в " .. toCity:GetName() .. " из-за недостатка пищи в городе"); return; end
Здесь мы просто смотрим какой прирост еды в городе, например, добыча еды 13, съедено 10, итого +3 - про эту цифру говорю. 1 новый житель потребляет 2 еды, соответственно, если новому жителю не будет хватать пищи, т.е. её прирост будет меньше 2, мигрант в город не поедет.Код:local iFoodPerTurn = toCity:FoodDifference(); if iFoodPerTurn < 2 then print("Мигрант отказался ехать в " .. toCity:GetName() .. ", из-за недостатка пищи в городе. Еда в ход: " .. iFoodPerTurn); return; end
Tomahawk's Collection for Civilization V - сборник модификаций. Качественный перевод и совместимость между собой.
R.E.D. World War II - масштабный сценарий Второй мировой войны.
Война Судного дня - сценарий войны на Ближнем Востоке, произошедшей в 1973 году.
EC2 - разработка игры
Мастерская Steam - мои моды для Civilization V
Last Citadel - сайт игроков Warlords III
Tomahawk's Collection for Civilization V - сборник модификаций. Качественный перевод и совместимость между собой.
R.E.D. World War II - масштабный сценарий Второй мировой войны.
Война Судного дня - сценарий войны на Ближнем Востоке, произошедшей в 1973 году.
тут такая новость, запостил я на ихфанатикс анонс шестой версии
и сегодня отписался в теме чел, в общем он уже сделал давно "для себя" то что мы тут только собираемся и ломаем мозг
вот архивчик:
http://forums.civfanatics.com/attach...6&d=1457304032
только с пантеоном там видимо проблема не решена, сейчас буду смотреть-изучать
ps: чуда не произошло, формула конверсии в исходном городе у него неправильная. работает только в случае 2х религий. а если больше - дает неточный результат. хотя близко к нужному.
еще там в уведомление вставляется иконка религии, сделать это можно более простым способом
инфа о религии получается как
local religion = GameInfo.Religions[id];
и дальше можно использовать religion.IconString, будет работать с модами добавляющими новые религии.
Последний раз редактировалось Peter; 07.03.2016 в 22:44.
EC2 - разработка игры
Мастерская Steam - мои моды для Civilization V
Last Citadel - сайт игроков Warlords III
иммиграция с учетом пантеона
общая формула конверсии в религию:
процент конверсии x = 100/p где p - население города после иммиграции, применяется ко всем представленным в городе религиям (см пример с копенгагеном выше).
алгоритм религиозной миграции:
1. если мигрирует атеизм - делаем конверсию в атеизм.
2. если мигрирует пантеон - смотрим, основал ли владелец города пантеон player:HasCreatedPantheon().
2.a. если основал - делаем конверсию в пантеон.
2.b. если не основал - делаем конверсию в атеизм.
3. если мигрирует религия - смотрим, есть ли в городе пантеон (число последователей пантеона > 0)
3.a. если пантеона нет - конвертируем в религию.
3.b. если пантеон есть, производим специальную конверсию (не пользуемся общей формулой конверсии):
- сохраняем число атеистов и язычников в городе: af, pf
- конвертируем 100*(1+1/pf)% пантеона в атеизм
- конвертируем 1 атеиста в религию, x = 100/(af+pf+1)
- конвертируем pf атеистов назад в пантеон, x = 100*pf/(af+pf)
пример:
целевой город - 3 жителя, 100 очков атеизм (1п), 200 очков пантеон (2п)
af = 1, pf = 2.
приезжает индуист.
конвертируем 100*(1+1/pf)=150% пантеона в атеизм, получаем 400 атеизма, 0 пантеона (очки давления не могут уйти в минус)
конвертируем атеиста в религию, x = 100/(1+2+1)=25% = 100 очков получает индуизм, в атеизме остается 300
конвертируем атеистов в пантеон, x = 100*2/(1+2)=67% или 201 очков
результирующее распределение:
4 жителя, 100 индуизм (1п), 100 атеизм (1п), 201 пантеон (2п)
эмиграция с учетом пантеона
если в городе есть пантеон,
1. сохраняем исходное число атеистов и язычников af, pf
2. сливаем 100% пантеона в атеизм и дальше делаем по обычному алгоритму (см пост №55); при эмиграции язычника перелив в другие религии будет делаться из атеизма.
3. по окончании конвертируем атеистов назад в пантеон:
3.a. если эмигрировал атеист, x = 100*pf/(pf+af-1)
3.b. если эмигрировал язычник, x = 100*(pf-1)/(pf-1+af)
3.c. иначе x = 100*pf/(pf+af)
ps я думаю этот алгоритм мне самому нужно будет закодировать, займусь этим послезавтра
Последний раз редактировалось Peter; 08.03.2016 в 22:24.
EC2 - разработка игры
Мастерская Steam - мои моды для Civilization V
Last Citadel - сайт игроков Warlords III