title: Calculate the super root of a number

text:
# Question
Title: Calculate the super root of a number
In mathematics, tetration is the next hyper operator after exponentiation, and is defined as iterated exponentiation.

**Addition** (***a*** succeeded ***n*** times)

**Multiplication** (***a*** added to itself, ***n*** times)

**Exponentiation** (***a*** multiplied by itself, ***n*** times)

**Tetration** (***a*** exponentiated by itself, ***n*** times)

The inverse relations of tetration are called the super-root, and the super-logarithm. Your task is to write a program that, given A and B, prints out the Bnd-order super-root of A.

For example:

* if A = `65,536` and B = `4` it prints `2`
* if A = `7,625,597,484,987` and B = `3` it prints `3`

A and B are positive integers and the result must be floating point number with a precision of 5 digits after the decimal point. The result belongs to the real domain.

*Be careful, super-roots may have many solutions.*

# Answer
> 6 votes
# C — aiming for clarity, didn't attempt to squeeze the code

Considering input:

```
A: A ∈ ℝ, A ≥ 1.0
B: B ∈ ℕ, B ≥ 1

```

Then there should usually be only one solution in ℝ, which simplifies the problem considerably.

Code is:

```
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define TOLERANCE    1.0e-09

double tetrate(double, int);

int main(int argc, char **argv)
{
    double target, max, min, mid, working;
    int levels;

    if (argc == 3)
    {
        target = atof(argv[1]); // A
        levels = atoi(argv[2]); // B

        // Shortcut if B == 1
        if (levels == 1)
        {
            printf("%f\n", target);
            return 0;
        }

        // Get a first approximation
        max = 2.0;
        while (tetrate(max, levels) < target)
            max *= 2.0;

        min = max / 2.0;

        // printf("Answer is between %g and %g\n", min, max);

        // Use bisection to get a closer approximation
        do
        {
            mid = (min + max) / 2.0;
            working = tetrate(mid, levels);
            if (working > target)
                max = mid;
            else if (working < target)
                min = mid;
            else
                break;
        }
        while (max - min > TOLERANCE);

        // printf("%g: %f = %f tetrate %d\n", target, tetrate(mid, levels), mid, levels);
        printf("%f\n", mid);
    }

    return 0;
}

double tetrate(double d, int i)
{
    double result = d;

    // If the result is already infinite, don't tetrate any more
    while (--i && isfinite(result))
        result = pow(d, result);

    return result;
}

```

To compile:

```
gcc -o tet_root tet_root.c -lm

```

To run:

```
./tet_root A B

```

E.g.:

42

```
$ ./tet_root 65536 4
2.000000

```

33

```
$ ./tet_root 7625597484987 3
3.000000

```

3π

```
$ ./tet_root 1.340164183e18 3
3.141593

```

n(2½) ➙ 2 as n ➙ ∞ ? (well known limit)

```
$ ./tet_root 2 10
1.416190

$ ./tet_root 2 100
1.414214

$ ./tet_root 2 1000
1.414214

```

Yes!

n(e1/e) ➙ ∞ as n ➙ ∞ ? (upper bounds)

```
$ ./tet_root 9.999999999e199 100
1.445700

$ ./tet_root 9.999999999e199 1000
1.444678

$ ./tet_root 9.999999999e199 10000
1.444668

$ ./tet_root 9.999999999e199 100000
1.444668

```

Cool! (e1/e ≅ 1.44466786101...)

# Answer
> 5 votes
## Python, 87 chars

```
E=lambda x,n:x**E(x,n-1)if n else 1
def S(A,B):
 x=1.
 while E(x,B)<A:x+=1e-5
 return x

```

A simple linear search for the answer.

Off-topic, but what the \*#$(@! is up with the python `**` operator?

```
>>> 1e200*1e200
inf
>>> 1e200**2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: (34, 'Numerical result out of range')

```

# Answer
> 3 votes
## Mathematica, ~~35~~ 40

```
n /. Solve[Nest[#^(1/n) &, a, b] == n]~N~5

```

Generates a list of all solutions, with 5 digit precision.

```
n /. Last@Solve[Nest[#^(1/n) &, a, b] == n]~N~5

```

5 more characters to get only the real solution, which the updated rules demand.

# Answer
> 3 votes
When did this become a code golf? I thought it was a code challenge to come up with the best algorithm!

---

# APL, 33 chars

```
{r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6}

```

This is a simple linear search, starting from C = 1 + 10-6 and incrementing it by 10-6 until
logC logC logC ⋯ A ≤ 1
where the logC function is applied recursively B times.

**Examples**

```
      4 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 65536
2.0000009999177335
      3 {r←⍵⋄⍺{1≥⍵⍟⍣⍺⊢r:⍵⋄⍺∇⍵+i}1+i←1e¯6} 7625597484987
3.0000000000575113

```

This code is very slow, but for small bases such as 2 or 3 it completes in a few seconds. See below for a better thing.

---

# APL, logarithmic complexity

Actually linear complexity on the root order, logarithmic on the result size and precision:

time = O(B × log(C) + B × log(D))

where B is the root order, C is the tetration base being asked for, and D is the number of digits of precision asked. This complexity is my intuitive understanding, I have not produced a formal proof.

This algorithm does not require big integers, it only uses the log function on regular floating point numbers, therefore it's quite efficient on very large numbers, up to the limit of the floating point implementation (either double precision, or arbitrary large FP numbers on the APL implementations that offer them.)

The precision of the result can be controlled by setting `⎕CT` (comparison tolerance) to the desired acceptable error (on my system it defaults to 1e¯14, roughly 14 decimal digits)

```
sroot←{              ⍝ Compute the ⍺-th order super-root of ⍵:
  n←⍺ ⋄ r←⍵          ⍝ n is the order, r is the result of the tetration.
  u←{                ⍝ Compute u, the upper bound, a base ≥ the expected result:
    1≥⍵⍟⍣n⊢r:⍵       ⍝   apply ⍵⍟ (log base ⍵) n times; if ≤1 then upper bound found
    ∇2×⍵             ⍝   otherwise double the base and recurse
  }2                 ⍝ start the search with ⍵=2 as a first guess.
  (u÷2){             ⍝ Perform a binary search (bisection) to refine the base:
    b←(⍺+⍵)÷2        ⍝   b is the middle point between ⍺ and ⍵
    t←b⍟⍣n⊢r         ⍝   t is the result of applying b⍟ n times, starting with r;
    t=1:b            ⍝   if t=1 (under ⎕CT), then b is the super-root wanted;
    t<1:⍺∇b          ⍝   if t<1, recurse between ⍺ and b
    b∇⍵              ⍝   otherwise (t>1) returse between b and ⍵
  }u                 ⍝ begin the search between u as found earlier and its half.
}

```

I'm not sure whether `1≥⍵⍟⍣n` above could fail with a Domain Error (because the log of a negative argument could either fail immediately, or give a complex result, which would not be in the domain of ) but I haven't been able to find a case that fails.

**Examples**

```
      4 sroot 65536
1.9999999999999964
      4 sroot 65537
2.000000185530773
      3 sroot 7625597484987
3
      3 sroot 7625597400000
2.999999999843567
      3 sroot 7625597500000
3.000000000027626

```

'3' comes out as an exact value because it happens to be one of the values directly hit by the binary search (starting from 2, doubled to 4, bisect to 3). In the general case that does not happen, so the result will approximate the root value with a ⎕CT error (more precisely, the logarithmic test of every candidate base is performed with ⎕CT tolerance.)

# Answer
> 2 votes
# Julia

```
julia> t(a,b)=(c=a;for j=1:b-1;c=a^c;end;c)
julia> s(c,b)=(i=1;while t(i,b)!=c;i+=1;end;i)
julia> s(65536,4)
2
julia> s(7625597484987,3)
3

```

Ignored floating point instruction since the the question only defines behavior for integers.

# Answer
> 1 votes
## Ruby, 79 bytes

```
->a,b{x=y=1.0;z=a;eval"y=(x+z)/2;x,z=a<eval('y**'*~-b+?y)?[x,y]:[y,z];"*99;p y}

```

This is the same as the below program, but less accurate since it only runs 99 loops.

## Ruby, 87 bytes

```
->a,b{x=y=1.0;z=a;(y=(x+z)/2;x,z=a<eval("y**"*~-b+?y)?[x,y]:[y,z])while y!=(x+z)/2;p y}

```

Try it online

This is simply bisection. Ungolfed:

```
-> a, b {
    # y^^b by evaluating the string "y ** y ** ..."
    tetration =-> y {eval "y ** " * (b-1) + ?y}

    lower = middle = 1.0
    upper = a

    while middle != (lower + upper) / 2 do
        middle = (lower + upper) / 2

        if tetration[middle] > a
            upper = middle
        else
            lower = middle
        end
    end

    print middle
}

```

# Answer
> 0 votes
# k \[52 chars\]

```
{{{((%x)*(z*x-1)+y%z xexp x-1)}[x;y]/[2]}[y]/[y<;x]}

```

A modified version of my own post nth root

Example:

```
{{{((%x)*(z*x-1)+y%z xexp x-1)}[x;y]/[2]}[y]/[y<;x]}[7625597484987;3]
3f

{{{((%x)*(z*x-1)+y%z xexp x-1)}[x;y]/[2]}[y]/[y<;x]}[65536;4]
2f

```

# Answer
> 0 votes
## Mathematica, 41 bytes without optimization

Mathematica was basically invented to solve problems like this. One easy solution is to construct the problem as a nested power series and pass it to the built-in `Reduce` function, which seeks analytical solutions to equations. As a result, the following, in addition to being unusually concise code, is also not brute force.

```
Reduce[Nest[Power[#, 1/x] &, a, b] == x, x, Reals]

```

You can remove the restriction to provide only Real number solutions if you're patient and want to save six bytes. You can also express some of the nested functions in abbreviated form to save a few more bytes. As given, it returns thusly

# Answer
> 0 votes
## Haskell

Simple linear search, returns first, smallest match found.

```
{-
    The value of a is the result of exponentiating b some number of times.
    This function computes that number.
-}
superRoot a b = head [x | x<-[2..a], tetrate x b == a]

{-
    compute b^b^...^b repeated n times
-}
tetrate b 1 = b
tetrate b n = b^(tetrate b (n-1))

```

Example

```
*Main> superRoot 65536 4
2
*Main> superRoot 7625597484987 3
3

```

# Answer
> 0 votes
# 05AB1E, 16 bytes

```
1[ÐU²FXm}¹@#5(°+

```

Port of *@KeithRandall*'s Python answer.

Try it online.

**Explanation:**

```
1                 # Push a 1
 [                # Start an infinite loop:
  Ð               #  Triplicate the top value on the stack
   U              #  Pop and store one in variable `X`
    ²F            #  Inner loop the second input amount of times:
      Xm          #   And take the top value to the power `X`
        }         #  After the inner loop:
         ¹@       #  If the resulting value is larger than or equal to the first input:
           #      #   Stop the infinite loop
                  #   (after which the top of the stack is output implicitly as result)
            5(°+  #  If not: increase the top value by 10^-5

```

`ÐU²FXm}` could also be `D²>и.»m` for the same byte-count:

```
  D               #   Duplicate the top value on the stack
   ²>             #   Push the second input + 1
     и            #   Repeat the top value that many times as list
      .»          #   Reduce it by:
        m         #    Taking the power

```

---
Tags: code-golf, math
---


title: Gold Battle KoTH

text:
# Question
Title: Gold Battle KoTH
> This challenge has ended. To see the final scores of the competitors, click here

In this challenge, each submission is one bot. Each bot should be a Javascript function. Bots will fight to obtain the highest total worth in gold. Gold can be farmed, or earned from killing other bots, and is used to upgrade healing, attacking, shielding, and farming.

**Objective:**

Over a number of rounds containing up to 1000 turns (ends when only one bot is left), the bot with the highest total worth (the sum of all gold obtained) is the winner.

**Turns:**

In each turn, every bot which is alive (\>0 HP) will be run once. It can return a move, which can be one of the following:

* Heal: Regains HP
* Attack: Removes HP from another bot
* Shield: Defends against later attacks
* Stun: Skips another bot's next turn
* Farm: Earns gold at the cost of HP
* Upgrade: Make certain moves better

All bots will return their move before any are executed, so a stun, heal, attack, shield, etc. will not affect any bots moving later in that turn. For example, if Bot A stuns Bot B, and Bot B is after Bot A in the turn order, Bot B will still move later in that same turn and the stun will occur on the next turn.

**Combat, Farming, and Upgrading:**

Each bot has a maximum HP of 100, and an assigned UID between 0 and 99. This UID changes after every round, and is how bots keep track of each other.

Healing is one of the simplest moves, adding an amount of HP determined by its level (starts at 5 HP). A bot cannot heal past 100 HP.

