BF Joust strategies

From Esolang
Jump to: navigation, search

BF Joust is more involved than its simple rules might suggest. This page details some of the major strategies which are used, and gives a short example for each. It then lists major programs and describes the strategies they use.

Attack[edit]

Rush[edit]

Rush-based programs focus entirely on attack, though they may use any attack strategy. They tend to be further divided into "slow rushes" that set large decoys, and "fast rushes" which try instead to reach the opponent before they can set up their own decoys.

The rule of nine[edit]

There is no purpose in attacking the first 9 cells, since the enemy's flag will never occupy one of them. For this reason, it is common to start fast rush programs with code similar to

(>)*9

Slow rush programs will instead generally set up decoys and then move to the tenth square of the tape and start attacking from there, in the hope of avoiding decoys.

Many programs want to skip the first nine cells this way, and then do something (such as a clear) on each of the potential remaining 21 cells. In such cases, the simplest code puts 8 of the > commands into an initial repeat, and then the ninth inside a loop, in order to give nine > instructions but not run off the end of a length-30 tape if the "something" fails:

(>)*8(>do something)*21

The only reason a rush program might want to not start at the tenth cell is if it's specifically trying to detect decoys, as in tripwire avoidance; even though the enemy flag cannot be in the first 9 cells, enemy decoys can be, and this can sometimes produce useful information.

Exploiting the fact that an opponent uses this tactic is difficult or impossible; in theory it can give away information about the tape length, but it's too easily confused by decoys and similar tactics.

Clear[edit]

The most obvious strategy is to look for any set cells and zero them as in Brainfuck.

[-]

The canonical example of this strategy is

(>)*9([-]>)*21

Trace and animation

This is known as a "two-cycle clear", and is fast and common, but can often be exploited by defence programs. A slower "three-cycle clear" looks like this:

[-.]

(or alternatively with the - and . reversed). Three-cycle clears are less generally exploitable by defence programs; sometimes programs use five-cycle clears to make absolutely sure. (Four-cycle clears are not useful as they are generally locked by the same code that locks two-cycle clears.)

The vast majority of programs use some kind of clear. A simple non-offset clear such as this one, though, is very vulnerable to decoys; a decoy with one polarity (positive or negative depending on whether the clear is based on [-] or [+]) will have almost no effect, but a decoy with the other polarity will cause the clear to take much longer, as it has to cycle through all the possible values until it reaches 0 from the other direction. Another method of exploiting an enemy clear is to lock it; this requires knowing or guessing the cycle length of the clear, and thus two-cycle clears, being the most common, are also the most vulnerable to this.

Offset clear[edit]

It is common to set values in several cells as decoys. The values of these decoys are usually very close to zero, often 255 (-1) or 1. As such, using a clear such as

[-]

will result in the maximum cycles spent looping to clear a cell. This can be offset by first adding an expected decoy value.

(+)*9[-]

The canonical example of an offset clear program (with offset 9) is

(>)*9([(+)*9[-]]>)*21

Trace and animation

Offset clears are less prone to decoys than regular clears, but can still be defeated by decoys larger than the offset. They are slower on average than typical clears, too, and almost as vulnerable to locking (unless the offset is large enough to throw off the timing of the lock). Additionally, offset clears have a distinctive pattern of zeroing on a small tripwire of the right polarity (first zeroing for one cycle, and then later zeroing for two cycles), meaning that a carefully placed tripwire can detect the presence, polarity, and offset of an offset clear, making locking it very easy unless it varies from one tape position to the next.

Wiggle clear[edit]

A further extension of the offset clear concept is to have nested loops in opposite directions, to catch small values quickly. For instance, the clearing algorithm

([-{ ([+{ [-] }])%8 }])%4

will finish quickly with values from -4 to 4. The inner clear algorithm can be anything, including a larger offset clear. Combining wiggle clear with offset clear yields the canonical program

(>)*9 ( ([-{ ([+{ (+)*9[-] }])%8 }])%4 >)*21

Trace and animation

One downside of the canonical wiggle clear is the part where it closes a lot of brackets in a row before moving on to the next cell. This renders it vulnerable to triplocks, which begin rebuilding a just-cleared decoy by the time the third closing bracket is reached, preventing the algorithm from ever being able to leave the triplocked cell. The most straightforward way to avoid this is to add an extra clear before every closing bracket in this row. A canonical offset wiggle clear algorithm with triplock avoidance might look like:

(+)*4 ([-{ [(-)*15 [+]] }[-]])%8

Note that this algorithm will be stuck clearing the triplocked cell of a good triplocker for nine consecutive triplock phases, and this may be enough for the triplocker to win on short tapes. However, it typically takes more than 9 triplock phases to full clear a long tape, at which point this clear algorithm will finish and the program using it will move on the next cell. If the triplocker uses the tripwire method to wait for its opponent to clear its triplock, it will sit waiting forever while the program using this clear moves on to take out its flag.

Here is a direct incorporation of the above clear algorithm into an otherwise simple program defeating a sophisticated triplocker on all tape lengths and polarities: Trace and animation

Careless clear[edit]

The careless clear, also known as the turtle strategy, is a fast way of clearing cells which are equal to the value 128, the initial flag value. Rather than looping, the attacker simply adds or subtracts 128 from the cell, then waits one cycle in case the flag is zero. This saves one cycle per iteration (since there are no true iterations), but is expensive on small values.

(-)*128.

This of course will only have the desired result if the flag is not changed by the opponent. The canonical example of this careless clear is

(>)*9([(-)*128.>]>)*21

Trace and animation

The careless clear can also be combined with the concept of the offset clear to support some range of values by waiting after a sequence of modifications rather than only the last one. For instance, to support values from 112 to 144:

(-)*112(-.)*32

Trace and animation

Although very fast against large decoys, careless clears can typically be tricked off the end of the tape simply by changing the value of your own flag (although the amount often has to be quite large); for much the same reason, they tend to be defeated by shudder-based programs, and often also by vibration-based programs. Setting a lot of decoys helps as well, as small and moderate-sized decoys can be set much faster than the careless clear can clear them.

Reverse offset clear[edit]

When you suspect you're on an opposing flag, but fear the opponent might have used anti-careless-clear tactics, it is possible to use an offset clear centred about 128, rather than 0; instead of a small offset then clearing in the opposite direction to the offset, it uses an offset just below 128 followed by a clear in the same direction. The following program does this, after first checking for decoys of size 1:

>+>-(>)*6(>[-[++[(+)*120[+]]]])*21

Trace and animation

The advantage of this over a careless clear that checks a range of values is that it's guaranteed to clear an undefended cell eventually even if it's been set to a very unusual value for a flag, rather than running off the tape like a careless clear would; and the advantage over a regular offset clear is that for flags near 128, it's almost twice as fast. The disadvantage is that if the cell isn't actually a flag, it can take much longer than a typical offset clear would, leaving it vulnerable to being outraced. It's thus mostly useful only if you have a good idea that the current cell is a flag.

Anti-shudder clear[edit]

Due to the danger of suiciding when the opponent changes their own flag to zero and back again, it is now necessary to make sure to close at least two brackets before moving to the next cell. Generally speaking, this consists of a simple clear like a two-cycle clear, followed by a clear with a much large cycle length in order to beat defenders and shudderers. This following example does this, with a two-cycle offset clear followed by an eleven-cycle clear, and in addition ensures that the canonical shudder program will die in as few cycles as possible:

(>)*8(>[(+)*9[-].[.++-------]])*21

Trace and animation

Such clears are only slightly slower than typical clears (and likewise, an offset anti-shudder clear is comparable and slightly slower than a straight offset clear), and are hard to take advantage of via defensive programs. Lock-based programs can sometimes lock such clears on their first, simple clear, though, although generally only if they know their polarity (the lock will break eventually otherwise, but can sometimes take a very long time to do so, sometimes long enough for the lock-based program to clear three or four tape cells even via the slow full-tape clear method).

Timer clear[edit]

One interesting way to evade locks is to simply stop clearing after a while and move onto a different strategy; this allows fast two-cycle clears to be used to defeat rush programs, whilst still not being trivially locked by defence-based programs. Here's a simple example, showing a program that changes clear direction and period after 500 clear attempts, and running it against a trivial lock-based program that tries to lock the sort of clear that the program starts with into an infinite loop and a draw (in practice, lock-based programs would probably be trying to win, but the same principle applies):

(>)*8(>([-{[+.]}>])%500)%21

Trace and animation

The major issue with timer clears is their inflexibility; although it is relatively easy to make an offset and/or anti-shudder timer clear, most other modifications are difficult or impossible. (For instance, they cannot check to see if a cell is 0 before offsetting it, like most offset clear algorithms do.)

Flexible timer clear[edit]

The inflexibility of timer clears can be effectively worked around simply by embedding multiple timer clears inside each other, putting each inside timer clear just after the > of the one immediately afterwards. This allows each of the individual clears to be on a separate timer; it also allows pretty much arbitrary modifications to the clear algorithm, which can even be different for differently positioned decoys. Here's an example using offset clears with multiple different offsets:

