Corewars Revisited by fdh56iuoui

VIEWS: 24 PAGES: 29

									                                                   Corewars: Revisited




  Corewars Revisited




                     May 2009


                Adrian Busolini
                  aab@cs.man.ac.uk



             Supervisor: Jim Garside

Computer Science MENG at the School of Computer Science
              The University of Manchester



                        1 of 29
                                                                            Corewars: Revisited




    Abstract 

    Corewars: Revisited analyses the current state of Corewars, a programming game first
    announced 25 years ago by A. K. Dewdney, and asks whether there are ways in which
    gameplay could be improved. I suggest ways in which the game could be altered to
    influence the design trends behind modern day Corewars programmers, and try to affect
    those changes in my own implementation of the Corewars software known as the
    Memory Array Redcode Simulator.




    Adrian Busolini

    Supervisor: Jim Garside




                                         2 of 29
                                                                                                                           Corewars: Revisited



Table of Contents
Corewars Revisited...............................................................................................................................1
1 Introduction......................................................................................................................................4
   1.1 What is Corewars?....................................................................................................................4
   1.2 Shortcomings and Solutions.....................................................................................................5
   1.3 Objectives.................................................................................................................................6
2 Background.......................................................................................................................................8
   2.1 The Inspiration for Corewars ...................................................................................................8
   2.2 The Game of Corewars.............................................................................................................9
      2.2.1 Instruction Set ..................................................................................................................9
      2.2.2 Addressing.......................................................................................................................10
      2.2.3 Instruction Modifiers.......................................................................................................11
      2.2.4 Playing the Game.............................................................................................................11
   2.3 Warriors ..................................................................................................................................12
3 Design ............................................................................................................................................14
   3.1 Assembler ...............................................................................................................................14
   3.2 Virtual Machine......................................................................................................................15
      3.2.1 Core..................................................................................................................................15
      3.2.2 Scheduling........................................................................................................................17
4 Implementation...............................................................................................................................19
   4.1 Overview..................................................................................................................................19
   4.2 Program Flow..........................................................................................................................21
   4.3 Processor Class........................................................................................................................22
   4.4 Multiple Cores.........................................................................................................................22
   4.5 2D Core....................................................................................................................................23
   4.6 Priority Scheduling..................................................................................................................23
5 Evaluation.......................................................................................................................................25
   5.1 Adding Complexity..................................................................................................................25
      5.1.1 Programming Bombers....................................................................................................25
      5.1.2 Programming Replicators................................................................................................26
      5.1.2 Programming Scanners....................................................................................................26
   5.2 Future Work............................................................................................................................26
6 Conclusion......................................................................................................................................28
 References........................................................................................................................................29




                                                                     3 of 29
                                                                                         Corewars: Revisited




1         Introduction

          “ two programs doing battle
          in the dark and noiseless corridors of core ”
          - A. K. Dewdney [9]



1.1       What is Corewars?

Corewars (also known as Core Wars, Corewar and Core War) is a programming game played on a
virtual computer called a Memory Array Redcode Simulator (MARS), and was introduced to the
world back in 1984 by a Professor of Mathematics; the notable A. K. Dewdney, then working as a
computer scientist. His work followed a range of other peoples' projects, all aimed in part at
simulating aspects of life with man-made machines. A popular method for doing so was through the
creation of cellular automata; one of the principal examples being John Conway's Game of Life,
created back in 1970.

Cellular automata consist of a cellular grid, of which each individual cell exists in a particular state,
and the next state of each cell is determined by applying a set of pre-defined rules to a subset of the
cells. Even though the Game of Life totalled only four rules and two states, it succeeded in
simulating self-reproduction and, in essence, life itself. However, it didn't innately offer the
challenge of designing one's own 'creature' and pitching it against another's in a battle for survival.

Whilst the Game of Life had a short and simple set of rules for state progression, and each cell was
only ever in a binary state, games such as Darwin and Corewars expanded the concept immensely;
simple binary states became computer instructions, and the simple rule processor which controlled
state transitions became a fully-fledged virtual machine, allowing for many additional complexities
to be added, including threading. A possible input for the Game of Life would be a grid of cells (or
other such representation), some of which may be in an “on” state, and the rest being in a
corresponding “off” state. Meanwhile, a possible input for Corewars is shown in Fig. 1. And whilst
the Game of Life doesn't necessarily terminate, Corewars has termination rules as part of the game.

A game of Corewars contains:
                                                                dwarf         mov      bomb,@bomb
      ●   MARS – a virtual processor; it orders and                           add      #4,bomb
          executes instructions, and enforces game rules                      jmp      dwarf
      ●   Core – the memory space in which instructions         bomb          dat      #0
          and loaded and the game is played
      ●   Warrior – a set of instructions (and possibly
          pseudo-instructions) written in Redcode            Figure 1 A sample Corewars warrior: a slight
                                                             variation on Dewdney's original Dwarf warrior
Dewdney took the automaton concept, and injected

                                                4 of 29
                                                                                                  Corewars: Revisited

into it aspects of computer science. The mathematical art of creating self-replicating patterns by
selecting specific cells to be “on” or “off” was abstracted up the level of computer assembly
language, allowing participants to create more advanced creatures, encompassing more human
processes by coding for replication, self-modification and self-repair, as well as adaptive techniques
for incapacitating other warriors in the same core.

