PMARS(6)
๐ PMARS ๐ (that's pmars, section 6 of the Games Manual, bestie)
okay so. if you've ever wanted to make tiny programs fight each other in a memory array until one of them is the last one standing โ welcome, you're home. this is pMARS, the portable Memory Array Redcode Simulator, aka the corewar interpreter that runs literally everywhere. it's a Games Manual page, it's a whole personality, and we're going through it together. grab a snack. ๐
โจ NAME โจ
pmars โ portable corewar system with ICWS'94 extensions
โจ SYNOPSIS โจ
pmars [ option ... ] file1 [ file(s) ]
โจ DESCRIPTION โจ
pMARS (portable Memory Array Redcode Simulator) is a corewar interpreter with multi-platform support, and honestly? she gets around. pMARS currently runs on UNIX systems, Windows and the Mac. she implements the ICWS'94 draft standard, but can also be used in ICWS'88 mode. the base system includes a graphical core display for UNIX (curses, X-windows) and PC/linux (svgalib). and there's a line-oriented debugger included to help you write warriors for the ICWS'94 draft standard. so thoughtful of her. ๐
pMARS runs one or more warriors written in Redcode that you hand her as file(s) on the command line. running a single warrior is supported for debugging (solo arc, we love to see it). Two warriors get pitted against each other for standard play, but up to 36 warriors can be named for "multi-warrior" core war โ yes, thirty-six, it's giving battle royale. ๐
if the warrior(s) assemble without error they get loaded into the core array and executed in round-robin mode, starting with the first warrior. warrior 1 is loaded starting at core position 0; warrior 2, 3, etc., at either a random or fixed position. and for fairness the starting order is rotated after each round. iconic behavior honestly.
โจ SCORE โจ
the score is reported after all rounds have been played. a round ends when either a single surviving warrior remains or when a maximum number of cycles has elapsed. โณ
for each round, every surviving warrior is awarded points calculated from a score formula (F). by default, this is (W*W-1)/S, where W is the total number of warriors participating, S is the number of of survivors, and / is integer division. (yes, integer division. no decimals here, bestie, we're doing math the crunchy way.) alternative score formulas can be specified with the = option (see below).
when two warriors battle, the results are reported as wins1, wins2, and ties, where wins1 and wins2 are the numbers of rounds that each warrior won, and ties are the number of rounds in which both warriors lasted until time-out. the score is then:
warrior 1: points = wins1 * F + ties * F
warrior 2: points = wins2 * F + ties * F
F is a score formula containing the W and S parameters. when more than two warriors (W) participate in a game, results are reported as wins[1], wins[2], .., wins[W], losses for each warrior, where the index indicates the number of warriors that survived until the end (the S parameter in the score formula). the total number of points for each warrior is then calculated as:
points = sum (S=1..W) (wins[S] * F)
a few alternative score formulas:
10
(W+1)/S
(x=W-S+1)*(x+1)/2
(S==3)*5 + (S==2)*3 + (S==1)
(S == 1)*W + (S != 1)
โจ OPTIONS โจ
command line options may occur anywhere on the command line โ she's flexible like that. single-letter options without a parameter can be combined as in -fbe. the special argument - (dash) stands for standard input (stdin). it can be combined with the -@ option (see below) to signify reading options from stdin, or the - can take the place of a warrior filename, in which case warrior code starting with a ;redcode line and ending with an END statement is extracted from stdin. the END statement can be omitted if the next ;redcode line immediately follows the last instruction. several warriors, each specified by a separate dash on the command line and bracketed by ;redcode/END can be piped into pMARS. #- (where # is a positive number) is a shorthand for writing this number of dashes on the command line. ๐
-r #โ this option sets the number of rounds to play. the default is1.-r 0produces assembly output (unless-bis specified), but does not execute the warrior(s). a maximum of32767rounds can be specified.-s #โ the-soption specifies the size of core memory in number of instructions. it defaults to8000. maximum core size is platform-dependent, but usually at least65535.-c #โ-csets the maximum number of cycles per round. a cycle consists of one execution of each warrior. a round ends when either a single warrior remains executing or when the maximum number of cycles has elapsed.-p #โ this option sets the maximum number of processes a warrior can run. the default is8000.-l #โ this sets the maximum length of a warrior source file in instructions. it defaults to100.-d #โ this option specifies the minimum distance between the first instruction of each warrior. it cannot be smaller than the maximum length (the-loption) and defaults to100instructions.-S #โ the-Soption sets the size of the P-space to # cells. the default is1/16thof core size if core size is evenly divisible by sixteen, or the next larger divisible fraction. see also the P-SPACE section below.-R #โ the-Roption sets the read limit. the read limit must be a factor of core size. the default is core size, i.e. no read limit.-W #โ the-Woption sets the write limit. the write limit must be a factor of core size. the default is core size, i.e. no write limit.-fโ the-foption instructs the loader to use a fixed series of addresses for positioning warriors. this is done by initializing the pseudo random number generator with a checksum value derived from the source of all warriors. thus, initial placements will still be "random" from round to round, but will be the same if the same warriors are run again. as a consequence, the result of battles run with the-foption will show no statistical fluctuations. this option is useful for validating ports of pMARS to new platforms and for providing an absolute, albeit arbitrary, performance measure for warriors.-F #โ this option serves two purposes. it sets the seed value of the pseudo random number generator, and also tells the loader to install warrior 2 at the given address # for round 1. if the number is larger than the core size minus the minimum warrior distance, it will be wrapped around to the range of available starting positions. this option is useful for testing different versions of a warrior with constant initial placement. warrior 1 is always installed at address0. the-Fand-foptions are mutually exclusive. if neither option is specified, the pseudo random number generator is initialized with the system time.-Pโ this option makes pMARS use an alternative algorithm for positioning warriors. this algorithm uses all possible combinations of starting order and position in a random sequence, and will not use the same combination twice unless all the combinations have already been used. if the-roption is not given, the number of rounds fought will be the number of all possible combinations. > trying to use this option with more (or less) than two warriors causes an error.-eโ if this option is specified, the cdb debugger is entered immediately after loading warriors into core.-bโ this option runs pMARS in brief output mode.-bsuppresses warrior listings after assembly.-Aโ the-Aoption assembles the input warriors without running any fights. emits ICWS'94 draft compliant load files.-kโ with the-koption, pMARS uses the same output format as the KotH program. this option enables pMARS to work with scripts written for the KotH server.-8โ this option enforces strict compliance with the ICWS'88 standard and disables all ICWS'94 language extensions, which are flagged as syntax errors by the assembler. since ICWS'94 is a superset of ICWS'88, this option is not necessary to run ICWS'88 warriors.-oโ when this option is given, pMARS reports scores in decreasing order rather than in the order warriors were named on the command line. this is mostly useful for multi-warrior play.-Vโ the assembler generates verbose output with this option. this is only useful for debugging.-vโ this option sets the display mode for UNIX and DOS display versions (see APPENDIX).-@ <fn>โ pMARS continues reading options and filenames from the parameter file <fn>. if <fn> is a-(dash) standard input is parsed. comments in the parameter file start with a semicolon.-= <string>โ the=(equal) option allows you to specify a custom score formula (see SCORE). the formula may contain the standard arithmetic and logical operators (as in the C language), as well as the parameters W (number of warriors participating) and S (number of warriors surviving this round). you need to enclose the formula string with quotes if it contains spaces or characters interpreted by the operating system.-Q #โ the "query" option is intended for use in scripts that run pMARS in batch mode. depending on the number code following-Q, the program returns an informative number as the exit status.pmars -Q 1000e.g. will cause pMARS to exit with a code that spells out the program version. more on-Qarguments and exit codes can be found in the ADDENDUM.$โ the$(dollar) parameter is not preceded by a dash and cannot be grouped with other options. it terminates reading command line parameters and is used in parameter files or input streams (-@ fn). the$is necessary if you want to combine two or more of command line parameters, warrior code and cdb commands in the same input stream or file. below an example of such a combined input file:
;Below the command line parameters:
-r 10 -beF 1000 2- $
;redcode
;name Imp 1
;assert 1
mov 0,1
end
;redcode
;name Imp 2
;assert 1
mov 0,2
mov 0,2
end
!! cdb commands follow:
sk 1000
reg
quit
๐ฆ X-WINDOWS OPTIONS ๐ฆ
okay so bestie, the X-Windows display version of pMARS is the โจglow-upโจ edition and it comes with extra command line options on top of everything else. here they are:
-display <string>โ this one takes a string telling you where the window should pop up. Following X standards, the display spec is formatted likehostname.domain:display.screen, where the part before the colon is the standard internet host specification, anddisplayandscreenare integers. the screen spec? totally optional, you can ghost it. ๐
for an example, picture this: you're working at an X terminal named ncd13.complang.tuwien.ac.at, and you're remotely logged in at host stud1.tuwien.ac.at where the binary of pmars lives. you can run:
stud1$ pmars -display ncd13.complang.tuwien.ac.at:0 -b aeka.red aeka.red
and the window will appear at your local screen. ๐
-geometry <string>โ lets you set the initial size and position of the window. format iswidthxheight+x+ywherewidth,height,x,yare integers and+may be replaced by-. either of the two parts (widthxheightor+x+y) may be omitted. heads up: this overrides the-vswitch concerning the window geometry. ๐
examples, because we love a visual:
pmars -geometry 600x400+30+100 ....opens a window of 600 by 400 pixels at the screen position (30,100).pmars -geometry 1024x768 ...creates a window of 1024x768 pixels.pmars -geometry -20+300 ...creates a window with standard size with its left upper corner at position (-20,300), i.e. out of the left side of the screen. iconic, unhinged, we stan.
-fn <string>โ the string after this argument specifies the X font to use. by default, a terminal font is used. if this font can't be found,"fixed"is used for a font ("fixed"should be present at every X installation, she's everywhere bestie). use the commandxlsfontsto get a listing of fonts that can be used at your X server, andxfontselprovides a comfortable way to select a font."fixed"is the fallback if the specified font can't be found. it is strongly recommended to use a fixed pitch font. ๐
oh and pookie, quick note about the argument of the -v display option: in the X-Windows version it has an additional fourth digit. 0 (the default) enables the color display, 1 the grayscale, and 2 the black and white display (e.g. -v 1033 for the grayscale display). ๐ธ
๐ฅ REDCODE ๐ฅ
so pMARS implements an extension of the proposed ICWS'94 standard. the new instruction modifiers .A, .B, .AB, .F, .X, and .I, the arithmetic instructions MUL, DIV and MOD, as well as post-increment indirect (>) are supported. slay. โจ
Version 0.5 of pMARS adds support for three experimental opcodes that are currently not included in the ICWS'94 draft:
SEQ(Skip if EQual): this is a synonym forCMPand is included mainly for clarity (future versions ofpMARSmay implementSEQas a "predefined EQU" rather than a true opcode).SNE(Skip if Not Equal): the opposite ofSEQ.NOP(No OPerations): do nothing.
Version 0.6 adds three new indirect addressing modes that use the A-field instead of the B-field as the pointer for indirection:
*โ indirect using A-field{โ predrecement indirect using A-field}โ postincrement indirect using A-field
the new P-space instructions of version 0.8 are discussed under a separate heading below. ๐
the assembler also supports multi-line EQU statements, a feature not included in the current ICWS'94 draft. the format for multi-line EQUates is:
<label> EQU <line1>
EQU <line2>
[...]
EQU <lineN>
<label> in the warrior source is replaced by <line1> <newline> <line2> <newline> [....] lineN. and in contrast to KotH, pmars EQUs substitute arbitrary text, and not just expressions. EQU expressions are not implicitly parenthesized. no cap. ๐
pMARS features the non-standard FOR text-repetition macro. this macro repeats the text between FOR and ROF a specified number of times:
<labels> <counter> FOR <times>
[..]
ROF
<times> is an expression specifying the number of expansions; it may contain EQUates and labels as long as they have been defined before the FOR/ROF block. <counter> is the last label before the FOR word, but not necessarily on the same line. it is expanded to 01, 02, .., <times> in each repetition. the optional <labels> label the first instruction after FOR expansion. an example:
ORG start
start
sp FOR 2
a&sp SPL a&sp
JMP a&sp
ROF
becomes after expansion:
start
a01 SPL a01
JMP a01
a02 SPL a02
JMP a02
the symbol & concatenates 'a' and 01, 02 to form a valid label. EQU expansion and FOR/ROF processing is done in the same pass. it is therefore possible to write:
dest01 EQU 500
dest02 EQU 1000
dest03 EQU 1500
idx FOR 3
MOV src,dest&idx
MOV src+1,dest&idx
ROF
src MOV <-1,<-1
JMP src,<-2
using predefined EQUates (see below) it is possible to define adaptive FOR/ROF blocks. the next example fills the remainder of the warrior (up to MAXLENGTH lines) with decoy instructions:
FOR MAXLENGTH-CURLINE
DAT 1,1
ROF
since true logical expressions have a value of "1" and false expressions a value of "0", you can write conditionally assembled code enclosed by FOR/ROF:
FOR CORESIZE == 8000
<some code>
ROF
FOR CORESIZE != 8000
<other code>
ROF
pMARS uses KotH-style ;name and ;author comments to describe warriors. if a line starting with ;redcode is present, all text preceding it is ignored. this makes it possible to run posted warriors without removing mail headers and descriptive text (bestie, the laziness is the feature ๐). the ;version, ;strategy and other comments mentioned in the ICWS'94 draft are currently not used.
as another "non-standard" extension, the assembler predefines the following run-time variables: CORESIZE, MAXPROCESSES, MAXCYCLES, MAXLENGTH, MINDISTANCE, PSPACESIZE, READLIMIT, ROUNDS and WRITELIMIT. they can be used in your Redcode as though they were defined by EQUs like:
CORESIZE EQU 55440 ;current value of -s parameter
MAXPROCESSES EQU 10000 ;current value of -p parameter
[etc.]
the run-time variable CURLINE holds the current instruction number offset from the first instruction. WARRIORS is initialized with the number of warriors specified on the command line. ๐ซถ
pMARS supports the ;assert directive as a way of checking whether a warrior is run under the parameters it was designed for. if the expression following ;assert evaluates to "0" (false), assembly is aborted with an error message. if an ;assert is missing, a warning is issued. examples:
;assert CORESIZE == 55440 && MAXLENGTH >= 200
;assert !(CORESIZE % 4) ; is multiple of 4
;assert 1 ; if warrior works under all settings
the run-time variable VERSION holds the current pMARS version (e.g. "60" is v0.6.0) and is useful in ;assert expressions. โจ
with the -8 option, pMARS is fully ICWS'88 compatible, except that a comma is required between operands. extensions like predefined and multi-line EQUs and FOR/ROF are supported even in ICWS'88 mode. periodt.
a full treatment of corewar and ICWS'94 in particular is beyond the scope of this document. general information about corewar as well as the ICWS'94 draft is available by anonymous FTP from https://corewar.co.uk/standards/ ๐
๐ง P-SPACE ๐ง
originating from discussions on rec.games.corewar, P-space is an attempt at making warriors more "intelligent" by giving them a memory. P-space, short for "private", "permanent" or "priviledged" space, is a memory area separate from core whose contents is not cleared between rounds. every warrior has its own P-space for gathering information about the opposing warrior, but there is a provision for sharing P-space in team play (see below). the way she remembers things across rounds? highkey main character energy. ๐
P-space cells contain values in the range 0..CORESIZE-1. the number of P-space cells can be adjusted with the -S command line option; by default, P-space size is 1/16th of CORESIZE. this number is available to warriors as the predefined variable PSPACESIZE. pMARS updates P-space cell 0 at the beginning of each round with the result of the previous round: 0 signifies a loss in the previous round, a number larger than zero means that the warrior survived until the end of the round, the value indicating the number of surviving warriors. that is, a value of "1" means that the warrior survived by itself (a "win" in a two-warrior battle), a value of "2" that two warriors lasted until the end (a "tie" in a two warrior battle), etc.. in the first round, P-cell 0 is set to -1 (actually CORESIZE-1) to indicate that there is no previous result. ๐ธ
there are two new instructions for accessing P-space:
LDP(Load P-space) loads P-space cell specified by A-value into core at B-address.STP(Store P-space) stores A-value into P-space cell specified by B-value.
it is important to note that P-space cells are referred to by A/B-values as opposed to A/B-addresses. as an example, "STP #9,#1" stores number 9 in P-cell 1. ๐
since all P-space access is only via these two instructions, it takes too much time and space to use P-space for working variables where they would be safe from the opposing warrior. P-space was made deliberately hard to access, unlike a set of general purpose registers. she's exclusive, she's guarded, she's not for everyone. ๐
P-space can also be used for communication between warriors belonging to a team in multi-warrior core war. to allow communication, P-space has to be declared as "shared". you do this by including the PIN pseudo-opcode in your source:
PIN(P-space Identification Number) has a single numerical argument. if two or more participating warriors have the samePINargument, they share the same P-space. if thePINpseudo-opcode is missing from a warrior's source, its P-space is strictly private. thePINargument is not normalized to[0..CORESIZE-1]before comparison."PIN 0"and"PIN CORESIZE"are therefore not the same. ๐ฆ
P-cell #0 holding the result of the last round is exempt from sharing, i.e. every warrior has its own last round cell even though the rest of its P-space may be shared. ๐
๐ฉท CDB DEBUGGER ๐ฉท
okay bestie so cdb is a line-oriented debugger. It is invoked either by specifying the -e option (enter cdb immediately), by including debugging commands in the warrior source, or by hitting Ctrl-C during the simulation. The debugger is also entered whenever a warrior terminates ("post-mortem") if execution was started with the go command. cdb is very powerful and has an overwhelming number of commands. You may want to start with only the most often used commands: step (single step execution), go (execute until breakpoint), list (look at core), trace and untrace (set and remove breakpoints), and go on to more complex ones later.
The following commands are available at the cdb prompt; commands can be abbreviated to the first unambiguous substring.
<Enter>โ repeats the last command issued at the cdb prompt. ๐helpโ displays a brief command summary.progressโ displays the status of the current game in progress.registersโ displays the current state of the simulator, including program counters and task queues.goโ runs the simulator until an instruction whose trace bit is set is executed. If there are no traced instructionsgoreturns to the post-mortem debugger.stepโ executes the next instruction in the task queue and returns to the cdb prompt.continueโ returns to the simulator to complete the game without interruptions.threadโ is similar tostepexcept that only the current task thread is traced.skip [count]โ executes the next[count]instructions in the queue silently before returning to the cdb prompt.execute [address]โ resets the task queue of the current warrior to[address]and executes it. This is useful in conjunction withedit.quitโ aborts pMARS and returns to the OS prompt.trace [range]โ sets the trace bit of the specified address or address range.untrace [range]โ clears the trace bit of the specified address or address range.moveable on|offโ specifies whether the trace bit is copied by theMOV.Iinstruction. The default ison.list [range]โ displays the specified range of core addresses, a set trace bit is indicated by'T'. Unmodified addresses (DAT.F 0,0) are shown as blank.edit [range]โ allows modifying core. The specified addresses are edited by typing in new instructions. Typing one or more spaces leaves the core address unchanged, just hitting<return>repeats the last input, and a syntax error aborts the edit. The full Redcode syntax including labels and (multi-line) EQUates can be used. Label and EQUate definitions remain in effect until the program terminates. Theeditcommand is useful for modifying warriors and trying out single instructions without having to exit and restart pMARS.fill [range]โ is similar toedit. Instructions in the specified range are replaced by one typed in instruction. EnteringDAT.F 0,0,e.g. clears the address range.search [pattern]โ searches core instructions for a text pattern in the forward direction. The next instruction matching[pattern]is displayed. The search includes the address number and trace symbol (T), is case- and space-insensitive and may contain wildcards:*(asteriks) matches any number of characters;?(question mark) matches exactly one character. E.g.search ,searches for the next non-blank address;search dat*, ?0tsearches for the next DAT instruction that is traced and has a zero B-operand value, regardless of modifier, A-operand and B-mode.write [file]โ opens a file for logging subsequent cdb output to. The logfile is closed by issuingwritewithout an argument.echo [string]โ is used mostly inside macros.[string]is echoed to the screen followed by<newline>.remark [string]โ is ignored by cdb and can therefore be used to comment macros.clsโ clears the screen. The no-display UNIX version does this by echoing an ANSI escape sequence; if this doesn't work for you, you need to change theCLRSCRstring inconfig.hand recompile.clearis a synonym forcls.display clear|on|off|nnnโ (available in display versions only) allows clearing the core display (display clear) or changing the display mode.display onchanges the display to the default mode,display off(same asdisplay 0) suspends all display updates, anddisplay nnn, wherennnis a 1 to 3-digit number, sets the display to this mode."nnn"is interpreted like the parameter to the-vcommand line option (see APPENDIX).switch [1|2]โ (available in display versions only) makes the left (1) or right (2) panel the current panel for cdb output. Without a number argumentswitchchanges to the other panel. If the right panel doesn't exist (initially, or afterclose, see below), it is created first.closeโ (available in display versions only) closes the right cdb panel (if it exists) and makes the left panel fullscreen.calc expr1[,expr2]โ is a command line calculator. Sincecalchas no side-effects other than echoing the result of expression 1 (and expression 2 if provided). In the context of cdb macros it is also used to assign values to the register variables'c'through'z'.macro [name][,file]โ loads, executes or lists macros. A macro expands to one line of cdb commands separated by the tilde character (~) (a so-called command chain, see below). The commandmacro nameexecutes the macro"name"; if"name"is left out, all currently available macros are listed.macro name,fileloads macro definitions from file"file"and executes macro"name"; again, if"name"is missing, only a listing is produced. Macro definitions are appended to the list of previously loaded definitions or replace a previously loaded macro definition with the same name. If you are trying to execute or list macros, but no macros have been loaded yet, the default macro filepmars.macis loaded automatically. The special macro fileusercan be specified to input macro definitions directly from the keyboard. Macro definitions consist of a macro name, followed by the equal sign, followed by a command (chain). The macro name can consist of any printable character excluding<space>and comma; the equal sign is only allowed at the end of a macro name. Individual macro lines have a limit of 80 characters, but macro calls inside macro expansions are allowed. Cdb can hold up to 200 macros in memory. See also the section on cdb macro programming below.if <expression>โ controls execution of commands in macros or command chains. If<expression>evaluates to zero, the next command block is skipped. A command block consists of either a single command or any number of commands bracketed by!!(loop start) and.<expression>may contain C-style comparison and boolean operators (see below). Anifimmediately preceding a loop end (![e]) can skip out of the loop.resetโ is used inside macros in conjunction withifto terminate macro execution, e.g. inside an infinite loop (...~if A==0~reset~...~!).pqueue [1|2|..|off]โ switches cdb into "process queue mode". In this mode,list,editandfilloperate on the process queue instead of the core array, i.e. you can view and modify the process queue as easily as the core array. This is especially useful for debugging complicated multi-process warriors.pqueuewithout argument uses the process queue of the current warrior. With argument1,2,.., uses the process queue of warrior1,2,.., respectively.pqueue offreturns to normal mode.wqueue [off]โ stands for "warrior queue" and is similar topqueue, except that numbers provided as arguments forlist,editandfillnow refer to warriors:list 0now shows the program counter of warrior 1,list 1that of warrior 2 and so on.wqueue offreturns to normal "address mode".pspace [1|2|..|off]โ complements thepqueueandwqueuecommands. If a number is specified, the P-space of that warrior is selected for viewing/editing. Without an argument, the P-space of the currently executing warrior is selected.pspace offreturns to core mode.
go, step, continue and thread may have a single address argument. The program counter of the current warrior is set to this address before execution continues.
The range argument of the list, trace, etc. commands has the format <start>,<stop>. Addresses <start> and <stop> are numbers, special symbols or C-style expressions including special symbols. If either <start> or <stop> is omitted, it defaults to the current address. If both are omitted, the range of the last cdb command is used. A single address (without the comma) acts on only that address. Addresses starting with a + or - are interpreted relative to the current address.
Expressions may contain the arithmetic operators -,+,*,/,% (modulo), the comparison operators ==, !=, <=, >=, and the boolean operators && (AND), || (OR), and ! (negation). Expressions may also include register variables C through Z and the assignment operator =. Operator precedence is like that of the C-language and may be overridden by parentheses. Assignment, comparison and boolean operations are mostly used with calc and if commands in macros, but can also be used in Redcode operands.
Special address symbols used in cdb commands:
.(dot) is the current address (displayed last).$(dollar) is the last core address.Ais the A value of the current instruction.Bis the B value of the current instruction.PCis the program counter of the currently executing warrior.PC1is the program counter of warrior 1.PC2is the program counter of warrior 2.LINESis the number of lines available to the cdb displayCYCLEis the current execution cycle (counted down)
In process queue (pq), warrior queue (wq) or pspace (ps) mode (see pqueue, wqueue, pspace), most of these symbols have a different meaning:
.(dot) โ the current process number (pq), warrior (wq), or P-space cell (ps) that got displayed last. the throwback one โจ$(dollar) โ the last process in the process queue (pq), the last warrior (wq), or the last P-space cell (ps). the end of the line, bestieAโ the A value of the instruction of the current process (pq), the next executing process of the current warrior (wq), or the P-space selector (ps, same as the warrior number if unshared).Bโ the B value of the instruction of the current process (pq), the next executing process of the current warrior (wq), or the P-space selector (ps).PCโ is 0. yes really, 0PC1..โ are 0.
Put an @ (ampersand) in front of a command and it won't print to your screen โ but it will still go to a logfile. Put an & in front and it kills both the screen output and the logfile output, which is lowkey iconic when all you care about are the "side-effects" of a command. And if you start a command with a <Space> character, it won't get saved to the "last-command" buffer that <Enter> recalls. sneaky, but valid
๐ COMMAND CHAINS AND MACRO PROGRAMMING ๐
You can stack several commands on one line if you separate them with the tilde character ~. These "command chains" are so useful for repeating long command sequences, because <Enter> recalls the entire chain (peep the examples below). And commands that need you to actually interact โ list, edit, fill โ will read their input straight from the chain too. <butterfly>no hands needed, slay</butterfly>
The "empty command" (two tildes back to back, or a tilde at the end of the chain) just repeats the last command in the chain. And a command that's nothing but a <Space> is a null command โ it's how you fake pressing <Enter> inside list, edit and fill. mimicry ๐
The exclamation mark ! character is a special "chain repetitor" command. The optional expression after ! tells it how many times to run the command chain that starts at the beginning of the line, or at the last !. And ! with no expression at all? It repeats until the program terminates. fr fr, forever
The symbol !! is for nested loops โ it marks the start of a command block that's gonna be repeated. That block gets closed by ![expression], and it can contain other command blocks inside it. Also: a command block that immediately follows an if command only runs if the condition is true. conditional queen behavior
With loops, subroutines (macros calling macros), variables (C..Z), expressions involving comparisons and boolean operations, and conditional execution (if), the cdb command language can be used to construct complicated macros โ for stuff like executing a warrior until a certain core address has changed, controlling the 2-panel display, automatically finding the right constants for a warrior, etc. Go look at the file pmars.mac for examples. iykyk ๐
๐ธ EXAMPLE CDB COMMANDS ๐ธ
list ,+20โ lists the next 20 instructions. twenty whole instructions, we love hertrace pc-10,pc+10โ traces 21 addresses centered around the program counter of the currently executing warrior.untrace 0,$โ clears all the trace bits.go~reg~l+a,+bโ chains these commands: execute until the next traced address or end of round, display the simulator status, and list addresses in the range A-number to B-number of the current instruction.@fill0,100~dat.f 0,0โ fills addresses 0 through 100 withdat.f 0,0, and does not echo the changed addresses to the screen. quiet mode activated ๐คซwrite trace.log~!!~step~!โ produces a continuous execution trace by repeatingstepuntil pMARS terminates, saving the output to logfiletrace.log.@l x=5~!!~@ed x~dat x,0~if (x=x+1)<$+1~!โ okay bestie this one is the moment, listen. This command chain could be useful for debugging a stone-type, self-modifying warrior, which in this example is assumed to occupy address 0 through 4. The command fills core starting at address 5 withdat 5,0,dat 6,0, a.s.o., so you can tell where a bomb that overwrites the warrior came from. And to save some typing, you can turn this command into a macro (foo=@l x=5~..).
Here's how it works, step by step:
- Assign 5 to register
xand make it the current address (@l x=5). - Start a loop (
!!) and change addressxtodat x,0(@ed x~dat x,0). - Increment
x, and ifxis then smaller than the core size ($+1), keep looping (if (x=x+1)<$+1~!).
Oh and the @ in front of the list and edit commands suppresses screen output. aesthetic and functional
@s~@4~if b<2 || b>=$-3~reset~!โ this command executes a warrior until the B-field of address 4 points to address 0 through 5. Step and make address 4 the current address (@s~@4). If the B-field is less than 2, or greater than or equal to 7996 (CORESIZE-1-3), stop execution โ otherwise keep looping (if b<2 || b>=$-3~reset~!). math girlies rise ๐งฎ
๐ SOURCE DEBUGGING DIRECTIVES ๐
Plot twist: trace bits can also be set by putting debugging commands right in the warrior source. It uses a comment format so it stays compatible with simulators that don't support source-embedded debugging commands. backwards compatible and cute, a dual threat
;debug [static/off]โ this command enables/disables all subsequent source-embedded commands. It's what you use for commenting out other source comments.;debug statichas the same effect as the commandmoveable offat the cdb command prompt. And;debugis implicitly added in front of every warrior. The last;debugor;debug staticencountered is the one that specifies whether the trace bit gets copied by aMOV.Iinstruction or not. last one wins, periodt;trace [off]โ;tracestarts setting the trace bit with the next instruction until EOF, or until a;trace offcommand shows up.;breakโ sets the trace bit of the next instruction. short, sweet, sets bits ๐
๐ BUGS ๐
None whatsoever (right). ๐ญ
Contact for bug reports and suggestions is Stefan Strack (stst@vuse.vanderbilt.edu). Please be detailed, and include a logfile of the cdb session if it applies. And if your bug reports and suggestions are about the Macintosh display and interface, those should also go to Alex MacAulay (macaulay@mundil.cs.mu.oz.au). be nice, be thorough, include receipts ๐ซถ
๐ AUTHORS ๐
The portable MARS project was initiated after discussing the ICWS'94 draft on the rec.games.corewar newsgroup. We realized we needed a portable system to try out the proposed standard and to accept, modify or reject it. The people who started portable MARS โ and who are responsible for the base code as well as the DOS and UNIX displays โ are:
- Albert Ma (
ama@athena.mit.edu) - Nandor Sieben (
nandor.sieben@asu.edu) - Stefan Strack (
stst@vuse.vanderbilt.edu) - Mintardjo Wangsaw (
wangsawm@csos.orst.edu)
Alex MacAulay (macaulay@mundil.cs.mu.oz.au) wrote the Macintosh display version. Martin Maierhofer (m.maierhofer@ieee.org) contributed the linux SVGA and X windows display. Nathan Summers (00ncsummers@bsuvc.bsu.edu) did the port to VMS. a whole squad of legends โจ
๐ ACKNOWLEDGMENTS ๐
We thank Planar (Damien.Doligez@inria.fr) for expert help with debugging and porting pMARS to different UNIX machines. We also appreciate the help of Chris Lindensmith (lind0014@student.tc.umn.edu) and Pierre Baillargeon (dak@info.polymtl.ca) with the initial Mac and Amiga ports respectively. Mark Durham (durham@ricevm.rice.edu) spearheaded development of the ICWS'94 draft, and we thank him for writing the sample interpreter code included with the draft. giving credit where credit is due, always ๐
๐ฆ APPENDIX ๐ฆ
โฆto be continued, bestie ๐
โจ PMARSV โจ
pMARSv is the DOS version of pMARS, and it comes with a graphical core display. Bestie, you get to pick between EGA/VGA graphics or plain text mode โ either with the -v command line option, or just by smashing v while the game is running. ๐
The -v option takes a three digit argument xyz:
- Digit
xsets the initial display speed and ranges from0(fastest) to7(slowest). - Digit
yis the initial display mode:0for text mode,1for standard VGA graphics,2and3for SVGA,4and5for EGA, and6for CGA graphics.
The display level z says how much gets shown:
0โ Display nothing. This greatly speeds up execution, especially when in graphics mode. speedrun era fr fr1โ Display execution of addresses. In text mode, a black0on blue background is shown for warrior 1, a black1on green for warrior 2, a.s.o.. Numbers blink in white when aDATinstruction is executed. In graphics mode, a blue square represents warrior 1, a green square warrior 2, a.s.o.. These colors are also used for other core accesses.2โ Also display write accesses. In text mode, they appear as dots; in graphics mode, they appear as two pixels, offset diagonally.3โ Also display decrements and increments. They are shown as+and-in text mode and as two pixels offset vertically or horizontally in graphics mode.4โ Also display read accesses, which appear as small dots in text mode and as single pixels in graphics mode.
The more is displayed, the slower runs the simulation. ๐ญ The argument for -v defaults to 103, i.e. speed=1, mode=text, level=3.
The text mode display is very fast, but contains less on-screen information than the graphics display. The core display and the cdb debugger run full-screen on separate display pages. two pages, no overlap, iconic
In graphics mode, core and debugger share the same screen. The mouse can be used to navigate around core when debugging is enabled: clicking a mouse button on any core location lists addresses starting there. The mouse cursor follows the current program counter when in single step mode. ๐ฑ๏ธ
In both graphics and text mode, the cdb display can be divided into two side-by-side panels. You can switch between panels with the switch command (or the <Tab> macro) and close the right panel with close (or the <Shft-Tab> macro). Extended (function keys, arrow/page keys, ALT keys, etc.) and control keys generate macro calls at the cdb prompt; some of these "hot key macros" have been defined in pmars.mac; you can easily change them or add more with a text editor. E.g. <PgDn> and <PgUp> keys currently invoke macros that scroll through core one screen at a time.
A white line at the top of the display, called the time meter, indicates the time required to finish the current simulation. The amount of time depends on the number of warriors still alive in the arena. After a warrior dies it no longer needs simulation time so the required time to finish the simulation becomes less. On the time meter this is indicated by a discontinuity. One can count the number of dead warriors in the arena by counting the number of discontinuities on the time meter. math but make it visual โจ
Just below, the length of "process meters" in the color of the warriors they represent show how many processes each warrior has running.
The following keys are available at the core display screen:
0..4โ selects the display level (see above).vโ switches from text display to graphics display and vice versa.>โ increases the display speed.<โ decreases the display speed. The current speed is indicated by a red bar in graphics mode.dโ enters thecdbdebugger. "Debug" on the graphics menu bar is highlighted in red insidecdb.<space>โ (alsor) refreshes the core display.<escape>โ (alsoq) exits to DOS.
You can define additional keys and commands associated with them by defining "key-x" macros ("x" is any printable character). E.g.:
key-p= progress~registers~continue
Function-key and other macros can also be invoked from the core display.
๐ CURSES DISPLAY ๐
The curses display is very similar to the DOS text mode display. There are separate pages for core and debugger. There is a status bar at the bottom of the core display:
Rave [0]: 1 Lucky 3 [1]: 3702 Cycle: 72967 R: 2/5 (0 0 1)
The display symbol that indicates execution is shown in brackets after the warrior name. The number after the colon shows the number of processes active. The "2/5 (0 0 1)" means that this is round 2 of 5; the result so far is one tie. Only cycle and round information is shown if more than two warriors are run. condensed info, still ate ๐
There is no "hot key" user interface during the core display, but you can enter the debugger by hitting Ctrl-C and clearing the display, changing the display mode, etc. from within cdb. Only the first and third digit of the -v option and display command argument, namely the display speed and level, have an effect (see PMARSV above). The display speed setting (0=fastest, 7=slowest) adjusts the screen refresh rate; depending on the size of your display, movement in core may appear "jerky" at fast speeds. jerky core movement is a vibe, not a bug bestie Control keys at the cdb prompt generate a macro call like in the DOS versions.
If you redirect standard input (by supplying a - filename or parameter file), all interactive input is disabled.
๐ MACINTOSH DISPLAY ๐
MacpMARS is a Macintosh version of pMARS with a graphical core display and standard Macintosh user interface. It has two windows, the Core window and the Text window. The display of the core uses four patterns for each warrior (black and white backgrounds respectively) to show what is happening in the core:
ยด/ยดwhen the core location is written to (including incrementing and decrementing);ยด\ยดwhen a process has died at the core location;ยด-ยดwhen a process has executed at the core location;ยด|ยดwhen a process is waiting to execute at the core location.
If you click on a core location in the Core window while a battle is being run, the contents will be displayed in the Text window. ๐ฑ๏ธโจ
Two warriors can be in memory at any one time. To assemble a warrior choose "Choose Warrior n..." from the File menu. To remove the warrior from memory choose "Remove Warrior n...". You can modify the settings used by choosing "Preferences..." (this can only be done when no battle is being run). Alternatively, you can type in a command line in the same way as if you were typing from a unix prompt (if you're used to that sort of thing) by choosing "Command Line...". The Edit menu is just the normal Macintosh Edit menu and can be used to cut and paste text in the Text window and dialogs. The items in the Play menu are fairly self-explanatory: "Go" starts (or continues) a battle; "Step" executes one instruction and enters the debugger; "Halt" halts the battle and enters the debugger; "Abort" aborts the battle. The Window menu is used to show and bring either of the two windows to the front of the screen.
The cdb commands display, switch and close are not available in MacpMARS. not me finding out my faves are missing ๐ญ
Note: to use very large core sizes (up to about 65000) and process limits you may need to increase the memory partition for MacpMARS. To do this, choose"Get Info"from the File menu in the Finder and set the preferred memory size to about1200K.
๐ EXIT CODES ๐
The following is mainly useful for people who write scripts or batch files for pMARS. Upon normal exit, the program returns 0. Below is a listing of what the abnormal exit codes mean. Your operating system may not support negative exit codes; in this case you have to convert the value to its unsigned counterpart.
-4 graphics error
-3 trying to execute 80386 code on a lesser processor
-2 memory allocation error
-1 serious program logic error, contact developers
1 file not found
2 command line error
3 assembly error
4 user aborted program
The exit codes of the VMS version conform to the VMS standard. The -Q (Query) command line option (see OPTIONS) allows you to customize the pMARS exit code. E.g. "pmars -Q 1000" returns the current pMARS version. Below the -Q arguments and what the resulting exit codes mean.
1..Wโ exit code is score of this warrior,1: first in result output,2: second, a.s.o.. If the-ooption is also given,"1"gives the score of the highest scoring warrior, etc..101..1Wโ returns the number of this warrior in the result output. Usually-Q 101returns1,-Q 102returns2etc., so this is not very useful. If you also specify the"-o"(order results) option,-Q 101returns the position of the highest scoring warrior on the command line,-Q 110the position of the 10th highest scoring warrior, etc..1000โ exit code is the pMARS version in the same format as the predefinedVERSIONvariable.1001โ returns the pMARS "variant":0if the program was compiled with the SERVER option (no debugger),1with debugger but without display,2with debugger and core display.1002โ returns a combination of version and variant:10*variant+version.1003โ the exit code is the core address size in bytes. On a 32-bit CPU, this issizeof(int), usually4. With SMALLMEM compilation, core address size issizeof(unsigned short), usually2.2000โ returns how many warriors share one or more P-spaces. A value of4, e.g. means that either four warriors share one P-space, or that two pairs of warriors share two P-spaces.
and that's the whole page bestie, you made it all the way to the end ๐ซถ This one's from pMARS v0.9.5, dated January 3, 2026, and it lives in section 6 of the manual โ go forth and simulate, you absolute icon. ๐โจ๐๐ฆ๐ธ
๐ฆ where this page comes from
- nixos 26.05: pmars 0.9.5
- nixpkgs unstable: pmars 0.9.5
- ubuntu resolute: pmars 0.9.5-1 ยท GPL-2.0-or-later
- ubuntu stonking: pmars 0.9.5-1 ยท GPL-2.0-or-later
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms