TEV0 Mods

The TEV0 program is an expression of minimalism, and does not waste code on unnecessary things like eliminating warning messages and providing a user interface. However it's quite easy to add a few bits of code to make it run more smoothly, one of the nice things about minimal evolvers is they have lots of room for customizing. First things first - it runs almost as-is under the Blassic interpreter which is smoother than GWBASIC, doesn't output a linefeed for every shell making nicer status displays possible, and permits using more memory for larger soups (not so important with TEV but quite handy for unguided evolvers which need a big soup to be effective). To run TEV0.BAS in Blassic just get the blassic.exe binary and put in the current or a path directory and modify the batch file to run blassic instead of gwbasic.

Blassic permits running TEV-like code practically unchanged under Linux, simply change the "copy w.evo best.war" string to the Linux equivalent of "cp w.evo best.war" and run using a shell script that does what the batch does...

#!/bin/bash
cd `dirname $0`
ls -1 *.red > w.evo
echo END >> w.evo
xterm -e blassic tev.bas

...save as something like "run_tev.sh" and edit if TEV isn't saved as tev.bas or you want to use a different terminal. If new to scripting - right-click the script and set properties to permit executing - and don't use spaces in file or directory names, the above script won't work if you do that. Also make sure the .red matches the extension of the bench warriors - Linux is case-sensitive.

Note - Blassic does not support TIMER as in RANDOMIZE TIMER, however just RANDOMIZE works fine so if running under Blassic comment out the TIMER part.

The TEV0 program is sensitive to the order of the benchmark warriors. With the original batch for running it the bench warriors are read in from oldest to newest, the Linux script for running it reads the bench warriors in alphabetical order. It might help to put the weaker warriors first so the program doesn't give up too early on a strong warrior that performs poorly against the first few warriors [not precisely sure how this works, something to experiment with].

Mods... these are for the TEV0 version. Line numbers etc may vary with other versions, and note that the following information is subject to change or be removed should other versions of TEV appear.

To get rid of the warning messages about missing assert change line 120 to this...

120 OPEN "w.evo" FOR OUTPUT AS #1:PRINT #1,";assert 1":FOR I=1 TO L

For smoother display and exiting (especially under Blassic) add a line before the main loop...

59 PRINT "Evolving. Press q to quit."

...change line 230 to GOTO 290 instead of 60, remove the GOTO 60 from line 250, and add the line...

290 IF INKEY$<>"q" THEN 60

That's better (but bigger but this is now about using, not being the smallest - the evolution engine in TEV0 is fairly powerful despite its tiny size). Occasionally it still outputs no instructions warnings, to get rid of these remove the comment instruction from line 20, and do experiment with different weightings by including duplicate instructions, for example an extra mov.i or two along with maybe an extra spl.b or spl.x. Sometimes I use extra $ address modes as well.

