⏰⏰⏰⏰⏰⏰⏰ 💻💻💻💻💻 ☠ ☠
⏰ ⏰ ⏰ ⏰ ⏰⏰⏰⏰⏰⏰ 💻 💻 💻💻💻💻 💻💻💻💻💻 💻💻💻💻💻💻 ☠ ☠ ☠ ☠☠ ☠☠☠☠☠
⏰ ⏰ ⏰⏰ ⏰⏰ ⏰ 💻 💻 💻 💻 💻 💻 ☠ ☠ ☠ ☠ ☠ ☠ ☠
⏰ ⏰ ⏰ ⏰⏰ ⏰ ⏰⏰⏰⏰⏰ 💻 💻 💻 💻 💻 💻💻💻💻💻 ☠ ☠ ☠ ☠ ☠ ☠ ☠
⏰ ⏰ ⏰ ⏰ ⏰ 💻 💻 💻 💻💻💻💻💻 💻 ☠ ☠ ☠ ☠☠☠☠☠☠ ☠☠☠☠☠
⏰ ⏰ ⏰ ⏰ ⏰ 💻 💻 💻 💻 💻 💻 💻 ☠ ☠ ☠ ☠ ☠ ☠ ☠
⏰ ⏰ ⏰ ⏰ ⏰⏰⏰⏰⏰⏰ 💻💻💻💻💻 💻💻💻💻 💻 💻 💻💻💻💻💻💻 ☠☠ ☠☠ ☠ ☠ ☠ ☠
================= Time Core War =================
A fight where programs are executed in the same RAM and can change their own code or the one of the others if they succeed in finding them.
================= License =================
Copyright © 2011 Martin Bodin
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/>.
To contact me, please use the address “greatfermat at users.sourceforge.net”.
================= Usage =================
It depends whether you are an human or not.
If not (you’re probably a graphical interface for this program, welcome¹ there!), just add “--computer”, it will be simpler to parse.
If you are one:
As a human, you should mostly be interested in the two following way of calling TimeCoreWar (eventually with a “S42” option):
./TimeCoreWar.opt <your program> --color --test | less -R # To test your program.
./TimeCoreWar.opt <your programs> --official --no-data-limit --color | less -R # To make your program fight each other.
There follows a more precise description of the uses of this program.
If you want just to test your program, just launch through the following line:
./TimeCoreWar.opt <your program> --color --test | less -R
If you want to change the default size of the map (100 by default), just add an argument to the option “--test” which will be the size of the RAM you want to simulate.
For instance:
./TimeCoreWar.opt <your program> 300 --color --test | less -R
Note that this number does have to be specially after a “--test” option.
If you want to make two or more programs fighting each other, remove the “--test” option and put all your programs as arguments. (“--test” just makes the simulator continue when there is only one fighter left.)
You will probably want to launch an “official” fight. This will changes some behaviors: instead of being put randomly in the map, programs will be put regularly in the map. The number you might want to put in argument of the program will no longer be the size of the map, but the space between two programs instead.
Officials fights will although limit the maximum number stored in the cells (to unset it, you can use the option “--no-data-limit”). This is to avoid bigger programs to be penalized by “dwarves” (see examples).
For instance
./TimeCoreWar.opt --official --no-data-limit --color examples/Imp examples/Dwarf | less -R
You can also launch a fight between all the fighters of a directory by
./TimeCoreWar.opt --official --color examples/* | less -R
If you have problems the way your terminal displays colors, I advise you to remove the option “--color”.
There exists additional options:
--final Instead of travelling back in the output each time a program is travelling back, this option print only the last state of the universe in the order they appear, in local time. It may be however much more complex to follow. (This option is experimental yet.)
--rw Add informations about cells, such as it has been read or written this turn.
--random-init Initialise the map with random instructions instead of “Data 0”.
--extract-code Use this option to extract each of your codes given as an argument to a file with additional extension “.raw” (note that the program doesn’t check if this file already exists or not).
This will remove all labels, comments and spaces you give. It can be useful if you prefer not to give too much informations of what your program is doing to other players.
Here is a way to only convert (without actually playing a match):
./TimeCoreWar.opt --extract-code <your codes> M0 > /dev/null
S0 Print the map only when the final state is reached (if no “M” option is specified, this might (if no fighter is winning) loop without drawing anything).
S2 Print only the maps of even times.
S3 Print only the maps of times dividable by 3.
S4 I think you’ve understand. It should work for every number from 1 to 2^31-1.
--moo: Well… It’s nothing, forget about it.
M42_000 Limit the computation at the time 42 000.
B42 Set the number of cells between two processes to be between 42 and 84.
U42 Limit the number in a data cell to be between -42 and 42 (included). An overflow results to the result 42, and underflow -42. (It is the space between two programs in official fights, but it is possible to reset this after a “--official” option.)
R0.5 Set the energy transfer rate when calling the instruction “GiveEnergy” (see below) to be 0.5 (the receiver only get half what the sender sent).
----------------- Note about file names -----------------
To open the standard input, you can use “-”.
To open a file that have a special name (such that “--official” or one that starts by ‘B’, ‘F’, etc. for instance), type “'F<the name of your program, with escaped ‘\'’>'” (or add “./” in front of its name).
----------------- Note -----------------
The goal is to be the last one alive in the RAM. If someone (including yourself) kills a thread of you, it’s not that bad if it’s not the last one.
Another goal is to kill the most of your opponents: each time you kill one of your opponent, you win 2 points and make him loose 1 point.
These two scorings are orthogonal.
================= Contents of fighter =================
They are just files containing list of instructions.
Comments are preceded by a “;”.
They are some examples of them in the examples/ folder.
I advise to read them in the following order:
Imp, Dwarf, DwarfRandom, Threads, WaitingImp, Function, AntiImp.
There are several ways to point cells:
· one is direct, for instance “Goto 1” will go to the next instruction.
· one is indirect, for instance “Goto @1” will assume the next cell is a “Data i” and will jump to the i-th cell (relative to the current instruction, i.e. “Goto @1”). If it is not a Data, it will kill the current program.
This kind of indirection can be iterated: “Goto @@@1” is perfectly valid (by can be very dangerous: if any of the three cell read are not Data, this instruction won’t be valid).
· It is also possible to define labels by writing a label name (any identifier) followed by a colon “:” and the labelled instruction. You then refers to a cell directly using this identifier. You can although refer to an identifier relatively to another cell using the syntax “reference:target”. At each instruction, the label “cell” refers to the current cell.
When I describe the instruction, I’ll speak of pointers. Such pointers are always relative to the location of the instruction itself. For instance if an instruction refers to a cell which contains data which should be interpreted as a pointer, this pointer is relative to the place where is the program and not relative to the data itself. There is no beginning in the RAM: it’s a ring.
Here are the available instructions (each time, a, b, c are numbers):
Data a It’s not exactly an instruction (if someone try to execute it, it will be killed), but it contains an information. Some instructions however read cells that are supposed to be data (each time they request to be whether an integer, whether a pointer). If it’s not the case (the pointed cell is not a data), then too, the program is killed.
Add a, b, c It reads two data cells pointed by a and b, and puts the sum of them in the cell indexed by c. If the result of the sum is greater in modulus than the maximal value, the cell pointed by c will contain the maximal value, with the sign of the actual result.
Mult a, b, c Same as “Add”, but performs a multiplication.
Div a, b, c Same as “Add”, but performs a division. Note that if the diviser is zero, your program is killed.
Mod a, b, c Same as “Add”, but performs a modulo. Note that if the diviser is zero, your program is killed.
Cp a, b It copies the content of cell a (whatever it is) to the cell b.
Goto a The instruction which is executed at the next tick will be the one in the cell pointed by a.
Nop It does nothing (it’s in fact converted to a “Goto 1”, which is equivalent).
If a, b, c It checks if the data in the cell a (which must be a data cell) is equal to 0 or not. If it is, it jumps to b, otherwise to c.
IfDat a, b, c It checks if the cell a is a data or not. If it is, it jumps to b, otherwise to c.
JmpIfEqu a, b, c It checks in the content of the cell a is equal to the one of the cell b. If it is, it jumps to c, otherwise do nothing (just go to the next instruction).
JmpIfSameType a, b, c Same as JmpIfEqu, but it tests if the two cells a and b contains the same instruction (without considering its arguments).
JmpIfNotEqu a, b, c It checks in the content of the cell a is equal to the one of the cell b. If it is not, it jumps to c, otherwise do nothing (just go to the next instruction).
JmpIfGreater a, b, c It checks whether the data stored in cell a is greater then the one in cell b and jump to c if it is true. The cells a and b must be data cells.
Call a, b
Function c These two instructions goes together. When executing a Call (a Function cannot be executed, otherwise it makes the program die), it checks if the cell pointed by a if a Function or not. If not, it’s invalid. If it is, then it copies the content of b in the cell c, where c is counter relatively to the Function cell. It’s useful to make function if you’re fighter have repetitive pattern, or if you want to code it in a clean and readable way.
Back a The content of the cell a must be a data. It travels through time by the number of units of time stored in a. If it’s negative, you go back to the past, if it’s positive you just disappear (travelling to the future) until that time. Note that if you travel to the past, this creates a new clone of yourself: one that is where it where in the past, and the new one (the traveller of the future), which is just after the instruction Back at this time. You can change the past if you want, you can even prevent you (and it’s advisable) to go back in the past in the future (still following myself?), that’s not a problem: the universe is supposed deterministic, polymorphic (that is when you go back to the past, you arrive in fact in a new universe similar to this one ; the important word here is the “new”) and with only one following politics (once you’ve travelled through time, as you came from an other universe, no one can prevent you to appear at that time, even by going back another time in the past to kill you!).
There is a shared energy given to every clones of the same program. You get one unit of energy every two turns and you start by 0 energy. When you travel of n units of time in the past, you (and all your clones: it’s shared) loose n units of energy when you arrive. When you travel of n units of time in the future, it’s when you go away that you loose this energy. Be aware that if any clone of a program uses all its energy, then it is killed ; and as the energy is shared, all you’re clones are killed immediately. That could make a strategy to force a thread of someone to execute a code that makes it use all its energy… You can try it if you want!
Cpt a, b, c It copies the content of the cell pointed by a to the cell pointed by b, but at the relative time described by the cell pointed by c. As for Back, it use energy.
Rand i It puts a random data in the cell i. At a given time, all the calls to “Rand” will returns the same result, which is thus deterministic: going to the past won’t change the behavior of programs even if they use the “Rand” instruction.
CountThreads i, d It puts in the cell i the number of thread currently executed at position d.
GiveEnergy i It gives the energy at cell i to the one that has written this last cell. This is an energy transfer: in practise, it is only useful to try to make other program execute it. Note that some energy will be lost in the transfer, even if the destination is the same as the initial one. If the given energy is negative, the program loose this energy but the destination get nothing. Note that this energy will be available at the next turn if the destination is not the sender. If the receiver gets too much energy (so much that it can go in the past before the first unit of time), then the exceeding amount of energy is lost.
================= Conclusion =================
If you have any question, just ask² me!
Cheers,
Martin.
¹ As none are currently known of me, I’m interested in it! Please let me know ☺
² You can e-mail me using the address “greatfermat at users.sourceforge.net”.