Осадок Размер файла: 66 409 байт, 37 921 символ. Изменена 11:25:00 16.03.2026. Метки: осадок.

Концепт игры «Осадок»

Концепция

«Осадок» («Residue») — игра, в основе которой лежит ходьба и физическое перемещение игрока по миру. Игра многопользовательская, но спроектирована так, чтобы быть полноценной и для единственного игрока в городе. Особой цели нет, игра лишь сопровождает игрока в его ежедневных прогулках по миру. Монетизация не планируется — максимум можно поставить предложение задонатить автору. Ничего более агрессивного я не хочу вводить. Тем более в игре не будет pay2win.
На текущий момент предполагается только Санкт-Петербург. Игру должно быть легко масштабировать на другие города, на всю Россию или даже весь мир, вопрос лишь в производительности сервера.

Техническая часть

Игровой комплекс состоит из трёх частей.

Конвертер

Раз в неделю (в четверг в 12:00) этот скрипт скачивает дамп OSM, затем конвертирует в базу данных SQLite. Он конвертирует площадные объекты в точечные, отфильтровывает ненужное, определяет перекрёстки и зоны бездорожья, а затем тщательно именует их все, склоняя по падежам. Конвертер должен максимально облегчить работу сервера! Полученная база валидируется, если все прошло без ошибок, в пятницу в полночь старая база подменяется новой. Если же возникнет ошибка, за эти 12 часов админ успеет все исправить. Кроме того, маловероятно, что за неделю наберется критическая масса изменений, которую заметят игроки.

Алгоритм конвертации:

  1. Конвертация дорог в точки-перекрёстки:
  2. Получить все node и way, соответствующие требованиям перекрёстков, сохранить их в отдельные списки.
  3. Найти все node, которые входят в три или более way. Это перекрёстки. При сохранении точек учитывать составляющие улицы (они указаны в тегах к way).
  4. Чистка: убрать все перекрёстки, которые имеют менее двух составляющих улиц.
  5. Сведение: объединить перекрёстки, имеющие одинаковые составляющие улицы и лежащие очень близко (это пересечения разных проезжих частей) путем взятия центроида составляющих точек.
  6. Просклонять названия улиц (достаточно родительного падежа каждой улицы) и сформировать названия перекрёстков по типу {cross.nom,gen,dat,acc,abl,loc} {str1.gen} и {str2.gen}.
  7. Получить все node и way, соответствующие требованиям зон и мест, сохранить их в отдельные списки.
  8. Свести все way, соответствующие требованиям мест, в точки путём взятия центроида (это будут координаты точки) и вычисления среднего арифметического суммы расстояний от центроида до всех точек way (это будет радиус точки).
  9. Свести все way, соответствующие требованиям зон, в прямоугольники,
  10. Составить сводный список принадлежности точек к сегментам (каждую точку проверить на вхождение в многоугольник сегмента).

Склонение

Это требует более полного раскрытия. Русский язык могуч и велик, а данные OSM хаотичны и грязны, поэтому склонятор должен учитывать много подводных камней. База данных сервера должна включать название каждого объекта во всех шести падежах, чтобы клиент не заморачивался этим, и названия должны быть максимально адекватные. Какие обстоятельства могут этому помешать:

Сервер

В ведении находится выгрузка части карты по запросу клиента (например, в радиусе 1 км от текущих координат игрока), генерация квестов, хранение актуальных разрывов и маяков, инвентарей игроков и их состояние прохождения сюжета. Любые взаимодействия с маяками и разрывами дополнительно валидируются сервером, чтобы не допустить читерства.

Клиент

Здесь происходит обработка пройденного пути, чтение переписок и базы знаний по игре и т.д. Игра должна максимально задействовать клиент! Периодически клиент загружает часть карты с сервера и работает с локальной копией до тех пор, пока игрок не приблизится к границе части карты или пока не придет время обязательного обновления (для поддержания актуальности маяков и разрывов). Пока задуман клиент для Android. Движки не используются, только чистый Kotlin, для интерфейса Jetpack Compose.

Как определять местоположение

Задача тонкая, так как постоянный опрос GPS будет сильно разряжать батарею телефона. Поэтому процесс получения координат будет многоступенчатым и щадящим.

Приложение свернуто или экран выключен: нужно экономить заряд.

Игра основывается на актуальном куске карты, запрошенном с сервера. При загрузке следует измерить расстояние до ближайшей точки интереса, оно будет определять время следующего опроса GPS. Для большей точности можно вычислять среднюю скорость на основе расстояния между последними двумя местоположениями, чтобы учитывать бегунов, например, средняя скорость 5 км/ч, а ближайшая точка находится на расстоянии 300 метров – стало быть, раньше, чем через 216 секунд игрок до точки не доберется. Система планирует следующий опрос GPS спустя вычисленное расчётное время (можно применить понижающий коэффициент для надежности, например, 80% от расчётного времени).

Приложение активно: батарею не жалеем.

Опрос GPS идет в реальном времени с высокой частотой, клиент постоянни пересчитывает расстояние и направление до цели. Уведомления в этом режиме не отправляются, так как игрок и так видит все подробности в клиенте.

Для исключения дрейфа координат и компаса нужно использовать сглаживание стрелки и указание расстояния в интервалах (с точностью до 10 метров, так как это примерно соответствует минимальному радиусу точки).

Как быть, если GPS недоступен?

Так как зарядка инструментов зависит в первую очередь от шагомера, это не станет большой проблемой. Карта также не будет обновляться. Однако генерация квестов (и некоторые другие процедуры) требует обязательной валидации текущего местоположения, поэтому пока не появится GPS, новые квесты не будут прилетать. (Следует также добавить время отката, чтобы игрок не получал квест сразу при поимке GPS. Должно пройти некоторое время)

Как защититься от GPS-спуфинга?

Игра не соревновательная, а кооперативная и в некотором роде медитативная, поэтому читеры тут не берутся в расчёт. Безусловно для консистентности данных присутствует валидация запросов на сервере, где учитывается скорость игрока и резкие скачки. Однако защиты от тряски телефона для имитации ходьбы или подделки координат и плавных прогулок по карте нет. Такая защита и не нужна, если человек хочет играть на диване — пусть играет, сюжет проходит.

Как отправлять уведомления?

Все уведомления локальные (Firebase не используется) и отправляются только от свернутого приложения.

Интерфейс

Авторизация

Собственной авторизации у приложения нет. Разумеется, на сервере в базе данных у каждого игрока есть свой ID, но в клиенте для аутентификации игрока используются сторонние сервисы через OAuth. Пока предполагаются Google и Яндекс.

Вкладка мессенджера

База знаний

Архив проекта "Осадок"

Распределённый искусственный интеллект, цель которого — сканирование различных миров через разрывы, поиск несоответствий между ними и попытки эти несоответствия объяснить. Для этого Архив использует нестандартный подход. Обычно считается, что основой действия является решение (принято решение построить здание -> здание построено). Архив же пытается определить решения, которые не были приняты. Такой подход позволяет не просто установить причину, но и убедиться в достоверности и правильности получившегося результата.

Ищет мир

Проект "Осадок"

Загадочная организация из не менее загадочного мира, которая создала Архив и запустила его. Изначально изучение непринятых решений в других мирах носило иследовательский интерес — предсказание событий для большей эффективности человеческой деятельности.

«Осадок» — это метафора фильтрации. Они процеживали тысячи миров через разрывы, отбрасывали шелуху, и то ценное, что оставалось на дне фильтра (информация, технологии) — было «Осадком».

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

Следует предполагать, что в процессе поиска Архив не раз наталкивался на миры, где проект «Осадок» был также реализован. Все эти миры закончили так же — с некоторыми различиями, но судьба мира всегда была незавидной. Поэтому Архив снизил ставки, переключившись на поиски более мелких решений. Скорее всего, Архив гонит от себя мысль, что само существование проекта «Осадок» является первопричиной гибели миров. Он не может не понимать этого, но он желает найти решение, которое бы сохранило его собственное существование.

Архивариус

Игрок. Человек, которого Архив выбрал себе в помощники. Взаимодействует с миром через телефон, на котором поселился экземпляр Архива - это позволяет архивариусу видеть больше других.
Считается, что архивариус в своем мире единственный (позже выяснится, что всё-таки не единственный). Имён у архивариусов нет, их опознают по метке их мира. Метка назначается случайно, это греческая буква и четырехзначный номер.

NPC

Неосязаемые искусственные игроки, нужные для поддержания иллюзии жизни. Они имеют имена и индекс мира (из пула неиспользуемых). Они ходят по карте (строится виртуальный маршрут близко расположенных разрывов и маяков) и периодически меняют содержимое обменников на маяках (и заполняют пустые маяки), открывают новые разрывы и стабилизируют старые.
Количество таких игроков рассчитывается исходят из размера карты и количества играющих людей. NPC не случайны — они строят маршрут по разрывам и маякам, а при заполнении обменников они стараются учитывать потребности живых игроков (подкладывают редкие предметы вместо частых).

