Случайная раса без повторений.
Добрый день!
Совсем недавно начал изучать редактор и столкнулся трудностью в реализации следующей задачи:
Есть 4 игрока и 4 расы.
При инициализации карты каждый игрок должен получить одну из этих 4х расс и построить главное здание этой рассы в центре своего региона.
Рассы не должны повторяться.
Реализовать пытался на GUI через рандомное число от 1 до 4.
А чтобы исключить повторы я ввёл проверку по наличию здания на карте.
К примеру игрок 1 зарандомил эльфов и построил древо жизни.
Игрок 2 тоже зарандомил эльфов но т.к. древо жизни уже есть на карте, то рандом +1 и повторная проверка.
В общем иногда всё даже работает как нужно, но чаще всего возникают такие ошибки:
  1. 1 игрок может получить сразу несколько расс.
  2. Может заспавниться всего 2 или 3 здания, а остальные игроки остаются без них.
  3. Могут заспавниться все здания но принадлежать они будут одному игроку.
и т.д.
Заранее извиняюсь, что объясняю своими словами и не шарю в терминах.




Просмотров: 679

» Лучшие комментарии


PT153 #1 - 6 месяцев назад (отредактировано ) 3   
МассивРас - массив рас.
ВерхРас - целочисленная, означающая самую последнюю занятую ячейку в МассивРас. Изначально 4.
РасаИгрока - массив расы игрока, id игрока есть номер ячейки.
Для А = 1 до 4 делать
    Число = Случайное число от 1 до ВерхРас
    РасаИгрока[A] = МассивРас[Число]

    Если МассивРас[Число] не равно МассивРас[ВерхРас], то
        МассивРас[Число] = МассивРас[ВерхРас]
    ВерхРас = ВерхРас - 1
Если у игроков id не 1, 2, 3 и 4, то нужно добавить массив IdИгрока, где в ячейках 1, 2, 3 и 4 будут записаны настоящие id игроков.
Для А = 1 до 4 делать
    Число = Случайное число от 1 до ВерхРас
    РасаИгрока[IdИгрока[A]] = МассивРас[Число]

    Если МассивРас[Число] не равно МассивРас[ВерхРас], то
        МассивРас[Число] = МассивРас[ВерхРас]
    ВерхРас = ВерхРас - 1