Attacking a bot by its UID is another possible move, with a base damage of 5 HP at level 0. Bots can also be stunned, skipping their next turn, which also uses UIDs.

Bots have additional shield HP, which has no limit. This shield HP will absorb damage from direct attacks from other bots, and is added by shielding. At level 0, shielding adds 5 shield HP.

Farming will earn 5 gold at level 0, at the cost of 2 HP. This 2 HP cannot be shielded. The only use for gold (beyond winning) is to upgrade moves. Healing, attacking, and shielding have a base value of 5 HP, and farming starts at 5 gold. Each of those moves have individual levels, which start at 0. These formulas will determine the value in HP or gold of a move, where L is the level:

* Healing: `L + 5`
* Attacking: `1.25L + 5`
* Shielding: `1.5L + 5`
* Farming: `2L + 5`

The cost of upgrading any move is the same for a certain level, and is determined by `2.5L² + 2.5L + 10`, where L is the current level. A bot can use the function `cost(currentLevel)` as a shortcut to determine this.

Bots start with 25 gold, allowing them to quickly upgrade either two moves to level 1, or one move to level 2. This beginning gold does not count towards a bots total worth. Killing a bot gives you half of its total worth in gold, rounded up, and if two bots kill another in the same turn, they both get the reward.

**Input/Output:**

In order to communicate with the controller, the return value of the function is used to send move information. One of these should be returned:

* Heal: `heal()`
* Attack: `attack(uid)`
* Shield: `shield()`
* Stun: `stun(uid)`
* Farm: `farm()`
* Upgrade: `upgrade("heal" / "attack" / "shield" / "farm")`

To skip a turn (do nothing), return nothing, or return a falsy value.

To get the current turn number (starts at 1), use `turn()`.

The arguments of your function will include information about your bot, UIDs of other bots, and between-turn storage. The first argument is an object with the following properties: `uid`, `hp`, `gold`, and `shield`. These are copies of your bot's current information. There is also an nested object `levels`, with the level numbers of `heal`, `attack`, `shield`, and `farm`.

The second argument is a shuffled array of all alive bots other than yours, formatted as an object containing properties `uid`, `hp` (plus shield), `worth`, and `attack` (attack level). The third argument is an empty object which can be used for between-turn storage.

**Example Bots:**

This bot will farm until it can upgrade its attack to level 5, then attack a random bot each turn until it dies (or wins). Not very effective due to lack of healing/shielding.

```
function freeTestBotA(me, others, storage) {
    if (me.levels.attack < 5) {
        if (me.gold < cost(me.levels.attack))
            return farm();
        return upgrade("attack");
    }
    return attack(others[0].uid);
}

```

This bot has two modes: offensive and defensive. It will either stun a random bot or heal when in defensive mode, and it will either attack or shield when in offensive mode. It will attempt to upgrade its attacks whenever possible.

```
function freeTestBotB(me, others, storage) {
    if (me.gold >= cost(me.levels.attack))
        return upgrade("attack");
    if (me.hp < 50)
        if (Math.random() < 0.5)
            return stun(others[0].uid);
        else
            return heal();
    else
        if (Math.random() < 0.5)
            return attack(others[0].uid);
        else
            return shield();
}

```

**Rules:**

* Standard Loopholes forbidden
* Bots may not read, modify, or add any variables outside of their scope, may not attempt to cheat, and may not call any controller-defined or DOM functions
* Return value must be falsy, or one of the above function outputs
* Bots should not be designed to target a specific bot, but can be designed to take advantage of common strategies
* Bots may not attack themselves (discovered due to a comment by @Ness)
* Bots must be sufficiently different from any other bots that they can be reasonably considered separate entries
* Teaming is **now not** allowed
* Controller can be found here
* Chatroom

**New Controller Debugging:**

Using the file `gold-battle-log.js`, you can set the value of the `debug` property of a bot in `botData` to 0 (no logging), 1 (log moves), or 2 (log moves, hp, gold, levels, etc.)

**Challenge ends at 1700 UTC on Friday, August 9th**

# Answer
> 7 votes
# The Bot That Farms, Attacks, Shields, And Even Heals But Never Stuns

<sup>*(Short name is **TBTFASAEHBNS**, not to be mistaken with TBTPTGCBCBA)*</sup>

```
function TBTFASAEHBNS(me, others, storage) {
    this.getLevel = function (type) {
        return (typeof me.levels[type] === 'undefined' ? 0 : me.levels[type]);
    };

    this.getPower = function (type, level) {
        if (typeof level === 'undefined') level = this.getLevel(type);
        if (type === 'heal') return level + 5;
        if (type === 'attack') return (level * 1.25) + 5;
        if (type === 'shield') return (level * 1.5) + 5;
        if (type === 'farm') return (level * 2) + 5;
    };

    this.canUpgrade = function (type) {
        return myGold >= cost(this.getLevel(type));
    };

    this.farmOrUpgradeFarm = function () {
        if (this.canUpgrade('farm')) return upgrade('farm');
        if (myHp < 3) return heal();
        return farm();
    };

    let currentTurn = turn(),
        myGold = me.gold,
        myHp = me.hp,
        myShield = me.shield,
        myTotalHp = myHp + myShield,
        myHealPower = this.getPower('heal'),
        myShieldPower = this.getPower('shield'),
        myAttackPower = this.getPower('attack'),
        myFarmPower = this.getPower('farm'),
        topAttackPower = 0,
        attackOptions1 = [],
        attackOptions3 = [],
        attackOptions2 = [],
        finalTurns = 980;

    if (currentTurn === 1) {
        storage.othersInfo = {};
    }

    others.sort((a, b) => b.attack - a.attack);
    for (let i = 0; i < others.length; i++) {
        let other = others[i];

        if (i < 3) topAttackPower += this.getPower('attack', other.attack);

        if (other.worth > myFarmPower) {
            if (other.hp <= myAttackPower) {
                attackOptions1.push(other);
            } else {
                if (typeof storage.othersInfo[other.uid] !== 'undefined') {
                    let otherHpChange = storage.othersInfo[other.uid].hp - other.hp;

                    if (other.hp - otherHpChange <= 0) {
                        attackOptions2.push(other);
                    } else if (other.hp - (otherHpChange * 3) <= 0) {
                        attackOptions3.push(other);
                    }
                }
            }
        }

        storage.othersInfo[other.uid] = {hp: other.hp};
    }

    if (myTotalHp < (topAttackPower * 7) + 5) return shield();
    if (currentTurn <= 10) return this.farmOrUpgradeFarm();

    if (attackOptions1.length > 0) {
        attackOptions1.sort((a, b) => b.worth - a.worth);
        return attack(attackOptions1[0].uid);
    } else if (attackOptions2.length > 0) {
        attackOptions2.sort((a, b) => b.worth - a.worth);
        return attack(attackOptions2[0].uid);
    } else if (attackOptions3.length > 0) {
        attackOptions3.sort((a, b) => b.worth - a.worth);
        return attack(attackOptions3[0].uid);
    }

    if (currentTurn <= 20) return this.farmOrUpgradeFarm();
    if (currentTurn < finalTurns && myShieldPower < topAttackPower / 2 && Math.random() * 15 < 1 && this.canUpgrade('shield')) return upgrade('shield');
    if (currentTurn < finalTurns && this.canUpgrade('farm')) return upgrade('farm');
    if (currentTurn < finalTurns && myHealPower < 10 && this.canUpgrade('heal')) return upgrade('heal');
    if (myHp < 3) return heal();
    return farm();
}

```

This bot basically:

* Builds up on farming at start
* Defends itself when needed
* Attacks when it can kill or when it thinks there is a chance to kill someone
* Upgrades here and then
* Farms the rest of the time
* Never stuns

**Edit 1:** Fixed an issue and improved some tiny things in the bot based on tests with lots of games.

**Edit 2:** Reduced shield upgrades.

# Answer
> 16 votes
# Unkillable

forked from Undyable.

```
function UnkillableBot(me){
    if(me.hp <= 100 - (me.levels.heal + 5)){
        return heal()
    }else if(turn() % 10 == 0 && me.shield < 800) {
        return shield()
    }else{
        if(me.gold >= cost(me.levels.shield) && me.levels.shield <= 9){
            return upgrade("shield")
        }else if(me.gold >= cost(me.levels.farm)){
            return upgrade("farm")
        }else{
            if(me.shield < 500 && me.levels.shield > 4) {
                return shield()
            }
            return farm()
        }
    }
}

```

Given the exponential costs of upgrades, may as well upgrade farming if we can't upgrade healing, allowing the bot to collect gold more efficiently.

# Answer
> 12 votes
# ThanosBot

```
function ThanosBot(me, others, storage){
    if(turn()==1){
        storage.origPopulation = others.length;
        return upgrade("attack");
    }

    if (others.length < storage.origPopulation / 2)
    {
        if(me.hp <= 100 - (me.levels.heal + 5)){
            return heal();
        }
        else {
            return farm();
        }
    }

    if(me.hp <= 100 - (me.levels.heal + 5)){
        return heal()
    }else{
        if(me.gold >= cost(me.levels.attack)){
            return upgrade("attack")
        }else if(me.gold >= cost(me.levels.heal)){
            return upgrade("heal")
        }else if(me.gold >= cost(me.levels.farm)){
            return upgrade("farm")
        }else{
            if(Math.random() < 0.5){
                return attack(others[0].uid);
            }
            else{
                return farm();
            }
        }
    }
}

```

There are too many bots, not enough gold to go around. This bot proposes a solution.

Genocide, yes, but random, dispassionate, fair to rich and poor alike.

They called him a madman.

ThanosBot wants the best for the bot community, and is willing to go all the way. In the beginning, he will upgrade his attack, farming and healing, to more efficiently gather resources and win battles. Prograssively, he will start attacking people randomly while still gathering resources, for upcoming battles. He will keep improving his army, his weapons and himself.

Once 50% of the population has been eliminated, bots born will only know full bellies and clear skies, he will retire to a life of farming, and watch the sun rise on a grateful universe. He will become completely pacifist, only healing himself with vegetable soups and farming.

# Answer
> 11 votes
# Kill Stealer

```
function killStealer({hp, gold, attack:atck, shield:shld, levels:{heal:lHeal, shield:lShld, farm:lFarm, attack:lAtck}}, es, S) {
  let saneReduce = (a, f, n) => a.length? a.reduce(f) : n;
  let t = turn();
  if (t===1) {
    S.worth = 0;
    S.pHP = 100;
    S.pGold = 0;
    S.stat = {};
    S.pT = 0;
    for (let e of es) S.stat[e.uid] = {kills:0, seen:0};
  }

  let pT = S.pT;
  S.pT = t;

  let shp = shld+hp;

  let healP = lHeal      + 5;
  let shldP = lShld*1.5  + 5;
  let farmP = lFarm*2    + 5;
  let atckP = lAtck*1.25 + 5;
  let pheal = () => hp<5  ||  Math.min(100, hp+healP)-hp > shldP? heal() : shield();

  let attacked = S.pHP-hp-shld > 2;
  S.pHP = hp+shld;

  if (gold>S.pGold  &&  t!=1) S.worth+= gold-S.pGold;
  S.pGold = gold;

  let pes = S.pEs;
  let ces = {};
  for (let e of es) ces[e.uid] = {uid:e.uid, hp:e.hp, worth:e.worth};
  S.pEs = ces;

  if (t === 1) return shield(); // to not break things depending on previous frame

  if (t == pT+1) {
    for (let uidE in pes) {
      let e = pes[uidE];
      if (!ces[uidE]) { // dead
        if (e.worth < 30) continue; // don't bother, because others probably won't
        for (let a of es) {
          let pa = pes[a.uid];
          if (a.worth >= pa.worth + e.worth/2 - 2) {
            S.stat[a.uid].kills++;
          }
          if (a.worth != pa.worth || a.hp > pa.hp) S.stat[a.uid].seen++;
        }
      }
    }
  }

  let attackers = es.filter(c => {
    let k = S.stat[c.uid].kills;
    let s = S.stat[c.uid].seen;
    return k > 1  &&  k > s*.7;
  });
  let maxDmg = es.map(c=>c.attack).reduce((a, b) => Math.max(a, b), 0)*1.25 + 5;
  for (let e of es) {
    if (e.worth < farmP) continue;
    let p = pes[e.uid];
    let dmg = p.hp-e.hp;
    if (e.hp <= atckP) {
      return attack(e.uid);
    }
    if (e.hp-dmg-atckP <= 0) {
      return attack(e.uid);
    }
    if (e.hp-maxDmg-atckP <= 0) {
      return attack(e.uid);
    }
    if (e.hp-maxDmg-dmg <= 0) {
      return attack(e.uid);
    }
  }
  if (attackers.length>0 && t>50) {
    for (let e of es) {
      if (e.hp - maxDmg*2 - atckP <= 0  &&  e.worth > 200) {
        let worst = saneReduce(attackers.filter(c => c.hp > 80), (a, b)=>a.worth>b.worth? a : b, null);
        if (worst) return stun(worst.uid);
      }
    }
  }

  if (t < 60  &&  t%5 == 1) return shield();
  if (t === 2) return upgrade("heal");
  if (t === 3) return upgrade("farm");
  if (t%10 == 1) return shield();

  if (gold>=cost(lShld) && lFarm>-2) return upgrade("shield");
  if (gold>=cost(lFarm) && !attacked) return upgrade("farm");

  if (es.length > 2) {
    let notDead = es.filter(c => c.hp > 20);
    if (notDead.length !== 0) {
      notDead.sort((a, b) => a.hp-b.hp);
      if (notDead[Math.min(2, notDead.length-1)].hp > shp) {
        return pheal();
      }
    }
  }

  if (gold>=cost(lHeal)  &&  lHeal+5 < lFarm) return upgrade("heal");
  if (gold>=cost(lAtck)  &&  lAtck+5 < lFarm  &&  es.every(c=>c.attack<=lAtck+2)) return upgrade("attack");

  if (lShld>5  &&  shp < 205+healP+t  &&  shp < 600+t*5) return pheal();
  if (es.every(c => c.worth < S.worth+farmP) && es.length>2 && t<100 && lShld<6) return pheal();
  if (shp<=120  ||  hp<5) return pheal();
  return farm();
}

```