(>)*8(>(+)*24([-{[+.]}>(+)*23
             ([-{[+.]}>(+)*22
             ([-{[+.]}>(+)*21
             ([-{[+.]}>(+)*20

(etc...)

             )%500])%500])%500])%500)*-1

It works as a drop-in replacement for standard sorts of clear, as it works identically before the timer expires; the main disadvantage is its length, which can make it hard to fit into more control-heavy programs. Unlike regular timer clears, it cannot reasonably be nested, and so can be locked if the defending program finds a lock pattern that works on both the inside and the outside clear loops.

Full-tape clear[edit]

If the opponent does not do anything, it is possible to definitively clear the opposing flag in constant time by setting every element on the tape to each of its 256 possible values and waiting a turn. Naive code to do that looks something like this:

(>)*8(>(+.)*255)*21

Trace and animation

Such an approach is both incredibly slow and prone to locking, and thus rarely if ever seen in successful rush programs. However, its fixed-cycle and easily interruptible nature makes it incredibly valuable in programs that use locks themselves; if the opponent is successfully locked, a defensive program can alternate between maintaining the lock and continuing its full-tape clear. As such, this is considered a very defensive form of attack, generally used only by defense programs to finish off their opponent.

To beat a full-tape clear, all that is necessary is to be able to act freely, rather than stuck in a lock; almost any aggressive technique will outrace it, and many defensive techniques will beat it too, although often with a tape length dependency.

Poke[edit]

A slow rusher can usually win by having more decoys than its opponent, and there are two ways to do that: by making your opponent have fewer decoys, and by building yourself more decoys. Poking is a strategy that makes both of these things possible. The idea is to find out where your opponent is before building any of your own decoys, and then adjusting your decoy line forward so as to make room for more of your own decoys, and also possibly to identify a safe location behind your opponent's decoys, depending on how they build them. Here is an example:

(>)*8(>[(<)*8(-)*33(>)*8([-[++[(+)*9[-]]]]>)*21])*21

Trace and animation

Pokes can be made less effective by setting up advanced decoys early, in order to cause them to think the tape is shorter than it is; this is rarely fatal to the opposing program, but will often slow it down. Additionally, rushing forwards quickly gives a chance to get behind the opponent's decoys before they are set up, making the enemy flag very easy to find. Thus, poke-based programs normally need a separate countermeasure against fast rush programs.

Poke can be combined with the wiggle clear to produce a deep poke. This strategy was first used in Gregor_furry_furry_strapon_pegging_girls, see its behavior against Deewiant_pendolino for a good example: Trace and animation

Tripwire avoidance[edit]

Any program that assumes the first nonzero cell it sees is probably a decoy and keeps searching. Here is an example:

(>)*8(>[(>[(+)*9[-]]>)*21])*21

Trace and animation

Note that it will suicide against any opponent that doesn't make decoys. Or, that doesn't make them fast enough for it to see them. (Tripwire avoiders will sometimes wait deliberately, and change the Rule of Nine to a Rule of Seven or whatever, in order to make sure that if the opponent makes decoys, it spots them. However, this removes some of their speed advantage.)

Tripwire avoidance can be defeated by setting up no decoys, but this is often a bad idea due to the huge disadvantage it gives against other sorts of programs. Alternatively, setting up an extra small decoy is often all that is needed to neutralize the tactic.

Reverse tripwire avoidance[edit]

For small reverse tripwires, it is possible to avoid triggering them by restoring them to their original value before moving away from them, such as the following example that restores all size 1 decoys:

(>)*8((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]_>((>[-[{(++[(+)*9[-]]_>
((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]->
((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]->
((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]->
((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]->((>[-[{(++[(+)*9[-]]->
((>[-[{(++[(+)*9[-]]->[-]{}])}]]+)%1)*2{}])}]]+)%2)*2{}])}]]+)%3)*3{}])}]]+)%4)*4
{}])}]]+)%5)*5{}])}]]+)%6)*6{}])}]]+)%7)*7{}])}]]+)%8)*8{}])}]]+)%9)*9{}])}]]+)%10)*10{}])}]]+)%11)*11
{}])}]]+)%12)*12{}])}]]+)%13)*13{}])}]]+)%14)*14{}])}]]+)%15)*15{}])}]]+)%16)*16{}])}]]+)%17)*17
{}])}]]+)%18)*18{}])}]]+)%19)*19{}])}]]+)%20)*20{}])}]]+)%21)*21

As you can see, it is not very compact or flexible. Futhermore, this only works if the program using them does not check them constantly, as in this case, it would check them before you had a chance to restore them. However, the primary benefit of reverse tripwires is their ability to allow a program to go do other things before determining if the tripwire has been tripped, so most programs that use them will not check them immediately. However, in the age of larger reverse tripwires, it may become prohibitively expensive to restore their value.

In the case of programs that use small reverse tripwires and check them incessantly, just checking several times in a row if a cell is nonzero before attempting to modify it can avoid them in many timings/tape lengths (at the cost of slowing down your decoy clear by a few cycles):

(>)*8(>[[[[+[--[(+)*9[-]]++]-]]]])*21

Reverse decoy avoidance[edit]

If you assume that the opponent uses a reverse decoy setup, you can look for a nonzero cell, assume it's the first of a series of reverse decoys, then keep moving until you find an empty cell, then move again until you find a nonempty cell, asssume it's a flag, and clear it (e.g. with a reverse offset clear, wiggled to avoid small decoys, as shown in the example below):

>>>>(>[[>]((>++++[-[-[-[-[-[-[-[-[(-)*120[-]{}]]]]]]]]])%29)*-1])*-1

As written, the strategy is trivially defeated by a trail or forward decoy setup, making it a very fast risky rushing strategy. (Some protection against trails can be added either by looking for small values on cells, which has problems of its own, or more plausibly deciding that a reverse decoy setup is probably not in use after seeing a suspiciously large number of decoys.) It also tends to be quite sensitive to the details of the opposing programs (the details of decoy setups tend to vary wildly).

Interrupted rush[edit]

On short tape lengths, rushers benefit from rushing as quickly as possible to prevent the enemy taking a lot of time to build more and larger decoys, or at least to tear through their decoys nearly as fast as they can be built. However, since decoy building is always faster than decoy clearing, on longer tapes it benefits one to slow down the opponent by having a lot of decoys. Thus, a very effective strategy is to rush for a while, then go back and build more decoys when you believe your initial set of decoys has almost been destroyed, then go back and rush some more. Examine Deewiant_pendolino in the Major Programs section for an example of this strategy. One might also wish to interrupt a rush to do other things, like switch to a defense strategy, or repair your own flag a little bit. These sorts of ideas are advanced strategies that have not yet been thoroughly explored.

Defense[edit]

Note that no defense programs are simple (the very nature of a defensive strategy makes this so), and as such the examples used here are generally ineffectual on their own and sometimes not very short. They are presented simply to give the gist of a particular strategy, without being a good program in and of themselves. Defensive tactics can sometimes also be useful even for rush programs, in order to buy more time for their rush.

Decoy[edit]

The most fundamental defensive strategy is the decoy. Since it is impossible for an attacker to distinguish the flag from any other non-zero cell, filling a section of the tape with various non-zero values can slow down or even foil an attack. It is important to use both positive and negative decoys, so that your decoys slow down your opponent equally in either polarity.

(>+>-)*4

Decoys can be further split into "small decoys" that are less than the range of a typical offset clear (or in the case of a wiggle clear, the offset of the wiggle) and serve only to trick the opposing program into thinking that something is there (in order to defeat tripwire-avoiders, confuse pokes, etc.); and "large decoys" that are designed to be large enough to force even offset clears with the wrong polarity to clear the cell in the wrong direction. It is also common to refer to "medium decoys", which are larger than the wiggle offset of a typical wiggle clear, but smaller than the much larger offset that follows the wiggle.

Since decoys are unlikely to cause an opponent to lose on their own, they are almost always combined with other strategies. They are common in all sorts of programs to buy time to perform their strategies (in rush programs, to try to buy time with an undefended flag in order to zero the enemy flag first; in defence programs, in order to set up tripwires and adjust cells on which locks will be performed to sane starting values).

A few programs may benefit from not setting up decoys. This normally happens with bad programs, where setting up decoys may not aid their strategy because it was a bad idea in the first place, whereas not setting up decoys can trick tripwire avoiders off the end of the tape; this is not particularly useful, though, as it won't correct the fundamental flaws in the original program. Alternatively, not using decoys can benefit defence programs that don't use tripwires either, in order to make the likely timings of the opponent a little more consistent, and aid them in setting up a successful lock or shudder.

Small decoys are typically avoided via offset clears. For large decoys, using a fast clear is one possible method to avoid them. However, techniques like tripwire avoidance and careless clears work better by entirely neutralising the decoy's effect, and defensive programs, especially those that use tripwires for synchronization, generally care nothing for opposing decoys, either due to not attacking at all, or due to using full-tape clears that are unaffected by decoy values.

Reverse decoy setup[edit]

When setting a large number of decoys, it is often a good idea to set the ones nearer the enemy flag first, in order that the first few decoys might buy time to set up the last few against faster rush programs.

>>>>>(-)*64<(+)*64<(-)*64<(+)*64(>)*7(>[-])*21

Here's a comparison (decoy setups versus a simple rush program):

The major disadvantage of a reverse decoy setup is on shorter tapes, where instead of some of a large number of decoys working, none do (assuming that the opponent skips them via the Rule of Nine), and the program is defeated trivially. Therefore, it is often a good idea to gain an idea of what the tape length is before embarking upon such a system. Unless the first few decoys are small and set up quickly, reverse decoy setups also often lose to tripwire avoidance, as the first decoys are skipped before the later decoys are set up. If it's suspected that the opponent is using a reverse decoy setup, it's also possible to skip cells until a zero cell is found, but doing so is incredibly risky as it will suicide against other sorts of programs.

Interrupted decoy setup[edit]

Just as building the decoys furthest from your flag can give you more time to build more decoys behind it, one can also use the time afforded by the building of a decoy to do other things. This could be considered an "advanced" strategy. Check out the animation/trace of quintopia_space_elevator in the Major Programs section to see a decoy build interrupted to check a reverse tripwire. Also, see Deewiant_pendolino for an example of a decoy build interrupted to rush the opponent.

Breadcrumb decoys[edit]

By making a series of very small decoys as a trail, then reversing to the beginning of the tape and building them further, it is possible to build decoys precisely until the opponent is encountered. This is done by using the small decoys as reverse tripwires to see if the opponent has come this far already. The idea is to check a reverse tripwire immediately before each decoy is built and interrupt the build as soon as the opponent has been detected, changing strategies based on when and where the opponent was last seen. This is a special type of interrupted decoy build.

Here is a small example program that uses this strategy:

>-(>[<<<(+)*10(<+[{}(+)*23>(--[(>)*7(>[(-)*15[+]])*21](-)*23>)*24])*24]+)*10
<<<(+)*10(<+[{}(+)*23>(--[(>)*8(>[(-)*15[+]])*21](-)*23>)*24])*24

Trace and animation

Also, compare the early-game behavior (immediately after the deep poke) of Gregor_furry_furry_strapon_pegging_girls, the program that introduced it, with quintopia_a, a later champion that uses it, as they compete: Trace and animation

Trail[edit]

Any attacker which zeroes cells may also choose to change that value before moving on to the next cell. That changed value can effectively be a decoy. For instance, the below program combines a simple clear with a trail.

(>+>-)*4>([-]+>[-]->)*11

Trace and animation

