CodeBots 2: Event Driven Design

Welcome to Code Bots 2!

You've learned your lesson since the last Code Bots. You've tried to figure out more ways to fit more actions in less lines, and now you finally have it. You're going to make an event-driven Code Bot.

Your bot must consist of 24 lines. Each line follows one of the two formats:

Condition:Action


or

Action


Your bot also have enough storage to store 5 integers named A through E. An integer can store values from 0 to 23.

Each turn, you will execute line C, unless one of the conditions is true. If so, then C will then contain the line number of the conditional that is true, and then that line will be executed. At the end of each turn, C will be incremented.

There are the available conditions:

1. Start is true only on the first turn. You must have this in your code exactly once
2. BotAt(N) is true if there is a bot at the location defined by N
3. Equals(A,B) is true if A equals B. They can be different types, if so, they will not be equal.
4. Modified(A) is true if A was copied to during the last turn. A must be a variable name, a line, or a condition
5. Any(C1,C2,...) is true if any of the conditions are true
6. None(C1,C2,...) is true if none of the conditions are true
7. All(C1,C2,...) is true if all of the conditions are true
8. Not(C) is true if C is false. C must be a condition.

Variables can be in one of the following formats. The first 9 are numerical, and can be be used for whenever N is used in this page.

1. A,B,C,D,E
2. A number from 0 to 23
3. This will return the line number it is currently on
4. Add(N1,N2,...) will return the sum of all values
5. Sub(N1,N2) will return N1 minus N2
6. Mult(N1,N2,...) will return the product of all values
7. Div(N1,N2) will return N1 divided by N2
8. Mod(N1,N2) will return N1 mod N2
9. OVar(N) will accept a variable name, and will return the opponent's variable
10. Line(N) will return the Nth line in your code
11. Type(N) will return the Nth line type in your code (the types are the names of the actions)
12. Cond(N) will return condition on the Nth line
13. CondType(N) will return the condition type on the Nth line (the types are the names of the conditions)
14. OLine(N) will return the Nth line in your opponent's code
15. OType(N) will return the Nth line type in your opponent's code
16. OCond(N) will return the condition on the Nth line
17. OCondType(N) will return the condition type on the Nth line

A and B are for your personal use, C is used to determine which line to execute in your code, and D is used as a direction. Each value of D refer to a different square and direction pair.E produces a random value each time. D and E will be initialized to a random value, otherwise 0.

The direction used will be [North,East,South,West][D%4]. Your opponent is the bot in the immediate square in that direction.

There are 4 actions available to you:

1. Move will move you 1 square forward in the Dth direction. If there is a bot there, you will not move.
2. Copy(A,B) will copy the variable A to B. B cannot be a numerical value, except for a variable name. A and B cannot be of different types. Copying a line does not copy the condition.
3. Flag does nothing. The bot with the most flags in your code will get a point. The bot with the most points wins.
4. If(C,L1,L2) will perform the line on L1 if C is true, else performs L2. C is a condition, and L1 and L2 must be lines.

The Big Picture

50 copies of every bot will be placed in the world. Your goal is to get your flag into as many bots as possible. For each bot that has more of your flag type than any other flag type, you get a point.

The bots will be placed as follows:

B...B...B...B...
..B...B...B...B.
B...B...B...B...


There will be 10 games run, and points will be averaged across all of the games, determining who the winner is.

Side Notes

If multiple conditions apply, then the one that most immedately follows Start will be executed

The bots will be closely packed but you will not start neighboring another bot. (It techincally will be the same format as the last CodeBots)

As this challenge was not posted in the sandbox (to give nobody an advantage), I reserve the right to change small details for fairness, or additional capabilities. Also, if there is a bug in the CodeBots runner, I will change it, even if a bot depended on that bug for its success. I am trying to be as fair as possible.

Recursive If statements will not be executed

If your bot is shorter than 24 lines, the remaining lines will be filled with Flag

Remember when copying to your own C, that C is incremented at the end of your turn.

The CodeBots interpreter can be found here. It includes a .jar file for easy execution. Simply add your bot to the bots folder

