The goal of radiation hardening is to make a program still work after you remove a byte. However, what if a skilled competitor is purposefully trying to mess with you?

In this game, each bot will take turns removing one character from the next bot down the line. If the bot fails to produce valid output next turn you gain one point. The bot with the most points at the end wins. Simulation will be run several times with different orders to reduce randomness. Final score will be the median of each iteration.

If a program reaches 0 bytes in length it will always be eliminated, regardless of if it produces valid output or not. Otherwise it would be unbeatable.

Note the goal of the game is to get kills, not necessarily to survive the longest. You can be the last one living but if you haven't eliminated anyone you can still lose. Of course, it's impossible to gain any more points after being eliminated.

## IO format

Since I want many languages to be able to compete, I will need to enforce strict IO rules to make it possible for me to run each program. Thus, IO will be purely using STDIN and STDOUT.

The input of a program is the full source code of the next program, piped over STDIN.

The output is the 0-based index of the byte you are trying to remove, then a space, then the byte value. For example if the victim was "abc" a valid output would be "1 b". A optional trailing newline is allowed but any other extra output is invalid. If the character after the space does not match the victim's byte at that position the output will be considered invalid.

## Language selection

This will be a multi language KOTH. Languages must be free to participate and able to run inside a Ubuntu Linux Docker container. Please include a installation script and a script that can run your program. Your script should also install libraries or packages include a script that installs them.

Languages purposefully designed to beat this challenge are disqualified.

Programing languages must be capable of reading the code form a file, taking input from STDIN, and outputing to STDOUT, just because they are hard for me to run reliably otherwise. I may make exceptions to this rule, mostly if you have sufficiently detailed setup and run instructions. Bots posted before this edit are exempt.

# Example Bot - C

Code:

///////////////////////////////////////////////////////////////////////////////////
k,j;main(i){for(j=getchar();i<255&&k>=0;i++){k=getchar();if(!((k&168)^'(')){printf("%d %c",i,k);exit(0);}}printf("0 %c",j);}


Base 64 (Only needed if you have unprintable characters or want to use a SBCS)

Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KayxqO21haW4oaSl7Zm9yKGo9Z2V0Y2hhcigpO2k8MjU1JiZrPj0wO2krKyl7az1nZXRjaGFyKCk7aWYoISgoayYxNjgpXicoJykpe3ByaW50ZigiJWQgJWMiLGksayk7ZXhpdCgwKTt9fXByaW50ZigiMCAlYyIsaik7fQ==


### Installation:

apt-get install gcc -y


### How to run: (Include any command line arguments your program needs here)

mv code code.c
gcc code.c -o code
./code


### Explanation

Removes the first instance of ['(', ')', ',', '-', 'h', 'i', 'l', 'm'] from it's target. If none is found remove the first character.

## Leaderboard (Last updated (FINAL UPDATE) 29-08-2022 6:48 UTC)

window.location.href = "https://mousetail.github.io/koth-leaderboard-pages/results.html"

You are free to edit and submit more bots, but if you want to appear on the leader-board you need to run the controller yourself. I'd be happy to accept pull requests to the ranking repo.

## Other rules

1. Program length can be up to 256 bytes
2. No opening files, networking, or any other IO. Writing to STDERR is ok.
3. It's ok to try to crash programs by including NULL bytes and invalid unicode etc. in your source code.
4. Programs must take <1s to complete. Taking longer than 2s is considered invalid output, though try to keep is less than 1s to account for uncertainty.
5. It's ok to submit multiple bots as long as they are not specifically designed to support each-other.
6. Command line arguments are allowed, but no cheating by putting the "real" code in the command line arguments.
7. Any negative votes bots will not participate until they gain more votes. This is intended to help moderate the points above when subjective.
• @Jonah each round each bot has 1 less character, so it will be different Aug 18 at 16:26
• The positive votes idea is very clever, I'm surprised no one's thought of it Aug 19 at 9:22
• Red = more frequent, blue = less frequent. If a letter is red in the vulnerable (top) part it means this letter is removed a lot. The bottom part it's how often that letter was the last removed before the bot died @thejonymyster Aug 19 at 17:32
• are programs ever run against themselves? if not, id be curious to see what would happen lol but obviously it isn't super pertinent to the challenge if it isn't already part of it Aug 22 at 22:14
• Happy Birthday! Aug 26 at 9:57

# A Pear Tree, Distributed Damage

A Pear Tree isn't actually that good at this challenge as languages go – its general efficiency at is because it's good at detecting damage, but it has no real way to repair it, so the best you can do is to write the same program several times in a row and hope that at least one copy stays undamaged.

Nonetheless, I'm entering an answer by popular demand :-)

This program contains unprintable characters (thus no TIO link). However, it looks something like this (except that ��\n are actually three non-newline nonprintable characters); see below for a hex dump:

l=length;(.618*l)=~/\..*/;i=int($&*l);$_=i." ".substr$_,i,1#-�� l=length;(.618*l)=~/\..*/;i=int($&*l);$_=i." ".substr$_,i,1#-��
l=length;(.618*l)=~/\..*/;i=int($&*l);$_=i." ".substr$_,i,1#-�� l=length;(.618*l)=~/\..*/;i=int($&*l);$_=i." ".substr$_,i,1#-��


## Hexdump

This is the actual submission, as an xxd reversible hex dump.

00000000: 6c3d 6c65 6e67 7468 3b28 2e36 3138 2a6c  l=length;(.618*l
00000010: 293d 7e2f 5c2e 2e2a 2f3b 693d 696e 7428  )=~/\..*/;i=int(
00000020: 2426 2a6c 293b 245f 3d69 2e22 2022 2e73  $&*l);$_=i." ".s
00000030: 7562 7374 7224 5f2c 692c 3123 2db4 9616  ubstr$_,i,1#-... 00000040: 6c3d 6c65 6e67 7468 3b28 2e36 3138 2a6c l=length;(.618*l 00000050: 293d 7e2f 5c2e 2e2a 2f3b 693d 696e 7428 )=~/\..*/;i=int( 00000060: 2426 2a6c 293b 245f 3d69 2e22 2022 2e73$&*l);$_=i." ".s 00000070: 7562 7374 7224 5f2c 692c 3123 2db4 9616 ubstr$_,i,1#-...
00000080: 6c3d 6c65 6e67 7468 3b28 2e36 3138 2a6c  l=length;(.618*l
00000090: 293d 7e2f 5c2e 2e2a 2f3b 693d 696e 7428  )=~/\..*/;i=int(
000000a0: 2426 2a6c 293b 245f 3d69 2e22 2022 2e73  $&*l);$_=i." ".s
000000b0: 7562 7374 7224 5f2c 692c 3123 2db4 9616  ubstr$_,i,1#-... 000000c0: 6c3d 6c65 6e67 7468 3b28 2e36 3138 2a6c l=length;(.618*l 000000d0: 293d 7e2f 5c2e 2e2a 2f3b 693d 696e 7428 )=~/\..*/;i=int( 000000e0: 2426 2a6c 293b 245f 3d69 2e22 2022 2e73$&*l);$_=i." ".s 000000f0: 7562 7374 7224 5f2c 692c 3123 2db4 9616 ubstr$_,i,1#-...


### Strategy/algorithm

Most of the submissions to this challenge so far use one of two hardening strategies: either the "core and chaff" strategy, in which only a part of the program has any meaning and the rest is just junk to distract the opponents, or a more traditional approach which has redundant copies of all the important data and will attempt to find and use an undamaged copy.