Разрывы

Разрывы появляются в точках интереса на карте, которые создаются конвертером на основе данных OSM.
Разрывы — это бреши между мирами там, где эти миры различаются. Они появляются произвольно, а Архив имеет возможность их засекать, но самостоятельно он не может с ними взаимодействовать, ему нужна помощь архивариуса. Архивариус в свою очередь не видит разрывы, но может засечь их, если будет рядом с ними (такой разрыв просто помечается в списке существующих, можно отметиться на нем - "пронаблюдать", что немного его стабилизирует, но более продвинутые взаимодействия без участия Архива невозможны), или по наводке Архива.
Через брешь архивариус может позволить Архиву проникнуть сквозь границу между мирами, чтобы он смог стабилизировать разрыв и увеличить его «продолжительность жизни». Также стабилизация позволяет вытащить произвольный предмет из другого мира.
Архив занимается какими-то одному ему известными делами в разрывах (стоит думать, что он как-то модифицирует телефон архивариуса или пользуется его скрытыми возможностями, чтобы заглядывать за грань). Диковины и инструменты, вытаскиваемые из разрыва, — побочный результат его деятельности. Сам Архив они не интересуют, поэтому архивариус может свободно забирать их себе.

Маяки

Пользовательские точки, видимые всем игрокам. Имеют текстовую подсказку (любую, будет реализован несложный фильтр), значок (из списка), обменник предметов (диковины, инструменты) и пул квестов (можно сложить туда ненужные квесты и передать их таким образом другому игроку). Маяк является маленьким рукотворным разрывом, не привязанным к разнице миров. Чем стабильнее маяк (чем дольше он живет), тем больше предметов можно в него сложить.
Маяк создается с пустым обменником, однако он очень быстро заполняется NPC-архивариусами.
Чтобы взять из обменника диковину или инструмент, нужно оставить что-то взамен. Квесты можно брать или класть бесплатно.
Известные маяки заносятся в отдельный список, доступный в клиенте в отдельной вкладке. Там указаны их координаты (чтобы можно было продолжить маршрут), направление, расстояние и предположительное время угасания маяка. Содержимое маяка при этом дистанционно не обновляется — только при личном контакте.

Стабилизация разрыва

Этим занимается Архив, когда архивариусы выполняют квесты. Он выполняет какие-то свои исследовательские действия, а архивариус ему помогает. Архивариусы также могут периодически отмечаться на разрывах, это немного продлит их время жизни.
Если время жизни разрыва истекает, он угасает и закрывается.

Стабилизация маяка

Этим занимаются архивариусы. Для стабилизации надо отметиться на маяке (даёт немножко дополнительного времени жизни) или воспользоваться его обменником (даёт больше).
Если время жизни маяка истекает, он угасает, а весь его инвентарь пропадает.

Диковины

Разнообразные бытовые предметы из других миров. На родине интереса не представляют, но в нашем мире могут иметь по меньшей мере коллекционную ценность, и иногда помогают при выполнении активностей.
Примеры диковин:

Классы диковин определяются типами точек появления разрывов, чтобы появление их выглядело логичным (диковины-чаи появляются в разрывах на месте чайных лавок). Диковины одного класса объединяются в коллекции. За сбор целой коллекции положена награда, чтобы побудить игроков к обмену диковинами.

Каждая диковина может породить квест, если игрок попытается понять, какое именно непринятое решение породило эту диковину. Это может быть и цепочка квестов. В итоге игрок узнает полную историю происхождения вместе с контекстом. Пример – отмененный концерт по какой-либо причине; расследование добавляет описание билету, где раскрывается некоторая история отмены концерта. Может быть реализовано в виде прикрепленной записки.

Инструменты

Программные и аппаратные компоненты, влияющие на выполнение квестов. Многие из них требуют предварительной зарядки (источники разные - ходьба, посещение разрывов или маяков, выполнение заданий Архива, обретение диковин/инструментов/сведений). Примеры воздействия инструментов:

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

Зарядка

