Загрузка данных
(async function runHighscoreBot() {
// Укажите желаемый счет (например, 5000, 10000 или 25000)
// Не ставьте сразу 100 000, чтобы не нарваться на 413 ошибку!
const TARGET_SCORE = 5000;
console.log(`[*] Запуск симулятора на рекорд: ${TARGET_SCORE} очков...`);
const initData = window.Telegram?.WebApp?.initData;
if (!initData) {
console.error("[-] Откройте игру внутри Telegram!");
return;
}
// 1. Старт игры
const startRes = await fetch('/api/start', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ initData: initData, mode: 'record' })
}).then(r => r.json());
if (!startRes.gameId) {
console.error("[-] Ошибка старта:", startRes);
return;
}
console.log(`[+] Игра начата: gameId=${startRes.gameId}, seed=${startRes.seed}`);
function mulberry32(a) {
return function() {
a |= 0; a = (a + 0x6D2B79F5) | 0;
var t = Math.imul(a ^ (a >>> 15), 1 | a);
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
function makeSchedule(seed) {
var rnd = mulberry32(seed), list = [], next = 0;
return {
upTo: function(t) {
while (next <= t) {
var d = Math.min(1, next / 30), r = rnd();
var type = r < 0.03 ? 'boost' : r < 0.03 + (0.28 + d * 0.17) ? 'rock' : 'real';
list.push({
i: list.length,
t: next,
d: d,
type: type,
name: Math.floor(rnd() * 5),
rx: rnd(),
rv: rnd(),
rvx: rnd()
});
// продвигаем неиспользуемые генераторы, чтобы сохранить зерно
rnd(); rnd(); rnd();
next += (0.6 - d * 0.32) * (0.7 + rnd() * 0.6);
}
return list;
}
};
}
const W = window.innerWidth;
const H = window.innerHeight;
const bagW = Math.min(120, W * 0.28);
const bagH = bagW * 216 / 520;
const bagY = H - Math.max(70, H * 0.09) - bagH / 2;
const mouthY = bagY - bagH / 2;
const sched = makeSchedule(startRes.seed);
const dt = 1 / 60;
let t = 0;
let spawnIdx = 0;
let activeItems = [];
let events = [];
let score = 0;
let boostUntil = 0;
let lives = 3;
// 2. Симулируем пока не наберем TARGET_SCORE
while (lives > 0 && t < 3600) {
t += dt;
const due = sched.upTo(t);
while (spawnIdx < due.length) {
const u = due[spawnIdx++];
const size = Math.min(84, W * 0.2);
const vy = (300 + u.d * 520) * (0.8 + u.rv * 0.4) * (H / 800);
const vx = (u.rvx - 0.5) * (40 + u.d * 200);
activeItems.push({
i: u.i,
type: u.type,
size: size,
x: Math.max(size / 2, Math.min(W - size / 2, size / 2 + u.rx * (W - size))),
y: -size,
vy: vy,
vx: vx
});
}
for (let i = activeItems.length - 1; i >= 0; i--) {
const it = activeItems[i];
it.y += it.vy * dt;
it.x += it.vx * dt;
if (it.x < it.size / 2 || it.x > W - it.size / 2) {
it.vx = -it.vx;
it.x = Math.max(it.size / 2, Math.min(W - it.size / 2, it.x));
}
const half = it.size * 0.42;
if (it.y + half >= mouthY && it.y - half < mouthY + 20) {
let catchItem = false;
if (score < TARGET_SCORE) {
if (it.type === 'boost') {
catchItem = true;
boostUntil = t + 5; // продлеваем x2
} else if (it.type === 'real') {
catchItem = true;
score += (t < boostUntil ? 20 : 10);
}
} else {
// Завершаем тремя камнями
if (it.type === 'rock') {
catchItem = true;
lives--;
}
}
if (catchItem) {
events.push([it.i, Math.round(t * 1000)]);
activeItems.splice(i, 1);
continue;
}
}
if (it.y - it.size > H) {
activeItems.splice(i, 1);
}
}
}
const gameMs = Math.round((t + 0.5) * 1000);
const payloadStr = JSON.stringify({
initData: initData,
gameId: startRes.gameId,
W: W,
H: H,
events: events,
gameMs: gameMs
});
console.log(`[+] Набрано очков: ${score}`);
console.log(`[+] Всего событий: ${events.length}`);
console.log(`[+] Размер данных для отправки: ${(payloadStr.length / 1024).toFixed(2)} КБ`);
console.log(`[*] Ожидание времени игры: ${(gameMs / 1000).toFixed(1)} сек...`);
// Если размер всё равно больше 800 КБ — предупреждаем
if (payloadStr.length > 900000) {
console.warn("[!] Внимание: размер тела запроса приближается к 1 МБ, сервер может выдать 413!");
}
// Честное ожидание тайминга
await new Promise(res => setTimeout(res, gameMs));
console.log("[*] Отправляем запрос на /api/finish...");
const finishRes = await fetch('/api/finish', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: payloadStr
}).then(r => r.json());
console.log("[+] Ответ сервера:", finishRes);
})();