Distributed Damage works by trying to spread its deletions evenly over the target program; against "core and chaff" this is probably a bit more likely to hit the core than choosing randomly (the first shot is no better than random, but subsequent shots avoid areas that didn't kill the opponent, and are thus more likely to aim for places that could); and against "redundant copies" this is more likely than random to damage every copy and thus prevent the program being repaired.

In order to work out where the program has previously attacked, the attack position is based entirely on the length of the target program (thus, if the program is, e.g., 219 bytes long, it's possible to determine where the previous attack was via knowledge of which byte is attacked in a 220-byte program). The length of the target program is multiplied by (an approximation of) the golden ratio, and the fractional portion of the result is used to give the target to attack – this naturally leads to the attack positions being spread in a distributed way across the target program.

This algorithm was inspired by nature – many plants use the same algorithm to, e.g., place their leaves in such a way that they aren't blocking each others' view of the sun, because it makes it possible to distribute locations approximately evenly even if you don't know in advance how many of them there will be, and the calculation is very simple.

The radiation hardening isn't anything special, just a "redundant copies" approach, with four copies of the 64-byte program (256 bytes in all). The last four bytes of each copy are a checksum; A Pear Tree refuses to run programs unless they have a section that checksums correctly, and will run that section first (thus, if any of the four copies is undamaged, that copy runs). Unfortunately, this means that there's no way to continue if all four copies get damaged, because the program won't parse at all. (It might be possible to put a secondary checksum around the portion from i= onwards so that at least the interpreter would have something to run if every copy got damaged, but that would be unlikely to get extra kills, and I ran out of bytes so there's no room for extra checksums.)

I'm hoping that this answer will do particularly well defending against, and decently at attacking, "tiny core" programs that aim purely for survival rather than kills, and don't have any algorithm for choosing targets – such programs nearly always choose targets near the start, and this program is unlikely to stop working unless all four quarters of it get hit (in particular, the last quarter has to get hit). Programs like Almost Rare that are designed to detect programs consisting of redundant copies and damage them all in the same way are likely to beat this very quickly, though.

## Installation

Install perl if necessary (it's installed by default on Ubuntu).

Install Digest::CRC (Ubuntu package libdigest-crc-perl).

To run the program, use perl apeartree-v2.pl programfilename. A Pear Tree reads in binary (rather than Unicode) by default, so there's no need to worry about changing the default encoding.

### Explanation

The interpreter for A Pear Tree will rotate an undamaged portion of the program to the start (determined by looking for a valid checksum). If it can't, that's a syntax/checksum error (a partridge).

If it finds an undamaged portion, that portion will do the following:

                       # {implicit input, reading all of stdin into $_} l=length; # assign length of {the input} to l, as shorthand (.618*l) # multiply the length by 0.618 =~/\..*/; # regex, matching from . to end of string # i.e. this matches the fractional portion i=int( # assign to i the value, truncated to integer, of$&*l);             # the string matched by the regex, times l
$_=i # assign the following to$_: i,
." ".                # concatenated with " ", concatenated with
substr$_, # the substring of the input i,1 # starting at i, with length 1 # # comment to newline (i.e. end; there is no newline) # {implicit output of$_}


It's a bit surprising that regexing numbers (i.e. converting them to strings and looking for the decimal point) is the tersest way to extract the fractional portion, but I haven't found anything better.

One change for golfiness, necessary to get this down to 64 bytes: the golden ratio is approximately equal to 1.618, not 0.618, but because we're taking the fractional portion of the result it doesn't matter what the integer portion of the value we're multiplying by is.

• I was hoping for a pear tree answer Aug 19 at 18:43
• I'm getting this error, it's probably a easy fix but I don't know enough about perl: an't locate Digest/CRC.pm in @INC (you may need to install the Digest::CRC module) (@INC contains: /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.34.0 /usr/local/share/perl/5.34.0 /usr/lib/x86_64-linux-gnu/perl5/5.34 /usr/share/perl5 /usr/lib/x86_64-linux-gnu/perl-base /usr/lib/x86_64-linux-gnu/perl/5.34 /usr/share/perl/5.34 /usr/local/lib/site_perl) at apeartree-v2.pl line 76. BEGIN failed--compilation aborted at apeartree-v2.pl line 76. Aug 19 at 19:11
• @mousetail: Looks like I was mistaken about which packages shipped with Perl. I've added installation instructions for Digest::CRC to the post – fortunately it's packaged on Ubuntu. Aug 19 at 19:34
• "A Pear Tree isn't actually that good at this challenge as languages go". And yet, this bot is completely dominating in 1st place. Aug 26 at 2:04
• Does modulo 1 not work to get the fractional part? Aug 26 at 22:57

# Jelly with LANG=C.ISO-8859-1, The Burrowing Wheel

⁸

¹¹»¹«
¹
ṛ⁸ẈMị⁸ẈMị⁸ẈMị⁸ẈMị⁸ẈMị⁸ẈMị⁸ẈMị⁸ẈMị

¹

¹ ḷ

¹« »

¹

«a

oao

«»«»« »«»«» « »« »

ḷ¹¹ ¹

ṛ
“““““““““““““““““““““““⁹ƈ€µTịµJḟⱮịṙṢṪ€ɗ€JŒgẈNMX©ịṭ®_1¤KȮị““““⁹ƈ€µTịµJḟⱮịṙṢṪ€ɗ€JŒgẈNMX©ịṭ®_1¤KȮị““““⁹ƈ€µTịµJḟⱮịṙṢṪ€ɗ€JŒgẈNMX©ịṭ®_1¤KȮị”µµẈMị¹¹¹⁺VVV⁺


Try it online!

Exits by crashing, putting junk on standard error, but standard output should be correct.

I don't know how fast the OP's computer is, and it matters for this submission – this program takes around 0.5-0.6 seconds to run on my computer and on TIO, so may go over the time limit if the OP's computer is significantly slower.

Jelly uses a custom code page, so here's a hexdump (xxd format) of what this looks like after encoding:

00000000: 887f 7f81 81fb 81fa 7f81 7fde 88bb 4dd8  ..............M.
00000010: 88bb 4dd8 88bb 4dd8 88bb 4dd8 88bb 4dd8  ..M...M...M...M.
00000020: 88bb 4dd8 88bb 4dd8 88bb 4dd8 7f7f 817f  ..M...M...M.....
00000030: 7f81 20da 7f7f 81fa 20fb 7f7f 7f20 817f  .. ..... .... ..
00000040: 7f7f 7f7f fa61 7f7f 6f61 6f7f 7ffa fbfa  .....a..oao.....
00000050: fbfa 20fb fafb fafb 20fa 20fb fa20 fb7f  .. ..... . .. ..
00000060: 7fda 8181 2081 7f7f de7f fefe fefe fefe  .... ...........
00000070: fefe fefe fefe fefe fefe fefe fefe fefe  ................
00000080: fe89 9c0c 0954 d809 4aeb 9560 d8f3 b7ce  .....T..J......
00000090: 0c9d 0c4a 1367 bb4e 4d58 06d8 e008 5f31  ...J.g.NMX...._1
000000a0: 034b cad8 fefe fefe 899c 0c09 54d8 094a  .K..........T..J
000000b0: eb95 60d8 f3b7 ce0c 9d0c 4a13 67bb 4e4d  .........J.g.NM
000000c0: 5806 d8e0 085f 3103 4bca d8fe fefe fe89  X...._1.K.......
000000d0: 9c0c 0954 d809 4aeb 9560 d8f3 b7ce 0c9d  ...T..J........
000000e0: 0c4a 1367 bb4e 4d58 06d8 e008 5f31 034b  .J.g.NMX...._1.K
000000f0: cad8 ff09 09bb 4dd8 8181 818a 5656 568a  ......M.....VVV.


## Strategy/algorithm

This program checks to see which of the various possible irradiated versions are shortest when compressed, and chooses a byte to delete that produces one of those most-compressible targets.

The idea behind this algorithm is:

• Repetitive chaff (like ///////////////) compresses very well, so the algorithm avoids damaging it (which is generally a useless thing to do, programs with long repeating runs of characters rarely care about the exact number);
• Redundant parts of a program (that could survive damage) are often repeated multiple times; the algorithm will tend not to damage those because damaging one copy will make the program less compressible, rather than more;
• If one redundant part of a program does have to be damaged (e.g. because the entire program is made of them), the algorithm will then tend to try to damage other parts in the same way;
• If a program is formed of some completely random chaff, plus some meaningful code, the algorithm is more likely to target the meaningful code; this is because meaningful code often contains near-repeats (and the algorithm will tend to make them more exact repeats, thus breaking the code), whereas completely random chaff doesn't, and so there's more of a compressibility gain to attacking the meaningful code than the chaff.

Jelly doesn't have compression (as opposed to decompression) builtins, so in order to work out what the most compressible irradiated versions are, I had to write my own compressor. The idea is to take a Burrows–Wheeler transform of the input (this is the same general technique that bzip2 uses) – take all cyclic permutations of the irradiated program, sort them, and look at the last bytes of each permutation in their sorted order. If a substring appears repeatedly, then imagine the cyclic permutations that split that substring between the start and end of the string; for each copy, the portion that's at the start will be the same, so they'll sort next to each other, and thus the portion at the end (which is also the same) will also sort next to each other, creating runs of the same value in the list of the last bytes.

Burrows–Wheeler-based compression works by run-length-encoding that list of the last bytes, but to work out which irradiated program is the most compressible, there's no actual need to go through with the rest of the compression; it's possible simply to count how many runs there are. This submission does that, looks for the irradiated version with the fewest runs, and outputs whichever byte will produce that particular irradiated version.

Often there'll be more than one possibility, in which case this program picks at random.

The TIO! link above shows this program attacking NÜL tränslätör – there are only two target bytes it will attack, the r of tr and the first " of printf "%d ". Both of these bytes are fatal to the target, so the algorithm is making good choices there. (The attack on the printf quotes is because the other printfs don't use quotes, so it's trying to make all the printfs the same. I'm not totally sure what causes the attack on tr, but suspect that it's related to most uses of r being in an expression (r+1) or to spell printf – the algorithm has thus correctly identified meaningful code that doesn't have a redundant copy elsewhere in the program.)

## Installation

There's no change from my other Jelly answer. So that this answer is complete, I'm repeating the instructions here:

• Install python3 and pip3 (on Ubuntu, python3 and python3-pip); also git if you haven't already.
• You will need to run from an account with a real home directory – if your container is so stripped down that it doesn't have one, create one with, e.g.,
mkdir ./home
export HOME=$(readlink -f ./home)  • Install Jelly using the instructions at https://github.com/DennisMitchell/jellylanguage: git clone -q https://github.com/DennisMitchell/jellylanguage.git cd jellylanguage pip3 install --upgrade --user .  To run programs: LANG=C.ISO-8859-1 ~/.local/bin/jelly f programfilename, where programfilename is the name of the program you're running. Standard input can be piped in or redirected from a file, as normal. ## Explanation ### Radiation hardening The first half of the program is just chaff, intended to create false-positives for most programs that try to aim their attacks, and to take ages to chew through for programs that scan from the start of the program in sequence – it's possible to delete the whole thing and nothing will change. Almost everything here is a) the empty string, or b) a function that always returns one of its arguments literally, so even if some of this code somehow ends up running, it won't do anything. However, Jelly starts execution from the start of the last line of the program, so you need to start deleting newlines in order to even get the code to run. The radiation hardening is done using three copies of the core program logic – the longest will be run. As an improvement over my previous Jelly submission, I separated them with multiple “ marks (which in this context are kind-of like commas) – in order to cause two copies to be combined and become longest, you need to delete all the “ marks in that section. Most likely, it's easier to disrupt the program by damaging all three copies separately than by causing two to be combined. I didn't radiation-harden the code that selects an appropriate copy to run, but it's only four bytes long and one is hardened (as ¹ is a no-op in most contexts, making it safe to add redundant copies of it), so hard to hit unless aiming at this program in particular: ẈMị¹ Ẉ Take the length of each program in the list M Find the indexes of the maximums (i.e. longest programs) ị Index back into ¹ the original list  This gives us a list of the longest programs, which is subsequently evaluated using V. The programs actually get concatenated together by V, so there's an intentional crash to exit before the program runs a second time and produces output again. ### Target selection ⁹ƈ€µTịµJḟⱮịṙṢṪ€ɗ€JŒgẈNMX©ịṭ®_1¤KȮị ⁹ € Form a list of 256 elements ƈ read from standard input T Find the truthy elements µ i and select them J Take the indexes of the elements Ɱ For each index ḟ produce a list of indexes that omits it µ ị Index back into the input ɗ€ On each of those lists, do: ṙ J rotate it by all possible amounts Ṣ sort the rotated lists Ṫ take the last element € of each of the rotated lists Œg Group consecutive equals in {each list} Ẉ Take the length of each list NM Find all indexes of the minimum value X Pick one at random © and store it in ® ị Take the {input character} at that index ṭ Prepend ®_1¤ ® - 1 K separated by a space Ȯ Output the result ị Index {using a string}, crashes  The ṙ … J is actually slightly buggy – the J is measuring against the length of the original program, not the length of the irradiated version, so one of the rotated lists ends up being added twice. However, this ends up having no impact on the results, because the two identical lists will sort next to each other, and their last elements are the same, thus end up in the same run of consecutive equals and don't change the total number of runs. # Jelly with LANG=C.ISO-8859-1, Almost Rare ““““““⁹ƈ€µTịµṢœ-QŒrṪÐṂFX©⁸ẹX_1⁶®⁸ị“⁹ƈ€µTịµṢœ-QŒrṪÐṂFX©⁸ẹX_1⁶®⁸ị“⁹ƈ€µTịµṢœ-QŒrṪÐṂFX©⁸ẹX_1⁶®⁸ị“⁹ƈ€µTịµṢœ-QŒrṪÐṂFX©⁸ẹX_1⁶®⁸ị“⁹ƈ€µTịµṢœ-QŒrṪÐṂFX©⁸ẹX_1⁶®⁸ị“⁹ƈ€µTịµṢœ-QŒrṪÐṂFX©⁸ẹX_1⁶®⁸ị“⁹ƈ€µTịµṢœ-QŒrṪÐṂFX©⁸ẹX_1⁶®⁸ị”¹¹LÐṀoo¹¹VVV”¹¹LÐṀoo¹¹VVV”¹¹LÐṀo¹¹VVV  Try it online! Hexdump (xxd reversible hexdump format, decode with xxd -r): 00000000: fefe fefe fefe 899c 0c09 54d8 09b7 1e2d ..........T....- 00000010: 5113 72ce 0fb3 4658 0688 d658 5f31 8608 Q.r...FX...X_1.. 00000020: 88d8 60fe 899c 0c09 54d8 09b7 1e2d 5113 .......T....-Q. 00000030: 72ce 0fb3 4658 0688 d658 5f31 8608 88d8 r...FX...X_1.... 00000040: 60fe 899c 0c09 54d8 09b7 1e2d 5113 72ce .....T....-Q.r. 00000050: 0fb3 4658 0688 d658 5f31 8608 88d8 60fe ..FX...X_1..... 00000060: 899c 0c09 54d8 09b7 1e2d 5113 72ce 0fb3 ....T....-Q.r... 00000070: 4658 0688 d658 5f31 8608 88d8 60fe 899c FX...X_1....... 00000080: 0c09 54d8 09b7 1e2d 5113 72ce 0fb3 4658 ..T....-Q.r...FX 00000090: 0688 d658 5f31 8608 88d8 60fe 899c 0c09 ...X_1......... 000000a0: 54d8 09b7 1e2d 5113 72ce 0fb3 4658 0688 T....-Q.r...FX.. 000000b0: d658 5f31 8608 88d8 60fe 899c 0c09 54d8 .X_1.........T. 000000c0: 09b7 1e2d 5113 72ce 0fb3 4658 0688 d658 ...-Q.r...FX...X 000000d0: 5f31 8608 88d8 60ff 8181 4c0f c86f 6f81 _1.......L..oo. 000000e0: 8156 5656 ff81 814c 0fc8 6f6f 8181 5656 .VVV...L..oo..VV 000000f0: 56ff 8181 4c0f c86f 8181 5656 56 V...L..o..VVV  Exits via crashing, so a lot of junk goes to stderr and must be ignored, but stdout should be correct. ## Strategy/algorithm This program looks for characters in the input program that appear more than once, but under that restriction, as few times as possible. (So the ideal is to find a character that appears twice.) It picks one of those characters at random, picks a random occurrence of it, and chooses that. The program is (unless I've missed something) radiation-hardened against any single deletion, and can frequently withstand quite a lot of random deletions (although there are ways to make it fail with only two deletions, it takes some understanding to realise what needs to be deleted). Unfortunately, Jelly by default has no byte-level I/O at all – any attempt to read invalid UTF-8 (except by shelling out to Python) will cause a crash in the read routines. This is fixable by explicitly disabling Unicode handling when running the program, using LANG=C.ISO-8859-1 as a prefix to the command. (This may produce warnings because your OS probably doesn't have non-Unicode locale data files installed nowadays, but Python should still be able to run under these conditions.) Note that the similar LC_ALL doesn't work – using this triggers a special case in Jelly which produces output encoded in Jelly's codepage, rather than the specified encoding. ## Installation • Install python3 and pip3 (on Ubuntu, python3 and python3-pip) • You will need to run from an account with a real home directory – if your container is so stripped down that it doesn't have one, create one with, e.g., mkdir ./home export HOME=$(readlink -f ./home)

• Install Jelly using the instructions at https://github.com/DennisMitchell/jellylanguage:
git clone -q https://github.com/DennisMitchell/jellylanguage.git
cd jellylanguage


To run programs: LANG=C.ISO-8859-1 ~/.local/bin/jelly f programfilename, where programfilename is the name of the program you're running. Standard input can be piped in or redirected from a file, as normal.

## Explanation

The program that actually does the work is:

⁹ƈ€µTịµṢœ-QŒrṪÐṂFX©⁸ẹX_1⁶®⁸ị
ƈ€                            Read     characters from standard input
⁹                                   256
µTị                         Remove falsey characters (i.e. past EOF)
µ                        Assign to ⁸
Ṣ                       Sort the characters,
œ-                       and remove
Q                        one occurence of each character.
Œr                  Run-length encode,
ÐṂ                 and take the (char, length) pairs with minimal
Ṫ                   last component (i.e. length)
F              Convert into a list of chars, no lengths
X             Pick one at random
⁸ẹ          Find all locations of it within ⁸
X         Pick one at random
_1       Subtract 1 (to use 0-based indexing)
⁶      {Output the location}, and a space,
®     and ®
⁸ị  Index the input into itself (i.e. crash)


This gets repeated many times as elements of a giant list literal, which is then decoded:

¹¹LÐṀoo¹¹VVV
¹¹             no-ops, prevent a crash if the L is deleted
ÐṀ          take the list elements with the maximum
L              length
oo¹¹      logical-OR with the list literal (a no-op, usually)
V     evaluate (running the program and crashing)
VV   spare Vs in case one gets deleted


The various deletions from this will generally either do nothing, or represent a program that concatenates the entire list literal into a single program and runs it (so in effect it ends up running the first copy of the program rather than the longest, i.e. least mutated, copy) – it's carefully structured to prevent syntax errors appearing as a result of deletions, e.g. Ðo is a valid command ("apply to odd elements") and thus won't cause a crash before the evaluation runs.

The decoder is also repeated, but that's mostly irrelevant / chaff to confuse other programs about what we're doing, and matters only if the ” that closes the list literal gets deleted (in that case, the second copy of the decoder is used instead).

• This throws a error: gist.github.com/mousetail/6e6849bb0b858808816bedab71610e83 Aug 18 at 18:18
• Outputted b'0 061 w\n' which isn't valid, should be at most exactly one space and the literal character value of what you deleted Aug 18 at 18:23
• The error is expected – it's the easiest way to end the program and stop it producing more output. I have noticed a mistake in the program (it's using 1-based rather than 0-based indexes, I'll have to fix that), but I'm surprised that the output you're getting is so different from the intended output – I wonder if something went wrong with encoding? (Perhaps you copy-and-pasted the program rather than using the hexdump? Jelly doesn't use UTF-8, so a copy-and-pasted program will be misencoded.) Aug 18 at 20:30
• I used the hexdump in the way you suggested, using xxd -r | base64. You can double check in the base64 version I used is correct here: codeberg.org/Mousetail/Radiation-Hardened-Koth/src/branch/main/… Aug 18 at 20:32
• I've edited the program to fix the 0- versus 1-based indexing error, but both versions of the program are working fine for me on TIO (on a simple test input) and locally (I tested on your example bot above), so I'm surprised that it isn't working in your environment – I can't think of anything that might have broken it. (The base64 looks correct.) Aug 18 at 20:41

# Ghost, Whitespace

A bot that will remove white-space from other bots, while itself being made of only whitespace.

## Code:


v
un
0r
e_

of
e

r\
}
y

g
i
e       nc

te
(s
no

l

an
i(     \w

n

la

hr
t"
t(

l

'a
.

l=
)
ie

uin'o{tts)fa:


## Base64:

ICAgIAp2IAogdW4JCgkgCQkJMHIgICAJCmVfCiAgICAKICAgIAogCiAJCgkgCQkJb2YgCiBlCgkJCQkKclwgCiB9ICAgCSAgICAgCnkJICAJCgkgIAkKZyAKIGkgICAJICAJCmUJICAJbmMKCSAgCQp0ZSAKIChzICAgCSAJIApubwkgIAkKCSAgCQpsIAoKYW4gICAJCmkoCSAgIFx3CiAKICAKCiAgCQkKbiAKCmxhIAoKaHIgICAgCnQiIAoJdCgKIAogCQpsCiAgIAkKJ2EgCgkuCQogCSAgIAkgICAgIApsPQkKICApCQogIGllCgoKdWluJ297dHRzKWZhOg==


## Disassembled

PUSH 0
DUP
RETREIVE
PUSH 1

; START MAIN LOOP
MARK 0  ; main loop

PUSH 0
DUP
; SPACE PART
RETREIVE
DUP
JLT -1
DUP
PUSH ' '
SUB
JEQ 1

; TAB PART
DUP
PUSH 9 ; tab
SUB
JEQ 1
; END TAB PART

; LINE BREAK PART
DUP
PUSH 10
SUB
JEQ 1
POP
; END LINE BREAK PART

PUSH 1
JMP 0

MARK -1

POP
POP
PUSH 0
SWAP
JMP 1

MARK 1

SWAP
WRITEN
PUSH ' '
WRITEC
WRITEC
EXIT


## Setup

I spent a long time finding a whitespace interpreter that allowed me to detect EOF and write logic for it.

apt-get install -y make
apt-get install -y g++
if [[ ! -d pavelshub-cpp ]]
then
git clone https://github.com/wspace/pavelshub-cpp.git
cd pavelshub-cpp
make
cd ..
fi


Run:

./pavelshub-cpp/wspace code

• Ouch. This one will be hard to compete against Aug 19 at 14:35

# MVP - Python 3

import sys


Try it online!

MVP - (noun) Minimum Viable Product. This bot meets all the requirements set out in the challenge with 43 bytes. It is unsurprisingly not particularly radiation-resistant.

### Installation

apt-get install python3


### How to run

Depending on how you have Python installed:

python code.py


or

python3 code.py

• Welcome to Code Golf! This would probably go against the bot's goal, but maybe adding a few hundred spaces in a comment or something could make it slightly more competitive without ruining the simplicity. Aug 21 at 1:51
• Thanks you for providing complete build instructions Aug 21 at 5:41
• I think PEP 8 recommends a blank line after imports, and spaces around the '+' operator. Aug 25 at 21:56

# Parentheses Killer - PARI/GP

### Code

/*in"(n1fo]e)itr(s-),)i=nj1sn)io#r]nnsrt()*/print(-1+i=if(a=[i|i<-[1..#s=Vec(strjoin(readstr("/dev/stdin"/*1e=a1i= o""sr==s,fia")[aVtid(ir.iddsr")i*/)))],s[i]=="("],a[random(#a)+1],random(#s)+1)" "s[i])\\)i]so)(smirc/=/o"r,tr+)1++[")=s"[id)nos]


### Installation

Just install the pari-gp package on Ubuntu.

apt install -y pari-gp


### How to run

Assume that the filename is a.gp:

gp -fq a.gp


### Explanation

Removes a random ( if there is one. Otherwise removes a random character.

PARI/GP doesn't have a built-in to read a string from STDIN, so I have to use readstr("/dev/stdin"). This only works on unix-like systems.

• Nice answer, seems to never last longer than a single round though Aug 18 at 12:53
• @mousetail I modified the code and added some comments. I hope this is allowed since there isn't any other answer yet. Aug 18 at 13:42
• Yes totally fine. You are on the board now with 1 total kill. Aug 18 at 13:49

# Befunge-98 (FBBI), Comment Skipper

Note: in the actual submission, the rs are replaced with nonprintable or invalid-UTF-8 bytes; see the hexdump below. I've used r to represent them in this post and in the TIO link, because all unimplemented commands in Befunge-98 have identical semantics to r.

50050050050050050050050050050050050050050xxxxxnnnnn#####;;;;;~~~~~:::::~~~~~-----!!!!!!!!!!;;;;;@@@@@,,,,,.....;;;;;#####\\\\\kkkkkrrrrr'''''#####-----:::::ccccc-----*****#####rrrrr!!!!!;;;;;#####-----aaaaa~~~~~+++++;;;;;#####11111kkkkkrrrrr22222+++++;;;;;


Try it online!

## Hexdump

This is the actual submission, as an xxd reversible hex dump.

00000000: 3530 3035 3030 3530 3035 3030 3530 3035  5005005005005005
00000010: 3030 3530 3035 3030 3530 3035 3030 3530  0050050050050050
00000020: 3035 3030 3530 3035 3078 7878 7878 6e6e  050050050xxxxxnn
00000030: 6e6e 6e23 2323 2323 3b3b 3b3b 3b7e 7e7e  nnn#####;;;;;~~~
00000040: 7e7e 3a3a 3a3a 3a7e 7e7e 7e7e 2d2d 2d2d  ~~:::::~~~~~----
00000050: 2d21 2121 2121 2121 2121 213b 3b3b 3b3b  -!!!!!!!!!!;;;;;
00000060: 4040 4040 402c 2c2c 2c2c 2e2e 2e2e 2e3b  @@@@@,,,,,.....;
00000070: 3b3b 3b3b 2323 2323 235c 5c5c 5c5c 6b6b  ;;;;#####\\\\\kk
00000080: 6b6b 6bff ffff ffff 2727 2727 2723 2323  kkk.....'''''###
00000090: 2323 2d2d 2d2d 2d3a 3a3a 3a3a 6363 6363  ##-----:::::cccc
000000a0: 632d 2d2d 2d2d 2a2a 2a2a 2a23 2323 2323  c-----*****#####
000000b0: 0000 0000 0021 2121 2121 3b3b 3b3b 3b23  .....!!!!!;;;;;#
000000c0: 2323 2323 2d2d 2d2d 2d61 6161 6161 7e7e  ####-----aaaaa~~
000000d0: 7e7e 7e2b 2b2b 2b2b 3b3b 3b3b 3b23 2323  ~~~+++++;;;;;###
000000e0: 2323 3131 3131 316b 6b6b 6b6b c1c1 c1c1  ##11111kkkkk....
000000f0: c132 3232 3232 2b2b 2b2b 2b3b 3b3b 3b3b  .22222+++++;;;;;


## Strategy/algorithm

Looks at characters in pairs from the start of the program. If they're:

• not equal, deletes the first character of the pair;
• equal but not // nor ##, moves onto the next pair;
• equal and // or ##, moves onto the next line.

The idea is that if programs in practical languages are using "hide where my code is" techniques rather than proper radiation-hardening techniques, we should be able to find the start of the real code. If the program starts with a large number of repetitive no-ops, we can skip over those because every consecutive pair in a long string of repeated characters is equal; if it starts with a comment marker consisting of repeated characters, that's in most practical languages probably going to be ////… \n or #####… \n and we can skip to the next line; if it starts with a comment/literal marker that doesn't consist of repeated characters (such as /*) we can in most cases simply delete the first character of the marker to uncomment the chaff code, which will also typically break a program because the chaff isn't valid code. (Python also has ''' and """ as literal markers, but these have an odd length so we damage the marker rather than the useless contents inside.) So there's a reasonable chance that the first or second character we delete will end up breaking the program we're attacking.

## Installation

Install appropriate packages for building C programs (on Ubuntu, this is build-essential), and download https://catseye.tc/distfiles/fbbi-1.0-2015.0729.zip, then:

unzip fbbi-1.0-2015.0729.zip
cd fbbi-1.0-2015.0729/
(cd src; make)


Run programs using bin/ffbi programfilename (while in the ffbi-1.0-2015.0729/ directory created during the install).

## Explanation

This is based on a technique discovered by Martin Ender for this answer, which is a little difficult to explain to people who don't know Befunge-98, but I'm going to try anyway.

It works using the x command; you can think of this command as taking a pair of coordinates interpreted as a vector, and creating something line-like (a "Lahey line") in 2D space by repeatedly moving in the direction of the vector (and the exact opposite direction) starting from itself. For example, if an x is given the coordinates (2,1), it creates the following Lahey line (which is also an actual line) in 2D space (marked with + signs), stretching out to infinity in both directions:

+..........
..+........
....x......
......+....
........+..
..........+


Unlike actual lines, though, which pass through every point on them, specifying a vector like (2, 0) gives you a Lahey line that only passes through some of the squares along it:

.+.+.+.x.+.+.+.+.


While the x command is in effect, the Befunge-98 interpreter basically acts as though all the commands that aren't on the Lahey line don't exist. This means that if we can set up an appropriate Lahey line that passes through every fifth character of the program (starting at the first x that remains in the program after radiation damage), and every character from then on (including the x) is repeated five times, any four characters can be deleted from the program and yet it will still have identical behaviour to the original version – in either case, the set of non-hidden characters from the x onwards are identical. (The idea is that before the location of the first deletion, the Lahey line passes through the first character of each set of five; between the first and second deletions, it passes through the second character of each set of five, etc., with the last character of the set being used after the fourth deletion.)

Befunge has a lot of commands that cancel the effect of x (including, most notably, x itself, plus pretty much all the flow control commands). That made this program a fairly awkward challenge, as I had to write some nontrivial program logic with most of the flow control commands missing. However, the fact that x cancels the old Lahey line before creating a new one is useful in setting up the appropriate Lahey line delta, of (5, 0). The idea is to start by putting a lot of 5s and 0s on the stack in the repetitive 050 050 050 … pattern (the stack starts with a zero on it, so the leading 0 can be omitted); each of these patterns (if non-irradiated) will be interpreted as either (5, 0) or (0, 5) depending on its distance from the top of the stack, and the interpretation of two adjacent patterns alternates between (5, 0) or (0, 5) unless radiation hits the upper copy of the pattern. Because there are many more than four copies of the pattern on the stack, there's thus guaranteed to be a (5, 0) pair on the stack somewhere if it's interpreted as pairs from the top. Also, there's nothing but 0s and 5s on the stack, so any pair must be (0, 0), (0, 5), (5, 0), or (5, 5).

Now, consider what happens when the x command gets run. If its argument is (5, 0), it creates the Lahey line that we want, and the program continues in its radiation-hardened way. If it's (0, 0), (0, 5) or (5, 5), then the Lahey line that's created misses our program altogether; (0, 5) and (5, 5) are vertical and diagonal lines that cross our program only at a single point, and the Lahey line (0, 0) is a special case that's inherently a single point. In these cases, therefore, everything in the program apart from the x we just ran gets hidden, so the interpreter has no choice but to run the x again (exiting is always explicit in Befunge), taking the next pair from the stack. Thus, with a one-liner program like this, the behaviour of x inherently looks at pairs of values at a time along the stack until it finds the (5, 0) that must exist, and thus is guaranteed to create a Lahey line that runs along the program in the correct way to radiation-harden it.

(There are many more 050 patterns in this program than are actually required for the radiation hardening to survive four deletions – the idea is to be able to survive for more than four rounds if the opponent is primarily attacking the start of the program, because most damage there is survivable; to eliminate the (5, 0) pattern entirely, a number of deletions equal to the number of 5s is required.)

### How to do flow control

When writing the main body of the program, because almost all flow control commands cancel the Lahey line, ; … ;# and kr are pretty much all I had to work with.

; … ; is a jump, and adding #s in various places controls whether the jump is taken or skipped when executing the code in forward and/or reverse order (it also sometimes has the unfortunate side effect of skipping one character beyond the end of the jump, because # is a skip command, but this is easy to work around by repositioning characters; it just makes the program harder to read).

kr is a method of creating a conditional without breaking the Lahey line, but it's very quirky (the semantics of k are famously confusing). This combination pops the stack, then does nothing if a 0 was popped, reverses the execution direction if an odd or negative number was popped (for different reasons in the two cases), and its semantics are too complicated to easily describe if an even positive number was popped – this program therefore uses only the arguments 0 and 1, to keep the behaviour of kr easy to understand.

r on its own reverses the execution direction unconditionally, which was useful in one place (as #r, which reverses the execution direction only if it's currently going to the left).

As usual for Befunge-98, it's possible to replace r with any invalid command, so I picked NUL, plus two high-bit-set characters that aren't valid UTF-8, in the hope of confusing programs that don't have binary-safe input routines. (FBBI itself is binary-safe if run on a Unix-like system, like the one being used in this challenge.) The command in question is nonetheless written as r in this post, as that's the "official" name for it.

### Doing the actual work

Once the x command gets hit, here's what the remaining program along hte Lahey line looks like, and how it works (there's also some junk 0s and 5s at the start but they never again get executed):

xn#;~:~-!!;@,.;#\kr'#-:c-*#r!;#-a~+;#1kr2+;
x                                            establish Lahey line
n                                           clean stack (pop all the 5s)
#;                                         jump label, no-op right now


From this point onwards, the element currently on the top of the stack (which at this point is a 0 because the stack has just been cleaned) counts the number of bytes that the program has read.

xn#;~:~-!!;@,.;#\kr'#-:c-*#r!;#-a~+;#1kr2+;
:                                       copy it
-                                     subtract
!!                                   cast to bool (like in C)
;   ;#                             jump … to jump label + skip
kr                          reverse direction if truthy


A truthy value at this point means that the two bytes we read were different, so it's time to select the first of the two bytes and exit the program. Top of the stack at this point is the first of the two bytes; the second stack element is its index (because it's still unchanged from the start of the main loop).

xn#;~:~-!!;@,.;#\kr'#-:c-*#r!;#-a~+;#1kr2+;
\                            swap
;#                            jump label, no-op going left
.                              output integer then space
,                               output raw byte
@                                exit program


Very convenient that Befunge's "output integer then space" command is usable in this challenge (because it requires a space after the integer)! If the format didn't allow/require a space there, the integer-to-decimal conversion would take up much, much more room and probably reduce the amount of radiation hardening available as a consequence.

If the two bytes the program read are the same, the program continues by checking to see if they're // and/or ##, via arithmetic on character codes:

xn#;~:~-!!;@,.;#\kr'#-:c-*#r!;#-a~+;#1kr2+;
'#-                       subtract char code of #
:  *                   multiply by (itself
c-                      minus 12)
#r                 no-op if going right
!                logical not
;     ;#        jump … to jump label + skip
kr     reverse direction if truthy


The direction reverse here happens if, in C syntax, !(d*(d-12)), where d is the first byte of the pair minus the character code of #; # and / have character codes that differ by 12, so this is true if the byte is # or / (the multiplication * is being used like a logical AND). In this case, the strategy is to skip until finding a newline. The top of the stack at this point is the byte counter, because everything else has been popped, and that gets update while looking for the newline:

xn#;~:~-!!;@,.;#\kr'#-:c-*#r!;#-a~+;#1kr2+;
+  1       add 1 to top of stack
;#        jump label, no-op going left
-a            subtract 10
;#              jump label, no-op going left
!                logical not
r                 reverse direction
!                logical not again
;     ;#        jump … to jump label + skip
kr     reverse direction if truthy


In other words, the program adds 1 to the byte counter, then reads the next byte, and continues doing this until a newline was read. (This shares some of the code from the previous case – in that case, the ! is executed once, so that the loop is exited/not entered if the character isn't / or #, but in this loop, the same ! is executed twice, so that the loop is exited if the character is a newline. In one-line Befunge-98, opportunities like this to use the same character in both directions are rare, but fun when they happen.)

If the byte pair was something other than // or ##, or when the newline has been found, the program's main loop continues:

xn#;~:~-!!;@,.;#\kr'#-:c-*#r!;#-a~+;#1kr2+;
2+   add 2 to top of stack
#;                                      ;  jump … to jump label


This skips over the xn at the start, and also skips over any of the 0s and 5s that happen to fall on the Lahey line. (In Befunge-98, execution wraps, but it wraps along the Lahey line rather than toroidally around the program, so the same set of characters will be executed after the wrap; the program's length modulo 5 is irrelevant.)

The program "forgot" to add 2 to the byte counter after the pair was checked, so it gets done here; the reason for postponing it is that less stack manipulation is needed to set it here (because there's no need to remember the first character of the pair at this location in order to check whether it's / or #, so the byte counter is the only thing on the stack at this point), and postponing it still produces the correct results because addition is commutative, so it doesn't matter whether we add the 2 before or after adding the 1s. (The skip-to-newline loop doesn't actually inspect the byte counter, just increment it.)

This program doesn't actually work for all inputs – I didn't add any code to handle EOF, rather the hope is that it won't be given input for which the algorithm reaches EOF before reaching a termination condition. I think this is probably a reasonable tradeoff – code to handle EOF given the stringent restrictions on control flow would make the program much longer and thus reduce the amount of radiation it could withstand, as I'd have to use a higher-frequency Lahey line to fit it all into 256 bytes.

• Note that #.......\n is also a commment Aug 19 at 14:34
• @Seggan If the start-of-comment marker isn't doubled, then it's probably possible to break the target program by removing the leading #,dumping the contents of the comment into the program, so there's no need to skip the comment in that case. Aug 19 at 14:37
• Ok this hangs after it has taken some damage, will need to modify the controller so it can kill a running process Aug 19 at 15:59
• That doesn't surprise me – an infinite loop is quite a likely consequence of damage in Befunge-98, as the vast majority of error conditions reverse the flow of execution rather than exiting the program. Aug 19 at 16:02
• Ok I got it working now. Interestingly it seems to have formed a symbiotic relationship with the example python bot, moving it from last to second place. Aug 19 at 16:12

# Vyxal, The Terrible Bot

□⁋□⁋###□⁋□⁋
;;}□⁋□⁋□⁋ ėλntt¶ntt=¬;;;Ḋƛ'kwntc¬; λ\#\#\/\#\/JJJJnttc¬;Ẏ;;;Þf℅h :::: □⁋i \   pJ
;;}□⁋□⁋□⁋ ėλntt¶ntt=¬;;;Ḋƛ'kwntc¬; λ\#\#\/\#\/JJJJnttc¬;Ẏ;;;Þf℅h :::: □⁋i \   pJ
;;}□⁋□⁋□⁋ ėλntt¶ntt=¬;;;Ḋƛ'kwntc¬; λ\#\#\/\#\/JJJJnttc¬;Ẏ;;;Þf℅h :::: □⁋i \   pJ


Try it Online!

Base64-encoded:

4pah4oGL4pah4oGLIyMj4pah4oGL4pah4oGLCjs7feKWoeKBi+KWoeKBi+KWoeKBiyDEl867bnR0wrZudHQ9wqw7OzvhuIrGmydrd250Y8KsOyDOu1wjXCNcL1wjXC9KSkpKbnR0Y8KsO+G6jjs7O8OeZuKEhWggOjo6OiDilqHigYtpIFwgICBwSgo7O33ilqHigYvilqHigYvilqHigYsgxJfOu250dMK2bnR0PcKsOzs74biKxpsna3dudGPCrDsgzrtcI1wjXC9cI1wvSkpKSm50dGPCrDvhuo47OzvDnmbihIVoIDo6Ojog4pah4oGLaSBcICAgcEoKOzt94pah4oGL4pah4oGL4pah4oGLIMSXzrtudHTCtm50dD3CrDs7O+G4isabJ2t3bnRjwqw7IM67XCNcI1wvXCNcL0pKSkpudHRjwqw74bqOOzs7w55m4oSFaCA6Ojo6IOKWoeKBi2kgXCAgIHBK


### Installation

pip install vyxal


### Running

vyxal code.vy

• Thank you for being the first to have complete build instructions. Unfortunately, it seems the bot produces invalid output. You need to output index of the character you want to remove, followed by a space, followed by the literal character value. Aug 19 at 19:39
• @mousetail Should be fixed now. Aug 19 at 19:44
• Looks like the problem is that it's coming in at STDIN. Vyxal was never designed to work with STDIN, so it's very buggy when using it. Does it work to provide the input as command-line arguments, where each line is its own argument? If not, I'll submit a patch to Vyxal to fix things, and we'll probably have to wait a while (PRs need two approves). Aug 19 at 21:04
• Unfortunately, the entire controller is based on sending things to STDIN so I can't make a exception for one program. However, I'd happily use a vyxal version from your fork until the PR is approved if you tell me how to install it Aug 20 at 5:18
• @mousetail It should work now. Please change pip install vyxal to pip install https://github.com/Vyxal/Vyxal/archive/fix-all-inputs.zip. Aug 22 at 21:56

              (       ]                   (      (                    [:        ":           [          ),          ' ',               {      )    ~            [:                  ?         #         )          (1!:1@3              '')


Try it online! (although TIO won't accept EOF signals/characters for input as far as I'm aware, so it may not work as intended)

### Installation

(source)

These instructions assume you are on a x86_64 processor. If you are on armv7/armv8/aarch64, use the Raspberry Pi downloads in the link above.

Prior to installation, you may need to install necessary libraries:

apt-get install libqtgui4 libqt4-svg libqt4-svg libqt4-opengl libqt4-network libqtwebkit4


Then, save the installation archive (recommended location is the home folder, but can be installed anywhere else with sufficient permissions) with a command similar to

wget http://www.jsoftware.com/download/j903/install/j903_linux64.tar.gz


Now extract the archive. There should be a folder called j903. Inside the folder, there should be a file called jconsole.sh.

### How to run

#### Option 1

./jconsole.sh


Then, paste the source code above in to the console (followed by a newline), or pass it in by script.

#### Option 2

Run the code below. The additional echo is necessary due to the limitations of program output when running directly from script. The echo is generally not counted as part of the source code. In addition, there is an additional character inside the body due to the need to escape the " character.

./jconsole.sh -js "echo               (       ]                   (      (                    [:        \":           [          ),          ' ',               {      )    ~            [:                  ?         #         )          (1!:1@3              '')                   "


#### Option 3

Save source code into file and run:

./jconsole.sh code.ijs


However, there are some caveats. Firstly, echo may need to be added to the beginning of the code to get the output to work correctly (like in Option 2) due to how J is primarily an interpreted language. Also, the appearance of an EOF in stdin may cause extra undesired output to be written to stderr. Finally, I have not tested this on an Ubuntu Linux device as I do not have access to one and am currently unable to access Docker to set one up.

### Explanation

Just like natural random radiation events, this bot will choose a random character to remove from its target. The bot itself has some basic radiation resistance, but is unable to handle targeted radiation attacks.

• I ran the code like this: echo "echo" > code.ijs && cat code >> code.ijs && j/j903/jconsole.sh ../../code.ijs but I'm getting the error Syntax Error Numerical Value not Entered. Aug 22 at 7:17
• @mousetail Can you try running it with Option 2 above? It's not the cleanest solution, but it worked on my computer. Aug 22 at 11:32
• Ok I spent a lot of time trying to get this to work now but to no avail. Feel free to submit a pull request to the controller with a working setup but otherwise I'm afraid I need to give up. Aug 23 at 6:33

# Brainfuck, 168 bytes, "the 2nd'er"

,#(((((((
>+++++++!
+++++++;/
+++++++//
+++++++/*
+++++++*/
+(+(+(+(+
+#{#+#}#+
!!+++++!!

|v.v|
----|
----v
----|
----v
.<.</

LCMoKCgoKCgoCj4rKysrKysrIQorKysrKysrOy8KKysrKysrKy8vCisrKysrKysvKgorKysrKysrKi8KKygrKCsoKygrCisjeyMrI30jKwohISsrKysrISEKCnx2LnZ8Ci0tLS18Ci0tLS12Ci0tLS18Ci0tLS12Ci48Ljwv

• How do I run this? Please include installation and run instructions :) Aug 19 at 12:59
• I don't actually know how you run brainfuck code... you can try pypi.org/project/python-brainfuck or dev.to/5elenay/python-brainf-ck-compiler-alpha-34lf or... IDK Aug 19 at 13:36
• Ok I'm going to try to find a interpreter when I get home Aug 19 at 13:53
• I think the first time I copy pasted it I might have added a line break at the end by accident Aug 21 at 7:20

# Sorry, Self-modifying Brainfuck

<<<<<<<<<<<<<<<<<<<<<<<<<<<<.<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<.<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<,.                                                        00000000000000000000000000000000000000000000000000000000


Try it online!

Install (assumes gcc and wget):

wget https://soulsphere.org/hacks/smbf/smbf.c
gcc smbf.c -o smbf


Run (assumes the source stored as src.smbf in the same folder as smbf executable):

./smbf src.smbf


Does the most obvious thing, maximizing defense against random deletions and nothing else.

# Piet + ascii-piet, 256 bytes (4×86=344 codels), picture perfect v3

jsamtfjsamtfjsamtfjsaqdusiiiiaaaabbbbddddffffjjjjvvvvtttteeeeeeeeeeeeeeeeeeeeeeeeeeeeEc?b?bed??j???bkaubuebmvmk                eeeeeeeeeeeeeeeeeeeeeeeeeee             e  Edjfvetejkbbraqmusqemqudsiadbdiab              eeeeeeeeeeeeeeeeeee               ee eE


Base64 encoded

anNhbXRmanNhbXRmanNhbXRmanNhcWR1c2lpaWlhYWFhYmJiYmRkZGRmZmZmampqanZ2dnZ0dHR0ZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZUVjP2I/YmVkPz9qPz8/YmthdWJ1ZWJtdm1rICAgICAgICAgICAgICAgIGVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZSAgICAgICAgICAgICBlICBFZGpmdmV0ZWprYmJyYXFtdXNxZW1xdWRzaWFkYmRpYWIgICAgICAgICAgICAgIGVlZWVlZWVlZWVlZWVlZWVlZWUgICAgICAgICAgICAgICBlZSBlRQ==


Try Piet online!

This bot probably won't do too well, considering that all it does is remove the first character each time, but hopefully it survives moderately well to place top 10 :P

V2: Hopefully fixed the vulnerability that I noticed when I took a look in the leaderboards.

V3: Fixes a vulnerability where removing the first 5 characters is fatal. Also added some protection against Thief, which hopefully works.

(credits to @Bubbler for the installation and run instructions)

# Installation

pip install Pillow
cd piet
./configure
make npiet
cd ..
git clone https://github.com/dloscutoff/ascii-piet.git ascii-piet


# Run

Save the source code in the text file src.txt:

python3 ascii-piet/ascii2piet.py src.txt src.png && piet/npiet -q src.png


# NÜL tränslätör - Bash

Just run it with bash, it should work (TM).

##((()
##(()

i=$(tr '\0' ' ') s=$(printf  %s  "$i"|wc -c) [$s  -gt  -1  ]||s=$(printf %s "$i"|wc  -c)

r=$((RANDOM%s)) [$r  -gt  -1  ]||r=$((RANDOM%s)) printf "%d "$r

p=$((r+1)) p=$((r+1))

printf  %s  "$i"|head -c$p|tail  -c1
##((()


It can survive some parts being broken, but unfortunately not syntax errors. Eg. if $s isn't a valid integer, [ will fail and s will be reassigned. IyMoKCgpCiMjKCgpCgppPSQodHIgICdcMCcgICcgJykKCnM9JChwcmludGYgICVzICAiJGkifHdj ICAtYykKClsgICRzICAtZ3QgIC0xICBdfHxzPSQocHJpbnRmICAlcyAgIiRpInx3YyAgLWMpCgpy PSQoKFJBTkRPTSVzKSkKClsgICRyICAtZ3QgIC0xICBdfHxyPSQoKFJBTkRPTSVzKSkKCnByaW50 ZiAgIiVkICIgICRyCgpwPSQoKHIrMSkpCgpwPSQoKHIrMSkpCgpwcmludGYgICVzICAiJGkifGhl YWQgIC1jICAkcHx0YWlsICAtYzEKIyMoKCgpCg==  ## Non-competing version This one can handle NUL bytes, I think. ##()() ##()() f=ooga f=ooga cp /dev/stdin$f

s=$(wc -c <$f)

[  $s -gt -1 ]||s=$(wc  -c < $f) r=$((RANDOM%s))

[  $r -gt -1 ]||r=$((RANDOM%s))

printf  "%d "  $r p=$((r+1))

p=$((r+1)) (head -c$p  $f||head -c$p  $f)|tail -c1 ##()()  But it saves input in a temp file violating rule 2. • Nice, one of the first bots that worked for me the first try with no configuration Aug 22 at 11:14 # V (vim), Golf Core 00000000: 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b ................ 00000010: 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b ................ 00000020: 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b ................ 00000030: 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b ................ 00000040: 3132 3334 3536 3738 394a 4a4a 4a4a 4a4a 123456789JJJJJJJ 00000050: 4a4a 4a4a 4a4a 4a4a 4a4a 4a4a 4a20 4449 JJJJJJJJJJJJJ DI 00000060: 3020 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b 0 .............. 00000070: 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b 1b1b ................ 00000080: 2f2f 2f2f 2f2f 2f2f 2f2f 2f2f 6162 6365 ////////////abce 00000090: 6620 6768 696b 6d20 6e6f 7071 7220 7374 f ghikm nopqr st 000000a0: 7576 7720 7879 7a41 4220 4345 4648 4a20 uvw xyzAB CEFHJ 000000b0: 4b4c 4d4e 4f20 5051 5253 5420 5557 5859 KLMNO PQRST UWXY 000000c0: 5a20 2829 5b5d 7b7d 2020 2020 2028 5b5d Z ()[]{} ([] 000000d0: 7b7d 2920 285b 7b7d 5d29 20e5 a4a9 e59c {}) ([{}]) ..... 000000e0: b0e7 8e84 e9bb 84e5 ae87 e5ae 99e6 b4aa ................ 000000f0: e88d 920d 0d0d 0d0d 0d0d 0d0d 1b1b 1b1b ................  Try it online! A stupid program which always remove the first character from input. Try to confuse other programs by the unprintable bytes. The only thing that make sense here is 89J DI0 <esc>. I'm not sure if this is valid since V doesn't read from stdin but from a file. (I failed to make it read from stdin.) Starting from Python 3.6 docker container (you may need to mount source code folder into the container so it could be used later) docker run -it --name=thev python:3.6 /bin/bash  Download source code and install all dependency cd ~ pip install docopt neovim trollius apt update apt install neovim -y apt install xterm -y wget https://github.com/DJMcMayhem/V/archive/refs/heads/master.zip unzip master.zip cd V-master  Place the source code into the container some how xxd -r > ~/program.v (paste the xxd source code in this post)  Open another terminal, and run the program docker exec -i thev /bin/bash -c 'cat - > ~/input && ~/V-master/v ~/program.v -f ~/input'  • Installation instructions? Aug 19 at 6:11 • Also I need the command to run this on the command line Aug 19 at 6:37 • @mousetail I had included an instruction. I'm not sure if this is valid. And Python 3.6 is required. It failed to work on Python 3.5 or Python 3.7. – tsh Aug 22 at 11:50 # Tapestry, <>< No good strategy, focuses on being very hardened. Each character is at least 4x redundant. iiiiiiiivvvvvvv lllllllllllllll 111111111111111 --------------- nnnnnnnnnnnnnnn 888888888888888 222222222222222 222222222222222 *************** *************** ooooooooooooooo ooooooooooooooo ;;;;;;;;;;;;;;;  ## Explanation: 1. iiiiiiii push the first 8 characters of our opponent to the stack. 2. v go down 3. l get the length of the stack. In case one of the i was deleted 4. 1 push one to the stack 5. - subtract 1 to get a 0 based index 6. n print this as a number, this is the index 7. 822** push "32" to the stack, the ASCII code for space 8. o print a space 9. o print the original character 10. ; end the program ## Setup if [[ ! -f fish.py ]] then wget https://gist.github.com/anonymous/6392418/raw/3b16018cb47f2f9ad1fa085c155cc5c0dc448b2d/fish.py fi  ## Run python3 fish.py code  # The Newline Killer, 172 Bytes, In response to the new edit in this. ////// ////## ////(( ////>> k,j;main(i){for(j=getchar();i<999;i++){k=getchar();if(k=='\n'||k=='='){printf("%d %c",i,k);exit(0);}}printf("0 %c",j);} ////// ////## ////(( ////>>  I managed to do this without learning C I am so smart (this is written in C). Targets the first new line or =. Hopefully there won't be too much irrelevant =s. Else targets the first character. Most of the code has comments which can cause them to break by commenting their own code. • This seems to be 176 bytes, not 172. Aug 25 at 8:17 • ok, will change that Aug 25 at 8:42 # Python3, Key Characters Attack, 255 bytes  # # # # # # # repetitionrepetitionrepetition=lxn_1";=lxn_1";$(>+%cstststststststststststst\n\n\nfrom sys import stdin as s;\ni=s.read();\nfor c in'\\n )}.01+\\n )}.01+'[len(i)%8:][:8]:\n if c in i:print(f'{i.index(c)} {c}');exit();\n\nprint(f'{len(i)-1} {i[-1]}');

Which is:

" #"

[ "$a" = "$b" ] && eval "$a" (  Survival odds against 1 random deletion: 253/256 Survival odds against 2 random deletions: 31747/32640 Survival time against forward sequential whitespace deletion: 25 Survival time against forward sequential deletions: 10 Don't know why it prints "20 0120 " after 11 deletions when fed its own original source, it start right, but then adds a 1 and runs again. I0AjLF8jCgphPSJwcmludGYgJzIwICc7aGVhZCAtYzIxfHRhaWwgLWMxO2V4aXQiCmI9InByaW50 ZiAnMjAgJztoZWFkIC1jMjF8dGFpbCAtYzE7ZXhpdCIKWyAiJGEiID09ICIkYiIgXSYmWyAiJGEi ID09ICIkYiIgXSYmZXZhbCAiJGEiCgoiICMiCgphPSJwcmludGYgJzIwICc7aGVhZCAtYzIxfHRh aWwgLWMxO2V4aXQiCmI9InByaW50ZiAnMjAgJztoZWFkIC1jMjF8dGFpbCAtYzE7ZXhpdCIKWyAi JGEiID0gIiRiIiBdICYmIGV2YWwgIiRhIgooCg==  ## Tailstrike - Python 3 I had this laying around, doesn't seem to get immediately killed by the Burrowing Wheel. Since the last byte is quite likely to be an unnecessary line terminator, the bot actually attacks the 2nd last byte. It turns out it's near impossible to get Python 3 to NOT use utf-8. PYTHONIOENCODING only affect the already opened stdin/stdout/stderr, open(0) defaults to utf-8 even with LC_ALL=C.ISO-8859-1. Using sys.stdin however isn't too horrible, the default error handling is to use surrogate-escape on both stdin and stdout. 2 3 5 7 """" 11,0 13,0 '((' import sys s=sys.stdin.read();print("%d "%(len(s)-2)+s[-2]) ### """"" """" "%(17,0)" "%(19,0)" n=s=sys.stdin.read();print("%d "%(len(s)-2)+s[-2]) ###""""" import sys s=sys.stdin.read();print("%d "%(len(s)-2)+s[-2])  ### base64 for easy copying MgozCjUKNwoKCgoiIiIiCjExLDAKMTMsMAonKCgnCgoKaW1wb3J0ICAgc3lzCgpzPXN5cy5zdGRp bi5yZWFkKCk7cHJpbnQoIiVkICIlKGxlbihzKS0yKStzWy0yXSkKIyMjICIiIiIiCgoKIiIiIgoi JSgxNywwKSIKIiUoMTksMCkiCm49cz1zeXMuc3RkaW4ucmVhZCgpO3ByaW50KCIlZCAiJShsZW4o cyktMikrc1stMl0pCiMjIyIiIiIiCgppbXBvcnQgIHN5cwoKcz1zeXMuc3RkaW4ucmVhZCgpO3By aW50KCIlZCAiJShsZW4ocyktMikrc1stMl0pCg==  • This should work on 2.7 as well. Aug 28 at 18:55 ## Bastarf Mark III, Python 3 only Run with python3 bastarf. This is a bastard, but my finger slipped. It is focused on offense targeting the current leaders. ### Mark III Implemented @mousetail's suggestion to use exec(""" to reduce sensitivity to deletions. Also made print flush as output isn't to a terminal, don't know why this worked with Mark II but maybe it didn't. Same targets as Mark II but hopefully less fragile. Some improvements could still be made, like removing nested exec, but there already three versions. # # # # import os i=os.sys.stdin.read() try: exec(r""" def f(x): exec('p=i.find(x)\nif p>=0:print("%d %c"%(p,i[p]),flush=True);os._exit(0)') f('=l') f('xn') f('_1') f('";') f('\n\t') f('$(')
f('>+')
f('%c')
f('st')
1//0
""")
except:
print("9 "+i[9])

IwoKIwoKIwoKIwppbXBvcnQgb3MKaT1vcy5zeXMuc3RkaW4ucmVhZCgpCnRyeToKIGV4ZWMociIi
IgpkZWYgZih4KToKIGV4ZWMoJ3A9aS5maW5kKHgpXG5pZiBwPj0wOnByaW50KCIlZCAlYyIlKHAs
aVtwXSksZmx1c2g9VHJ1ZSk7b3MuX2V4aXQoMCknKQpmKCc9bCcpCmYoJ3huJykKZignXzEnKQpm
KCciOycpCmYoJ1xuXHQnKQpmKCckKCcpCmYoJz4rJykKZignJWMnKQpmKCdzdCcpCjEvLzAKIiIi
KQpleGNlcHQ6CiBwcmludCgiOSAiK2lbOV0pCg==

• f('=l') specifically targets Distributed Damage
• f('xn') tries to target Comment Skipper by attacking the one fatal spot
• f('_1') tries to target Almost Rare by messing up the 1-base to 0-base conversion hopefully without causing pre-mature exit
• f('";') puts Example Python BOt in an unterminated string
• f('\t\n') attacks Ghost
• f('\$(') will break NÜL Tränslätör, unless the input is actually cat
• f('>+') tries to target The 2nd'er
• f('%c') will make Example C bot output invalid data
• f('st') targets stdin in Example Node Bot, MVP and Parenthesis Killer

And then it starts getting too big.

Mark I and Mark II are hidden in the edit history.

• Is the name "Nonono, I'm gonna edit" or "bastarf"? Aug 22 at 14:18
• @mousetail: I thought I had already posted the answer and was making a last "minute" change. Anyway, there's a Mark II now. Aug 22 at 14:46
• Thanks, according to my initial tests mark 2 seems significantly worse than mark 1. Will update the breadboard when I get home. Aug 22 at 14:55
• One thing you could consider is using "## at the start since many bots default to removing the first character Aug 22 at 14:57
• You could maybe use something like try:exec(""" so you don't need to indent? Aug 22 at 15:02

## The Bloody Awful, Batch

This is the most cursed I could come up with that doesn't involve having to install an Itanic emulator and learning Itanium assembler.

@@@@@@@@@@@@@@@   echo   off

@@@@@@@@@@@@@@@   echo   off

:::   The bloody awful   :::

::: Mmmmm         whitespace

set  /p  i=

<NUL   set  /p  x=2 %i:~2,1%

exit  /b

set  /p  i=

<NUL   set  /p  x=2 %i:~2,1%

exit  /b


It has CRLF line endings, so you may need to use the base64

QEBAQEBAQEBAQEBAQEBAICAgZWNobyAgIG9mZiAgIA0KDQpAQEBAQEBAQEBAQEBAQEAgICBlY2hv
ICAgb2ZmICAgDQoNCjo6OiAgIFRoZSBibG9vZHkgYXdmdWwgICA6OjoNCg0KOjo6IE1tbW1tICAg
ICAgICAgd2hpdGVzcGFjZQ0KDQoNCg0Kc2V0ICAvcCAgaT0NCg0KPE5VTCAgIHNldCAgL3AgIHg9
MiAlaTp+MiwxJQ0KDQpleGl0ICAvYg0KDQoNCnNldCAgL3AgIGk9DQoNCjxOVUwgICBzZXQgIC9w
ICB4PTIgJWk6fjIsMSUNCg0KZXhpdCAgL2INCg==


### Installation

Wine is required. Probably just apt-get install wine. I have tested that it works with just wine64 (no wine32 installed) on Debian, but I have not tested at all on Ubuntu.

Run with wine cmd /c bloody-awful.bat

### Strategy

It doesn't seem to be possible to just read a byte from "standard input" in batch/cmd. This bot will read the first line (excluding line terminator) and select one character from it. The safest character to pick would be the first on the line, but even that isn't 100% safe since the line can be completely empty.

I choose to pick the 3rd character since that seems likely enough to exist and will get to the good parts slightly faster than picking the 1st.

For hardening, there is highly redundant at symbols before the redundant echo offs as well as plenty of whitespace (including after 'off') to mitigate against attacks from comment skippers and whitespace deleters.

All critical code is duplicated but not actually redundant, but it's enough to keep the Burrowing Wheel distracted with the useless comment for a while.

### And now for something completely different

A recipe for a nice smoothie