1. What is Maezumo?

Maezumo is an open-source program that automatically generates virus-like programs (known as warriors) for the game Corewar. This document describes the settings for version 1.04 of Maezumo.

In Corewar these warriors battle each other in the core memory space of a virtual computer called MARS (Memory Array Redcode Simulator) to eliminate all opponents.

If you're not familar with Corewar go to one of the following sites for more information:


The warriors are usually hand-coded, but there are also programs - like Maezumo - available who "evolve" such warriors.

2. How does Maezumo work?

If you start Maezumo executable the following will happen:

1. A warrior will be created (details are in chapter 3)
2. The warrior battles then against the No.1 of the internal league (known as hill). This is Phase 1 of the Benchmarking.
3. If the warrior performs good enough (according to the used settings) it will battle the whole hill. This is the Phase 2 of the benchmarking.
4. The last placed warrior will fall off the hill
5. Maezumo startes again from 1.

This loop will run infinitely until you press "q" in the cmd window. In case you're in progress to benchmark against the whole hill it could take a moment until Maezumo stops.

To watch the progress in evolution simply open the index.htm. It will be updated every time a warrior battles against the whole hill.

3. How does Maezumo generates warriors?

Maezum offers different modes to generate warriors:

Pure Evolution Mode
All instruction lines in the warrior are randomly generated. This is similar to what most other "evolving" programs for Corewar do.

Paper Hint Mode
This hint mode will generate exclusively warriors which self-replicates. If you don't know what this means please read the following links for more details:

Exploring Replicators by Nenad Tomašev - Core Explorer #1
Papers by Christian Schmidt - at the Corewar Lexicon

The hint mode generates instruction lines by random selection of precasted code fragments together with randomly generated code, as used in the pure evolution mode. Overall a good randomness is achieved for a high divergency of generated warriors.

Scanner Hint Mode
This hint mode will generate scanning warriors. If you don't know what this means please read the following links for more details:

Anatomy of the Scanner - A Basic Introduction by John Metcalf

The hint mode generates instruction lines by random selection of precasted code fragments together with randomly generated code, as used in the pure evolution mode. However, scanner can be quite complex, so the divergency is still limited so far.

Stone Hint Mode
This hint mode will generate stone warriors. If you don't know what this means please read the following links for more details:

My First Corewar Book by Steven Morrell - Chapter 2: Stones
Exploring Stones - The Basics by Nenad Tomašev - Core Explorer #2

The hint mode generates instruction lines by random selection of precasted code fragments together with randomly generated code, as used in the pure evolution mode.

Composite Hint Mode
This hint mode uses randomly all available precasted code fragments.

This is not a hint mode, but if activated it will generate a separate pool of warriors and mutate them. Sometimes it will be send back for Phase 1 of the benchmarking. For details about Mutation see section 6.

The type of hint used to create a warrior is recorded in the warrior comments, for example ;origin Paper 44 for a paper created at hill age 44. Warriors created randomly within the soup are labeled ;origin Random followed by a number indicating the original soup position. This method helps to ensure that new warriors have a unique origin string. New warriors begin at generation 0, if the warrior mutates then the ;generation number is incremented but the origin comment remains the same. Note that mutation can change a warrior so that it is no longer the kind of warrior indicated by the origin.

4. How can I modify the settings to my demands?

Now, after you know how Maezumo works here is the description how you can adjust the settings to your demands. Just open the Maezumo.ini and change the values of the parameter.

Warrior Parameter
name       :____
The name will appear in the warrior as ;name ___ followed by the number
author     :____
The author will appear in the warrior as ;author ___
type       :____
The type will appear in the warrior as ;redcode-___

Benchmarking and Hill Parameter

