Dies ist eine Adaption von Core War , einem Programm von KOTH aus dem 20. Jahrhundert. Genauer gesagt wird ein unglaublich vereinfachter Befehlssatz verwendet, der hauptsächlich auf dem ursprünglichen Vorschlag basiert .
Hintergrund
In Core War kämpfen zwei Programme um die Kontrolle über den Computer. Das Ziel jedes Programms ist es, durch Auffinden und Beenden des gegnerischen Programms zu gewinnen.
Der Kampf findet im Hauptspeicher des Computers statt. Dieser Speicher wird als Core bezeichnet und enthält 8192 Adressen. Wenn der Kampf beginnt, wird der Code für jeden Konkurrenten (als Krieger bezeichnet) in einem zufälligen Speicherblock abgelegt. Die Programmausführung wechselt zwischen Kriegern und führt jeweils eine Anweisung aus. Jeder Befehl ist in der Lage, einen Teil des Kerns zu ändern, was zur Möglichkeit führt, Programme selbst zu ändern.
Ziel ist es, das gegnerische Programm zu beenden. Ein Programm wird beendet, wenn versucht wird, einen ungültigen Befehl auszuführen, bei dem es sich um einen beliebigen DAT
Befehl handelt.
Der Befehlssatz
Jedes Programm besteht aus einer Reihe von Anweisungen auf niedriger Ebene, die jeweils zwei Felder enthalten, die als A- und B-Felder bezeichnet werden.
Dieser Befehlssatz lehnt sich stark an die ursprüngliche Spezifikation an. Die wichtigsten Änderungen sind 1) Erläuterungen zum Hinzufügen / Entfernen von Befehlen und 2) eine Änderung des #
Adressierungsmodus, damit er überall verwendet werden kann. Die meisten Vollversionen von Core Wars haben über 20 Opcodes, 8 Adressierungsmodi und eine Reihe von "Anweisungsmodifikatoren".
Opcodes
Jeder Befehl muss einen von sieben verschiedenen Operationscodes haben.
DAT A B
- (Daten) - Hier stehen einfach die ZahlenA
undB
. Wichtig ist, dass ein Prozess abstürzt, wenn er versucht, einen DAT-Befehl auszuführen.MOV A B
- (Verschieben) - Verschiebt den Inhalt des SpeicherortsA
zum SpeicherortB
. Hier ist eine Demonstration von Vorher und Nachher:MOV 2 1 ADD @4 #5 JMP #1 -1
MOV 2 1 JMP #1 -1 JMP #1 -1
ADD A B
- (Hinzufügen) - Fügt den Inhalt des SpeicherortsA
zum Speicherort hinzuB
. Die beiden ersten Felder von beiden werden hinzugefügt, und die zweiten Felder werden hinzugefügt.ADD 2 1 MOV @4 #5 JMP #1 -1
ADD 2 1 MOV @5 #4 JMP #1 -1
SUB A B
- (subtrahieren) - Hiermit wird der Inhalt des Speicherorts vom Speicherort subtrahiertA
(und das Ergebnis dort gespeichert)B
.SUB 2 1 MOV @4 #5 JMP #1 -1
SUB 2 1 MOV @3 #6 JMP #1 -1
JMP A B
- (Sprung) - Sprung zur PositionA
, die im nächsten Zyklus ausgeführt wird.B
muss eine Zahl sein, tut aber nichts (Sie können sie jedoch zum Speichern von Informationen verwenden).JMP 2 1337 ADD 1 2 ADD 2 3
Der Sprung bedeutet,
ADD 2 3
dass der nächste Zyklus ausgeführt wird.JMZ A B
- (Sprung bei Null) - Wenn beide ZeilenfelderB
0 sind, springt das Programm zur PositionA
.JMZ 2 1 SUB 0 @0 DAT 23 45
Da die beiden Felder der Anweisung 1 0 sind, wird der DAT-Befehl in der nächsten Runde ausgeführt, was zum unmittelbar bevorstehenden Tod führt.
CMP A B
- (vergleichen und überspringt , wenn nicht gleich) - Wenn die Felder in AnweisungenA
undB
nicht gleich sind, lassen Sie die nächste Anweisung.CMP #1 2 ADD 2 #3 SUB @2 3
Da die beiden Felder von Befehl 1 und 2 den gleichen Wert haben, wird der Befehl ADD nicht übersprungen und in der nächsten Runde ausgeführt.
Wenn zwei Befehle addiert / subtrahiert werden, werden die beiden Felder (A und B) paarweise addiert / subtrahiert. Der Adressierungsmodus und der Opcode werden nicht geändert.
Adressierungsmodi
Es gibt drei Arten von Adressierungsmodi. Jedes der beiden Felder eines Befehls hat einen dieser drei Adressierungsmodi.
Sofort
#X
-X
ist die Zeile, die direkt bei der Berechnung verwendet werden soll. Zum Beispiel#0
ist die erste Zeile des Programms. Negative Zeilen beziehen sich auf Zeilen im Kern vor dem Start des Programms.... //just a space-filler ... ADD #3 #4 DAT 0 1 DAT 2 4
Dadurch wird die erste der beiden DAT-Zeilen zur zweiten hinzugefügt, da sich diese in den Zeilen 3 bzw. 4 befinden. Sie möchten diesen Code jedoch nicht verwenden, da der DAT Ihren Bot im nächsten Zyklus tötet.
Relativ
X
- Die Zahl gibtX
die Position einer Zielspeicheradresse relativ zur aktuellen Adresse an. Die Nummer an dieser Stelle wird für die Berechnung verwendet. Wenn line#35
ausgeführt wird und enthält-5
, wird line#30
verwendet.... //just a space-filler ... ADD 2 1 DAT 0 1 DAT 2 4
Dadurch wird die zweite DAT-Zeile zur ersten hinzugefügt.
Indirekt
@X
- Die NummerX
repräsentiert eine relative Adresse. Der Inhalt an dieser Stelle wird vorübergehend zur Nummer X hinzugefügt, um eine neue relative Adresse zu bilden, von der die Nummer abgerufen wird. Wenn die Zeile#35
ausgeführt wird@4
und das zweite Feld#39
die Nummer enthält-7
, wird die Zeile#32
verwendet.... //just a space-filler ... ADD @1 @1 DAT 0 1 DAT 2 4
Dadurch wird das erste DAT zum zweiten DAT hinzugefügt, jedoch auf eine komplexere Weise. Das erste Feld ist @ 1, das die Daten von dieser relativen Adresse abruft. Dies ist das erste Feld des ersten DAT, eine 0. Dies wird als zweite relative Adresse von dieser Position interpretiert, sodass 1 + 0 = 1 die Summe ergibt Versatz von der ursprünglichen Anweisung. Für das zweite Feld erhält @ 1 den Wert von dieser relativen Adresse (die 1 im zweiten Feld des ersten DAT) und fügt ihn auf die gleiche Weise zu sich selbst hinzu. Der Gesamtversatz beträgt dann 1 + 1 = 2. Diese Anweisung wird also ähnlich wie folgt ausgeführt
ADD 1 2
.
Jedes Programm kann bis zu 64 Anweisungen enthalten.
Wenn eine Runde beginnt, werden die beiden Programme zufällig in einer Speicherbank mit 8192 Speicherplätzen abgelegt. Der Befehlszeiger für jedes Programm beginnt am Anfang des Programms und wird nach jedem Ausführungszyklus inkrementiert. Das Programm stirbt, sobald der Befehlszeiger versucht, einen DAT
Befehl auszuführen .
Parameter des Kerns
Die Kerngröße beträgt 8192 mit einem Timeout von 8192 * 8 = 65536 Ticks. Der Kern ist zyklisch, sodass das Schreiben an Adresse 8195 dem Schreiben an Adresse 3 entspricht. Alle nicht verwendeten Adressen werden mit initialisiert DAT #0 #0
.
Jeder Teilnehmer darf nicht länger als 64 Linien sein. Ganzzahlen werden als 32-Bit-Ganzzahlen mit Vorzeichen gespeichert.
Parsing
Um den Wettbewerbern das Programmieren zu erleichtern, werde ich dem Parser eine Zeilenbeschriftung hinzufügen. Alle Wörter, die in einer Zeile vor einem Opcode vorkommen, werden als Zeilenbezeichnungen interpretiert. Hat zum Beispiel tree mov 4 6
die Zeilenbezeichnung tree
. Wenn sich irgendwo im Programm ein Feld befindet, das tree
#tree
oder enthält @tree
, wird eine Zahl ersetzt. Auch die Großschreibung wird ignoriert.
Hier ist ein Beispiel, wie Zeilenbeschriftungen ersetzt werden:
labelA add labelB @labelC
labelB add #labelC labelC
labelC sub labelA @labelB
Hier stehen die Bezeichnungen A, B und C in den Zeilen 0, 1 und 2. Die Instanzen von #label
werden durch die Zeilennummer der Bezeichnung ersetzt. Instanzen von label
oder @label
werden durch die relative Position des Etiketts ersetzt. Adressierungsarten bleiben erhalten.
ADD 1 @2
ADD #2 1
SUB -2 @-1
Wertung
Für jedes Teilnehmerpaar wird jede mögliche Schlacht durchgeführt. Da das Ergebnis eines Kampfes von den relativen Offsets der beiden Programme abhängt, wird jeder mögliche Offset (etwa 8000 davon) ausprobiert. Darüber hinaus hat jedes Programm die Möglichkeit, sich bei jedem Versatz zuerst zu bewegen. Das Programm, das die Mehrheit dieser Offsets gewinnt, ist der Gewinner des Paares.
Für jedes Paar, das ein Krieger gewinnt, erhält er 2 Punkte. Für jedes Unentschieden erhält ein Krieger 1 Punkt.
Du darfst mehr als einen Krieger einreichen. Es gelten die typischen Regeln für mehrere Einreichungen, wie kein Tag-Teaming, keine Zusammenarbeit, keine Königswerdung usw. In Core War gibt es dafür sowieso keinen Platz, daher sollte es keine große Sache sein.
Der Controller
Der Code für den Controller sowie zwei einfache Beispiel-Bots befinden sich hier . Da dieser Wettbewerb (bei Verwendung der offiziellen Einstellungen) vollständig deterministisch ist, entspricht die von Ihnen erstellte Rangliste genau der offiziellen Rangliste.
Beispiel Bot
Hier ist ein Beispiel-Bot, der einige Funktionen der Sprache demonstriert.
main mov bomb #-1
add @main main
jmp #main 0
bomb dat 0 -1
Dieser Bot löscht langsam den gesamten Speicher im Kern, indem er ihn durch eine "Bombe" ersetzt. Da die Bombe eine DAT
Anweisung ist, wird jedes Programm, das eine Bombe erreicht, zerstört.
Es gibt zwei Zeilenbezeichnungen, "main" und "bomb", die dazu dienen, Zahlen zu ersetzen. Nach der Vorverarbeitung sieht das Programm folgendermaßen aus:
MOV 3 #-1
ADD @-1 -1
JMP #0 0
DAT 0 -1
Die erste Zeile kopiert die Bombe in die Zeile unmittelbar über dem Programm. In der nächsten Zeile wird der Wert von bomb ( 0 -1
) zum Befehl move hinzugefügt und die Verwendung des @
Adressierungsmodus demonstriert . Dieser Zusatz bewirkt, dass der Befehl move auf ein neues Ziel zeigt. Der nächste Befehl springt bedingungslos zum Programmstart zurück.
Aktuelle Rangliste
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
Paarweise Ergebnisse:
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
Das neueste Update (neue Versionen von Turbo und Paranoid) benötigte ungefähr 5 Minuten, um auf einem alten Laptop ausgeführt zu werden. Ich möchte Ilmari Karonen für seine Verbesserungen am Controller danken . Wenn Sie eine lokale Kopie des Controllers haben, sollten Sie Ihre Dateien aktualisieren.
quelle
Antworten:
Zwergeningenieur
Ein neuer und verbesserter Zwerg. Gewinne gegen alles andere, was bisher eingereicht wurde. Die ausgefallene Corestep- optimierte Schrittweite ist hier wohl übertrieben.
Bemerkenswerte Features sind die schnelle Bombardierung Schleife , die zwei Bomben in vier Zyklen, für eine durchschnittliche Bombardierung Geschwindigkeit von 0.5c in alten Core Sind Jargon wirft, und die Verwendung
JMZ
zu erkennen , wenn die Bombardierung abgeschlossen ist und es Zeit zum Schalter auf Plan B ( hier ein Kobold).Ich habe Core War in den 90er Jahren gespielt (einige von Ihnen haben vielleicht den grundlegenden Leitfaden gesehen, den ich 1997 geschrieben habe), und ich dachte, es wäre interessant zu sehen, welche alten Strategien aus der RedCode '88 / '94-Welt das könnten in dieser Variante nützlich sein.
Meine ersten Gedanken waren:
Es gibt keine
SPL
, also keine Replikatoren (und keine Koboldringe / Spiralen). Dies sollte Bomber stark machen. (Auch all diese ausgefallenen Bombenstrategien, die darauf ausgelegt sind, mit Replikatoren und Koboldspiralen umzugehen? Völlig unnötig und nutzlos hier. Einfach mit irgendwelchen Bomben bombardierenDAT
.)Dann wieder,
CMP
Scannen ist immer noch potenziell schneller als Bombardierung, so dass ein schneller Scanner könnte eine Chance haben.Das Fehlen von In / Dekrementen macht das Löschen des Kerns sehr langsam. Tatsächlich ist ein Core Clear in dieser Variante so ziemlich nur ein Bomber mit einer (suboptimalen) Schrittweite von ± 1. Auch dies schadet den Scannern. Eine One-Shot-Scanner-Bomber-Strategie könnte jedoch funktionieren.
Schnellscanner / Schnellbomber (eine Strategie für das frühe Spiel, bei der eine ungerollte Scan- / Bomben-Schleife verwendet wird, für diejenigen, die nicht mit Core War-Jargon vertraut sind) sind immer noch potenziell nützlich, aber nur gegen lange Programme (die sie selbst sind), also gibt es eine Art Feedback hier bewirken). Schwer zu sagen, ob es sich wirklich lohnt.
Das Punktesystem ist interessant. Krawatten erzielen halb so viele Punkte wie ein Sieg (statt 1/3 wie im traditionellen Kernkrieg), wodurch sie attraktiver werden. Andererseits ist das einzige Programm, das nach diesen Regeln wahrscheinlich viele Gleichstände erzielt, ein Kobold. (Auch das Fehlen von De- / Inkrementen erschwert Imp-Gates, so dass selbst einfache Imps tatsächlich die Chance haben, ein Unentschieden zu erzielen, wenn sie ihren Gegner lebend erreichen.)
Da die endgültigen Platzierungen nur davon abhängen, welche Programme Sie schlagen, und nicht davon, um wie viel Sie sie schlagen, werden Einträge von Generalisten bevorzugt. Es ist besser, nur alle Gegner zu besiegen, als die Hälfte zu vernichten und nur knapp gegen die anderen zu verlieren.
Da der Code öffentlich ist, ist es immer möglich, ein Programm zu finden, das eine bestimmte frühere Einreichung - möglicherweise sogar mehrere - übertreffen kann, egal wie gut sie im Allgemeinen sind. Solche Tricks (wie das Abstimmen der Schrittgröße, um den Gegner kurz vor dem Treffer zu treffen) können jedoch leicht billig erscheinen. Und natürlich könnte der Zielspieler immer nur eine neue Version mit anderen Konstanten einreichen.
Das Ergebnis ist jedenfalls, dass ich beschlossen habe, entweder einen schnellen Bomber oder einen sehr schnellen Scanner zu schreiben und vielleicht einen Quickscanner / Bomber daran anzuheften. Von diesen Optionen schien ein schneller Bomber am einfachsten und am wahrscheinlichsten zu funktionieren.
Zu diesem Zeitpunkt habe ich viel zu viel Zeit damit verbracht, den Interpreter-Code von PhiNotPi zu optimieren, weil ich dachte, ich würde wahrscheinlich viele Brute-Force-Tests durchführen, um die Konstanten zu optimieren. Zufälligerweise musste ich das nie tun - der obige Code ist so ziemlich die erste Version, die tatsächlich funktioniert hat (nach ein paar fehlgeschlagenen Versuchen, die aufgrund alberner Fehler Selbstmord begangen haben).
Der Trick, der meinen Bomber schnell macht, ist die indirekte Adressierung, um zwei Bomben für jede zu werfen
ADD
. So funktioniert es:Im ersten Zyklus führen wir aus
MOV bomb @aim
. Dadurch wird diebomb
Anweisung an die Stelle im Kern kopiert, an der sich das B-Feld mit denaim
Punkten befindet (anfangs genau 6326 Anweisungen zuvoraim
oder 6328 Anweisungen zuvorstep
; Sie werden später sehen, warum diese Zahlen von Bedeutung sind).Im nächsten Schritt führen wir die
aim
Anweisung selbst aus! Beim ersten Durchgang, sieht es wie folgt aus :MOV bomb @-6326
. So kopiert esbomb
an die Stelle auf die das B-Feld des Befehls bei 6326 Zeilen vor sich selbst zeigt.Also, was gibt es bei 6326 Zeilen vor
aim
? Es ist die Kopie, diebomb
wir gerade einen Zyklus früher dort abgelegt haben! Und wir haben die Dinge einfach so angeordnet, dass das B-Feld vonbomb
einen Wert ungleich Null hat, sodass die neue Bombe nicht über die alte kopiert wird, sondern in einiger Entfernung (in der Tat beträgt die Entfernung 3164, das ist die Hälfte unserer nominellen Schrittgröße 6328, aber andere Offsets könnten funktionieren, vielleicht sogar besser).Im nächsten Zyklus passen wir unser Ziel mit
SUB step aim
, die die Werte der subtrahiertstep
Anweisung (was auch der Sprung wir als nächstes ausführen werden sein geschieht, obwohl es haben könnte nur ein einfacher gewesenDAT
irgendwo) ausaim
.(Ein Detail hier beachten ist , dass wir Art von dem A-Wert sollen von
step
Null sein, so dass wir immer noch die gleichen Bomben auf der nächsten Iteration werfen würden sogar , dass nicht unbedingt erforderlich ist, obwohl,. Nur die Bomben geworfen Nach dem ersten Befehl muss das B-Feld 3164 sein, der Rest kann alles sein.)Als nächstes wird
JMZ
überprüft, ob der Befehl 6328 immer noch null ist, und in diesem Fall wird zum Anfang des Codes zurückgesprungen. 6328 ist die Schrittgröße unseres Bombers und durch 8 teilbar (aber nicht durch 16). Wenn wir also alle 6328 Schritte Bomben werfen würden, würden wir irgendwann dahin zurückkehren, wo wir angefangen haben, nachdem wir jede achte Anweisung im Kern bombardiert haben (und mit den zusätzlichen Bomben, die um 3163 = 6328/2 mod 4 versetzt sind (Mod 8) , wir hätten jede vierte Anweisung getroffen).Aber wir haben unseren Bombardierungslauf mit 6328 Anweisungen vor dem begonnen
JMZ
und sind bei jeder Iteration um -6328 zurückgegangen, also werden wir die Position 6328 Schritte nach derJMZ
einzigen Iteration bombardieren, bevor wir dieJMZ
selbst treffen würden . Wenn dieJMZ
Bombe 6328 Anweisungen später entdeckt, ist dies ein Zeichen dafür, dass wir so viel wie möglich vom Kern abgedeckt haben, ohne uns selbst zu treffen, und dass wir zu einer Sicherungsstrategie wechseln sollten, bevor wir uns selbst töten.Was die Backup-Strategie angeht, ist es nur ein alter
MOV 0 1
Kobold, da mir momentan nichts Besseres einfällt. So wie ich es sehe, wenn wir jeden vierten Ort des Kerns bombardiert haben und immer noch nicht gewonnen haben, kämpfen wir wahrscheinlich gegen etwas sehr Kleines oder sehr Defensives und könnten genauso gut versuchen zu überleben und uns mit einem Unentschieden zufrieden zu geben. Es ist in Ordnung, weil solche kleinen oder defensiven Programme im Allgemeinen nicht sehr gut darin sind, irgendetwas anderes zu töten. Selbst wenn wir also nur ein paar Kämpfe zufällig gewinnen, werden wir wahrscheinlich immer noch die Nase vorn haben.Ps.
Für den Fall, dass es jemand anderes möchte, hier ist meine leicht verbesserte Version des PhiNotPi-Turniercodes . Es ist ungefähr doppelt so schnell, speichert alte Kampfergebnisse, sodass Sie sie nicht erneut ausführen müssen, und behebt einen meiner Meinung nach geringfügigen Fehler bei der Berechnung der Kampfergebnisse.Die Änderungen wurden von PhiNotPi in die Hauptversion übernommen. Vielen Dank!quelle
Diagrammansicht
Dies kann als Debugging-Tool verwendet werden. Es zeigt den Kern und die Position des Players an. Um es zu benutzen, müssen Sie es aus dem Code aufrufen. Ich habe auch ein modifiziertes bereitgestellt, das das GraphView
Game.java
automatisch anzeigt.PhiNotPi und Ilmari Karonen haben kürzlich den Controller gewechselt. Ilmari Karonen hat freundlicherweise ein aktualisiertes GameView an dieser Stelle zur Verfügung gestellt .
Geändertes Game.java:
quelle
./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()
Methode auskommentieren sollen.Turbo
Mein zweiter CoreWar-Versuch. Entwarf, Zwerg zu schlagen. Scannt alle 2 Sekunden um 3 Sekunden nach Daten und legt dann eine Bombe ab. Jede Stufe besteht aus nur 3 Anweisungen, in der Hoffnung, dass die Bomben der Zwerge diese verfehlen.
NEUER Turbo ++ : Jetzt erweitert. Es scannt rückwärts, bis es Daten findet, bewegt sich dann dorthin und bombardiert dann rückwärts. Die Hoffnung ist, dass der Zug entweder den Gegner überfordert oder an einen bereits bombardierten und damit sicheren Ort geht.
... und eine Bearbeitung, die das Scannen sparsamer macht, lässt es alle schlagen!
quelle
Zwerg
Ein allgemeines und einfaches Programm, das einen Zwerg darstellt, der Steine wirft. Es gibt
DAT
alle vier Adressen eine Anweisung aus.EDIT: Korrigiert die Adressierung. Anscheinend unterscheiden sich die Adressierungsmodi von der Spezifikation, mit der das OP verknüpft ist.
quelle
add 3 3
, aber dann würde es jede Schleife verdoppeln, anstatt sie hinzuzufügen, und das wäre nicht nützlich.#4
Ist ein sofortiger4
Wert, wird die Nummer zum zweiten Wert in der Adresse hinzugefügt, die3
nach der aktuellen Adresse liegt.#
Adressierungsmodus in der Herausforderung falsch interpretieren . Wie in der Spezifikation angegeben, habe ich den#
Adressierungsmodus geändert .Entwickelt
Ich verstehe ehrlich gesagt nicht, wie es funktioniert. Es scheint seinen Quellcode zu konstruieren, bevor etwas unternommen wird. Ich würde es lieben, wenn mir jemand erklären würde, wie es funktioniert.Nachdem ich es studiert hatte, stellte ich fest, dass es einfach ein modifizierter Zwerg mit einem Koboldschutz ist. Anstatt die Feinde mit
DAT
Anweisungen zu bombardieren , wird der Code der Feinde gemischt. Es bombardiert auch alle zwei Register anstatt alle vier Register. Bei genügend Zeit würde es sich zweifellos selbst zerstören.quelle
FirstTimer
Wenn es funktioniert, sollte es versuchen, am Anfang des Kerns eine Position einzunehmen und eine Abwehr zu schaffen
quelle
#0
Bezieht sich auf den Start Ihres Programms (dh auf das Gleiche wie#main
), nicht auf den Start des Kerns (was ohnehin kein wirklich aussagekräftiges Konzept ist - der Kern ist es) Rundschreiben, Ihr Code kann nicht sagen, wo es beginnt oder endet). Was passiert ist, dass Ihr erster Befehl (main
) sich mit dem überschreibtMOV #data #100
, wonach Ihr Code effektiv in einen 0.25c (= ein Befehl pro vier Zyklen) Forward Core Clear verwandelt.#0
für den Anfang des Kerns gehalten. Die 5 ersten Anweisungen sind dann völlig unbrauchbar.CopyPasta
Nie an einem CoreWar teilgenommen, versucht dieses einfache Programm nur, sich selbst einzufügen und die Kopie dann auszuführen. Möglicherweise hat es nicht das richtige Verhalten. Sagen Sie mir bitte, ob dies der Fall ist.
Es ist zu pazifistisch und kann in der Tat nicht gewinnen.
quelle
JMP loop 0
). Wenn es dann dorthin springt, wo der Anfang der Kopie sein soll, ist es nur ein leerer Raum und es verliert.Hausmeister
Es sollte überprüfen, ob die folgenden Adressen leer sind und falls nicht, sie bereinigen (also hoffentlich den gegnerischen Bot löschen).
Bearbeiten: Diese neue Version sollte schneller sein (jetzt, da ich den
JMZ
Befehl und die@
Referenz richtig verstanden habe).quelle
ADD 3 -2
, aber du hast recht, dass er es ändern sollte, denke ich.JMZ
und dachte, ich würdeJMZ A B
prüfenA
und aufB
0 springen, wenn es anscheinend das Gegenteil ist. Danke, dassScanBomber
Entfernen Sie meine Kommentare vor dem Kompilieren. Sucht eine Weile und bombardiert dann, wenn ein Programm gefunden wird. Es wird aber wahrscheinlich immer noch gegen meinen Zwerg verlieren.
quelle
#
völlig anders als die Spezifikation (lies den Link, mit dem er verlinkt ist), ich muss dieses Programm noch dafür reparieren.#
vor jedem Verweis darauf setzenzero
? Ja, ich denke ich muss ...Han zuerst erschossen (v2)
Ich dachte, die Konkurrenz könnte etwas mehr Abwechslung gebrauchen, und hier ist mein zweiter Beitrag: ein One-Shot-
CMP
Scanner.Dies ist Version 2 mit verbesserter Anti-Imp-Abwehr - sie kann nun Imp schlagen, wenn auch nur um einen Punkt. Es verliert immer noch gegen den Zwergeningenieur, schlägt aber alles andere bisher und belegt damit derzeit den ersten Platz.
Dabei werden benachbarte Kernpositionen in Abständen von 10 Schritten in einem Abstand von 5 Schritten verglichen, bis ein Unterschied festgestellt wird. Wenn es dies tut, wirft es in Abständen von 2 Schritten Bomben, bis es seinen Gegner tötet oder sich um den gesamten Kern schlingt, um sich selbst zu erreichen.
Wenn der Scan nicht nicht irgendetwas anderes finden, wird es schließlich um Schleife und seinen eigenen Code finden und sie angreifen. Das wäre Selbstmord, aber der glückliche Zufall, dass die erste Bombe direkt auf der Erde landet
aim
Linie , wodurch die nächste Bombe 12 Positionen (anstatt der üblichen 2) in den Kern geworfen und der Code übersprungen wird. (Dies geschieht auch mit einer Wahrscheinlichkeit von 50%, wenn der Scan etwas findet, den Gegner jedoch nicht tötet.) Da die Kerngröße ein Vielfaches von zwei ist, geschieht dies auch dann, wenn der Bombenangriff eine Schleife durchläuft, wodurch die Notwendigkeit für a entfällt weitere Backup-Strategie.(Dieser Selbstbombardierungstrick war ursprünglich ein reiner Zufall - ich hatte mir eine völlig andere Art des Wechsels vom Scan- zum Bombenmodus vorgenommen, wenn nichts gefunden wurde, aber als ich den Code zum ersten Mal testete, waren die Konstanten einfach richtig, um ihn zu erstellen arbeite auf diese Weise, und ich habe mich entschlossen, dabei zu bleiben.)
quelle
Imp
Einfach Zoll durch das Programm.
quelle
Schnecke
Kriecht rückwärts durch den Speicherplatz. Wirft gelegentlich eine Bombe weit weg.
quelle
Osterhase
Er hüpft gerne rückwärts :)
quelle
Paranoid
Eine Art Kopiernudel, prüft aber, ob der Code durch Bombenangriffe geändert wurde. Wenn ja, kopiert es an einem Zwerg vorbei und führt ihn aus. Wenn ich es schaffe, das GameView erneut zu erstellen, werde ich versuchen, einige der Konstanten zu ändern.
quelle