[snip] Last September I was looking for that patched version of pMARS as well for Will Varfar, but I couldn't find it. I think what happened was that it was on my previous machine that died some years ago. So I redid the modifications and added Will's idea of checksumming of the core and process queues every cycle to the debugging output. You can find the executables for exhaust-1.9 and vanilla pmars-0.9.2 server version here: http://www.cs.helsinki.fi/~jpihlaja/cw/pmars-0.9.2-dbg.tar.gz http://www.cs.helsinki.fi/~jpihlaja/cw/exhaust-1.9-dbg.tar.gz The exhaust version is based on 1.9.0, not the newer 1.9.2 but the latter only removes a restriction on the number of warriors in a multiwarrior battle so that shouldn't matter. In the pmars tar file you should find three executables pmars1.exe pmars2.exe and pmars3.exe in the src/ directory. The first only prints the checksum of the core contents after every round, the second prints the debugging output for every executed instruction, and the third adds to that the checksum of the core contents and process queue contents every cycle. Similarly in the exhaust tar file there are exhaust1.exe exhaust2.exe exhaust3.exe. Each debugging line contains these fields (from left to right): - The number of instructions to execute before a tie. So in single warrior battles this is a cycle counter, in one-on-one battles it is a half-cycle counter and so on. - Instruction pointer. - Disassembly of the current instruction before execution. - Number of processes of the current warrior. - Effective address of the instruction's A-field operand. - Effective address of the insutrction's B-field operand. - The A- and B-fields of the A-operand's register. - The A- and B-fields of the B-operand's register. in pmars3.exe also: - The checksum of the core computed after the instruction's operand's have been evaluated, but before instruction itself has been executed. (So core changes due to < and > and { and } are reflected in the sum.) - The checksum of the current warrior's process queue before the current instruction's address is removed from the queue. In addition the checksum of the core is displayed after each round. I'm going to describe the checksumming operation next, but check the top of sim.c in exhaust to be sure, and sim.c in pmars to be doubly sure. The checksum routine is embodied in a procedure accumulate() that takes as input some state variables and the data to be accumulated. The state variables are SUM and SEED, both unsigned 32 bit variables, and both initialised to hex $12345678. accumulate() is SEED <- rng(SEED) SUM <- SUM xor ((SEED + DATA) <<< DATA) where <<< is a 32 bit left rotate operation and DATA is the 32 bit data to add to the checksum. The function rng() is the pMARS random number generator from src/pos.c. The checksum of a warrior's process queue is computed by initialising SEED and SUM to $12345678, and then doing accumulate() for all the core addresses in the process queue from the first to execute up to the last to execute (in that order). The checksum of the core contents is similar; SEED and SUM are initialised to $12345678 and then accumulating each instruction in core from core address 0 to CORESIZE-1. An instruction is represented by six values: OPCODE, MODIFIER, AMODE, ADATA, BMODE, BDATA, where OPCODE encodes an instruction's opcode using exhaust's encoding: DAT = 0 SPL = 1 MOV = 2 DJN = 3 ADD = 4 JMZ = 5 SUB = 6 SEQ = CMP = 7 SNE = 8 SLT = 9 JMN = 10 JMP = 11 NOP = 12 MUL = 13 MOD = 14 DIV = 15 LDP = 16 STP = 17 MODIFIER is encoded as: # = 0 $ = 1 @ = 2 < = 3 > = 4 * = 5 { = 6 } = 7 AMODE/BMODE are encoded as: .F = 0 .A = 1 .B = 2 .AB = 3 .BA = 4 .X = 5 .I = 6 and ADATA and BDATA are the operands' data values normalised to 0..CORESIZE-1. So, using this encoding an instruction is is accumulated into the core checksum by applying accumulate() with DATA argument in turn to OPCODE, MODIFIER, AMODE, BMODE, ADATA, BDATA, in that order. That is done for every instruction in core. Concerning validation suites, you're right that there are no other validation suites for the -94 draft + extensions, at least that I'm aware of. I added some redcode and .rc files into the t/ directory to test the checksumming operation, and also one that shows how the pMARS assembler defaults the addressing modes and modifiers when the redcoder omits them. What I did with exhaust and suggest to you is this: - Run some battles between two warriors with the debugging logs turned on and diff the results. The -F argument of pMARS (and in exhaust) is useful for this. - If that checks, implement the pMARS positioning algorithm for one-on-one battles, run some battles with multiple rounds between some warriors and compare the checksums of the core contents after each round. - If that checks, run every combination of starting positions for some pairs of non-p-space warriors. You could implement the -P switch of pMARS to run every permutation of battles, or do what I did and have a script run the simulators and check the results (test.pl in the exhaust tar file.) Use a few papers, For me at least this was the most fruitful approach since I had some nasty bugs (overflows) in the process queue management that showed up extremely rarely. You might want to check out the tiny hill on Koenigstuhl for this test: http://www.ociw.edu/~birk/COREWAR and John Metcalf's Infinite tiny hill (with the same warriors and a few more): http://myweb.tiscali.co.uk/corewar/corewar - When that works your simulator probably is OK. Implement the multiwarrior positioning algorithms from pMARS, run a few battles, and check the scores. OK, so this seems like a hell of a lot of work, and it is, but if the bugs show themselves you'll be glad you did it. :) There aren't many validation suites for the pMARS preprocessor unfortunately. It has some quirks you should be aware of (especially in for/rof block handling), but I'm a bit bushed out to list or remember them. I'd grab all the files from Koenigstuhl, run them through your assembler and pMARS's assembler (with the -r 0 command line argument so you don't need to fight any battles) and diff the results.