Little Corewar Evolver
======================

This program evolves warriors for the game of Corewar.
Included files...

LCE8qb.bas - QBasic-compatible program code
LCE8.bas - FreeBasic-compatible source code
LCE8.ini - settings file
LCE8.txt - docs

Read LCE8.txt for instructions (the FreeBasic conversion is already done).

This program is supplied as-is and without warranty.
This program is free public domain, do whatever you want with it.
Rewriting "properly" would be a good start... the present code is written
in a very compacted mannor for rapid development (and for code art - my way).

For reference here's a psuedocode listing of what the code does:
(not exact, leaves out some specifics like strings, might contain mistakes)

----------------------------------------------------------------------------
  Set default parameters...
    SoupSize - how many warriors in the soup
    MaxLen - maximum evolved size of a warrior
    Range - maximum soup distance for battle pairs
    Hint - true to begin initial warriors with SPL, false for all random
    Coresize - size of core for choosing big numbers
    pmars command line - passed to the OS to run warrior battles
    instruction string and count - base instructions
    modifier string and count - instruction modifiers
    mode string and count - address mode symbols
    insert chance - chance of inserting a random or duplicate line
    delete chance - chance of deleting a line
    instruction chance - chance of changing the instruction
    nodifier chance - chance of changing the modifier
    address chance - chance of changing an A or B address mode
    data chance - chance of randomly changing a A or B value
    incdec chance - chance of incrementing or decrementing an A or B value
    dup line chance - if line insert, chance of being a duplicate line
    small number chance - if random data, chance of choosing a small offset
  Randomize the random number generator using the system timer as a seed
  If the INI file exists Then
    Read replacement parameters from the INI file
    If modifier string = "88" Then
      modifier string = "   "
      modifier count = 1
      88mode = true
    If SoupSize>5000 Or MaxLen>500 Or Left(pmars,2) <> "pm" Then exit program
  gridoffset = INT(SquareRoot(SoupSize))
  temploops = INT((Sine(system timer) + 2) * 100)
  Call Rnd temploops times to further randomize the random number generator
  If warrior 1.red doesn't exist create a random soup...
    For warrior = 1 to SoupSize
      Open Str(warrior)+".red" for output
      Write ";assert 1" to output file
      If hint Then write "spl    $    0,$    0" to output file
      Number of lines = INT(Rnd * MaxLen + 1)
      If hint Then Start line = 2 Else Start line = 1
      For line = Start line to Number of lines (only if more lines to add)
        Call Random line sub
        Write redcode line to output file
      Next line
      Close file
    Next warrior
  Loop
    warrior1number = INT(Rnd * SoupSize + 1)
    If Range > 0 Then (ring topology)
      warrior2offset = INT(Rnd * Range + 1)
      If Rnd < .5 Then
        warrior2number = warrior1number + warrior2offset
      Else
        warrior2number = warrior1number - warrior2offset
    Else (select by grid topology)
      Loop
        warrior2number = warrior1number + INT(Rnd * 3 - 1)
        warrior2number = warrior2number + INT(Rnd * 3 - 1) * gridoffset
      Keep looping until warrior2number <> warrior1number
    warrior2number = warrior2number MOD SoupSize
    If warrior2number < 1 Then warrior2number = warrior2number + SoupSize
    Print warrior1number " vs " warrior2number (tab) (no crlf)
    warrior1 = Str(warrior1number)+".red"
    warrior2 = Str(warrior2number)+".red"
    Battle warrior1 and warrior2 in pmars writing to temp file
    Open temp file for input
    Read line from input file
    score1 = value of text after "scores " in line
    Read line from input file
    score2 = value of text after "scores " in line
    Close file
    Print score1 " " score2 (tab) (no crlf)
    If score1 > score2 Then
      source = warrior1
      destination = warrior2
    Else
      source = warrior2
      destination = warrior1
    Print source " --> " destination (crlf)
    Open source for input
    Open destination for output
    Read first line from input and write to output
    Length = 0
    Loop
      Read redcode line from input file
      Saved line = redcode line
      If Rnd < delete chance Then
        If not end-of-file Then
          read redcode line from input file
          Saved line = redcode line
      If Rnd < insert chance Then
        Save redcode line
        Call write sub (randomizes redcode line)
        If Rnd < dup line chance Then restore redcode line
      If Rnd < instruction chance Then
        Replace instruction with a random instruction from instruction string
      If Rnd < modifier chance Then
        Replace modifier with a random modifier from modifier string
      If Rnd < address chance Then
        Replace A mode with a random mode from mode string
      If Rnd < data chance Then
        If Rnd < small number chance Then
          Replace A data with INT(Rnd * MaxLen * 2 - MaxLen)
        Else
          Replace A data with INT(Rnd * Coresize)
      If Rnd < incdec chance Then
        If Rnd < .5 Then
          A data = A data + 1
        Else
          A data = A data - 1
      If Rnd < address chance Then
        Replace B mode with a random mode from mode string
      If Rnd < data chance Then
        If Rnd < small number chance Then
          Replace B data with INT(Rnd * MaxLen * 2 - MaxLen)
        Else
          Replace B data with INT(Rnd * Coresize)
      If Rnd < incdec chance Then
        If Rnd < .5 Then
          B data = B data + 1
        Else
          B data = B data - 1
      If 88mode Then
         Call Check88 sub
         If Bad88 Then redcodeline = Saved line
      Call write sub
    Keep looping until end of input file is reached
    Close files
  Keep looping until a key is pressed
  Exit program

  Write sub:
    If Length < MaxLen Then
      Write redcode line to output file
      Length = Length + 1
    Call Random line sub (actually just drops through to it)
  Return

  Random line sub:
    Loop
      Randomly pick an instruction from the instruction string
      Randomly pick a modifier from the modifier string
      Randomly pick an address mode for the A field from the mode string
      If Rnd < small number chance Then
        A data = INT(Rnd * MaxLen * 2 - MaxLen)
      Else
        A data = INT(Rnd * Coresize)
      Randomly pick an address mode for the B field from the mode string
      If Rnd < small number chance Then
        B data = INT(Rnd * MaxLen * 2 - MaxLen)
      Else
        B data = INT(Rnd * Coresize)
      Call Check88 sub
    Keep looping while Bad88 = true
  Return

  Check88 sub:
    Bad88 = false
    If 88mode Then
      preInstr = first two chars of redcode line
      Amode = character that's A-mode of redcode line
      Bmode = character that's B-mode of redcode line
      jumpinstr = false
      If preInstr = "jm" Or
         preInstr = "dj" Or
         preInstr = "sp" Then
            jumpinstr = true
      If (jumpinstr And Amode = "#") Or
         (jumpinstr = false And Bmode = "#") Or
         ((Amode = "@" Or Amode = "$" Or
           Bmode = "@" Or Bmode = "$") And preinstr = "da") Or
         (Bmode = "#" And (preInstr = "cm" Or preInstr = "sl")) Then
            Bad88=true
  Return
----------------------------------------------------------------------------

Example output...

;assert 1
spl.b  # 3860,$    3
spl.i  $ 2342,*  -20
mov.i  >   -6,}   -1
djn.i  }  953,@ 3886
djn.a  { 1876,<   -7
djn.ba @    6,*  -10

----------------------------------------------------------------------------
Terry Newton (wtn90125@yahoo.com)