Now not only steals kills, but steals stealing kills too!

This bot doesn't do much except farm, and when it notices the possibility, joins in doing the final blow to a dying enemy, and somehow manages to be very good.

# Answer
> 9 votes
# Optimist

```
function Optimist(me, others, storage) {
    if (me.hp < 10)
        return heal();
    if ( (me.hp + me.shield) < 50 )
        return shield();
    if (me.gold >= cost(me.levels.farm) && cost(me.levels.farm) < 0.8 * (1000 - turn()))
        return upgrade("farm");
    rich_bots = others.sort( (x,y) => y.worth - x.worth );
    potential_victim = rich_bots.find( bot => bot.hp <= me.levels.attack * 1.25 + 5 );
    if (potential_victim)
        return attack(potential_victim.uid);
    if (me.gold < rich_bots[0].worth + cost(me.levels.farm) + 25)
        return farm();
    if (me.levels.heal < me.levels.farm)
        return upgrade("heal");
    if (me.levels.shield < me.levels.heal)
        return upgrade("shield");
    if (me.levels.attack < me.levels.shield)
        return upgrade("attack");
    return shield();
}

```

Assumes it will be able to spend 80% of its time peacefully farming, so it starts off by maxing out farming, and only then starts paying any attention to its combat skills. Surely nothing will go wrong!

# Answer
> 9 votes
# The Equalizer

This bot seeks to restore peace in the bot community. He relentlessly targets the bots with the highest attack, giving up only if the bot's healing is better than his own attack. Once no bots with healing worse than its attack are left, he will retire to a life of peaceful farming.

```
function equalizer(me, others, storage){
  if(storage.agroKilled == null)storage.agroKilled = false;
  if(!storage.agroKilled){
    if(storage.blacklist == null)storage.blacklist = [];
    if(storage.lastAttack == null)storage.lastAttack = -1;
    var maxAtk = 0;
    var maxAtkUid = -1;
    var maxAtkHealth = 0;
    for(var i = 0; i < others.length; i++)if(others[i].uid == storage.lastAttack){
      maxAtk = others[i].attack*1.25+5;
      maxAtkUid = storage.lastAttack;
      maxAtkHealth = others[i].hp;
    }
    for(var i = 0; i < others.length; i++){
      if(storage.lastAttack == others[i].uid && others[i].hp >= storage.lastHealth){
        maxAtk = 0;
        maxAtkUid = -1;
        maxAtkHealth = 0;
        storage.blacklist.push(others[i].uid);
      }
    }
    storage.lastAttack = -1;
    var willHeal;
    for(var i = 0; i < others.length; i++)if(others[i].attack*1.25+5 > maxAtk){
      willHeal = false
      for(var j = 0; j < storage.blacklist.length; j++)if(others[i].uid==storage.blacklist[j])willHeal = true;
      if(!willHeal){
        maxAtk = others[i].attack*1.25+5;
        maxAtkUid = others[i].uid;
        maxAtkHealth = others[i].hp;
      }
    }
    if(me.hp < maxAtk) return heal();
    if(me.hp <= 100 - me.levels.heal - 5) return heal();
    var target = -1;
    var targetWorth = me.levels.farm * 2 + 5;
    for(var i = 0; i < others.length; i++) {
      if (others[i].hp <= maxAtk && others[i].worth / 2 > targetWorth) {
        target= others[i].uid;
          targetWorth = others[i].worth / 2;
      }
    }
    if(target!=-1) return attack(target);
    if(me.gold >= cost(me.levels.attack)) return upgrade("attack");
    if(me.levels.heal + 7 < me.levels.attack && me.levels.heal < 9 && me.gold >= cost(me.levels.heal)) return upgrade("heal");
    if(maxAtkUid!=-1){
      storage.lastAttack = maxAtkUid;
      storage.lastHealth = maxAtkHealth;
      return attack(maxAtkUid);
    }
    storage.agroKilled = true;
  }
  if(me.hp < 30) return heal();
  if(me.gold > cost(me.levels.farm)) return upgrade("farm");
  return farm();
}

```

# Answer
> 8 votes
# Kill Assist

```
function KillAssist(me, others, storage) {
  let t = turn();
  if (t===1) {
    storage.worth = 0;
    storage.pHP = 100;
    storage.pGold = 0;
  }
  let hp = me.hp;
  let gold = me.gold;
  let shld = me.shield;
  let lHeal = me.levels.heal+0.25;
  let lFarm = me.levels.farm;
  let lShld = me.levels.shield;
  let lAtck = me.levels.attack;
  let healPower = lHeal      + 4.75;
  let shldPower = lShld*1.5  + 5;
  let farmPower = lFarm*2    + 5;
  let atckPower = lAtck*1.25 + 5;

  let dmgTaken = storage.pHP-(hp+shld);
  let attacked = dmgTaken > 2;
  storage.pHP = (hp+shld);

  if (gold > storage.pGold) storage.worth+= gold-storage.pGold;
  if (gold-storage.pGold > farmPower+5)  storage.lastAtck = -10;
  storage.pGold = gold;
  let pOthers = storage.pOthers;
  storage.pOthers = {};
  for (let o of others) {
    storage.pOthers[o.uid] = {hp: o.hp, uid: o.uid, worth: o.worth};
  }

  if (t === 1 || t === 2) return upgrade("shield");
  if (t === 3) return shield();

  let maxdmg = others.map(c=>c.attack).reduce((a, b) => Math.max(a, b))*1.25 + 5;
  let lowhp = others.map(c=>c.hp).reduce((a, b) => Math.min(a, b));
  let lowhpid = others.find(c=>c.hp == lowhp).uid;
  let maxAttacker = others.find(o => o.attack*1.25 + 5 == maxdmg).uid;
  for (let o of others) {
    if (o.hp < atckPower  &&  o.worth > farmPower) {
      storage.dead = o.uid;
      storage.deadWorth = o.worth;
      return attack(o.uid);
    }
    let pO = pOthers[o.uid];
    let dmg = pO.hp - o.hp;
    if (o.hp - dmg - atckPower <= atckPower && o.worth >= farmPower) {
      storage.dead = o.uid;
      storage.deadWorth = o.worth;
      return attack(o.uid);
    }
    if (o.hp - maxdmg - atckPower <= atckPower && o.worth >= farmPower) {
      storage.deadWorth = o.worth;
      return attack(o.uid);
    }
  }
  let lowhpdiff = Math.max(pOthers[lowhpid].hp - others.find(o => o.uid == lowhpid).hp,0);
  if (others.some(o => o.hp > maxdmg && o.hp < lowhpdiff*2+atckPower+maxdmg && o.worth > farmPower)) {
    let bad = others.reduce((a, b) => a.worth>b.worth? a : b);
    let bad2 = others.reduce((a, b) => bad.uid == b.uid ? a : (bad.uid == a.uid ? b : (a.worth>b.worth ? a : b)));
    if(bad.worth < bad2.worth*3 && bad.hp >= (maxdmg+atckPower)*2 && bad.uid != maxAttacker && bad.uid != lowhpid) {
      return stun(bad.uid);
    }
    if(bad2.hp >= (maxdmg+atckPower)*2 && bad2.uid != maxAttacker && bad.uid != lowhpid) {
      return stun(bad2.uid);
    }
  }

  if (t%10 == 9  &&  lShld>4) return shield(); // slowly build up shield just in case
  if (shld+hp < 100) return shldPower>healPower || hp >= 100-healPower? shield() : heal();

  var bon = shldPower-maxdmg < 3 && t < 700 ? lShld/2 : 0;
  var bon2 = t/100;
  if (gold>=cost(lFarm) && lShld+2 > lFarm && bon == 0 && !attacked) return upgrade("farm"); // farm first, but make sure it doesn't get too far ahead
  if (gold>=cost(lShld) && t>20 && (lShld<10+bon || lShld+5+bon2 < lFarm+bon) && t < 900) return upgrade("shield");
  if (gold>=cost(lFarm)) return upgrade("farm"); // try upgrading farming again, because shield upgrading can be picky
  if (gold>=cost(lHeal) && (lHeal<3)) return upgrade("heal"); // healing isn't that important

  if (shld<200 && attacked || shld<500 && t>20 && others.filter(c=>c.hp>=100).every(o=>o.hp+10 > hp+shld)) return shldPower>healPower || hp >= 100-healPower? shield() : heal();

  let hpdelta = attacked ? dmgTaken+shldPower : maxdmg
  if (shld<lShld*60 && (1000-t)*(hpdelta) > shld+hp) return shield(); // we want to look impressive & terrifying
  if (hp<=100-healPower) return heal();

  return farm();
}

```

Why upgrade attack value when you can do plink damage and still get full credit?

Once more back to piggybacking off Kill Stealer. I was able to simplify several blocks of code where statements were always true and fiddle with some numbers that resulted in massive gains over the original.

I have to hand it to @dzaima for realizing that stunning a wealthy opponent that is likely to be involved in an assist the turn before a kill happens is quite clever. One of the (very) few times `Stun()` has a positive sum outcome. Once again I was able to improve upon the idea, as knowing that Kill Stealer will be running similar logic, Kill Assist looks for a "second best" target (with some discretion) and stuns them instead.

Minor update to prevent stunning the bot-about-to-die and prevent stunning the bot-most-likely-to-make-the-kill.

Sample results (truncated top 5 after 1000 games)

```
VM2406:1629 Kill Assist: 39495.679
VM2406:1629 The Accountant: 29990.267
VM2406:1629 Kill Stealer: 23530.153
VM2406:1629 Unkillable: 12722.604
VM2406:1629 captFarmer: 12232.466

```

# Answer
> 7 votes
## Undyable Bot (v3)

```
function undyableBot(me, others, storage){

    if(me.hp < 100 - (me.levels.heal + 5)*2){
        return heal()
    }else{
        if(me.levels.heal < 10 && cost(me.levels.heal) / 2 < cost(me.levels.farm)){
            if(me.gold >= cost(me.levels.heal)){
                return upgrade("heal")
            }else{
                return farm()
            }
        }else{
            if(me.gold >= cost(me.levels.farm)){
                return upgrade("farm")
            }else{
                return farm()
            }
        }
    }
}

```

---

# Answer
> 6 votes
## JustFarm

I thought I'd start simple.

```
function justFarm(me, others){
    return farm();
}

```

# Answer
> 6 votes
# FizzBuzz

```
function FizzBuzz(me, others, storage) {
    if (!storage.target) storage.target = others[0].uid;
    const uids = others.map(x=>x.uid);
    if(!uids.includes(storage.target) || (turn() % 30 === 0
        && others[uids.indexOf(storage.target)].hp>30))
        storage.target = others[0].uid;

    if (cost(me.levels.farm) < me.gold) return upgrade("farm");
    if (turn() % 15 === 0) return heal();
    if (turn() % 3 === 0) return farm();
    if (turn() % 5 === 0) return heal();

    if (cost(me.levels.attack) < me.gold) return upgrade("attack");
    return attack(storage.target);
}

```

Mostly offensive bot. Extremely upset by the fact that it can't truly FizzBuzz so it just Buzzes angrily instead. When it's not Fizzing or Buzzing, it chips away at another bot for 30 turns and gives up and chooses another bot to target if it isn't making progress.

~~Performs extraordinarily inconsistently.~~ Never mind, updated the controller, now seems to always be around the middle of the pack.

# Answer
> 6 votes
# Switzerland