Scores

1. 893.9 Borg
2. 1.3 LazyLioness
3. 0.9 Defender
4. 0.5 Flagger
5. 0.4 CliqueBot
6. 0.4 Insidious
7. 0.3 Attacker
8. 0.3 Gard
9. 0.3 SingleTarget
10. 0.2 FreezeBot
11. 0.2 Sentinel
12. 0.2 Driveby
13. 0.0 AntiInsidious
14. 0.0 MoveBot
15. 0.0 CliqueBorg
16. 0.0 Calculator
17. 0.0 TestBot
18. 0.0 Imitator

UPDATE

Lines of code are now rotated when you view your opponent's code. That means, your opponent's line 1 may be line 14 (or whatever line). A bot will have a fixed offset which will offset his lines by X amount when viewed by an opponent. The opponent's C variable will also be offset by the same X amount. X will not change within the same game, but it will change from game to game.

• Nathan: Are you able to check out "Lazy Lioness" to see whether the bugs I've reported are legitimate (or if I'm just out to lunch)? No rush. Just making sure you're aware of the submission.
– COTO
Sep 10, 2014 at 5:31
• @COTO Sorry, schools been crazy. I'll try to get to it tonight. Sep 10, 2014 at 17:01
• The 'All' condition could be made implicit for any comma separated list of conditions. It would make reading the entries a bit easier. Sep 11, 2014 at 11:27
• I think I found your bug. The FuctionParser objects are being used as keys in a HashMap which means you need a proper equals method. This fixes the problem with CliqueBot and likely Lazy Lioness as well. I sent you a pull request. Sep 11, 2014 at 20:47
• @ccarton the HashMap only memoizes the values, it isn't used for testing equality Sep 11, 2014 at 23:53

Borg

Converts all other bots into clones of itself. Resistance is futile.

Start:Copy(2,A)                               # Cloning will begin at line 2
All(Not(BotAt(D)),Not(Equals(2,A))):Copy(2,A) # Reset A if the opp left before we were done
Not(BotAt(D)):Move
Equals(A,A):Copy(Add(A,1),A) # Increment A. It will wrap around all 24 lines before the completion check matches


Edit: Small fix to reset A if the opponent moves before I'm done with him. Doesn't seem to affect the score but it makes me feel better.

Edit #2: Added a more complete check to ensure the cloning process has completed properly (line 3)

Edit #3: Update to handle the new random offsets. The difficulty here was that new clones would have their code located at random offsets which means they don't know the location of their own lines. That means that all references to my own lines must be relative (to This). Opponent line numbers can still be absolute since they are random anyway.

• @Nathan, did you use the latest version of this entry in the most recent run? Sep 14, 2014 at 22:43
• I am amazed that this bot is able to infect other bots so successfully. I'd love to see a rundown of how it works. Sep 14, 2014 at 22:49
• @ccarton no. I didn't realize it was updated. Rerunning. Sep 14, 2014 at 23:37
• @Sparr I've added some comments. Hope that makes it easier to follow. I think the bot is so effective because of the exponential effect of the cloning. Each bot it infects goes out and infects others. Also, they will naturally try to repair each other when they take damage. Sep 15, 2014 at 0:02

Flagger

Shoot for the moon

Start:Flag


And the rest gets auto-filled with flag.

Calculator

This bot doesn't understand the goal of this challenge, so he decided to calculate some numbers for the enemy.

Equals(Mod(OVar(E),5),0):Copy(Add(OVar(A),OVar(B)),OVar(D))
Equals(Mod(OVar(E),5),1):Copy(Sub(OVar(A),OVar(B)),OVar(D))
Equals(Mod(OVar(E),5),2):Copy(Mult(OVar(A),OVar(B)),OVar(D))
Equals(Mod(OVar(E),5),3):Copy(Div(OVar(A),OVar(B)),OVar(D))
Equals(Mod(OVar(E),5),4):Copy(Mod(OVar(A),OVar(B)),OVar(D))
Start:Move