8gabriel8 #2 - 6 месяцев назад (отредактировано ) 2   
Создаёшь группу игроков из своих четырёх. Далее определяешь каждой расе своего игрока, например, для расы эльфов выбираешь случайного игрока из группы, удаляешь его из группы и создаёшь ему соответствующее здание в его позиции. Потом повторяешь это для остальных трёх рас. Понадобятся переменные для группы игроков и для запоминания случайного игрока.
MaxSnoK #3 - 6 месяцев назад 0
8gabriel8:
Создаёшь группу игроков из своих четырёх. Далее определяешь каждой расе своего игрока, например, для расы эльфов выбираешь случайного игрока из группы, удаляешь его из группы и создаёшь ему соответствующее здание в его позиции. Потом повторяешь это для остальных трёх рас. Понадобятся переменные для группы игроков и для запоминания случайного игрока.
Мне очень понравился ваш метод, единственная проблема в том, что я не совсем понял как запомнить рандомного игрока.
Я сделал вот таким образом, а дальше не понимаю.
Прикрепленные файлы
Ikobot #4 - 6 месяцев назад 0
Вот тебе костыльный вариант.
Число определяет пул выдачи всем игрокам.
1 - Хум, Орк, Андед, НЭ
2 - Хум, Андед, Орк, НЭ
3 - Хум, НЭ, Андед, Орк
И т.д.
Ультра костыльно и упорото, но как вариант
MaxSnoK #5 - 6 месяцев назад 0
Ikobot:
Вот тебе костыльный вариант.
Число определяет пул выдачи всем игрокам.
1 - Хум, Орк, Андед, НЭ
2 - Хум, Андед, Орк, НЭ
3 - Хум, НЭ, Андед, Орк
И т.д.
Ультра костыльно и упорото, но как вариант
такой вариант я тоже рассматривал, но в дальнейшем расс может быть не 4, а например 10. И тогда прописывать все вариации будет проблематично )
PT153 #6 - 6 месяцев назад (отредактировано ) 3   
понял как запомнить рандомного игрока
Создать переменную такого типа в менеджере переменных и установить значение переменной через соответствующее действие.
Игрок = Случайный игрок из группы Х
Удалить игрока Игрок из группы Х
8gabriel8 #7 - 6 месяцев назад (отредактировано ) 1   
PT153 верно указал. полностью триггер будет выглядеть так:
Пусть у случайного игрока переменная PlayerX, а у группы игроков PlayerGroup.
Устанавливаешь PlayerGroup
Set PlayerX=(Random player from PlayerGroup)
Player Group - Remove PlayerX from PlayerGroup
Unit - Create Ratusha for PlayerX at (PlayerX start position) facing 270.00 degrees
Set PlayerX=(Random player from PlayerGroup)
Player Group - Remove PlayerX from PlayerGroup
Unit - Create Dom Vojdei for PlayerX at (PlayerX start position) facing 270.00 degrees
Set PlayerX=(Random player from PlayerGroup)
Player Group - Remove PlayerX from PlayerGroup
Unit - Create Nekropol for PlayerX at (PlayerX start position) facing 270.00 degrees
Set PlayerX=(Random player from PlayerGroup)
Unit - Create Drevo Zhizni for PlayerX at (PlayerX start position) facing 270.00 degrees
PT153 #8 - 6 месяцев назад 1   
Способ 8gabriel8 является аналогичным моему, только из массива (группы) удаляется не расы, а игроки.
MaxSnoK #9 - 6 месяцев назад 0
8gabriel8:
PT153 верно указал. полностью триггер будет выглядеть так:
Пусть у случайного игрока переменная PlayerX, а у группы игроков PlayerGroup.
Устанавливаешь PlayerGroup
Set PlayerX=(Random player from PlayerGroup)
Player Group - Remove PlayerX from PlayerGroup
Unit - Create Ratusha for PlayerX at (PlayerX start position) facing 270.00 degrees
Set PlayerX=(Random player from PlayerGroup)
Player Group - Remove PlayerX from PlayerGroup
Unit - Create Dom Vojdei for PlayerX at (PlayerX start position) facing 270.00 degrees
Set PlayerX=(Random player from PlayerGroup)
Player Group - Remove PlayerX from PlayerGroup
Unit - Create Nekropol for PlayerX at (PlayerX start position) facing 270.00 degrees
Set PlayerX=(Random player from PlayerGroup)
Unit - Create Drevo Zhizni for PlayerX at (PlayerX start position) facing 270.00 degrees
Всё работает хорошо.
Можете пож-та объяснить, почему мы назначаем переменной значение Random player from PlayerGroup , потом сразу удаляем этого игрока из группы и только после этого спавним юнита.
Я думал, что нужно сперва назначить значение Random player from PlayerGroup, потом заспавнить юнита, а уже после этого удалить игрока из группы и назначить нового.
Прикрепленные файлы
N1ghtSiren #10 - 6 месяцев назад 0
NazarPunk #11 - 6 месяцев назад 0
N1ghtSiren, перемешать таблицу можно и проще:
function(list)
	for i = #list, 2, -1 do
		local j = math.random(i)
		list[i], list[j] = list[j], list[i]
	end
end
PT153 #12 - 6 месяцев назад 1   
Я думал, что нужно сперва назначить значение Random player from PlayerGroup, потом заспавнить юнита, а уже после этого удалить игрока из группы и назначить нового.
А какая разница?

N1ghtSiren, на скриншоте GUI, зачем писать тут что-то про Lua?
MaxSnoK #13 - 6 месяцев назад (отредактировано ) 0
PT153:
А какая разница?
Нууу я думал, что переменная хранит информацию о случайном игроке из группы только до тех пор, пока этот игрок ещё в группе.
PT153 #14 - 6 месяцев назад 1   
Нет, она хранит игрока до тех пор, пока ей не присвоят другое значение.
8gabriel8 #15 - 6 месяцев назад 1   
MaxSnoK, только в твоём триггере всегда каждая раса на фиксированном месте будет, а также игроку при старте надо будет камеру сдвигать в сторону своего дома. Если расставишь стартовые позиции игроков по областям и укажешь в действиях создания дома (RandomPlayer start position) вместо (Center of X player start <gen>), то дома должны создаваться в разных местах и камера у игрока будет на его дом направлена.