There are two kinds of benchmarking: scoring warriors against a hill of warriors, and scoring warriors against a test set composed of warriors of the same type to estimate the strength of the evolved warriors.
coresize   :
max. proc  :
max. cycle :
max. len   :
min. dist  :
These should be set for the type of warriors being evolved. Typical types are:
Type-name     type   coresize   max. proc   max. cycle   max. len   max. dist
Standard | 94 | 8000 | 8000 | 80000 | 100 | 100 |
Tiny | tiny | 800 | 800 | 8000 | 20 | 20 |
Nano | nano | 80 | 80 | 800 | 5 | 5 |
Tourney | 94t | 8192 | 8000 | 100000 | 300 | 300 |
Limited Proc | lp | 8000 | 8 | 80000 | 200 | 200 |
Experimental | 94x | 55440 | 10000 | 500000 | 200 | 200 |
Maezumo only generates '94 code, it cannot generate '88-rules code such as used by the ICWS hill.
mars       :(typically exmars or pmars)
Sets the path and name of the mars simulator. The string "mars" must occur in the name, optionally a location such as "D:\MyFiles\pmars-server.exe" can be specied, if the path contains spaces the parameter must be quoted. Maezumo uses typical pmars-compatible switches, the simulator must understand -s -c -p -r -k -l -d -F etc.

hillsize   :(typically 11 to 31)

How many warriors are used for the hill. The last warrior is either a warrior that did not make the hill, or was pushed off the hill.

threshold  :(0 to evo rounds)
Number of wins against the first ranked warrior of the benchmarking hill to enter phase 2
advance    :(0 to +- evo rounds)
Number of wins which must achieved more than the first ranked warrior of the benchmarking hill to enter phase 2
evo rounds :>10 (typical 250)
Number of rounds against the first ranked warrior of the benchmarking hill (phase 1)
hill rounds:>10 (typical 250)
Number of rounds against the benchmarking hill (phase 2)
hill freeze:(0-(hillsize-1))
This parameter let freeze the top of the benchmarking hill. The value assign the number of warriors affected. If 0 all warriors are benchmarked. This parameter is especially useful if evolveing against a certain set of warriors.
No of koth :(0-(hillsize-1))
Number of top warriors on the benchmarking hill which are randomly fighting in Phase 1. If 1 then only the first ranked warrior of the benchmarking hill is used. This parameter is especially useful if evolveing against a certain set of warriors.
hill save  :(0,1)
If this parameter is set to 1 then all warriors who make it onto the hill will be saved in the species directory
If this parameter is set to 1 then all warriors who make the hill will be benchmarked against a test set
BenchDir   :(directory containing test warriors)
If EnableBench is set to 1 then BenchDir specifies the test set directory used for the bench score, which is added to the warrior comments. Warriors must have .red .war or .rc extension to be recognized.
ShowExtra  :(0,1)
If ShowExtra is set to 1 then origin, generation and bench score is displayed in the HTML report. Only the first 3 letters of the origin is displayed, generation and bench score are displayed only if mutation/bench enabled.

Evolving Parameter
hint mode  :(0,1,2,3,4,7,8)
Set the hint mode for the evolving:
0: pure evolution mode
1: paper mode
2: scanner mode
3: fragment mode
4: stone mode
7: ALL modes ON
8: paper and scanner mode
evo len    :(5 - max. len)
Number of instructions (Warrior Length) of the evolved warrior
spl        :(0-5000)
mov :(0-5000)
add :(0-5000)
sne :(0-5000)
seq :(0-5000)
probabilities for linear opcodes (0-5000)
djn        :(0-5000)
jmn :(0-5000)
jmz :(0-5000)
jmp :(0-5000)
probabilities for looping opcodes (0-5000)
hint-pur   :(0-5000)
hint-pap :(0-5000)
hint-sca :(0-5000)
hint-fra :(0-5000)
hint-sto :(0-5000)
Probabilities for different hints when using hint mode 7