The impact Corewars had is reflected in the foundation of the International Core War Society
(ICWS) shortly after Dewdney's initial Corewars publication. The society released two Corewars
standards (ICWS'86 and ICWS'88), prepared a third standard (ICWS'94) and organised annual
tournaments [1]. Each standard added new features and expanded the instruction set. Many
independent tournaments 'hills' have also been established, and continue to this day [2]. Further,
many different MARS applications have been developed over the years; some adding innovative
new features, some offering evolutionary capabilities for warriors, some simply implementing an
ICWS standard, and some just providing basic implementations based on Dewdney's publications.
Some notable MARS applications include pMARS [3], nMars [4] and jMars [5]. Corewars has itself
inspired other projects, such as Tierra, which further investigated life and evolutionary processes.


1.2    Shortcomings and Solutions

Corewars transformed what had started with simple, mathematical concepts into a programming
battle game, in which warriors compete against each other to gain control of the core. As the
popularity of the game spread, and competitive “hills” arose which pitched warrior against warrior
in a battle for the high score tables, very different strategies for warrior design emerged.

Perhaps the most striking inversely proportional relationship found in warriors lay in the number of
assembly instructions each was composed of; the smaller the warrior, the harder it is to locate in the
core, but conversely, the larger the warrior, the more complex attacking and defensive systems can
be included (see Fig. 2).

This results in an unfortunate consequence for the game: complex, advanced warriors, with many
assembly instructions, all too often lose out to their simpler, smaller counterparts, which are simply
very difficult to locate and kill. The purpose of Corewars: Revisited, therefore, was to further
develop the game of Corewars in such a way as to necessitate both the maturation of simpler
warriors, and also the diversification of tactics employed by all warriors.

To achieve this, a variety of alterations and expansions have been considered, including making
changes to:


      0                                                                                                  N-1


            Warrior 1 (small, simple)              Warrior 2 (large, complex)               Core (0 to N-1)

  Figure 2 A core containing two warriors: the large warrior has the advantage of being able to conduct more
  complicated attacks and defensive moves, whilst having a very real disadvantage of being far easier to locate. The
  small warrior may not contain much code, but it will be hard to find.


                                                       5 of 29
                                                                                    Corewars: Revisited



      ●   the Redcode Instruction Set
      ●   the MARS virtual processor
      ●   the Core

The core of Corewars, a simple 1-dimensional wraparound memory space, has seen no real change
since its proposal by Dewdney in the 1980s; yet, it could offer some of the most intriguing and
revolutionary modifications to the game. The core is, therefore, one of the main focuses of this
project.


1.3       Objectives

I had settled on C++ as the development language for a number of reasons:

      ●   I specifically wanted to hone my C++ skills
      ●   I hoped Object Oriented Programming (OOP) would simplify the code
      ●   It compiles to native code, and should therefore execute quickly
      ●   Common libraries exist for standard output formatting and GUI creation

It was my original intention to begin with an existing Corewars implementation and to develop it
from there. I wanted an open-source, C++-based, cross-platform, well tested implementation with
minimal dependencies on external libraries. However, the two most likely candidates both had
issues:

      ●   Corewars' most common implementation, Portable MARS (pMARS), is written in C; I
          wanted an OOP language to work with, and so rejected pMARS.
      ●   nMars is a C++ implementation, but is unfortunately based on Microsoft's .NET framework
          (using Mono for *nix support) [6]. Given development was to commence under Linux, and
          given the controversy surrounding Microsoft's patent agreement with Novell [7] (owners of
          Mono), along with a preference to open source software, I took the decision not to use
          nMars.

With a lack of other C++ implementations satisfying the necessary conditions, my objectives
changed to additionally include the creation of:

      ●   a Redcode assembler
      ●   a Corewars virtual processor (Memory Array Redcode Simulator)

Furthermore, in order to provide suitable interfaces for development, testing, batch jobs, etc., and to
cater for everyone from beginners to experienced Corewars programmers, I intend to create both a
command line interface (CLI) and a graphical user interface (GUI) with a 2D core display. Both
interfaces should provide interactive debugging facilities.

I planned to complete the implementation (see Fig. 3) to ICWS'94 standards [8] first, before starting
work on my extensions, thereby giving a clear appreciation of project progress throughout.

