VERY(!) preliminary docs for BIO.E ---------------------------------- I'm just whipping this up quickly so those of you getting the pre-beta, UUENCODED copy of BIO.E off the list can understand a bit about what the program code is all about. Play with it at your own risk. I'm hardly responsible for my OWN life, much less your playthings. CONSTANTS --------- SOUPSIZE This sets up the size of the huge memory array that all the 'cells' will operate in. Right now it's set to 4000, but play around with it. You can make it as big or small as you like (within compiler and memory constraints). REGISTERS UNUSED. Used to be good for something, but I just haven't removed it from the code yet. STACKSIZE Ditto. MAXATOMS Maximum number of 'cells' allowed to operate in the soup. Now that I have a self-replicating cell, there's a bug related to this that I have yet to fix. Live with it (for now). RADIUS Maximum distance allowed for template searches. Will be explained under the instruction set, where the ADRx and JMPx instructions are explained. MAXTZ Related to the same thing. This is the maximum template size allowed. MAXMUTATE The maximum number of cells to bitflip if a mutation is called for. OBJECTS ------- cell This is the object used to define one address in the soup. Should have substructures documented in the code itself. cpu The object that defines one virtual vpu. AX and BX are address registers, CX and DX are just plain registers, stx are stack locations (10 of 'em), sp is the stack pointer, ip is the instruction pointer, and fl is a flag used to indicate an instruction execute failure. GLOBAL VAR'S ------------ atom Array of cells. Contains all the virtual cpu's. soup Array of memory addresses in the soup. atomcount Counter for keeping track of the number of active cells. largestatom Keeps track of the cell with the longest code-length. howmany Tracks the number of cells with a length=largestatom. births # of new vcpu's allocated to code resulting from self-replication. deaths Tracks how many cells are removed from the soup by the reaper. cellsize Array used to track size in codelength of all cells. atomloc Tracks starting location of every cell. daughterlist Tracks how many cells have allocated a block of memory to use for self-replication, but have not yet told the OS to make that block a seperate cell yet. PROCEDURES ---------- initsoup() Zeros out the soup. initcpu() Does the same for all the vcpu's. initrand() Sets a random Rnd seed. (Tanks to Barry Wills for the code). initpopsoup() Randomly assigns one instruction to each cpu available. This was done because I have a routine that randomly associates cells into bigger cells, in the hopes of EVOLVING self- reproducing code. There's a hack in here that also loads a 22-instruction self-replicating program into the soup. makeancestor() This is the hack for the self-replicator. Here's the entire code for it: nop0 adrb nop1 divide sub_ac movab adrf nop0 inc_a subab mal pushbx nop0 movii dec_c ifz ret inc_a inc_b jmpb nop1 movii I'll document it later. For now, It's an exercise for the reader. It's also straight outta one of Tom Ray's papers, and was not WRITTEN by Ray. It was EVOLVED from a program of codelength 80. displaysoup() Used to display all nonzero contents of the soup when a run is halted using CTRL-C. I moved the code around a bit, and now it's useless, 'cuz it won't tell you the memory address or the owner of the instruction anymore. Suffer. main() Had to have one somewhere, didn't I? mutate(me) me=address to mutate at. Simply randomly bitflips a value at a particular address. Called from main probabilistically. freemem() Computes total amount of soup memory unused by any cell. computesize() Computes the size (in instructions) of all cells and stores it in the cellsize[] array. computeaddress() Finds the starting address of all cells and stores them in atomloc[]. slicer() Controls who executes when. reaper() Kills off the cell with the highest cpu flag value (i.e., the one that fails the most). chooseelements() Randomly chooses two cells and joins them together into a bigger cell, based on some instruction-bonding constraints I came up with. checkbonding(i1, i2) Makes sure the two instructions (i1, i2) are able to be legally joined. (I'll explain the reasoning for this when I release a better version). execute(ce) Allows cell # ce to execute one instruction. storeonstack(ce, value) Used in all POPxx instructions to put a value into the proper stack slot. getfromstack(ce, pointer) Get a value from stack location pointer and return it. INSTRUCTION SET --------------- nop0, nop1 Do notihing instructions. Used as templates for searching. This is an alternative to direct or indirect addressing schemes. not0 If CX is odd, make it even, and vice-versa. shl Shift CX left one bit. zero Zero out CX. ifz If CX is 0, move the IP one instruction up, otherwise move it 2. sub_ab Subtract BX from AX, store in CX. sub_ac Subtract CX from AX, store in AX. inc_x Increment the desired register (AX, BX, CX). dec_c Decrement CX. pushxx Put the value in the register (AX,BX,CX, or DX) onto the stack. popxx Get the value from the stack at the current pointer location and store it in the specified register (AX, BX, CX, or DX). ret Get a value from the stack at the current pointer location, and put it into the IP. movab or movcd Copy the value in the (AX or CX) register into the (BX or DX) register. movii Copy the instruction found at the address stored in BX into the address stored in AX. jmp, jmpb, call, adrf, adr, adrb These instructions look for nop0 or nop1 sequences immediately following them, and then look forward, backward, or both directions in the soup, trying to find the complement of the pattern of nop0s and nop1s it originally looked at. If it is found within a distance of RADIUS, that address is either stored in a register, the stack, or directly assigned to the IP, depending on the instruction. Look at the actual code to see which does what. mal Asks for a block of free memory of the size found in the CX register. If one is not available, the reaper kills off unsuccessful cells until enough room is available. divide Takes a block of memory that was previously mal'ed and assigns a vcpu to it. From then on, this is a new cell. A new cell has been 'born'. findfreecellnum Finds a cell designation from 1 to MAXATOMS that is not currently being used, and passes it to divide for use with the new cell. findfreemem Checks to see if a block of free memory of size s is available. If yes, it returns the starting address, otherwise zero. debug This is currently the only window you have to program operation. Sorry. This will be revised and expanded when I add a GUI, debug it completely, etc. For now, you'll have to live with this and your code-interpretation skills.