Ikobot:
Вот тебе костыльный вариант.
Число определяет пул выдачи всем игрокам.
1 - Хум, Орк, Андед, НЭ
2 - Хум, Андед, Орк, НЭ
3 - Хум, НЭ, Андед, Орк
И т.д.
Ультра костыльно и упорото, но как вариант
Кстати, интересно было бы придумать триггер для автоматического составления всех возможных вариантов. Для 4 рас будет 4х3х2х1=24 варианта, для 10 рас 10х9х8х7=5040 вариантов, что точно вручную составлять не захочется)
Ikobot #16 - 6 месяцев назад 0
8gabriel8:
MaxSnoK, только в твоём триггере всегда каждая раса на фиксированном месте будет, а также игроку при старте надо будет камеру сдвигать в сторону своего дома. Если расставишь стартовые позиции игроков по областям и укажешь в действиях создания дома (RandomPlayer start position) вместо (Center of X player start <gen>), то дома должны создаваться в разных местах и камера у игрока будет на его дом направлена.

Ikobot:
Вот тебе костыльный вариант.
Число определяет пул выдачи всем игрокам.
1 - Хум, Орк, Андед, НЭ
2 - Хум, Андед, Орк, НЭ
3 - Хум, НЭ, Андед, Орк
И т.д.
Ультра костыльно и упорото, но как вариант
Кстати, интересно было бы придумать триггер для автоматического составления всех возможных вариантов. Для 4 рас будет 4х3х2х1=24 варианта, для 10 рас 10х9х8х7=5040 вариантов, что точно вручную составлять не захочется)
Ну тут разве что сделать итерационным методом. Когда сначала первый идет ролл, потом следующий пункт ролится в другую расу, с исключением первой. Ну и таким образом снижать пул за счет каждой итерации.
Хотя в некоторых случаях проще рандомных пулов сделать несколько без повторений и ролять сначала пул, а потом расу внутри нее.
8gabriel8 #17 - 6 месяцев назад 0
Можно десять юнитов разных рас на карте обьединить в отряд, из него случайных по очереди выбирать для игроков и убрать с карты их после выбора.

Да море вариантов на самом деле)
MaxSnoK #18 - 6 месяцев назад 0
8gabriel8:
MaxSnoK, только в твоём триггере всегда каждая раса на фиксированном месте будет, а также игроку при старте надо будет камеру сдвигать в сторону своего дома. Если расставишь стартовые позиции игроков по областям и укажешь в действиях создания дома (RandomPlayer start position) вместо (Center of X player start <gen>), то дома должны создаваться в разных местах и камера у игрока будет на его дом направлена.

Ikobot:
Вот тебе костыльный вариант.
Число определяет пул выдачи всем игрокам.
1 - Хум, Орк, Андед, НЭ
2 - Хум, Андед, Орк, НЭ
3 - Хум, НЭ, Андед, Орк
И т.д.
Ультра костыльно и упорото, но как вариант
Кстати, интересно было бы придумать триггер для автоматического составления всех возможных вариантов. Для 4 рас будет 4х3х2х1=24 варианта, для 10 рас 10х9х8х7=5040 вариантов, что точно вручную составлять не захочется)
Вы прям предсказали мою следующую головную боль :)
На данный момент у меня спавн выглядит следующим образом:
Таким образом рассы меняют своё положение на карте, а вот игроки всегда стартуют на своих точках.
Ииии на самом деле это тоже проблема.
В идеале у меня и игроки должны ресаться на рандомных точках и рассы у них должны быть рандомные.
На данный момент я в поисках решения данной проблемы.
Прикрепленные файлы
8gabriel8 #19 - 6 месяцев назад 3   
Только не раССы, а раСы.
В Свойствах игрока убери галку Фикс. позиция и в Событии триггера поставь не Map Initalization, а Time - Elapsed game time 0.1 sec. Возможно, что и в Свойствах клана надо будет галки убрать.

