W tym wyzwaniu musisz zaprojektować gatunek organizmów jednokomórkowych, które będą walczyć na śmierć i życie na arenie Petriego. Arena jest reprezentowana jako prostokątna siatka, w której każda komórka zajmuje jedno miejsce:
.....x....
...x...o..
...x.c..o.
.......o..
Atrybuty
Każda komórka ma trzy atrybuty. Określając gatunek komórek na początku gry, przypisujesz 12 punktów do tych atrybutów.
- Punkty wytrzymałości (HP): Jeśli HP komórki spadnie do zera, umiera. Nowe komórki mają pełne HP.
- Kiedy komórka umiera, pozostawia zwłoki, które mogą zostać zjedzone przez inne komórki w celu uzyskania energii.
- Komórka nie może odzyskać utraconego HP, ale może utworzyć nową komórkę z pełnym HP, dzieląc.
- Energia : większość działań, jakie może podjąć komórka, wymaga energii. Aktywnie odpoczywając, komórka może odzyskać utraconą energię do maksimum swojego gatunku.
- Gatunek komórek o energii mniejszej niż 5 prawdopodobnie zawiedzie, ponieważ nie może się podzielić, aby utworzyć nowe komórki.
- Komórka nie może odzyskać energii przekraczającej maksymalną wartość swojego gatunku.
- Nowo utworzona komórka ma początkową wartość energii skopiowaną z jej rodzica (i maksymalną wartość podyktowaną specyfikacją gatunku).
- Kwasowość : Jeśli komórka zdecyduje się eksplodować, poziom kwasowości komórki jest wykorzystywany do obliczania uszkodzeń sąsiednich komórek.
działania
W każdej turze każda komórka może wykonać jedną akcję:
Przesuń: komórka porusza się o jedno pole w dowolnym kierunku (N / S / E / W / NE / NW / SE / SW) kosztem 1 energii.
- Komórka nie może przejść na pole zajmowane przez inną żywą komórkę.
- Komórka nie może zejść z siatki.
- Przeniesienie na zwłoki komórkowe niszczy zwłoki.
Atak: Komórka atakuje sąsiednią komórkę, zadając 1 do 3 obrażeń, wydając 1 do 3 punktów energii.
- Komórka może atakować w dowolnym kierunku (N / S / E / W / NE / NW / SE / SW).
- Atakowanie przyjaznych komórek jest legalne.
Podziel: Komórka dzieli się i tworzy nową komórkę na sąsiedniej przestrzeni, kosztem 5 energii.
- Komórka może dzielić się w dowolnym kierunku (N / S / E / W / NE / NW / SE / SW).
- Nowa komórka ma pełne HP zgodnie z oryginalną specyfikacją komórki.
- Nowa komórka ma tyle samo energii, co jej komórka macierzysta po odjęciu kosztu podziału. (Na przykład komórka rodzicielska z początkowymi 8 punktami energii zostanie zredukowana do 3 energii i wytworzy komórkę potomną z 3 energiami).
- Nowa komórka nie może działać do następnej tury.
- Komórka nie może podzielić się na przestrzeń zajmowaną przez żywą komórkę, ale może podzielić się na przestrzeń zajmowaną przez zwłoki martwej komórki (to niszczy zwłoki).
Jeść: Komórka zjada zwłoki sąsiedniej komórki, zyskując 4 energię.
- Komórka może jeść w dowolnym kierunku (N / S / E / W / NE / NW / SE / SW).
Odpoczynek: Komórka nic nie robi przez jedną turę, odzyskując 2 energię.
Eksploduj: Gdy komórka ma 3 lub mniej PW i więcej energii niż HP, może wybuchnąć, zadając obrażenia wszystkim ośmiu sąsiednim komórkom.
- Uszkodzenie każdej sąsiedniej komórki wynosi
(exploding cell HP) + (explodng cell acidity)
- Eksplodowana komórka umiera i pozostawia zwłoki, podobnie jak wszystkie komórki zabite w wyniku eksplozji.
- Uszkodzenie każdej sąsiedniej komórki wynosi
Protokół
Ustawiać
Twój program będzie działał z ciągiem BEGIN
podanym na stdin. Twój program musi napisać na standardowe miejsce oddzieloną spacją listę 3 nieujemnych liczb całkowitych reprezentujących HP, energię i kwasowość dla gatunków komórek: np 5 6 1
. Liczby muszą się sumować do 12. Kwasowość może być 0
, jeśli chcesz. (Inne atrybuty mogą być również zerowe, ale funkcjonalnie powoduje to utratę gry!)
Zaczynasz z jedną komórką, w północno-zachodnim lub południowo-wschodnim rogu, jedną przestrzeń od każdej krawędzi. Początkowa komórka ma pełne HP i energię.
Każda komórka działa
W każdej turze twój program będzie wywoływany raz dla każdej komórki żyjącej w twoim zespole (oprócz komórek właśnie utworzonych w tej turze), aby komórka mogła działać. Twój program zawiera dane o stdin, które obejmują stan płytki Petriego i informacje o tej konkretnej komórce:
10 4
..........
..xx.c....
...c...o..
......o...
6 3 5 7
Pierwsze dwie liczby wskazują szerokość i wysokość areny: tutaj jest arena 10 na 4.
- Te
o
komórki są twoje; tex
komórki są twoi wrogowie. (To zawsze jest prawda; każdy gracz zawsze widzi swoje własne komórki jakoo
.) - Miejsca
.
są puste. - Te
c
przestrzenie stanowią jadalne ciał komórkowych.
Liczby po pustym wierszu reprezentują informacje o tej komórce:
- Pierwsze dwie liczby to
x,y
współrzędne, indeksowane od0,0
lewego górnego rogu (6 3
tutaj odnosi się doo
komórki na południe ). - Trzecią liczbą jest HP komórki; czwarta liczba to energia komórki.
Twój program powinien wypisać (na standardowe wyjście) działanie. W poniższych przykładach użyjemy N
jako przykładowego kierunku, ale może to być dowolny kierunek zgodny z prawem dla tej akcji ( N
/ S
/ E
/ W
/ NE
/ NW
/ SE
/ SW
). Wszystkie dane wyjściowe programu nie rozróżniają wielkości liter, ale przykłady będą używać wielkich liter. Każda akcja wyjściowa, która jest niepoprawna (ponieważ ma niepoprawną składnię lub podejmuje próbę nielegalnej akcji) jest ignorowana i skutkuje REST
łączeniem komórek (i w ten sposób zyskuje 2 energię).
MOVE N
DIVIDE N
EAT N
ATTACK N 2
- liczba reprezentuje siłę ataku (1–3)REST
EXPLODE
Tura twojego zespołu polega na tym, że wszystkie komórki mają możliwość działania, jeden po drugim. Wszystkie twoje komórki działają zanim zadziała którakolwiek z komórek przeciwnika. Gdy wszystkie komórki zadziałają, twoja tura się kończy i tura twojego przeciwnika. Gdy wszystkie komórki przeciwnika zaczną działać, twoja tura zaczyna się od nowa. W twojej turze każda komórka ma pierwszeństwo działania na podstawie jej wieku: najstarsze komórki w twoim zespole działają najpierw przed młodszymi komórkami.
Przykład
Oto jak może się zachowywać program. Dane wejściowe ze standardowego wejścia oznaczone są tutaj >
strzałkami wiodącymi (oddzielonymi od rzeczywistych danych wejściowych spacją wyjaśniającą), a dane wyjściowe ze standardowego wejścia mają <
strzałki.
> BEGIN
< 5 6 1
Następnie program jest wywoływany ponownie:
> 10 4
> ..........
> .o........
> ........x.
> ..........
>
> 1 1 5 6
< DIVIDE SE
Po turze przeciwnika (który zdecydował się DIVIDE W
na pojedynczą komórkę początkową), twój program jest wywoływany dwukrotnie, raz dla każdej komórki:
> 10 4
> ..........
> .o........
> ..o....xx.
> ..........
>
> 1 1 5 1
< MOVE E
Dla drugiego wywołania w twojej turze:
> 10 4
> ..........
> ..o.......
> ..o....xx.
> ..........
>
> 2 2 5 1
< MOVE SE
Zauważ, że ta druga komórka widzi zaktualizowany stan planszy na podstawie ruchu drugiej komórki wcześniej w twojej turze. Zauważ też, że komórka ta została stworzona z 1 energią, ponieważ komórka macierzysta miała 6 energii podczas wykonywania podziału w ostatniej turze (tak więc pierwotna 6, minus 5-energetyczny koszt podziału, stworzyła komórkę potomną z 1 energią).
Teraz twoja tura się skończyła i rozpoczyna się tura przeciwnika. Dwie przeciwne komórki otrzymają szansę działania, a następnie rozpocznie się kolejna tura.
Zwycięstwo
Możesz wygrać poprzez:
- Niszczenie wszystkich komórek przeciwnych lub
- Posiadanie większej liczby komórek niż przeciwnik po ukończeniu 150 tur przez każdego gracza
Punktacja będzie oparta na liczbie wygranych w 100 grach przeciwko sobie. W połowie symulacji twój program będzie mógł zacząć jako pierwszy.
Gry remisowe (tj. Dokładnie taka sama liczba komórek po 150 turach lub jedyne pozostałe komórki zostają zabite razem w wyniku eksplozji) nie są liczone w łącznych wygranych żadnego z graczy.
Inne informacje
- Wasz program nie powinien próbować utrzymywać stanu (poza wykorzystaniem stanu płytki Petriego): organizmy jednokomórkowe nie mają bardzo dobrej pamięci i reagują na chwile na świecie z każdą chwilą. W szczególności zapisywanie do pliku (lub innego magazynu danych), komunikacja ze zdalnym serwerem lub ustawianie zmiennych środowiskowych są wyraźnie zabronione.
- Zgłoszenia będą uruchamiane / kompilowane na Ubuntu 12.04.4.
- Specyfika 100 gier punktowanych nie została jeszcze potwierdzona, ale prawdopodobnie będą obejmować wiele rozmiarów aren (na przykład 50 biegów na małej arenie i 50 biegów na większej arenie). W przypadku większej areny mogę zwiększyć maksymalną liczbę tur, aby zapewnić prawidłową bitwę.
Zasoby
Oto kod sterownika, który uruchamia symulację, napisany dla Node.js, wywoływany przez node petri.js 'first program' 'second program'
. Na przykład może wyglądać skierowanie komórki napisanej w języku Python na komórkę napisaną w języku Java node petri.js 'python some_cell.py' 'java SomeCellClass'
.
Ponadto rozumiem, że czytanie i analizowanie wielu wierszy na stdin może być ogromnym bólem, dlatego stworzyłem kilka pełnych przykładowych komórek w różnych językach, na których podstawie możesz swobodnie rozbudowywać, całkowicie modyfikować lub całkowicie ignorować.
- Komórka Java
- Komórka Python
- Komórka JavaScript (do użytku z Node.js)
Oczywiście możesz napisać komórkę w innym języku; to po prostu trzy języki, dla których postanowiłem napisać prosty kod, aby zaoszczędzić czas.
Jeśli masz problemy z uruchomieniem sterownika, możesz wysłać mi ping do pokoju czatu, który utworzyłem dla tego wyzwania . Jeśli nie masz wystarczającej reputacji na czacie, po prostu zostaw komentarz.
źródło
'node c:/cell/cell_template.js'
przypadku każdego argumentu, tak samo jak'java CellTemplate'
w przypadku kodu Java. Wyjaśnię to w tekście wyzwania. Jeśli nadal masz problemy, my (i każdy z problemami technicznymi) możemy kontynuować tę dyskusję w właśnie utworzonym przeze mnie czacie .Odpowiedzi:
Oto mój stosunkowo prosty bot, który zaprogramowałem w Ruby. Zasadniczo priorytetem jest dzielenie jako pierwsze i próba dzielenia się na wrogów w celu uzyskania kontroli nad polem. Drugim priorytetem jest jedzenie, a trzeci atakowanie. Z łatwością pobił próbkę komórki Pythona.
źródło
$
.$
służy do wskazania zmiennej globalnej. Tak, są źli, ale w tym małym programie nie ma to większego znaczenia.Ameba
Najpierw dzieli się na cztery, a następnie próbuje dostać się na środkowy grunt, aby ograniczyć przestrzeń replikacji przeciwników. Następnie rozpoczyna się replikacja. Podczas przenoszenia lub replikacji znajduje optymalną ścieżkę do najbliższego wroga i przesuwa się w jej kierunku, aby spróbować odciąć wroga dostępną przestrzeń.
Jeśli wróg znajduje się w sąsiedztwie lub jest o jedno pole dalej, zawsze atakuje lub zbliża się do niego, pozwalając rzędowi za sobą nie robić nic, aby wypełnić puste pola.
Nie testowałem tego na żadnym innym zgłoszeniu, więc nie mam pojęcia, jak dobrze sobie poradzi.
źródło
Prosta komórka wykonana w
node.js
. Przetestowany pod kątem komórek węzłów przykładów i przeciwko Kostronorowi bije je.Aktualizacja
Wciąż dość proste, spróbuj zbliżyć się do wroga lub podzielić.
źródło
Ewolucja
To poddanie ewoluowało i nie jest już prostym organizmem jednokomórkowym! Próbuje atakować / eksplodować, gdy tylko jest to możliwe, w przeciwnym razie dzieli lub zbliża się do wroga. Poruszanie powinno rozwiązać problem komórki otoczonej przyjaznymi komórkami o maksymalnej energii, niezdolnymi do zrobienia czegoś pożytecznego.
Po przeprowadzce zawsze pozostają 3 energie, by trafić wroga tak mocno, jak to możliwe.
źródło
Berserker
Ponieważ korzystałem z Clojure, który ma pewne ograniczenia, głównie z powodu ogromnego czasu uruchamiania, trochę się ożywiłem. Gdy program jest podany
BEGIN
, wyświetla dane wyjściowe4 6 2 LOOP
, co oznacza, że się nie zatrzymuje. Następnie przyjmuje dane wejściowe jako ciągły strumień i kończy się naEND
. Nie zapisuje żadnego stanu, co jest wyjaśnione przez brak użycia zmiennych globalnych lub ponowne użycie wartości zwracanych. Ponieważ implementacja tego działania pętli nie została jeszcze wykonana, nie mogłem w pełni przetestować kodu (mam nadzieję, że kod jest wystarczająco jasny).Komórka zyskała swoją nazwę od charakteru eksplozji, gdy tylko jest to możliwe (a tym samym kwasowości) i poprzez priorytetowe atakowanie zaraz po podziale.
Przesłałem wygenerowany plik jar do mojego Dropbox . Biegnij z
java -jar petridish-clojure.jar
Aby wyjaśnic:
Zaktualizuj dziennik
źródło
Głodny, głodny bot
Oto wpis w R. Mam nadzieję, że dobrze zrozumiałem, jakie były specyfikacje techniczne dotyczące komunikacji z twoim programem. Powinny zostać uruchomione za pomocą
Rscript Hungryhungrybot.R
.Jeśli ma co najmniej 6 energii, dzieli się, najlepiej w kierunku wroga. W przeciwnym razie zjada to, co jest obok lub co jest osiągalne. Jeśli jedzenie nie jest osiągalne, albo eksploduje, gdy w pobliżu jest więcej wrogów niż komórki siostrzane, albo walczy z pobliskimi wrogami. Odpoczywa tylko wtedy, gdy energia wynosi 0 i nie ma nic do jedzenia.
źródło
Error: unexpected 'else' in "else"
kod. Obawiam się, że w ogóle nie znam R. Tak więc nie mogę rozpocząć rozwiązywania tego błędu. Dla porównania, ten błąd pojawia się zarówno po uruchomieniu go w sterowniku, jak i po prostu po uruchomieniu programu i ręcznym wpisaniuBEGIN
.Error in if (dir[1] < 0) where <- paste(where, "N", sep = "") : missing value where TRUE/FALSE needed
Error: object 'food' not found
(w starciu z poddaniem się Ruby Alexa, ewentualnie innymi)Skoordynowane bakterie
Mam nadzieję, że się nie spóźnię.
Wygraj z innymi przeciwnikami (i zawsze zabijając ich wszystkich), w moich testach, a bitwa nigdy się nie skończy, jeśli stanie w obliczu samej siebie, dowód na to, że strategia jest silna.
Kiedy jesteś jednokomórkowy, możesz zapamiętać poprzedni stan, ale możesz wykorzystać własną pozycję, by zachowywać się inaczej! =)
Spowoduje to podział bakterii na dzielnik i ruch, a dzięki temu więcej bakterii będzie użytecznych zamiast samej linii frontu, a linia obrony pozostanie w linii.
Koordynuje także swoje ataki, aby skupić się na konkretnym wrogu, dzięki czemu wrogowie szybciej się zabijają (ma to na celu stawienie czoła mojej innej pojedynczej komórce, która skupia się na HP).
W środkowej fazie gry, która jest wykrywana przez liczbę komórek na planszy, będą próbować wepchnąć się na terytorium wroga, oskrzydlając je. To jest kluczowa strategia wygrywania.
Ma to najwyższe tempo wzrostu w porównaniu do wszystkich innych przeciwników obecnie, ale ma powolny start, więc działa to lepiej na dużej arenie.
Uruchom to z
java CoordinatedBacteria
źródło
Myślę, że opublikuję moje zgłoszenie, ponieważ jesteście tak hojni, aby dodać logikę płyty kotłowej ...
Wystąpił problem w twojej logice, polegający na tym, że akcja jedzenia wydawałaby ATAK zamiast JEDZENIA i marnowała zwłoki.
Zmodyfikowałem twoją treść tak samo, aby mieć działające rozwiązanie, które powinno działać stosunkowo dobrze. Zaczyna się od 4 hp i 8 energii, więc po podziale i odpoczynku oba ogniwa mogą się ponownie podzielić. Będzie próbował się rozmnażać, atakować wrogów, jeść zwłoki i odpoczywać w tej kolejności. Tak więc komórki wewnętrzne będą przechowywać 8 punktów energii, aby szybko zastąpić zabite komórki zewnętrzne i pozostawić im 3 punkty energii, aby wykonać 3-punktowy atak lub pomnożyć się po odpoczynku jednej tury. 4 hp mają przetrwać co najmniej jeden atak pełnej siły.
kwas wydaje mi się marnowaniem punktów, więc trzymałem go z daleka ...
Nie przetestowałem zgłoszenia, ponieważ było to 2 minuty;)
oto mój kod:
źródło
Cienko rozłożony bombowiec
Ponieważ tak uprzejmie dostarczyłeś kod bojlera, postanowiłem stworzyć własną prostą komórkę; Komórka ma 4 kwasowości, tylko 1 KM i 7 energii. Próbuje wyjść poza zasięg towarzyski, a następnie czeka tam (lub je, jeśli to możliwe), aż pojawi się szansa wysadzenia w powietrze lub replikacji. Atakuje tylko, jeśli jest to jedyna opcja.
Jest to dość ballsy strategia i prawdopodobnie będzie źle działać, ale jestem ciekawy, jak to działa. Być może przetestuję go i poprawię później.
źródło
node c:/cells/petri.js 'node c:/cells/bomber.js' 'node c:/cells/sample.js
. Kiedy piszę to w konsoli aplikacji węzła, dostaję tylko trzy kropki, kiedy próbuję uruchomić go w cmd systemu Windows, otrzymuję: „węzeł” nie jest rozpoznawany jako polecenie wewnętrzne lub zewnętrzne, program operacyjny lub plik wsadowy. Zapisałem wszystkie pliki jako pliki .js w odpowiednim folderze. JAKAŻ pomoc dla nooba? Chodziłbym na czat lub komentował gdzie indziej, ale mój przedstawiciel jest zbyt niski.if((nearbyEnemies.length - nearbyFriendlies.length > 1 ¦¦
-¦¦
nie wydają się być poprawnym operatorem i masz niedopasowane nawiasy. Myślę, że może formatowanie kodu zostało pomieszane po opublikowaniu?=
), gdy chcesz porównać równość (==
).