(function() { // Ohjelma async-funktiona. Älä vaihda funktion nimeä! async function ohjelma(input, output) { // Tervehdys. output("Maalitaulu v1"); const tervehdys = await input(); if (tervehdys == "ping" || tervehdys != "2019-kuurupiilo") { return; } // Pelin asetukset ja esteet. const asetusrivi = await input(); const asetukset = asetusrivi.split(" ").map(s => +s); const pelaajia = asetukset[0], numero = asetukset[1]; const pelaajat = []; // Alustetaan pelaajien tiedot. for (let i = 0; i < pelaajia; ++i) { pelaajat.push({x: 0, y: 0, r: 32, kohdeX: 0, kohdeY: 0, nähtynä: 0, päivitetty: 0, etsijä: i < 3, liikkuu: false}); } const itse = pelaajat[numero - 1]; const pakoetäisyys = 900; itse.etäisyys = [0, 1000, 700, 300][numero] || pakoetäisyys; itse.vaihe = 0; function suunnista(etsijät) { function kulmaero(a, b) { let k = a - b; for (; k > Math.PI; k -= Math.PI * 2); for (; k <= -Math.PI; k += Math.PI * 2); return k; } const kulmat = etsijät.map(o => Math.atan2(o.y - itse.y, o.x - itse.x)); kulmat.sort((a, b) => a - b); // Kohti suurinta etsijöiden rakoa. let eromax, kohdekulma; for (let i = 0; i < kulmat.length; ++i) { let k0 = kulmat[i], k1 = kulmat[(i+1) % kulmat.length]; let ero = kulmaero(k1, k0); if (!i || Math.abs(ero) > eromax) { eromax = Math.abs(ero); kohdekulma = k0 + ero / 2 + Math.PI; } } // Jos etsijät ovat sumpussa, mennään 60 asteen kulmassa. if (kulmat.every(k => Math.abs(kulmaero(kohdekulma, k)) > 2)) { kohdekulma += Math.PI * 60 / 180; } // Jos etsijä ajaa reunalle, tehdään täyskäännös. if (Math.hypot(itse.x, itse.y) > 920 && Math.abs(kulmaero(kohdekulma, Math.atan2(itse.y, itse.x))) < 0.3) { kohdekulma += Math.PI; } let kohdeX = itse.x + (Math.cos(kohdekulma) * 400) | 0; let kohdeY = itse.y + (Math.sin(kohdekulma) * 400) | 0; while (kohdeX * kohdeX + kohdeY * kohdeY > 1050 * 1050) { kohdeX = (63 * kohdeX) >> 6; kohdeY = (63 * kohdeY) >> 6; } if (Math.abs(kulmaero(Math.atan2(itse.kohdeY - itse.y, itse.kohdeX - itse.x), Math.atan2(itse.kohdeY - itse.y, itse.kohdeX - itse.x))) < 0.5 && itse.vaihe < 0) { // Ei vaihdeta suuntaa jatkuvasti. } else { itse.vaihe = -10; itse.kohdeX = kohdeX; itse.kohdeY = kohdeY; } } // Ajetaan peliä. if (!itse.etsijä) { for (let i = 0; i < 100; ++i) { const rivi = await input(); if (!rivi || rivi == "0") { return; } output("800 600"); } } for (let kierros = itse.etsijä ? 200 : 100;; ++kierros) { // Kierroksen syöte: näkyvien pelaajien sijainnit. const rivi = await input(); if (!rivi || rivi == "0") { break; } const luvut = rivi.split(" ").map(s => +s); for (let i = 1; i < luvut.length; i += 6) { const n = luvut[i] - 1, p = pelaajat[n]; p.x = luvut[i+1]; p.y = luvut[i+2]; p.kohdeX = luvut[i+3]; p.kohdeY = luvut[i+4]; p.nähtynä = luvut[i+5]; p.päivitetty = kierros; } // Lasketaan ja ilmoitetaan oma siirto. if (!itse.etsijä) { const etsijät = pelaajat.slice(0, 3).filter(o => kierros - o.päivitetty < 30); itse.vaihe += 1; if (etsijät.length) { suunnista(etsijät); } else if (itse.x == itse.kohdeX && itse.y == itse.kohdeY) { let k = (Math.atan2(itse.y, itse.x) || 0) + 0.5; itse.etäisyys = pakoetäisyys; itse.kohdeX = (Math.cos(k) * itse.etäisyys) | 0; itse.kohdeY = (Math.sin(k) * itse.etäisyys) | 0; } } else if (numero == 1) { if (itse.x == itse.kohdeX && itse.y == itse.kohdeY) { itse.vaihe += 1; } switch (itse.vaihe & 7) { case 0: itse.kohdeX = 1000; itse.kohdeY = 0; break; case 1: itse.kohdeX = 707; itse.kohdeY = 707; break; case 2: itse.kohdeX = 0; itse.kohdeY = 1000; break; case 3: itse.kohdeX = -707; itse.kohdeY = 707; break; case 4: itse.kohdeX = -1000; itse.kohdeY = 0; break; case 5: itse.kohdeX = -707; itse.kohdeY = -707; break; case 6: itse.kohdeX = 0; itse.kohdeY = -1000; break; case 7: itse.kohdeX = 707; itse.kohdeY = -707; break; } } else { // Numerot 2 ja 3 kiertävät samaa matkaa ensimmäisen kanssa. itse.kohdeX = pelaajat[0].kohdeX; itse.kohdeY = pelaajat[0].kohdeY; const d0 = Math.trunc(Math.hypot(itse.kohdeX, itse.kohdeY)) || 1; itse.kohdeX = Math.trunc(itse.etäisyys * itse.kohdeX / d0); itse.kohdeY = Math.trunc(itse.etäisyys * itse.kohdeY / d0); } output(itse.kohdeX + " " + itse.kohdeY); } } // ÄLÄ VÄLITÄ NÄISTÄ: // Ohjelman suoritus. if (typeof window == "undefined") (async function run() { let finished = false, lines = [], promises = []; const exit = s => { try { process.exit(s) } catch (ex) {} try { quit(s) } catch (ex) {} }; const output = s => { try { process.stdout.write(s + "\n") } catch (ex) {} try { print(s) } catch (ex) {} }; const addInput = s => { if (promises.length) { promises.shift()(s); } else { lines.push(s); } }; const input = () => { if (finished) return; try { addInput(readline()); } catch (ex) {} if (lines.length) return lines.shift(); return new Promise(r => promises.push(r)); }; try { require("readline").createInterface({input: process.stdin}).on("line", addInput).on("close", () => finished = true); } catch (ex) { } try { await ohjelma(input, output); exit(0); } catch (ex) { output("ERROR: " + ex); console.error(ex); exit(1); } })(); return ohjelma; }())