# Specifikace Následující dokument obsahuje specifikaci závodu, pokud ji chcete implementovat ve vašem oblíbeném jazyce. Aby závod fungoval stejně v každé implementaci, **všechny výpočty jsou prováděny pomocí 64-bitových celých čísel**. ## Objekty V rámci závodu definujeme tyto objekty: ```python class Racer: # (loď) x: int y: int vx: int vy: int radius: int ``` ```python class Asteroid: # (asteroid) x: int y: int radius: int ``` ```python class Goal: # (gól) x: int y: int radius: int ``` ```python class Instruction: # (instrukce) vx: InstType vy: InstType ``` ```python class BoundingBox: # (okraj) min_x: int min_y: int max_x: int max_y: int ``` ## Simulace Každý krok simulace lze rozdělit do následujících tří fází: 1. **pohyb lodi** podle zadané instrukce 2. **řešení kolizí** 3. **kontrola dosažení cíle** (označení splněných cílů) Tyto kroky jsou podrobně vysvětleny v následujících sekcích. _Poznámka 1: Pro účely optimalizace je k ukládání asteroidů a cílů vhodné použít nějakou datovou strukturu (například 2D slovník nebo K-d strom), aby stačilo kontrolovat kolize pouze okolo aktuální pozice lodi. Nezapomeňte zohlednit poloměr lodi!_ _Poznámka 2: Celá část druhé odmocniny, kterou simulace používá, odpovídá Python funkci `math.isqrt`, která vrací „největší celé číslo takové, že a² ≤ n.“ Tato implementace je přesná a nevyužívá plovoucí desetinnou čárku._ ### 1) Pohyb lodi S danou instrukcí `(vx, vy)` se loď pohybuje podle následujících pravidel: - zpomalí se o 10 %: `racer.velocity = (racer.velocity * 9) // 10` - k její rychlosti se přidá instrukce: `racer.velocity += (vx, vy)` - závodník se posune podle své rychlosti: `racer.position += racer.velocity` Je důležité poznamenat, že **operátor dělení zahodí desetinnou část čísla.** To znamená, že Pythoní celočíselné dělení nefunguje korektně pro záporná čísla (`-5 // 2 = -3`), což je v našem případě špatně. Jedním ze způsobů, jak to napravit, je použít `abs(x) // v * signum(x)`, což zajistí správný výsledek. Instrukce je platná pouze tehdy, pokud **její délka** (euklidovská vzdálenost) **nepřesáhne `127`**. Kontrola délky instrukce se provádí porovnáním čtverců délky instrukce a maximálního zrychlení (`distance_squared(vx, vy) > 127 ** 2`). ### 2) Řešení kolizí Kolize se řeší v **1 až 5 podkrocích**. V rámci každého podkroku se nejprve kontrolují kolize se všemi asteroidy a poté s ohraničujícím boxem. Pokud dojde ke kolizi během podkroku, kolize se vyřeší (viz. níže) a **okamžitě se zahájí další podkrok,** dokud není dosažen limit (5). Pokud během celého kroku dojde ke kolizi, rychlost závodníka se sníží na polovinu. Toto zpomalení může nastat nejvýše **jednou za krok**, bez ohledu na počet kolizí v individuálních podkrocích. #### Asteroidy Iterujeme přes všechny asteroidy `asteroid` v pořadí, v jakém byly přidány do simulace, a pro každý provádíme následující kroky: - Pokud `euclidean_distance(asteroid, racer) > (asteroid.radius + racer.radius)`, kolize nenastala (pokračujeme k dalšímu asteroidu). - V případě kolize provedeme následující: - Spočítáme vzdálenost: `distance = euclidean_distance(asteroid, racer)` - Vektor k vytlačení závodníka: `vn = racer.position - asteroid.position`. - Vzdálenost posunutí: `push_by = distance - (asteroid.radius + racer.radius)`. - Posuneme závodníka: `racer.position -= (push_by * vn) / distance`. #### Ohraničující box Pro každou stranu boxu zkontrolujeme kolizi (například pokud `racer.x - racer.radius < box.min_x` pro levou stranu). Pokud ke kolizi dojde, posuneme závodníka zpět k hranici boxu. ### 3) Kontrola dosažení cíle Iterujeme přes všechny cíle `goal` a označíme je jako dosažené, pokud `euclidean_distance(racer, goal) <= (racer.radius + goal.radius)`, tedy pokud dochází k jejich průniku. ### Poznámky Všimněte si, že simulace používá několik neintuitivních zjednodušení: - při úvodním posunu lodi o její rychlost **nekontrolujeme** kolize - kolize kontrolujeme až jako průsečík finální pozice lodi s asteroidy či cíle - při kolizi s asteroidem se loď **neodrazí**, tedy nezmění se směr její rychlosti - při řešení kolizí loď pouze posouváme ven z asteroidů - při kolizi nezáleží na tom, v jaké fázi řešení podkroků vydělíme rychlost lodi dvěma