Mutation Parameter
Mutation   :(0,1)
Set Mutation to 1 to enable, 0 to disable
Topology   :(0 to soupsize-1)
Set Topology to 0 for grid-shaped soup, >0 selects ring and specifies maximum distance between warriors selected to battle each other during parallel evolution.
SoupSize   :(>5 or >topology whichever is bigger)
Size of the hidden soup for mutation
SoupX      :(0 to soupsize/2)
Width of the soup when using grid topology, if 0 specified then selects a square soup (as close as possible). SoupSize should be a multiple of SoupX (or square of an integer) for a "normal" grid.
Set to 0 for no soup display in the report, or set to 1 for text cells, 2 for narrow blocks, 3 for wide blocks or 4 for hex symbols. Browser support may vary. The soup display is colored so the main color represents the instruction sequences with other redcode elements changing the shade of the color. Soup display mode 5 selects a custom display string, specified by the SDcustom setting.
SW Display :(0,1)
Set to 1 to display the code of randomly selected soup warriors along with its display color (if soup display enabled)
SaveSoup   :(0,1,2)
Save soup behavior.
0: load soup from species dir, don't save
1: load soup from soup dir, save to soup dir
2: load soup from species dir, save to soup dir
MutByProb  :(0,1)
Set MutByProb to 1 to use probability settings above. Set to 0 to mutate from array using hard-coded opcodes and weighting
dat        :(0-5000)
Additional probability setting for dat instructions
MutSelect  :(0-1)
This parameter sets how often mutation is selected rather than a hint, from 0 to 1 (0 effectively disables mutation, 1 always mutates if a soup warrior is available, typical value is 0.5 to 0.8)
EnableSeed :(0,1)
Set EnableSeed to 1 to copy warriors that make the hill to the soup. Set to 0 to disable seeding so that parallel evolution is not influenced by the hill or hint-made warriors. Useful for evolving without using the pure hints, select the pure hint mode and set MutSelect to 1, a few pure hints will make the hill at first but if the parameters are good the "Random" soup warriors should take over.
MinChanges :(typical 1)
Minimum number of changes when mutating to avoid duplicate warriors
MutRate    :(typical 1)
Master mutation rate, all rates are multiplied by this
SoupIter   :(typical range 3 to 25)
Number of soup battles/mutations for each hill cycle. Smaller is faster, larger produces more mutation within the soup. Set to 0 to disable parallel soup evolution
SoupRounds :(typical range 20 to 200)
Number of rounds used for soup battles, smaller is faster, larger for more accurate battles (not always good)
InstrRate  :(0-1) (typical 0.01)
Chance of instruction change per line
AddrRate   :(0-1) (typical 0.03)
Chance of address mode change per item
DataRate   :(0-1) (typical 0.05)
Chance of data value change per item
SwapRate   :(0-1) (typical 0.01)
Chance of swapping two lines of redcode, per line
InsertRate :(0-1) (typical 0.01)
Chance of inserting a new line, per line
DeleteRate :(0-1) (typical 0.01)
Chance of deleting the current line, per line
DupLine    :(0-1) (typical 0.2)
Chance of duplicating the previous line when inserting a new line
IncDec     :(0-1) (typical 0.5)
Chance of increment or decrement (instead of random) when changing data
BigNum     :(0-1) (typical 0.5)
Chance of a big number (instead of small number within the warrior size) when randomly changing data.

5. How can I re-initialize Maezumo for a new evolution?

Actually to re-initialize Maezumo you have to do the following:

- empty the "species" and "soup" folders

- set the value in the age.ini and evo.ini to 1 (also works to delete the files to start at age 0)

- delete the content in the warrior.ini (or delete the file)

- change the parameter for your new evolutionary run in the Maezumo.ini

This can be automated using a batch file, say "re-initialize.bat" (be careful not to run by accident!):
@del soup\*.red
@del species\*.red
@del age.ini
@del evo.ini
@del warrior.ini

6. How does Mutation work in Maezumo?

