Darwinbots Forum
Bots and Simulations => DNA - General => DNA Tools => Topic started by: Gobo on November 16, 2007, 05:15:38 PM
-
Please check it out.
http://ersatz.org/sanger-1.0.zip (http://ersatz.org/sanger-1.0.zip)
Feedback and bug reports are equally welcome. If you notice a bad turn of speech in documentation, please report me as well, since English is not my native language and I can hardly check myself.
NAME
sanger.pl - Darwinbots DNA macro language interpreter
SYNOPSIS
sanger.pl [file]
sanger.pl -e [code]
sanger.pl --help
DESCRIPTION
Sanger is a macro language designed to make conditionless DNA
construction easier. Sanger is named after Frederick Sanger, inventor
of DNA sequencing.
"sanger.pl" is Sanger interpreter which gives classic low-level DNA code
on output. Sanger code may contain macro definitions and file
inclusions. Everything else is interpreted as instructions, I. e. macro
calls and plain DNA code.
MACROS
Macro definition starts with DEFINE and lasts till a semicolon. Macro
names are case-insensitive.
DEFINE NEZ $1 sgn abs;
DEFINE NE NEZ( $1 $2 sub );
Definition of a macro may contain argument references: $1, $2 and so on.
When macro is called, argument references are replaced with arguments.
For instance,
NE( *.myeye, *.refeye )
is interpreted as
*.myeye *.refeye sub sgn abs
FILE INCLUSIONS
File inclusions start with INCLUDE and last till a semicolon, similar to
macros.
INCLUDE filename;
STANDARD LIBRARY
These macros are found within 'stdlib.dna' file going in distribution.
NOT( boolean )
AND( boolean, boolean )
OR( boolean, boolean )
XOR( boolean, boolean )
Boolean operators.
EQZ( integer )
NEZ( integer )
GTZ( integer )
LTZ( integer )
GEZ( integer )
LEZ( integer )
Compare the top value on the stack with zero.
EQ( integer, integer )
NE( integer, integer )
GT( integer, integer )
LT( integer, integer )
GE( integer, integer )
LE( integer, integer )
Compare two integers on the top of the stack.
TEST( boolean, integer )
If the first argument is true, pushes the second argument on the
stack, otherwise pushes zero.
IF( boolean, integer, integer )
If the first argument is true, pushes the second argument on the
stack, otherwise pushes the third.
EXAMPLES
Lionfish's genes are taken for demonstration.
INCLUDE stdlib.dna;
' Venom blinding and strvenom killer exploit
IF( 1 rnd, IF( 1 rnd, .eye5width, .eye5dir ), .strvenom ) .vloc store
' Selective shooting
DEFINE ENEMY NE( *.in1, *.refage );
IF( GT( *.eye5, 60 ),
IF( NEZ( *.refeye ),
TEST( ENEMY(), -3 ),
-6 ),
TEST( GT( *.nrg, 1000 ), -3 ) ) .shoot store
SEE ALSO
Frederick Sanger
<http://en.wikipedia.org/wiki/Frederick_Sanger>
Lionfish's genes explained
<http://www.darwinbots.com/Forum/index.php?showtopic=2169>
AUTHOR
Ivan Fomichev <ifomichev@gmail.com>
COPYRIGHT
Copyright (C) 2007 Ivan Fomichev
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
-
Neat, but you might want to consider changing the names for the "standard library" to be clearer. For instance, EQZ is awefully cryptic if you've never used assembly. And the macro language is supposed to be higher level than the original DNA. Maybe something like EqualsZero or similar.
-
Neat, but you might want to consider changing the names for the "standard library" to be clearer. For instance, EQZ is awefully cryptic if you've never used assembly. And the macro language is supposed to be higher level than the original DNA. Maybe something like EqualsZero or similar.
I thought about that, but preferred clarity to brevity. Actually these names are based rather on Perl operators than assembly. By the way, high level language may have nothing with clarity, e. g. see APL (http://en.wikipedia.org/wiki/APL_(programming_language))
Nevertheless thank you for your notice, I'm likely to add verbose names as aliases in the next revision.
-
I noticed, that IF is not as effective as it might be, when arguments themselves are complex expressions, since $3 is calculated twice. This will be fixed in the next revision.
Originial definition:
DEFINE IF $2 $3 sub $1 mult $3 add;
Revised definition:
DEFINE IF $3 dup $2 sub $1 mult sub;
-
Okay, maybe I am acting like a stupid-head. Well just maybe.
What can I do with this sanger-program???
Give some explanation, becouse I just don't get the full point.
I Just read the first line again.
It says.
Darwinbots DNA macro language interpreter
Does it means it converts DB dna to a higher languege. If so, I don't understand the languege at all.
But you want to make a program or something that codes what you make in DB-dna and can recode back to higher languege. That could be pretty good. Maybe something for a better understandment of evolved bots or something.(their dna is mostly harder to read)
And just to know, what does EQZ exactly mean??(along with the others)
-
What can I do with this sanger-program???
You can write a high level version of DNA that gets compiled into Darwinbots DNA code. I believe one of the more recent bots in the arena, the one that was crazy long, Guardian I think, was written in a macro language like this, and "compiled" into usable code.
As the complexity of a bot increases, it becomes more and more necessary to write in a higher level and compile it into DNA. I doubt, for instance, a person could write DNA that's thousands of bps long. The complexity is just overwhelming.
And just to know, what does EQZ exactly mean??(along with the others)
You need to actually read posts before declaring that they don't make sense.
-
I thought about that, but preferred clarity to brevity. Actually these names are based rather on Perl operators than assembly. By the way, high level language may have nothing with clarity, e. g. see APL (http://en.wikipedia.org/wiki/APL_%28programming_language%29)
Nevertheless thank you for your notice, I'm likely to add verbose names as aliases in the next revision.
Well, it depends on how high level you want to get. Something like Ruby (http://www.ruby-lang.org/en/) is what I consider the "perfect" language. Making programming easy for the programmer is emphasized over implementation difficulty. The result is that it's very intuitive and fun to program in.
By contrast, something like assembly is designed only to be easy for the computer to interpret. Programming ease is not the priority at all. The current DNA language is comparable to assembly, so I'm thinking you should aim for something like ruby. Something totally natural for a coder to work in. You could even go the full nine yards and implement classes, too. Just depends on your goals.
You might want to give this (http://www.darwinbots.com/Forum/index.php?showtopic=2133&hl=guardian) a look. About the 4th or 5th post down Trafalgar shows the code he used for Guardian for his interpreter.
-
You might want to give this (http://www.darwinbots.com/Forum/index.php?showtopic=2133&hl=guardian) a look. About the 4th or 5th post down Trafalgar shows the code he used for Guardian for his interpreter.
Hmmm... It seems I have reinvented a bike
Is Guardian's interpreter's code available?
-
I don't think he ever released it, but he'd probably share if you could reach him.
-
I don't think he ever released it, but he'd probably share if you could reach him.
I think I dropped him a personal message, but it didn't show up in "Sent Items". Is it ok?
-
And just to know, what does EQZ exactly mean??(along with the others)
You need to actually read posts before declaring that they don't make sense.
When did I declare they don't make sense?
What made you think I didn't red any posts?
EQZ( integer )
NEZ( integer )
GTZ( integer )
LTZ( integer )
GEZ( integer )
LEZ( integer )
Compare the top value on the stack with zero.
I see compare the top value on the stack with zero. Everyone?, I don't think they all do desame so what do they do.
I don't think he ever released it, but he'd probably share if you could reach him.
I think I dropped him a personal message, but it didn't show up in "Sent Items". Is it ok?
Yes, it is.
-
EQZ( integer )
NEZ( integer )
GTZ( integer )
LTZ( integer )
GEZ( integer )
LEZ( integer )
Compare the top value on the stack with zero.
I see compare the top value on the stack with zero. Everyone?, I don't think they all do desame so what do they do.
EQZ - equal to zero
NEZ - not equal to zero
GTZ - greater than zero
LTZ - less than zero
GEZ - greater or equal to zero
LEZ - less or equal to zero
If you glanced in 'stdlib.dna', you could easily figure that by yourself.
-
You might want to give this (http://www.darwinbots.com/Forum/index.php?showtopic=2133&hl=guardian) a look. About the 4th or 5th post down Trafalgar shows the code he used for Guardian for his interpreter.
I looked into it more thoroughly. Trafalgar's interpreter has a prettier syntax, but it seems it lacks at least two prominent features Sanger has.
First, there are no macros with arguments. So Trafalgar's interpreter's language seems to me less extensible, than Sanger.
Second, there is no branching with "else" case (compare to IF macro in Sanger). As the result, I expect DNA code produced with Trafalgar's interpreter's language be much more verbose than Sanger's, since the same conditions repeat in compiled code excessively.
-
By contrast, something like assembly is designed only to be easy for the computer to interpret. Programming ease is not the priority at all. The current DNA language is comparable to assembly, so I'm thinking you should aim for something like ruby. Something totally natural for a coder to work in.
I have trifled Parse::Eyapp (http://search.cpan.org/perldoc?Parse::Eyapp) and I think I can manage a prettier syntax. Sample code for the same Lionfish's genes follows.
include "stdlib.dna";
.vloc = rnd(1) ? .strvenom : rnd(1) ? .eye5width : .eye5dir;
function isEnemy() { *.in1 != *.refage }
if ( *.eye5 > 60 ) {
if ( *.refeye != 0 ) {
if ( isEnemy() ) .shoot = -3;
}
else .shoot = -6;
}
else if ( *.nrg > 1000 ) .shoot = -3;
I suppose to embed plain DNA with backticks and have named arguments for "functions". The following example is contrived, since notEquals is built-in "!=", and notEqualsZero is thought to be used within as an optimization of "a != 0".
function notEqualsZero(a) { a, `abs sgn`; }
function notEquals(a, b) { notEqualsZero( a - b ); }
Please make your notices before I begin developing, because it is much easier to change code before it has been written
-
I have written pre-alpha Sanger with new syntax. This is not yet documented, though is quite intuitive.
You can download it from http://ersatz.org/sanger-1.999.tar.gz (http://ersatz.org/sanger-1.999.tar.gz) or try it online at http://ersatz.org/sanger.html (http://ersatz.org/sanger.html). By default the form contains the source of Animal Minimalis in Sanger.
Just few notices.- There is a ternary conditional assignment operator: EXPR1 ?? EXPR2 = EXPR3. It means: assign EXPR3 to EXPR1 if EXPR2 is true. EXPR2 may contain a special word this (but just once), which refers to EXPR3. E. g.
.aimsx ?? this = ( *.eye9 && -40 ) + ( *.eye8 && -30 ) + ( *.eye7 && -20 ) +
( *.eye6 && -10 ) + ( *.eye4 && 10 ) + ( *.eye3 && 20 ) +
( *.eye2 && 30 ) + ( *.eye1 && 40 );
.eye5width ?? ( this != *.eye5width ) = ( rnd(4) == 0 ? 900 : 0 );
- You can define macros with -> operator. For now, they cannot be inside genes. They may have arguments, separated with comma.
friendly() -> *.refeye == *.myeye;
chance( n ) -> rnd( n ) == 0;
- Custom variables are defined with similar syntax.
kinfactor -> 971;
- For now, there is only syntax for conditionless genes.
always {
...
}
- You may have expressions on the left side, too.
*.eye5 > 50 && !friendly() && .shoot = -1;
- Logical operators || and && have the same return value as in Perl. It means that
5 || 3 == 5
0 || 2 == 2
3 && 5 == 5
0 && 2 == 0
-
Very nice. I think the ternary operator is a little non intuitive, but I come from a C background, so maybe it's based on something in Perl? I don't know how hard it would be, but something like:
if A && B || C then ... else ...
would mirror the DNA's structure and be more intuitive.
Also, I'm unfamiliar with Perl's && || operators. Others probably are too. Could you explain what they do?
-
Well yes what do they, and will this be backward compatible. Dna->sanger
-
Very nice. I think the ternary operator is a little non intuitive, but I come from a C background, so maybe it's based on something in Perl? I don't know how hard it would be, but something like:
if A && B || C then ... else ...
would mirror the DNA's structure and be more intuitive.
Also, I'm unfamiliar with Perl's && || operators. Others probably are too. Could you explain what they do?
I'm going to introduce if later with the following syntax:
if ( ... ) {
...
}
else {
...
}
But there are some difficulties in implementation:- Assigning to a variable in then and else which is used in the condition. This includes assigning to an expression, since expression may evaluate to an address of the variable used in the condition. Evaluation of the variable's address at compile time may be a complex task. Sometimes expression cannot be evaluated at the compile time at all (e. g. rnd(1000) ).
- Using rnd(...) in the condition.
Perhaps I'll just forbid- using rnd() in condition expression
- using variables modified inside then and else clauses in condition expression
- assigning to expressions inside then and else
Naturally if is already implemented, all I need to implement those checks, that is quite a bore.
Ternary conditional assignment operator is not met in Perl, though you can say in Perl:
$a = 1 if $b == 0;
Perhaps it is prettier, isn't it? I still can change to this syntax without much effort. What do you think?
&& and || work in Perl and Sanger as follows:- a && b equals a if a is false (== 0 in Sanger's case), b otherwise (no matter if b is true or false)
- a || b equals a if a is true (!= 0 in Sanger's case), b otherwise (no matter if b is true or false)
Since it is so, you may do conditional assignment an extra way:
*.nrg > 20000 && .repro = 10;
which is basically the same as
.repro ?? *.nrg > 20000 = 10;
But ternary conditional operator has an additional possibility to use this in condition. It refers to the value of the expression you assign. It is implemented with dup assembly operator.
Well yes what do they, and will this be backward compatible. Dna->sanger
Though I don't understand what you mean by 'backward compatible', I can assure you it won't make trouble. Sanger tracks boolean and integer contexts and modifies integer values met in boolean context accordingly (with sgn abs).
-
Well yes what do they, and will this be backward compatible. Dna->sanger
Though I don't understand what you mean by 'backward compatible', I can assure you it won't make trouble. Sanger tracks boolean and integer contexts and modifies integer values met in boolean context accordingly (with sgn abs).
Ok, what I mean.
With sanger you do.
sangercode--->DB-dna
Can you also do
DB-dna--->sangercode
So having normal dna and with it making sanger.
Edit: I know at this very moment it isn't possible, but is it going to be.
-
With sanger you do.
sangercode--->DB-dna
Can you also do
DB-dna--->sangercode
So having normal dna and with it making sanger.
Edit: I know at this very moment it isn't possible, but is it going to be.
"Decompiling" is just another task. You cannot just take any DNA code and transform it into Sanger, since DNA code produced with Sanger is just a subset of all possible DNA code. I'm planning to write a tool, which would deobfuscate DNA code a little bit. But at the moment, I cannot advance because I don't understand how cond-start-else work exactly. I need to experiment with those.
-
"Decompiling" is just another task. You cannot just take any DNA code and transform it into Sanger, since DNA code produced with Sanger is just a subset of all possible DNA code. I'm planning to write a tool, which would deobfuscate DNA code a little bit. But at the moment, I cannot advance because I don't understand how cond-start-else work exactly. I need to experiment with those.
Yes, decompiling is the word. I thought that you made with your program normal animal minimalis dna, but you make SGinised animal minimalis dna.
And, yes there are different kinds of programming. Could be nice to see animal minimalis being changed ito his SGinised version this way.
But further you say this is pre-alpha, is it already possible to make all kinds of bots or was this just an example. I could maybe try and see, but I have a little difficulty to understand it all.
I don't know much different programing-langues so that could also be me. If there is a manuel maybe I am taking a look. Undocumated it will probably too hard.
-
Classic animal minimalis with conditional genes will look like the following:
friendly() -> *.refeye == *.myeye;
/* Food Finder */
when ( *.eye5 > 0 && !friendly() ) {
.dx = *.refveldx;
.up = *.refvelup + 30;
}
/* Eat Food */
when ( *.eye5 > 50 && !friendly() ) {
.shoot = -1;
.up = *.refvelup;
}
/* Avoiding Family */
when ( *.eye5 == 0 || friendly() ) {
.aimdx = rnd(314);
}
/* Reproduce */
when ( *.nrg > 20000 ) {
.repro = 10;
}
Here I changed familiar if-else syntax to when-otherwise in order to explicitly differentiate between if-else that will encounter inside genes due to limitations in if-else constructs described above (when-otherwise construct won't have these limitations naturally). But if community decides it is not essential, I may use the same syntax for both (what do you say?).
It is called pre-alpha because syntax is subject to change (e. g. I'm now inclined to change ... ?? ... = ... syntax in favor of ... = ... if ...), documentation is not yet here, and there may be some several bugs, since it was not thoroughly tested. Also I'd like to introduce if-else construct in alpha. Though it is quite functional. You can write in anything you want, not just Animal Minimalis, for sure
-
A DNA deobfuscater (sp? ) would be very helpful, too. Though considering how insane DNA can get it's not an easy task. The simplest would be to backtrack from all the store, inc, or dec operators and remove and "junk" dna that doesn't effect the final result. Some sort of DNA stripper.
I don't mind the when...otherwise thing. Makes the language have character
The ternary operator in C (which is what I'm used to) operates like this:
a ? b : c, which is the same as:
if a then b else c. So if your ternary operator is significantly different from that form, there's some unlearning that needs to be done by people like me. And Perl's && and || syntax seem a little alien to me, though you explained it very well. I might need to do some quick research.
With the new changes to conditions, it actually simplifies a lot of the DNA. You can totally get rid of cond blocks and just have a long start statement. I might write up a new version of animal minimalis in another thread as a demonstration. I think it should make some of what you're doing easier, too.
-
I second the call that an evolved DNA deobfuscator would be very useful. Building a complete one is harder than it sounds though. I been thinking of doing it in the simulator since by doing so, I could leverage the actual DNA execution logic which of course knows which things to ignore and which not to but the problem is that it doesn't know that at the moment the instruction pointer is on the base pair. It only knows down the road, when the boolean stack is cleared by a cond for example etc. as to whether boolena values pushed on the boolean stack got used. It can't make a real time decision as to whether removing a BP will impact the logic.
A few things are easy. Removing all non-coding DNA for example. But doing a complete job is a non-trivial task.
Oh, and Sanger looks cool. When I get two minutes to rub together I'll dive in.
-
Sanger 2.0 (alpha) is released!
http://www.ersatz.org/sanger-2.0.zip (http://www.ersatz.org/sanger-2.0.zip) - source
http://www.ersatz.org/sanger.html (http://www.ersatz.org/sanger.html) - online
-
Does it allow nested conditions? Animal Minimalis's second gene is collapsable in to the first if you nest it. I tried doing it myself, and it didn't yell at me and seemed to compile, but I'm too lazy to double check it to see if it did it right.
-
Also, you don't need to start the DNA with a cond. You can just have a start statement, because an empty bool stack is assumed to be true, so a start statement will run without a cond. Second, you don't need a stop statement. Once the end of the DNA is reached, a stop and end command are assumed.
Also, it would be nice if the compiled DNA result was formatted a little better. It gave me this for my Animal Minimals tweak:
cond
start
*.eye5 0 > *.refeye *.myeye != and *.refveldx .dx store
*.refvelup 30 add .up store
*.eye5 50 > -1 .shoot store
*.refvelup .up store true or and true or and
*.eye5 0 = *.refeye *.myeye = or 314 rnd .aimdx store true or and
*.nrg 20000 > 10 .repro store true or and
stop
Where something like this would look better:
start
*.eye5 0 >
*.refeye *.myeye != and
*.refveldx .dx store
*.refvelup 30 add .up store
*.eye5 50 >
-1 .shoot store
*.refvelup .up store
true or and true or and
*.eye5 0 =
*.refeye *.myeye = or
314 rnd .aimdx store
true or and
*.nrg 20000 >
10 .repro store
-
Yes, surely it's collapsable. You can do arbitrary deep nested ifs. I just wanted to save the whole logic of Animal Minimalis to have a better analogy.
friendly() -> *.refeye == *.myeye;
always {
/* Food Finder + Eat Food + Avoiding Family */
if ( *.eye5 > 0 && !friendly() ) {
.dx = *.refveldx;
if ( *.eye5 > 50 ) {
.shoot = -1;
.up = *.refvelup;
}
else {
.up = *.refvelup + 30;
}
}
else .aimdx = rnd(314);
/* Reproduce */
if ( *.nrg > 20000 ) .repro = 10;
}
Formatting is in the queue. It's not of the first priority, I hope you agree.
Perhaps I will remove cond from definition of always gene. But stop is better to stay, imho, because there may be more than one gene, and it's not a great deal to save a single command in the special case of the last gene.
-
Yes, surely it's collapsable. You can do arbitrary deep nested ifs.
Will it handle changes to the condition or integer stack? That is, if I do:
if (false) {
10
} else {
20 store
}
Will it store 10 to 20 or not? It's not supposed to, though this is a rather pathological example.
Perhaps I will remove cond from definition of always gene. But stop is better to stay, imho, because there may be more than one gene, and it's not a great deal to save a single command in the special case of the last gene.
True.
-
You cannot operate stacks directly with Sanger 2.0 (at least, at the moment). You must store a value into the memory. Otherwise there would be much confusion, because the integer stack is used for expressions evaluation.
Though 'if (false)' shall work right (it doesn't, because I forgot to define true and false )
-
Three things:
First, I can't run it (the script exits with the error 'Can't call method "s" on unblessed reference at sanger.pl line 56.') I'm running Gentoo Linux, perl version 5.8.8-r4 with ithreads enabled. I run the online interpreter instead.
Second, could you modify it so that it uses the new "dropbool" command instead of "true or and"? "dropbool" is much simpler
Third, nested if's don't work:
always {
if ( 1 == 0 ) {
if ( 1 == 1 ) {
.aimdx = 100;
}
.aimdx = -100;
}
}
results in (formatting added)
start
1 0 =
1 1 =
100 .aimdx store
true or and
-100 .aimdx store
true or and
stop
when it should result in
start
1 0 =
1 1 = and
100 .aimdx store
dropbool
1 0 =
-100 .aimdx store
dropbool
stop
-
I think it was made before dropbool was added, so that's why. Gobo's AWOL, so if you know how to make changes to what he has, please do!
-
He's AWOL? Oh well. Wait, so am I! I'll just refer to him as 'you' anyways in this post.
Yes, surely it's collapsable. You can do arbitrary deep nested ifs. I just wanted to save the whole logic of Animal Minimalis to have a better analogy.
I'm curious how you got that to work (or if bugfixes or changes to DarwinBots fixed what was preventing mine from working). I actually had nested if/elseif/elseif/else etc supported in PyBot (which is what I called my bot compiler thing), but the generated code didn't work because of a DarwinBots bug. This might have been it: http://www.darwinbots.com/Forum/index.php?showtopic=2132 (http://www.darwinbots.com/Forum/index.php?showtopic=2132)
I just tried looking at the code I had written for the if/elif/etc and branching stuff, but I couldn't read the DarwinBots code it outputs anymore (I've forgotten what all the symbols do).
Perhaps when I get more time I'll see about posting it, and look at yours, but at the moment I'm a bit too busy.
(The main reasons I didn't post it before going AWOL, IIRC, were:
1. I hadn't written any documentation about how to use it, or any documentation for it at all really.
2. I thought that releasing it might be a bad idea, since it might lead to many more super-long-DNA but super-energy-efficient bots, slowing league matches way down.
3. I wanted branching conditionals to be supported by it, but was waiting for a version which fixed the bug that was making them not work.
)
You're right that it didn't have passable parameters for functions and such, of course.
IIRC I went AWOL after:
1. I evolved (from a zerobot) a bot with an actual conditional (It looked extremely unlikely to me to be possible to evolve anything more advanced from it), and
2. I made a bot which beat the entire F1 league, and was encouraged to have it be in the F2 league too even though it used a tactic that I thought should be nerfed, but the league tables never got updated (at least not before I went AWOL).
So I kinda felt like I had reached the top of the mountain, and went off to find something else to do.
-
So I kinda felt like I had reached the top of the mountain, and went off to find something else to do.
The mountain's been growing pretty quickly recently
-
I think it was made before dropbool was added, so that's why. Gobo's AWOL, so if you know how to make changes to what he has, please do!
Hi, I think I know what should be done. After Eric had introduced more operations on boolean stack, conditionals became much easier. Though I'll need some time to remember the code :-)