```
function switzerland(self,others,storage){
    let turnsLeft=999-turn()
    let lowestHpBots=others.sort((a,b)=>a.hp-b.hp)
    if(!storage.worth){
        storage.worth=0
        storage.prevGold=25
    }else if(self.gold>storage.prevGold){
        storage.worth+=self.gold-storage.prevGold
    }
    if(others.length===1&&storage.worth>others[0].worth){
        //stun lock the other bot if there are only 2 left and I can win
        return stun(others[0].uid)
    }else if(self.hp<=(95-self.levels.heal)){
        return heal()
    }else if(lowestHpBots[0]&&lowestHpBots[0].hp<20&&lowestHpBots[0].worth/2>2*self.levels.farm+5&&self.hp+self.shield>=110){
        //kill assist
        return attack(lowestHpBots[0].uid)
    } else if(self.shield<=50||self.shield<=5500/others.length&&self.shield<=1200&&turn()>=20||lowestHpBots[1]&&lowestHpBots[1].hp>self.hp+self.shield){
        return shield()
    }else if(self.gold>=cost(self.levels.shield)&&self.levels.shield<=8){
        return upgrade("shield")
    } else if(self.gold>=cost(self.levels.farm)&&(turnsLeft+1)*(2*(self.levels.farm)+5)<turnsLeft*(2*(self.levels.farm+1)+5)){
        return upgrade("farm")
    } else if(self.gold>=cost(self.levels.heal)&&(turnsLeft+1)/(self.levels.heal+5)*(2*self.levels.farm+5)<turnsLeft/(self.levels.heal+6)*(2*self.levels.farm+5)&&self.levels.heal<=2){
        return upgrade("heal")
    }else{
        return farm()
    }
}

```

Like the name suggests, this bot is ~~neutral~~ mostly neutral(now it helps kill bots that are going to die) and just farms and heals, slowly building up its gold(~~just like switzerland~~)

# Answer
> 6 votes
# PatientStrategistBot

I tried to write a bot that starts out framing and defending as needed and then switches to killing other high value bots later in the game.

Currently this doesn't seem to work properly since its either killed by a gang of murder-bots in the start of the game or gets stuck somewhere in its offensive mode.

Still pretty happy with this being my first JS code, so ... (I did steal code snippets from here & there cause that was faster than googling all of the JS basic syntax)

```
function PatientStratgistBot(me, others, storage) {

    //set up some stuff in first turn
    if (turn() == 1) {
    storage.selfWorth = 0;
    storage.attackMode = false;
    storage.expectHP = 100;
    storage.expectShield = 0;
    storage.shieldTarget = 0;
    storage.targetUid = "None";
    storage.attackRounds = 0;
    storage.targetStartHP = 100;

        return upgrade("farm");
    }

    let farmPower = me.levels.farm * 2 + 5;

    //defensive Actions

    var maxAtk = Math.max(...others.map(o => o.attack));

    storage.shieldTarget = Math.ceil(maxAtk * 1.25 / 1.5) + 1;

    if (me.levels.shield < storage.shieldTarget && me.gold >= cost(me.levels.shield) && me.levels.shield < me.levels.farm)
        return upgrade("shield");

    if (turn() >= 7 && me.shield < 10 && me.levels.shield * 1.5 >= me.levels.heal) return shield();

    if (turn() >= 15 && me.shield < 15 && me.levels.shield * 1.5 >= me.levels.heal) return shield();

    if (turn() >= 30 && me.shield < 20 && me.levels.shield * 1.5 >= me.levels.heal) return shield();

    //attack mode
    // check if there any targets worth to go for

    function findTarget(potentialTargets, baseR){
    var targetUID = "None";
    var best = 0;
    for( var i = 0; i < potentialTargets.length; i++) {
        //We upgrade to attack lvl12, so 20 dmg; assume an enemy can heal/shield up to 15 per round
        var killRounds = Math.ceil(potentialTargets[i].hp / 5)
        var gain = potentialTargets[i].worth / ( 2 * ( killRounds + baseR) )
        //console.log(me, turn(), potentialTargets[i], killRounds, baseR, gain, farmPower)
        if (gain > farmPower * ( killRounds + baseR ) && gain > best)
            targetUID = potentialTargets[i].uid;
            storage.targetStartHP =  potentialTargets[i].hp;
    }
    return targetUID;
    }

    if (turn() >= 600) {

    //check if a current target is dead
    const uids = others.map(x=>x.uid);
        if(storage.targetUid != "None" && !uids.includes(storage.targetUid)) {
        storage.targetUid = "None";
        storage.attackMode = false;
        storage.attackRounds = 0;
    }

    // check if we are doing enough damage to current target
    if (storage.targetUid != "None" && storage.attackRounds >= 3) {

        var deltaHP = storage.targetStartHP - others[storage.targetUid].hp

        if (deltaHP / storage.attackRounds < 5) {
            storage.targetUid = "None";
            storage.attackMode = false;
            storage.attackRounds = 0;

        }

    }

    var investCost = 0
    for( var i = me.levels.attack; i < 12; i++) investCost += cost(i);

    if (storage.attackMode == true && me.gold >= investCost && me.levels.attack < 12) return upgrade("attack");

    if (storage.attackMode == false) {
        baseRounds = investCost / farmPower * 1.2; //overestimation with the heal level we should have at this point

        if (findTarget(others, baseRounds) != "None")
            storage.attackMode = true;

        var betterThanMe = others.filter(o => o.worth >= storage.selfWorth);

        if (betterThanMe.length > 0)
            storage.attackMode = true;

        //storage.attackMode = true;

    }

    }

    if (storage.attackMode == true && me.levels.attack == 12) {

    if (storage.targetUid == "None") {

        var target = findTarget(others, 0)
        storage.targetUid = target;
        storage.attackRounds = 0;
        return attack(target);

    }

    return attack(storage.targetUid)

    }

    //otherwise farm

    if (me.hp < 50) {
    storage.expectHP += 5 + me.levels.heal;
        return heal();
    }

    if (me.gold >= cost(me.levels.farm) && storage.attackMode == false)
        return upgrade("farm");

    //upgrade heal, so we can farm more, but increase farm ability faster
    if (me.levels.farm > 5 && me.levels.heal < 10 && me.gold >= 2*cost(me.levels.heal))
        return upgrade("heal");

   //be opportunistic - check if killing someone is more profitable than farming
    killable = others.filter(o => o.hp < me.levels.attack * 1.25 + 5 && o.worth / 2 > farmPower);
    if (killable.length > 0){
    //ideally check for the most worth target here
        return attack(killable[0].uid);
    }

    storage.expectHP -= 2;
    storage.selfWorth += farmPower;
    return farm();

}

```

# Answer
> 5 votes
# bullyBot

```
function bullyBot(me, others, storage){
    if(turn()==1){return farm();}
    if(storage.bullyTarget==null){storage.bullyTarget=others[0].uid;}

    var targetlives = false;
    for(var i = 0; i < others.length; i++) {
        if (others[i].uid == storage.bullyTarget) {
            targetlives = true;
            break;
        }
    }
    if(!targetlives){storage.bullyTarget = others[0].uid;}

    return stun(storage.bullyTarget);
}

```

Try it online!

May not win but will certainly try his damndest to make sure his target doesn't either. bullyBot also farms on the first turn so that if there's no outside influence, he will beat his target 5-0 or tie them 5-5.

# Answer
> 5 votes
# SniperBot

*This bot will only be effective if someone starts adding bots that actually attack on a regular basis. SmartFarmer is my current optimized solution*

1. heals if can get one-shot
2. heals if under 30
3. attacks bot if can pick it off and earn more money than farming
4. upgrades farming if can afford
5. upgrades healing if is under 80 health and can afford
6. farms

vultures don't need an attack

```
function sniperBot(me, others){
    if(me.hp < 30) return heal();
    for(var i = 0; i < others.length; i++)if(others[i].attack > me.hp)return heal();
    var target = -1;
    var targetWorth = me.levels.farm * 2 + 5;
    for(var i = 0; i < others.length; i++) {
        if (others[i].hp <= 1.25 * me.levels.attack + 5 && others[i].worth / 2 > targetWorth) {
            target= others[i].uid;
            targetWorth = others[i].worth / 2;
        }
    }
    if(target!=-1) return attack(target);
    if(me.gold >= cost(me.levels.farm)) return upgrade("farm");
    if(me.hp < 50 && me.gold >= cost(me.levels.heal)) return upgrade("heal");
    return farm();
}

```

# Answer
> 5 votes
# BullyDozerBot

```
function BullyDozerBot(me, others, storage){
    if(me.gold >= cost(me.levels.attack) && (storage.bullyTarget && storage.bullyTarget.hp < 500)) {
        return upgrade("attack");
    }
    if(storage.bullyTarget==null){
        storage.bullyTarget=others.sort((a,b) => a.hp - b.hp)[0];
    }
    potential_victim = others.find( bot => bot.hp <= me.levels.attack * 1.25 + 5 );
    if (potential_victim) {
        return attack(potential_victim.uid);
    }
    var targetlives = false;
    for(var i = 0; i < others.length; i++) {
        if (others[i] == storage.bullyTarget) {
            targetlives = true;
            break;
        }
    }
    if(!targetlives){
        storage.bullyTarget=others.sort((a,b) => a.hp - b.hp)[0];
    }
    if(storage.bullyTarget.hp >= 500) {
        if(me.gold >= cost(me.levels.farm)) {
            return upgrade("farm");
        }
        for(var i = 0; i < others.length; i++){
          if(others[i].attack*1.25+10 > me.hp){
            return heal();
          }
        }
        return farm();
    }
    return attack(storage.bullyTarget.uid);
}

```

Mashup of BullyBot and some other bits. Optimist had a short and sweet opportunistic attack chunk that I yoinked (though other bots do similar calculations).

Instead of bullying the target by stunning them, *it murders them* for their sweet, sweet loot. It also targets the weakest in the herd for bullying, but it will give up and just go farming if the weakest target's HP is too high.

# Answer
> 4 votes
## ScavengerBot (V2)

Realized it wasn't much of a scavenger before. New strategy is wait until it can kill another bot. If no one can be killed, it sits and builds up shield.

```
function scavengerBot(me, others) {
    if (me.shield < (me.levels.shield * 1.5 + 5)) {
        return shield();
    }
    var currentAttack = 1.25 * me.levels.attack + 5;
    var hasVictim = false;
    var victimUid = 0;
    var maxWorth = 0;
    for (var i = 0; i < others.length; i++) {
        var hp = others[i].hp;
        var worth = others[i].worth;
        if (hp <= currentAttack && worth > maxWorth) {
            hasVictim = true;
            victimUid = others[i].uid;
            maxWorth = worth;
        }
    }

    if (hasVictim) {
        return attack(victimUid);
    }

    if (me.gold >= cost(me.levels.attack)) {
        return upgrade("attack");
    }

    if (me.gold >= cost(me.levels.shield)) {
        return upgrade("shield");
    }
    return shield();
}

```

# Answer
> 4 votes
# Moody

```
function Moody(me, others, storage) {
    health = me.hp + me.shield;
    damage = storage.previous_health - health;
    storage.previous_health = health;
    if( damage > 2 ) {
        storage.fear = 2;
    }
    if( storage.fear ) {
        storage.fear -= 1;
        if( me.gold >= cost(me.levels.heal) )
            return upgrade("heal");
        return heal();
    }
    if ( me.hp <= 50 ) {
        return heal();
    }
    if (cost(me.levels.farm) < 0.15 * (1000 - turn())) {
        if( me.gold >= cost(me.levels.farm) )
            return upgrade("farm");
        if( me.gold >= cost(me.levels.heal) )
            return upgrade("heal");
        return farm();
    }
    rich_bots = others.sort( (x,y) => y.worth - x.worth );
    richest_enemy = rich_bots[0];
    if (richest_enemy.hp >= storage.target_hp) {
        storage.anger = true;
    }
    storage.target_hp = NaN;
    if (storage.anger) {
        if( me.gold >= cost(me.levels.attack) ) {
            storage.anger = 0;
            return upgrade("attack");
        }
        return farm();
    }
    storage.target_hp = richest_enemy.hp;
    return attack(richest_enemy.uid);
}

```

Moody's default strategy is to upgrade farming and healing for a while, then take out the other bots in descending order of worth. However, if it's attacked, it'll get scared and refocus on healing for a bit. If it attacks and "fails", because the victim was healing or shielding more effectively than the attack, it'll get angry and go off to upgrade its attacking abilities.

# Answer
> 4 votes
# The Opportunist

This one borrows a bit from a few others (notably ScavengerBot (V2) and Unkillable) since they had the same ideas I had in mind, but I generally like well-roundedness and jack-of-all-trades styles more than focusing on only one or two things. This will likely mean that I will not win, but it should be in the middle somewhere (which happens to me most of the time in many things).

