Jest to adaptacja Core War , programu KOTH z 20 wieku. Mówiąc ściślej, używa niesamowicie uproszczonego zestawu instrukcji, opartego głównie na oryginalnej propozycji .
tło
W Core War istnieją dwa programy walczące o kontrolę nad komputerem. Celem każdego programu jest zwycięstwo poprzez zlokalizowanie i zakończenie programu przeciwnego.
Bitwa odbywa się w głównej pamięci komputera. Ta pamięć nazywa się Core i zawiera 8192 adresów. Na początku bitwy kod każdego zawodnika (zwanego wojownikiem) jest umieszczany w losowej części pamięci. Wykonanie programu przebiega na przemian między wojownikami, wykonując jedną instrukcję dla każdego z nich. Każda instrukcja może modyfikować część rdzenia, co prowadzi do możliwości samodzielnej modyfikacji programów.
Celem jest zakończenie programu przeciwnika. Program kończy się, gdy próbuje wykonać niepoprawną instrukcję, którą jest dowolna DAT
instrukcja.
Zestaw instrukcji
Każdy program składa się z szeregu instrukcji niskiego poziomu, z których każde zajmuje dwa pola, zwane polami A i B.
Ten zestaw instrukcji czerpie głównie z oryginalnej specyfikacji. Główne zmiany to 1) wyjaśnienie dotyczące dodawania / odejmowania poleceń oraz 2) zmiana #
trybu adresowania, aby można go było używać w dowolnym miejscu. Większość pełnych wersji Core Wars ma ponad 20 kodów, 8 trybów adresowania i zestaw „modyfikatorów instrukcji”.
Kody
Każda instrukcja musi mieć jeden z siedmiu różnych kodów.
DAT A B
- (dane) - To po prostu zawiera liczbyA
iB
. Co ważne, proces umiera, gdy próbuje wykonać instrukcję DAT.MOV A B
- (przenieś) - Przenosi zawartość lokalizacjiA
pamięci do lokalizacji pamięciB
. Oto demonstracja „przed i po”:MOV 2 1 ADD @4 #5 JMP #1 -1
MOV 2 1 JMP #1 -1 JMP #1 -1
ADD A B
- (dodaj) - Dodaje zawartość lokalizacjiA
pamięci do lokalizacji pamięciB
. Dwa pierwsze pola obu zostaną dodane, a drugie pola zostaną dodane.ADD 2 1 MOV @4 #5 JMP #1 -1
ADD 2 1 MOV @5 #4 JMP #1 -1
SUB A B
- (odejmij) - Odejmuje zawartość miejsca w pamięciA
od (i zapisuje wynik w) miejscu w pamięciB
.SUB 2 1 MOV @4 #5 JMP #1 -1
SUB 2 1 MOV @3 #6 JMP #1 -1
JMP A B
- (skok) - Przejdź do lokalizacjiA
, która zostanie wykonana w następnym cyklu.B
musi być liczbą, ale nic nie robi (możesz jej użyć do przechowywania informacji).JMP 2 1337 ADD 1 2 ADD 2 3
Skok oznacza, że
ADD 2 3
zostanie wykonany następny cykl.JMZ A B
- (skok, jeśli zero) - Jeśli oba pola liniiB
mają wartość 0, program przeskakuje do lokalizacjiA
.JMZ 2 1 SUB 0 @0 DAT 23 45
Ponieważ dwa pola instrukcji 1 mają wartość 0, polecenie DAT zostanie wykonane w następnej turze, co doprowadzi do nieuchronnej śmierci.
CMP A B
- (porównaj i pomiń, jeśli nie są równe) - Jeśli pola w instrukcjachA
iB
nie są równe, pomiń następną instrukcję.CMP #1 2 ADD 2 #3 SUB @2 3
Ponieważ dwa pola instrukcji 1 i 2 mają jednakową wartość, polecenie ADD nie jest pomijane i jest wykonywane w następnej turze.
Kiedy dwie instrukcje są dodawane / odejmowane, dwa pola (A i B) są dodawane / odejmowane parami. Tryb adresowania i kod operacji nie są zmieniane.
Tryby adresowania
Istnieją trzy rodzaje trybów adresowania. Każde z dwóch pól instrukcji ma jeden z tych trzech trybów adresowania.
Natychmiastowe
#X
-X
to linia, która ma być używana bezpośrednio w obliczeniach. Na przykład#0
jest pierwszą linią programu. Linie ujemne odnoszą się do linii w rdzeniu przed rozpoczęciem programu.... //just a space-filler ... ADD #3 #4 DAT 0 1 DAT 2 4
Spowoduje to dodanie pierwszej z dwóch linii DAT do drugiej, ponieważ znajdują się one odpowiednio w wierszach 3 i 4. Nie chciałbyś jednak używać tego kodu, ponieważ DAT zabije twojego bota w następnym cyklu.
Względne
X
- liczbaX
reprezentuje lokalizację docelowego adresu pamięci w stosunku do bieżącego adresu. Liczba w tej lokalizacji jest używana do obliczeń. Jeśli linia#35
jest wykonywana i zawiera-5
, wówczas#30
używana jest linia .... //just a space-filler ... ADD 2 1 DAT 0 1 DAT 2 4
Spowoduje to dodanie drugiej linii DAT do pierwszej.
Pośrednie
@X
- liczbaX
reprezentuje adres względny. Zawartość w tym miejscu jest tymczasowo dodawana do liczby X w celu utworzenia nowego adresu względnego, z którego pobierana jest liczba. Jeśli linia#35
jest wykonywana, a jej drugim polem jest@4
, a drugie pole linii#39
zawiera liczbę-7
, wówczas#32
używana jest linia .... //just a space-filler ... ADD @1 @1 DAT 0 1 DAT 2 4
To doda pierwszy DAT do drugiego, ale w bardziej skomplikowany sposób. Pierwsze pole to @ 1, które pobiera dane z tego adresu względnego, który jest pierwszym polem pierwszego DAT, a 0. To jest interpretowane jako drugi adres względny z tej lokalizacji, więc 1 + 0 = 1 daje sumę przesunięcie w stosunku do oryginalnej instrukcji. Dla drugiego pola @ 1 pobiera wartość z tego względnego adresu (1 w drugim polu pierwszego DAT) i dodaje ją do siebie w ten sam sposób. Całkowite przesunięcie wynosi wtedy 1 + 1 = 2. Tak więc ta instrukcja jest wykonywana podobnie do
ADD 1 2
.
Każdy program może zawierać do 64 instrukcji.
Po rozpoczęciu rundy oba programy są losowo umieszczane w banku pamięci z 8192 lokalizacjami. Wskaźnik instrukcji dla każdego programu rozpoczyna się na początku programu i jest zwiększany po każdym cyklu wykonywania. Program umiera, gdy wskaźnik instrukcji spróbuje wykonać DAT
instrukcję.
Parametry rdzenia
Rozmiar rdzenia to 8192, a limit czasu to 8192 * 8 = 65536 tyknięć. Rdzeń ma charakter cykliczny, więc zapis na adres 8195 jest taki sam jak zapis na adres 3. Wszystkie nieużywane adresy są inicjowane DAT #0 #0
.
Każdy zawodnik nie może być dłuższy niż 64 linie. Liczby całkowite będą przechowywane jako liczby całkowite ze znakiem 32-bitowym.
Rozbiór gramatyczny zdania
Aby ułatwić programowanie konkurentom, dodam funkcję parowania linii do parsera. Wszelkie słowa występujące w linii przed kodem operacji będą interpretowane jako etykiety linii. Na przykład tree mov 4 6
ma etykietę linii tree
. Jeśli gdziekolwiek w programie znajduje się pole zawierające tree
#tree
lub @tree
, liczba zostanie zastąpiona. Również wielkie litery są ignorowane.
Oto przykład zastępowania etykiet linii:
labelA add labelB @labelC
labelB add #labelC labelC
labelC sub labelA @labelB
Tutaj etykiety A, B i C znajdują się w wierszach 0, 1 i 2. Wystąpienia #label
zostaną zastąpione numerem wiersza etykiety. Wystąpienia label
lub @label
są zastąpione względną lokalizacją etykiety. Tryby adresowania są zachowane.
ADD 1 @2
ADD #2 1
SUB -2 @-1
Punktacja
Dla każdej pary uczestników odbywa się każda możliwa bitwa. Ponieważ wynik bitwy zależy od względnych przesunięć obu programów, wypróbowywane jest każde możliwe przesunięcie (około 8000 z nich). Co więcej, każdy program ma szansę na pierwsze przesunięcie w każdym przesunięciu. Program, który wygrywa większość tych przesunięć, jest zwycięzcą pary.
Za każdą parę wygraną przez wojownika przyznaje się 2 punkty. Za każdą remis wojownik otrzymuje 1 punkt.
Możesz przesłać więcej niż jednego wojownika. Obowiązują typowe zasady wielokrotnego przesyłania, takie jak brak łączenia tagów, brak współpracy, tworzenia króla itp. W Core War i tak nie ma miejsca na to, więc nie powinno to być wielkim problemem.
Kontroler
Kod kontrolera wraz z dwoma łatwymi przykładowymi botami znajduje się tutaj . Ponieważ ta konkurencja (uruchamiana przy użyciu oficjalnych ustawień) jest całkowicie deterministyczna, tworzona tabela wyników będzie dokładnie taka sama jak oficjalna tabela wyników.
Przykład Bot
Oto przykładowy bot pokazujący niektóre funkcje języka.
main mov bomb #-1
add @main main
jmp #main 0
bomb dat 0 -1
Ten bot działa, powoli usuwając całą pozostałą pamięć w rdzeniu, zastępując ją „bombą”. Ponieważ bomba jest DAT
instrukcją, każdy program, który dotrze do bomby, zostanie zniszczony.
Istnieją dwie etykiety linii, „główna” i „bomba”, które służą do zastąpienia liczb. Po wstępnym przetwarzaniu program wygląda następująco:
MOV 3 #-1
ADD @-1 -1
JMP #0 0
DAT 0 -1
Pierwszy wiersz kopiuje bombę do linii bezpośrednio nad programem. Następny wiersz dodaje wartość bomby ( 0 -1
) do polecenia ruchu, a także demonstruje użycie @
trybu adresowania. To dodanie powoduje, że polecenie move wskazuje nowy cel. Następne polecenie bezwarunkowo przeskakuje z powrotem na początek programu.
Aktualny ranking
24 - Turbo
22 - DwarvenEngineer
20 - HanShotFirst
18 - Dwarf
14 - ScanBomber
10 - Paranoid
10 - FirstTimer
10 - Janitor
10 - Evolved
6 - EasterBunny
6 - CopyPasta
4 - Imp
2 - Slug
Wyniki parami:
Dwarf > Imp
CopyPasta > Imp
Evolved > Imp
FirstTimer > Imp
Imp > Janitor
Imp > ScanBomber
Slug > Imp
DwarvenEngineer > Imp
HanShotFirst > Imp
Turbo > Imp
EasterBunny > Imp
Paranoid > Imp
Dwarf > CopyPasta
Dwarf > Evolved
Dwarf > FirstTimer
Dwarf > Janitor
Dwarf > ScanBomber
Dwarf > Slug
DwarvenEngineer > Dwarf
HanShotFirst > Dwarf
Turbo > Dwarf
Dwarf > EasterBunny
Dwarf > Paranoid
Evolved > CopyPasta
FirstTimer > CopyPasta
Janitor > CopyPasta
ScanBomber > CopyPasta
CopyPasta > Slug
DwarvenEngineer > CopyPasta
HanShotFirst > CopyPasta
Turbo > CopyPasta
CopyPasta > EasterBunny
Paranoid > CopyPasta
Evolved > FirstTimer
Evolved > Janitor
ScanBomber > Evolved
Evolved > Slug
DwarvenEngineer > Evolved
HanShotFirst > Evolved
Turbo > Evolved
EasterBunny > Evolved
Paranoid > Evolved
Janitor > FirstTimer
ScanBomber > FirstTimer
FirstTimer > Slug
DwarvenEngineer > FirstTimer
HanShotFirst > FirstTimer
Turbo > FirstTimer
FirstTimer > EasterBunny
FirstTimer > Paranoid
ScanBomber > Janitor
Janitor > Slug
DwarvenEngineer > Janitor
HanShotFirst > Janitor
Turbo > Janitor
Janitor > EasterBunny
Janitor > Paranoid
ScanBomber > Slug
DwarvenEngineer > ScanBomber
HanShotFirst > ScanBomber
Turbo > ScanBomber
ScanBomber > EasterBunny
ScanBomber > Paranoid
DwarvenEngineer > Slug
HanShotFirst > Slug
Turbo > Slug
EasterBunny > Slug
Paranoid > Slug
DwarvenEngineer > HanShotFirst
Turbo > DwarvenEngineer
DwarvenEngineer > EasterBunny
DwarvenEngineer > Paranoid
Turbo > HanShotFirst
HanShotFirst > EasterBunny
HanShotFirst > Paranoid
Turbo > EasterBunny
Turbo > Paranoid
Paranoid > EasterBunny
Najnowsza aktualizacja (nowe wersje Turbo i Paranoid) działała na starym laptopie około 5 minut. Chciałbym podziękować Ilmari Karonenowi za jego ulepszenia w kontrolerze . Jeśli masz lokalną kopię kontrolera, powinieneś zaktualizować swoje pliki.
źródło
Odpowiedzi:
Krasnoludzki inżynier
Nowy i ulepszony krasnolud. Wygrywa ze wszystkimi innymi zgłoszonymi do tej pory. Fantazyjny, zoptymalizowany rozmiar kroku kroku jest tutaj prawdopodobnie przesadą.
Godne uwagi funkcje obejmują szybką pętlę bombardowania, która rzuca dwie bomby w czterech cyklach, dla średniej prędkości bombardowania 0,5 c w starym żargonie Core War, a także użycie
JMZ
do wykrywania, kiedy bombardowanie jest zakończone i nadszedł czas, aby przejść do planu B ( tutaj Imp).Kiedyś grałem w Core War w latach 90. (niektórzy z was mogli zobaczyć podstawowy przewodnik, który napisałem w '97), więc pomyślałem, że byłoby interesujące zobaczyć, które stare strategie ze świata RedCode '88 / '94 mogłyby przydać się w tym wariancie.
Moje pierwsze myśli to:
Nie ma
SPL
, więc nie ma replikatorów (i nie ma pierścieni imp / spirali). To powinno wzmocnić bombowce. (Poza tym wszystkie te wymyślne strategie bombardowania zaprojektowane z myślą o replikatorach i spiralach impów? Zupełnie niepotrzebne i bezużyteczne. Po prostu bombarduj dowolnymiDAT
s.)Z drugiej strony
CMP
skanowanie jest nadal potencjalnie szybsze niż bombardowanie, więc szybki skaner może mieć szansę.Brak in / dekrementacji powoduje, że czyszczenie rdzenia jest bardzo wolne. W rzeczywistości rdzeń czysty w tym wariancie jest właściwie tylko bombowcem z (nieoptymalnym) rozmiarem kroku ± 1. To znowu boli skanery; jednak skaner jednorazowy → strategia bombowca może działać.
Szybkie skanery / szybkie bombowce (strategia z wczesnej fazy gry wykorzystująca rozwiniętą pętlę skanowania / bombardowania, dla tych, którzy nie są tak znani z żargonu Core War) są nadal potencjalnie przydatne, ale tylko w przypadku długich programów (którymi oni są, więc istnieje pewien rodzaj informacji zwrotnej efekt tutaj). Trudno powiedzieć, czy naprawdę warto.
System punktacji jest interesujący. Remisy zdobywają o połowę mniej punktów niż wygrana (zamiast 1/3, jak w tradycyjnej Wojnie Podstawowej), co czyni je bardziej atrakcyjnymi. Z drugiej strony, jedynym programem, który może zdobyć wiele remisów na tych zasadach, jest imp. (Również brak de / krokach sprawia imp bramy ciężko, więc nawet proste chochliki faktycznie zrobić mają szansę strzelenia krawat jeśli dotrą do ich przeciwnik żywy).
Ponadto, ponieważ końcowe rankingi zależą tylko od tego, które programy pokonałeś, a nie od tego, o ile je pokonałeś, zazwyczaj faworyzuje wpisy ogólne. Lepiej jest po prostu ledwo pokonać wszystkich przeciwników, niż całkowicie zniszczyć ich połowę i po prostu ledwo przegrać z resztą.
Ponieważ kod jest publiczny, zawsze można znaleźć program, który pokona każde wcześniejsze zgłoszenie - być może nawet kilka z nich - bez względu na to, jak ogólnie są dobre. Takie sztuczki (takie jak dostosowanie wielkości kroku, aby uderzyć przeciwnika tuż przed nim) mogą łatwo wydawać się tanie. I oczywiście docelowy gracz zawsze może po prostu przesłać nową wersję z różnymi stałymi.
Tak czy inaczej, wynik tego wszystkiego jest taki, że zdecydowałem, że powinienem spróbować napisać albo szybki bombowiec, albo bardzo szybki skaner, a może przyczepić do niego szybki skaner / bombowiec. Spośród tych opcji szybki bombowiec wydawał się najprostszy i najprawdopodobniej zadziałał.
W tym momencie spędziłem zbyt wiele czasu na ulepszaniu i optymalizacji kodu interpretera PhiNotPi, ponieważ pomyślałem, że prawdopodobnie przeprowadzę wiele prób brutalnej siły, aby zoptymalizować stałe. Tak się składa, że nigdy nie musiałem tego robić - powyższy kod jest właściwie pierwszą wersją, która faktycznie działała (po kilku nieudanych próbach, które popełniły samobójstwo z powodu głupich błędów).
Sztuczka, która sprawia, że mój bombowiec jest szybki, wykorzystuje adresowanie pośrednie, aby rzucić dwie bomby na każdą
ADD
. Oto jak to działa:W pierwszym cyklu wykonujemy
MOV bomb @aim
. Spowoduje to skopiowaniebomb
instrukcji do dowolnego miejsca w rdzeniu pola Baim
punktów (początkowo dokładnie 6326 instrukcji wcześniejaim
lub 6328 instrukcji wcześniejstep
; zobaczysz, dlaczego te liczby mają znaczenie później).W następnym kroku wykonujemy
aim
samą instrukcję! Na pierwszym przejeździe, to wygląda tak:MOV bomb @-6326
. Tak więc kopiujebomb
do miejsca, na które wskazuje pole B instrukcji na 6326 liniach przed sobą.Co jest wcześniej w 6326 liniach
aim
? To kopia,bomb
którą umieściliśmy tam jeden cykl wcześniej! I właśnie tak zorganizowaliśmy rzeczy, aby pole Bbomb
miało niezerową wartość, więc nowa bomba nie zostanie skopiowana na starą, ale w pewnej odległości (w rzeczywistości tutaj odległość wynosi 3164, co stanowi połowę naszego nominalnego rozmiaru kroku 6328; ale inne przesunięcia mogłyby działać, być może nawet lepiej).W następnym cyklu dostosowujemy nasz cel
SUB step aim
, który odejmuje wartościstep
instrukcji (która również jest skokiem, który wykonamy w następnej kolejności, chociaż może to być po prostu prostaDAT
)aim
.(Jeden szczegół, aby pamiętać, jest to, że my niby chcą wartości A
step
na zero, tak że będziemy nadal rzucać te same bomby na następnej iteracji Mimo że nie jest to bezwzględnie konieczne, chociaż;. Tylko bomby rzucone przez pierwsze instrukcji konieczności posiadania ich B-field równą 3164, reszta może być cokolwiek).Następnie
JMZ
sprawdź, czy instrukcja 6328 od niej odchodzi, jest wciąż równa zero, a jeśli tak, przeskakuje z powrotem na górę kodu. Teraz 6328 jest wielkością kroku naszego bombowca i dzieli się przez 8 (ale nie 16); tak więc, jeśli tylko będziemy rzucać bombami co 6328 kroków, w końcu wrócilibyśmy do miejsca, w którym zaczęliśmy, zbombardowując co ósme instrukcje w rdzeniu (i z dodatkowymi bombami przesuniętymi o 3163 = 6328/2 ≡ 4 (mod 8) , trafilibyśmy co czwartą instrukcję).Ale zaczęliśmy nasz bieg bombardowania w 6328 instrukcją przed
JMZ
i cofnęła przez -6328 przy każdej iteracji, więc mamy zamiar bombardować lokalizacja 6328 kroki po tymJMZ
tylko jednej iteracji, zanim będziemy uderzyćJMZ
się. Kiedy więcJMZ
wykryje bombę po 6328 instrukcjach po niej, jest to znak, że pokryliśmy jak najwięcej jądra, jak możemy, nie uderzając się w siebie, i powinniśmy przejść na strategię tworzenia kopii zapasowych, zanim się zabijemy.Jeśli chodzi o strategię tworzenia kopii zapasowych, to zwykły stary
MOV 0 1
chochlik, ponieważ na razie nie mogłem wymyślić nic lepszego. Z mojego punktu widzenia, jeśli zbombardowaliśmy co czwarte miejsce rdzenia i nadal nie wygrywamy, prawdopodobnie walczymy z czymś bardzo małym lub bardzo defensywnym, i równie dobrze możemy spróbować przetrwać i zadowolić się remisem. Jest w porządku, ponieważ takie małe lub defensywne programy na ogół nie są zbyt dobre w zabijaniu czegokolwiek innego, więc nawet jeśli wygramy tylko kilka walk przypadkiem, prawdopodobnie nadal wyjdziemy na prowadzenie.Ps.
Jeśli ktoś tego chce, oto mój nieco ulepszony kod turniejowy PhiNotPi . Jest około dwa razy szybszy, zapisuje stare wyniki bitwy, dzięki czemu nie trzeba ich ponownie uruchamiać, i naprawia coś, co uważam za drobny błąd w obliczaniu wyników bitwy.Zmiany zostały scalone do głównej wersji przez PhiNotPi. Dzięki!źródło
Widok wykresu
Może to być użyte jako narzędzie do debugowania. Wyświetla rdzeń i pokazuje lokalizację odtwarzacza. Aby go użyć, musisz wywołać go z kodu. Mam również zmodyfikowaliśmy pod warunkiem
Game.java
, że automatycznie wyświetla GraphView.PhiNotPi i Ilmari Karonen niedawno zmienili kontroler. Ilmari Karonen był na tyle miły, że zapewnił zaktualizowaną wersję GameView w tej lokalizacji .
Zmodyfikowana Game.java:
źródło
./Game.java:275: error: method toString in class Object cannot be applied to given types; System.out.println(Player.toString(line)); ^ required: no arguments found: int[]
printCore()
metodę.Turbo
Moja druga próba CoreWar. Zaprojektowany, aby pokonać Dwarf. Skanuje dane o 3, a następnie umieszcza bombę co 2. Każdy etap przebiega tylko w 3 instrukcjach, mając nadzieję, że bomby krasnoluda tęsknią.
NOWOŚĆ Turbo ++ : teraz ulepszona. Skanuje wstecz, aż znajdzie dane, a następnie się tam przenosi, a następnie bombarduje wstecz. Istnieje nadzieja, że ruch ten albo zapycha przeciwnika, albo znajduje się w miejscu zbombardowanym, a zatem bezpiecznym (ish).
... A edycja, która sprawia, że skanowanie jest rzadsze, sprawia, że bije wszystkich!
źródło
Krasnolud
Wspólny i prosty program przedstawiający karła rzucającego kamieniami. Umieszcza
DAT
instrukcję co cztery adresy.EDYCJA: Naprawiono adresowanie. Najwyraźniej tryby adresowania różnią się od specyfikacji, z którą powiązany jest PO.
źródło
add 3 3
, ale wtedy podwoiłoby każdą pętlę zamiast dodawać, a to nie byłoby przydatne.#4
jest natychmiastowy, więc dodaje liczbę4
do drugiej wartości w adresie następującym3
po bieżącym adresie.#
tryb adresowania w wyzwaniu. Jak podano w specyfikacji, zmieniłem#
tryb adresowania.Ewoluował
Naprawdę nie rozumiem, jak to działa. Wydaje się, że konstruuje swój kod źródłowy przed zrobieniem czegokolwiek. Chciałbym, żeby ktoś wyjaśnił mi, jak to działa.Po przestudiowaniu go odkryłem, że jest to po prostu zmodyfikowany karzeł ze strażnikiem chochlików. Zamiast bombardować wrogów
DAT
instrukcjami, tasuje kod przeciwnika. Bomba również co dwa rejestry zamiast co cztery rejestry. Mając wystarczająco dużo czasu, bez wątpienia sam się zniszczy.źródło
Nowicjusz
Jeśli to działa, powinien spróbować zająć pozycję na początku rdzenia i stworzyć obronę
źródło
#0
odnosi się do początku twojego programu (tj. Tego samego, co#main
), a nie do początku rdzenia (który zresztą nie jest tak naprawdę sensowną koncepcją - rdzeń jest okólnik, Twój kod nie może określić, gdzie zaczyna się lub kończy). Co się dzieje, to twoja pierwsza instrukcja (main
) zastępuje sięMOV #data #100
ciągiem, po którym kod skutecznie zmienia się w 0,25 c (= jedna instrukcja na cztery cykle) do przodu, usuwając rdzeń.#0
na początku rdzenia. 5 pierwszych instrukcji jest wtedy całkowicie bezużytecznych.CopyPasta
Ten prosty program nigdy nie uczestniczył w CoreWar, tylko próbuje samodzielnie skopiować i wkleić, a następnie wykonać kopię. Może nie mieć poprawnego zachowania, proszę powiedz mi, czy tak jest.
Jest zbyt pacyfistyczny i tak naprawdę nie może wygrać.
źródło
JMP loop 0
). Następnie, gdy przeskakuje do miejsca, w którym powinien być początek kopii, jest to po prostu puste miejsce i traci.Dozorca
Powinien sprawdzić, czy poniższe adresy są puste, a jeśli nie, czyści je (tym samym, mam nadzieję, usunięcie bota przeciwnika).
Edycja: Ta nowa wersja powinna być szybsza (teraz, gdy poprawnie zrozumiałem
JMZ
polecenie i@
odniesienie).źródło
ADD 3 -2
, ale masz rację, że powinien go zmienić, tak myślę.JMZ
i pomyślałem, żeJMZ A B
sprawdzamA
i skaczę doB
if 0, kiedy najwyraźniej jest odwrotnie. Dzięki, że zauważyłem, bo tego nie zrobiłem :)ScanBomber
Usuń moje komentarze przed kompilacją. Skanuje przez chwilę, a następnie bombarduje, gdy znajdzie program. Jednak pewnie nadal przegra z moim Krasnoludem.
źródło
#
zupełnie inaczej niż specyfikację (przeczytaj link, do którego linkował), muszę jeszcze naprawić ten program.#
przed każdym odniesieniemzero
? Tak, myślę, że muszę ...Han Shot First (v2)
Uznałem, że konkurencja mogłaby wykorzystać więcej różnorodności, więc oto mój drugi wpis:
CMP
skaner jednorazowy .To jest wersja 2 , z ulepszoną obroną przeciw Imp - może teraz pokonać Imp, choćby tylko o jeden punkt. Nadal przegrywa z Krasnoludzkim Inżynierem, ale jak dotąd bije wszystko inne, stawiając go obecnie na pierwszym miejscu.
Działa poprzez porównywanie sąsiednich lokalizacji rdzenia w odległości 5 kroków od siebie, w odstępach co 10 kroków, aż do znalezienia różnicy. Kiedy to robi, zaczyna rzucać bomby w 2-etapowych odstępach, aż zabije przeciwnika lub zapętli się wokół rdzenia, aby dotrzeć do siebie.
Jeśli skanowanie nie znajdzie niczego innego, ostatecznie zapętli się, znajdzie swój kod i go zaatakuje. Byłoby to samobójcze, gdyby nie przypadek, że pierwsza bomba wylądowała dokładnie na
aim
linii, powodując zrzucenie następnej bomby o 12 pozycji (zamiast zwykłych 2) w dół rdzenia, wygodnie pomijając kod. (Dzieje się tak również z 50% prawdopodobieństwem, jeśli skan znajdzie coś, ale nie zabije przeciwnika.) Ponieważ rozmiar rdzenia jest wielokrotnością dwóch, tak się stanie, jeśli bombardowanie zapętli się, eliminując potrzebę dalsza strategia tworzenia kopii zapasowych.(Ta sztuczka polegająca na samobombardowaniu była początkowo czystym zbiegiem okoliczności - zaplanowałem zupełnie inny sposób przejścia ze skanowania do trybu bombardowania, jeśli nic nie zostanie znalezione, ale kiedy po raz pierwszy przetestowałem kod, stały się po prostu słuszne działaj w ten sposób i postanowiłem się z tym trzymać).
źródło
Chochlik
Po prostu cale przez program.
źródło
Ślimak
Przeszukuje przestrzeń pamięci do tyłu. Czasami rzuca bombę daleko.
źródło
Zajączek wielkanocny
Lubi skakać do tyłu :)
źródło
Paranoidalny
Niby kopia makaronu, ale sprawdzi, czy kod został zmodyfikowany przez bombardowanie. Jeśli tak, skopiuj obok krasnoluda i go wykonaj. Jeśli uda mi się ponownie utworzyć GameView, spróbuję zmienić niektóre stałe.
źródło