• you should put the results into OVar(D) not A! Sep 5, 2014 at 14:41
• @MegaTom Done ;) Sep 5, 2014 at 14:44

CliqueBot

Flag
Start: Copy(11,B)
Not(Equals(Line(20),Line(21))): If(Equals(Line(21),Line(22)),Line(7),Line(8))
Not(Equals(Line(21),Line(22))): If(Equals(Line(20),Line(21)),Line(9),Line(10))
All(BotAt(D),Not(Equals(11,OVar(B)))): If(Equals(Line(20),OLine(OVar(C))),Line(10),Line(11))
Equals(1,1): Move
Copy(Line(21),Line(20))
Copy(Line(20),Line(21))
Copy(Line(21),Line(22))
If(Equals(Line(20),OLine(Sub(OVar(C),1))),Line(5),Line(12))
Copy(Line(20),OLine(OVar(C)))
Copy(Line(20),OLine(E))


Recognizes friends via their B value, fills everyone else's lines with flags. Also goes to some length to preserve the integrity of one of its own flags (this part is cute but probably not very useful).

Edit: Unsurprisingly, there appears to be a bug here somewhere, judging by the score.

Suspect that lines are 0-indexed and my code is 1-indexed. Should really have checked that earlier. Added a Flag at the beginning to bump everything up one.

• I think I found the bug in the controller. I sent him a pull request. Until he accepts it, you can try my fork if you like and let me know if it works for you. Sep 11, 2014 at 20:52
• The bug has been fixed in the latest version. Sep 13, 2014 at 11:58

Defender

Start:Copy(0,A)
Copy(0,B)
Flag
Flag
All(Modified(Line(2)),Equals(A,0)):Copy(1,A)
Copy(Line(3),Line(2))
Copy(0,A)
Copy(10,C)
All(Modified(Line(3)),Equals(B,0)):Copy(1,B)
Copy(Line(2),Line(3))
Copy(0,B)
BotAt(D):Copy(Line(2),OLine(E))


MoveBot

Start:Move
Copy(E,D)
Copy(-1,C)

• Shouldn't that be Copy(23,C)? Sep 4, 2014 at 18:16
• Negative values are now allowed. Sep 4, 2014 at 18:16

Attacker

Start:Move
Any(BotAt(0),BotAt(1),BotAt(2),BotAt(3)):Move
None(BotAt(0),BotAt(1),BotAt(2),BotAt(3)):Copy(E,D)

• BotAt(D):Copy(Line(X),OLine(E)) where line X contains Equals(1,1):Flag ... for fun Sep 5, 2014 at 18:35
• @Sieg Line copies only the action, not the condition. Sep 5, 2014 at 19:05
• My overpowered tactic :( Sep 5, 2014 at 19:08

Single Target

Start:Move
All(BotAt(D),Not(Equals(OVar(D),D))): Copy(D,OVar(D))
BotAt(D):Copy(Line(E),OLine(E))
Equals(A,A):Move


Will hunt you down and fill you with flags!

• The All condition needs a ) Sep 5, 2014 at 1:50

Insidious

Start:Flag           # comments -->                                                                                 # why move when we can fit another flag here?
Equals(E,0):Copy(Add(D,Sub(Mult(2,Mod(E,2)),1)),D)                                                                  # 1/24 chance to turn left or right
BotAt(D):Copy(Add(D,Sub(Mult(2,Mod(E,2)),1)),D)                                                                     # turn left or right if we've infected our target
Equals(A,A):Move                                                                                                    # move if all else fails, also infection freeze condition
Flag                                                                                                                # first of many flags


Similar idea to the bot by the same name in the previous contest. Move until I hit another bot, then freeze it into a loop overwriting its own code with my flags. This time the infected bots overwrite random lines instead of sequential lines, making the infection process a little less effective but much faster.

• Line(4) can be simplified a bit. Add(OVar(C),0) is the same as OVar(C) and Add(This,Add(4,Mod(E,14))) is the same as Add(This,4,Mod(E,14)). Sep 8, 2014 at 18:31
• @MegaTom I did the first unnecessary Add to make the logical parts of the preceding lines line up. The second one was due to not knowing that Add could take multiple parameters. Thanks Sep 8, 2014 at 20:24