Mutation is a process where random changes are made to the code of warriors in the hopes of making them better. For parallel evolution, two "nearby" soup warriors are selected for battle, and the warrior that wins is copied over the warrior that loses while making occasional random changes. Sometimes no change at all is made, sometimes many changes are made at once. The soup is arranged as a ring of warrior positions, warriors selected for battle are from 1 to 4 positions apart. If a selected position is empty, a random warrior is created. This causes different parts of the soup to develop areas of different strategies which can develop semi-independently of other areas, although eventually strong warriors spread throughout the soup. The ring "topology" with the limited range slows the spread of strong warriors to provide a better chance for other strategies to develop elsewhere in the soup. Another popular topology is the grid where warriors battle one of 8 neighboring warriors. The grid topology tend to work best with a large soup (and is more "visual" when used with an evolver with a soup display), the ring topology provide better control of spread when using a smaller soup but the "islands" of similar strategies can only battle other strategies on one of two "sides" so the warriors are not exposed to as many different strategies unless the form spreads elsewhere. It would be relatively easy to add support for a grid-shaped soup to Maezumo, but practically the two approaches perform roughly the same so the simpler method was chosen.

Maezumo uses a hill and hint-generated warriors, and can make use of mutation even if parallel evolution is disabled. Each time a warrior makes the hill, if  it is copied to a random location within the soup without change, and at each hill cycle, there is a chance (set by the MutSelect parameter) that it will select a random soup warrior and mutate that (instead of using a hint) to create the warrior used for the Phase 1 test. If a soup warrior does not exist, or the minimum number of changes (set by the MinChanges parameter) were not made (to avoid duplicate warriors), then it uses the originally selected hint. This simple method permits combining brute-force hint-based evolution using an evaluation hill with traditional Darwin-style evolution.

Several kinds of changes can happen when a warrior is mutated, controlled by the mutation rates and other settings described in section 4. The individual rates are described by a number from 0 to 1, if InstrRate is set to say .03 then each instruction in the warrior has a 3-in-100 chance of being changed to a different instruction. Some control over the selected instructions can be performed by setting MutByProb to 1 then setting the instruction probabilities as desired - these settings also affect code generation by the pure "hint". When MutByProb is 0 then the program uses a hard-coded table of opcodes and (sometimes) modifiers, selected to generate more MOV and SPL instructions than others. The hard-coded address mode table selects "$" modes more often. Expert evolvers may wish to modify the source code to alter the default tables but if doing that the first 16 instructions and first 8 address modes must not be changed, the hints and probability settings depend on these remaining the same. It is possible to add INI file support for changing the "extra" instructions and modes, however this was not done in the present version to avoid unnecessary complexity. One factor that must be considered if altering the tables - if changed then previously-created warriors that use instructions removed from the table won't be correctly loaded back into the soup, so the instruction tables aren't something that should be easily changed. Try to use the probability settings if a different instruction mix is desired.

Some of the mutation settings are used only if other kinds of changes take place. The IncDec setting is used when a data (field) value is changed, and determines if a +/- 1 change is done instead of choosing a new random value. If a random value is chosen, then the BigNum setting determines if it is a big number from 0 to coresize-1, or a small number +/- warrior size. The DupLine setting is used when a line is inserted to determine the chance of it being a duplicate of the previous line, this can help build up blocks of SPL and MOV instructions but if set too high it can be distracting, making the line look like a mistake.

7. How can I make stronger "Pure" warriors?

By choosing evolving parameters that favor the survival of strong warriors, however that is easier said than done. Pure evolution is a very random process, the same parameters produce different results with each run so it can be very difficult to find the right settings. Purely-evolved warriors for larger coresizes can be interesting but rarely can compete with hand-coded warriors except in some environments that are "friendly" to evolved warriors. However it is possible to evolve nano warriors that are stronger than hand-coded warriors. The top few slots of the SAL nano hill are usually occupied by evolved warriors. Don't expect it to be easy - evolving strong nano warriors often requires many tries and experimenting with the settings, and it may take many runs to determine if a particular INI file is "good". Sometimes it only works well only once.