A nice thing about TEV is it does the benchmarking internally so best.war will always be the strongest warrior, mostly eliminating having to bench a whole soup. Just occasionally copy best.war to best1.war (in case it gets overwritten with a better best while benchmarking but that probably doesn't matter) and use a bench program to see what you have. Or... it might be convenient to just write the internal bench score to best.war then it can just be periodically viewed to check progress. To do this change line 190 and add a few lines...

190 S(1)=100*S(1)/(W*R):IF S(1)<=H THEN 200 ELSE H=S(1)
191 OPEN "w.evo" FOR INPUT AS #1:OPEN "best.war" FOR OUTPUT AS #2
192 WHILE NOT EOF(1):LINE INPUT #1,Z$:PRINT #2,Z$:WEND
195 PRINT #2,";score ";H:CLOSE #1:CLOSE #2

This also gets rid of the OS-specific shell command while providing a way to add more info if desired. A useful addition is a print to indicate the current best score...

197 PRINT "Score ";H

The minimalized TEV0 provides no way to stop then restart the program, or examine what's going on in the soup. Sometimes some of the soup warriors might score better against other benchmarks so for finding a hill-topper that can be helpful. Here's one way that can be done, adds to the other mods...

55 GOSUB 400
. . .
300 INPUT "Save soup (y/n) ",Z$:IF Z$<>"y" THEN 370
310 PRINT "Saving...":FOR J=1 TO P:W$="soup\"+MID$(STR$(-J),2)+".red"
320 OPEN W$ FOR OUTPUT AS #1:PRINT #1,";assert 1":FOR I=1 TO L
330 PRINT #1,RIGHT$(" "+A$(I,J),5);" ";B$(I,J);
340 PRINT #1,RIGHT$(" "+STR$(C(I,J)),5);",";D$(I,J);
350 PRINT #1,RIGHT$(" "+STR$(E(I,J)),5):NEXT I
360 PRINT #1,";score ";S(J):CLOSE #1:NEXT J
370 SYSTEM
400 INPUT "Load soup (y/n) ",Z$:IF Z$<>"y" THEN RETURN
410 PRINT "Loading...":FOR J=1 TO P:W$="soup\"+MID$(STR$(-J),2)+".red"
420 OPEN W$ FOR INPUT AS #1:INPUT #1,Z$:FOR I=1 TO L:LINE INPUT #1,Z$
430 A$(I,J)=LEFT$(Z$,5):B$(I,J)=MID$(Z$,8,1):C(I,J)=VAL(MID$(Z$,9,5))
440 D$(I,J)=MID$(Z$,15,1):E(I,J)=VAL(MID$(Z$,16)):NEXT I:INPUT #1,Z$
450 S(J)=VAL(MID$(Z$,8)):CLOSE #1:NEXT J:RETURN

For Linux change the "\" characters in lines 310 and 410 to "/" instead. The soup directory must be created before saving a soup, don't try to load a soup that doesn't exist, and the L and P parameters must match the saved soup.

OK, now let's do something about the weighting... change line 20 to something like...

20 O$="mov.imov.ispl.bspl.xdjn.f":M$="<@>{*}$$$#":U=2.5

(added a new setting U to control how small numbers are) now add ^W after each RND in the RND-RND expressions in lines 60 and 70 - for neatness the first IF RND... expression can be moved to line 65. Note that in the program the new value is added to the existing value so this has an effect of providing bias to small numbers as well as bias towards making smaller +/- adjustments to the existing value.

Here's my present hacked-up version (this is a Linux version - adjust lines 310 and 410 for Dos/Windows), subject to change...

1 REM an extended version of John Metcalf's TEV0 evolver
2 REM hacks by WTN 6/18/09 - codename TEV0-WB
10 P$="pmars -s 80 -p 80 -c 800 -l 5 -b -k -P":R=142:L=5:P=50:K=80
20 O$="mov.imov.ispl.bspl.xdjn.f":M$="<@>{*}$$$#":U=1.5
30 DIM W$(500),A$(L,P),B$(L,P),C(L,P),D$(L,P),E(L,P),S(P):RANDOMIZE 'TIMER
40 W=0:OPEN "w.evo" FOR INPUT AS #1:M=LEN(M$):H=80
50 INPUT #1,W$(W+1):IF W$(W+1)<>"END" THEN W=W+1:GOTO 50 ELSE CLOSE #1
55 GOSUB 400
59 PRINT "Evolving. Press q to quit."
60 FOR I=1 TO L
65 IF RND*S(1)/H<.6/L THEN C(I,1)=(C(I,1)+INT((RND^U-RND^U)*K))MOD K
70 IF RND*S(1)/H<.7/L THEN E(I,1)=(E(I,1)+INT((RND^U-RND^U)*K))MOD K
80 IF RND*S(1)/H<.3/L THEN B$(I,1)=MID$(M$,INT(RND*M)+1,1)
90 IF RND*S(1)/H<.4/L THEN D$(I,1)=MID$(M$,INT(RND*M)+1,1)
100 IF RND*S(1)/H<.3/L THEN A$(I,1)=MID$(O$,INT(RND*LEN(O$)/5)*5+1,5)
110 NEXT I
120 OPEN "w.evo" FOR OUTPUT AS #1:PRINT #1,";assert 1":FOR I=1 TO L
130 PRINT #1,A$(I,1)+" "+B$(I,1);C(I,1);","+D$(I,1);E(I,1):NEXT I:CLOSE #1
140 S(1)=0:FOR I=1 TO W:SHELL P$+" w.evo "+W$(I)+" >s.evo"
150 OPEN "s.evo" FOR INPUT AS #1:INPUT #1,Z$:CLOSE #1:Z=1
160 IF MID$(Z$,Z,1)<>" " THEN Z=Z+1:GOTO 160
170 S(1)=S(1)+3*VAL(LEFT$(Z$,Z))+VAL(RIGHT$(Z$,LEN(Z$)-Z))
180 IF I>W/5 AND S(1)*150/H<I*R THEN 240 ELSE NEXT I
190 S(1)=100*S(1)/(W*R):IF S(1)<=H THEN 200 ELSE H=S(1)
191 OPEN "w.evo" FOR INPUT AS #1:OPEN "best.war" FOR OUTPUT AS #2
192 WHILE NOT EOF(1):LINE INPUT #1,Z$:PRINT #2,Z$:WEND
195 PRINT #2,";score ";H:CLOSE #1:CLOSE #2
197 PRINT "Score ";H
200 FOR J=2 TO P:IF S(J)>S(1) THEN NEXT J:GOTO 230
210 FOR I=1 TO L:A$(I,J)=A$(I,1):B$(I,J)=B$(I,1):C(I,J)=C(I,1)
220 D$(I,J)=D$(I,1):E(I,J)=E(I,1):NEXT I:S(J)=S(1)
230 IF S(1)>H*.9 THEN 290
240 Z=INT(RND*(P-1))+2:FOR I=1 TO L:A$(I,1)=A$(I,Z):B$(I,1)=B$(I,Z)
250 C(I,1)=C(I,Z):D$(I,1)=D$(I,Z):E(I,1)=E(I,Z):NEXT I:S(1)=S(Z)
290 IF INKEY$<>"q" THEN 60
300 INPUT "Save soup (y/n) ",Z$:IF Z$<>"y" THEN 370
310 PRINT "Saving...":FOR J=1 TO P:W$="soup/"+MID$(STR$(-J),2)+".red"
320 OPEN W$ FOR OUTPUT AS #1:PRINT #1,";assert 1":FOR I=1 TO L
330 PRINT #1,RIGHT$(" "+A$(I,J),5);" ";B$(I,J);
340 PRINT #1,RIGHT$(" "+STR$(C(I,J)),5);",";D$(I,J);
350 PRINT #1,RIGHT$(" "+STR$(E(I,J)),5):NEXT I
360 PRINT #1,";score ";S(J):CLOSE #1:NEXT J
370 SYSTEM
400 INPUT "Load soup (y/n) ",Z$:IF Z$<>"y" THEN RETURN
410 PRINT "Loading...":FOR J=1 TO P:W$="soup/"+MID$(STR$(-J),2)+".red"
420 OPEN W$ FOR INPUT AS #1:INPUT #1,Z$:FOR I=1 TO L:LINE INPUT #1,Z$
430 A$(I,J)=LEFT$(Z$,5):B$(I,J)=MID$(Z$,8,1):C(I,J)=VAL(MID$(Z$,9,5))
440 D$(I,J)=MID$(Z$,15,1):E(I,J)=VAL(MID$(Z$,16)):NEXT I:INPUT #1,Z$
450 S(J)=VAL(MID$(Z$,8)):CLOSE #1:NEXT J:RETURN

Other kinds of mods are possible, but for the most part I stuck with the stock evolving code and just added stuff around it to help explore the bench-driven evolution technique employed by TEV0.