So it steals juicy kills; heals if necesssary; upgrades farm, attack, and heal in that order; and farms otherwise.

```
function Opportunist(me, others, storage) {

    // Initializing and keeping track of selfWorth
    if (turn() == 1) {
        storage.selfWorth = 0;
    }
    else if (storage.previousGold < me.gold) {
        storage.selfWorth += (me.gold - storage.previousGold);
    }
    storage.previousGold = me.gold;

    // Me stats
    var me_attack = 1.25 * me.levels.attack + 5;
    var me_heal = me.levels.heal + 5;

    // Look for the juiciest hunk of loot
    // If there are multiple of the highest worth, the last is chosen
    var choice = others[0].uid;
    var mostWorthy = -1;
    for (var i = 0; i < others.length; i++) {
        worth = others[i].worth
        if (others[i].hp <= me_attack && worth >= mostWorthy) {
            choice = others[i].uid;
            mostWorthy = worth;
        }
    }

    // Actions in order of priority
    // The juicy targets must be worth the action
    if (mostWorthy > (storage.selfWorth * 0.25) ) {
        return attack(choice);
    }
    else if (me.hp <= 100 - me_heal) {
        return heal()
    }
    else if (me.gold >= cost(me.levels.farm)) {
        return upgrade("farm");
    }
    else if (me.gold >= cost(me.levels.attack)) {
        return upgrade("attack");
    }
    else if (me.gold >= cost(me.levels.heal)) {
        return upgrade("heal");
    }
    else {
        return farm();
    }
}

```

# Answer
> 4 votes
# Bandit

```
function Bandit(me, others, storage) {
    // stuff we need
    const epsilon = 0.3; // really high epsilon
    function argmax(xs) {
        var max = 0;
        var argmax = 0;
        for (var i=0; i<xs.length; i++) {
            if (xs[i]>max) {
                max = xs[i];
                argmax = i;
            }
        }
        return argmax;
    }
    function base3ToActionSeries(strategy) {
        const actions = [shield(), farm(), heal()];
        var idxs = []
        var strategy_cut = strategy;
        for (var i = 81; i >= 1; i /= 3) {
            if (strategy_cut >= 2 * i) {idxs.push(2); strategy_cut -= 2*i}
            else if (strategy_cut >= i) {idxs.push(1); strategy_cut -= i}
            else idxs.push(0);
        }
        return idxs.map(idx => actions[idx]);
    }

    // actual logic starts here
    // current strategy and info to calculate reward
    if (!storage.prior)
        storage.prior = [0,0.03325,0,0.0361,0.0361,0.2372,0,0.2372,0,0.00035,0.0361,0.23555,0.01305,0.0361,0.5798,0.23555,0.62065,0.23555,0,0.2372,0,0.20965,0.5841,0.2372,0,0.21905,0,0.0361,0.0361,0.2081,0.0361,0.0361,0.01455,0.000350,0.62065,0.205,0.000350,0.0361,0.3708,0.0361,0.0323,1.018050,0.5798,0.04495,0.5798,0.23555,0.62065,0.23555,0.62065,1.06395,0.62065,0.23555,0.62065,0.23555,0,0.2372,0,0.2372,0.5841,0.2372,0,0.2372,0,0.23555,0.62065,0.13775,0.5798,1.0257,0.5798,0.23555,0.62065,0.23555,0,0.2339,0,0.2372,0.5841,0.2339,0,0.2372,0,0.0342,0.0361,0.2372,0.03515,0.03325,0.6228,0.2372,0.5841,0.2372,0.0361,0.0130599,0.62065,0.03515,0.0361,1.0665,0.62065,0.24050,0.62065,0.23555,0.51465,0.2372,0.6228,1.0257,0.6228,0.2372,0.5841,0.2372,0.0361,0.0361,0.58195,0.0361,0.0313596,1.0614,0.58195,1.02315,0.58195,0.0342,0.0361,1.0206,0.02255,0.0183,0.02595,1.0206,1.5526,1.0206,0.58195,1.02315,0.58195,0.02765,0.0251,1.0614,0.0007,0.02085,0.3088,0.2372,0.5841,0.2273,0.6185,0.02255,0.6228,0.2372,0.5841,0.2372,0.62065,1.06395,0.62065,1.0665,0.0917,1.0665,0.62065,0,0.62065,0.2372,0.5841,0.2372,0.6228,1.0257,0.6228,0.2372,0.5841,0.2372,0,0.2372,0,0.23225,0.5841,0.2372,0,0.2372,0,0.23555,0.62065,0.23555,0.5798,1.0257,0.5798,0.23555,0.6142,0.23555,0,0.22235,0,0.2372,0.5841,0.2372,0,0.2372,0,0.23555,0,0.21905,0.62065,0.02255,0.62065,0.23555,0.61205,0.23555,0.5798,1.05885,0.5798,1.018050,0.03895,1.018050,0.5798,1.05885,0.5798,0.23555,0.62065,0.23555,0.62065,0.0361,0.62065,0.23555,0.62065,0.23555,0,0.2372,0,0.2372,0.3745,0.2372,0,0.2372,0,0.23555,0.62065,0.23555,0.5798,0.9452,0.5798,0.23555,0.5626,0.23555,0,0.2372,0,0.18175,0.5841,0.0138,0,0.2372,0]
    if (storage.lastScore == null)
        storage.lastScore = 0;
    if (storage.bestStrategy == null)
        storage.bestStrategy = argmax(storage.prior);

    if (cost(me.levels.heal) < me.gold) return upgrade("heal");
    if (cost(me.levels.farm) < me.gold) return upgrade("farm");

    // This barely explores and mostly exploits.
    if (turn() % 5 === 0) {
        // update
        const reward = me.gold/2 - storage.lastScore;
        // biased a bit towards later learned rewards
        storage.prior[storage.bestStrategy] += reward*0.01
        storage.prior[storage.bestStrategy] *= 100/101

        // explore
        if (Math.random() < epsilon) {
            storage.bestStrategy = Math.floor(Math.random()*243);
        }
        else { // exploit
            storage.bestStrategy = argmax(storage.prior);
        }
        storage.lastScore = me.gold/2;
    }

    var action = base3ToActionSeries(storage.bestStrategy)[turn() % 5];
    return action;
}

```

First attempt at a reinforcement learning bot. Purely defensive for now to narrow down the search space. Sort of a smarter spinoff of FizzBuzz -- it repeats a specific series of five actions over and over; the five actions are what are chosen by RL.

But it's mostly based off of enumeration for now -- I just generated all 3^5=243 permutations of series of five defensive actions that repeated itself over and over, and stored their average scores (divided by 200, to get the average gain over five turns) over 100 iterations in the `storage.prior` array. Then, during the game, it implements an epsilon-greedy approach to updating those score lists so it's more future-proof. (Also because using epsilon=0.3 did way better than epsilon=0.1 so I just kept it.)

It does okay, consistently placing between scavengerBot and Optimist. I'm currently doing some more training on real games, and looking for better ways to frame the strategy, to see if I can improve it.

# Answer
> 4 votes
# ScaredBot

1. It finds other bots:
    * with the highest attack
    * with most wealth and HP lower than own attack
2. If its HP+shield is lower than the found `highest attack * (25% of bots)`, or it gets near the lower end of `HP + shield`, then it shields
3. If it found a bot with lower shield than its own attack, it attacks it.
4. If its health is `< 50`, it heals.
5. If it can upgrade any of shield, heal and farm, it upgrades the one with the lowest level
6. It farms

```
function ScaredBot(me, others) {
    const my_attack = me.levels.attack * 1.25 + 5;
    const my_defense = me.hp + me.shield;

    var max_attack_val = 0;
    var min_hp_worth = 0;
    var min_hp_id = null;
    var hp_under_me = 0;
    for (var i=0; i<others.length; i++){
        if (others[i].hp < my_attack && others[i].worth > min_hp_worth){
            min_hp_id = others[i].uid;
            min_hp_worth = others[i].worth;
        }
        if (others[i].attack*1.25+5 > max_attack_val){
            max_attack_val = others[i].attack*1.25+5;
        }
        if (others[i].hp < my_defense && others[i].hp > 0){
            hp_under_me++;
        }
    }
    if (max_attack_val*0.25*others.length > my_defense || hp_under_me < 0.25*others.length){
        return shield();
    }
    else if (min_hp_id != null){
        return attack(min_hp_id);
    }
    else if (me.hp < 50){
        return heal();
    }
    else {
        var min_lvl = NaN;
        var min_name = null;
        const vals = [me.levels.heal, me.levels.shield, me.levels.farm];
        const names = ["heal", "shield", "farm"];
        for (var i=0; i<vals.length; i++){
            if (!(min_lvl < vals[i])){
                min_lvl = vals[i];
                min_name = names[i];
            }
        }
        if (me.gold > cost(min_lvl)){
            return upgrade(min_name);
        }
        return farm();
    }
}

```

The idea is to stay alive the longest possible and otherwise try getting gold in a safe and cheap way to be able to upgrade.

Upgrade priorities should probably be tweaked, as well as the condition when determining on whether to shield.

# Answer
> 4 votes
# reallyCommittedTurtle

```
function reallyCommittedTurtle(me, others, storage) {
    if( storage.previousHP ) {
        others.forEach ( o => {storage.deltaHP[o.uid] = o.hp - storage.previousHP[o.uid]; storage.previousHP[o.uid] = o.hp } );
    }
    else {
        storage.previousHP = {};
        storage.deltaHP = {};
        others.forEach ( o => storage.previousHP[o.uid] = o.hp );
    }
    if (turn() < 3)
        return upgrade("shield");
    if ( me.shield < 400 || others.find( o=> o.deltaHP < -2 ) )
        return shield();
    if (me.hp <= 95 - me.levels.heal) {
        if (me.gold >= cost(me.levels.heal))
            return upgrade("heal");
        return heal();
    }
    rich_bots = others.sort( (x,y) => y.worth - x.worth );
        potential_victim = rich_bots.find( bot => bot.hp + storage.deltaHP[bot.uid] <= me.levels.attack * 1.25 + 5 );
        if (potential_victim && potential_victim.worth/2 > me.levels.farm*2 + 5)
            return attack(potential_victim.uid);
    if (me.gold >= cost(me.levels.farm))
        return upgrade("farm");
    return farm();
}

```

Here's the thing. It's gotten really dangerous out there. Farming at all increases your worth, making you a target. So it's really not safe to farm until you've built up a huge shield and all the violence has died down. Then you can poke your head out of your shell and start farming. Or kill-assisting. Whatever pays better.

# Answer
> 3 votes
# Friendly bot

```
function menShengFaDaCai(me, others) {
  // heal if needed
  const maxAttack = Math.max(...others.map(bot => bot.attack));
  const maxAttackCost = maxAttack * maxAttack + 5;
  const othersHp = others.map(bot => bot.hp).sort();
  const targetHp = othersHp[Math.ceil(othersHp.length / 2)];
  if (me.hp < 95 && me.hp < Math.max(maxAttackCost * 2, targetHp, 50)) return heal();

  // upgrade heal and farm if possible
  const { heal: healLevel, farm: farmLevel } = me.levels;
  const gain = (heal, farm) => ((5 + heal) / 2) * (2 * farm + 5) / ((5 + heal) / 2 + 1);
  const gain0 = gain(healLevel, farmLevel);
  const gainUpgradeHeal = gain(healLevel + 1, farmLevel);
  const gainUpgradeFarm = gain(healLevel, farmLevel + 1);
  const gainUpgradeHealPerGold = (gainUpgradeHeal - gain0) / cost(healLevel);
  const gainUpgradeFarmPerGold = (gainUpgradeFarm - gain0) / cost(farmLevel);
  const preferUpgradeHeal = gainUpgradeHealPerGold > gainUpgradeFarmPerGold;
  const mayOffer = type => me.gold >= cost(me.levels[type]);
  if (preferUpgradeHeal && mayOffer('heal')) return upgrade('heal');
  if (!preferUpgradeHeal && mayOffer('farm')) return upgrade('farm');

  // keep farming
  return farm();
}

```

`others[0].hp` is `hp + shield` instead of `hp`...

# Answer
> 3 votes
# SmartFarmer