Gard

Start: Move
BotAt(D):IF(Equals(Line(7),OLine(C)),Line(6),Line(5))
Copy(Line(7),OLine(OVar(C)))
Copy(Cond(7),OCond(Sub(OVar(C),1)))


Attacks any robot next to it.

• Your last line cannot copy from a condition to a line. Sep 5, 2014 at 1:53
• @NathanMerrill I was just fixing that... Sep 5, 2014 at 2:24
• OCon needs to be OCond Sep 5, 2014 at 2:30

Freeze Bot

Start:Move
All(BotAt(D),Not(Equals(OCond(1),Cond(5)))):Copy(Cond(5),OCond(1))
All(BotAt(D),Not(Equals(OLine(1),Line(6)))):Copy(Line(6),OLine(1))
BotAt(D):Copy(Line(20),OLine(OVar(A)))
Equals(A,A):Move


Traps you in a loop Incriminating your own A variable, then fills you with flags and moves on to the next victim.

• Line 3: Please replace D+1 with Add(D,1) Sep 5, 2014 at 15:42
• You're assuming that Start is on line zero. Now everyone is incentivized to put their Start on line 2. This is going to lead to a silly escalation/resubmission trend :( Sep 5, 2014 at 18:41

Imitator

Start:Move
BotAt(D):If(OCond(0),OLine(0),Line(2))
If(OCond(1),OLine(1),Line(3))
If(OCond(2),OLine(2),Line(4))
If(OCond(3),OLine(3),Line(5))
If(OCond(4),OLine(4),Line(6))
If(OCond(5),OLine(5),OLine(OVar(C)))


Predicts what you would do, then does that.

• Also, you cannot pass in a command as a line. You either have to pass in a OLine or a Line Sep 5, 2014 at 17:31
• @NathanMerrill ready to go! (At least I think it is) Sep 5, 2014 at 19:00
• This bot really put my code through some trouble, but that was my fault, not yours. There are a few bugs, please put Line around the 2, and Add(D,1) instead of D+1 Sep 6, 2014 at 13:36

Lazy Lioness

Originally just "Lioness", my first submission to the contest earned the title "lazy" by literally doing nothing when introduced into the simulator.

Her lethargy is in fact due to a bug (or possibly my misunderstanding the event model) wherein the conditions in the first three lines (a simple parity check for ensuring that flags are not overwritten) occasionally, inexplicably evaluate true, locking leo in a lemniscate loop. Several other conditions (particularly those that rely on the BotAt() condition) also evaluate true at times when no adjacent bot(s) are present. Finally, Move and Copy directives are clearly ignored when stepping through the simulator. Since my conditional logic chains are somewhat epic, there's plenty of room for bugs in my code and in the simulator. ;)

In any case, I submit Lazy Lioness as a test case for either error diagnosis or simulator debugging, which will hopefully lead to the emergence of not-so-lazy Lioness that I can then simulate and refine as my first bona fide submission to the Bots v2 competition.

It Does Nothing