The "pure" hint can help or hinder depending on what it does. Sometimes it seeds the soup with a good form that does well both in the soup and on benchmark tests, other times the pure hint produces a warrior that beats the soup warriors but does not score well. The MutSelect setting can be used to determine how much of an effect the pure hint warriors have, lower values (typically 0.5) should seed the soup with warriors of Pure origin, to encourage warriors of Random origin set MutSelect to 1. The SoupIter setting also has an effect, higher values make it more likely for a Random warrior to take hold in the early stages of evolution, and performs more parallel evolution per cycle for less interference from the hill (and also requires better mutation settings since the hill won't be driving the scores up as much). To totally disable the effect of the hints on the soup set EnableSeed to 0. Set MinChanges to 0 to keep the pure hint from running should the warrior not mutate, this produces more duplicate warriors but it might add stronger warriors to the hill by not changing the soup warriors and weakening an already strong form.

Experiment with different topologies. Usually the ring soup with Topology set to 4 does fine, but experiment with the number which determines how rapidly warrior forms spread through the soup. The grid topology may offer slightly better performance because warriors are exposed to a greater variety of other strategies and might provide greater diversity. The main advantage of the grid topology is it permits visually observing the soup to determine if mutation rates are too low or too high. Identical colors are usually duplicate warriors, similar colors are usually mutations of the same instruction sequence. For best results "islands" of similar warriors should appear, if not the mutation rate is probably too high. Some duplicates in the soup usually is a good thing, but if a single color takes over completely the mutation rate is probably too low.

If a strong form (such as SPL MOV MOV MOV DJN or MOV SPL MOV MOV DJN) does not appear within a few hundred cycles, consider starting over, or archive the run and come back to it later. If an inferior form takes over the soup it makes it unlikely for a stronger form to arise because new sequences usually start out weak. This is sometimes called finding a "local maximum". Making the soup larger may help, but typically a single popular form will take over anyway. The trick is to get a strong form to mostly take over but still show diversity within itself. Note that if using the soup display often the same sequence of base instructions will be colored completely different because different instruction modifiers are used, observe the code that makes the hill and how well it scores.

Sometimes the warrior that beats the king of the hill isn't the best warrior to try, or a very strong warrior might not be able to beat the top warrior. Setting no. of koth to 3 might work better than the normal value of 1 (this can sometimes help hint-driven evolution too).

Once strong warriors arise, test them against multiple benchmarks. Warriors that do well on the nano hill should score high on the NanoBM07 benchmark, and also score high against the top 20 nano warriors from Koenigstuhl. A good nano warrior that can place near the top of the hill should get a score of around 150 on both benchmark tests.

8. How can I find strong warriors?

When EnableBench is set to 1, Maezumo adds a benchmark score to each warrior that makes the hill and is saved to the species directory. Warriors with high bench scores don't necessarily stay on the hill. The following "findtop.bas" program searches through the species directory and reports the best warrior found:
100 REM Find top-scoring Maezumo warrior in the species dir
110 REM (warriors must have ;benchscore comment)
112 REM by WTN 7/15/09
120 usewin=1 'set to 0 for Linux, 1 for Windows
130 targetdir$="species"
140 outfile$="" 'optional output file (useful if thresh < 1)
150 thresh=1 'lists warriors within this of top score
160 topscore=0:top$=""
170 if usewin then dc$="dir /b /on ":ps$="\" else dc$="ls -1 ":ps$="/"
180 shell dc$+targetdir$+ps$+"*.red > findtop.dl"
190 open "findtop.dl" for input as #1
200 if outfile$<>"" then open outfile$ for output as #3
210 while not eof(1)
220 line input #1,wn$:if usewin then wn$=targetdir$+ps$+wn$
230 open wn$ for input as #2
240 b$="0"
250 while not eof(2)
260 line input #2,a$
270 if left$(a$,12)=";benchscore " then b$=mid$(a$,13,6)
280 wend
290 close #2
300 score=val(b$):if score < topscore*thresh then goto 340
310 if score > topscore then topscore=score:top$=wn$
320 print "Warrior ";wn$;" scores ";str$(score)
330 if outfile$<>"" then print #3,"Warrior ";wn$;" scores ";str$(score)
340 wend
350 close #1:kill "findtop.dl"
360 if thresh >= 1 then goto 390
370 print "Top score warrior is ";top$;" score=";topscore
380 if outfile$<>"" then print #3,"Top score warrior is ";top$;" score=";topscore
390 if outfile$<>"" then close #3
400 system
To also list warriors that rate near the top score set thresh=0.97 or so - sometimes the slightly lower-scoring varients will score better on other benchmark tests. This might list a lot of warriors, run on a terminal with scrolling ability or set outfile$="topscore.txt" to write the results to a topscore.txt file.

It might also be a good idea to check the soup directory for strong warriors. Soup warriors don't have benchmark scores written to them so a benchmark program would have to be used. This can take a long time but might find strong warriors that were not able to make the hill. The following "benchsoup.bas" program might be useful:
100 REM Benchmark a directory of warriors against a benchmark set
102 REM by WTN 7/15/09
110 REM ---------------------------------------------------------------
120 usewin=1 'set to 1 for Windows, 0 for Linux
130 soupdir$="soup" 'set to directory containing warriors to test
140 testdir$="NanoBM07" 'set to directory containing test set
150 testmask$="*.RED" 'set to match test warriors
160 report$="souprep.txt" 'set to name of file to write bench report to
170 rounds=500 'number of rounds
180 sim$="exmars -b -k -s 80 -p 80 -c 800 -l 5 -d 5 -F 40" 'sim comline
190 REM ---------------------------------------------------------------
200 sim$=sim$+" -r "+str$(rounds)+" ":print "Press Esc to stop"
210 if usewin then dc$="dir /b /on ":ps$="\" else dc$="ls -1 ":ps$="/"
220 shell dc$+soupdir$+ps$+"*.red > souplist.tmp"
230 shell dc$+testdir$+ps$+testmask$+" > testlist.tmp"
240 open report$ for output as #1:topscore=0:top$=""
250 open "souplist.tmp" for input as #2
260 while not eof(2) and inkey$<>chr$(27)
270 score=0:n=0
280 line input #2,war$:if usewin then war$=soupdir$+ps$+war$
290 open "testlist.tmp" for input as #3
300 while not eof(3)
310 line input #3,opp$:if usewin then opp$=testdir$+ps$+opp$
320 shell sim$+war$+" "+opp$+" >scores.tmp"
330 open "scores.tmp" for input as #4
340 line input #4,a$:close #4
350 z=instr(a$," "):w=val(left$(a$,z)):t=val(mid$(a$,z))
360 score=score+w*3+t:n=n+1
370 wend
380 close #3
390 score=(score/n)*(100/rounds)
400 if score>topscore then topscore=score:top$=war$
410 sc$=mid$(str$(-1*(1000+score+.00001))+" ",3,6)
420 print sc$;" ";war$
430 print #1,sc$;" ";war$
440 wend
450 close #1:close #2
460 kill "souplist.tmp":kill "testlist.tmp":kill "scores.tmp"
470 print "Top score = ";str$(topscore);" by ";top$
480 system
Edit lines 130 to 180 to set up the benchmark, sim$ must be correctly set for the core size etc, usually -F is coresize/2. Smaller core sizes require a bigger rounds number for accuracy, 500 to 1000 for nano, 200 to 500 for tiny, 100 to 300 for standard. Exmars is shown but if desired pmars can be used instead. For nano versions 0.9.2+ have a "permutate" option which increases accuracy with fewer rounds, instead of -F 40 specify -P and specify 142 for rounds. Like this...
170 rounds=142 'number of rounds
180 sim$="pmars -b -k -s 80 -p 80 -c 800 -l 5 -d 5 -P" 'sim comline
The bench program lists the top-scoring warrior for convenience, but this might not be the "best" warrior, if strong warriors are found for best results sort the output file (souprep.txt unless changed). For both Windows and Linux the command sort souprep.txt should list the strongest warriors at the end of the list. Note that the soup is usually full of duplicates, warriors with the same score are likely identical copies.

These programs are designed to run under the Blassic interpreter but they should also run under QBasic etc. If desired they can be compiled using FreeBasic using the option -lang qb but compiling makes it more difficult to change the settings by editing the BASIC code.

[variations of these programs are in the tools directory]