acombine.ru
← все заметки

Боты, которые добивают лобби за 10 секунд

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

Решение банальное и честное: если за короткое время реальные соперники не набрались, добиваем стол ботами. Весь фокус в том, чтобы это ощущалось нормальной игрой, а не отпиской.

Правило десяти секунд

Игрок нажимает «играть» и попадает в лобби. Дальше сервер ждёт: если за 10 секунд собралось нужное число живых — стартуем сразу. Если нет — досаживаем ботов до полного состава и всё равно стартуем. Игрок почти никогда не ждёт дольше десяти секунд.

// упрощённо, на стороне сервера
setTimeout(() => {
  const need = seats - lobby.humans.length;
  for (let i = 0; i < need; i++) lobby.add(makeBot());
  startMatch(lobby);
}, 10_000);

// а если живых и так набралось — стартуем раньше
function onJoin(p) {
  lobby.humans.push(p);
  if (lobby.humans.length === seats) startMatch(lobby);
}

Чтобы бот не выдавал себя

Технически посадить бота легко. Сложнее — сделать так, чтобы он не читался мгновенно. Что помогло мне:

Цель бота — не выиграть, а сделать матч живым, пока в игре мало людей. Хороший бот проигрывает достаточно часто.

Тихая подмена на живого

Приятный бонус: если посреди матча с ботами подключается живой игрок, а кто-то из ботов ещё не «занял ключевую роль», сервер может отдать место человеку. Для остальных за столом ничего не меняется. Так лобби с одним живым игроком постепенно превращается в лобби с несколькими, и никто не замечает шва.

Этот механизм я вынес в тот самый маленький игровой сервер на Go, о котором упоминал на главной. Он ничего не знает про правила конкретной игры — только про лобби, места и таймеры, — поэтому переезжает из проекта в проект почти без правок.

← все заметки