Redcode Evolver Bash Script
REBS is a GNU/Linux bash script that uses pmars to evolve warriors for corewar.
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. For now the number of lines is not self-adjusting, generally make status line 3 more than ylines to avoid printing it in the middle of the soup. If xsize is small then columns are displayed, width is automatic. Subject to change... for the moment this allows ok flexibility with minimal code.
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)





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.