M.A.X.    Вы вошли как гость
Российский Клуб игроков M.A.X.
 
[Новости]   [Новичку]   [Энциклопедия]   [Документы]   [Файлы]   [Игроки]   [Архивы]   [Архив форума]  
[Новый сайт]   [M.A.X. Gold]   [Партии]  

 
 
 
Архив форума  МаксГолд
[Основной форум] [Голосования] [МаксГолд] [Off-Topic]
 


Третий вариант  -  Artlav,  09.02.2011  21:08:10

Во-превых, я наверное поспешил просить крепко задумываться, так как постановка меняется раз в 12-24 часа по мере моего обдумывания задачи.

Во-вторых, вторая ветка обсуждения тут - http://www.gamedev.ru/code/forum/?id=143859

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



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

-Обработка возможно как по временной схеме без изменений (для запросов), так и по постоянной с записью изменений
-У юнита есть единое состояние включенности, при котором он потребляет и производит, это состояние может быть константой (невыключаемый юнит) или переменной
-Потребляющий юнит не может быть невыключаемым
-Чисто производящий юнит может быть невыключаемым
-У юнита есть приоритет (есть или нет, два варианта)
-Хранение и долги юнит даёт всегда, отказаться нельзя (нельзя закрыть склад или перекрыть трубу)
-Проводимость у юнита постоянная (проводит либо не проводит)

-Все ситуации и события считать в пределах одного домена (ниже), конец хода перебирает все домены



Данные:
-У каждого юнита для каждого ресурса хранится рабочая и временная структуры:
--=num Емкость хранилища
--=use Потребить в этом ходу
--=next_use Потребить на следующем ходу (строитель может иметь непостоянное потребление, при просчёте конца хода это надо учесть)
--=now Имеется на борту
--=pro Произвести за этот ход
--=dbt Долг за этот ход, необходим чтобы определить, а можем ли мы включить что-то
--=isact Включенность

-Каждое здание хранит в себе номер домена (комплекса), который обновляется при соответствующих событиях созидания и разрушения (вне проблемы данной задачи, считать всегда правильными)
-По определению все здания в одном домене связаны, все здания с разными доменами не связаны
-Номер домена не имеет географической или игроковой привязки, это величина, объединяющая связанные на данный момент группы юнитов конкретным идентификатором



События игры:
-Создан юнит
--=Выключенный или постоянно производящий, включение - отдельное событие, у постоянно включенного то же, но сразу после создания
--=Может изменить связность, но не влияет на распределение
--=Ничего менять не надо

-Убран юнит
--=Взорван, вероятна потеря связности. Нужно обновить от всех, кто рядом с ним
--=Вырублен диверсантом, не потеряна связность. Нужно обновить от него

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

-Остановлен юнит
--=Запросить возможность остановки, по временной схеме
--=В случае успеха повторить на основной схеме или скопировать в неё
--=В случае неуспеха не останавливать, сообщить игроку чего не хватит

-Изменено потребление/производство юнита
--=Запросить разницу как запрос добавления/остановки, по временной схеме. Один ресурс за событие
--=В случае успеха повторить на основной схеме или скопировать в неё

-Заменён юнит (удалён-создан без изменения связности, например здание построено на трубах)
--=Ресурсы не задействованы, удалить и создать без запросов к распределителю

-Передача материалов
--=Проверить на связность, если да - то передать долг вместе с материалом, если нет, то следующий такт.
--=Если долг превышает остаток+производство, то сделать долг равным производству и обновить, иначе ничего не делать



Обновление:
-Возможные конечные ситуации:
--=Всё ОК
--=Долги остались, потребитель пропал
--=Потребление осталось, долги пропали
-Решение:
--=Суммировать всё потребление и суммировать все долги
--=Вычесть из долгов потребление, остаток долга освободить или избыток добавить (запрос добавления долга по временной схеме)
--=При нехватке производства последовательно по возрастанию приоритета искать потребляющий юнит с наименьшим производством и останавливать, повторяя запрос на добавление долга
--=При успешности запроса на добавление долга записать его в постоянную схему



Конец хода:
-Требования:
--=Нужно удовлетворить потребности
--=Нужно остановить тех, кто не получил по потребностям
--=Нужно положить избыток в хранилища (возможно, что произведено больше, чем влезет, но будет потрачено и влезет)
--=Нужно обновить потребления у производителей
--=Всё должно быть целостным
-Решения:
--=Перебирать последовательно все домены
--=Предположить что всё обновлено, либо вызвать обновление.
--=Произвести всё, доложить в хранилища не учитывая их размера
--=Вычесть все свои долги, из хранилищ. Производство учитывается переполнением хранилищ
--=Отсечь избыток из хранилищ, распределив его по остальным и выбросив не влазящее (запрос на немедленную клажу в себя распределит по соседям избыток, и вернёт остаток что не влез - его удалить)
--=Пересчитать потребление - продвинуть на шаг строительство, и т.п. (use=next_use, обеспечить корректность next_use до вызова конца хода)
--=Обновить



Функции:
-Обновить
-Конец хода
-Передача

-Запрос на добавление ресурса немедленно
--=Не меняет балансировку
--=Перебрать всех в домене, кладя по мере нахождения пустот, выйти при иссякании запроса, или вернуть не доложенное как результат

-Запрос наличия:
--наличия ресурса (сумма хранения)
--наличия свободного места (сумма пустоты)
--наличия свободного долга (сумма производства и хранения)
--наличия свободного ресурса (хранение минус max(0,(долг минус производство)))
--=Перебрать всех в домене, суммируя требуемое, и вернуть сумму как результат

-Запрос на добавление долга
--=Перебрать всех в домене по временной схеме, добавляя долг
--=Если не хватит, то откатить и начать поиск объекта для запуска, запустить его, и вернуться в начала
--=Если хватило, то перенести временное в постоянное, иначе вернуть отказ
--=Что если хватило одного ресурса, но не второго? Электростанции останутся запущенными, и всё?

-Запуск юнита (нужно думать):
--=Проверить необходимость потребления, если нет, то всё
--=Если есть потребление, то по отдельности на каждый ресурс запросить долг по временной схеме
--=Если хватило, то запросить долг по основной

-Остановка юнита:
--=Если нет производства, то освободить потребление и всё
--=Если есть производство, то по временной схеме запросить эквивалентное число долгов (исключая себя)
--=Если хватило, то выключится и запросить по основной схеме, освободить потребление, и готово



Проблемы:
Раздельность:
-Если обновлять ресурсы по отдельность, то как гарантировать то, что обновление одного не угробит обновление другого?
-Как решить задачу оптимизации по потреблению? Если надо выключить юнит, который снабжает другие юниты? (две станции, мало бензина. Которую гасить?)