Farms, upgrades farming, heals if low health. Farming seemed overpowered until the truly offensive bots arrived. Now my bot gets killed :-(

```
function smartFarmer(me, others){
    if(me.hp < 13) return heal();
    for(var i = 0; i < others.length; i++)if(others[i].attack * 1.25 + 5 > me.hp)return heal();
    if(me.gold >= cost(me.levels.farm)) return upgrade("farm");
    if(me.levels.heal < 9 && me.levels.farm > me.levels.heal + 7 && me.gold >= cost(me.levels.heal)) return upgrade("heal");
    return farm();
}

```

# Answer
> 3 votes
# Mort

```
function Mort(me, others, storage) {
    if (me.hp <= 100 - (me.levels.heal + 5))
        return heal();
    actions = ["farm", "heal", "attack"].filter(action => cost(me.levels[action]) <= me.gold).map( action => [upgrade(action), 1000 - turn() - cost(me.levels[action]) ] )
    my_damage = me.levels.attack * 1.25 + 5;
    actions = actions.concat(others.map( bot => [ attack(bot.uid), (bot.worth/2)/Math.max(bot.hp/(my_damage-(bot.hp > my_damage ? 5 : 0)),1) ] ));
    actions.push( [farm(), (2 * me.levels.farm + 5)*(1-2/(me.levels.heal+5))] );
    return actions.sort( (x,y) => y[1] - x[1] )[0][0];
}

```

Each turn, compares the amortized profit of killing each bot to that of farming and healing and picks the best option. Really it should use state to figure out how long it'll take to kill a bot, but for now it just assumes every bot heals or shields an average of 5 points a turn net of damage other bots do.

# Answer
> 3 votes
# The Accountant

This practical bot calculates the most economically beneficial move, but he likes to keep his attack profile low to avoid trouble from all of the vigilante bots. He doesn't try to pick help the defenseless or prey on them. Rather, he does what helps him the most.

```
function accountant(me, others, storage) {
    if (turn() == 1) {
        storage.lastHP = me.hp + me.shield;
        storage.hisAttack = 5;
        storage.timesAttacked = 0;
        storage.lastAttack = -1;
        storage.healths = [], storage.uids = [], storage.heals = [];
        for (var i = 0; i < others.length; i++) {
            storage.healths.push(others[i].hp);
            storage.uids.push(others[i].uid);
            storage.heals.push(5);
        }
    }
    storage.timesAttacked++;
    if (storage.lastHP == me.hp + me.shield) storage.timesAttacked = 0;
    else storage.hisAttack = storage.lastHP - me.hp - me.shield;
    storage.lastHP = me.hp + me.shield;
    var attacks = [];
    for (var i = 0; i < others.length; i++) if (others[i].uid != me.uid) attacks[i] = 1.25 * others[i].attack + 5;
    attacks.sort();
    for (var i = 0; i < others.length; i++) {
        storageIndex = storage.uids.indexOf(others[i].uid);
        if (storage.heals[storageIndex] < others[i].hp - storage.healths[storageIndex] + (others[i].uid == storage.lastAttack ? 1.25 * me.levels.attack + 5 : 0)) others[i].hp - storage.healths[storageIndex] + (others[i].uid == storage.lastAttack ? 1.25 * me.levels.attack + 5 : 0);
    }
    var maxProfitTurn = 2 * me.levels.farm + 5, victimID = -1, tempProfit;
    for (var i = 0; i < others.length; i++) {
        storageIndex = storage.uids.indexOf(others[i].uid);
        tempProfit = others[i].worth / 2 * (1.25 * me.levels.attack + 5 - storage.heals[storageIndex]) / others[i].hp;
        if (tempProfit > maxProfitTurn) {
            victimID = others[i].uid;
            maxProfitTurn = tempProfit;
        }
    }
    maxUrgentProfit = 0;
    for (var i = 0; i < others.length; i++) if (maxUrgentProfit < others[i].worth / 2 && others[i].hp <= attacks.slice(0, 4).reduce((a, b) => a + b) + 1.25 * me.levels.attack + 5) {
        maxUrgentProfit = others[i].worth / 2;
        victimID = others[i].uid;
    }
    if (maxUrgentProfit > 0) {
        storage.lastAttack = victimID;
        return attack(victimID);
    }
    storage.lastAttack = -1;
    if (storage.timesAttacked == 0) {
        if (me.levels.shield < 20 && me.gold >= cost(me.levels.shield)) return upgrade("shield");
        if (me.levels.heal < 5 && me.levels.shield >= me.levels.heal + 5 && me.gold >= cost(me.levels.heal)) return upgrade("heal");
        if (Math.random() < Math.pow((me.hp + me.shield) / 100, -2)) {
            storage.lastHP += 1.5 * me.levels.shield + 5;
            return shield();
        }
    }
    else {
        if (Math.random() < .5 || me.hp + me.shield - storage.hisAttack - attacks[0] <= 10) {
            storage.lastHP += 1.5 * me.levels.shield + 5;
            return shield();
        }
        if (me.levels.shield < 20 && me.gold >= cost(me.levels.shield)) return upgrade("shield");
        if (me.hp <= 2) {
            storage.lastHP += me.levels.shield + 5;
            return heal();
        }
        storage.lastHP -= 2;
        return farm();
    }
    if (me.gold >= cost(me.levels.farm)) return upgrade("farm");
    storage.lastAttack = victimID;
    if (victimID != -1) return attack(victimID);
    if (me.hp <= 2) {
        storage.lastHP += me.levels.shield + 5;
        return heal();
    }
    storage.lastHP -= 2;
    return farm();
}

```

# Answer
> 2 votes
## Indestructible

A modification of Draco18's bot, using shields (more effective against other bots)

```
function indestructible(me){
    if (me.hp < 100) {
        return heal();
    } else if (me.shield < 15) {
        return shield();
    } else {
        if (me.gold >= cost(me.levels.shield)) {
            return upgrade("shield");
        } else if (me.gold >= cost(me.levels.farm)) {
            return upgrade("farm");
        } else {
            return farm();
        }
    }
}

```

# Answer
> 2 votes
# Guardian

I can have more than one submission, right?

A fork of CampBot. Doesn't shield, instead focusing on attacking. Shows a preference for attacking players with higher attack stats, rather than striking at random like CampBot. Focuses on upgrading its farming rather than healing.

```
function guardian(self,others,storage){
    if(!storage.victimBlacklist){
        storage.victimBlacklist=[]
    }
    let turnsLeft=999-turn()
    function findVictim(){
        let potentialVictims=others.filter(bot=>!storage.victimBlacklist.includes(bot.uid))
        if(potentialVictims.length>0){
            let victim=potentialVictims.reduce((el, em) => el.attack > em.attack ? el : em);
            storage.victimUid=victim.uid
            storage.victimPrevHp=victim.hp
            storage.prevMove="attack"
            return attack(victim.uid)
        }else{
            storage.prevMove="farm"
            return farm()
        }
    }
    if(self.hp<=(95-self.levels.heal)){
        storage.prevMove="heal"
        return heal()
    } else if(self.gold>=cost(self.levels.attack)){
        storage.prevMove="upgrade"
        return upgrade("attack")
    } else if(self.gold>=cost(self.levels.farm)&&turnsLeft>100&&self.levels.heal<=1){
        storage.prevMove="upgrade"
        return upgrade("farm")
    } else if(!storage.victimUid){
        return findVictim()
    }else if(Object.values(others).map(bot=>bot.uid).includes(storage.victimUid)){
        let victimCurrHp=Object.values(others).filter(bot=>bot.uid==storage.victimUid)[0].hp
        if(storage.victimPrevHp<victimCurrHp&&storage.prevMove==="attack"){
            storage.victimBlacklist.push(storage.victimUid)
            storage.victimUid=undefined
            return findVictim()
        }else{
            storage.victimPrevHp=victimCurrHp
            storage.prevMove="attack"
            return attack(storage.victimUid)
        }
    }else{
        storage.victimUid=undefined
        return findVictim()
    }
}

```

# Answer
> 2 votes
# Kill Bot

```
function killBot(me, others, storage) {
    // If I lost health since my last check, shield.
    if (me.hp < storage.hp){
        storage.hp = me.hp;
        return shield();
    }

    storage.hp = me.hp;

    health = Math.min(...others.map(o => o.hp));
    // If I have the least health or can be one-shot, shield.
    if (others.some(o => o.attack * 1.25 + 5 >= me.hp + me.shield) || (health > me.hp + me.shield && health < 500)) return shield();

    // If I can kill someone, kill them!
    targets = others.filter(o => o.hp < me.attack);
    if (targets.length > 0){
        wealth = Math.max(...targets.map(o => o.worth));
        targets = targets.filter(o => o.worth == wealth);
        target = targets[Math.floor(Math.random()*targets.length)];
        return attack(targets[0].uid);
    }

    // If I have the money, upgrade shielding or attack
    if (me.levels.shield <= me.levels.attack){
        if (cost(me.levels.shield) < me.gold) return upgrade("shield");
    } else {
        if (cost(me.levels.attack) < me.gold) return upgrade("attack");
    }

    // Otherwise, attack the weakest!
    targets = others.filter(o => o.hp == health);
    // And if there's a tie, attack the wealthiest.
    wealth = Math.max(...targets.map(o => o.worth));
    targets = targets.filter(o => o.worth == wealth);
    target = targets[Math.floor(Math.random()*targets.length)];
    return attack(targets[0].uid);
}

```

A simple bot, Kill Bot just wants to kill its enemies. Since shielding is much more efficient than healing (especially when levelled), Kill Bot just tries to always be an unappealing target by shielding itself whenever attacked. Kill Bot does quite well among the weak, pacifistic bots around here (you can feel its scorn for them).

# Answer
> 2 votes
# Rando

This silly guy will choose actions based on uniform randomness with some biases. If a randomly chosen action won't work, then it drops down to the next choice.

So on average, he should attack almost 2/9 of the time and farm almost 3/9 of the time. The rest are about 1/9 chance if he is able to upgrade, or if the healing/shielding is worth it, etc.

He will not likely perform well, but at least there's a small chance that he reigns supreme. And that's the whole purpose of Rando. He just needs to believe in himself! All the options are laid in front of him. He needs only choose what is needed for any given situation.

```
function Rando(me, others, storage) {

    var rnum = Math.floor(Math.random() * 9);
    switch (rnum) {
        case 0:
            if (me.gold >= cost(me.levels.shield)) {
                return upgrade("shield");
            }
        case 1:
            if (me.hp >= 100 - (me.levels.heal + 5) && me.levels.shield >= me.levels.heal) {
                return shield();
            }
        case 2:
            if (me.hp < 100 - (me.levels.heal + 5)) {
                return heal();
            }
        case 3:
            if (me.gold >= cost(me.levels.farm)) {
                return upgrade("farm");
            }
        case 4:
            if (me.gold >= cost(me.levels.heal)) {
                return upgrade("heal");
            }
        case 5:
            if (me.hp > 2) {
                return farm();
            }
        case 6:
            // Beat down the leader!
            var currentLeader = others[0].uid;
            var leaderWorth = -1;
            for (var i = 0; i < others.length; i++) {
                worth = others[i].worth;
                if (worth > leaderWorth) {
                    currentLeader = others[i].uid;
                    leaderWorth = worth;
                }
            }
            return stun(currentLeader);
        case 7:
            if (me.gold >= cost(me.levels.attack)) {
                return upgrade("attack");
            }
        case 8:
            // Find the juiciest kill (if any), or attack the strongest
            var choice = others[0].uid;
            var choiceWorth = -1;
            var currentLeader = others[0].uid;
            var leaderWorth = -1;
            for (var i = 0; i < others.length; i++) {
                worth = others[i].worth
                if (worth > leaderWorth) {
                    currentLeader = others[i].uid;
                    leaderWorth = worth;
                }
                if (others[i].hp <= (1.25 * me.levels.attack + 5) && worth >= choiceWorth) {
                    choice = others[i].uid;
                    choiceWorth = worth;
                }
            }
            if (choice > -1) {
                return attack(choice);
            }
            else {

                return attack(currentLeader);
            }
        default:
            return false
    }
}

```

(I know "default" is unnecessary, but I think it is good coding practice for robust code.)

# Answer
> 2 votes
# FarmHeal Bot

Forked from @Anonymous' JustFarm bot

```
function farmhealBot(me, others, storage) {
  if (me.hp <= 95)
    return heal();
  else return farm();
}

```

# Answer
> 1 votes
# PacifistBot

He keeps track of every single bot in the game via `storage.others`. It permits him to know of the dead guys' worth to know if he can win, even when they're dead.

**Decision tree**:

* If he's 1v1 and winning, **stuns** the opponent until turn 1000.
* If he's really low life, **heal**. Has to be rethinked because it calcs on max atk over all the others, and now others are more aggressive.
* If he's not safe, **shield**. It's the main source of its defense since it will upgrade shield the most. Has to be rethinked because I forgot to take `shield` attribute in account, I was using `me` like I use `others` (`hp` being `hp` \+ `shield`).
* **Upgrades heal** once, so to level 1, never more. it permits 3 farms per heal for a ridiculously low cost, rather than 5 farms per 2 heals.
* **Upgrades shield** if someone becomes aggressive. Could be rethinked to look out for aggressiveness towards him.
* **Upgrades farm** if possible, keeping a solid active gold basis to be able to upgrade shield in case of imminent danger.
* **Farms**.

```
function pacifistWinnerBot(me, others, storage) {
	if(!storage.start){
		storage.start=true;
		storage.others = others;
	}
	others.map(bot =>
		storage.others.map(
			bot2 => {if(bot2.uid==bot.uid)bot=bot2}//update worth, hp, attack level
		)
	);
	const maxAtk = 5+1.25*Math.max(storage.others.map(bot => bot.attack));
	if(storage.win || ((me.gold > Math.max(storage.others.map(bot => bot.worth))+25) && storage.others.reduce((bot,x) => x+(bot.hp<=0),0)==1)){
		storage.win=true;
		return stun(storage.others.filter(bot => bot.hp>0)[0].uid);
	}
	if(me.hp < 2+maxAtk) return heal();
	if(me.hp < 2+maxAtk*2) return shield();
	if(me.levels.healing<1 && me.gold>cost(me.levels.healing)) return upgrade("heal");
	if((me.gold > cost(me.levels.shield)) && (1.5*me.levels.shield+5 < 2*maxAtk)) return upgrade("shield");
	if(me.gold > 50+cost(me.levels.farm)) return upgrade("farm");
	return farm();
}

```

Try it online! with for timestamp 4.57pm Aug 2nd UTC+2.

BullyDozer is making it hard, but still happy with what I've done.

# Answer
> 1 votes
# CampBot

```
function campBot(self,others,storage){
    if(!storage.victimBlacklist){
        storage.victimBlacklist=[]
    }
    let turnsLeft=999-turn()
    function findVictim(){
        let potentialVictims=others.filter(bot=>bot.worth>70&&((bot.attack>1&&bot.hp<200)||bot.hp<80)&&!storage.victimBlacklist.includes(bot.uid))
        if(potentialVictims.length>0){
            let victim=potentialVictims[Math.floor(Math.random()*potentialVictims.length)]
            storage.victimUid=victim.uid
            storage.victimPrevHp=victim.hp
            storage.prevMove="attack"
            return attack(victim.uid)
        }else{
            storage.prevMove="farm"
            return farm()
        }
    }
    if(self.hp<=(95-self.levels.heal)){
        storage.prevMove="heal"
        return heal()
    } else if(self.shield<=50){
        return shield()
    } else if(self.gold>=cost(self.levels.attack)&&turnsLeft>100&&self.levels.attack<=3){
        storage.prevMove="upgrade"
        return upgrade("attack")
    } else if(self.gold>=cost(self.levels.farm)&&cost(self.levels.farm)<turnsLeft*(2*(self.levels.farm+1)+5)){
        storage.prevMove="upgrade"
        return upgrade("farm")
    }else if(self.gold>=cost(self.levels.heal)&&cost(self.levels.heal)<turnsLeft/(self.levels.heal+6)*(2*self.levels.farm+5)&&self.levels.heal<=2){
        storage.prevMove="upgrade"
        return upgrade("heal")
    }else if(self.gold>=cost(self.levels.shield)&&self.levels.shield<=3){
        return upgrade("shield")
    }else if(!storage.victimUid){
        return findVictim()
    }else if(Object.values(others).map(bot=>bot.uid).includes(storage.victimUid)){
        let victimCurrHp=Object.values(others).filter(bot=>bot.uid==storage.victimUid)[0].hp
        if(storage.victimPrevHp<victimCurrHp&&storage.prevMove==="attack"){
            storage.victimBlacklist.push(storage.victimUid)
            storage.victimUid=undefined
            return findVictim()
        }else{
            storage.victimPrevHp=victimCurrHp
            storage.prevMove="attack"
            return attack(storage.victimUid)
        }
    }else{
        storage.victimUid=undefined
        return findVictim()
    }
}

```

If there is an easy target with a decent amount of gold, then it attacks it. If it discovers that the other bot heals faster than it can attack, then it blacklists the other bot from being attacked and finds another victim. If there are no good targets, it just camps by farming while waiting for a good target(hence the name).

# Answer
> 1 votes
# Serial Killer

```
function serialKiller(self,others,storage){
    let turnsLeft=999-turn()
    let lowestHpBots=others.sort((a,b)=>a.hp-b.hp)
    if(self.hp<=(95-self.levels.heal)){
        return heal()
    } else if(self.shield<=150||self.shield<=6000/others.length&&self.shield<=1200&&turn()>=20||lowestHpBots[1]&&lowestHpBots[1].hp>self.hp+self.shield){
        return shield()
    } else if(self.gold>=cost(self.levels.attack)&&turnsLeft>20){
        return upgrade("attack")
    }else if(self.gold>=cost(self.levels.shield)&&self.levels.shield<=4&&turnsLeft>20){
        return upgrade("shield")
    }else{
        return attack(others.sort((a,b)=>a.hp-b.hp)[0].uid)
    }
}

```

This bot's one goal is to kill everything, starting from the bot with the lowest health.

# Answer
> 1 votes
## Captain Farmer

It's hard being everyone's favorite superhero, so he just kills the villains that are easy to get. When he's not busy letting other people do his job, he farms gold and heals once he reaches a certain threshold. When his health gets too low, he'll put up some shields to keep himself safe from the villains (other bots), so he can get back to farming. If he knows he's going to die, he'll farm for the rest of his short life to maximize his gold output.

```
function captFarmer(me, others, storage) {
    if (!storage.mode)
        storage.mode = "prep";
    var weak = others.find(el => el.hp < me.levels.attack * 1.25 + Math.max(...others.map(el => el.attack)) * 1.75 + 10 && Math.ceil(el.worth / 2) > me.levels.farm * 2 + 5);
    if (weak && storage.weak >= 0) {
        storage.weak += 1;
        return attack(weak.uid);
    }
    if (storage.weak < 0)
        storage.weak += 1;
    else if (storage.weak > 3)
        storage.weak = -3;
    else if (!storage.weak)
        storage.weak = 0;
    if (me.hp + me.shield < 90)
        storage.mode = "lowhp";
    if (storage.mode == "prep") {
        if (turn() < 5)
            return shield();
        if (turn() == 5)
            return upgrade("attack");
        if (turn() == 6)
            return upgrade("attack");
        storage.modeTimer = 0;
        storage.mode = "farm";
    } else if (storage.mode == "lowhp") {
        let last = storage.lastHp;
        let hp = me.hp + me.shield;
        storage.lastHp = hp;
        if (!last)
            return shield();
        if (me.hp == 100) {
            if (me.shield >= 25) {
                storage.mode = "farm";
                storage.modeTimer = 0;
            }
            return shield();
        }
        if (last > hp) {
            if (last - hp + me.levels.heal + 5 <= me.levels.shield * 1.5 + 5)
                return shield();
            else
                return farm();
        } else {
            return shield();
        }
    } else if (storage.mode == "farm") {
        if (me.gold >= cost(me.levels.shield))
            return upgrade("shield");
        if (me.gold >= cost(me.levels.farm))
            return upgrade("farm");
        if (me.gold >= cost(me.levels.attack))
            return upgrade("attack");
        if (me.hp > 80 && !storage.healMode)
            return farm();
        storage.healMode = true;
        if (me.hp < 97)
            return heal();
        storage.healMode = false;
        return shield();
    }
    return shield();
}

```

# Answer
> 1 votes
# Persistent Blue Shell

```
function BlueShell(me, others, storage) {
    var victimUid = 0;
    var maxWorth = 0;
    var needNewVictim = true;
    var victimHp = 100;
    for (var i = 0; i < others.length; i++) {
        var hp = others[i].hp;
        var worth = others[i].worth;
        var uid = others[i].uid;
        if (worth > maxWorth) {
            victimUid = uid;
            maxWorth = worth;
            victimHp = hp;
        }
        if (uid == storage.victim) {
            needNewVictim = false;
        }
    }
    var attacked = false;
    if (turn() > 1) {
        attacked = (me.hp + me.shield) < (storage.hp + storage.shield);
    }
    storage.hp = me.hp;
    storage.shield = me.shield;
    if (needNewVictim || !storage.victim || attacked) {
        storage.victim = victimUid;
        storage.victimHp = victimHp;
        if (cost(me.levels.shield) <= me.gold) {
            return upgrade("shield");
        } else {
            return shield();
        }
    }
    if (storage.victimHp <= 5) {
        return attack(storage.victim)
    }
    return stun(storage.victim);
}

```
* Select the bot with highest worth
* Repeatedly attempt to stun (attack if victim has \< 5 health)
* If the chosen bot dies or BlueShell gets deflected (i.e. attacked) re-evaluate who is in the lead and target them instead.
    + But first shield once to avoid dying (hopefully) mitigate damage from attacks

Will never win, and almost never ends with a non-zero worth, but when testing it looks like it will affect the order of the bots in the top few places

# Answer
> 1 votes
# AntiWar

```
function antiWar(self,others,storage){
    let turnsLeft=999-turn()
    let lowestHpBots=others.sort((a,b)=>a.hp-b.hp)
    if(self.shield<=50||self.shield<=5500/others.length&&self.shield<=1200&&turn()>=20||lowestHpBots[1]&&lowestHpBots[1].hp>self.hp+self.shield){
        return shield()
    } else if(self.gold>=cost(self.levels.attack)&&turnsLeft>20){
        return upgrade("attack")
    }else if(self.gold>=cost(self.levels.shield)&&self.levels.shield<=4&&turnsLeft>20){
        return upgrade("shield")
    }else{
        return stun(others.sort((a,b)=>b.attack-a.attack)[0].uid)
    }
}

```

This bot hates all others that fight and tries to prevent war. Its method of doing this is stunning the bot with the most attack, as that bot is most likely to attack others.

# Answer
> 1 votes
# LittleAnt

Didn't really have time. Wrote it in last moment. Had only time to test if it works. No idea how it will do.

```
function LittleAnt(me, others) {
    if (turn() == 1) {
        return upgrade('farm');
    }
    if (turn() ==2) {
        return upgrade('shield');
    }
    let avgHp = 0;
    let minHp = 100;
    let maxHp = 0;
    let avgGold = 0;
    let maxGold = 0;
    let avgAttack = 0;
    let maxAttack = 0;
    let i = 0, calculatedValue;
    let countOthers = others.length;
    let currEnemy = null;
    let estimatedAttackers = 0;
    let maxAttackEnemyId = null;
    let maxUpgradeName = null;
    let maxAttackValue = 0;
    let maxHealValue = 0;
    let maxUpgradeValue = 0;
    let maxFarmValue = 0;
    let bestTacticValue = 0;
    let maxShieldValue = 0;
    let levels = [
        {
            name: "attack",
            level: me.levels.attack,
            averageValue: 2,
            estimatedValue: 0
        },
        {
            name: "farm",
            level: me.levels.farm,
            averageValue: 6,
            estimatedValue: 0
        },
        {
            name: "heal",
            level: me.levels.heal,
            averageValue: 3,
            estimatedValue: 0
        },
        {
            name: "shield",
            level: me.levels.shield,
            averageValue: 8,
            estimatedValue: 0
        }
    ];

    for (i = 0; i < countOthers; i++) {
        currEnemy = others[i];
        avgHp += currEnemy.hp / countOthers;
        avgGold += currEnemy.worth / countOthers;
        avgAttack += currEnemy.attack / countOthers;
        maxHp = ((maxHp > currEnemy.hp) ? maxHp : currEnemy.hp);
        minHp = ((minHp < currEnemy.hp) ? minHp : currEnemy.hp);
        maxGold = ((maxGold > currEnemy.worth) ? maxGold : currEnemy.worth);
        maxAttack = ((maxAttack > currEnemy.hp) ? maxAttack : currEnemy.hp);
        estimatedAttackers = Math.floor(Math.sqrt(countOthers - 1));
        calculatedValue = (-currEnemy.hp + estimatedAttackers * (me.levels.attack + 5)) * (currEnemy.worth / 2);
        maxAttackValue = maxAttackValue > calculatedValue ? maxAttackValue : calculatedValue;
        maxAttackEnemyId = maxAttackValue > calculatedValue ? maxAttackEnemyId : currEnemy.uid;
    }

    maxHealValue = 100 - me.hp + Math.sqrt(turn()) + 5 + Math.sqrt(countOthers);

    for (i = 0; i < 4; i++) {
        if (me.gold - cost(levels[i].level) >= 0) {

        } else {
            levels[i].estimatedValue = -100;
        }
        levels[i].estimatedValue = Math.sqrt(me.hp) * (me.gold / cost(levels[i].level) * levels[i].averageValue) - Math.sqrt(turn());
        maxUpgradeValue = maxUpgradeValue > levels[i].estimatedValue ? maxUpgradeValue : levels[i].estimatedValue;
        maxUpgradeName = maxUpgradeValue > levels[i].estimatedValue ? maxUpgradeName : levels[i].name;
    }

    maxFarmValue = 5 + Math.sqrt(turn()) + me.levels.farm - 2 - Math.sqrt(maxHealValue);
    maxShieldValue = Math.sqrt(turn()) * me.shield + 50;
    maxShieldValue = maxShieldValue > 80 ? maxShieldValue : 80;

    bestTacticValue = Math.max(maxHealValue, maxAttackValue, maxFarmValue, maxUpgradeValue, maxShieldValue);

    if (me.hp < 3) {
        return heal();
    } else {
        if (Math.abs(maxAttackValue - bestTacticValue) < 1) {
            return attack(maxAttackEnemyId);
        }
        if (Math.abs(maxFarmValue - bestTacticValue) < 1) {
            return farm();
        }
        if (Math.abs(maxUpgradeValue - bestTacticValue) < 1) {
            return upgrade(maxUpgradeName);
        }
        if (Math.abs(maxHealValue - bestTacticValue) < 1) {
            return heal();
        }
    }
    return farm();
 }

```

# Answer
> 1 votes
# Reformed TeamBot

```
function reformedAttackBot(self,others,storage){
    let turnsLeft=999-turn()
    let lowestHpBots=others.sort((a,b)=>a.hp-b.hp)
    let maxDamage=others.map(c=>c.attack).reduce((a, b) => Math.max(a, b))*1.25+5
    if(storage.attackFailures===undefined){
        storage.attackFailures=0
    }
    if(!storage.worth){
        storage.worth=5
        storage.prevGold=self.gold
    }else if(self.gold>storage.prevGold){
        storage.worth+=self.gold-storage.prevGold
    }
    if(others.length===1&&storage.worth>others[0].worth){
        //stun lock the other bot if there are only 2 left and I can win
        return stun(others[0].uid)
    } else if(self.hp<=(95-self.levels.heal)){
        return heal()
    } else if(lowestHpBots[0]&&lowestHpBots[0].hp<=25&&lowestHpBots[0].worth/2>2*self.levels.farm+5&&self.hp+self.shield>=110){
        //kill assist
        return attack(lowestHpBots[0].uid)
    } else if(self.shield<=200||self.shield<=6000/others.length&&self.shield<=1200&&turn()>=20||lowestHpBots[1]&&lowestHpBots[1].hp>self.hp+self.shield){
        return shield()
    }if(storage.attackFailures>3){
        if(self.gold>=cost(self.levels.shield)&&self.levels.shield<=6){
            return upgrade("shield")
        } else if(self.gold>=cost(self.levels.farm)&&(turnsLeft+1)*(2*(self.levels.farm)+5)<turnsLeft*(2*(self.levels.farm+1)+5)){
            return upgrade("farm")
        } else if(self.gold>=cost(self.levels.heal)&&(turnsLeft+1)/(self.levels.heal+5)*(2*self.levels.farm+5)<turnsLeft/(self.levels.heal+6)*(2*self.levels.farm+5)&&self.levels.heal<=2){
            return upgrade("heal")
        }else{
            return farm()
        }
    } else if(self.gold>=cost(self.levels.attack)&&turnsLeft>20&&self.levels.attack+1<Math.max(others.map(bot=>bot.attack))){
        return upgrade("attack")
    } else if(self.gold>=cost(self.levels.shield)&&self.levels.shield<=4&&turnsLeft>20){
        return upgrade("shield")
    } else if(others.length>0){
        if(others.find(bot=>bot.uid===storage.target)===undefined){
            let target=others.sort((a,b)=>b.worth-a.worth)[0]
            storage.target=target.uid
            if(storage.targetPrevHP!==undefined&&storage.targetPrevHp<target.hp){
                storage.attackFailures++
                return farm()
            }else{
                storage.targetPrevHp=target.hp
                return attack(target.uid)
            }
        }
    } else if(self.gold>=cost(self.levels.farm)&&turnsLeft>100){
        return upgrade("farm")
    }else{
        return farm()
    }
}

```

After the ban on teaming, TeamBot - Attack reformed and stopped teaming. This hasn't prevented it from exploiting PersistentBlueShell's stunning to attack, though. If PersistentBlueShell dies, it switches to farming.

Old Teambots

# Answer
> 1 votes
## LettuceBot

Nobody really likes, nobody really hates it. Bots eat it, but usually not on its own.

```
function lettuceBot(me, others, storage) {
    var weak = others.find(el => el.hp < me.levels.attack * 1.25 + Math.max(...others.map(el => el.attack)) * 2.5 + 10 && Math.ceil(el.worth / 2) >= 5);
    if (weak)
        return attack(weak.uid);
    if (me.levels.heal < 1)
        return upgrade("heal");
    if (me.gold >= cost(me.levels.farm))
        return upgrade("farm");
    if (me.shield < 100)
        return shield();
    if (me.hp <= 94)
        return heal();
    return farm();
}

```

# Answer
> 1 votes
# Bernard Szumborski

```
function BernardSzumborski(me, others) {
    this.getLevel = function (type) {
        return (typeof me.levels[type] === 'undefined' ? 0 : me.levels[type]);
    };

    this.getAttackPower = function (level) {
        if (typeof level === 'undefined') level = this.getLevel('attack');
        return (level * 1.25) + 5;
    };

    this.shieldOrUpgrade = function () {
        if (myGold >= cost(this.getLevel('shield'))) return upgrade('shield');
        return shield();
    };

    let currentTurn = turn(),
        myGold = me.gold,
        myTotalHp = me.hp + me.shield,
        myAttackPower = this.getAttackPower(),
        topAttackPower = 0,
        attackOptions = [];

    others.sort((a, b) => b.attack - a.attack);
    for (let i = 0; i < others.length; i++) {
        let other = others[i];
        if (i < 5) topAttackPower += this.getAttackPower(other.attack);
        if (other.hp <= myAttackPower + 10) attackOptions.push(other);
    }

    if (attackOptions.length > 0) {
        attackOptions.sort((a, b) => b.worth - a.worth);
        return attack(attackOptions[0].uid);
    }

    if (myTotalHp < (topAttackPower * 3) + 5) return shield();

    if (currentTurn > 50) {
        let topWorth = others.filter(other => (other.hp > (currentTurn / 2) + 100)).sort((a, b) => b.worth - a.worth).slice(0, 3);
        let topHp = others.sort((a, b) => b.hp - a.hp).slice(0, 2);

        for (let topWorthBot of topWorth) {
            for (let topHpBot of topHp) {
                if (topWorthBot.uid === topHpBot.uid) {
                    return stun(topWorthBot.uid);
                }
            }
        }

        if (topWorth.length > 0 && Math.random() * 20 < 19) {
            let target = topWorth[Math.floor(Math.random() * topWorth.length)];
            return stun(target.uid);
        }
    }

    return this.shieldOrUpgrade();
}

```

**Bernard Szumborski** is a mercenary, he has been sent by a group of people to stop the powerful wealthy class.

He makes sure that he is strong enough that no one can kill him. Then looks for wealthiest with lots of defense (HP) and targets them because they are the wealthiest of wealthiest! If the ones with top wealth don't have lots of defense, then just targets one of them randomly each turn.

Although it is not in his contract to kill, he gets tempted when he sees someone very weak and kills them.

# Answer
> 0 votes
## Barbarian Man

As everyone's least favorite superhero, he's a bit desperate. Rather than farm in his free time, he likes to use complex math to choose which villain to repeatedly attack. Once the world is empty of easy-to-kill villains, he retires to a peaceful life of farming. Like his cousin Captain Farmer, he has a special emergency low-health mode.

```
function barbarianMan(me, others, storage) {
    if (!storage.mode) {
        storage.mode = "prep";
        storage.prep = 0;
    }
    if (me.hp + me.shield < 100)
        storage.mode = "lowhp";
    var weak = others.find(el => el.hp < me.levels.attack * 1.25 + Math.max(...others.map(el => el.attack)) * 2.5 + 10 && Math.ceil(el.worth / 2) >= 5);
    if (weak && storage.weak >= 0) {
        storage.weak += 1;
        return attack(weak.uid);
    }
    if (storage.weak < 0)
        storage.weak += 1;
    else if (storage.weak > 3)
        storage.weak = -3;
    else if (!storage.weak)
        storage.weak = 0;
    if (storage.mode == "prep") {
        storage.prep += 1;
        if (storage.prep < 3)
            return upgrade("shield");
        if (storage.prep < 7)
            return shield();
        if (storage.prep < 10)
            return farm();
        if (storage.prep < 11)
            return heal();
        if (storage.prep < 13)
            return farm();
        if (storage.prep < 14)
            return heal();
        if (storage.prep < 16)
            return upgrade("attack");
        storage.mode = "kill";
    } else if (storage.mode == "lowhp") {
        if ((me.hp + me.shield) > 150) {
            if (me.hp >= 95)
                storage.mode = "kill";
            return heal();
        }
        return shield();
    } else if (storage.mode == "kill") {
        if (!storage.badTargs) {
            storage.badTargs = [];
            storage.testHp = [];
        }
        storage.lastHp = null;
        if (me.gold >= cost(me.levels.attack) && me.levels.attack < 5)
            return upgrade("attack");
        if (me.gold >= cost(me.levels.shield))
            return upgrade("shield");
        if (me.gold >= cost(me.levels.farm))
            return upgrade("farm");
        if (storage.gTarg && attack(storage.gTarg)[0])
            return attack(storage.gTarg);
        if (storage.test == "attack1" && attack(storage.tTarg)[0]) {
            storage.test = "attack2";
            storage.testHp[0] = others.find(el => el.uid == storage.tTarg).hp;
            return attack(storage.tTarg);
        }
        if (storage.test == "attack2" && attack(storage.tTarg)[0]) {
            storage.test = "exam";
            storage.testHp[1] = others.find(el => el.uid == storage.tTarg).hp;
            return attack(storage.tTarg);
        }
        if (storage.test == "exam" && attack(storage.tTarg)[0]) {
            if (storage.testHp[1] - storage.testHp[0] > 3) {
                storage.gTarg = storage.tTarg;
                storage.test = null;
            } else {
                storage.badTargs.push(storage.tTarg);
                storage.test = null;
            }
            return heal();
        }
        let targs = [];
        let scores = [];
        for (let o, i = 0; i < others.length; i++) {
            o = others[i];
            if (storage.badTargs.includes(o.uid))
                continue;
            targs.push(o.uid);
            scores.push((-(o.worth ** 2) / 5000 + 4 * (o.worth) / 15) / o.hp);
        }
        if (!targs.length)
            storage.mode = "farm";
        storage.tTarg = targs[scores.indexOf(Math.max(...scores))];
        storage.test = "attack1";
        return heal();
    } else if (storage.mode == "farm") {
        if (me.gold >= cost(me.levels.shield))
            return upgrade("shield");
        if (me.gold >= cost(me.levels.farm))
            return upgrade("farm");
        if (me.hp > 80 && !storage.healMode)
            return farm();
        storage.healMode = true;
        if (me.hp < 97)
            return heal();
        storage.healMode = false;
        return shield();
    }
    return shield();
}

```

# Answer
> 0 votes
# TheHalfHalf

Looks every second move for heal or farm. Every other move he shields or randomly attacks other bots. Decides everything on ~50% of its own HP.

```
function TheHalfHalf(me, others, storage){

    if (turn() == 0) {
        return upgrade("heal");
    }

    if(turn() % 2 == 0) {
        if(me.hp <= 50 - (me.levels.heal + 5)){
            return heal()
        } else {
            if(me.gold >= cost(me.levels.farm)){
                return upgrade("farm")
            } else {
                return farm();
            }
        }
    } else {
        if(me.hp <= 50){
            return shield();
        } else {
            return attack(others[Math.floor(Math.random() * Math.floor(others.length))].uid);
        }
    }
}

```

# Answer
> 0 votes
# TeacherBot

```
function TeacherBot(self, others, storage){
    var maxAtk = others.map(c=>c.attack).reduce((a, b) => Math.max(a, b));
    var maxDmg = maxAtk * 1.25 + 5;
    var myDmg = self.levels.attack * 1.25 + 5;
    var potential_victim = others.find( bot => bot.hp <= Math.max(maxDmg, myDmg) );
    if (potential_victim) {
        return attack(potential_victim.uid);
    }
    let turnsLeft=999-turn()
    if(self.shield<50 && turn() > 5){
        return shield()
    }else if(self.gold>=cost(self.levels.attack)&&turnsLeft>20){
        return upgrade("attack")
    }else if(self.gold>=cost(self.levels.shield)&&self.levels.shield<=4&&turnsLeft>50){
        return upgrade("shield")
    }else{
        return attack(others.sort((a,b)=>b.attack-a.attack)[0].uid)
    }
}

```

The teacher is not above getting in on a kill (who doesn't like money? BullyBot, that's who), but its primary focus for attacks is the bot with the highest attack value, aiming to punish them for attacking other bots.

Performs at about rank #8 (~12k average gold).

---
Tags: king-of-the-hill, javascript
---