XRK Extra RedCode Kit v1.50.1 ============================= Copyright 1992-2012 By Marco Pontello .. contents:: Table of contents Introduction ------------ XRK is the acronym of Extra Redcode Kit and, like the name suggest, it's a set of tools for developing Redcode warriors for Core War, from the first phases of testing & debugging, to full featured large scale tournaments. The various modules are: XRA, XRD, XRS, XRC, RedMap Editor All modules conform to the directives of **ICWS-86** standard. Even being a standard, a lot of different interpretations have surfaced in time, maybe because of some imprecisions in what are considered the reference documents. This implementation follow the rules described in the issues of MC Microcomputer (an old Italian computer magazine) from #67 to #69 (plus some other articles that followed). To sum them up:: Max program instructions: 512 Core size: 8.192 Minimum initial distance: 2.048 Max tasks for each program: 64 Time Out (clock ticks): 50.000 New tasks are executed immediately after the generating task, i.e. they are inserted as the "next task" in the task queues of each program. Contents of each instructions is copied in registers before execution. XRK also implement some original and interesting characteristics, that will be described in details later, like: - The compiler / assembler can digest Redcode sources written in a lot of different styles, it recognize the 'EQU' directive, parse expressions (from left to right), automatically extract the author's name. It generate error messages in a customizable format, including line & column number, and could be adapted to work with any kind of programmer editor. - Single match & tournament simulators feature an optimized allocation method to determine initial warriors position (non random), that ensure more accurate and repeatable results. - There's a Playback system that record match results, so tournaments with known warriors can be speed up dramatically. In addition, the same system lead to a very quick recovery in the event of a power down, without loosing any match just simulated. - Network tournaments are supported. The workload is shared among various PCs, and the results are shown on every screens. Slave clients can be added or removed at any time during the competition. This is not a Core War tutorial. If you aren't familiar with core, Redcode, tasks and indirect addressing modes, check the file *CoreWar.txt*. The sources and compiled objects, along with Playback results, of some warriors are included: from old classics (Dwarf, Imp), to glorious champions (Mice, Ferret), and some others. Now on the description of the various modules. Remember that each one can produced a brief list of all the supported parameters and switches with the usual '/HELP', '/H', '/?'. XRA - Extra Redcode Assembler ----------------------------- :: Format: XRA [path][.RED] /NN /NS /F:string source Redcode (.red) file /NN don't ask for author's name /NS don't show source lines in errors/warns /F: specify a format string for error lines This is the assembler / compiler, that starting from an ASCII file with the Redcode source of a warrior (.red), generate an object module (.rbj, from Redcode object), that can be used with the other modules. XRA accept all the standard commands:: DAT B MOV A B ADD A B SUB A B JMP A JMZ A B JMN A B DJN A B CMP A B SPL B and the equally standard addressing modes:: # Immediate $ Direct @ Indirect < Indirect auto decremented XRA parse label up to 16 characters (alphanumeric only, with the first mandatory alphabetic). The system label 'Start' will identify the start / origin of a program; if omitted, execution will start at the first line, as reminded by a warning message. That's just to make sure one will not start with a 'DAT' by mistake. Speaking of 'DAT', regardless of how it will be used in the source, it will always assembled as a 'DAT #x'. That means that a 'DAT 0' location will be identical to an empty core location. The pseudo instruction 'EQU' is supported, and it's used to assign a specific value to a label, as a macro of sort. They can be used anywhere in the source, as they are evaluated before the rest of the instructions. Ex:: Step EQU 7 Expressions can be used whenever an operand is requested. Expressions must be enclosed in parens, and can contains the classics 4 operators (+ - * / o \), numbers or labels. Operations are evaluated from left to right, without considering any priorities:: Step EQU (512+37) Max DAT (2048/Step) Square brackets have a special meaning, and can be used to express an addressing relatively absolute (or absolutely relative!), referred to the program's first instruction. In other words, this can be used to express offsets from the program's start, without having to use expressions like (Start + x). It's useful to simplify writing programs that relocate or copy themselves in the core. Ex:: IstA Mov -1,<-1 Mov $-1 <-1 IstB Jmp -1 Jmp $-1 IstC Djn 0,<-1 Djn $0 <-1 Start Mov IstA,[2000] Mov $-3 $1997 Mov IstB,[2001] --> Mov $-3 $1997 Mov IstC,[5000] Mov $-3 $4995 Spl [2000] Spl $1994 Jmp [5000] Jmp $4993 **N.B.** In previous versions of XRA, the same results was obtained using the pseudo-addressing mode '*'. This is still supported for backward compatibility. XRA ignore any eventual 'END' or 'SPACE' pseudo-instructions. Remarks are simply started with ['] [;] or 'REM'. In case of missing or duplicated labels, bad expressions, syntax errors, etc., the compiler will emit targeted error messages, showing the line and the approximate position of the errors. With the switch '/NS', only the error messages will be shown, without echoing the corresponding source lines. The way the error message is show can be customized, so that it can be adapted to the parser of any programmers editors, with the '/F:string' switch. On the formatting strings these symbols can be used:: \F file name \P path \T type (error or warning) \E error message \L line number \C column \N return \_ space \\ backslash Default is: \L\_\T:\_\E Some example. Let's take a 'test.red' source like this:: Target Dat 0 Loop Mov !Bomb,@Target Sub #4,Targt Jmp Loop Bomb Dat 0 ; by Humpty When assembling, XRA will output:: 4 ERR: Illegal Addressing Mode '!' (A) Loop Mov !Bomb,@Target ^ 5 ERR: Undefined label 'TARGT' (B) Sub #4,Targt ^ If one need to call XRA from an editor that expect error messages following Turbo Pascal conventions, XRA could be run like:: XRA test /NS /F:\f(\l):\_\e In order to get:: TEST.RED(4): Illegal Addressing Mode '!' (A) TEST.RED(5): Undefined label 'TARGT' (B) Once fixed the errors, the output will look like:: TEST.RED(3): Label 'Start' not found. Execution start at 1st inst. TEST.RED(3): Program start with a DAT! Finished. Author: Humpty Writing file TEST.RBJ... File length = 5 lines / 106 Bytes XRA show a warning to notify that the execution will start with a 'DAT', and so the warrior will have a very brief life! Anyway, as the program is formally correct, XRA doesn't bother too much and build the object code. Another thing that XRA does it to insert in the object code some additional informations, including the assembly date and the author's name. Just inserting a remark in the source will enable XRA to automatically detect the author as the string after the 'by'. The standard ';author' remark is also recognized. For example:: ' Test - By Humpty Dumpty ' Test (1994) ' By Humpty Dumpty --> Author: Humpty Dumpty ;program Test ;author Humpty Dumpty If XRA will not find any info on the author in the source, it will stop and prompt the user. That could be avoided using the switch '/NN' (for No Name). In the absence of any author information, it will be recorded as 'Unknowed Anonym'. XRD - Extra Redcode Disassembler -------------------------------- :: Format: XRD [path][.RBJ] name of a compiled program (.rbj) This is the most simple and standard module of the entire group. When launched, it will show some info about the specified program, the author, version of the assembler used to produce it, and date of creation. Then follow the length in lines, the one at which the execution start, and then the disassembled listing. The "source" just obtained is also written on the file *xrd.red*, ready for being edited. XRS - Extra Redcode Simulator ----------------------------- :: Format: XRS [path][.RBJ] [[path][.RBJ]] [/G] [/S] [/R:xxxx] [/D:xxxx] name of a compiled program (.rbj) /G force graphic rappresentation /S standard players allocation (random) /R:xxxx number of rounds (default 100) /D:xxxx use a specific distance between the warriors Before all the switches explanations, a (boring) discussion of the programs allocation is due. Why usually programs are inserted in the core in random position, subject only to a minimal distance? Because in Core War relativity is a central concept, and any program must have no idea of the opponent position. So, when a match start, the only assumptions that a warrior can make is that the adversary have to be between locations 2048 and 6144 (minimal distance forward, and backward), and nothing more. This way things works but, there are collaterals effects: an high number of rounds per match is needed to get meaningful and stable results. Otherwise, with just an hundreds rounds, results can oscillate greatly, and sometime in spectacular ways, as any CW fan know for having witnessed directly. A classic example is a Dwarf vs Dwarf match, that very rarely end in a drawn. Check this two results, with random allocation:: Extra RedCode Simulator v1.50 - (C) 1992-2002 Marco Pontello ------------------------------------------------------------ DWARF by A.K.Dewdney 139 46.3% DWARF by A.K.Dewdney 136 45.3% Match won by DWARF after 100 Rounds. ( W 38.0% - L 37.0% - D 25.0% ) Elapsed Time: .11 Sec. - 914.3 Rounds/Sec. Extra RedCode Simulator v1.50 - (C) 1992-2002 Marco Pontello ------------------------------------------------------------ DWARF by A.K.Dewdney 161 53.7% DWARF by A.K.Dewdney 104 34.7% Match won by DWARF after 100 Rounds. ( W 42.0% - L 23.0% - D 35.0% ) Elapsed Time: .17 Sec. - 581.8 Rounds/Sec. The first is what one would expect, the second is what happens more often than not. The most easy and secure solution is to simulate all the possible 4.096 rounds for every couple of warriors, that lead to results absolutely free of any lucky strike. I think this is what was done in the first world championship organized by the ICWS (probably was either that or a really high number of rounds). On the contrary, on other official tournaments some strange things have been done (like first grouping the players in subdivisions, to reduce the number of matches), that may have caused some equally strange results. XRK's optimized allocation instead try to make the relative positions of the programs distributed in an uniform fashion, with a number of tweaks to insure to have a good approximation of all the possibles distances and "steps". Obviously, sometimes the results still aren't absolutely right, but I think that in general it's still an improvement compared to the random allocation, and with 100 rounds it's possible to have results surely better than with the usuals ways. Just try a match between two identical warriors, and see what it mean. All considered, it surely come handy to benchmark a new warrior against a set of known ones and make an idea of its value. Note that the algorithm is optimized to work best with 100 or more rounds. Even better, as with optimized allocation the results between certain warriors are always the same, this has led to the implementation of an especially useful feature of XRC. But more on that on the next section. Back to the parameters accepted by XRS. The two warriors object modules are obvious. It's also possible to specify only one, to see how a program behave alone and for debug in general. The number of rounds can be specified with the '/R:tot' switch; if omitted, just one round will be simulated. The '/G' switch is used to force a graphic representation during the simulations (VGA and CGA video cards supported). This is meant to override the default, that are graphic mode for single rounds (because that's usually for debugging purpose) and text mode for multi rounds (when more speed is desired). But remember to check the graphic mode with more than one rounds, because it's still fast and is very nicely done. The screen is divided in 4 view ports, and at each round the simulation will alternate between them. In graphic mode, the colors are used as follow:: Player A Player B Executed Blu Red Modified Cyan Yellow Read/scan Green Magenta **N.B.** The graphic mode as just described require a VGA/MCGA video card. If that's not available, there's a simplified 2 colors display mode that's compatible with the plain old CGA. The supported video modes will be auto detected by XRS, and the right mode will be set. It's possible to specify a certain distance between the players with '/D:tot'; this way it will be possible to test a warrior in a specific situation, without having to run a lot of simulations waiting for that scenario to happen. Obviously the usual min/max distance limits will still apply. With '/S' the standard / random allocation system is selected. This is also the default if only 1 round is selected. Now about the debug functions available during single round simulations. In this occasions, the executions speed is set to be very low, in a screen occupied for the vast majority by the core representation, and then the program names and the cycles executed. It is possible to speedup the simulation with the right [SHIFT], to quickly go past boring and uninteresting phases, and go in the step-by-step mode with the left [SHIFT]. In this mode, additional info are displayed on the side of each program: the current task, and the location & instruction just executed. The current tasks PC are also pointed out graphically. In this mode too it's possible to use the right [SHIFT] to speedup the execution, or press any key to step to next cycle. Pressing [RETURN], and inspect cursor show up, and can be moved along the core with the cursor keys, adding [CTRL] so move faster. The content of the pointed location is shown, so that's possible to check any place of interest. Pressing the left [SHIFT] again, the normal (very slow) execution speed is restore. At any moment it's possible to exit with [ESC]. **N.B.** Described in this way it probably sound more complex than it is. In facts, it's instead very easy and practical, so just try it out. To end the XRS section, and the end of the match the points accumulated by the two warriors will be show: 2 points for a win, 1 for a draw, 0 for the loser. Another data shown is the program efficiency, or the ratio between the total points obtained and the max theoretical score (for winning every round):: eff% = points * 100 / (rounds * 3) Also shown are rounds won, lost, drawn, elapsed time, rounds per second, and, of course, the winner. XRC - Extra Redcode Competition Simulator ----------------------------------------- :: Format: XRC [/PR] [/PW] [/PN] [/PI] [/PD:prg] [/PO] [/T] [/S] [/R:xxxx] [/L:file] [/N] [/NET:Master|Slave] prg warrior .RBJ file PlayList to use /PR only read results from Playback /PW only write results to Playback /PN don't use Playback /PX exclude Playback results with less rounds /PI show Playback info /PO optimize Playback data /PD:file remove a program's data from Playback /T disable matches inside the same team /S standard (random) allocation /R:xxxx number of rounds per match (default 100) /L recall last used warriors /N check for author's name /NET:x network mode: master or slave A brief intro, linking back to the optimized allocation discussion in the XRS section. XRC leverage the fact that a match between the same 2 warriors lead always to the same results. With the Playback system, every time a tournament is simulated, XRC check if in the file *playback.xrd* there's already the results for a certain match. If the match is found, the results are simply read, and the score updated, taking about no time at all. If, instead, a result for the match was never recorded, the simulation start, and when the match is completed, the new result is written. This way, after just some tournaments, a substantial data base of results for every warrior is created. That mean that when testing a new warrior in a tournament, only the matches with the new program are simulated, greatly reducing the total time needed to get the final scores. Another interesting byproduct is that if a power shortage happens mid tournament, all the work done up to that moment is automatically saved. Restarting the tournament, all the match already played will just be read from the Playback system, restoring the previous situation in a matter of seconds. Some practical / technical notes. Each match/results record take just 52 bytes, so even a Playback file of a large number of results will be very small. Every record keep also a checksum of the programs, so if a program is modified those old results are automatically ignored. When a new record is record, it's simply added at the end of the file. The Playback system is able to find any record in any position, but every now and then launching a Playback optimization maybe a nice thing. Last thing on this topic. When the results of a new match are added, the record will contain also the number of rounds simulated. Then, when the Playback system search for records during a tournament, this info is usually ignored, unless the '/PX' switch is used. Also, when the Playback optimization is performed, if the are duplicated entries for a certain match, only the one with the most rounds is kept, to keep the most accurate result. When comparing match obtained with the standard and optimized allocation, the latter are considered "better". The ratio is:: 1 round optimized = 4 x rounds standard The network mode open the possibility of leveraging the CPU power of other PCs around, creating a Core War's crunching cluster. The only requirement is a shared directory: Win 9x file sharing, Novell, LANtastic, etc. should all works. Of course it's possible to use this mode even on just one PC, and this could be a way to get more speed on multiprocessors systems. Now for the practical details. A station will act as a master (run with the 'net:master'), plus any number of slaves ('net:slave'). On the master XRC, when starting it will be possible to select all the details (see below). After the usual selection and loading of all the warriors, and settings of the various options, XRC will generate some files that will be used by all the other slaves to participate in the tournament. The slaves stations could be launched at any time, and will remain in stand by, waiting for messages from the master. So, for example, one will launch XRC in slave mode in all the PCs of the office (turned in a Core War site during the launch pause). Then, on the last / main one, XRC will be started as a master, specifying the rounds number, all the players, the Playback mode, etc.; the moment this XRC will start crunching rounds, the others slaves will wake up and start to take on one match after the other. If, after a while, another PC will become available, just starting another slave will add some CPU power on the cluster: it will automatically show the current scores and start working on some matches. Conversely, if a PC become needed, it can simply exit with [ESC] and the rests of the machines will keep working as if nothing happened, albeit just a bit slower. At the end of the tournament, the master XRC will terminate and end normally, while the slave stations will enter in standby again, awaiting for further instructions and ready to start working again on another tournament. **Warning** In the event of an abrupt interruption (for a power shortage, for example), it may be needed to deleted the file *nport.xrd* (used for messages exchanging) before restarting. If instead one slave crash, or is just being very slow, at the end of the tournament all the active machines may show a "waiting results..." message. In this event, it's possible to press [ESC] on the master station and select "Free match". The missing results slot will be unlocked and the remaining rounds completed. Going back on XRC normal workings, at the end of any tournament XRC will display the final scores, and also write on a *results.txt* file all the details, including team scores, results of every match, etc. If a result file is already present, this will be saved as *results.bak*. Another thing. XRC will manage tournaments with up to 75 players, even if during the competition just the first 30 will be displayed on screen. That's not a big limitation: a warrior over the 30th position probably doesn't deserve much attention anyway! :-) About all the various possible settings. XRC launched without any switch or parameter, start immediately asking for the first warrior, up to when an empty name will be entered. Each player will be checked for existence and integrity, and some default will be assumed: 100 rounds per match, Playback system fully active, optimized allocation:: Player 01: Dwarf Player 02: Mice Player 03: Ferret Player 04: The team mode is activated simply adding the team name to the first warrior of that team. For example:: Player 01: Alfa Team1 Player 02: Beta Player 03: One Team2 Player 04: Two Player 05: The '/S' and '/R:tot' switches works exactly as in XRS. '/N' tell XRC to check for the presence of the author name of every warrior. If one is missing, XRC will ask for it before continuing. The '/L' switch cause XRC to automatically recall the players used on the last tournament. This come especially handy when testing a new warrior. The playlist correspond to the file *playlist.xrd*; it's possible to indicate a different one with 'L:file'. After the tournament, the new list will be saved to the default one. The '/T' exclude matches inside the same team. The '/PR', '/PR' and '/PN' switches limits the usage of the Playback system to only read results, write, or disable it completely. This can come handy in real / official tournament, when it would be desirable to see the all the rounds being effectively simulated at the moment. With the '/PX', XRC will not read and use records from the Playback system that are obtained with less rounds per match than in the present tournament. Any eventual records obtained with the standard allocation would need to have at least 4 x the rounds. '/PI' show some statistics about the *playback.xrd* file, like the number of records and the warriors presents, and also some note on its fragmentation level. '/PO' is used to optimize / sort the Playback file, and make it more efficient. More unsorted records equals to more time needed to find them. So, every now and then it may be a good thing to optimize it. But it's not a real problem, the speed difference will rarely be noticeable. '/PD:file' is used to remove from the Playback system all the records of a certain program. Can be useful if one is used to numbering warriors during testing, like test1, test2, etc. In this way, when a warrior is finally completed, all the old and now unneeded tests can be deleted. REDMAP - RedMap Editor ---------------------- This tool let one create in a very simple way programs that draw recognizable shapes in the core, text included. Can be used to add a sort of logo / sign to a program, taunting against the adversary, etc. Admittedly not very useful, but can come handy for some jokes. One notable use was to create a classic "Hello World" in Redcode. See the YouTube video here: http://goo.gl/ZfQG2 The program present itself as a pixel by pixel editor, where the color of the location currently pointed can be changed using the keys from [1] to [3] and the space bar. Movement along the core is done with the cursor keys, as usual. Then the work is completed, [RETURN] will generate a Redcode source and save it as *redmap.rep*. The source can then be assembled and used as is, or cut & paste inside some other program. [ESC] instead will simply quite.