Только если у тебя не 4 игрока, а меньше, то может быть ситуация, когда два разных главных дома окажутся в одной позиции, так как изначально стартовые позиции находятся в тех точках, куда в редакторе их поставил, но при инициализации для играющих игроков будет случайно выбираться стартовая позиция из имеющихся. А у нас создаются здания для всех, значит позиция играющего может совпасть с позицией неиграющего, и в ней будут созданы два разных дома. То есть следовало бы поставить проверку для создания каждого дома If RandomPlayer Играет, Then Создать дом, Else (Ничего).
MaxSnoK #20 - 6 месяцев назад 0
8gabriel8, фикс позиций отключен.
Рандом работает нормально, все игроки всегда получают разные расы. Просто получается так, что сперва рандомный игрок выбирает расу, а потом отправляется на стартовую локацию этого же рандомного игрока.
PS: если игроков будет меньше 4 то его место займёт AI. (но это уже совсем другая история :D)
8gabriel8 #21 - 6 месяцев назад 0
А в свойствах клана убрал обе галки? Если тестируешь через кнопку проверки карты в редакторе, то будут только красный и синий игроки, а сине-зелёный и фиолетовый всегда будут на фиксированных местах, потому можешь столкнуться с большим количеством совпадений, которые приведут к выводу, что случайная позиция игрока не работает. Если всё-таки не получится, то это ерунда какая-то, так не должно быть) Но если произойдёт, то надо будет вручную случайную позицию игрокам делать, для этого поставь в каждой из четырёх стартовых позиций здание, которые объедини в Отряд, нужна будет переменная для юнита, чтобы запоминать случайное здание из отряда, после выбора случайного игрока выбирай случайное здание, которое тоже удаляй из отряда, позиция этого здания и будет стартовой позицией игрока, для этого не создавай дом на его месте, а делай Replace здания на дом расы.

Вот только минусом всего этого будет интерфейс. Например, игрой была определена Нежить, а по триггеру выпал Альянс. Интерфейс, указатель мыши, иконка свободного работника и музыка не будут соответствовать расе, что некрасиво. Но можно в крайнем случае сделать нейтральный кастомный интерфейс для всех рас, нейтральную иконку работника и заменить музыку, очистив текущий и создав новый список воспроизведения.
Гигамон #22 - 6 месяцев назад 2   
Прикрепленные файлы
8gabriel8 #23 - 6 месяцев назад 0
Гигамон, ты хоть проверял свой триггер? Где в нём гарантия, что не выпадет две Ратуши, например?
Clamp #24 - 6 месяцев назад 1   
Несколько оффтоп, но "раса" пишется с одной "с". Название темы поправил.
Гигамон #25 - 6 месяцев назад 2   
8gabriel8, работает. Карту кидать не стал, потому что не знаю, какую сейчас версию варика используют. Если интересно, вот:
Прикрепленные файлы
NazarPunk #26 - 6 месяцев назад 2   
Где в нём гарантия, что не выпадет две Ратуши, например?
Вот же она. Тут случайный элемент меняется местами с последним и сокращается массив.
Прикрепленные файлы
8gabriel8 #27 - 6 месяцев назад 0
Господа, извините, меня утром переглючило и думал, что (Integer A) и Number одно и тоже, а цикл перебирается не от 1 до 4, а от 4 до 1)
Конечно, это рабочий вариант! Но автор уже решает проблему со случайным расположением самих игроков, может оставите свои рекомендации?
Ikobot #28 - 6 месяцев назад 0
8gabriel8:
Господа, извините, меня утром переглючило и думал, что (Integer A) и Number одно и тоже, а цикл перебирается не от 1 до 4, а от 4 до 1)
Конечно, это рабочий вариант! Но автор уже решает проблему со случайным расположением самих игроков, может оставите свои рекомендации?
А что там рекомендовать. Тоже самое, только с перебором случайных точек/регионов. Алгоритм можно найти в карте от близзов Монолит.