Leaving a trail generally helps against slowly rushing enemies, as it effectively gives you a lot of free decoys. It hurts against fast rush programs, though, which will generally have overtaken you before the trail is even set, and in such cases a trail will just slow you down. (Not to mention, that offset clears can easily avoid a typical trail.) A typical defence program won't even notice whether you're trailing or not.

Lock[edit]

Upon somehow deducing the location of the enemy data pointer (e.g. via a tripwire), and its clear mechanism (e.g. guessing a two-cycle clear or two-cycle offset clear), it is possible to turn the cell in question in the other direction at much the same rate, thus forcing the opponent into an infinite loop. Locking can also be done less reliably by turning the cell in the same direction, such that the cell never becomes zero for two cycles; the risk in this is that the opponent can detect that it's happening and take countermeasures. If a defense program is lucky, the opponent will respond by falling off the tape, but rush programs rarely fall for such tactics nowadays. Here is possibly the simplest lock-based program:

>+[]<(.)*90
((+)*256 (>)*9 (+.)*119 (<)*9)*3
((+)*256 (>)*10 (+.)*118 (<)*10)*3
((+)*256 (>)*11 (+.)*117 (<)*11)*3
((+)*256 (>)*12 (+.)*116 (<)*12)*3
((+)*256 (>)*13 (+.)*115 (<)*13)*3
((+)*256 (>)*14 (+.)*114 (<)*14)*3
((+)*256 (>)*15 (+.)*113 (<)*15)*3
((+)*256 (>)*16 (+.)*112 (<)*16)*3
((+)*256 (>)*17 (+.)*111 (<)*17)*3
((+)*256 (>)*18 (+.)*110 (<)*18)*3
((+)*256 (>)*19 (+.)*109 (<)*19)*3
((+)*256 (>)*20 (+.)*108 (<)*20)*3
((+)*256 (>)*21 (+.)*107 (<)*21)*3
((+)*256 (>)*22 (+.)*106 (<)*22)*3
((+)*256 (>)*23 (+.)*105 (<)*23)*3
((+)*256 (>)*24 (+.)*104 (<)*24)*3
((+)*256 (>)*25 (+.)*103 (<)*25)*3
((+)*256 (>)*26 (+.)*102 (<)*26)*3
((+)*256 (>)*27 (+.)*101 (<)*27)*3
((+)*256 (>)*28 (+.)*100 (<)*28)*3
((+)*256 (>)*29 (+.)*99 (<)*29)*3

Trace and animation

Locks can be broken by using a different clear algorithm from the one they expect; using a three-cycle clear is typically enough for this, and a five-cycle clear nearly always escapes locks perfectly. Varying clear algorithms from tape cell to tape cell makes it much harder for a lock to guess what you are doing. Locks are also incapable of trapping careless clears and full-tape clears on any particular cell, but often beat them anyway by incidentally tricking them off the end of the tape, so they cannot be seen as sensible countermeasures.

Another way to break free from a lock is to change strategy after a while, either based on time, or on observing a zero cell for one cycle but not two (a giveaway that you are either being locked, or facing a vibration or shudder program). The anti-shudder clear exploits this by dropping through into something crazy, like an eleven-cycle clear, that no program could be expected to have an appropriate lock algorithm for, or to figure out that that clear algorithm was being used even if it did.

Probabilistic lock[edit]

The invention of the timer clear meant that new defensive strategies were needed for defence programs to be able to maintain their locks. The probabilistic clear abandons any attempt to synchronize with an opponent; rather, it resigns itself to the fact that it will only get a lock some proportion of the time.

The basic idea is to pick a length of time that's a small power of 2 (such as 128 cycles), then throughout most of that time, increase then decrease the cell you're locking on. Here's an example from ais523_preparation (which increases and decreases the cell by 56.5 cycles, alternating the rounding between iterations):

(+)*56(-)*57(.)*15
(+)*57(-)*56(.)*15

Because the lock's repeat rate is a power of two and makes no net change to the lock cell, the sequence of values on the lock cell will have the same repeat rate as the opponent's clear loop would naturally; in particular, this means that the lock loop and the opposing clear loop will always be at the same point whenever the lock cell hits zero. Almost half the time, the lock is working with the opponent; almost half the time, it's working against. However, the value of the lock cell moves faster when the two loops are moving it in the same direction, than when they're moving it in opposite directions. Thus, the odds are in favour of both loops pushing in the same direction as the lock cell crosses zero, which is the most important condition for a lock to hold.

This sort of lock thus gives a chance to defeat timer clears. Because it does not care that much about the details of the enemy's clear loop, there is a good chance that, having changed clear loop upon the timer expiry, the new loop will immediately be locked again by the probabilistic lock.

The huge downside is that this sort of lock only leaves a very small window to do anything other than maintain the lock. The above example gives fifteen cycles of freedom each time round the lock; this is enough to (very slowly) check or adjust cells within seven cells of the lock, but does not allow any sort of full-tape clear. Typical uses of this time would be to set up very strong decoys, and/or to check tripwires to see if the lock had broken (which can happen by chance, due to the lack of any meaningful sort of synchronization).

Triplock[edit]

A triplock is a different sort of lock, which targets a different part of the opponent's program. While ordinary locks are almost exclusively aimed at the opponent's clear loop, a triplock instead tries to lock the opponent in its control flow; to be precise, it locks programs that contain three or more ] commands in a row, which is very common in constructs such as [+[--[-]]], and can appear in programs for other reasons. (To be precise, it locks programs that contain three ] commands with no < or > in between immediately after a clear (with the first ] possibly part of the clear loop), and also certain other control flow patterns.)

The basic idea is to wait until a decoy (that cannot be the flag, unlike an ordinary lock) becomes zeroed, then immediately set it up to a large nonzero value again, using tripwire code such as [](+)*128. In order to actually win with the lock, it needs to be combined with a clear. A full-tape clear can be used, as typically is with locks; but a triplock (and no other known defensive construct, at the moment) also allows a much shorter "inline clear", allowing for a complete program that looks much like this:

>(+)*128[](+)*128>(+)*15[-]<[](+)*128>>(+)*15[-]<<[[](+)*128>>[>]->([-{[<+]}])%10<[<]<]

Trace and animation (warning: can be very slow to load on several browsers)

(The inline clear works by using the tape itself as working space to remember how far through its clear algorithm it is; but because it takes a variable rather than fixed amount of time like a full-tape clear does, it cannot be combined with an ordinary lock.) Other clears can also be used, such as 2-cycle clears or offset clears, but run quite a risk of the opponent breaking the lock if clearing one cell takes too long.

The simplest way to beat a triplock is merely to avoid the sort of control flow structures it is vulnerable to, but this can often cripple a program for other reasons (inability to use complex control flow is quite serious). Alternatively, certain types of clear algorithms can avoid triplocks by breaking the lock faster than it can complete its clear (reverse offset clears tend to do this, often on only one polarity depending on the details of the triplock). It may also be possible for a program to detect that it has been triplocked, although ordinary locks pushing in the wrong direction look much the same from the point of view of a program, so programs need to experiment further to determine exactly how the opponent is trying to lock them.

There is an interesting symmetry between triplock and shudder programs, incidentally; shudder programs tend to beat programs that check the value of the tape cell they are on once before moving on, whereas triplock programs tend to beat programs that check the value three or more times before moving on. Two would thus seem to be the optimal number, in a program that can afford the control flow restrictions that come with it.

Shudder[edit]

Shuddering is cycling the value of the flag through increments and decrements in order to cause attack loops to fail to put the flag at 0 for two cycles. The reversal of direction is key to this strategy. It usually results in a net increase/decrease over time, differentiating it from a "vibrator" below. Although moderately good as a defensive strategy, it tends to lose at random on certain tape lengths, and it renders its user entirely incapable of attacking as the shudder needs to be kept up constantly. Shudder programs thus can only win by tricking the opponent off the end of the tape. Canonical example:

(++-)*100000

Trace and animation

As shuddering can only win by tricking its opponent off the end of the tape, waiting for two zero cycles in a row before moving on guarantees at least a draw against it, and often a win. Clears designed to exploit this property are known as anti-shudder clears.

Vibrator[edit]

A vibrator vibrates its own flag between zero and nonzero constantly, thus making it very dangerous to assume a flag is cleared just because it hit zero. However, it is very easy to defeat by using a clear that is out of phase with its vibration. Canonical example:

(-)*127(-+)*100000

Trace and animation

If you fear falling off the tape due to missing a vibrator, you can check two cycles in a row before moving on (the difference between this and counter-shudder tactics is that it must be done at the start of the loop, rather than the end).

Reconnaissance[edit]

Although a program that entirely ignores it's opponents attacks (and in some cases, even the opponent's defences) can be effective, many programs will want to discover information about their opponent's strategy, the opponent's current actions (e.g. to synchronize a lock), the tape length, or some combination of these.

Tripwire[edit]

A tripwire is one of the simplest reconnaissance and synchronization devices, detecting an enemy clear loop.

An ordinary tripwire looks like this:

+[]

What it does is obvious, as it causes you to wait for your opponent to clear it. Using one is guaranteed to make you draw with any non-attacking program.

A variation is the two-cycle tripwire:

+[[]]