All extensions on top of the base Corewars implementation (with ICWS'94 extensions) should be

                                               6 of 29
                                                                           Corewars: Revisited

provided as options which can be enabled if desired.




                                           Assembler


                        CLI                                          GUI


                                     Virtual Machine
  Figure 3 Architectural design of the new Corewars implementation




                                                    7 of 29
                                                                                    Corewars: Revisited




2      Background

       “ The rules of Core War are few and simple. [...]
       One problem with these rules is that they
       reward small but uninteresting programs ”
       - D. J. Jones & A. K. Dewdney [13]

2.1   The Inspiration for Corewars

Dewdney has repeatedly claimed that his inspiration for Corewars originated from the worms
Creeper and Reaper [9]. Although he now describes them as little more than 'folklore', various
theories exist today, many purporting that Creeper was possibly the first worm ever made, and that
Reaper was designed and released solely to eradicate the Creeper worm. Whether they were worms,
viruses, distributed computing test projects, or simply myths, Dewdney refers to similarities
between the Creeper/Reaper tale and two programs which certainly did exist: Darwin and Worm.

Worm was an early attempt at distributed computing, created in the 1970s. Interestingly, in the
article Worm Programs – Early Experience with a Distributed Computation [10], Shoch and Hupp
also claim that Creeper existed, and they define it as a “relocatable program” .

Darwin, though, bears many startling similarities to Corewars. It was a game purportedly invented
in 1961, although details weren't formally published until 1971. In Darwin, much like in Corewars,
there is a memory space (called the 'arena') and competing programs (called 'organisms').
Organisms are programmed with IBM 7090 machine code, with the addition of 3 instructions
(probe, claim, kill) which are interpreted by the Darwin controller (called the 'umpire'). The aim,
much like with Corewars, is to proliferate your own species of organisms whilst killing off all other
species [11].

One major difference between Corewars and Darwin is that Darwin doesn't interpret the organisms'
instructions; it executes them directly (although it does interpret the 3 umpire instructions).
Corewars, in stark contrast, uses an abstract assembly language called Redcode for programming
warriors, which clearly requires interpretation by a virtual computer (MARS). Given the same
hardware, it would be reasonable to assume that Redcode instructions would execute more slowly
than Darwin's 7090 instructions; however, without interpretation, Darwin's umpire cannot verify if
all the organism's instructions are legal insofar as the rules of the game are concerned. As a result,
when played competitively, the instructions for each player's organisms would typically be
distributed following the completion of the game, so players could verify the legitimacy of each
other's constructions [11].

Why didn't Darwin develop a lasting legacy in the same way Corewars did? Whilst part of the
explanation probably rests with the relative degree of access most people had to computers over the

                                               8 of 29
                                                                                                  Corewars: Revisited

1960s-70s compared with post-1984, another part of the problem was Darwin's simplicity; within
weeks of inventing the game, Robert H. Morris (well known in UNIX history, and correspondingly
well credited in the UNIX Programmer's Manual, 1979 edition [12]) wrote a 44-instruction self-
modifying organism, which was so effective in locating other organisms, that nobody was able to
create an organism capable of beating it [11].

The creators of Darwin acknowledged in a letter dated June 29, 1971 that the game could be
extended through further complication to create a more challenging experience:

          “Though Morris cleaned up under the particular rules, Darwin would again become
          interesting if the umpire introduced a little randomness in any of a number of ways.” [11]
          - M. D. McIlroy, R. Morris, V. A. Vyssotsky

The team of creators never did extend Darwin in the way they suggested, leaving the field open for
others to take over where they left off. Whether Dewdney was correct in perceiving the
Creeper/Reaper tale as little more than a myth, probably derived from the Worm and Darwin
programs, it was the ideas behind both Reaper and Darwin that sparked his curiosity.

          “Last year I decided that even if the story [of Creeper and Reaper] turned out not to be true,
          something like it could be made to happen.” [9]
          - A. K. Dewdney


2.2       The Game of Corewars

2.2.1 Instruction Set
The original Corewars instruction set was defined in 1984 in Core War Guidelines [13]. In it, Jones
and Dewdney acknowledge that there is no limitation to the size of the instruction set (and therefore
to the complexity of the Corewars implementation) other than the individual's available computer
memory, which was a serious limitation. Nowadays, many people's personal computers contain of
the order of tens of thousands of times the amount of RAM as some of the newest models around
the time Corewars was introduced [14], and memory requirements for all but the most demanding
applications are no longer of serious concern.

The ICWS'86 (1986) standard, based on the Core War Guidelines document [13], included only 8
different Redcode instructions:

      ●   DAT             Initialisation instruction; kills any thread that executes it
      ●   MOV             Moves (copies) a value or instruction
      ●   ADD             Addition



      0     JMP 1 JMP 9                                                                                  9

 Figure 4 Relative addressing. Starting at position 0, the first instruction would advance the Program Counter (PC)
 to the next memory cell. JMP 9 would then return the PC to the initial memory cell.


                                                       9 of 29
                                                                                   Corewars: Revisited

   ●   SUB            Subtraction
   ●   JMP            Jump
   ●   JMZ            Jump if zero
   ●   DJZ            Decrement and jump if zero
   ●   CMP            Compare values or instructions

The instruction set was extended to 11 instructions by the ICWS'88 (1988) standard [15]. The most
significant change was the introduction of multi-threading with the SPL instruction, allowing one
warrior to have multiple threads running simultaneously.

   ●   JMN            Jump if not zero
   ●   SLT            Skip if less than
   ●   SPL            Split (new thread)

   ●   DJZ (decrement and jump if zero) was changed to DJN (decrement and jump if not zero)

The ICWS'94 (1994) standard, whilst never being officially ratified, does exist as a draft proposal,
which many Corewars implementations adopted (including the reference implementation, pMARS).
Implementations including these newer draft proposals usually refer to them as ICWS'94
extensions. A further three instructions were introduced, taking the final total up to 14.

   ●   MUL            Multiplication
   ●   DIV            Division
   ●   MOD            Modulus

The final instruction set (with ICWS'94 extensions) is still simple and compact, but notably has
acquired multi-threading capabilities, a less-than comparison, and some common arithmetic
functions. However, since the ICWS'94 draft, no further additions or alternations have been made to
the standards, and therefore many implementations haven't added any additional features beyond
the '94 extensions. Some have, however, added a few additional commands of minimal importance,
such as SEQ (skip if equal: an alias for CMP), SNE (skip if not equal) and NOP (no op) [17].


2.2.2 Addressing
Corewars has a single memory space called the core, in which all addressing is relative, using
modulo-arithmetic. So far as warriors are concerned, there is infinite memory, as the core simply
wraps around when it reaches the end. Therefore, the current instruction is always instruction 0, the
next instruction is instruction 1, etc.

The core has a fixed size, N. As an example of addressing (see Fig. 4), if we consider N = 10, then
the core will run from 0 to 9. Using modulo arithmetic, if we start at the first memory space
(absolute position 0), and jump 1 instruction forward (or 11, or 21, ...), we will simply land on the
next memory space (absolute position 1) due to the wrap-around. Moving backwards to our
previous memory space (absolute position 0) can be accomplished by issuing a command to jump 9
instructions forward (or 19, or 999, ...).

There are a variety of different Addressing Modes available in Redcode, although initially (under

                                              10 of 29
                                                                                     Corewars: Revisited

ICWS'86) there were only three [13]. Pre-decrement was introduced in ICWS'88 [15], and post-
increment in ICWS'94 [16]; both being useful for loops.

   ●   Relative or Direct (relative to current instruction)
       ○ Addressing Mode: [blank] or $
   ●   Immediate (stores a value – immediately accessible data)
       ○ Addressing Mode: #
   ●   Indirect (uses one level of indirection to obtain the final value)
       ○ Addressing Mode: @
   ●   Pre-decrement Indirect (indirect, plus it decrements the indirect offset before following it)
       ○ Addressing Mode: <
   ●   Post-increment Indirect (indirect, plus it increments the indirect offset after following it)
       ○ Addressing Mode: >



2.2.3 Instruction Modifiers
Each instruction has two positive operands, respectively termed A and B. For example:

   ●   MOV 1,2 would copy the next instruction to the following memory cell
   ●   ADD 0,1 would add 0 to the A-field of the following instruction, and would add 1 to the B-
       field of the following instruction
   ●   ADD #1,0 would add the number 1 to the B-field of this instruction (leaving: ADD #1,1)

Until the ICWS'94 draft, programmers had no additional control over which operands are used in
different instructions, aside from using relative addressing to specify values directly, in which case
the B-field of the referenced instruction would typically be modified. Otherwise, with most
instructions, both A- and B-fields were affected.

One of the probable reasons the ICWS'94 draft is so commonly implemented (even though it
remains unofficial) is the addition of instruction modifiers, giving programmers moreorless
complete control over which fields are involved in different instructions. Amongst other benefits, it
makes it easier to make use of instructions' unused fields for storing data/counters/pointers, thereby
shrinking the size of the warrior.

   ●   A       read and write A-fields
   ●   B       read and write B-fields
   ●   AB      read A-field of A-operand & read B-field of B-operand; write to B-field
   ●   BA      read B-field of B-operand & read A-field of A-operand; write to A-field
   ●   F       read A-field, write to A-field; read B-field, write to B-field
   ●   X       read A-field, write to B-field; read B-field, write to A-field
   ●   I       read and write entire instruction


2.2.4 Playing the Game
Before warriors can be used, they need to be assembled. Most Corewars implementations will
include built-in Redcode assemblers; my implementation will include a standalone assembler which
integrates with the main application. The main task of the assembler is to generate a symbol table


                                               11 of 29
                                                                                       Corewars: Revisited

and replace all labels with relative addresses. Following successful assembly, the desired warriors
are randomly loaded into the core (there will usually be a specification of the minimum separation
between warriors).

The game commences with one instruction being executed from each warrior in a round-robin
fashion. With three warriors, execution would proceed: W0, W1, W2, W0, W1, W2, W0... . Should
a warrior split into multiple threads, then in each of the warrior's execution slots, one of the
instructions from one of its threads is executed (with the threads also scheduled in a round-robin
fashion): e.g. W0, W1, W2, W0, W1T0, W2, W0, W1T1, W2, W0, W1T0, W2, ... .

Any thread that executes any DAT instruction is killed (and removed from the warrior's thread
queue), and when all of a warrior's threads are killed in this fashion, the warrior is deemed to have
lost. The final warrior left alive is deemed the winner. Note that games will normally have set time
limits, meaning that it is possible for games to end in draws.


2.3       Warriors

The simplest warrior that can be made in Redcode was introduced by Dewdney in his original
article [9] as the Imp:

          MOV 0,1              [ or, in ICWS'94 parlance with modifiers, MOV.I 0,1 ]

The Imp uses a method known as a core clear to sequentially copy itself over every instruction in
the core. Due to its size it's very difficult to kill, so many warriors use multiple Imps as part of a
backup strategy; if the main part of the warrior is wiped out, at least some Imps will still exist, and
hence the warrior still has a chance of winning (but more likely drawing, if there's a time limit).

Many warriors use strategies than can (broadly) be categorised into three separate groups:

      ●   Replicators
             ○ Self-replicating; these warriors make many copies of themselves with different
                 threads, making them difficult to wipe out, but not very offensive either
                     ■ Consider how replicators will gradually slow their offensive manoeuvres as
                         as they create more threads: if your warrior currently has 10 threads
                         running, and your opponent's has just 1, then for every 10 instructions that
                         your opponent's warrior executes, each of the copies of your warrior will
                         execute just 1 instruction.
                     ■ Therefore, replicators often draw.
                     ■ Replicators are most effective against bombers due to replicators' resiliency.
      ●   Bombers
             ○ Offensive; bombers write DAT instructions at intervals throughout the core. Bombers
                 tend to be highly successful.
                     ■ If the interval is constant, it should be a multiple of the number of
                         instructions in the warrior and also (coresize % interval) should yield zero;
                         so as not to 'bomb' your own warrior.
                     ■ Bombers are most effective against scanners due to scanners being large



                                                12 of 29
                                                                                     Corewars: Revisited

                     (easy to hit with a reasonably small interval) and fragile.
   ●   Scanners
          ○ Highly offensive; scanners attempt to locate other warriors in the core before
             attacking them. The attack may be as simple as a core clear, or far more advanced.
                 ■    One way of locating other warriors is by placing pickets at intervals, and
                     periodically comparing the pickets to see if they've been overwritten
                 ■ Scanners are most effective against replicators; they often also use bombing
                     techniques to force replicator threads to continually create more threads,
                     thereby slowing execution down even more.

The analogy between “Replicators, Bombers and Scanners” and the “Paper, Rock and Scissors”
game is quite often made. Many warriors exhibit combinations of the three categories, and even
with relatively pure warriors victory for a 'Paper' warrior against a 'Rock' warrior (for example) is
hardly guaranteed. However, in many cases you do see a definite bias towards the Paper, Rock,
Scissors paradigm.




                                               13 of 29
                                                                                      Corewars: Revisited




3         Design

          “ Instructions that protect a larger program
          from a small, hard-to-defeat one would help to elevate
          Core War to a higher, more interesting level. ”
          - D. J. Jones & A. K. Dewdney [13]


3.1       Assembler

Corewars warriors are programmed in Redcode, an abstract assembly language. Due to its
simplicity there is relatively little compilation to perform before it reaches a state in which it can be
passed to the virtual machine for execution. In comparison to a high level language such as C++,
the level of compilation required is negligible. However, some features of Redcode necessitate a
degree of compilation:

      ●   Labels        descriptive names given to instruction lines, used to reference those
                        lines later in the warrior
      ●   Pseudo-instructions instructions not present in the instruction set which are interpreted by
                                the assembler (ORG, EQU and END)
      ●   Expressions           instead of constants, operands can contain expressions, e.g. label + 5

Furthermore, an assembler is expected to verify the input warrior's syntax and semantics. Syntax
verification is conducted when parsing the input and validating instructions, modifiers etc. against
lists. Semantic verification involves checking that the instruction's modifier and address modes are
logical. For example, the following instruction would fail semantic verification, for copying an
instruction into the immediate value 9 makes no logical sense:

          MOV.I 3,#9

Finally, the assembler should fill in any missing details, such as adding default instruction modifiers
to instructions without modifiers, and adding default address modes where omitted. For example,
(disregarding semantic invalidity) the above instruction is missing an address mode, and would be
corrected to:

          MOV.I $3,#9

The assembler will take an input Redcode Assembly File, compile it by performing the following
procedure, and produce a Redcode Load File, ready for loading into the core and being executed by
the MARS implementation.

      1. Parse the input, verifying syntax


                                                14 of 29
                                                                                      Corewars: Revisited

      2.   Build the Symbol Table from labelled lines
      3.   Replace labels in expressions with relative addresses, and remove label markers
      4.   Evaluate operand expressions to constants
      5.   Process any pseudo-instructions
      6.   Verify the number of operands is permissible
      7.   Complete any omitted details
      8.   Perform semantic verification

It should be noted that Assembly Files can contain comments with ;this syntax. Comments
are preserved by the assembly process [16], and should also appear in the corresponding Load File.

The Symbol Table only needs to adopt the simplest of
structures and maintain a list of labels against              Symbol (Label)         Address
(absolute) addresses (see Fig. 5). Any expressions            Bomb                   0
involving labels can then look up the corresponding           Loop                   13
address, calculate the relative offset from the current       SetPicket              34
                                                              ChkPicket              38
line (label_address - current_line) and include that in       ...                    ...
the calculation. Of course, like all values, this should
lie in the range 0 to coresize (recall that Corewars
uses modulo-arithmetic). Therefore, the offset can be              Figure 5 A Symbol Table
calculated by:

           relative_offset = (label_address - current_line) % coresize

Given the pressing time constraints with this project, I don't anticipate being able to implement
particularly descriptive error reporting based on syntactic and semantic errors, but will leave this for
future development. Furthermore, I intend to develop the assembler to a basic (ICWS'94) standard,
and only to update it to handle any extensions as and when I implement them in the virtual machine.
In this fashion, I should be able to avoid wasting time developing assembler features that I end up
not implementing in MARS.


3.2        Virtual Machine

3.2.1 Core
The Corewars core is simply a 1-dimensional list of cells, which wraps around due to modulo-
arithmetic. This means that warriors need not (and indeed cannot) have any concept of their position
within the core; they can only determine the relative location of other warriors. In other words, no
maintenance code is required (or possible) for warriors to navigate the core. The only number
programmers (may) need to concern themselves with is the coresize. For example, we've already
seen the simplistic Imp warrior, which doesn't even need to consider the coresize:

           MOV.I $0,$1

A relatively obvious way to complicate warriors, which so far as I know has not yet been proposed
or tried in Corewars implementations, would be to alter the structure of the core itself, thereby
forcing warriors to take the design of the core into consideration.


                                                15 of 29
                                                                                    Corewars: Revisited



There are two core alternations I intend to perform:

   ●   Using a 2-dimensional core
   ●   Using multiple cores

A 2-dimensional core can be seen as a square grid of cells. However, what really matters is what
happens when a warrior reaches the end of a row (imagine an Imp progressing along a row in the
grid). (Quite aside from the other problems posed by this), if the default action were to not only
advance the warrior's Program Counter to the next column (wrapping-around) but also to the next
row, then the 2D core would function almost identically to the original 1D core.

In my implementation, each row can be seen as an independent wrap-around 1D core. So, an
unmodified Imp would theoretically keep looping around the same row, ignoring all other rows in
the core. To make it advance to the next row, we could use a dedicated instruction; however, for
readability and intuitiveness, I decided to introduce 2D addressing. For example, with 2D
addressing using (x,y) co-ordinates, the Imp would become:

       MOV.I $0,$0,$1,$0                                        0,0                            4,0

The two operands have each been broken down into (x,y)
values, creating a total of 4 values. $0,$0 is the A
operand, which refers to the current instruction, and
$1,$0 is the B operand, which refers to the next
instruction (in the row). However, this will only continue
to advance the Imp around the row ad-infinitum (see Fig.
6); to copy an instruction into the next row, the Imp would
need to increment the y-value:                                  0,4                            4,4
                                                              Figure 6 A 2D core with an Imp only
       MOV.I $0,$0,$1,$1                                      advancing along one row


However, the Imp would still need to explicitly jump to the next row (the brackets indicate
optionality):

       JMP $0,$1(,$0,$0)

Thus, there is now no simple, one or two-instruction solution for a complete core-clear warrior. In
other words, the design of the Imp would need to be complicated; it would be easiest to implement
with a block of static control code. Possible strategies include:

   1. creating a Bomber and 'bombing' the core with MOV instructions (entirely defeating the point
      of the Imp; one may as well bomb the core with DATs)
   2. creating a Replicator to place an Imp on each row, then splitting to each one (i.e. creating a
      new thread for each Imp)
   3. placing JMPs at the end of each row and protecting the JMP cells, then starting an Imp. This
      would also require special attention after each core clear; the JMPs would need re-
      protecting, and another JMP would be required so as not to overwrite the control code


                                              16 of 29
                                                                                         Corewars: Revisited

Clearly, the first strategy is of no help; the second, multi-      0,0                            W-1,0
threaded solution is probably simplest and smallest in                      replicator
terms of implementation (see Fig. 7). It has another
advantage, in that the control code is no longer required
after the Imps and threads have been set up, so another
Imp can be let loose on the first row, overwriting the
control code, and meaning the core-clear will be entirely
comprehensive, much like the original Imp.

No matter which strategy you use, the humble Imp will           0,W-1
have to become a lot larger and more complicated,                 Figure 7 A 2D core with a replication
giving it less of an advantage against larger warriors.           block launching W-1 Imps on W-1 rows

The second core extension I intend to implement is allowing multiple cores. Whilst the 2D core will
make navigation much more complex, having multiple cores in one game will further divide the
game space, giving an advantage to warriors which try to locate their opponents, as opposed to
strategies based more heavily on luck (such as core clearing and bombing).

My intention is to implement multiple cores with a switch core instruction, COR, which will change
the thread's active core to the one specified, and execution will proceed from PC + 1 as usual (e.g.
COR #2). In order to load different pieces of code into the different cores in the first place, I will
add a pseudo-instruction which will specify the core number (e.g. LDC 2).

Furthermore, I intend to add some randomness to the game by introducing random memory
corruption on some writes to the core. It would involve a part of the instruction being written
becoming corrupted and changing to another, mimicing a hardware fault. This will require warriors
to be designed in a highly robust fashion.


3.2.2 Scheduling
Corewars has two different scheduling tasks to perform: it has to decide which warrior to execute
next, and it has to decide which thread to execute next for a given warrior.

    1. Select a warrior
    2. Select a thread from the warrior
    3. Process the next instruction from the thread
       1. Retrieve the thread's PC
       2. Retrieve the instruction at PC
       3. Execute the instruction
    4. Repeat until no warriors with running threads remain (or until time limit is hit)

Corewars uses the same simple scheduling algorithm, round robin, for warrior and thread selection.
Round robin is clearly quite appropriate for warrior selection, and I see no reason to change it.
However, with round robin being only provision for thread scheduling (and hence an equal
distribution of time between all threads), some programmers may feel restricted. As it stands, the
creation of T threads results in the original thread having only 1/(T+1) of the processor time it had
before.


                                                17 of 29
                                                                                     Corewars: Revisited

Many warriors use a combination of tactics, each of which will be comprised of different sections
of code, and each will quite often run in separate threads. There are many occasions one can
imagine when one warrior thread may deserve a higher priority than another; with replicators, for
example, where the controlling thread may need a higher priority than the threads it creates.

The ability to specify thread priorities would also encourage the use of multi-threading, as the
programmer would then have almost total control over his resource allocation (virtual processor
time). It's for this reason that I intend to allow the choice between the use of round robin scheduling
and priority scheduling for thread selection.

Adding control over individual thread processing time raises the possibility of warriors spawning
(very) many low priority threads to act as 'insurance policies' against the main threads being killed,
or to perform slow bombing, etc. At present, the drawback to spawning (very) large numbers of
threads lies with the fair round robin scheduling algorithm, and this drawback will be reduced in
severity by the addition of priority scheduling. One way of combating this tactic is by introducing
the concept of continuing to allocate processor time to threads that have already been killed.
Processor allocations would respect the (dead) thread's priority (or round robin), but no productive
work would be performed in this processing time.

It's my hope that dead thread handling will give a warrior a fighting chance against a persistent, fast
replicator, by slowing it down as more of its threads are killed.




                                               18 of 29
                                                                                      Corewars: Revisited




4         Implementation

          “ It always takes longer than you expect,
          even when you take into account Hofstadter's Law. ”
          - “Hofstadter's Law”, Douglas R. Hofstadter [18]


4.1       Overview
I have produced an executable, zMARS, which provides a CLI interface Memory Array Redcode
Simulator, capable of taking one or more Redcode Load Files and providing an interactive
Corewars game, with many of my extensions. I also produced a second executable, Assembler,
which takes a Redcode Assembly File and produces the Load File. Neither currently contain all the
functionality I desired (including complete ICWS'94 compliance), however zMARS is more than
sufficiently developed to demonstrate most of the concepts in this paper.

ZMARS can take a small number of command line arguments, including (most importantly) the
warrior file locations, but most configuration is currently performed in the zMARS environment.
The following is an overview of the main configuration options available in zMARS:

      ●   Core size                    cs [core_width]
      ●   Number of cores              nc [num_cores]
      ●   2D core                      2d+ &     2d-                  (enable & disable)
      ●   Memory protection            mp+ &     mp-                  (enable & disable)
      ●   Memory corruption            mc+ &     mc-                  (enable & disable)
      ●   Dead thread persist          dt+ &     dt-                  (enable & disable)
      ●   Priority scheduling          ps+ &     ps-                  (enable & disable)

All settings are set to sensible default values at the start, with all additional extensions disabled. Any
manual configurations can be entered as the user sees fit; in this example, I first query the current
core size, and then set it to the value 8000:

          Command> cs?
          Core Size is 8192
          Command> cs
          Set Core Size
          Enter Core Size (1+, 0 to cancel): 8000
          Core Size set.

Users can also enter commands more directly; here I enable priority scheduling, memory protection,
memory corruption and set the coresize to 8000:

          Command> ps+ cs 8000 mp+ mc+


                                                19 of 29
                                    Corewars: Revisited




       Figure 8 zMARS UML diagram; showing only the
       most significant attributes and operations


20 of 29
                                                                                      Corewars: Revisited



The following is an overview of the main commands available in zMARS:

      ●   Add a warrior                  w [warrior_filepath]
      ●   Run                            r
      ●   Step                           s
      ●   Step                           step [number_times]
      ●   Instruction breakpoint         b [instruction]          (set)
      ●   Instruction breakpoint         b- [instruction]         (unset)
      ●   Display core                   cd [all | line_no | line_no-line_no]
      ●   Reset                          n
      ●   Help                           h
      ●   Complete command list          ?
      ●   Quit                           q

No external libraries are required to compile zMARS, aside from ncurses (link with -lncurses)
if the ncurses version is used; however, this is still under development.

4.2       Program Flow

I intend to give an overview of the main class interactions encountered in a typical execution of the
game. It may help to refer to Figure 8 to supplement this text.

      1. ZMARS instance is created
      2. Configuration instance is created with default configuration settings
      3. ArgParser instance is created
      4. Any command line arguments are parsed by ArgParser and handled by ZMARS (which will
         register them with the Configuration)
      5. CLIController instance is created
      6. VirtualMachine instance is created
      7. ZMARS waits for input; all input is handled by CLIController
      8. Any input specifying configurations is registered with the Configuration
      9. Input starting a game will call newGame() in VirtualMachine, then:
      10. VirtualMachine creates a Core instance (which then creates and initialises the core(s)) and a
          Scheduler instance
      11. Scheduler creates a ThreadHandler instance and a Processor instance
      12. VirtualMachine creates InstructionLoaders to load all warriors into the Core
      13. Initialisation is complete; CLIController regains control and invokes the run() or step()
          commands in Scheduler.
      14. Scheduler schedules a warrior and a thread, and passes control to Processor by calling
          fetch(), decode() and execute().


                                                 21 of 29
                                                                                    Corewars: Revisited

      15. Scheduler monitors game progress for breakpoints and victories, or if just stepping through
          the execution, then control will return to ZMARS, awaiting the next user command.
      16. When the game finishes or a breakpoint hits, control will return to ZMARS, awaiting the
          next user command.

4.3     Processor Class

The Processor class implements the MARS virtual machine which can process those instructions in
the Corewars instruction set, including my extensions. It doesn't implement all of the ICWS'94
features that I had intended it to, such as read and write limits, but the significant majority are
included, and the instruction set is complete. The ICWS'94 draft [16] was an invaluable reference for
creating this class.

A Processor is created by invoking Scheduler's constructor. The Scheduler is the class that receives
requests from the UI controller to control execution, and hence the scheduler passes instruction
addresses to the Processor to fetch, decode and execute.

         Instruction*
              fetch(Address) Retrieve the instruction at Address in the active core
                             and set the Instruction Register (IR). A pointer is
                             returned for debugging purposes.
         void decode()       Find the instructions/values referenced by the A and B
                             operands (the A- and B-pointers).
         void execute()      Process the instruction.

In processing the instruction, a function or collection of functions are called depending on the
opcode. Typically, values will then be read from the core, which will involve calling
Core::read(Address), and values will be written back to the core, which will involve calling
one of the write functions, such as Core::write(Address, Instruction). By routing all
write requests through the write functions as opposed to writing directly to core (which would, in
cases, be simpler), I can catch those write requests on protected cells, and take appropriate action.

Finally, the Processor may instruct the ThreadHandler to increment the current thread's PC, or to
queue a new thread with a call to one of the overloaded newThread functions such as
ThreadHandler::newThread(Address, ...), or it may ask the ThreadHandler to kill the
current thread.


4.4     Multiple Cores

I decided to implement the multiple core extension in a different fashion to the one described in the
previous chapter, as I wanted to allow the flexibility to move instructions between cores
dynamically during a game, and not just upon loading. Instead of a switch core instruction and an
additional pseudo-instruction, I opted for two new instructions, permitting moving instructions
between cores and spawning a new thread in a specified core:



                                               22 of 29
                                                                                        Corewars: Revisited

   ●   MVC             MOV (with core specifier) – move A to B on core C
   ●   SPC             SPL (with core specifier) – split to A [ignore B] on core C

Both take an additional operand at the end; the core specifier. As with everything else, the core
specifiers begin at 0, and the number of cores available corresponds to the nc configuration setting
(the default is 1 core).

       ___ Core 0 ______________               ___ Core 1 ______________
       ..                                      ..
       23    MVC.I $0,$1,1                     23
       24    SPC.I $0,1                        24    MVC.I $0,$1,1
       ..                                      25    MVC.I $0,$1,1

The effect of executing the two lines shown on core 0 (above-left) would be to:
       a) copy instruction 23 (core 0) to cell 24 (core 1)
       b) create a new thread, starting on cell 24 (core 1)
       c) the new thread would execute the MVC like a standard MOV as the core specifier (1) refers
       to the core it's in (1); an Imp has therefore been introduced to core 1.

You'll notice that MOV is simply a special case of MVC, so they are able to share the same code.
Furthermore, to reduce impact on existing code, I introduced the idea of an “active” core in the
Core class, which the generic “core” pointer references. The active core (pointer) can be set by
Core::setActiveCore(int).

4.5    2D Core

The 2D core needs to be enabled with the 2d+ configuration command, and the coresize should be
set with caution. Somewhat misleadingly named, the coresize configuration setting really sets the
core width (even on a 1D core, where core width is equal to core size). The size of the core created
from specifying cs 100, for example, would be 10,000 cells; when combined with multiple cores,
one can easily forget they're dealing in widths and request a very large block of RAM.


4.6    Priority Scheduling

Priority scheduling needs to be enabled with the ps+ configuration command. The implementation
is designed to be intuitive, and makes use of a previously unused operand in the SPL instruction.

       Without priority scheduling: SPL address[,anything]
       With priority scheduling:    SPL address[,priority]

The larger the priority value, the less time the thread will be allocated; for example, with two
threads of priorities 1 and 2, the priority 1 thread can expect almost two-thirds of the execution time
(execution would proceed T1, T2, T1, T1, T2, T1, T1, T2, T1, T1, T2 etc.).

The first thread is given a static priority of 1 by default, and further threads have their static


                                                23 of 29
                                                                                       Corewars: Revisited

priorities set by the priority given in the SPL instruction. The threads retain their static priorities,
but are also given dynamic priorities (originally set to the static priority value) in an effort to avoid
starvation. The ThreadHandler maintains each warriors' threads in queues, and the scheduling
algorithm works in this fashion:

   ●   Remove the thread at the top of the queue
   ●   Compare the thread's static and dynamic priority values
       ○ If they are equal, schedule an instruction from the thread for execution
   ●   Decrement the thread's dynamic priority by 1
       ○ If the thread's dynamic priority has fallen below 1, restore it to its static priority value
   ●   Insert the thread at the bottom of the queue
   ●   Repeat

Whilst there exist more efficient algorithms, this achieves excellent fairness over time and is
relatively simple to implement.

This debug output from a game, showing instruction execution, demonstrates the dynamic
prioritisation in action. Thread 0 has static priority 1, and thread 1 has static priority 5:


 [DEBUG]   Step 0 warrior: 0 Thread: 0 Priority: 1 Core: 0 PC: 2
 [DEBUG]   Processor: Executing 'SPL.I $1,#5'... adding thread priority 5 done.
 [DEBUG]   Step 1 warrior: 0 Thread: 1 Priority: 5 Core: 0 PC: 3
 [DEBUG]   Processor: Executing 'ADD.B #1,$1'... done.
 [DEBUG]   Step 2 warrior: 0 Thread: 0 Priority: 1 Core: 0 PC: 3
 [DEBUG]   Processor: Executing 'ADD.B #1,$1'... done.
 [DEBUG]   Prioritising... (Thread 1 Orig_Priority 5 Dyna_Priority 4 -> 3)
 [DEBUG]   Step 3 warrior: 0 Thread: 0 Priority: 1 Core: 0 PC: 4
 [DEBUG]   Processor: Executing 'JMP.A $9,$2'... done.
 [DEBUG]   Prioritising... (Thread 1 Orig_Priority 5 Dyna_Priority 3 -> 2)




                                                24 of 29
                                                                                   Corewars: Revisited




5      Evaluation

       “ universes of virtually unlimited complexity
       can be created in the form of computer programs ”
       - Joseph Weizenbaum [19]


5.1   Adding Complexity

The extensions I've implemented through this project were largely aimed at adding complexity. To
illustrate this, the ICWS'94 instruction set originally contained 14 instructions, but including the
extensions there are now 17. There are 5 additional features that can be enabled, and in addition the
number of cores can be specified.

In the following analyses from the perspectives of each of the main three strategy groups, I will
investigate the new issues involved in programming warriors, when all new features are enabled. Of
course, many warriors actually use a combination of these three strategies, so in reality the pluses
and minuses will be less readily apparent.


5.1.1 Programming Bombers
A 2-dimensional core will necessitate extra stages (to keep track of when to switch rows) in the
bombing loop, slowing down the bombing process considerably, unless a static off-centre diagonal
path through the grid is chosen, or some other such solution. Multiple cores will most likely be
handled by spawning new threads for each core (or some of them).

Memory protection could pose a real problem, for if another warrior has already protected its
essential cells, then one complete bombing run would be useless. The obvious way to remove the
risk of protection is to bomb each location twice in succession, but this would add at least two more
instructions to the bombing loop. On the other hand, the PTM instruction could be useful to use as a
bomb itself.

Memory corruption should pose less of a threat to a bomber than most for two reasons; a) because
the bombing loop (whilst growing longer with every extension) is still comparatively short, and b)
bombers don't need to replicate their control code, so the only writes that could be corrupted after
the warriors are loaded are the DAT (or JMP, PTM or SPL) bombs themselves, which wouldn't
particularly matter.

Finally, neither dead thread persistence nor priority scheduling should particularly impact bombers,
as they aren't innately dependent on multi-threading. I conclude, therefore, that bombers are likely
to drop bombs at a significantly slower rate (quite how much slower depends somewhat on whether
the programmer decides to double-bomb locations or not). However, I think this could be mitigated


                                              25 of 29
                                                                                     Corewars: Revisited

against by spawning new threads for rows and cores (and using thread priorities to control them if
necessary), or by carefully selecting a static bombing interval such that it distributes well over the
core.

5.1.2 Programming Replicators
Replicators are not affected by a 2D core to any serious degree, and replicating across multiple
cores shouldn't even require half-a-dozen extra instructions, depending.

Memory protection could pose a problem for replicators, especially if the core has already been
bombed with PTMs. To validate the warrior once it was copied would double the time taken for a
replication, in which case one may as well use the double-write technique. Either one of these,
though, would increase the size of the warrior, and more than double the copying time.

Replicators will also be vulnerable to memory corruption, given that they perform a lot of writes,
and most of the writes will be critical to the survival of each self-replication. Coupled with dead
thread handling, where each thread that dies continues to consume valuable processing time, this
could prove costly, if the likelihood of memory corruption is set particularly high.

Priority scheduling should give a big boost to replicators, as it gives them some control over the
importance of each separate replication. By employing tactics such as giving most self-replications
low priorities, whilst leaving one or two with high priorities and additionally protecting their cells,
replicators can mitigate against dead thread handling whilst retaining strong, protected regions,
which also acts as a backup in case of corruption or PTM bombing.

5.1.2 Programming Scanners
Scanners will be affected by the 2D core, especially when attempting to locate warriors through
pickets and when targeting discovered warriors. It is conceivable that some clever programming
will be required in order not to increase the size of the warrior by too large a proportion. Scanners
will also be affected by multiple cores, as large blocks of code will need to be copied from core to
core. Should dead thread handling be enabled, this may be a particularly time consuming process.

Memory protection may not pose such a problem for scanners; it's very likely that programmers will
want to protect their scanners due to their relatively large size and rarity in the core. Meanwhile,
pickets (being single cells) would often be statistically unlikely to be placed on a cell previously
bombed by a PTM, and once a warrior is located, it would make sense to core-clear or bomb the
suspected site using at least some double-writes. Also, memory corruption is unlikely to pose a
problem, as few if any of the writes will be critical to the warrior's survival.

Finally, priority scheduling may help some scanners, depending on their construction. So, the
largest problem faced by scanners is likely to be the additional logic behind navigating 2D cores,
and the time taken to copy the warrior to other cores. On the other hand, memory protection will
offer a strong advantage to a warrior which could previously be described as a sitting duck.


5.2   Future Work

My decision to reject the existing MARS sources and to start development 'from scratch' did result

                                               26 of 29
                                                                                            Corewars: Revisited

in a lack of time to complete all the intended tasks. The tasks remaining to be completed are:

   ●   Some minor ICWS'94 features
   ●   GUI
   ●   nCurses-based CLI (I have created a separate nCurses version, but so far haven't added the interactive
       displays that will make it worth its while)
   ●   Block memory copy instruction
   ●   Pseudo-instruction handling and default instruction modifier insertion in the Assembler

Furthermore, had planned to experiment with different warrior evolution strategies, with the goal of
developing a warrior evolver, and contrasting its success against other common evolvers.

There are now, however, many other ways in which I would like to extend the project further. For
one, configurations should be loadable from config files, specified on the command line. This
would allow batch jobs, faster and easier testing, and a more convenient way to load different sets
of default settings.

Another handy addition would be a pseudo-instruction, e.g. PRI, which would allow the
specification of the priority of the initial thread (when priority scheduling is enabled). By default,
the priority is 1, which could be restrictive if you want finer-grained control over priorities. The
ability to set the initial priority to 10, for example, would provide a wider range of possibilities.

Finally, the 2D addressing scheme, whilst working well, does have one drawback: there is no way
to select either an X or a Y value from one of the operands. In some cases this drawback can be
overcome, but only at the expense of additional instructions and messy code. A solution would be to
introduce additional instruction modifiers, which can explicitly select the X or Y portion of the
operand. For example:

       MOV.AX #3,#17,$1,$1                           Move the X portion of the A-operand (3) to the
                                                     X-portion of the A-operand
       MOV.BYX #9,#7,$3,$0                           Move the Y portion of the B-operand (0) to the
                                                     X-portion of the B-operand
       ADD.ABY #13,#1,$7,$8                          Add the Y portion of the A-operand (1) to and store
                                                     the answer in the Y portion of the B-operand

I intend to continue working towards these goals.




                                                      27 of 29
                                                                                    Corewars: Revisited




6      Conclusion

How much complexity is too much?
How much complexity is too little?

These questions almost always rest upon the observer's familiarity with the subject in question. For
a beginner to Corewars and Redcode, many of the additional features I've added may seem slightly
excessive, which is why they are optional, and disabled by default.

For some highly experienced Corewars players, I dare say I could have gone further, but the
additions already made, when all in use simultaneously, can drastically alter the game. To take but
one example; programming a warrior for a 1D core of just 8192 cells is dramatically different to
programming one for 50 2D cores, each with core widths of size 128. The latter would result in a
total of 100 times the number of cells in the 1D 8192 core, and accessibility is limited by multiple
self-wrapping rows and split-to-core instructions.

Undoubtedly, this project has added a lot of scope for warrior design, and has succeeded in making
the design of even conceptually simplistic warriors a far more challenging task.

Whilst I didn't complete the MARS to ICWS'94 standards, which is frustrating, I also didn't get
around to testing the effectiveness of evolving Redcode warriors. Especially since Corewars has
roots in Darwin, such an experiment would have been particularly appropriate.

A potential problem arising from including so many options in Corewars, especially when some are
quite dramatic in their effect, is the probability that warriors will be designed for specific sets of
enabled features. Without an assertion mechanism built in to the Assembly File (like is currently
used in some implementations to assert coresize), recognising which configurations to use, given a
particular warrior, could be tricky.

However, assertions can be added, but I think I have demonstrated at least conceptually that
Corewars can be made more challenging and more complex with relatively simple ideas; and, that
by doing so, it can give those with the will and the capability far more scope for designing
interesting warriors. I hope it also acts as an incentive, on Corewar's 25th anniversary year.




                                              28 of 29
                                                                             Corewars: Revisited




     References
1    rec.games.corewar FAQ:
     http://homepages.paradise.net.nz/~anton/cw/corewar-faq.html#WhatIsTheICWS
2    Corewar Hills
     http://corewar.co.uk/hills.htm
3    pMARS homepage
     http://www.koth.org/pmars/
4    nMars homepage
     http://nmars.sourceforge.net/
5    jMars homepage
     http://sourceforge.net/projects/jmars
6    nMars source code
     http://nmars.svn.sourceforge.net/viewvc/nmars/trunk/
7    Software Freedom: Microsoft – Novell Patent agreement
     http://www.softwarefreedom.org/perspectives/2006/ms-patent-promise/
8    Annotated Draft of the Proposed 1994 Core War Standard
     http://www.ecst.csuchico.edu/~pizza/koth/icws94.html
9    A. K. Dewdney: Computer Recreations article in Scientific American
     http://www.corewars.org/sciam/
10   Worm programs
     http://vx.netlux.org/lib/ajm01.html
11   Darwin letters
     http://www.cs.dartmouth.edu/~doug/darwin.pdf
12   1979 UNIX Programmer's Manual
     http://minnie.tuhs.org/UnixTree/V7/usr/doc/
13   Core War Guidelines 1984 (the basis of ICWS'86)
     http://corewar.co.uk/cwg.txt
14   IBM 5150 factsheet
     http://www-03.ibm.com/ibm/history/exhibits/pc25/pc25_fact.html
15   “Core War '88 - A Proposed Standard” (basis of ICWS'88)
     ftp://ftp.koth.org/pub/corewar/documents/standards/redcode-icws-88.Z
16   ICWS'94 Annotated Draft
     http://www.ecst.csuchico.edu/~pizza/koth/icws94.html
17   The beginners' guide to Redcode, v1.21, Ilmari Karonen
     http://vyznev.net/corewar/guide.html
18   Chapter 5, Godel, Escher, Bash: An Eternal Golden Braid, Douglas R. Hofstadter.
19   Computer Power and Human Reason, Joseph Weizenbaum




                                         29 of 29

								
To top