All(Not(Equals(Line(18),Line(21))),Equals(Line(21),Line(22))):Copy(Line(21),Line(18))
All(Not(Equals(Line(21),Line(22))),Equals(Line(22),Line(18))):Copy(Line(22),Line(21))
All(Not(Equals(Line(22),Line(18))),Equals(Line(18),Line(21))):Copy(Line(18),Line(22))
All(BotAt(D),Not(Equals(OCond(2),Cond(20))),Not(Equals(OLine(2),Line(19)))):Copy(Cond(20),OCond(2))
All(BotAt(D),Equals(OCond(2),Cond(20)),Not(Equals(OLine(3),Line(18)))):Copy(Line(18),OLine(3))
All(BotAt(D),Equals(OCond(2),Cond(20)),Not(Equals(OLine(4),Line(21)))):Copy(Line(21),OLine(4))
All(BotAt(D),Equals(OCond(2),Cond(20)),Not(Equals(OCond(0),Cond(22)))):Copy(Cond(22),OCond(0))
All(BotAt(D),Equals(OCond(2),Cond(20)),Not(Equals(OLine(0),Line(17)))):Copy(Line(17),OLine(0))
All(BotAt(D),Equals(OCond(2),Cond(20)),Not(Equals(OCond(1),Cond(21)))):Copy(Cond(21),OCond(1))
All(BotAt(D),Equals(OCond(2),Cond(20)),Not(Equals(OLine(1),Line(20)))):Copy(Line(20),OLine(1))
All(BotAt(D),Equals(OCond(2),Cond(20)),Not(Equals(OLine(2),Line(19)))):Copy(Line(19),OLine(2))
Not(Equals(A,A)):Flag
Not(Equals(A,A)):Copy(Line(3),OLine(E))
Equals(A,A):Move
Any(Equals(E,4),Equals(E,5),Equals(E,6),Equals(E,7),Equals(E,8),Equals(E,9)):Flag
Any(Equals(E,10),Equals(E,11),Equals(E,12),Equals(E,13)):Flag
Start:Copy(1,A)

• I can't see a bug, but just in case you should probably use Modified condition instead of some of the Equals Sep 10, 2014 at 17:09
• cliqueBot looks like it has the same problem. I think it is a compiler bug. Sep 10, 2014 at 17:24
• @MegaTom: The Modified condition is an invitation for an infinite loop. If I can't use a parity check, I'll just remove the lines entirely. Figure out something else useful to put in 'em. ;)
– COTO
Sep 10, 2014 at 19:40
• I think I found the bug in the controller. I sent him a pull request. Until he accepts it, you can try my fork if you like and let me know if it works for you. Sep 11, 2014 at 20:51

sentinel

improvment on Gard. Hits nearby bots with flags on the first 8 lines. (that is, all the most used ones)

flag
flag
Start:Copy(11,B)
copy(D,OVar(D))
copy(Line(Mod(E,2)),OLine(Mod(E,8)))

• I think you have a misplaced bracket on line 3. The first Not isn't closed properly. I think it should be All(BotAt(D),Not(Equals(OLine(Mod(E,8)),Line(0))),Not(BotAt(Add(D,1,Mod(E,3))))): Sep 12, 2014 at 22:38

CliqueBorg

Flag
BotAt(D): Copy(Line(Sub(This,1)),OLine(E))
Start: Move
All(BotAt(D),Not(Equals(OLine(Sub(OVar(C),1)),Line(3)))):Copy(Line(3),OLine(Sub(OVar(C),1)))
All(BotAt(D),Not(Equals(OCond(Sub(OVar(C),1)),Cond(3)))):Copy(Cond(3),OCond(Sub(OVar(C),1)))
All(BotAt(D),Not(Equals(OLine(Sub(OVar(C),2)),Line(2)))):Copy(Line(2),OLine(Sub(OVar(C),2)))
All(BotAt(D),Not(Equals(OCond(Sub(OVar(C),2)),Cond(2)))):Copy(Cond(2),OCond(Sub(OVar(C),2)))
All(BotAt(D),Not(Equals(OLine(Sub(OVar(C),3)),Line(1)))):Copy(Line(1),OLine(Sub(OVar(C),3)))
All(BotAt(D),Not(Equals(OCond(Sub(OVar(C),3)),Cond(4)))):Copy(Cond(4),OCond(Sub(OVar(C),3)))


Trying to combine CliqueBot and Borg technology to create a bot that recognizes copies of itself despite the line offset. It also starts its copying process at the last executed line of code on the opposing bot, rather than line 0, which is more likely to freeze it in place but also more likely to result in a corrupted copy (in fact, I'm not sure this even works, I haven't tested it and it's pretty complex).

• Please replace Plus with Add and Minus with Sub Sep 14, 2014 at 20:01

Driveby

One last try before the deadline.

Flag
Flag
BotAt(D):Copy(Line(Sub(This,1)),OLine(E))