Redcode Evolver Bash Script

REBS is a GNU/Linux bash script that uses pmars to evolve warriors for corewar.

  • Download rebs14.tar.gz · configured for nano, tiny and standard warriors
  • Redcode Evolver Bash Script v1.4 · "nano" version in text form
  • Redcode Evolver Bash Script v1.3 · previous "tiny" version in text form
  • Linux binaries for pmars/pmarsv · compiled by me from v0.8.6 source
  • evol_rd · the bash script I use to run on a Linux ramdisk
  • REBS also runs under Windows using Cygwin.

    Before attempting to run REBS, edit the script and make sure a non-graphics version of pmars is available using the command listed for the pmars variable. Specify the full path/name if pmars is not installed in a path directory. Edit the number of files and change the display variables as needed.

    Now that solid state drives are more common - do not run REBS on a solid state drive! like most file-based evolvers it writes files constantly and will wear out a flash-based disk. Run from a ram disk instead and verify using iostat etc that no disk writes are taking place. Good idea even on a regular hard drive.

    REBS does a lot of file reading and sometimes triggers a bash memory leak, this should now be fixed in REBS v1.4 running under bash versions 3.1 or 3.2 but when testing use a utility to monitor memory usage to ensure it doesn't clog up the system and/or terminate with a fork error. If leaking memory periodically stop and restart to reclaim the wasted buffer memory. This is more of an issue when evolving nano warriors. By default REBS uses a lot of CPU time, with v1.4 increase the sleeptime setting at the top of the script to reduce CPU usage.


    Sample run...

    The following screen shots show the early evolution of a soup of ~650 warriors, colored by origin...
    (this was created with a previous version of REBS, now all of the warriors in a grid are plotted, status display looks a bit different in the 1.4 versions)

    Unfortunately with only 15 colors there's a chance multiple species (warriors of different origins) will be colored the same, a different color mapping reveals two dominant species...

    The best-performing warriors were found in the gray region, like this one...

    ;redcode
    ;name 359.red
    ;author rebs1.3
    ;parent 295.red
    ;origin 567.red
    ;generation 63
    ;assert 1
    add.a { 279 , > 111
    spl.x # 431 , $ -9
    mov.i # 465 , } 2
    mov.i # 465 , } 3
    spl.f < 43 , } 670
    spl.f # 22 , @ 94
    mov.f < 230 , # -7
    mov.i $ 439 , } 8
    mov.i @ 439 , } -2
    mov.a # 192 , } 6
    jmp.i { 89 , @ 377
    dat.a @ 590 , { -10
    dat.a @ 590 , { -10
    end 1

    ...which scores a fairly low (~114 against the Franz test set) at this very early stage of development. This is a soup I'm running on my 133mhz Win95/Cygwin machine so results are slow in coming. My 1.4ghz AMD evolves hundreds of generations in an overnight run, sometimes producing warriors that score in the 130-150 range as of version 1.3b. Luck plays a huge role, as does the evolution parameters, in how strong a soup will grow. Unfortunately this means the results of a single run or even a few runs often doesn't mean anything but sometimes does, making parameter selection tricky. Another phenomena to watch out for is an unchanging environment may never produce particularly strong code, not enough challenge. Periodically altering the change rates and other variables may help encourage new strategies.


    REBS Ramblings...

    First code was posted 3/9/05, first relatively stable version was 1.0f posted 3/12/05. Page down for the most recent postings, out-of-date stuff is periodically purged when too much accumulates.

    3/20/05 - Updated rebs.txt to version 1.1, added an option for circle topology and now writes parent, origin and generation count into the comments. Ok to use with soups from 1.0, adds the new comments upon evolving. So far the circle topology is working well for maintaining diversity long enough to allow weaker but more intelligent designs (like papers) to work themselves out before being exposed to other more direct forms (like stones).

    3/21/05 - Added the evol_rd script for evolving on ramdisk, hopefully it's general enough now to adapt. I've been running the new code with circular topology for a couple of days now, no super-warriors have appeared but it seems to work better than plain random selection, at least it keeps one form from immediately taking over the soup. In the end though the maximum strength warriors attain in the runs I've made is about the same (~140 Franz) regardless of topology, so something else seems to be limiting things, I'd like to see at least the 160's. When I increased the change rates replicators appeared after only 30 or so generations but after 200+ generations nothing stronger than about 105 was in the soup and it didn't appear to be improving. I'm running an experiment with lower change rates to see if that makes a difference. I can tell things are on a slow track, at ~80 generations there were only a couple forms trying to replicate and doing a really bad job at it. There are many other things that might limit strength (or more accurately affect the odds of strong code appearing) including population size, instruction mix and lack of precision battles. Sometimes mutations happen that cause strong code to appear despite less than optimum parameters, only after many runs can trends be deduced and then not exactly.

    3/23/05 - The slow change-rate run never went anywhere, back to the original chance numbers. Instead I'm trying other things for version 1.2... new vars datatweekchance and endtweekchance control how often an increment or decrement occur rather than replacing with a random number. Now has double-fixed battles which seems to produce more accurate battle results. Ring topology was interesting, added grid topology to the selections. Actually it's a skewed cylinder with wrap on the sides but no wrap from the top to bottom, this was the easiest to code. An xsize variable controls how many warriors are on each line. This number determines how fast code spreads by how much room there is for the strain to squeeze by competing forms. Eventually I'd like to program an inspection tool for browsing, battling and benchmarking the soup, hopefully something native but I've got a lot more to learn about Linux programming before I can tackle anything fancy like that. An evolver or a benchmarker is relatively easy... but making a highlight bar move around a dense display of warriors with list, run, bench and battle options for all neighbors is another matter, might have to invoke QBasic.

    3/24/05 - 1.2a - fixed a couple of minor bugs.. added another condition to prevent warriors from growing too big under rare conditions, origin status display (O:number) now displays all the digits when more than 1000 warriors. This version has somewhat higher change rates, particularly in the data fields, and xsize is set to 3, an odd topology resembing a triangular spiral tower if visualized but it helps avoid early saturation while allowing some mixing.

    3/27/05 - 1.2b - changed the way the random number generator (RNG) is seeded, now it prompts. The problem with most RNG's is they aren't really random, just an extremely long sequence of numbers that appears random. Because of this, the outcome is predetermined by the exact position in the RNG's sequence (the seed), the exact state of the variables and evolution code, and the state of the soup. Previously I was using the output of date to seed the RNG but that leaves huge regions unexplored, besides requiring a GNU date command, a potential compatibility problem for Windows since dos's date might get picked up instead. The present solution is don't seed at all (thus intruducing at least some uncertanity when a script is stopped then restarted) unless a key is pressed within 2 seconds of startup, then it prompts for the seed number (up to 9 digits on my system). I figure if anything is going to predetermine the outcome then let it be the user's imagination.

    Version 1.2b also has somewhat different parms, the high change rates in 1.2a seemed to be too much, backed off, increased the number of warriors to 1000 and increased rounds to 250 double-fixed battles in an attempt to generate stronger code. The latest versions had only been reaching a max score of around 125, worse than before when the change rates were in the 200-500 range with 200 random battles with random or circle topology. Now the change rates are in the 400-500 range, but it may take days to see how the new parms perform due to the higher rounds and warriors... typically 200 generations or more are needed before one can tell where a soup is going and judging from past experience, sometimes thousands of generations are needed to produce warriors capable of placing a hill.

    3/29/05 - turns out read -t n fails on some versions of bash (like the Cygwin 1.1/bash 2.04 I have under Win95), tired of trying to solve the RNG seed issue in a satisfactory way so for REBS 1.3 removed the seed code altogether, in the grand scheme of things it probably doesn't matter unless the random numbers printed on startup are the same every time, in which case system-specific RNG seed code can be put in another script.

    REBS 1.3 now has a soup display! Uses columns to display long and narrow grids, not sure how system dependent the ANSI codes are but sure looks neat and gives a much better feel for what's going on in the soup. Since it would be difficult to add any kind of interactive interface to REBS itself I'm contemplating making a soup exploration program based on the same display but with cursor keys to select a warrior and keys for running in pmarsv and benchmarking.

    3/30/05 - the big crash.... for about 10 minutes on 3/29 a broken 1.3 was posted (forgot a 10# in the colorizing code), got the fix uploaded and went to work and that was the last time my 900 mhz machine booted. Might be terminal, the processor fan clogged and likely the cpu got too hot. The good news is it looks like I'll be getting one of those speedy GHZ motherboards I keep hearing about and once fixed I'll be able to waste ~3x the cpu cycles. Until then I'm stuck testing the current 1.3 on my 133mhz Win95/Cygwin platform. So far it's working slowly but fine, presently running a soup of 650 warriors arranged in a 65 by 10 grid (warriors=650, xsize=65, ylines=10, statline=13, rounds=50, enablefixed=0) to get a screenshot.

    4/2/05 - REBS 1.3a was developed on my 133mhz Cygwin machine and has the rounds set low to make it bearable, display is set to a single-column 65 by 10 grid (same parms used for the screenshot). Added an option to display the existing soup before evolving (making grabbing screenshots much easier). This may be the beginnings of an interactive user interface... my previous thinking was to make that a separate exploration program but it would make more sense if one script did it all, the display code is already there. Today I installed new guts in my fast machine, now it's a 1.75 ghz AMD Sempron 2500 running at 1.4 ghz with the motherboard defaults, barely gets warm.

    4/4/05 - The new system is very fast, I ran REBS 1.3a for awhile to see what happens (this time) with the fast low-rounds parms, eventually warriors scoring ~125 appeared. Along the way I added a colormethod variable and a condition to color the warriors by origin or by length, to keep a color display after the soup saturates with one species.

    4/6/05 - REBS 1.3b is set up to color by length. I'm noticing that high rounds and double-fixed battles don't necessarily produce stronger code, 50 rounds random works about as good as 400 or more fixed rounds and evolve warriors at a much faster rate. Or it's fooling me again... conclusions are hard to make with only a couple runs. I tried less bias on the SPL and MOV instructions but the results were not as strong over a couple of runs, for whatever it's worth.

    4/7/05 - Trying a larger soup (~1300 warriors) with lower change rates, also replaced the 3 in the by-species colorizing code with $fndigits so it would catch all of the origin number when more than 1000 files. The generation readout in the status line is jumping back and forth in the status line, gotta fix that too... stupid bug. New version 1.3c uploaded.

    4/8/05 - I finally fixed the roundoff problems causing REBS to not generate all of the specified files, new version 1.3d uploaded. Also should select all data elements when evolving 8000-sized warriors. I resisted this because I didn't want to complicate things but the missing warriors were getting to me, ended up being easy and very low impact. 1.3d is set up to generate 1617 files (21x77) and may have the change rate set too low (or I'm not being patient enough), best results scored in the 90-100 range. Trying again with the rates set to 300-500. [nothing good became of it]

    4/10/05 - version 1.3e had change rates in the 200-500 range, with greater odds of duplicate lines. Rounds set to 50, trying double fixed again. So far these variables have produced slightly stronger code, max scores in the 140 range. Version 1.3f adds a couple of command line options for use when redirecting the screen output to an ANSI "movie" file which can be played back at high speed using the cat command. This almost worked with the previous rebs but stopping and starting produced glitches, bin-editing a 20 meg file to remove the glitches was not fun so added the -redir option to suppress extra text and -append option to suppress extra text and the frame/soup redraw. The -redir parm isn't strictly necessary when starting a redirected recording (the extra text gets cleared anyway) but in the future may be necessary to suppress any other interface elements that may get added - like an interactive interface I can use to cursor around the soup and examine warriors, manually calculating file numbers is getting old.

    4/14/05 - I figured out how to partition the rest of my new 80 gig drive and now I don't have to worry about wasting gigs on huge ANSI files and such, but the raw output is way too large to post. I found code on the net for making animated gifs (ansi2gif by Vince Weaver) and modified it to skip a large number of characters between frames to make reasonably-sized animated graphics files, like this recording of a run (525k) which produced this replicator...

    ;redcode
    ;name 1586.red
    ;author rebs1.3f2
    ;parent 1585.red
    ;origin 0898.red
    ;generation 187
    ;assert 1
    mov.f @ 8 , } 64
    mov.ab $ 421 , @ -10
    spl.ba # 422 , } 568
    mov.i > -4 , } -2
    mov.i @ -5 , { 239
    jmp.i } -3 , > 3
    djn.i { -9 , < 8
    sne.ab * 232 , @ 4
    mod.x { -5 , * 5
    spl.i } 639 , @ 7
    spl.b * -11 , $ -8
    end 1

    An interesting feature of this specimen is it replicates in 800 and 8000 sized cores, not all that strong though.

    5/20/05 - after a long run of rebs 1.3f5...

    The strongest members I found were 1158.red, 1315.red and 1392.red, all similar. These score ~155 against the Franz "tiny" warriors, about ~135 against the contents of the SF evolved hill, and a not so great ~110 against the SF tiny hill warriors. Rebs 1.3f5 has lower change rates and a slightly different instruction mix compared to Rebs 1.3f, and is set to 50 rounds random battles rather than double-fixed battles. The lower change rate probably helps but luck and timing seems to be major determining factors. When the soup is checked makes a big difference, at around 7K generations the top scores were ~120 against the SF evolved, at around 9200 generations I was getting ~125-130, at ~9600 generations I picked out the above warriors, at ~9900 generations the top scores are ~125 again and the code has changed significantly (but essentially does the same thing just not as well against benchmarks). The up and down nature of the scores makes sense for a closed system, there is no evolutionary pressure to do anything except survive. After 9900 generations and noticing declining performance I lowered the size change chance and the mode/data chances (rev 1.3f6), continuing evolution to see what effect these changes have on the population.

    5/22/05 - I ran this soup to about 10600 generations, there was hope around 10400 generations but after that scores dropped again. Here's a comparison of five top-scoring warriors taken at different times...

                    |                |                |;name 1547.red  |
    |;name 1207.red |;name 1392.red |;gen 9953 |
    ;name 1385.red |;gen 9206 |;gen 9599 |seq.ba <227,@ -5|
    ;gen 7668 |seq.f { 1,*535|mov.b #216,< 1|seq.x {775,@ -5|;name 0515.red
    dat.a < -9,#388|jmp.x @700,<652|spl.a } 0,< -8|mod.f # -1,$307|;gen 10483
    dat.ab >667,{711|dat.x }695,# 3|dat.f #603,# 2|dat.ba > -6,{ 8|spl.f # -2,>280
    spl.i #722,> -7|spl.i #675,> -8|spl.ab #704,$ 2|spl.i #742,}529|spl.x #732,>271
    spl.i # -9,{ -1|spl.i #282,{ -1|spl.i # 57,{ -1|spl.i # 8,{ -1|spl.i # -6,{ -1
    mov.i #-10,} 5|mov.i # -8,} 6|mov.i # -9,} 6|mov.i # -8,} 6|mov.i # -8,} 6
    mov.i } 4,{ -3|mov.i } 5,{ -3|mov.i } 5,{ -3|mov.i } 5,{ -3|mov.i } 5,{ -3
    mov.i < 6,{ 2|mov.i { 6,{ 2|mov.i < 6,{ 2|mov.i < 6,{ 2|mov.i < 5,{ 2
    mov.i $ -6,< -5|mov.i $ 2,< 3|mov.i $ 2,< 3|mov.i $ 2,< 3|mov.i $ 2,< 3
    djn.ab @450,} 1|djn.f @444,{256|djn.i @443,{258|djn.i @440,{140|djn.i @433,<157
    mod.f * 79,<627|dat.i <688,<354|dat.i @693,<355|dat.i }515,< 99|dat.i <296,$614
    dat.f }532,{185|dat.a # 10,$777|dat.i > 19,*780|dat.x * 85,$776|mov.i @ 8,$778
    spl.x @482,>627|spl.i { -9,<606|slt.a *522,<-10|spl.b > 8,# -3|mov.b @557,$ 1
    end 2 |end 3 |end 3 |jmp.i < 2,< 1|djn.i } 7,# -9
    | | |spl.i > 8,>272|mov.i #508,{ -5
    | | |dat.ba } -5,< 3|jmp.i #508,{ -5
    | | |dat.f {-10,}605|jmn.f $509,{ -7
    | | |end 4 |spl.x <323,> -2
    | | | |end 1
    scores=151,122 |scores=146,132 |scores=156,133 |scores=142,126 |scores=141,131

    Things that stayed the same are colored green, changes are colored red and tweeked data fields (within 10) are colored blue. The green areas show the parts that apparently matter to functionality, the red areas are likely code-garbage.

    1/17/09 - I've been using REBS to evolve nano-size warriors for a coresize of 80 and a maximum length of 5 instructions. With nano parms REBS can perform hundreds of thousands or even millions of iterations in an overnight run, or hundreds to thousands of generations of the soup, which led to discovering a memory leak I never noticed before... every second it loses a few kilobytes, going through several hundred megabytes over the course of a few hours. When available user memory is exhausted it issues a fork error and stops, returning all the memory back to the system. Stopping the program normally by deleting DeleteMe also returns memory, some kind of internal buffer that accumulates cruft from something, trying to figure out what. In the mean time I just stop it every now and then, need to do that anyway to check the soup, or simply let it run out of memory and think of it as a feature to prevent overcooking the soup (not - got to at least figure out what's leaking).

    The /dev/ram15 ramdisk method doesn't work on all systems as the size of the ramdisk is fixed and sometimes (like on my Eee PC 701SD) not big enough. An alternate method is to use ramfs which permits specifying a maximum size and only uses memory actually consumed by files. However free space is always 0 so causes issues with some GUI's like Gnome. KDE complains when copying files to a ramfs ramdrive but permits clicking "ignore" to continue. Here's the ramdisk script I use on my 701SD...

    #!/bin/bash
    if [ ! -e ~/rd/work ];then
    echo "Creating 25 meg (max) ramdisk with ~/rd/work directory"
    if [ ! -e ~/rd ];then
    mkdir ~/rd
    fi
    sudo mount -t ramfs none ~/rd -o maxsize=25000 && sudo mkdir ~/rd/work
    if [ -e ~/rd/work ];then
    sudo chmod 777 ~/rd/work
    else
    echo "Operation failed"
    fi
    else
    echo "~/rd/work directory already exists"
    fi

    As currently posted REBS runs flat out consuming close to 100% of the CPU time. Typically that's what I want but sometimes (especially with nano warriors) it's useful to slow it down. Might also help with newer PC's that overheat with 100% CPU usage (especially laptops with more specs than cooling), or make the system more responsive to use while evolving. At the beginning of the script add a setting for sleeptime...

    .....
    version="1.3f"
    sleeptime=.1 # time in seconds to sleep between iterations
    # pmars configuration....
    .....

    ...and towards the end of the script insert a SLEEP command between the status echo and plot call...

    .....
     echo -n " O:${origin:0:$fndigits} L:${linecount:0:3}G:$generation "
    sleep $sleeptime
    if [ $enableplot -ne 0 ]; then
    .....

    [this is already present in the new v1.4 version of REBS]

    1/18/09 - I think I'm honing in on the mem-leak bug, illustrated by this short script...

    #!/bin/bash
    # memory leak test - bash 3.1.17
    function testread {
    read -r line
    }
    echo "test" > test.fil
    while [ 1 ]; do
    testread < test.fil
    done

    ...when run it eats memory rapidly, about a megabyte a second on my 701SD with bash 3.1.17, however it does not leak on my Ubuntu system running bash 3.2.39 so the leak there is something else, still losing about a megabyte every 2 minutes while evolving nano warriors. This varient does trigger a leak under Ubuntu...

    #!/bin/bash
    # mem leak test - bash 3.2.39
    function testread {
    read -r line
    }
    echo "test test" > test.fil
    while [ 1 ]; do
    testread < test.fil
    done

    The -r option simply suppresses interpreting backspace as an escape char, same results with just plain read line. Replacing the space in "test test" with x fixes the leak. Ouch. This varient doesn't leak...

    #!/bin/bash
    # mem leak test - bash 3.2.39 workaround
    function testread {
    read -r word1 word2 word3 word4 word5 word6 word7 word8
    line="$word1 $word2 $word3 $word4 $word5 $word6 $word7 $word8"
    }
    echo "test test" > test.fil
    while [ 1 ]; do
    testread < test.fil
    done

    Hmm... unfortunately it destroys the formatting of the original line, so that won't work unless other stuff is also modified, particularly the parsing functions that depend on the position of a string in the line.

    1/19/09 - fixed the memory leak I think, at least with bash versions 3.1 and 3.2. Took quite a bit of code change so REBS is now v1.4 (and experimental, might need more tweaks). The warrior format changed slightly, should still be compatible with older REBS versions but haven't tested yet. The new REBS (version 1.4exp1-nano) is configured for nano warriors, for tiny warriors copy the settings from v1.3. I was suprised the fix worked on bash 3.1 too, the trick seems to be to supply more read variable targets than there are word in the input line. Odd, but I'll take it. Now I can get back to the fun stuff - trying to evolve competitive nano warriors. So far not having much luck but noticed most nano warriors use only SPL MOV and DJN with the occasional DAT and other instructions, and none in my test sets use P-space. So weighted the instruction set to heavily favor SPL and MOV and moderately favor DJN, that seems to help but still not producing all that strong of warriors. I think the problem might be that warriors that score well against members of its own kind don't score particularly well against other warriors, and might suppress the generation of replicators which tend to tie when playing against similar replicators - as soon as a scanner or lucky bomber comes along the paper form is consumed. Contemplating ways to counter this effect... one way is through manual intervention - selecting warriors that show promise and evolving only them, or perhaps even introducing "alien" warriors into the soup then watching it carefully to keep them from simply killing off all the other soup warriors. I don't really want to re-evolve existing warriors since once a particular form has been optimized it generally gets worse with further evolution - but that's OK for the purpose of training the other soup warriors to learn how to beat them. The new v1.4 mod makes this a bit easier since now spacing isn't important in the redcode so long as there are no labels or constants and there is at least one space between each element. Alien warriors must begin with 7 comments in the normal REBS format with an end line address and be in "unix" text format if using Linux.

    1/21/09 - new version 1.4exp3-nano - modified the fixdata function to help resist invalid numbers, missing end lines etc, not quite as fragile now. REBS tends towards warriors of a single seed origin, partially because of statistics and partially because stronger forms tend to swamp weaker forms. Even though the soup might contain a lot of variation the display always becomes boring using the color by origin method. To better see what's really going on I added a new warrior comment for species which starts out the same as the origin, if the base instructions or starting location (end line) changes the species is set to the current warrior name. A new colormethod setting permits colorizing the soup by species so new forms that arise during the course of evolution can be seen in the display.

    2/6/09 - new version 1.4a0 - Added a new parameter to specify the minimum size of randomly generated warriors but not sure how effective it is, defaults to 1 like previous versions. Modified grabscores so it doesn't require single-word author and name (more like v1.3 now) and added more dummy words to the readinputline sub in preparation to possibly add periodic benchmark testing - I feel like on long runs I'm missing out on strong code that may arise then go away. This would open up the possibility of periodically reintroducing strong code back into the soup, providing a way to gently guide the evolution process without too much forcing like would occur if the warriors were evaluated directly against test warriors - that usually results in warriors that are strong against a test set but nothing else. Went through the code and tweaked up enough to drop the "experimental" label (I hope, but good enough for an "a"). Among changes, warriors and warrior numbers now use a random multiplier of 1000 for better accuracy, had noticed when evolving with a large soup of 5250 warriors (150x35 grid) the last 7 soup positions were never chosen, probably was doing the same with coresize 8000 warriors but worse had a bug where it occasionally made a warrior that was too big, fixed that. The tar.gz archive now contains versions of REBS configured for nano, tiny and standard warriors. Don't expect much from the size 8000 version, parms are copied from the 800 version. I never had much luck evolving standard size warriors, the search space is vast and with all those instructions human coders practically always do better, hard to get a "Wilkies" score over 80 with a simplistic evolver like REBS. Nanos are another story!

    I got a few REBS warriors (barely) on the SAL nano hill, here are a couple...

    ;redcode-nano
    ;name 0614.red
    ;author Terry Newton
    ;strategy Evolved by rebs1.4exp3-nano
    ;strategy Koen090112(20) score = 144.9
    ;strategy nanobm07 score = 141.1
    ;parent 0537.red
    ;origin 0020.red
    ;generation 3524
    ;assert CORESIZE == 80
    spl.ab # 72 , > 9
    mov.i { 0 , < 40
    mov.i @ 25 , { -2
    mov.i < 38 , { -1
    djn.i $ -2 , $ 76
    end 0
    ;species 1285.red

    Opponent Scores Results Performance of 0614.red
    -------- ------ ------- ---------=---------=---------=---------=
    Nano'Powa 331 397 125 103 22 *********************
    Black Sun III 399 321 97 123 30 *****************
    8c09fc1a-479925 336 405 132 109 9 *********************
    Chiki Chiki 333 375 111 97 42 ********************
    Cosmic Horror 417 291 83 125 42 ***************
    Dodecadence 369 339 99 109 42 ******************
    eerie glow 336 372 110 98 42 *******************
    flight 371 329 93 107 50 *****************
    Foggy Maus (bet 355 385 125 115 10 ********************
    glowing embers 349 364 109 104 37 *******************
    hemlock 338 341 90 89 71 ******************
    a slice of moon 403 340 111 132 7 ******************
    c82f15b5-85011f 385 355 115 125 10 ******************
    Pacler Deux 391 304 83 112 55 ****************
    Red Moon 403 337 109 131 10 *****************
    ripples in spac 330 369 106 93 51 *******************
    ripples 22 267 444 135 76 39 ***********************
    the spiders cre 345 354 101 98 51 ******************
    Staphylococcus 326 410 132 104 14 *********************
    White Moon 332 413 136 109 5 **********************
    1046.red 302 434 140 96 14 ***********************
    0614.red 345 399 131 113 6 *********************
    Left Alone 370 358 112 116 22 *******************
    Muddy Mouse (RB 365 377 123 119 8 ********************
    -------- ------ ------- ---------=---------=---------=---------=
    Adjusted Score: 146.8

    ;redcode-nano
    ;name 1046.red
    ;author Terry Newton
    ;strategy Evolved by rebs1.4exp2-nano
    ;strategy Koen090112(20) score = 143.8
    ;strategy Nanobm07 score = 142.5
    ;parent 0970.red
    ;origin 0179.red
    ;generation 739
    ;assert CORESIZE == 80
    spl.b # 0 , < 50
    mov.i < -1 , { 71
    mov.i $ 18 , < -2
    djn.i $ -2 , { 58
    spl.f } 47 , { 18
    end 0

    Opponent Scores Results Performance of 1046.red
    -------- ------ ------- ---------=---------=---------=---------=
    Nano'Powa 392 347 112 127 11 ******************
    Black Sun III 359 356 107 108 35 ******************
    8c09fc1a-479925 453 288 93 148 9 ***************
    Chiki Chiki 466 262 80 148 22 *************
    Cosmic Horror 395 308 87 116 47 ****************
    Dodecadence 390 345 110 125 15 ******************
    eerie glow 294 429 134 89 27 **********************
    flight 342 387 122 107 21 ********************
    Foggy Maus (bet 379 364 119 124 7 *******************
    glowing embers 262 442 132 72 46 ***********************
    hemlock 285 405 115 75 60 *********************
    a slice of moon 334 412 136 110 4 *********************
    c82f15b5-85011f 346 403 134 115 1 *********************
    Pacler Deux 371 362 115 118 17 *******************
    Red Moon 373 373 123 123 4 *******************
    ripples in spac 430 304 96 138 16 ****************
    ripples 22 443 293 93 143 14 ***************
    the spiders cre 339 393 125 107 18 ********************
    Staphylococcus 371 368 119 120 11 *******************
    White Moon 391 349 113 127 10 ******************
    1046.red 359 380 123 116 11 ********************
    0614.red 359 380 123 116 11 ********************
    Left Alone 398 344 112 130 8 ******************
    Muddy Mouse (RB 407 335 109 133 8 *****************
    -------- ------ ------- ---------=---------=---------=---------=
    Adjusted Score: 143.8
    
    

    As of today 0614.red is in 38th place with a score of 142.8 and 1046.red is in 46th place with a score of 141.5. We'll see how long that lasts. Another one, 0413.red, is hanging on in 50th place, I don't expect it to last long. 0614.red is from the same soup as 0413.red, just chosen using a more optimised test set. These warriors have been edited to include benchmark scores in the comments, the "nanobm07" score refers to the score against the warriors in nanobm07.zip (from http://corewar.co.uk/nano.htm), the "Koen090112(20)" score is the score against the top 20 warriors from the Koenigstuhl nano hill which is a somewhat better predictor of performance. The test sets used in the performance charts above are a combination of this plus my 2 nano warriors plus 2 other warriors from the SAL nano hill, this set is slightly more accurate but most of the hill contents is not published so it's a guessing game.

    The big question I'd like to answer... does all the fancy stuff like crossover etc really make an evolver better? Or does the increased performance come from other factors such as a larger population size, things that avoid settling into a "local maximum", better weighting of instructions, modifiers, modes and data, and other simple parameters that have nothing to do with esoteric techniques. In a random evolver like REBS I don't know how crossover could be implemented at all, cross with what? there'd have to be some tag which indicates an "attractive" warrior to combine with or the effort would probably be futile. I think the best technique for strengthening code is the method used by Barkley Vowk (bvowk), using "chain" tables based on existing warrior code to modify the odds of what the next instruction should be, at least when creating the initial population of warriors. Maybe crossover does in fact work better, but I'd be very interested in testing the theory with all the other parameters equalized. One possibility is a comment to track how many battles a warrior survives, then when a warrior wins a battle and gets to multiply it can look in its immediate vicinity for the "strongest" warrior to cross with. Something like that could be turned on and off to see if crossover really makes a difference.

    2/7/09 - here is a more detailed algorithm showing how warrior crossover might work...

    DO
    Pick a warrior at random
    Randomly select one of 8 neighbors
    (wrap on the sides but not the top and bottom, like a cylinder)
    If either warrior does not exist create a random warrior
    Battle the warriors and obtain scores
    Increment the win number of the warrior that won
    Examine the surrounding warriors and choose a warrior with the
    highest win number, excluding the warrior that lost and warriors
    not of the same origin (a tag maintained since initial creation)
    (or perhaps the same species, a tag changed whenever the instruction
    sequence changes but that might be too limiting)
    Switch = random 0 or 1
    Skip header comments of both winner and mate, write headers to loser
    DO
    Read one line from both the winner and from the mate
    If Switch = 0 evolve the winner's line to the loser
    If Switch = 1 evolve the mate's line to loser
    If random < switchrate, invert Switch (if 1 make 0 else make 1)
    UNTIL one or the other warriors runs out of instruction lines
    Evolve the end line (from winner or mate depending on Switch)
    Write the end tags (wins=0, change species if any instructions changed)
    UNTIL the evolver is stopped

    ...but don't expect any such thing from REBS, which will likely always remain a simple mutation-only evolver. One reason is because it's a script that uses redirection to feed in a warrior and output an evolved warrior, and only one file can be redirected at a time. That pretty much disallows crossover unless each warrior was read into an array and I'm not getting into all that. Another reason is also because it's a script - bash can do cool things but a general-purpose programming language it is not. REBS began almost as a joke to see if it was possible to create an evolver in a scripting language, I learned a lot about bash and REBS has become my reference script when I can't remember how to do something, but I can't imagine doing anything beyond a trivial algorithm using just bash. Rather, REBS was an experiment to see how trivial an evolver could be.

    2/9/09 - Got up this morning and discovered a particularly strong soup of nanos had evolved on my 701SD, previously I had weakened this soup by playing with the parms so went back to REBS 1.4a0 with stock parms, picked out a few warriors that scored the highest using my Koen090112(20) test set then picked 0535.red to mail to the SAL Nano Hill... 3rd place! Cool, that's progress. As a bonus it boosted 0614.red to 33rd place. I'm going to let that one sit for awhile before I reveal the code, but I think it's evidence that a simple mutation-only evolver can produce strong code without using esoteric techniques, at least for nano-size warriors.

    2/10/09 - RedMixer lives. It's very similar to REBS but is written in QBasic and implements the crossover idea. The crossover operations can work on an item-by-item basis as well as line-by-line switching, and in addition to tracking wins also records average score. Now will try to see if crossover really works.