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.