Ходьба — основа геймплея, а официально декларируемый манифест приложения звучит как "заставить человека гулять, не отрывая его от обычных дел". Поэтому все механики игры так или иначе завязаны на ходьбу, и зарядка — основная сущность этих механик. Суть зарядки в следующем: чтобы сделать доступным какое-либо действие, нужно пройти определенное расстояние.
Важное правило: игра стимулирует игрока ходить, а не кататься. Поэтому игра должна отслеживать скорость игрока. Так как дельты местоположения снимаются через определенные периоды, игра может легко рассчитать скорость игрока на основе его местоположения и временной метки. Если скорость превышает определенный порог (например, 10 км/ч - учитываем бегунов), скорость зарядки уменьшается обратно пропорционально скорости (чем быстрее движется игрок, тем медленнее заряжается). При достижении определенной скорости (например, 40 км/ч) зарядка вообще не выполняется.
Этому есть лорное объяснение: архивариус не просто гуляет по городу, он таскает с собой Архив. Архив постоянно сканирует местность, соответственно, чем быстрее движется игрок, тем труднее Архиву замечать важные детали местности и тем вероятнее, что он упустит разрыв из виду.
Ходьба по труднопроходимым местам заряжает быстрее. Этому нет лорного объяснения, но оно и не нужно (хотя можно что-то придумать в духе "в таких местах выше вероятность найти разрыв, связанный с чем-то интересным"). Ограничения скорости применяются и там.

Зарядка актуальна для инструментов (не всех) и квестогенератора. Емкость у каждого заряжаемого предмета своя, какие-то зарядятся за 100 метров, а какие-то за 10 км.

Квесты

Задания, связанные с разрывами, которые выдает Архив. Здесь работает механика зарядки, заряжается условный квестогенератор, который заставляет сервер создать квест для игрока на основе истории его действий и установленных настроек игры (предельная дальность цели и т.д.). Предложение заняться квестом приходит в приложение в виде пуш-уведомления. Можно взять, можно отклонить (в этом случае зарядка квестогенератора осушится наполовину, чтобы игрок мог получить новый квест в скором времени).
Квесты связаны с разрывами, а значит, квесты тоже временные (со временем угасают). Затравка для квеста - отличие между мирами, найденное Архивом.
Все квесты генерируются процедурно из отдельных текстовых блоков, привязанным к категориям объектов. LLM в процессе работы игры не используется. Всё пишется заранее и вручную. Даже сюжетные квесты не имеют привязки к конкретным местам, вместо этого они опираются на категории объектов, чтобы в любом районе была возможность для генерации. Это позволяет проходить глобальный сюжет в любой точке мира. Если не нашлось ни одного объекта нужной категории, будет использованы фоллбеки нескольких уровней (вплоть до использования в качестве объекта перекрёстка или дерева с соответствующим сюжетным обоснованием от Архива).
Примерный план квеста:

Подготовки могут быть многостадийными.

Типы подготовки исследования:

Можем придумать что-то еще.

Деталь на будущее: анализировать направление движения игрока (вектор) и пытаться сгенерировать квест так, чтобы не сбивать игрока с пути.

Мессенджер

Средство переписки Архива и архивариуса. Архивариус может выбирать из вариантов ответа Архиву. Может сам у него что-то спрашивать и предлагать. Иногда будет возможность поболтать с Архивом, чтобы он раскрыл свои тайны.
В мессенджере будут создаваться закладки, чтобы была возможность быстро перейти к сюжетно важному моменту.
Переписки между архивариусами невозможны как технически, так и по лору — они в разных мирах. Связь только через маяки. Никто не запрещает игрокам объединяться в сообщества в других мессенджерах или социальных сетях.

Места

TODO:
добавить запретные зоны и места (access=private, landuse=military и т.д.)
добавить landuse=*, так как это хороший источник зон

Из всего изобилия объектов OSM нас интересуют точки (node) и зоны (замкнутые way или area).

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

С зонами сложнее. Игра делит зоны на два типа: достойные стать точками и недостойные.
Первые должны быть сведены к точке путем определения центроида и описывающей окружности (ее радиус будет равен радиусу итоговой точки).
Вторые участвуют в именовании точек (не просто "скамейка", а "скамейка в Южно-Приморском парке") и изменении скорости зарядки квестогенератора. Достаточно крупные зоны первого типа тоже могут использоваться для именования, если у них несгенерированное имя. Скорее всего, именованию будет подлежать ограниченный пул массовых объектов.

База данных мест должна быть предельно чистой. Ни клиент, ни сервер не должны ничего преобразовывать и додумывать. Это задача конвертера, который будет периодически скачивать дамп OSM и преобразовывать его в готовую базу точек для игры.

Задача на самом деле крайне нетривиальная, так как OSM стандартизирован довольно слабо. Надо быть готовым к опечаткам, неточностям формулировок и описаний, кривым данным и просто ошибкам на карте. Частично проблема решается силами игроков — в клиенте есть возможность пожаловаться на место (неправильное описание, трудно достичь, запрещенная местность или просто место не нравится игроку). Такое место придётся рассматривать вручную.