which waits for a cell to be zeroed for two cycles before you can continue. (The similarity of this to BF Joust's main victory condition means that all but careless clears are likely to do this, and probably just before moving to the next cell, rather than as part of an offset clear).

Sometimes tripwires will have a value larger than 1 or -1; this is typically for the purpose of causing the length of time it takes to zero them to provide more information about the opponent's strategy.

Tripwire avoidance allows obvious tripwires to be skipped altogether, giving an easy win, but is itself fooled by decoys. Careless clears will not trip an ordinary tripwire at one polarity, nor a two-cycle tripwire at either polarity, meaning that they can often beat tripwire-based programs too. (However, tripwire-based programs that change the value of their flag can exploit this effect in reverse, to beat careless clears by tricking them off the end of the tape!)

Timer tripwire[edit]

A normal tripwire represents a significant commitment; the program will not leave its tripwire until it is tripped, and if the tripwire is never tripped, the warrior cannot win. But a quality defense program is afraid of commitment, and wants to be able to change its mind if it thinks the tripwire will never get tripped. If it also cannot tolerate the synchronization inaccuracies associated with a reverse tripwire, it can use a timer tripwire, wherein it stops monitoring the tripwire after a preset number of cycles:

++++++([{give up and switch strategies}][handle careless or offset clear]synchronization achieved)%1000

Reverse tripwire[edit]

An alternative sort of tripwire, that allows other operations to be done at the same time.

+go do some other processing-[tripped]not tripped

This allows you to go do other things like building decoys or deciding whether you want to attack instead of wait any longer. As long as you check it often enough, you can get almost as close to being in sync with your opponent as you could be using a regular tripwire, and yet still be able to change your mind about defending, perhaps due to a belief that the opponent is also a defender.

The reverse tripwire has three major weaknesses: an opponent can set it back to its previous value (generally 1 or -1) upon clearing it; if the opponent encounters it while its value happens to be 0, they may miss its existence entirely and skip past it; and a cautious opponent can observe that its value becomes 0 every now and then (a giveaway for a reverse tripwire or a vibrated flag) and choose not to clear it. (Also, they aren't cycle-accurate with respect to timing like regular tripwires are; for some defensive programs, this matters, for most it won't.) Sometimes values greater than 1 or -1 are used for reverse tripwires in order to reduce the risks, but that also means they take longer to check. Tripwire avoidance also works almost as well against reverse tripwires as it does against regular tripwires. Using multiple reverse tripwires is common in programs that use any, as a method of increasing the chance that at least one spots the opponent, and helping to defeat countermeasures.

Decoy detection[edit]

Most programs will not change a tape element that's already set to zero, even if they encounter it during a clear loop; and even if they do (e.g. as part of a trail), if a program changes a tape element, that's a sure sign that it at least knows that the tape is long enough to contain that element. As such, decoys beyond that point are not helpful.

You can detect enemy decoys simply by doing a [ on an element before setting a decoy there. If you discover it to be nonzero, there is no point in placing a decoy there or anywhere beyond that point. Lymia_nyuroki was the first program to exploit this in a reverse decoy setup, to detect clashing decoy patterns. An earlier and more common use involves placing decoys up to the first enemy decoy detected (e.g. via using a large trail); this is often wasteful against aggressive programs who set few decoys (as they will rule-of-nine past some), but helps against programs that set a lot of decoys (because the rule of nine is less useful for those programs), and against defensive programs (where the time wasted setting up unused decoys is not very costly, and thus setting up possibly-useful-possibly-useless decoys is worthwhile as the upside outweighs the downside).

Major Programs[edit]

This section details major programs, where "major" is, for the most part, defined as having been #1 on the #esoteric hill, and gives the source for the latest version.

2009[edit]

nescience_creepCode: >+>->+>->+>->+(>-++-(.)*132[+]++>-++-(.)*132[-]--)*15

A very slow rush that leaves a trail of small decoys, using a simple clear.

ehird_defend8mwahahaha

Patashu_lazyCode: >(+)*5>(-)*5>(+)*5>(-)*5>(-)*5>(+)*5>(+)*5>(-)*5(>(-.)*128)*21[-]((-)*2048(+)*2048.)*2

impomatic_shadowCode: (>(-)*9)*2(>-)*7(>(+)*10[-])*20

A basic offset clear rusher that leaves slightly larger decoys than its predecessors, but no trail.

impomatic_spyglassCode: (>(-)*9>(+)*9)*4(>(+)*10[-]++--[(---.)*9999])*21

A basic offset clear rusher with a counter-shudder/vibration backup clear.

nescience_shadeCode: (>(-)*9)*2>(>-)*4(>[(>(+)*10[-])*20]{})%20

An anti-tripwire offset clear rusher with a mix of small and medium sized decoys.

myndzi_slowrushTrace and animationCode: >(+)*22>(-)*22(>++++++>------)*1>+>->->+(>[[-(+)*22[-]]+>[+(-)*22[+]]->]+)*21

The canonical slow rush candidate. Leaves several much larger decoys, and uses equally large offsets in its clear. Leaves a trail and alternates polarity on each cell due to the tendency of many people to alternate the polarities of their decoys. Contains several guards against vibration/shudder style programs.

ehird_the_unknowable_reversi_of_slowrushCode: >(-)*20>(+)*20>->+>->+>->+(>[[+-----------------[+.]]->]-)*20

An obvious modification of slowrush, possibly of an earlier version. This is the first champion program to use a 3-cycle clear (to foil simple lock defenders).

ais523_vibration_fool_fasterTrace and animationCode: >>>++++<----<++++<(-)*127.(-+)*50000

A vibrator that leaves small decoys, set up in a reverse decoy setup, in an effort to ensure that it has cleared its own flag before the opponent arrives. Its major method of winning is to cause the opponent to miss the presence of the flag altogether, due to the 1 in 2 chance that it happens to be 0 when the opponent arrives; the rest of the time, it also has a chance to win the same way any other vibration program does.

myndzi_3passCode: >+>->+>->+>->+>---<++<--<++<--<++<++(+)*16>(-)*16>(+)*16>(-)*16>(+)*16>(-)*16>(+)*16>(-)*16(>[(-)*21[-[+]]](+)*19)*21

A fairly standard offset clear rush that constructs its decoys in three passes in order to give itself time to build bigger ones. In addition it leaves a trail of very large decoys, so it would be considered a rather slow rush.

Patashu_quickbeatinthestreetdanceonyo_feetcausethisissoneatCode: +(>[(-)*19[+]]>[(+)*19[-]])*15

An alternating polarity offset clear that leaves no decoys and takes forever to reach the other flag. It's a wonder this thing ever won.

Patashu_rushpolarityCode: >(+)*20>(-)*19>(-)*19>(+)*19>+>->->+>([(+)*19[-]](+)*15>[(-)*19[+]](-)*15>)*11

leonid__ughCode: ((>(+)*97>(-)*97)*2(>[-[+]])*4(<)*7)*59

ais523_defend9Trace and animation (with syntax fixes to replace unbalanced brackets with ({})%-based compression)

A lock-based defensive program that times how long the opponent takes to clear a large decoy, and uses that information in order to switch between one of many different lock algorithms, each tuned for a different cycle length and polarity. The free cycles in the lock are used for a full-tape clear.

Patashu_weaveCode: -->([-[+]]--->>)*15

Patashu_2_3weaveCode: (>(+)*23>(-)*23)*1>+>->->+>+>-(>[(-)*20[+]]->[(+)*21[-]]+>+)*10

ais523_defend7Trace and animation (Warning: This will take a long time to load)

A simple lock-based defensive program, which uses one decoy to defeat tripwire-avoiders, and one tripwire to judge its timing correctly. The lock itself is designed to beat two-cycle clears with either polarity; for one possible polarity, the flag never becomes 0 not even for an instant, preventing the opponent switching to a different sort of clear loop in order to break free. Free cycles in the lock are used for a full-tape clear.

jix_wiggle3

2010[edit]

jix_wiggle3 and myndzi_slowrush fought for first during 2010, no other competitor ever achieved first place.

2011[edit]

ais523_defend10

An evolved version of defend7. The main difference is a simpler and more efficient lock, that uses 256-cycle rather than 128-cycle intervals; this allows the full-tape clear to be shorter, simpler, and faster.

myndzi_carelessTrace and animationCode: >+++++>+++++>----->----->+>->>>((>[(-)*126(-.)*3)*22(])*22)*22

ais523_defend13

A complex defence program that switches between several different strategies depending on what its opponent does. The program uses two reverse tripwires for the purpose of detecting whether the opponent is a rush program. Assuming either is tripped, it sets a regular tripwire nearer its flag, and observes the way it is cleared in order to attempt to determine the opponent's polarity (on the assumption that the opponent will likely use an offset clear, and thus trip the tripwire for one cycle first, then two cycles a little later, on only one polarity). It picks an appropriate lock algorithm based on the opponent's behaviour, generally assuming a two-cycle clear. Additionally, if the opponent appears to be stuck on the tripwire cell, it assumes a two-cycle clear and attempts to lock it there; should it escape, it assumes that it got the polarity right but the interval wrong, and uses a lock algorithm that works for multiple cycle lengths but only one polarity on its own flag. If the antitripwires are never tripped at all, it eventually assumes that the opponent is using a defensive program, and switches to a five-cycle rush algorithm that evades most locks.

ais523_decoybooster2Trace and animationCode: (>)*7++<(-)*85(<(-)*85<(+)*85)*3(-)*43(>)*8(>[(+)*5[-.]])*21(+(.)*5)*10000

A slow rush program using reverse decoy setup to set several very large decoys (the first being small to avoid outright loss to tripwire avoiders). It actually contains a bug due to miscounting the number of decoys; although it means to change its own flag in order to avoid careless clears, it does so in an inefficient manner. It uses a three-cycle offset clear in order to defeat defence programs.

quintopia_wirelessTrace and animation

A slow rush with a large offset clear, a reverse decoy build of rather larger decoys, a flag decrement to foil turtles, and an alternating polarity clear to mess with the timing guessing of things like defend9. Uses a 3-cycle clear and anti-shudder techniques. Also tests a cell is nonzero four times before attempting to clear it to outwit small reverse tripwires in tight loops.

quintopia_wireless_frownieTrace and animation

Uses a reverse decoy placement, plus a novel reverse offset clear. wherein it tests the value of the cell after every bump in the offset 25 times before decrementing and beginning a standard 3-cycle clear with shudder defense. The fact that it has to waste over 30 cycles after clearing a cell slows it down, thus further confusing defense programs. Other than this innovation, it's basically identical to the original version of wireless.

Gregor_mapping_turtleTrace and animationCode: -(>(+)*10>(-)*10)*4>([(+)*120(+.)*16.+>]+>[(+)*120(+.)*16.->]->)*11

Simple decoys and a careless turtle clear with a range of +/-8, leaving a trail of 1s and -1s. Takes advantage of the fact that taking the time to substantially change your flag is too expensive for many other opponents, but leaves you vulnerable to turtles.

quintopia_i_like_turtlesTrace and animationCode: (+)*17>>>>(+)*33<(-)*65<(+)*91<(-)*128>>>>>>>>([-[++[(+)*15[.-]]]]>)*21

A basic 3-cycle offset clear rusher with a reverse decoy build. Primarily intended to defeat the slew of "turtle" warriors that assumed the flag was close to 128. The fact that this made it a champion reflects only the make-up of the hill at the time.

Gregor_high_fructose_corn_philipTrace and animation

Essentially a careless turtle clear with the slight twist that it first checks within a small range of zero to avoid very small obstacles.

Gregor_sucralose_philipTrace and animation

Same as high_fructose_corn_philip, but after finding four decoys, switches to a simple two-cycle clear strategy to avoid spending too many cycles on closing loops.

Gregor_lead_acetate_philipTrace and animation

Same as sucralose_philip, but now with a quick offset of 64 before starting the inner clear strategy for both big decoys (which were popular at the time) and starting off the flag low.

quintopia_space_elevatorTrace and animation

Utterly insane.

Deewiant_pendolinoTrace and animationCode: ->++(>)*5->+>+(>[-([+{[(+)*8[-].[.+]]}])%3])*2(+<)*4(+)*23<(-)*23<(-)*30<(+)*30<(-)*30<(+)*29(>)*9++(>[-([+{[(+)*8[-].[.+]]}])%3])*19

Bumps its flag to avoid simple careless clears before heading off with a fast rush for tape lengths 10 and 11. If the game is still on, it then backtracks to place decoys. Uses a clear that is adept at taking out small decoys and is typically shudder-proof, but can be tricked by locks and vibrators.

Gregor_furry_furry_leather_discipline_girlsTrace and animation

furry_furry_leather_discipline_girls is an extremely complicated slew of multiple strategies. The algorithm is something like this:
  • First leave a trail of small decoys (rule-of-nine length)
  • Now, using the poke strategy, find the enemy (still leaving a trail)
  • If we poked them at cell (0-indexed) 10 or before, set up about four decoys by the flag then use sucralose_philip.
  • If we poked them later:
    • Go back to the fourth cell. If it is not equal to 1 (what we set it to), the enemy is super-speedy and has been here, so switch immediately to sucralose_philip (no additional decoys since we suspect they're super-fast and probably on our flag, they have small or no decoys).
    • If the fourth cell is as we expect, then set the previous two cells to very large decoys (+/- 97, respectively)
    • We now treat the fourth cell as a tripwire, to very-slightly synchronize with the enemy.
    • If the fourth cell does not trip within 1000 cycles, we assume the enemy is either defensive or very clever, and switch to an extremely-conventional offset clear rush.
    • When the tripwire is tripped, we switch to a triplock strategy, going to the detected cell and spending 66 cycles in a two-cycle clear, then returning and simply doing (+)*255 or (-)*255 at the inner decoy. We go back and forth doing this until all cells are cleared, in hopes of locking the opponent at our inner decoy.

Deewiant_allegroTrace and animationCode: ->++>-->>+>>->+>+(>[(+)*9[-].[.+]])*2(+<)*4(+)*23<(-)*23<(-)*30<(+)*30<(-)*30<(+)*29(>)*9++(>[(+)*16[-].[.+]][-[+]])*19

Gregor_furry_furry_strapon_pegging_girlsTrace and animation

This program introduced two new strategies, the deep poke and breadcrumb decoys. It starts by doing a deep poke against the opponent, then goes back, building as many as three large decoys while filling every other intervening space with breadcrumbs. Then it reverses, turning every breadcrumb decoy into a large decoy until one has been perturbed. Finally, it advances to the location it found by the deep poke and uses a simple rush with offset clear and shudder avoidance from there.

ais523_waterfall3Trace and animation (warning: very long and very slow to load)

A defence program based on a series of locks; as each lock is broken, it reveals more information about the opponent's strategy, giving an idea of which lock to try next. It starts by setting up some small decoys for the purpose of not losing horrifically to pokes, and some reverse tripwires in order to be able to detect being overtaken by fast rush programs, then starts a reverse decoy setup, periodically interrupting to check the tripwires. If it notices that any have been tripped during the decoy setup, it switches to a simple two-cycle lock. If the opponent does not interfere, it sets a series of large decoys, many of which are also used for locking or as tripwires later. An advanced reverse tripwire is then periodically checked for a while to see if the opponent is attacking; and a reverse tripwire much nearer the flag is checked more frequently, in case the advance tripwire is detected somehow. (If the tripwire near the flag is tripped, it attempts a triplock combined with a full-tape clear on the cell next to its flag; should it find that the cell it's trying to triplock on is unexpectedly 0, typically a sign that the lock has been broken, it switches to a two-cycle lock on its flag, written with the assumption that the reason the lock was broken was due to a two-cycle reverse offset clear with the polarity that would break the lock, given the relative lack of information.) Another possibility is that neither tripwire will be tripped for a long time, indicating a passive or waiting enemy; in such a case, it switches to a 4-cycle anti-shudder reverse offset clear (a combination which none of the defence programs at the time were capable of locking; although 4-cycle clears are vulnerable to 2-cycle locks, making them reverse offset clears avoids that issue), with an unusually large trail, on the basis that the opponent is probably defensive enough that it might actually have some effect. More commonly, the advance reverse tripwire (8 cells from the flag) will be tripped first (as opposed to the early tripwire, or neither tripwire), in which case the program's main strategy begins.
Unlike many other programs, waterfall3 uses the tape for computation (rather than just in an attempt to confuse the enemy); the cell 2 cells from the flag is maintained blank for that purpose, and once the cell 8 from the flag has been seen to have been attacked, its value is changed to distinguish it from a reverse tripwire on the cell 3 cells from the flag. Then, an "offset tripwire" strategy is used, where it attempts to offset-clear the cell 7 from the flag (which has a large decoy on), except that it stops after a while and uses the cell as a tripwire instead. (The idea is to synchronize with the opponent, but to start moving again rather than go into an infinite loop if the opponent had already cleared the cell and left a trail.) In order to break out of its loop safely, it moves back to the cell 2 from the flag if it detects a zero, so that its flow control is not disrupted by enemy trails; and it then uses the reverse tripwire on the next cell to detect whether it made such a move or not. Meanwhile, it also tries to detect enemy careless clears (which would otherwise leave it stuck on its tripwire forever), which is only successful on one polarity; if it does, it goes and deletes its own decoys, in order to prevent decoy-counting careless clears (which were high on the hill at the time) changing strategy on the basis that the clear seemed not to be working, and thus letting them fall off the end of the tape (and meanwhile, trying to triplock a different cell just in case the "careless clear" was actually a misdetected reverse offset clear). Once this feat of synchronization has been accomplished, it moves onto its first actual lock.
The first lock is a 3-cycle lock on a large decoy 6 from the flag. It has two major purposes. First, it locks 3-cycle programs with the right polarity, like any other lock does. (If the lock seems to be holding, the cell before is converted to a reverse tripwire, then it alternates between locking and checking the reverse tripwire to see if it really is a perfect lock or not. If it is, it simply does a full-tape clear while maintaining the lock, randomizing the polarity of its clear in order to defeat defence programs on short tapes which have been misdetected due to an unfortunate clash of decoy patterns.) Second, the length of time it takes to break the lock, for the vast majority of programs that happen not to be 3-cycle clearing with the desired polarity, gives away what polarity the opponent is using for their clear, because a large decoy takes much longer to clear with a 2-cycle clear and a 3-cycle lock in opposite directions, than in the same direction. (This is the main difference between waterfall2 and waterfall3, incidentally; and also the most common reason for waterfall3 losing, as it can end up getting accidentally locked in the process due to bad timing interactions on the loop in question causing it to not notice that the cell was temporarily zeroed, something which means that changing the value of constants slightly can drastically affect its performance. The version that came first on the hill had a genetic algorithm tweak the constants until they beat all other existing programs.)
If (or most likely when) that lock is broken, the next lock depends on the polarity in question. If the 3-cycle lock had the right polarity, a standard 2-cycle lock is done on a decoy two squares before (so that enemies that alternate polarity in their clears will be on the same polarity as they had on the cell where their polarity was detected). (It's used first to finish decoy setup, then to do a full-tape clear). A reverse tripwire before the cell it locks on is also checked during the lock, to see if it was broken; if it was, then it triplocks with an inline clear (to keep the length of the program down) on a decoy on the cell next to the flag (and if even that triplock is also detectably broken, it moves back to its flag and shudders in the hope of salvaging a draw). If the 3-cycle lock had the wrong polarity, the setup is similar, except that it maintains two locks at once (on two different cells), using the spare cycles in the 2-cycle lock to maintain the 3-cycle lock and vice versa. This leaves only a small number of cycles to do decoy setup and full-tape clear, not to mention the reverse tripwire checks, but it's enough to maintain it over the majority of the tape. However, this is sufficiently slow that the full-tape clear is in danger of not finishing before the cycle limit, so if the clear reaches the 5th-from-last cell and still no program has won, it instead uses its locks to set up large decoys on every cell between the lock and the flag, and then changes to a standard 2-cycle offset clear rush on the remaining cells. (This is the codepath shown in the trace-and-animation above, and takes over 97000 cycles to win, dangerously close to the cycle limit.)

ais523_slowpokeTrace and animation

Another program based around the deep poke strategy. The main difference between it and similar programs was the relatively fast decoy setup (designed to beat other deep-poking programs), and the use of a two-cycle anti-shudder offset timer clear, to beat rush programs quickly whilst still evading locks.

2012[edit]

david_werecat_dreadnoughtTrace and animation

Leaves a trail of alternating small decoys until the enemy is found, then switches to the defensive. If the enemy is found early or late, the tape size is known and so the program will seek directly to their flag. While in the defensive, it tweaks the flag and strengthens the decoys using a 2n scheme, placing one decoy per every second space before the enemy was found with a maximum of 6 or 8 decoys. The program then seeks forward to either the tenth space or where the enemy was first found, whichever is further. It then uses an order 6 fast clear and an order 38 offset clear to attack. The clear is also offset with a secondary clear with reverse polarity to confuse intelligent programs. If a cleared space is re-enabled after 3 cycles, it moves onto the next space since the enemy is probably using a triplock.

quintopia_space_elevatorTrace and animation

Lays two reverse tripwires in opposite directions before running off to do a fast/shallow poke, leaving a minimal trail as it goes. Upon identifying the enemy, it backs up and leaves a medium-sized decoy to delay slow rushers while it does further processing. Then it backs up to check its reverse tripwires, leaving a size 1 trail along the way to slow down tripwire-avoiders long enough to put decoys in front of them.
If either are tripped, it assumes it is facing a fast rusher on a short tape, which therefore has few/small decoys. In this case, it runs back to where it poked and starts a reverse offset clear rush under the assumption that the fast-rushing opponent is already working on its flag. If it finds a large decoy at the position it poked to, it will tear it halfway down, then return to its own flag to repair it. This code path is illustrated here: Trace and animation. If it does not find a large decoy, it will clear the small decoy it found, return to its own flag, then wait a while before repairing it. (Hopefully, it waits long enough that the opponent has made significant progress on the flag, though, without proper synchronization, it sometimes fails.) It then returns to its regularly-scheduled reverse-offset clear rush, praying that it bought itself enough time to finish off the opponent's flag. This code path is illustrated here: Trace and animation.
If neither are tripped, it bumps its own flag to foil careless and reverse offset clears before building more very large decoys backwards from the first decoy it laid. Depending on how far away it believes the opponent is, it will lay as many as nine more decoys this way. The decoys do not alternate polarity, but rather change polarity in an unpredictable fashion. If the opponent was poked at a greater distance, it finishes its decoy build before attacking. If the opponent is believed to be close, it will build two decoys, rush the opponent long enough to clear two more cells, then return to build a third decoy. This is so that, if the opponent was detected because the tape is actually very short, it will avoid wasting more time building decoys against opponents who are already attacking its flag. After it returns to build this extra decoy, it assumes it must be on a longer tape and rushes ahead to two spaces ahead of where it knows it is safe to go. This causes it to suicide against some opponents on certain tape lengths, but successfully compensates for the fact that it builds far fewer decoys in this situation by ignoring some of the opponent's decoys. This code path is illustrated here: Trace and animation.
The rush it uses checks for small decoys before using a clear with a very large offset. This large offset is a disadvantage against opponents who use lots of small decoys, but a significant advantage against opponents using large decoys. This large offset, combined with the fact that it changes the polarity of its clear after two cells have been cleared, also serves to confuse defenders who try to determine what sort of clear it uses. It has simple anti-shudder, anti-triplock, and anti-vibration tactics built in, and leaves a trail of size 2.

david_werecat_leviathanTrace and animationCode: (>++>-->-->++)*2((+)*6<(-)*6<(-)*5<(+)*5<)*2--(>(+)*50>(-)*42>(-)*46>(+)*48)*2>>>(([----[+[+[+[+[+[+[+[+[(+)*38[-][+][+--]]>{}]>]]]]]]]]>)%21)*21

Sets up eight large decoys using multiple passes, then moves to the twelfth space to commence its attack. The clear strategy is an order 4 wiggle clear paired with a order 38 offset clear. It also utilizes several methods to avoid locks; such as polarity reversal, a four cycle vibrating clear and a loop escape mechanism.

quintopia_aTrace and animation

Leaves a series of reverse tripwires moving away from the flag until evidence of the opponent is encountered. If this happens early, a fast rush is attempted. Otherwise, a medium-small decoy is left at the 11th cell and larger decoys are built in a forward setup away from the flag until one of the reverse tripwires is found tripped. (This is the breadcrumb decoy strategy.) Then, the decoys behind this decoy are increased until they are 85 tall (which is the tallest reasonable size for a decoy, since an offset higher than this would be madness unless it were a reverse clear). Finally, it rushes beginning from a cell that is further ahead the further away the opponent was first encountered. It uses a wiggle clear with offset 70, the largest offset ever used to date. This large offset causes it to lose against opponents who leave many small decoys and use small offsets, since, having spent less time building decoys, they will have made more progress through the reverse tripwires by the time the forward decoy setup reaches them, and since quintopia_a requires around 240 cycles on average to clear even a reasonably small decoy. This program builds at most 10 large decoys, so it can be defeated also by programs that build many decoys (such as Gregor_furry_furry_strapon_pegging_girls on long tapes). Compare the two versions of the breadcrumb decoy strategy used by the two programs jousting in the "Animation" link above.

quintopia_space_hotelTrace and animation

An upgrade of quintopia_a. It adds a space_elevator-style poke, beginning in the middle of building the decoy at the 11th cell, and behaves differently depending on far away it finds the opponent. It builds decoys using quintopia_a's strategy before returning to the poked position. If it found the opponent close to its decoys, it will skip several cells past this position, assuming those cells contain decoys. If it finds the opponent far away, it assumes it's facing a fellow slow rusher and builds a few extra small decoys in front of its decoy build on its way to the poked position.

2013[edit]

ais523_anticipation2Trace and animation

The code that generates this program (the program itself is heavily golfed via the generation script, so that it fits within implementation limits of the egojoust hill)
A vibration program with heavy synchronization. It starts via a complex (mostly reverse) decoy setup to buy time for its synchronization pattern. (The decoys used for synchronization themselves are only set up partially to start with, and start to be enlarged to the required height just before the opponent reaches them, using the principle that decoys can be set faster than they can be cleared, in order to save time in the initial decoy setup and thus increase the chance it completes before the enemy gets inside it.) Two tripwires are used to check whether the enemy has nonetheless got inside it; if the one nearer the flag is tripped, it instantly switches to a lock and full tape clear algorithm (from shudderlock) on the flag, because the opponent is probably there already, and if the one further from the flag is tripped, it synchronizes on a tripwire and then uses the shudderlock algorithm from there.
If the decoy setup works, anticipation2 tests how long the opponent takes to move on from clearing a very large decoy to clearing a size 1 decoy. (The large decoys are used to reset any special-casing that the opponent might be using for small decoys that might leave them in an unusual place in their control flow; anticipation2 relies heavily on the opponent doing the same thing in the same circumstances.) Most programs will only take a few cycles to clear a size 1 decoy no matter what was before it, but there are exceptions (and the exceptions make up the bulk of the program, which is just repeats over and over again for the various possible times). What anticipation2 is actually trying to measure is not when the cell is cleared, but when the cell is tested for zero; it does this by assuming that cells are adjusted immediately after zero-testing them and finding them nonzero (which is true in the vast majority of programs), because doing anything else would simply waste time. Obviously, half the time, the cell will be adjusted in the wrong direction and anticipation2 won't be able to observe the zero test; in order to allow for this, it does two tests, one for one polarity, one for the other polarity, and two cycles apart (in order to leave the enemy program on the same polarity if it alternates polarity).
When anticipation2 has a good idea of when the opponent's zero test will be (or failing that, when it sets the size-1 decoy to zero, which is always observable), it sets up the same situation as the situation it had already measured, but with the size-1 decoy as its own flag. Then it sets it to zero on, hopefully, the cycle when the opponent zero-tests it; and because most programs don't test cells that were zero when encountered again before moving on, those programs fall off the end of the tape. (As such, anticipation2 is a true vibration program; its main method of winning relies on setting its flag to zero when the opponent encounters it. It was actually written as a follow-up to a vibration program doing unexpectedly well on the hill.)
If the game is still continuing at this point, the primary strategy has failed, but there is a strong secondary strategy: it has a very good idea of when the zero occurs in the opponent's clear loop, which allows shudderlock's lock algorithm to be used (it's independent of the cycle length of a clear, as long as it's an integer, but requires knowing when the locked-on cell is approximately zero). The lock is combined with a full-tape clear, and beats many programs that are running enough counter-vibration to not lose to the main strategy.
There is one other codepath: if none of the tripwires are tripped for 8000 steps, it assumes that it's facing a defence program, and rushes it (very slowly) with a 5/3-cycle clear algorithm with antishudder and antivibration. (Non-integer clear loops are very slow because they inevitably end up missing the fact that they've zeroed the cell they're on more than half the time, and as such end up having to clear it multiple times before being able to move on.) No defence programs at the time could lock that sort of clear, and it seems unlikely that any will be developed.
The standard example program beats anticipation2 because its complete lack of antishudder/antivibration/wiggle causes it to move from one cell to the next faster than anticipation2 can detect it, so the example linked above shows anticipation2's performance against a typical slow rush program.

ais523_omnipotenceTrace and animation

omnipotence has properties both of a defence program, and of a fast rush program. It starts off with a slow poke that clears and continues poking upon encountering any decoys of size 1, 2, or 3; as such, against the programs common at the time that do a poke or slow poke and just leave a few decoys to detect fast rush programs, it pokes all the way to the enemy flag. The enemy will probably poke all the way to omnipotence's flag at the same time (especially because it's intentionally tripped the enemy tripwires to encourage them not to bother with their normal decoy setup), but it's designed to allow for this. Alternatively, if the opponent is a rush program that doesn't poke, it will just move to omnipotence's flag naturally, because it sets only one decoy (of size 1). (The decoy is increased to size 5 after the poke is finished, and serves to slow down programs that are confused by small decoys or that don't poke yet spend a long time on their own decoy setup. Perhaps surprisingly, such programs actually exist.)
After the poke, it moves back to its flag and adjusts it (first down, then back up again); this forms the start of a lock algorithm. (This is required because the opponent has probably made progress on omnipotence's flag, and thus would clear first in a straight race.) After fixing its flag, it moves to the poked location and starts clearing it with a reverse offset clear (returning once during the clear to its own flag to repair it). If the game is still going at this point, the poke failed to find the opponent's flag (e.g. against traditional non-poking slow rush programs, or against defence programs), or found it but it had an unusual value (shudder/vibration programs, or programs with really extreme anti-turtling). It continues in such cases with an attempted lock on its flag. Due to the complete lack of synchronization, it uses defend7's lock algorithm: against 2-cycle clears, this gets a perfect lock 9/16 of the time, a detectable lock (i.e. one that the opponent can break out of via noticing the flag not being zero just after it was cleared) 3/16 of the time, and simply loses 1/4 of the time. (This still gives it a good win percentage against a majority of programs.) It tends to lose quickly against programs that don't use a 2-cycle clear loop, though. However, because it intentionally trips enemy tripwires early, opponents tend to conclude they're facing a fast rush program and thus don't use countermeasures against defence programs, and so the lock is broken less often than a typical defensive lock would be.
While locking, its own clear is a modified full-tape clear designed to do well against defence programs. (Against rush programs that are correctly locked, it doesn't matter how long it takes to win, because it will win eventually, and it'll lose anyway against timer clears that aren't beaten quickly, so optimizations against defence are worthwhile.) As such, it attempts to clear the detected flag location twice in both directions, and the two cells after it once in both directions, before moving on. (Other cells are just cleared once. Just in case there's some program which it's still in race with that's moving really slowly.)
omnipotence also has some shameless special casing against a couple of programs (waterfall3 and space_hotel); it detects them via recognising their decoy setup, and switches to a very fast rush algorithm against space_hotel (a wiggle clear for getting past its decoys as fast as possible, and a reverse offset clear for its flag, probably the most all-in of rush strategies), and a very slow rush algorithm against waterfall3 (a 7-cycle full tape clear which intentionally corrupts tape elements that waterfall3 normally uses for calculations; being 7-cycle prevents it being tricked off the end of the tape, and being a full tape clear prevents it being locked).
The example linked above shows omnipotence picking on its natural prey, a slow poke program (ais523_slowpoke). (Although it beats the standard example program, and on every tape length and polarity, it does so via a full tape clear, so the resulting trace and animation takes a long time to load.)

Oj742_smartlockTrace and animation

smartlock is a program that uses an absurd amount of timing cases based on multiple, irregular tripwires to determine the polarity, offset, cycle, and other properties of the clear of an opponent program, so that an accurate lock can be created. The standard cases assume a 2-cycle or 3-cycle clear of a certain polarity, an offset (near the values 0, 16, 32, 64, 128, or 256) of another polarity, and whether a wiggle clear is used. To prevent any kind of irregular/timer clears from breaking the lock, the program attempts to trap the opponent on a decoy flag for a large number of cycles. If they break free, the program switches to shuddering the flag and hopes for the best.
The lock itself is more dynamic than the standard lock strategy, as it skips any cell that has a value of -1, 0, or 1. To do this, it uses three cells for computation, which have to be cleared before the lock begins. If they cannot be cleared quickly enough, the program modifies the decoy flag to buy some more time, then switches to an offensive strategy.
There is also quite a lot of special casing against programs smartlock normally wouldn't be able to beat. For most of them, it's simply a lock that is different from the standard cases, due to an abnormal clear method and/or an offset that tricks the program. However, some make the program switch to a different (and likely offensive) strategy, specialized to work against the program that it thinks its up against.
smartlock's backup offensive strategy is a combination of large decoy avoidance, timer clear, and reverse offset clear. It's anti-defense strategy (which is used if the first tripwire is not cleared within 6200 cycles) involves a complex flexible timer clear based off of Oj742_smart_timerclear.

2014[edit]

ais523_preparationTrace and animation (warning: very long and slow to load even in 2014)

The dramatic debut of the probabilistic lock strategy. preparation follows a variety of different strategies:
Initially, it sets ten decoys (most of which are subsequently used as tripwires). This causes an immediate loss on tape length 10, but the tenth decoy gains more against tripwire avoiders than it loses against programs which might actually be beaten on tape length ten.
It then checks for a clash in decoy setup via checking to see if the eighth of these decoys has been disturbed. If it has been, it switches to a fast rush strategy based loosely on ais523_stealth; it moves right, attempting to preserve the structure of the tape, via undoing the ninth and tenth decoys and then using a method (adapted from a wiggle clear) that can preserve with many but not all sequences of decoys valued 1, 2, and 3 (specifically, it can only move forwards, or one step backwards, in the sequence of decoy values 0, -1, 1, 2, -2, -3, 3, 0, 1, -1, -2, 2, 3, -3, -4, 4, 5, -5. Upon finding a cell with a larger value, it's most likely a flag, and thus a reverse offset inflexible timer clear (with anti-vibration; the timer is used to beat shudder programs) is used. This algorithm works well against the dominant-in-2014 poke-and-slow-rush programs that use reverse tripwires to guard against fast rushes; restoring the value of the tripwire means that the opponent often doesn't realise that its flag is under attack and continues setting decoys rather than taking countermeasures.
If there wasn't a clash of decoys, the first seven decoys are all then raised to size 2 and then 3, checking in the process to see if they've been zeroed (which is faster than a true reverse tripwire check). If any have been zeroed, it assumes it's facing a fast rush program that set only minimal decoys, and switches into a very fast rush algorithm, moving forwards until it finds a cell of magnitude 9 or larger, then trying to clear values near 128, then if that fails, switching into a three-cycle clear in the other direction (which at this point is effectively an order-136 offset clear, which completely throws off the synchronization of any defence program that might be intentionally tripping tripwires to disguise itself as a fast rush program. If there appears to be time (i.e. the opponent was found far from the flag), it sets some small decoys to aid with this; the first decoy is increased to size 12, and if the enemy was detected on the second check, the second and third decoys are increased to size 52 if they are undisturbed.
At this point, the eight decoy is increased to be a very large decoy; this is the cell that the opponent will be locked on. Before the lock starts, the first seven decoys are checked once more, this time checking them to see if they have the expected value of 3, rather than just if they're zero. If they're found to have been disturbed, their actual value is checked to gain an idea of the enemy's activity on the cell; values near 3 are considered to be small decoys, values near 0 to be clears/trails, and other values to be large decoys. If the enemy seems to be clearing, they're probably already on the flag; the flag is repaired, then a fast rush (similar to the previous fast rush strategy but simpler) is used, with the starting point estimated as the ninth cell after the first cell cleared (which is the enemy flag, if the enemy is using the rule of nine). Otherwise, the opponent is probably among the decoys, and so each undisturbed cell is made into a large decoy before entering the clear loop; an attempt is made to detect whether the opponent is actively clearing via checking the order in which the decoys are removed (under the assumption that a clear loop moves forwards, and a decoy setup moves backwards because reverse decoy setups are so common), but this is only used to decide whether to start at the 11th cell or to the ninth cell after the first cell cleared (as in the previous case).
The program then starts the probabilistic lock loop. It does the following things with its spare cycles:
  • First, it checks the first seven decoys to see if they have the expected values. Again. (This is the fourth time, for people counting.) If the decoys are broken at this point, the assumption is that outracing the opponent is impossible (it's probably on the flag, and probably has too many decoys to race). Thus, it switches to the defend10 strategy, after waiting 128 cycles (spending the time engaging in counter-turtle tactics) in order to get a good estimate of synchronization with the enemy. During this time, a 16-cycle gap is left in the probabilistic lock.
  • The lock is strengthened to a 15-cycle gap for the rest of the program. It now spends its time building a large decoy on two cells to the left of the lock cell. It repeatedly checks tripwires to be able to observe the lock breaking. If the one near the end collapses, it uses one of five algorithms depending on how much progress the opponent seems to have made:
    • If the opponent appears to be on the flag, it shudders the flag in the hope of a draw.
    • If the opponent appears to have made a lot of progress but not quite reached the flag, it uses a lock on cell 1 and a full-tape clear.
    • If the opponent has disturbed distant cells but not nearby ones (perhaps due to tripwire avoidance), it shudders on the flag, using a shudder algorithm designed to maximise the chance of a draw against two- and three-cycle clears (produced via computer search on all repeating sequences of six +-. commands).
    • If the opponent appears to have made only marginal progress (i.e. the cell to the left of the lock cell is not near zero), the program's main strategy is replicated but moved to the left one cell, giving a second try at getting lucky with the probabilistic lock. If the lock breaks a second time, a shudder is attempted on the flag (because the most likely reason to break two probabilistic locks is that the opponent has broken anti-shudder mechanisms).
    • If the opponent has cleared the cell to the left of the lock cell, but not the cell to its left (this is quite a likely codepath, as the cell to its left was a small decoy, and the cell to its left was much larger), this works mostly the same way as the previous case, except one further cell to the left. However, in this case, there is a serious risk of not being able to set up enough decoys. Thus, the lock is held much longer than is necessary to set the decoys; in fact, it's left until just before the cycle limit. The idea is that if the opponent has set few or small decoys, there will still usually be enough time to take its flag; but if it has set enough decoys that it would clear first, it runs out of time before being able to take preparation's flag.
  • Once this decoy is large enough, preparation continues by building two more large decoys. One tripwire continues to be checked; if the tripwire is broken, the most likely reason is a timer clear, and preparation reacts by abandoning the lock attempt, just setting decoys on all remaining cells, and then racing. A timer clear is used in case the opponent is a lock-based program that uses no synchronization (and probably thinks it has preparation locked on an entirely different cell); it wouldn't do to run right into the lock and make that program's incorrect assumption correct.
  • After this point, checking the tripwires is abandoned in favour of making yet more decoys. There are four more remaining cells, each of which is made into a large decoy. Then all the decoys are adjusted to size 128, mostly for aesthetics.
At this point, the lock is no longer necessary; no matter what, preparation is planning to rush. (It's taken over 30000 cycles to reach this point; doing things in the spare cycles of a probabilistic lock is slow.) However, it first waits in place for 1280 cycles to see if the lock cell touches zero. The reason is that there are two reasons the program could reach this point; either the opponent was clearing and successfully locked, or the opponent was passively defending and never even reached the lock cell. Two different clear algorithms are used based on this:
  • If the lock cell was not zeroed even in 1280 cycles, the opponent is assumed to be a passive defender (within 1280 cycles, any clear algorithm with a denominator less than or equal to 5 will make the cell touch zero at some point, even if the non-integral clear algorithms might fail to actually clear it). The clear algorithm used is a "normal" two-cycle clear (with no offset); however, every 828 cycles (512 times the golden ratio, which guarantees that every possible timing will be tried eventually), it changes the clear direction, or the clear parity (i.e. clearing on even cycles or odd cycles). This is guaranteed to beat even a probabilistic clear eventually. (Note that a reasonably fast clear algorithm is necessary, in case the clear attempt trips a tripwire that causes the opponent to start rushing; the seven max-height decoys might not necessarily be enough.)
  • If the lock cell was zeroed, the opponent is assumed to be a rush program that got caught up in the lock. The resulting rush is a very simple order-12 offset clear with nothing fancy involved at all, because the opponent is assumed to never be touching the portion of the tape beyond where the lock was. (Using a small order increases the chance of outracing even a slightly superior number of decoys.) This is the codepath shown in the animation above, and probably the one responsible for the most wins.

ais523_monolithTrace and animationCode: (>+)*4 (>--)*4 ((-)*5<)*4 ((+)*6<)*3 (+)*5 (>)*7 ((-)*20<)*4 ((+)*20<)*3 (+)*20 (>)*7 ((-)*20<)*4 ((+)*20<)*4 (+)*50 (>)*10 (>[(-)*4([+{[.---]}][.-[.-]]>(-)*12)%3000][..++-----[..++-----]])*21

A remarkably simple program compared to the other hill-toppers from this period. The basic idea is to set eight large decoys regardless of what the opponent does, then rush. Multiple layers of reverse decoy setup are used to beat fast rush programs (setting up the first layer of decoys using a forwards decoy setup to provide some measure of defence against pokes). Thus, the clear loop is specialised to beat slow rush programs that set a lot of decoys, via using only a small offset on the offset clear; it assumes that there won't be many small decoys to offset against anyway, and avoids wasting the time spent setting and then clearing the offset. Perhaps surprisingly, these tweaks are enough to be able to bulldoze past the much larger number of decoys that poke-based programs can often set, at least on medium-length tapes (where this program does best).
In order to deal with defensive programs, monolith uses an (inflexible) timer clear that falls into a 3/5 cycle clear (because nowadays, almost any reasonable integral clear loop can be locked by some program or other), and the now-standard comprehensive anti-shudder/anti-vibration countermeasures. (In particular, it is physically incapable of falling off the end of the enemy tape, because it will only ever move forwards after observing two zeroes in a row on its current cell.)

Lymia.nyuroki Trace and animation

This bot is actually very simple, despite the long final output. It starts at cell 8, and starts setting up decoys in reverse. If it encounters a set cell during this, it jumps straight to its clear loop, bypassing the skip to 14 on smaller tape sizes. Otherwise, it builds up 8 rather large decoys, and then jumps straight to cell 14. The actual clear loop checks the cell twice to deal with stuff like anticipation, and does an offset clear of size 10. This offset clear has a 500 cycle timer, after which it switches to an opposite polarity five-cycle clear. This five-cycle clear is also triggered if the cell is still set after the timer clear exits. After clearing a cell, it leaves behind size 1 trail. This warrior originated no innovations in strategy, but was the first champion assembled by a generalized BF Joust macro system created to simplify construction of such programs. (Although there has been a longstanding tradition of using scripts to generate warriors, all prior champions had been produced by special purpose one-off scripts.)

2015[edit]

ais523_growth2 Trace and animation

(The source is heavily golfed via a generation script; for comments and a readable algorithm, look at the generation script that's embedded in the source.) Starts by building small decoys until it reaches an enemy decoy (small or otherwise, it doesn't really matter; the idea is to not place decoys beyond a place where the opponent has definitely been, because they wouldn't do their job), or cell 17. The decoys change polarity every two steps. Then it goes back through the decoys, making them larger over time, and if the opponent does nothing, repeats until the ones nearer the starting position are around size 128 (those decoys are incremented twice as fast as the ones further from the starting position, because they're more likely to have an effect), and then rushes with an inflexible timer clear with many anti-defence protections (2 cycle before the timer expires, 5 cycles afterwards, and the usual anti-shudder protection). The flag is also adjusted after seven cycles, to avoid losing to careless clears.
If a decoy is observed to be zero while trying to make it bigger, growth2 assumes it was cleared by the opponent (the alternative possibility, that it was an opponent's decoy and the opponent uses a forward decoy setup, normally causes growth2 to lose). It checks the cell two squares back for values near 0; if the cell still appears to be far from 0, it sets a large decoy on that cell and every previous cell. Whether it is or not, it then rushes. In most cases, this uses the same clear loop as if the decoy setup wasn't interrupted by an enemy clear. Notably, this uses an offset (a small offset of 5) only for the first 99 cycles, and then switches to an offset of 0 (on the basis that the opponent can be assumed to have decoys larger than any sensible offset, and if you're not going to be able to out-offset the enemy decoys, 0 is the fastest offset to use). The rush starts nine cells from the enemy clear; this can often locate the enemy flag directly on the assumption that the enemy is using rule of 9 (although if the enemy leaves a trail, the clear only has a 50% chance of being observable (if the parity of the trail and decoy are the same, it can't be observed)).
If the opponent appears to be a fast rush program, the details are a little different. If the opponent is first seen within two cells of the flag, growth2 assumes its flag is under attack, and repairs it before starting the rush. And if the opponent is discovered on the very first cycle of checking the decoys, growth2 assumes it's facing a very fast rush program and uses a reverse offset clear for the first cell it clears (not counting cells near zero; the assumption is that a program that can clear growth2's decoys that quickly wouldn't have time to set large decoys itself).

2016[edit]

ais523_margins3 Trace and animation

One of the weirdest programs ais523 has ever written (and one that's short enough to have been written by hand, if still somewhat long). At a very broad level, the program starts by looking at the tenth cell (the first one that can be the enemy flag). If it's large, it tries to clear it; if it's small but nonzero, it does a fast rush (and abandons the rest of its strategy); if it's zero, it retreats and plays for a draw rather than a win. In other words, the margins series of programs cares about winning short tapes and drawing long ones, to produce a winning record overall. The scoring differences between the two hills thus make a huge difference, with margins3 coming #1 on zemhill, but #28 on egojoust (at the time of writing).
Looking at margins3 in more detail, it starts by setting a few decoys (reverse tripwire on the second cell, medium decoy on the third, then trailing up to the tenth – speed is very important for a fast rush, so only minimal decoys can be set). The codepath that gets most wins against aggressive programs is if the cell happens to be small (no larger than ±3) and nonzero, in which case the cell is left clear (margins3 has forgotten its original value), and it starts a stealth clear on the rest of the tape. This clear restores the values of nonzero cells that it encounters under some (common, but relatively complex to define precisely) circumstances, meaning that an opponent will be mislead as to how far it got (and may incorrectly think that the change to its most distant decoy is a clash in decoy setups). Once it finds a cell it can't restore (most likely a large decoy), it sets two size-60 decoys, at the locations 9 and 10 positions behind its current position (as it's lost track of where it is on the tape by now). Then it returns to the unrestorable cell, and does a sort of modified reverse offset clear; the reverse offset is -83 for the first cell cleared this way, and -50 for subsequent cells, meaning that in the common case in which the opponent sets very large decoys (≥50) by its flag, there's a 50:50 chance (based on polarity matchup) that it "turtle clears" the decoy. There's an inflexible timer (of 900 total cycles clearing) to fall into a 3/5-cycle clear; if the timer is hit against a non-defensive program margins3 has probably lost anyway, so it can afford to take anti-defensive countermeasures at that point.
The strategy for if the tenth cell is large or zero is very defensive (although if the tenth cell is large, margins3 will attempt to clear it before starting to defend in case the tape length happens to be ten exactly). It removes most of its own decoys (to defeat decoy-skipping programs, which would tend to beat it otherwise), leaving a reverse tripwire on the second cell (of size 1), a reverse tripwire on the fourth cell (of size 3), and a size 10 decoy on the third cell, which is used as a lock. Because margins3 is not attempting to win at this point, it can deploy a very strong lock (technically a probabilistic one, but with a very high chance of working): it locks for 122 out of every 128 cycles, using the other six to check tripwires. On almost every occasion, it checks the tripwire nearer its flag (which alternates value between 1 and 2 to make good use of spare cycles that are needed for parity reasons). Assuming it remains undisturbed, this continues until very near the cycle limit, at which point margins3 moves backwards one cell, sets a large decoy, then rushes to the twelfth cell and turtle-clears it. (In the case where the tenth cell was large rather than zero, the eleventh cell is cleared instead if it's non-blank, to avoid issues with running off the end of the tape; it's normally safe to assume that the tape is longer than 11 if the 10th cell is blank, though.) If the tape length isn't 12, this will cause a draw, as there is not enough time left for the opponent to zero the decoy with a 2-cycle clear and the flag with a turtle clear, the fastest sensible strategy.
If the tripwire nearer the flag is disturbed (meaning that the lock was broken), margins3 starts shuddering its flag (hoping for a draw or to trick the opponent off the tape; the opponent has already moved on once from a cell that it's unlikely to have been able to observe at zero two cycles in a row, given that margins3 changes the cell basically every cycle and thus would change it during the first zero test, making it nonzero for the second). It starts with a shudder designed to lock 2-cycle clear algorithms for 1024 cycles, then changes to a shudder designed to lock 3-cycle clear algorithms, in a crude (yet surprisingly helpful) method of defending against timer clears. This codepath tends to beat turtles and full-tape clears, and sometimes manages a draw or even win against more traditional clear loops.
The remaining cases involve the reverse tripwire further from the flag. This is checked once, on cycle 4780, and the strategy described so far holds if its value has changed (indicating, in almost all cases, that the opponent is trying to attack). On the other hand, if that tripwire is unchanged, the opponent may well be passive or defensive. In this case, continuing on with the standard go-for-a-draw strategy may be disastrous, as defence programs that decide to change to the attack after a long period of inactivity are often completely biased towards anti-defense measures and willing to forgo rushing speed to be as nasty to defensive programs as possible. As such, margins3 needs to use yet another different strategy.
The first thing it does in this case is to determine the reason for no change in the tripwire. The possible reasons are that the opponent is a defence program, that the opponent is a program that skips (or restores tripwires on) some cells, that the opponent has a size 3 trail, or that the opponent sets no more than one decoy and the tape length is exactly 12. To test for the first case, defend3 stays still, constantly zero-checking the lock cell but otherwise doing nothing, for 500 cycles. A defensive program won't zero it; other programs will. If it does get zeroed, margins3 immediately sets a very large decoy on the second cell, and zeroes the twelth cell (if the twelth cell turns out to be near zero already, it uses its spare time to zero the thirteenth cell instead; this won't hurt and has a chance of stealing wins); this handles the tape length 12 case. Otherwise (in the remaining two cases, which are luckily quite rare), it shudders its flag for the rest of the game, as the only real remaining chance to not lose.
Finally, if the opponent's been established as defensive, it attacks cautiously. (This is the codepath shown in the animation above.) First it places a maximum size decoy on every zeroed cell between its current location and the enemy's decoys, to buy itself time if the opponent starts rushing. Then it uses an inflexible timer clear on a very short timer to clear a total size of 100 enemy small decoys (after an offset of 5); this will quickly skip through small decoys, and yet bail out soon enough on large ones, whilst being impossible to lock (as margins3 always stays in control of its control flow). Once the timer runs out, it clears with a 3-cycle clear that changes position modulo 3 or polarity every 621 adjustments (the idea being that this will eventually guarantee hitting a clear pattern that's maximally unfavourable for an enemy lock). If the current cell is observed at zero (and the game isn't over), it moves backwards a little to adjust the timing immediately without getting stuck in a loop, thus eventually beating shudder and vibration programs too.