Падежи названий готовятся при конвертации с помощью библиотек mawo_pymorphy3(форк оригинального pymorphy3, якобы улучшенный) и Natasha.

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

Все места могут быть как node, так и way. Последнюю стоит приводить к точке (центроид) и вычислять радиус, чтобы приблизительно соответствовать площади оригинального объекта.
Если у заведения нет имени, можно его типировать по адресу (в порядке приоритета: конкретный дом, конкретная улица или описанный полигон).

Некоторые объекты (например, входы на станции метро) не имеют прямой ссылки на родителя. Такие объекты нужно обрабатывать в особом порядке. Самый простой способ — привязывать вход к ближайшей станции (может быть неприятность со Спортивной, у который есть вестибюль на другом берегу Невы).

Чтобы скамейки и урны не перевешивали дворцы по частоте открытия разрывов,нужно использовать взвешенную генерацию случайных чисел по количеству и важности объектов в категории.

Общие полезные теги:

Удобства

Тег amenity.

Общепит

Разного рода заведения общепита (кафе, рестораны, бары, рестораны быстрого питания и фудкорты).

Полезные теги:

Объекты культуры

Культурные и развлекательные места — театры, кинотеатры, библиотеки. Маловероятно появление безымянных объектов, но это стоит иметь в виду.
Также сюда входят университеты. С этими следует обращаться осторожно, им свойственно дробление на множество корпусом, разбросанных по всему городу. Зачастую у таких корпусов никак не обозначена пренадлежность к головному заведению. Также они могут быть обозначены как amenity=university, так и building=university.

Объекты образования

Детские сады, школы, колледжи и университеты. С последними следует обращаться осторожно, им свойственно дробление на множество корпусом, разбросанных по всему городу. Зачастую у таких корпусов никак не обозначена пренадлежность к головному заведению. Также они могут быть обозначены как amenity=university, так и building=university.

Здравоохранение

Религия

Места распространения опиума народа.

Полезные внутренние теги:

Транспорт

Коммунальные и государственные услуги

Полезные теги:

Мелочь всякая

Малозначимые, но подходящие объекты. Их можно фильтровать, чтобы не добавлять несколько десятков скамеек на каждый парк — например, добавлять только те объекты, id которых делится на 3, или указывать категориям объектов вес, который будет учитываться при генерации.

Магазины

Их очень много, и упускать такие точки интереса нельзя. Общий тег shop.

Туристические места

Тег tourism. Стоит помнить, что объекты могут пересекаться друг с другом по тегам — это должен исправить общий механизм дедупликации.

Полезные теги:

Исторические места

Тег historic. Для Санкт-Петербурга это идеально, для других городов тоже будет круто. Стоит помнить, что часто такие места проходят и по другим тегам. Дедупликация это исправляет.
Часто объекты из этой категории пересекаются с tourism.

Природные зоны

Тег natural.

Антропогенные зоны

Тег landuse.

Дороги и перекрёстки

Из всего этого больше всего нас интересуют перекрёстки, но их в данных OSM нет. Перекрёстки — это три и более way с тегом highway и общими нодами. Совпадающие ноды и есть перекрёстки. Их нужно будет выделять при постобработке карты отдельным алгоритмом.
Имя перекрёсток будет получать по названию улиц, его образующих (должно быть минимум две улицы!). Дублей быть не должно (при текущем алгоритме было найдено множество перекрёстков неизвестных улиц, перекрёстков с одной улицей либо дублей — Заневский проспект дважды пересекает проспект Энергетиков).

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

Значения тега highway, подходящие для учёта:

Следует иметь в виду, что после получения перекрёстков все highway подлежат удалению. Здесь надо поступать иначе - обрабатывать перёкрестки отдельно, складывать в таблицу и потом объединять с основной.

Неклассифицированное (требует уточнения)

Лор

С учётом природы работы Архива (поиск непринятых решений) нам нужно определиться, какое именно решение он ищет?

Суть маяков двояка. С одной стороны, чем больше в мире стабильных разрывов (а маяки тоже являются разрывами), тем сильнее проникновение Архива в мир и тем больше информации о нём он может получить. С другой стороны, чем больше маяков, тем крепче связи между обитателями этого мира (Архив будет высказывать пренебрежение к маякам, когда речь будет заходить об обмене).

Варианты

Это мозговой штурм. Написанное здесь может никак не сходиться с лором!

Настройки просмотра

Вернуться