title: Survival Game - Create Your Wolf

text:
# Question
Title: Survival Game - Create Your Wolf
# The Board

The **Board** is a two dimensional array of cells. Cells are populated by **Animals**. Every day, all Animals on the Board simultaneously make one move. If two or more Animals move to the same cell, they fight until one remains. The possible moves and attacks are as follows:

* **Moves** \- { `Move.UP`, `Move.RIGHT`, `Move.DOWN`, `Move.LEFT`, `Move.HOLD` }
* **Attacks** \- { `Attack.ROCK`, `Attack.PAPER`, `Attack.SCISSORS`, `Attack.SUICIDE` }

Animals fight by playing Rock-Paper-Scissors. Standard rules apply but with two modifications. First, you may commit suicide at any time. Second, a tie is broken pseudorandomly. If more than two Animals collide, two are pseudorandomly selected to fight until one remains.

# The Players

Animal behavior and appearance is as follows.

* **Lion**
    + Represented by the character `L`. Moves `DOWN`, `RIGHT`, then repeats. Pseudorandomly attacks with `PAPER` or `SCISSORS`.
* **Bear**
    + Represented by the character `B`. Moves `DOWN` x 4, `RIGHT` x 4, `UP` x 4, `LEFT` x 4, then repeats. Attacks with `PAPER`.
* **Stone**
    + Represented by the character `S`. Moves `HOLD`. Attacks with `ROCK`.
* **Wolf**
    + Only wolves that are submitted as an answer will be included. Represented by 'W'. Moves with any Move. Attacks with any Attack

You will implement the Wolf by filling in the blanks in the following template. All submissions must be in Java and must be contained in a single file. Alternatively, @ProgrammerDan has written a wrapper class that extends the competition to non-java submissions.

```
// Optional code here
public class Wolf extends Animal {
    // Optional code here
    public Wolf() { super('W'); /* Optional code here */ }
    public Attack fight(char opponent) { /* Required code here. Must return an Attack. */ }
    public Move move() { /* Required code here. Must return a Move. */ }
    // Optional code here
}

```

The submission with the highest average number of living wolves after five trials with 1,000 iterations wins. I will update the winner each time a new answer is posted (but not within the first 24 hours).

# Tools

* You are provided with a small map of your immediate surroundings in the following form.
    + `char[][] surroundings` A zero indexed, 3 by 3 matrix of characters that represent nearby animals. Empty tiles are represented by a space character (' '). You are at `surroundings[1][1]`. For example, to your right would be `surroundings[1][2]`, and above you is `surroundings[0][1]`. Your surroundings are updated just before being asked to move, but may be out of date when asked to fight.
* You may persist data between invocations of your Wolf, Move requests, and Attack requests. You may neither read from nor modify files created by another Wolf class.
* You are provided with the size of the map in the following form
    + `int MAP_SIZE`

# Assumptions

* All submission will compete on the same board against all other submissions as well as Lions, Bears, and Stones
* The board is a square with sides of length `sqrt(n+3)*20` where `n` is the number of submissions. All sides wrap, so you can safely move in any direction infinitely.
* Simulation begins at ~25% board capacity with 100 of each Animal pseudorandomly distributed across the board.
* If an Animal throws an exception when asked to move, that Animal will `HOLD`
* If an Animal throws an exception when asked to fight, that Animal will `SUICIDE`
* If an Animal has no letter when the controller checks, that Animal will immediately die

# Getting Started and Testing Instructions

The tools you need to test your submission can be found here. The following files should be available at that link.

* **ExampleRun.gif** \- A 5-10 second gif of the program running.
* **Scoreboard** \- The latest results of the competition.
* **Wild.jar** \- An executable that you can run to watch the premade Animals run around.
* **Wild.zip** \- The NetBeans project that houses the controller program with a few premade Animals added. Use this to develop your submission.
* **WildPopulated.zip** \- Same as above, but with and about 40 submissions added for you to test against. The GUI has also been removed because of performance issues. The results will simply appear a few moments after you run. The non-Java submissions are commented out because they require extra downloads and effort. Use this to test your submission against the field.
* **Wolf.txt** \- A naive implementation of the Wolf class in Java. You may use and expand that implementation without crediting me.

To test your class:

* Download Wild.zip
* Rename your Wolf.java and Wolf class to something unique
* Add your UniquelyNamedWolf.java file to Wild\src\animals\
* In the Wild class, add your class to `classes` array, like this.
    + `Class[] classes = { UniquelyNamedWolf.class, Bear.class, Lion.class, Stone.class, Wolf.class };`
* Rebuild and run

I also included another project containing all of the submissions, for testing purposes. I creatively named it "WildPopulated". The three or four non-Java wolves were commented out, because getting them to run requires a lot of extra work and downloads. The one I posted should run with *zero* extra work. The GUI was also commented out for the sake of speed.

# Scoreboard April 22, 2014

The Scoreboard has been moved to Google Drive. View it here. It will be updated on a casual basis (i.e., when I get to it) as new submissions come in.

# Side Challenge - NoHOLD

Removed because no (as in zero) participation. It wasn't part of the original challenge anyway.

# Answer
> 48 votes
# HerjanWolf

Updated 10-4-2014 at 15:00

Averages of 100 rounds, 1000 iterations:

Standard mobs:

```
class animals.Bear - 2.2600002
class animals.Lion - 41.21
class animals.Stone - 20.159998
class animals.HerjanWolf - 99.99 <-- kind of flawless

```

20+ Species (Keep in mind, don't trust these scores since we keep calculating avgs until our wolves score best!)

```
class animals.Bear - 0.1
class animals.Lion - 0.0
class animals.Stone - 1.5
class animals.AlphaWolf - 75.5
class animals.HerjanWolf - 86.4 <-- #1
class animals.GatheringWolf - 39.5
class animals.OmegaWolf - 85.4 <-- #2
class animals.ShadowWolf - 71.1
class animals.MOSHPITFRENZYWolf - 8.8
class animals.WolfWithoutFear - 11.5
class animals.MimicWolf - 0.5
class animals.LazyWolf - 52.8
class animals.Sheep - 38.3
class animals.HonorWolf - 80.7
class animals.CamperWolf - 52.8
class animals.GamblerWolf - 14.7
class animals.WolfRunningWithScissors - 0.0
class animals.LionHunterWolf - 27.6
class animals.StoneEatingWolf - 70.8
class animals.Wion - 0.1
class animals.ProAlpha - 79.3
class animals.HybridWolf - 83.2

```

My Wolf:

```
package animals;

public class HerjanWolf extends Animal {

    private boolean lionTopLeft = false, lionTopLeftReady = false;
    private boolean lionRight = false, lionRightReady = false;
    private boolean lionBot = false, lionBotReady = false;
    private boolean lionDanger = false, careful = true, firstmove = true;
    private final int hold = 0, down = 1, right = 2, left = 3, up = 4;

    public HerjanWolf() {
        super('W');
    }

    public Attack fight(char c){
        switch (c) {
            case 'B':
                return Attack.SCISSORS;
            case 'L':
                return Attack.SCISSORS;
            case 'S':
                return Attack.PAPER;
            default:
                int rand = (int) (Math.random()*3);
                if(rand < 1)
                    return Attack.PAPER;
                else if(rand < 2)
                    return Attack.SCISSORS;
                else
                    return Attack.ROCK;
        }

    }
    public Move move() { //surroundings[y][x]

        checkLions();

        if(firstmove){
            if(surroundings[2][0] == 'L')
                lionBotReady = true;
            if(surroundings[0][2] == 'L')
                lionRightReady = true;
            firstmove = false;
        }

        int[] dang = new int[4]; // 0 is left side, 1 is top side, 2 is right side, 3 is down side

        for(int y = 0; y < 3; y++){
            for(int x = 0; x < 3; x++){
                if(surroundings[y][x] == 'W'){
                    if(y == 0){
                        dang[1]++;
                        if(x == 1)
                            dang[1]+=2;
                    }if(y == 2){
                        dang[3]++;
                        if(x == 1)
                            dang[3]+=2;
                    }if(x == 0){
                        dang[0]++;
                        if(y == 1)
                            dang[0]+=2;
                    }if(x == 2){
                        dang[2]++;
                        if(y == 1)
                            dang[2]+=2;
                    }
                }
            }
        }

        int maxIndex = 0, minIndex = 0, minIndex2 = 0;
        for(int i = 1; i < dang.length; i++){
            if(dang[i] > dang[maxIndex])
                maxIndex = i;
            if(dang[i] <= dang[minIndex]){
                minIndex2 = minIndex;
                minIndex = i;
            }
        }

        if(lionDanger || surroundings[1][0] == 'L' && lionTopLeftReady || surroundings[0][1] == 'L' && lionTopLeftReady || dang[maxIndex] >= 3){

            switch(minIndex){
            case 0:
                if (isSafe(1, 0)){
                    newMove(left);
                    return Move.LEFT;
                }
            case 1:
                if (isSafe(0, 1)){
                    newMove(up);
                    return Move.UP;
                }
            case 2:
                if(isSafe(1,2)){
                    newMove(right);
                    return Move.RIGHT;
                }

            case 3:
                if (isSafe(2, 1)){
                    newMove(down);
                    return Move.DOWN;
                }
            }

            switch(minIndex2){
            case 0:
                if (isSafe(1, 0)){
                    newMove(left);
                    return Move.LEFT;
                }
            case 1:
                if (isSafe(0, 1)){
                    newMove(up);
                    return Move.UP;
                }
            case 2:
                if(isSafe(1,2)){
                    newMove(right);
                    return Move.RIGHT;
                }

            case 3:
                if (isSafe(2, 1)){
                    newMove(down);
                    return Move.DOWN;
                }
            }

            if(dang[maxIndex]<3){ //if that was not the reason its really obligated (because of lions)
                if (isSafe(2, 1)){
                    newMove(down);
                    return Move.DOWN;
                }else if(isSafe(1,2)){
                    newMove(right);
                    return Move.RIGHT;
                }else if (isSafe(0, 1)){
                    newMove(up);
                    return Move.UP;
                }else{
                    newMove(left);
                    return Move.LEFT;
                }
            }
        }

        return Move.HOLD;
    }

    boolean isSafe(int y, int x){
        if(y <= 1){
            if(x <= 1){
                if(surroundings[y][x] != 'W' && !lionTopLeft)
                    return true;
            }else if(surroundings[1][2] != 'W' && !lionRightReady)
                    return true;
        }else if(surroundings[2][1] != 'W' && !lionBotReady)
            return true;

        return false;
    }

    public void checkLions(){
        int y = 0, x = 0;

        if(lionTopLeft)
            lionTopLeftReady = true;
        else
            lionTopLeftReady = false;

        if(surroundings[y][x] == 'L')
            lionTopLeft = true;
        else
            lionTopLeft = false;

        if(lionRight)
            lionRightReady = true;
        else
            lionRightReady = false;

        if(surroundings[y][x+1] == 'L') // && !lionTopLeftReady
            lionRight = true;
        else
            lionRight = false;

        if(lionBot)
            lionBotReady = true;
        else
            lionBotReady = false;

        if(surroundings[y+1][x] == 'L' && !lionTopLeftReady)
            lionBot = true;
        else
            lionBot = false;

        if(careful){
            if(surroundings[y+1][x] == 'L'){
                lionDanger = true;
            }else if(surroundings[y][x+1] == 'L'){
                lionDanger = true;
            }

            careful = false;
        }
    }

    public void newMove(int move){
        lionTopLeft = false;
        lionRight = false;
        lionBot = false;

        lionTopLeftReady = false;
        lionRightReady = false;
        lionBotReady = false;

        lionDanger = false;

        if(move == down){
            if(surroundings[1][0] == 'L')
                lionTopLeft = true;
            if(surroundings[2][0] == 'L')
                lionBot = true;

        }else if(move == right){
            if(surroundings[0][1] == 'L')
                lionTopLeft = true;
            if(surroundings[0][2] == 'L')
                lionRight = true;

        }else
            careful = true;
    }
}

```

# Answer
> 164 votes
## EmoWolf

EmoWolf hates Java, and would rather kill itself than participate. EmoWolf has starved itself, but still weighs 177 bytes.

```
package animals;public class EmoWolf extends Animal{public EmoWolf(){super('W');}public Attack fight(char opponent){return Attack.SUICIDE;}public Move move(){return Move.HOLD;}}

```

# Answer
> 53 votes
## LazyWolf

Aptly named, this guy does the bare minimum to survive. The only non-wolf threat is a lion, so he will move if one of those is about to step on him. Other than that, he just sleeps.

There's not much you can do against wolves that will be better than 50/50, so he just doesn't do anything. If a wolf attacks him, he chooses an attack in an evenly distributed manner.

That's it. I expect it to do pretty well, despite the simplicity.

```
package animals;
public class LazyWolf extends Animal{
    static int last = 0;
    static final Attack[] attacks = Attack.values();

    public LazyWolf() {super('W');}

    @Override
    public Attack fight(char other) {
        switch(other){
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S':
            return Attack.ROCK; // faker!
        default:
            return attacks[last++%3];
        }
    }

    @Override
    public Move move() {
        if(surroundings[0][1] == 'L')
            return Move.LEFT;
        if(surroundings[1][0] == 'L')
            return Move.UP;
        return Move.HOLD;
    }

}

```

**Update:**

CamoWolf was beating me handily. Since my wolf is so lazy, he'll *never* normally run into a real stone. Therefore, if a stone attacks, it's obviously a fake and needs a rock thrown in its face.

# Answer
> 52 votes
# Wrapper for Non-Java Submissions

**NOTE** MAP\_SIZE support has been added. If you care, please update your submission accordingly.

This is community wiki entry for a wrapper, usable by those who want to play but don't like/don't know Java. Please use it, have fun, and I'm happy to help you get things set up.

It's pretty late here as I'm finishing up, so other Java coders, please look this over and suggest improvements. If you can, do so via my github repository by filing an issue or submitting a patch. Thanks!

This entire is being distributed with the UNLICENSE, please follow/fork it from its github repository. Submit patches there if you find issues and I'll update this post.

# Current Examples of Wrapper in Use

### plannapus: WolfCollectiveMemory in R

### user3188175: SmartWolf in `C#`

### toothbrush: Toothbrush in ECMAScript

# How to use

What follows are instructions on the protocol for-inter process communication via PIPES I have defined for remote Wolves. Note I've skipped MAP\_SIZE as this doesn't appear to exist, in spite of its presence in OP's problem statement. If it does appear, I'll update this post.

**IMPORTANT NOTES**:

* Only a single invocation of your external process will be made (so wrap your processing logic in an infinite loop. This also lets you keep any processing in-memory, instead of using disk)
* All communication is to this single external process via STDIN and STDOUT
* You must explicitly flush all output sent to STDOUT, and make sure it is newline-terminated

# Specification

Remote scripts are supported by a simple protocol via STDIN and STDOUT hooks, and is split into initialization, Move, and Attack. In each case communication with your process will be via STDIN, and a reply is necessary from STDOUT. If a reply is not received in 1 second, your process will be assumed to be dead and an exception will be thrown. All characters will be encoded in UTF-8, for consistency. Every input will terminate with a newline character, and your process should terminate every output reply with a newline as well. **WARNING** Be sure to flush your output buffer after every write, to ensure the Java wrapper sees your output. Failure to flush may cause your remote Wolf to fail.

Note that only a single process will be created, all Wolves must be managed within that one process. Read on for how this spec will help.

### Initialization

**STDIN:** `S<id><mapsize>`\n

**STDOUT:** `K<id>`\n

**`<id>`:** `00` or `01` or ... or `99`

Explanation:

The character `S` will be sent followed by two numeric characters `00`, `01`, ..., `99` indicating which of the 100 wolves is being initialized. In all future communication with that specific wolf, the same `<id>` will be used.

Following the ID, a variable length sequence of numeric characters will be be sent. This is the size of the map. You'll know the sequence of numeric characters is over when you reach the newline (`\n`).

To ensure your process is alive, you must reply with the character `K` followed by the same `<id>` you received. Any other reply will result in an exception, killing your wolves.

### Movement

**STDIN:** `M<id><C0><C1>...<C7><C8>`\n

**STDOUT:** `<mv><id>`\n

**`<Cn>`:** `W` or  or `B` or `S` or `L`

**`W`:** Wolf

**:** Empty Space

**`B`:** Bear

**`S`:** Stone

**`L`:** Lion

**`<mv>`:** `H` or `U` or `L` or `R` or `D`

**`H`:** Move.HOLD

**`U`:** Move.UP

**`L`:** Move.LEFT

**`R`:** Move.RIGHT

**`D`:** Move.DOWN

Explanation:

The character `M` will be sent followed by the two character `<id>` to indicate which Wolf needs to choose a move. Following that, 9 characters will be sent representing that Wolf's surroundings, in row order (top row, middle row, bottom row from leftmost to rightmost).

Reply with one of the valid movement characters `<mv>`, followed by the Wolf's two digit `<id>` for confirmation.

### Attack

**STDIN:** `A<id><C>`\n

**STDOUT:** `<atk><id>`\n

**`<C>`:** `W` or `B` or `S` or `L`

**`<atk>`:** `R` or `P` or `S` or `D`

**`R`:** Attack.ROCK

**`P`:** Attack.PAPER

**`S`:** Attack.SCISSORS

**`D`:** Attack.SUICIDE

Explanation:

The character `A` will be sent followed by the two character `<id>` to indicate which Wolf is participating in an attack. This is followed by a single character `<C>` indicating which type of thing is attacking, either a `W`olf, `B`ear, `S`tone, or `L`ion.

Reply with one of the `<atk>` characters listed above, indicating what your response to the attack is, following by the two digit `<id>` for confirmation.

And that's it. There's no more to it. If you lose an attack, that `<id>` will never be sent to your process again, that's how you will know your Wolf has died -- if a complete Movement round has passed without that `<id>` ever being sent.

# Conclusion

Note that any exceptions will kill all the Wolves of your remote type, as only a single "Process" is constructed of your remote wolf, for all wolves of your type that get created.

In this repository you'll find the `Wolf.java` file. Search and replace the following strings to set up your bot:

* Replace `<invocation>` with the command line argument that will properly execute your process.
* Replace `<custom-name>` with a unique name for your Wolf.
* For an example look at the repository, where I have `WolfRandomPython.java` that invokes my example remote, the `PythonWolf.py` (a Python 3+ Wolf).
* Rename the file to be `Wolf<custom-name>.java`, where `<custom-name>` is replaced with the name you chose above.

To test your Wolf, compile the Java program (`javac Wolf<custom-name>.java`), and follow Rusher's instructions to include it in the simulation program.

**Important:** Be sure to provide *clear*, *concise* instructions on how to compile/execute your actual Wolf, which follows the scheme I've outlined above.

Good luck, and may nature be ever in your favor.

# The Wrapper Code

Remember, you MUST do the searches and replaces outlined about for this to work. If your invocation is particularly hairy, please contact me for assistance.

Note there is a `main` method in this wrapper, to allow rudimentary "pass/fail" testing on your local box. To do so, download the Animal.java class from the project, and remove the `package animals;` line from both files. Replace the MAP\_SIZE line in Animal.java with some constant (like 100). Compile them using `javac Wolf<custom-name>.java` an execute via `java Wolf<custom-name>`.

```
package animals;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Remote Wolf<custom-name> wrapper class.
 */
public class Wolf<custom-name> extends Animal {
    /**
     * Simple test script that sends some typical commands to the
     * remote process.
     */
    public static void main(String[]args){
        Wolf<custom-name>[] wolves = new Wolf<custom-name>[100];
        for(int i=0; i<10; i++) {
            wolves[i] = new Wolf<custom-name>();
        }
        char map[][] = new char[3][3];
        for (int i=0;i<9;i++)
            map[i/3][i%3]=' ';
        map[1][1] = 'W';
        for(int i=0; i<10; i++) {
            wolves[i].surroundings=map;
            System.out.println(wolves[i].move());
        }
        for(int i=0; i<10; i++) {
            System.out.println(wolves[i].fight('S'));
            System.out.println(wolves[i].fight('B'));
            System.out.println(wolves[i].fight('L'));
            System.out.println(wolves[i].fight('W'));
        }
        wolfProcess.endProcess();
    }
    private static WolfProcess wolfProcess = null;

    private static Wolf<custom-name>[] wolves = new Wolf<custom-name>[100];
    private static int nWolves = 0;

    private boolean isDead;
    private int id;

    /**
     * Sets up a remote process wolf. Note the static components. Only
     * a single process is generated for all Wolves of this type, new
     * wolves are "initialized" within the remote process, which is
     * maintained alongside the primary process.
     * Note this implementation makes heavy use of threads.
     */
    public Wolf<custom-name>() {
        super('W');
        if (Wolf<custom-name>.wolfProcess == null) {
            Wolf<custom-name>.wolfProcess = new WolfProcess();
            Wolf<custom-name>.wolfProcess.start();
        }

        if (Wolf<custom-name>.wolfProcess.initWolf(Wolf<custom-name>.nWolves, MAP_SIZE)) {
            this.id = Wolf<custom-name>.nWolves;
            this.isDead = false;
            Wolf<custom-name>.wolves[id] = this;
        } else {
            Wolf<custom-name>.wolfProcess.endProcess();
            this.isDead = true;
        }
        Wolf<custom-name>.nWolves++;
    }

    /**
     * If the wolf is dead, or all the wolves of this type are dead, SUICIDE.
     * Otherwise, communicate an attack to the remote process and return
     * its attack choice.
     */
    @Override
    public Attack fight(char opponent) {
        if (!Wolf<custom-name>.wolfProcess.getRunning() || isDead) {
            return Attack.SUICIDE;
        }
        try {
            Attack atk = Wolf<custom-name>.wolfProcess.fight(id, opponent);

            if (atk == Attack.SUICIDE) {
                this.isDead = true;
            }

            return atk;
        } catch (Exception e) {
            System.out.printf("Something terrible happened, this wolf has died: %s", e.getMessage());
            isDead = true;
            return Attack.SUICIDE;
        }
    }

    /**
     * If the wolf is dead, or all the wolves of this type are dead, HOLD.
     * Otherwise, get a move from the remote process and return that.
     */
    @Override
    public Move move() {
        if (!Wolf<custom-name>.wolfProcess.getRunning() || isDead) {
            return Move.HOLD;
        }
        try {
            Move mv = Wolf<custom-name>.wolfProcess.move(id, surroundings);

            return mv;
        } catch (Exception e) {
            System.out.printf("Something terrible happened, this wolf has died: %s", e.getMessage());
            isDead = true;
            return Move.HOLD;
        }
    }

    /**
     * The shared static process manager, that synchronizes all communication
     * with the remote process.
     */
    static class WolfProcess extends Thread {
        private Process process;
        private BufferedReader reader;
        private PrintWriter writer;
        private ExecutorService executor;
        private boolean running;

        public boolean getRunning() {
            return running;
        }

        public WolfProcess() {
            process = null;
            reader = null;
            writer = null;
            running = true;
            executor = Executors.newFixedThreadPool(1);
        }

        public void endProcess() {
            running = false;
        }

        /**
         * WolfProcess thread body. Keeps the remote connection alive.
         */
        public void run() {
            try {
                System.out.println("Starting Wolf<custom-name> remote process");
                ProcessBuilder pb = new ProcessBuilder("<invocation>".split(" "));
                pb.redirectErrorStream(true);
                process = pb.start();
                System.out.println("Wolf<custom-name> process begun");
                // STDOUT of the process.
                reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
                System.out.println("Wolf<custom-name> reader stream grabbed");
                // STDIN of the process.
                writer = new PrintWriter(new OutputStreamWriter(process.getOutputStream(), "UTF-8"));
                System.out.println("Wolf<custom-name> writer stream grabbed");
                while(running){
                    this.sleep(0);
                }
                reader.close();
                writer.close();
                process.destroy(); // kill it with fire.
                executor.shutdownNow();
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("Wolf<custom-name> ended catastrophically.");
            }
        }

        /**
         * Helper that invokes a read with a timeout
         */
        private String getReply(long timeout) throws TimeoutException, ExecutionException, InterruptedException{
            Callable<String> readTask = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return reader.readLine();
                }
            };

            Future<String> future = executor.submit(readTask);
            return future.get(timeout, TimeUnit.MILLISECONDS);
        }

        /**
         * Sends an initialization command to the remote process
         */
        public synchronized boolean initWolf(int wolf, int map_sz) {
            while(writer == null){
                try {
                this.sleep(0);
                }catch(Exception e){}
            }
            boolean success = false;
            try{
                writer.printf("S%02d%d\n", wolf, map_sz);
                writer.flush();
                String reply = getReply(5000l);
                if (reply != null && reply.length() >= 3 && reply.charAt(0) == 'K') {
                    int id = Integer.valueOf(reply.substring(1));
                    if (wolf == id) {
                        success = true;
                    }
                }
                if (reply == null) {
                    System.out.println("did not get reply");
                }
            } catch (TimeoutException ie) {
                endProcess();
                System.out.printf("Wolf<custom-name> %d failed to initialize, timeout\n", wolf);
            } catch (Exception e) {
                endProcess();
                System.out.printf("Wolf<custom-name> %d failed to initialize, %s\n", wolf, e.getMessage());
            }
            return success;
        }

        /**
         * Send an ATTACK command to the remote process.
         */
        public synchronized Attack fight(int wolf, char opponent) {
            Attack atk = Attack.SUICIDE;
            try{
                writer.printf("A%02d%c\n", wolf, opponent);
                writer.flush();
                String reply = getReply(1000l);
                if (reply.length() >= 3) {
                    int id = Integer.valueOf(reply.substring(1));
                    if (wolf == id) {
                        switch(reply.charAt(0)) {
                            case 'R':
                                atk = Attack.ROCK;
                                break;
                            case 'P':
                                atk = Attack.PAPER;
                                break;
                            case 'S':
                                atk = Attack.SCISSORS;
                                break;
                            case 'D':
                                atk = Attack.SUICIDE;
                                break;
                        }
                    }
                }
            } catch (TimeoutException ie) {
                endProcess();
                System.out.printf("Wolf<custom-name> %d failed to attack, timeout\n", wolf);
            } catch (Exception e) {
                endProcess();
                System.out.printf("Wolf<custom-name> %d failed to attack, %s\n", wolf, e.getMessage());
            }
            return atk;
        }

        /**
         * Send a MOVE command to the remote process.
         */
        public synchronized Move move(int wolf, char[][] map) {
            Move move = Move.HOLD;
            try{
                writer.printf("M%02d", wolf);
                for (int row=0; row<map.length; row++) {
                    for (int col=0; col<map[row].length; col++) {
                        writer.printf("%c", map[row][col]);
                    }
                }
                writer.print("\n");
                writer.flush();
                String reply = getReply(1000l);
                if (reply.length() >= 3) {
                    int id = Integer.valueOf(reply.substring(1));
                    if (wolf == id) {
                        switch(reply.charAt(0)) {
                            case 'H':
                                move = Move.HOLD;
                                break;
                            case 'U':
                                move = Move.UP;
                                break;
                            case 'L':
                                move = Move.LEFT;
                                break;
                            case 'R':
                                move = Move.RIGHT;
                                break;
                            case 'D':
                                move = Move.DOWN;
                                break;
                        }
                    }
                }
            } catch (TimeoutException ie) {
                endProcess();
                System.out.printf("Wolf<custom-name> %d failed to move, timeout\n", wolf);
            } catch (Exception e) {
                endProcess();
                System.out.printf("Wolf<custom-name> %d failed to move, %s\n", wolf, e.getMessage());
            }
            return move;
        }
    }
}

```

# Answer
> 46 votes
# CamoWolf

Abusing the required code format.

```
// Optional code here
public class Wolf extends Animal {
    // Optional code here
    public Wolf() { super('W'); // Optional code here }
    public Attack fight(char opponent) { // Required code here. Must return an Attack. }
    public Move move() { // Required code here. Must return a Move. }
    // Optional code here
}

```

So, my wolf is really smart, and he camouflages as a stone instead! Blending in with the environment is always a good survival tactic!

```
public class Wolf extends Animal {
    private Move lastMove;
    public Wolf() { super('S'); lastMove = Move.RIGHT; } /*
    public Wolf() { super('W'); }
    public Attack fight(char opponent) { */ public Attack fight(char opponent) {
        switch(opponent) {
        case 'B': return Attack.SCISSORS;
        case 'S': return Attack.PAPER;
        case 'W': return Attack.SCISSORS; // Here's an explanation why:
                                          // the wolves will see me and think I'm a rock.
                                          // Therefore, they'll attack with paper.
                                          // So, I'll use scissors instead!
        case 'L': return Attack.SCISSORS;
        }
    }
    public Move move() {
        // First we run away from any lions that we see, since they are the only threat
        if (surroundings[0][1] == 'L') {
            if (isSafe(surroundings[2][1])) return lastMove = Move.DOWN;
            else if (isSafe(surroundings[1][0])) return lastMove = Move.LEFT;
            else return lastMove = Move.RIGHT;
        }
        if (surroundings[1][0] == 'L') {
            if (isSafe(surroundings[1][2])) return lastMove = Move.RIGHT;
            else if (isSafe(surroundings[0][1])) return lastMove = Move.UP;
            else return lastMove = Move.DOWN;
        }

        // If there's no (threatening) lions in sight, be lazy.
        return lastMove = Move.HOLD;
    }
    private boolean isSafe(char c) { return (c != 'L' && c != 'W') }
}

```

**Update**: Added new `isSafe` check to also be safe from LazyWolf! Ha!
**Update 2**: Supposedly, being lazy is also a good survival tactic, so that's what mine does now. Doesn't move unless threatened by a lion. `lastMove` isn't needed anymore, but I kept it anyway just in case I change the code again.

# Answer
> 39 votes
## GatheringWolf

My *wolves* live in a group. They gather, if the lions let them. They're not so good at surviving, though.

**Update:** If a lion force them away, they now try to regather!

```
package animals;
import java.util.*;
public class GatheringWolf extends Animal {
    private static int iteration;
    private static Move preferredMove;
    private int localIteration;
    private int loneliness;
    private boolean dangerFlag;
    private Move lastMove;
    public GatheringWolf() {
        super('W');
    }
    @Override
    public Attack fight(char other) {
        switch (other) {
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S':
            return Attack.PAPER;
        default:
            return Attack.values()[(int) (Math.random() * 3)];
        }
    }
    @Override
    public Move move() {
        if (localIteration == iteration) {
            localIteration++;
            iteration++;
            preferredMove = Math.random() < 0.5 ? Move.DOWN : Move.RIGHT;
        } else
            localIteration = iteration;
        EnumSet<Move> moves = EnumSet.allOf(Move.class);
        if (surroundings[0][1] == 'W')
            moves.remove(Move.UP);
        if (surroundings[1][0] == 'W')
            moves.remove(Move.LEFT);
        if (surroundings[2][1] == 'W')
            moves.remove(Move.DOWN);
        if (surroundings[1][2] == 'W')
            moves.remove(Move.RIGHT);
        if (surroundings[0][0] == 'L') {
            moves.remove(Move.UP);
            moves.remove(Move.LEFT);
        }
        if (surroundings[0][1] == 'L')
            moves.remove(Move.UP);
        if (surroundings[1][0] == 'L')
            moves.remove(Move.LEFT);
        if (surroundings[0][2] == 'L')
            moves.remove(Move.RIGHT);
        if (surroundings[2][0] == 'L')
            moves.remove(Move.DOWN);
        if (surroundings[0][1] == 'L' || surroundings[1][0] == 'L')
            if (moves.size() > 1) {
                moves.remove(Move.HOLD);
                dangerFlag = true;
            }
        int wolfNear = -1;
        for (char[] a : surroundings)
            for (char c : a)
                if (c == 'W')
                    wolfNear++;
        boolean enoughWolfNear = wolfNear >= (Math.random() < 0.9 ? 1 : 2);
        if (moves.contains(Move.HOLD) && enoughWolfNear) {
            loneliness = 0;
            dangerFlag = false;
            return lastMove = Move.HOLD;
        } else
            loneliness++;
        if (loneliness > 10) {
            EnumSet<Move> preferred = EnumSet.copyOf(moves);
            preferred.retainAll(EnumSet.of(preferredMove, Move.HOLD));
            if (!preferred.isEmpty())
                moves = preferred;
        }
        if (loneliness == 2 && dangerFlag) {
            Move reverted = Move.values()[lastMove.ordinal() ^ 0b10];
            dangerFlag = false;
            if (moves.contains(reverted))
                return lastMove = reverted;
        }
        if (moves.contains(Move.HOLD))
            dangerFlag = false;
        if (moves.contains(preferredMove))
            moves.remove(preferredMove == Move.DOWN ? Move.RIGHT : Move.DOWN);
        int n = (int) (Math.random() * moves.size());
        Iterator<Move> ite = moves.iterator();
        while (n-- > 0)
            ite.next();
        return lastMove = ite.next();
    }
}

```

# Answer
> 32 votes
# The Sheep in Wolf's Clothing

Runs away.

It prioritizes running away from Wolves the most, since they're going to be the most dangerous. Next are Lions, since they're nondeterministic. Bears and Stones are both not at all a problem, but we still run away from them if we have nothing better to do because a Wolf killing a Bear or a Stone is, at that moment in time, not a Wolf killing a Sheep.

I haven't yet tested it against LazyWolf, but I have it on good authority that it kicks EmoWolf's ass. ;)

(Please forgive me if this code is terrible, I've haven't ever touched Java for much more than a Hello World program before.)

```
package animals;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class Sheep extends Animal {
    public Sheep() { super('W'); }

    private static final Map<Character, Integer> AnimalWeights;
    static{
        AnimalWeights = new HashMap<>();
        AnimalWeights.put('W', -3);
        AnimalWeights.put('S', -1);
        AnimalWeights.put(' ', 0);
        AnimalWeights.put('H', 1);
        AnimalWeights.put('L', -2);
        AnimalWeights.put('B', -1);
    }

    @Override
    public Attack fight(char c) {
        switch (c) {
            case 'B':
                return Attack.SCISSORS;
            case 'L':
                return Attack.SCISSORS;
            case 'S':
                return Attack.PAPER;
            default:
                return Attack.PAPER;
        }
    }

    @Override
    public Move move() {

        int xWeight = 0;
        int yWeight = 0;

        // Northwest
        xWeight += AnimalWeights.get(surroundings[0][0]);
        yWeight += AnimalWeights.get(surroundings[0][0]);

        // North
        yWeight += AnimalWeights.get(surroundings[0][1]);

        // Northeast
        xWeight -= AnimalWeights.get(surroundings[0][2]);
        yWeight += AnimalWeights.get(surroundings[0][2]);

        // West
        xWeight += AnimalWeights.get(surroundings[1][0]);

        // East
        xWeight -= AnimalWeights.get(surroundings[1][2]);

        // Southwest
        xWeight += AnimalWeights.get(surroundings[2][0]);
        yWeight -= AnimalWeights.get(surroundings[2][0]);

        // South
        yWeight -= AnimalWeights.get(surroundings[2][1]);

        // Southeast
        xWeight -= AnimalWeights.get(surroundings[2][2]);
        yWeight -= AnimalWeights.get(surroundings[2][2]);

        if (Math.abs(xWeight) < Math.abs(yWeight)) {
            if (yWeight > 0) {
                return Move.UP;
            } else {
                return Move.DOWN;
            }
        } else if (Math.abs(yWeight) < Math.abs(xWeight)) {
            if (xWeight > 0) {
                return Move.RIGHT;
            } else {
                return Move.LEFT;
            }
        }

        // Sit still if no one's around
        return Move.HOLD;
    }
}

```

# Answer
> 27 votes
Not an entry, just want to contribute to the GUI by adding color code for each class =D

### Result

### Wild.java

Change the code around `game.populate(c,100)` with:

```
String[] colors = generateColors(classes.length);
int idx = 0;
for(Class c : classes){
    Animal.setColor(c, colors[idx]);
    idx++;
    game.populate(c, 100);
}
stats.update();

```

with the `generateColors` defined as:

```
private static String[] generateColors(int n){
    String[] result = new String[n];
    double maxR = -1000;
    double minR = 1000;
    double maxG = -1000;
    double minG = 1000;
    double maxB = -1000;
    double minB = 1000;
    double[][] colors = new double[n][3];
    for(int i=0; i<n; i++){
        double cos = Math.cos(i * 2 * Math.PI / classes.length);
        double sin = Math.sin(i * 2 * Math.PI / classes.length);
        double bright = 1;
        colors[i][0] = bright + sin/0.88;
        colors[i][1] = bright - 0.38*cos - 0.58*sin;
        colors[i][2] = bright + cos/0.49;
        maxR = Math.max(maxR, colors[i][0]);
        minR = Math.min(minR, colors[i][0]);
        maxG = Math.max(maxG, colors[i][1]);
        minG = Math.min(minG, colors[i][1]);
        maxB = Math.max(maxB, colors[i][2]);
        minB = Math.min(minB, colors[i][2]);
    }
    double scaleR = 255/(maxR-minR);
    double scaleG = 255/(maxG-minG);
    double scaleB = 255/(maxB-minB);
    for(int i=0; i<n; i++){
        int R = (int)Math.round(scaleR*(colors[i][0]-minR));
        int G = (int)Math.round(scaleG*(colors[i][1]-minG));
        int B = (int)Math.round(scaleB*(colors[i][2]-minB));
        result[i] = "#"+String.format("%02x%02x%02x", R, G, B);
    }
    return result;
}

```

which algorithm is taken from this StackOverflow answer

With the `color` and `setColor` being defined in Animal.java

### Animal.java

```
public static HashMap<Class, String> color = new HashMap<Class, String>();

public static void setColor(Class animalClass, String animalColor){
    color.put(animalClass, animalColor);
}

```

Then update the `toString` methods in Game.java and Statistics.java:

### Game.java

```
public String toString() {
    String s = "<html>";
    for (ArrayList<ArrayList<Animal>> row : board) {
        for (ArrayList<Animal> cell : row) {
            if (cell.isEmpty())
                s += "  ";
            else
                s += "<span style='color:"+ Animal.color.get(cell.get(0).getClass()) +"'>" + cell.get(0).letter + "</span> ";
        }
        s+="<br>";
    }
    return s + "</html>";
}

```

### Statistics.java

```
public String toString() {
    String s = "<html>";
    for (int i = 0; i < classes.length; i++) {
        s += "<span style='color:" + Animal.color.get(classes[i]) + "'>" + classes[i] + "</span> - " + living[i] + "<br>";
    }
    return s + "</html>";
}

```

# Answer
> 24 votes
# AlphaWolf

Time to shine! My other wolf CamperWolf was very thin, now comes AlphaWolf, who is more muscular!

Instead of dodging lions the standard way, it swaps the field with them. It also assigns dangers-values to each surrounding field.

```
package animals;

import java.util.Random;

public class AlphaWolf extends Animal{
    private Boolean lionMoveDown = true;

    public AlphaWolf() {
        super('W');
    }
    @Override
    public Attack fight(char opponent) {
        switch(opponent){
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S':
            return Attack.PAPER;
        default:
            return randomAttack();
        }
    }

    @Override
    public Move move() {
        int[] danger = new int[4];
        final int wolfsDanger = 4;
        lionMoveDown = !lionMoveDown;
        if(surroundings[0][1] == 'L' && lionMoveDown) {
            return Move.UP;
        }
        if(surroundings[1][0] == 'L'&& !lionMoveDown) {
            return Move.LEFT;
        }
        if(surroundings[0][1] == 'W') {
            danger[0] += wolfsDanger;
        }
        if(surroundings[1][2] == 'W') {
            danger[1] += wolfsDanger;
        }
        if(surroundings[2][1] == 'W') {
            danger[2] += wolfsDanger;
        }
        if(surroundings[1][0] == 'W') {
            danger[3] += wolfsDanger;
        }
        if(surroundings[0][0] == 'W') {
            danger[0]++;
            danger[3]++;
        }
        if(surroundings[0][2] == 'W') {
            danger[0]++;
            danger[1]++;
        }
        if(surroundings[2][2] == 'W') {
            danger[1]++;
            danger[2]++;
        }
        if(surroundings[1][2] == 'W') {
            danger[2]++;
            danger[3]++;
        }
        Boolean shouldMove = false;
        Move bestMove = Move.HOLD;
        int leastDanger = 4;
        for(int i = 0; i < 4; i++) {
            if (danger[i] < leastDanger) {
                bestMove = Move.values()[i];
            }
            if(danger[i] > 3) {
                shouldMove = true;
            }
        }
        if(shouldMove) {
            return bestMove;
        } else {
            return Move.HOLD;
        }
    }

    public Attack randomAttack() {
        Random rand = new Random();
        switch (rand.nextInt(3)){
            case 1: return Attack.SCISSORS;
            case 2: return Attack.ROCK;
            default: return Attack.PAPER;
        }
    }

}

```

It is not very beautiful code, but in my tests it worked very well against all java wolves.

# Answer
> 23 votes
## Gambler Wolf

Gambler Wolf likes to take chances so he behaves erratically hoping Lady Luck is on his side! Fortunately for him, she never lets him down! By perpetual strokes of luck, Gambler Wolf clears the field of all non-wolf obstacles with unbelievable few causalities!

```
package animals;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Random;

public class GamblerWolf extends Animal {
    private static int last = 0;

    public GamblerWolf() { super('W'); gamble(); }
    public Attack fight(char opponent) {
        switch (opponent) {
        case 'S': return Attack.ROCK; /* Camo Wolf? */
        case 'B': return Attack.SCISSORS;
        case 'L': return Attack.SCISSORS;
        default:  return attackWolf();
        }
    }
    public Move move() {
        ArrayList<Move> moves = (ArrayList<Move>) Arrays.asList(Move.values());
        Collections.shuffle(moves);
        for(Move move : moves)
          if(isThreatenedBy(move))
            return moveToEvade(move);
        return Move.HOLD;
    }

    /* Remember, Gamblers Don't Gamble */
    @SuppressWarnings("serial")
    private static void gamble() {
        try {
        Field field = Math.class.getDeclaredField("randomNumberGenerator");
        field.setAccessible(true);
        field.set(null, new Random() {
              @Override
              public double nextDouble() {
                return 4; // chosen by fair dice roll
              }           // guaranteed to be random
            });           // proof: http://xkcd.com/221/
        }
        catch (SecurityException        e) {}
        catch (NoSuchFieldException     e) {}
        catch (IllegalArgumentException e) {}
        catch (IllegalAccessException   e) {}
    }

    private static Attack attackWolf() {
        return Attack.values()[last++ % 3];
    }
    private boolean isThreatenedBy(Move move) {
        return isWolf(move)
            || isStone(move);
    }

    private Move moveToEvade(Move move) {
        if(isSafeMove(getOpposite(move)))
            return getOpposite(move);

        ArrayList<Move> moves = (ArrayList<Move>) Arrays.asList(getOrthogonal(move));
        Collections.shuffle(moves);
        for(Move m : moves)
            if(isSafeMove(m))
                return m;
        return Move.HOLD;
    }

    private static Move[] getOrthogonal(Move move) {
        switch(move){
        case UP:
        case DOWN:  return new Move[] { Move.LEFT, Move.RIGHT };
        case LEFT:
        case RIGHT: return new Move[] { Move.UP,   Move.DOWN };
        default:    return null;
        }
    }

    private static Move getOpposite(Move move) {
        switch(move){
        case UP:    return Move.DOWN;
        case DOWN:  return Move.UP;
        case LEFT:  return Move.RIGHT;
        case RIGHT: return Move.LEFT;
        default:    return null;
        }
    }

    private boolean isSafeMove(Move move) {
        return !isWolf(move)
            && !isStone(move)
            && !couldAWolfMoveHere(move);
    }

    private boolean isWolf(Move move) {
        return isX(move,'W');
    }

    private boolean isStone(Move move) {
        return isX(move,'S');
    }

    private boolean isX(Move m, char c) {
        switch (m) {
        case UP:    return surroundings[0][1] == c;
        case LEFT:  return surroundings[1][0] == c;
        case RIGHT: return surroundings[1][2] == c;
        case DOWN:  return surroundings[2][1] == c;
        default:    return false;
        }
    }

    private boolean couldAWolfMoveHere(Move move) {
        switch (move) {
        case UP:    return surroundings[0][2] == 'W' || surroundings[0][0] == 'W';
        case LEFT:  return surroundings[2][0] == 'W' || surroundings[0][0] == 'W';
        case RIGHT: return surroundings[0][2] == 'W' || surroundings[2][2] == 'W';
        case DOWN:  return surroundings[2][0] == 'W' || surroundings[2][2] == 'W';
        default:    return false;
        }
    }
}

```

**Edit: v1.1**

* Now avoids Stones (Camo-Wolves?)
* Increased Randomness!

# Answer
> 23 votes
# DeepWolf

I put way too much time into this... Anyways, this wolf uses "deep" analytics, collecting and using as much environmental data as I could think of for it to use. The analysis operates on a mixture of wolf-specific knowledge, like known locations of lions and wolves and predictions of future locations, and pack hivemind knowledge, like estimated populations, wolf battle history, and danger of colliding with an animal opponent when moving. It's also extra massive, because in addition to having lots of logic, I went overboard on object-oriented design and have lots of special-purpose classes and methods.

I ran 100 iterations of the game for 1000 steps each with many of the popular and best-performing wolves. I purposely left out GamblerWolf because I thought it was a bit cheaty, although it shouldn't affect my wolf, anyways. Here's the average, maximum, and minimum performance data:

```
Averages:
Bear 0.0
Lion 0.0
Stone 3.51
Wolf 1.56
AlphaWolf 77.05
CamperWolf 69.17
DeepWolf 90.48
EmoWolf 39.92
GatheringWolf 52.15
HerjanWolf 86.55
HonorWolf 86.76
HybridWolf 86.78
LazyWolf 71.11
LionHunterWolf 32.45
MimicWolf 0.4
MOSHPITFRENZYWolf 8.95
OmegaWolf 88.67
ProAlpha 83.28
Sheep 54.74
StoneEatingWolf 75.29
WolfWithoutFear 11.9

Maxes:
Bear 0
Lion 0
Stone 9
Wolf 4
AlphaWolf 89
CamperWolf 81
DeepWolf 96
EmoWolf 57
GatheringWolf 65
HerjanWolf 95
HonorWolf 97
HybridWolf 95
LazyWolf 83
LionHunterWolf 41
MimicWolf 3
MOSHPITFRENZYWolf 22
OmegaWolf 95
ProAlpha 91
Sheep 66
StoneEatingWolf 88
WolfWithoutFear 18

Mins:
Bear 0
Lion 0
Stone 0
Wolf 0
AlphaWolf 65
CamperWolf 57
DeepWolf 83
EmoWolf 26
GatheringWolf 37
HerjanWolf 79
HonorWolf 79
HybridWolf 79
LazyWolf 58
LionHunterWolf 20
MimicWolf 0
MOSHPITFRENZYWolf 1
OmegaWolf 81
ProAlpha 70
Sheep 43
StoneEatingWolf 66
WolfWithoutFear 5

```

DeepWolf is in first place with an average of 90.48, although only with a narrow lead of about 2 more than the second place OmegaWolf's 88.67. About 4x the lines of code for only a 2% improvement! HerjanWolf, HonorWolf, and HybridWolf vie for third place, trailing OmegaWolf by about 2 more with very close 86.55, 86.76, and 86.78 averages, respectively.

Without further ado, I'll present the code. It's so massive that there are likely errors and/or potential for improved constants/logic that I haven't been able to see. If you have any feedback, let me know!

Code at this link, because it turns out to blow the post character limit: Ideone

# Answer
> 22 votes
# CamperWolf

The goal is to survive. As many of the other wolves run away from wolves, mine just stays where it is and fights all animals (even rocks, if cheating would be allowed).

```
package animals;

public class CamperWolf extends Animal {
    public CamperWolf() { super('W'); }
    @Override
    public Attack fight(char opponent) {
        switch(opponent){
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S':
            return Attack.ROCK;
        default:
            return Attack.values()[(int) (Math.random() * 3)];
        }
    }
    @Override
    public Move move() { return Move.HOLD; }
}

```

I expect it to perform very good, as many other wolves run away from wolves and this type of wolve can only die against other wolves.

# Answer
> 21 votes
## WolfRunningWithScissors

Nobody told WolfRunningWithScissors not to run with scissors. Or maybe they did but he does it anyway.

If he runs into an enemy he'll either win with scissors, lose with scissors, tie with scissors, or poke his eye out (suicide).

```
package animals;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class WolfRunningWithScissors extends Animal{

    public WolfRunningWithScissors() {
        super('W');
    }

    @Override
    public Attack fight(char c) {
        List<Attack> att = new ArrayList<>();
        att.add(Attack.SCISSORS);
        att.add(Attack.SUICIDE);
        Collections.shuffle(att);
        return att.get(0);
    }

    @Override
    public Move move() {
        List<Move> m = new ArrayList<>();
        m.add(Move.UP);
        m.add(Move.DOWN);
        m.add(Move.LEFT);
        m.add(Move.RIGHT);
        Collections.shuffle(m);
        return m.get(0);
    }

}

```

Just wanted to make a submission for fun. I've never used Java before and haven't tested this, but it should work. My random attack and moving code is based on `getRandomAttack()` from StoneEatingWolf.

# Answer
> 15 votes
Is it a boy? Is it a wolf? No, it's the

# BoyWhoCriedWolf.java

People are using reflection all over the place, so I figured, why not take it a step further?
I present you: the wolf that cannot lose.

```
package animals;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.instrument.ClassDefinition;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.jar.Attributes;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import javax.xml.bind.DatatypeConverter;

public class BoyWhoCriedWolf extends Animal {

    private static boolean ranAgent;

    public static void installAgent() {
        try {
            ranAgent = true;
            String javaExec = new File(System.getProperty("java.home"), "bin").getAbsolutePath() + File.separator + "java";
            Process proc = new ProcessBuilder(javaExec, "-cp", System.getProperty("java.class.path"),
                    "animals.BoyWhoCriedWolf", ManagementFactory.getRuntimeMXBean().getName().split("@")[0])
                    .inheritIO().start();
            proc.waitFor();
        } catch (InterruptedException | IOException e) {
            e.printStackTrace();
        }
    }

    public BoyWhoCriedWolf() {
        super('W');
        if (!ranAgent) {
            installAgent();
        }
    }

    @Override
    public Attack fight(char c) {
        return Attack.PAPER; // I like paper, it's my rubber duck.
    }

    @Override
    public Move move() {
        return Move.HOLD; // I'm terribly lazy.
    }

    public static void main(String[] args) {
        try {
            File temp = File.createTempFile("agent-", ".jar");
            temp.deleteOnExit();
            Manifest manifest = new Manifest();
            manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
            manifest.getMainAttributes().put(new Attributes.Name("Agent-Class"), "animals.BoyWhoCriedWolf");
            manifest.getMainAttributes().put(new Attributes.Name("Can-Redefine-Classes"), "true");
            JarOutputStream jos = new JarOutputStream(new FileOutputStream(temp), manifest);
            jos.close();

            // Add tools.jar
            Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
            addURL.setAccessible(true);
            addURL.invoke(ClassLoader.getSystemClassLoader(), new URL("file:" + System.getProperty("java.home") + "/../lib/tools.jar"));

            Class<?> virtualMachineClass = Class.forName("com.sun.tools.attach.VirtualMachine");
            Object vm = virtualMachineClass.getDeclaredMethod("attach", String.class).invoke(null, args[0]);
            virtualMachineClass.getDeclaredMethod("loadAgent", String.class).invoke(vm, temp.getAbsolutePath());
            virtualMachineClass.getDeclaredMethod("detach").invoke(vm);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void agentmain(String args, Instrumentation instr) throws ClassNotFoundException, UnmodifiableClassException {
        instr.redefineClasses(new ClassDefinition(wild.Game.class, DatatypeConverter.parseBase64Binary(base64Game)));
    }

    private static final String base64Game =
              "yv66vgAAADMA9QoAOQCRBwCSCgACAJEJABIAkwkAEgCUBwCVCgAGAJEJABIAlgoABgCXCgAGAJgK"
            + "AAIAmQoABgCaCgCbAJwHAJ0HAJ4KABIAnwoAEgCgBwChCgASAKIHAKMKABIApAkAFAClCgAUAKYH"
            + "AKcJAGUAqAkAOgCpCgBlAKoKAAYAqwsArACtCwCsAK4KAAYArwcAsAoABgCxCQAUALIKABQAswkA"
            + "cQC0CgC1ALYGP+AAAAAAAAAJADoAtwoAcQCqCQBxALgJAHEAuQkAcQC6CgCbALsIALwHAL0KAC8A"
            + "kQoALwC+CAC/CgAvAMAKAC8AwQgAwggAwwgAxAcAjQcAxQcAxgEADElubmVyQ2xhc3NlcwEABWJv"
            + "YXJkAQAVTGphdmEvdXRpbC9BcnJheUxpc3Q7AQAJU2lnbmF0dXJlAQBVTGphdmEvdXRpbC9BcnJh"
            + "eUxpc3Q8TGphdmEvdXRpbC9BcnJheUxpc3Q8TGphdmEvdXRpbC9BcnJheUxpc3Q8TGFuaW1hbHMv"
            + "QW5pbWFsOz47Pjs+OwEAA2dlbgEAEkxqYXZhL3V0aWwvUmFuZG9tOwEABFNJWkUBAAFJAQAGPGlu"
            + "aXQ+AQAEKEkpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUB"
            + "AAFqAQABaQEABHRoaXMBAAtMd2lsZC9HYW1lOwEABHNpemUBAA1TdGFja01hcFRhYmxlBwChAQAI"
            + "cG9wdWxhdGUBABUoTGphdmEvbGFuZy9DbGFzcztJKVYBAAFlAQAoTGphdmEvbGFuZy9SZWZsZWN0"
            + "aXZlT3BlcmF0aW9uRXhjZXB0aW9uOwEAA3JvdwEAA2NvbAEAB3NwZWNpZXMBABFMamF2YS9sYW5n"
            + "L0NsYXNzOwEAA251bQEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBABZMamF2YS9sYW5nL0NsYXNz"
            + "PFRUOz47BwDHBwDIAQAuPFQ6TGFuaW1hbHMvQW5pbWFsOz4oTGphdmEvbGFuZy9DbGFzczxUVDs+"
            + "O0kpVgEAB2l0ZXJhdGUBAAMoKVYBAAdtb3ZlQWxsAQAVTGphdmEvbGFuZy9FeGNlcHRpb247AQAB"
            + "YQEAEExhbmltYWxzL0FuaW1hbDsBAAVhTW92ZQcAyQEABE1vdmUBABVMYW5pbWFscy9BbmltYWwk"
            + "TW92ZTsBAARnYW1lBwCjBwCnBwDJAQAHZmxhdHRlbgEABXJhbmQxAQAFcmFuZDIBAAFiAQAFYVRh"
            + "Y2sHAMoBAAZBdHRhY2sBABdMYW5pbWFscy9BbmltYWwkQXR0YWNrOwEABWJUYWNrAQAEY2VsbAEA"
            + "J0xqYXZhL3V0aWwvQXJyYXlMaXN0PExhbmltYWxzL0FuaW1hbDs+OwEAPkxqYXZhL3V0aWwvQXJy"
            + "YXlMaXN0PExqYXZhL3V0aWwvQXJyYXlMaXN0PExhbmltYWxzL0FuaW1hbDs+Oz47BwDLBwCVBwDK"
            + "AQAEcG9sbAEAFChMamF2YS9sYW5nL0NsYXNzOylJAQABYwEABWNvdW50AQAIdG9TdHJpbmcBABQo"
            + "KUxqYXZhL2xhbmcvU3RyaW5nOwEAAXMBABJMamF2YS9sYW5nL1N0cmluZzsHAMwBAAdnZXRBcmVh"
            + "AQAHKElJKVtbQwEABXRlbXAxAQAFdGVtcDIBAAV0ZW1wMwEABXRlbXA0AQABbAEAAWsBAARhcmVh"
            + "AQADW1tDBwDNAQAKU291cmNlRmlsZQEACUdhbWUuamF2YQwARABfAQAQamF2YS91dGlsL1JhbmRv"
            + "bQwAQABBDABCAEMBABNqYXZhL3V0aWwvQXJyYXlMaXN0DAA8AD0MAM4AzwwA0ADRDADSANMMANQA"
            + "1QcAxwwA1gDXAQAgamF2YS9sYW5nL0luc3RhbnRpYXRpb25FeGNlcHRpb24BACBqYXZhL2xhbmcv"
            + "SWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbgwAYABfDABsAF8BAAl3aWxkL0dhbWUMAEQARQEADmFuaW1h"
            + "bHMvQW5pbWFsDACEAIUMANgAjQwA2QDaAQATamF2YS9sYW5nL0V4Y2VwdGlvbgwA2wBnDADcAN0M"
            + "AN4A3wwA4ADhBwDLDADiANUMAOMA1wwATQDfAQAXYW5pbWFscy9Cb3lXaG9DcmllZFdvbGYMAOQA"
            + "zwwA5QDmDADnAOgMAOkAcwcA6gwA6wDsDADtAN0MAO4AcwwA7wBzDADwAHMMAPEAzwEABjxodG1s"
            + "PgEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyDADyAPMBAAwmbmJzcDsmbmJzcDsMAH8AgAwA8gD0"
            + "AQAGJm5ic3A7AQAEPGJyPgEABzwvaHRtbD4BABBqYXZhL2xhbmcvT2JqZWN0AQALd2lsZC9HYW1l"
            + "JDEBAA9qYXZhL2xhbmcvQ2xhc3MBACZqYXZhL2xhbmcvUmVmbGVjdGl2ZU9wZXJhdGlvbkV4Y2Vw"
            + "dGlvbgEAE2FuaW1hbHMvQW5pbWFsJE1vdmUBABVhbmltYWxzL0FuaW1hbCRBdHRhY2sBABJqYXZh"
            + "L3V0aWwvSXRlcmF0b3IBABBqYXZhL2xhbmcvU3RyaW5nAQACW0MBAANhZGQBABUoTGphdmEvbGFu"
            + "Zy9PYmplY3Q7KVoBAANnZXQBABUoSSlMamF2YS9sYW5nL09iamVjdDsBAAduZXh0SW50AQAEKEkp"
            + "SQEAB2lzRW1wdHkBAAMoKVoBAAtuZXdJbnN0YW5jZQEAFCgpTGphdmEvbGFuZy9PYmplY3Q7AQAM"
            + "c3Vycm91bmRpbmdzAQAEbW92ZQEAFygpTGFuaW1hbHMvQW5pbWFsJE1vdmU7AQAESE9MRAEAHiRT"
            + "d2l0Y2hNYXAkYW5pbWFscyRBbmltYWwkTW92ZQEAAltJAQAHb3JkaW5hbAEAAygpSQEACGl0ZXJh"
            + "dG9yAQAWKClMamF2YS91dGlsL0l0ZXJhdG9yOwEAB2hhc05leHQBAARuZXh0AQAGcmVtb3ZlAQAG"
            + "bGV0dGVyAQABQwEABWZpZ2h0AQAaKEMpTGFuaW1hbHMvQW5pbWFsJEF0dGFjazsBAAdTVUlDSURF"
            + "AQAOamF2YS9sYW5nL01hdGgBAAZyYW5kb20BAAMoKUQBACAkU3dpdGNoTWFwJGFuaW1hbHMkQW5p"
            + "bWFsJEF0dGFjawEABVBBUEVSAQAIU0NJU1NPUlMBAARST0NLAQAKaXNJbnN0YW5jZQEABmFwcGVu"
            + "ZAEALShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9TdHJpbmdCdWlsZGVyOwEAHChDKUxq"
            + "YXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsAIQASADkAAAADAAIAPAA9AAEAPgAAAAIAPwASAEAAQQAA"
            + "ABQAQgBDAAAACAAEAEQARQABAEYAAADtAAMABAAAAF8qtwABKrsAAlm3AAO1AAQqG7UABSq7AAZZ"
            + "twAHtQAIAz0cG6IAOyq0AAi7AAZZtwAHtgAJVwM+HRuiAB8qtAAIHLYACsAABrsABlm3AAe2AAlX"
            + "hAMBp//ihAIBp//GsQAAAAMARwAAAC4ACwAAABEABAAOAA8AEgAUABMAHwAUACYAFQA1ABYAPAAX"
            + "AFIAFgBYABQAXgAaAEgAAAAqAAQANwAhAEkAQwADACEAPQBKAEMAAgAAAF8ASwBMAAAAAABfAE0A"
            + "QwABAE4AAAAYAAT/ACEAAwcATwEBAAD8ABUB+gAg+gAFAAQAUABRAAIARgAAARwAAgAGAAAAXRye"
            + "AFsqtAAEKrQABbYACz4qtAAEKrQABbYACzYEKrQACB22AArAAAYVBLYACsAABrYADJkAJiq0AAgd"
            + "tgAKwAAGFQS2AArAAAYrtgANtgAJV6cABToFhAL/p/+nsQACADYAUQBUAA4ANgBRAFQADwAEAEcA"
            + "AAAmAAkAAAAdAAQAHgAQAB8AHQAgADYAIQBRACIAVgAjAFkAJQBcACYASAAAAD4ABgBWAAAAUgBT"
            + "AAUAEABJAFQAQwADAB0APABVAEMABAAAAF0ASwBMAAAAAABdAFYAVwABAAAAXQBYAEMAAgBZAAAA"
            + "DAABAAAAXQBWAFoAAQBOAAAAGwAFAP8AUwAFBwBPBwBbAQEBAAEHAFwB+QACAgA+AAAAAgBdAAQA"
            + "XgBfAAEARgAAADsAAQABAAAACSq3ABAqtwARsQAAAAIARwAAAA4AAwAAACkABAAqAAgAKwBIAAAA"
            + "DAABAAAACQBLAEwAAAACAGAAXwABAEYAAAJjAAQABwAAAVu7ABJZKrQABbcAE0wDPRwqtAAFogE/"
            + "Az4dKrQABaIBLyq0AAgctgAKwAAGHbYACsAABrYADJoBESq0AAgctgAKwAAGHbYACsAABgO2AArA"
            + "ABQ6BBkEKhwdtwAVtQAWGQS2ABc6BacACjoGsgAZOgWyABoZBbYAGy6qAAAAAAAAzgAAAAEAAAAF"
            + "AAAAJAAAAEsAAABtAAAAjwAAALYrtAAIHARkKrQABWAqtAAFcLYACsAABh22AArAAAYZBLYACVen"
            + "AIYrtAAIHLYACsAABh0EYCq0AAVwtgAKwAAGGQS2AAlXpwBkK7QACBwEYCq0AAVwtgAKwAAGHbYA"
            + "CsAABhkEtgAJV6cAQiu0AAgctgAKwAAGHQRkKrQABWAqtAAFcLYACsAABhkEtgAJV6cAGyu0AAgc"
            + "tgAKwAAGHbYACsAABhkEtgAJV4QDAaf+z4QCAaf+vyortAAItQAIsQABAF4AZQBoABgAAwBHAAAA"
            + "WgAWAAAALgAMAC8AFgAwACAAMQA4ADIAUwAzAF4ANQBlADYAbwA3AJwAOQDAADoAwwA8AOIAPQDl"
            + "AD8BBABAAQcAQgErAEMBLgBFAUYAMAFMAC8BUgBLAVoATABIAAAAUgAIAGoABQBSAGEABgBTAPMA"
            + "YgBjAAQAZQADAGQAZwAFAG8A1wBkAGcABQAYATQASQBDAAMADgFEAEoAQwACAAABWwBLAEwAAAAM"
            + "AU8AaABMAAEATgAAADYADP0ADgcATwH8AAkB/wBPAAUHAE8HAE8BAQcAaQABBwBq/AAGBwBrLCYh"
            + "ISb5ABf6AAX6AAUAAgBsAF8AAQBGAAADuAAFAAwAAAFfKrQACLYAHEwruQAdAQCZAVAruQAeAQDA"
            + "AAZNLLYAHE4tuQAdAQCZATUtuQAeAQDAAAY6BBkEtgAfBKQBHiq0AAQZBLYAH7YACzYFKrQABBkE"
            + "tgAftgALNgYVBRUGn//uGQQVBbYACsAAFDoHGQQVBrYACsAAFDoIGQfBACCZAA4ZBBkItgAhV6f/"
            + "rBkIwQAgmQAOGQQZB7YAIVen/5kZBxkItAAitgAjOgmnAAo6C7IAJDoJGQgZB7QAIrYAIzoKpwAK"
            + "OguyACQ6ChkJGQqmAB0ZBLgAJRQAJpeeAAgZB6cABRkItgAhV6cAbbIAKBkJtgApLqoAAAAAAABh"
            + "AAAAAQAAAAMAAAAcAAAANAAAAEwZBBkKsgAqpgAIGQenAAUZCLYAIVenADAZBBkKsgArpgAIGQen"
            + "AAUZCLYAIVenABgZBBkKsgAspgAIGQenAAUZCLYAIVen/t+n/sin/q2xAAIAngCqAK0AGAC0AMAA"
            + "wwAYAAQARwAAAHYAHQAAAE8AGwBQADQAUQA9AFMASwBUAGAAVgBsAFcAeABZAIAAWgCIAFsAiwBc"
            + "AJMAXQCbAF4AngBiAKoAYwC0AGQAwABlAMoAZwDRAGgA6wBqARAAbAElAG0BKABvAT0AcAFAAHIB"
            + "VQB2AVgAdwFbAHgBXgB5AEgAAACEAA0ArwAFAFIAYQALAMUABQBSAGEACwBLAQoAbQBDAAUAWQD8"
            + "AG4AQwAGAGwA6QBiAGMABwB4AN0AbwBjAAgAqgADAHAAcwAJALQAoQBwAHMACQDAAAMAdABzAAoA"
            + "ygCLAHQAcwAKADQBJAB1AD0ABAAbAUAAVAA9AAIAAAFfAEsATAAAAFkAAAAWAAIANAEkAHUAdgAE"
            + "ABsBQABUAHcAAgBOAAABFQAa/AAIBwB4/QAXBwB5BwB4/AATBwB5/AAWAf4APwEHAGkHAGkSTgcA"
            + "avwABgcAek4HAGr8AAYHAHpXBwB5/wABAAsHAE8HAHgHAHkHAHgHAHkBAQcAaQcAaQcAegcAegAC"
            + "BwB5BwBpBiROBwB5/wABAAsHAE8HAHgHAHkHAHgHAHkBAQcAaQcAaQcAegcAegACBwB5BwBpBk4H"
            + "AHn/AAEACwcATwcAeAcAeQcAeAcAeQEBBwBpBwBpBwB6BwB6AAIHAHkHAGkGTgcAef8AAQALBwBP"
            + "BwB4BwB5BwB4BwB5AQEHAGkHAGkHAHoHAHoAAgcAeQcAaf8AAwAFBwBPBwB4BwB5BwB4BwB5AAD6"
            + "AAL5AAL6AAIABAB7AHwAAQBGAAABNgACAAkAAABvAz0qtAAItgAcTi25AB0BAJkAXS25AB4BAMAA"
            + "BjoEGQS2ABw6BRkFuQAdAQCZAD4ZBbkAHgEAwAAGOgYZBrYAHDoHGQe5AB0BAJkAHhkHuQAeAQDA"
            + "ABQ6CCsZCLYALZkABoQCAaf/3qf/vqf/oBysAAAABABHAAAAKgAKAAAAfAACAH0AHgB+ADsAfwBY"
            + "AIAAYQCBAGQAggBnAIMAagCEAG0AhQBIAAAAPgAGAFgADABiAGMACAA7ACwAdQA9AAYAHgBMAFQA"
            + "PQAEAAAAbwBLAEwAAAAAAG8AfQBXAAEAAgBtAH4AQwACAFkAAAAWAAIAOwAsAHUAdgAGAB4ATABU"
            + "AHcABABOAAAAJQAH/QAKAQcAeP0AGgcAeQcAeP0AHAcAeQcAeCH5AAL5AAL6AAIAAQB/AIAAAQBG"
            + "AAABWwADAAYAAACqEi5MKrQACLYAHE0suQAdAQCZAIUsuQAeAQDAAAZOLbYAHDoEGQS5AB0BAJkA"
            + "VBkEuQAeAQDAAAY6BRkFtgAMmQAauwAvWbcAMCu2ADESMrYAMbYAM0ynACa7AC9ZtwAwK7YAMRkF"
            + "A7YACsAAFLQAIrYANBI1tgAxtgAzTKf/qLsAL1m3ADArtgAxEja2ADG2ADNMp/94uwAvWbcAMCu2"
            + "ADESN7YAMbYAM7AAAAAEAEcAAAAqAAoAAACJAAMAigAeAIsAOgCMAEIAjQBZAI8AfACQAH8AkQCT"
            + "AJIAlgCTAEgAAAAqAAQAOgBCAHUAPQAFAB4AdQBUAD0AAwAAAKoASwBMAAAAAwCnAIEAggABAFkA"
            + "AAAWAAIAOgBCAHUAdgAFAB4AdQBUAHcAAwBOAAAAIwAG/QALBwCDBwB4/QAYBwB5BwB4/AA0BwB5"
            + "+gAi+gAC+QAWAAIAhACFAAEARgAAAdAABAALAAAApQYGxQA4Ak4CNgQVBASjAJYCNgUVBQSjAIcV"
            + "BARgNgYVBQRgNgcbFQRgKrQABWAqtAAFcDYIHBUFYCq0AAVgKrQABXA2CSq0AAgbFQRgKrQABWAq"
            + "tAAFcLYACsAABhwVBWAqtAAFYCq0AAVwtgAKwAAGOgotFQQEYDIVBQRgGQq2AAyZAAgQIKcADxkK"
            + "A7YACsAAFLQAIlWEBQGn/3mEBAGn/2otsAAAAAQARwAAADIADAAAAJcABwCYABAAmQAZAJoAHwCb"
            + "ACUAnAA1AJ0ARQCeAHMAnwCXAJkAnQCYAKMAogBIAAAAcAALAB8AeACGAEMABgAlAHIAhwBDAAcA"
            + "NQBiAIgAQwAIAEUAUgCJAEMACQBzACQAdQA9AAoAEwCKAIoAQwAFAAoAmQCLAEMABAAAAKUASwBM"
            + "AAAAAAClAEoAQwABAAAApQBJAEMAAgAHAJ4AjACNAAMAWQAAAAwAAQBzACQAdQB2AAoATgAAAFkA"
            + "Bv0ACgcAOAH8AAgB/wB2AAsHAE8BAQcAOAEBAQEBAQcAeQACBwCOAf8ACwALBwBPAQEHADgBAQEB"
            + "AQEHAHkAAwcAjgEB/wAGAAUHAE8BAQcAOAEAAPoABQACAI8AAAACAJAAOwAAABoAAwA6ABIAABAI"
            + "AGUAFABmQBkAcQAUAHJAGQ==";
}

```

Oh yeah, it does require a JDK to run, but I don't think that'll be a problem.

# Answer
> 14 votes
**Omega Wolf**

Interdependently derived solution that behaves very similar to Alpha Wolf, hence the name Omega Wolf

This wolf generates a "danger" map of the surrounding cells and will choose the movement (or hold) to the safest cell.

The firstly the cells where lions will move next are given EXTREAME\_DANGER level. Then the cells surrounding any detected Wolves are given danger levels based on the immediacy of attack... i.e. if the wolf is diagonal to the omega wolf it is deemed a low threat however wolves that are adjacent are deemed a moderate threat.

The "danger" map is then blurred to allow bleeding of the threats to surrounding cells. This allows the omega wolf to "sense" threat vectors and to avoid it.

Currently the actual attack logic is very primitive. I hope to be able to give it more smarts and eek out better win/lose ratios. This should be possible if I put in some statistical heuristics.

In my testing Omega Wolf conistantly wins against alpha bot 9 out of 10 times... though the margin is very fine :P

quick results of the avg remaining living wolves after 100 rounds of 1000 iterations:

```
class animals.OmegaWolf - 85
class animals.HonorWolf - 82
class animals.ProAlpha - 79
class animals.AlphaWolf - 77
class animals.ShadowWolf - 77
class animals.LazyWolf - 62
class animals.CamperWolf - 61
class animals.StoneEatingWolf - 59
class animals.GatheringWolf - 48
class animals.Sheep - 42
class animals.EmoWolf - 34
class animals.LionHunterWolf - 28
class animals.GamblerWolf (no cheating) - 27
class animals.WolfWithoutFear - 11
class animals.MOSHPITFRENZYWolf - 5
class animals.Wolf - 3
class animals.Stone - 2
class animals.Bear - 0
class animals.Lion - 0
class animals.MimicWolf - 0
class animals.Wion - 0

```

Code:

```
package animals;

import wild.Wild;

public class OmegaWolf extends Animal {

    boolean lionWillMoveDown=true;

    private static final int LOW_DANGER = 10;
    private static final int MODERATE_DANGER = LOW_DANGER*2;
    private static final int EXTREAME_DANGER = MODERATE_DANGER*4;

    private static final int UP=1;
    private static final int LEFT=3;
    private static final int RIGHT=5;
    private static final int DOWN=7;
    private static final int UP_LEFT=0;
    private static final int UP_RIGHT=2;
    private static final int DOWN_LEFT=6;
    private static final int DOWN_RIGHT=8;

    private static final int WOLVES_SPECIES_COUNT=(int) Math.round(Math.pow(((float) Wild.MAP_SIZE)/20,2)-3)-3;

    /*
     * Interdependently derived solution that behaves very similar to Alpha Wolf, hence the name Omega Wolf
     *
     * This wolf generates a "danger" map of the surrounding cells and will choose the movement (or hold) to the safest cell.
     *
     * The firstly the cells where lions will move next are given EXTREAME_DANGER level
     * Then the cells surrounding any detected Wolves are given danger levels based on the immediacy of attack... i.e. if the wolf is diagonal to the omega wolf
     * it is deemed a low threat however wolves that are adjacent are deemed a moderate threat.
     * The "danger" map is then blurred to allow bleeding of the threats to surrounding cells. This allows the omega wolf to "sense" threat vectors and to avoid it.
     *
     * Currently the actual attack logic is very primitive. I hope to be able to give it more smarts and eek out better win/lose ratios. This should be possible if
     * I put in some statistical heuristics.
     */

    public OmegaWolf() {
        super('W'); }

    @Override
    public Attack fight(char opponent) {
        switch(opponent){
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S':
            return Attack.PAPER;
        default:
            // if there is only one wolf species then it must be another omega wolf.
            if (WOLVES_SPECIES_COUNT==1)
            {
                return Attack.SCISSORS;
            }
            else
            {
                // lets just choose an attack with equal weight.
                double rand = Math.random();
                if (rand < 0.333333)
                {
                    return Attack.PAPER;
                }
                if (rand < 0.666667)
                {
                    return Attack.SCISSORS;
                }
                return Attack.ROCK;

            }
        }
    }

    public Move move() {

        lionWillMoveDown = !lionWillMoveDown;

        Move move = Move.HOLD;

        int[][] dangerMap = new int[3][3];
        int[][] blurredDangerMap = new int[3][3];

        // sense Lion Danger
        for (int y=0;y<3;y++)
        {
            for (int x=0;x<3;x++)
            {
                if (surroundings[y][x]=='L')
                {
                    if (lionWillMoveDown && y!=2)
                    {
                        dangerMap[y+1][x]+=EXTREAME_DANGER;
                    }
                    else if (x!=2)
                    {
                        dangerMap[y][x+1]+=EXTREAME_DANGER;
                    }
                }
            }
        }

        // sense Wolf Danger adjacent
        // UP
        if (surroundings[0][1]=='W')
        {
            dangerMap[0][1]+=MODERATE_DANGER;
            dangerMap[0][0]+=LOW_DANGER;
            dangerMap[0][2]+=LOW_DANGER;
            dangerMap[1][1]+=MODERATE_DANGER;
        }
        // DOWN
        if (surroundings[2][1]=='W')
        {
            dangerMap[2][1]+=MODERATE_DANGER;
            dangerMap[2][0]+=LOW_DANGER;
            dangerMap[2][2]+=LOW_DANGER;
            dangerMap[1][1]+=MODERATE_DANGER;
        }
        // LEFT
        if (surroundings[1][0]=='W')
        {
            dangerMap[1][0]+=MODERATE_DANGER;
            dangerMap[0][0]+=LOW_DANGER;
            dangerMap[2][0]+=LOW_DANGER;
            dangerMap[1][1]+=MODERATE_DANGER;
        }
        // RIGHT
        if (surroundings[1][2]=='W')
        {
            dangerMap[1][2]+=MODERATE_DANGER;
            dangerMap[0][2]+=LOW_DANGER;
            dangerMap[2][2]+=LOW_DANGER;
            dangerMap[1][1]+=MODERATE_DANGER;
        }

        // sense Wolf Danger diagonally
        // UP_LEFT
        if (surroundings[0][0]=='W')
        {
            dangerMap[0][0]+=LOW_DANGER;
            dangerMap[0][1]+=MODERATE_DANGER;
            dangerMap[1][0]+=MODERATE_DANGER;
        }
        // DOWN_LEFT
        if (surroundings[2][0]=='W')
        {
            dangerMap[2][0]+=LOW_DANGER;
            dangerMap[2][1]+=MODERATE_DANGER;
            dangerMap[1][0]+=MODERATE_DANGER;
        }
        // UP_RIGHT
        if (surroundings[0][2]=='W')
        {
            dangerMap[0][2]+=LOW_DANGER;
            dangerMap[1][2]+=MODERATE_DANGER;
            dangerMap[0][1]+=MODERATE_DANGER;
        }
        // DOWN_RIGHT
        if (surroundings[2][2]=='W')
        {
            dangerMap[2][2]+=LOW_DANGER;
            dangerMap[2][1]+=MODERATE_DANGER;
            dangerMap[1][2]+=MODERATE_DANGER;
        }

        // generate a blurred danger map. This bleeds danger to surrounding cells.
        int yj,xi,sampleCount,cumulativeDanger;
        for (int y=0;y<3;y++)
        {
            for (int x=0;x<3;x++)
            {
                sampleCount=0;
                cumulativeDanger=0;
                for (int j=-1;j<2;j++)
                {
                    for (int i=-1;i<2;i++)
                    {
                        yj=y+j;
                        xi=x+i;
                        if (yj>-1 && yj<3 && xi>-1 && xi<3)
                        {
                            cumulativeDanger+=dangerMap[yj][xi];
                            sampleCount++;
                        }
                    }
                }
                blurredDangerMap[y][x]=(dangerMap[y][x]+cumulativeDanger/sampleCount)/2;
            }
        }

        // find the safest cell
        int safestCellDanger=Integer.MAX_VALUE;
        int safestCellId = -1;
        int cellId=0;

        for (int y=0;y<3;y++)
        {
            for (int x=0;x<3;x++)
            {
                if (blurredDangerMap[y][x]<safestCellDanger)
                {
                    safestCellDanger=blurredDangerMap[y][x];
                    safestCellId=cellId;
                }
                cellId++;
            }
        }

        // safest cell is adjacent so move there
        if ((safestCellId&1)==1)
        {
            switch (safestCellId)
            {
                case UP:
                    move=Move.UP;
                    break;
                case LEFT:
                    move=Move.LEFT;
                    break;
                case RIGHT:
                    move=Move.RIGHT;
                    break;
                case DOWN:
                    move=Move.DOWN;
                    break;
            }
        }
        // safestCell is a diagonal cell or current cell
        else
        {
            // lets initialise the move to Hold.
            move = Move.HOLD;

            switch (safestCellId)
            {
                case UP_LEFT:

                    // check to see whether holding is not safer than moving up
                    if (dangerMap[1][1] > dangerMap[0][1] )
                    {
                        // move up if safer than moving left or if equally safe, when randomly chosen
                        if (dangerMap[0][1] < dangerMap[1][0] || (dangerMap[0][1] == dangerMap[1][0] && Math.random()>0.5))
                        {
                            move=Move.UP;
                        }
                        // left must be safest :P
                        else
                        {

                            move=Move.LEFT;
                        }
                    }
                    // check to see whether holding is not safer than moving left
                    else if (dangerMap[1][1] > dangerMap[1][0] )
                    {
                        move=Move.LEFT;
                    }

                    break;
                case UP_RIGHT:
                    // check to see whether holding is not safer than moving up
                    if (dangerMap[1][1] > dangerMap[0][1] )
                    {
                        // move up if safer than moving right or if equally safe, when randomly chosen
                        if (dangerMap[0][1] < dangerMap[1][2]|| (dangerMap[0][1] == dangerMap[1][2] && Math.random()>0.5))
                        {
                            move=Move.UP;
                        }
                        // right must be safest :P
                        else
                        {
                            move=Move.RIGHT;
                        }
                    }
                    // check to see whether holding is not safer than moving right
                    else if (dangerMap[1][1] > dangerMap[1][2] )
                    {
                        move=Move.RIGHT;
                    }
                    break;
                case DOWN_LEFT:
                    // check to see whether holding is not safer than moving down
                    if (dangerMap[1][1] > dangerMap[2][1] )
                    {
                        // move down if safer than moving left or if equally safe, when randomly chosen
                        if (dangerMap[2][1] < dangerMap[1][0]|| (dangerMap[2][1] == dangerMap[1][0] && Math.random()>0.5))
                        {
                            move=Move.DOWN;
                        }
                        // left must be safest :P
                        else
                        {
                            move=Move.LEFT;
                        }
                    }
                    // check to see whether holding is not safer than moving left
                    else if (dangerMap[1][1] > dangerMap[1][0] )
                    {
                        move=Move.LEFT;
                    }
                    break;
                case DOWN_RIGHT:
                    // check to see whether holding is not safer than moving down
                    if (dangerMap[1][1] > dangerMap[2][1] )
                    {
                        // move down if safer than moving right or if equally safe, when randomly chosen
                        if (dangerMap[2][1] < dangerMap[2][2] || (dangerMap[2][1] == dangerMap[1][2] && Math.random()>0.5))
                        {
                            move=Move.DOWN;
                        }
                        // right must be safest :P
                        else
                        {
                            move=Move.RIGHT;
                        }
                    }
                    // check to see whether holding is not safer than moving right
                    else if (dangerMap[1][1] > dangerMap[1][2] )
                    {
                        move=Move.RIGHT;
                    }
                    break;
            }
        }

        return move;

    }
}

```

# Answer
> 14 votes
# StoneGuardianWolf

This was pretty fun. I made a clunky port of the java code to javascript with createjs support for visualization: JavaScript StoneGuardianWolf

The StoneGuardianWolf seeks out pet rocks and takes shelter beside Stones. She protects them and would rather sacrifice herself for their safety.

### Stats

**Single Player:** ~75% Wolf survival rate + 35% Pet (Stone) survival rate.

**Summary:** 75% + 35% ---\> **110% Success Rate!** :)

**Multi Player:** Untested.

### Change Log

**v2:** Updated AI vs GamblerWolf and pet rock seeking strategy.

**v1:** Better Wolf avoidance

**v0:** Birthday

### Java Code

```
package animals;

public class StoneGuardianWolf extends Animal {
    public StoneGuardianWolf() {
        super('W');
    }

    private boolean petRock = false;
    private int heartache = 0;

    public Attack fight(char c) {
        this.heartache--;

        switch (c) {
        case 'B':
            return Attack.SCISSORS;
        case 'L':
            return Attack.SCISSORS;
        case 'S': // A motherly sacrifice
            return Attack.SUICIDE;
        default:
            int n = this.heartache % 3;
            if (n < 1)
                return Attack.PAPER;
            if (n < 2)
                return Attack.ROCK;
            return Attack.SCISSORS;
        }
    }

    public Move move() {
        char[][] surr = this.surroundings;
        int[][] clairvoyance = new int[3][3];

        for (int i = 0; i < 3; i++)
            for (int j = 0; j < 3; j++)
                clairvoyance[i][j] = 1;

        boolean seeNoStone = true;

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                switch (surr[i][j]) {
                case 'L':
                    if (i < 1 && j < 1) {
                        clairvoyance[1][0] += 50;
                        clairvoyance[0][1] += 50;
                    }

                    if (i == 1 && j < 1) { // above
                        clairvoyance[1][1] += 50;
                    }

                    if (i < 1 && j == 1) { // left
                        clairvoyance[1][1] += 50;
                    }
                    break;

                case 'S': // seek stones for protection
                    seeNoStone = false;
                    this.petRock = true;
                    clairvoyance[i][j] += 999; // Only hugs!
                    if (i < 2)
                        clairvoyance[i + 1][j] -= 10;
                    if (j < 2)
                        clairvoyance[i][j + 1] -= 10;
                    if (i > 0)
                        clairvoyance[i - 1][j] -= 10;
                    if (j > 0)
                        clairvoyance[i][j - 1] -= 10;
                    break;

                case 'B': // ignore bears
                    break;

                case 'W':
                    // skip self
                    if (i == 1 && j == 1)
                        continue;
                    int m = 25; // avoid wolves

                    // don't fight unless pet rock is in danger
                    if (petRock)
                        clairvoyance[i][j] -= 999; // motherly wrath
                    else
                        clairvoyance[i][j] += 100;

                    // avoid stepping into wolf path
                    if (i != 1 && j != 1) {
                        if (i < 2)
                            clairvoyance[i + 1][j] += m;
                        if (j < 2)
                            clairvoyance[i][j + 1] += m;
                        if (i > 0)
                            clairvoyance[i - 1][j] += m;
                        if (j > 0)
                            clairvoyance[i][j - 1] += m;
                    }
                    break;

                default:
                    clairvoyance[i][j] += 0;
                }
            } // for loop
        } // for loop

        int size = clairvoyance[1][1];
        int x = 1;
        int y = 1;

        for (int i = 0; i < 3; i++) {
            for (int j = 0; j < 3; j++) {
                if (i != 1 || j != 1)
                    continue;
                int tmp = clairvoyance[i][j];
                if (tmp < size) {
                    size = tmp;
                    x = i;
                    y = j;
                }
            }
        }

        if (seeNoStone)
            this.heartache++;

        this.petRock = false;
        if (seeNoStone && heartache % 10 == 0) { // Find a pet stone! :3
            if ((heartache % 3) < 2 || clairvoyance[1][2] >= 45) {
                // try move right
                if (clairvoyance[2][1] < 45)
                    return Move.RIGHT;
            }

            // try down instead
            if (clairvoyance[1][2] < 45)
                return Move.DOWN;
        }

        if (x == 0 && y == 1)
            return Move.LEFT;
        if (x == 2 && y == 1)
            return Move.RIGHT;
        if (x == 1 && y == 0)
            return Move.UP;
        if (x == 1 && y == 2)
            return Move.DOWN;

        if (!seeNoStone)
            this.petRock = true;

        return Move.HOLD;
    }
}

```

# Answer
> 12 votes
## Wolves with a Collective Memory

A Wolf pack in R

The idea of this wolf pack is that it keeps in memory who's alive or dead, check what the dead wolves and the alive wolves used as attacks and change the choice probability accordingly.

Here is the R code:

```
infile <- file("stdin")
open(infile)
repeat{
    input <- readLines(infile,1)
    type <- substr(input,1,1)
    id <- substr(input,2,3)
    if(nchar(input)>3){
        info <- substr(input,4,nchar(input))
    }else{
        info <- NULL
    }
    attack <- function(id,info){
        if(info%in%c("B","L")){choice <- "S"}
        if(info=="S"){choice <- "P"}
        if(info=="W"){
            if(exists("memory")){
                dead <- memory$ID[memory$Status=="Dead"]
                veteran <- memory[memory$Attack!="" & !is.na(memory$Attack), ]
                if(nrow(veteran[!is.na(veteran[,1]),])>0){
                    deadvet<-veteran[veteran$ID%in%dead,]
                    deadvet<-unlist(lapply(split(deadvet,deadvet$ID),function(x)tail(x$Attack,1)))
                    deadvet <- table(factor(deadvet,levels=c("R","P","S","")))
                    livevet <- table(factor(veteran$Attack,levels=c("R","P","S","")))-deadvet
                    probR <- (1+livevet['R'])/(1+livevet['R']+deadvet['R'])
                    probS <- (1+livevet['S'])/(1+livevet['S']+deadvet['S'])
                    probP <- (1+livevet['P'])/(1+livevet['P']+deadvet['P'])
                    choice <- sample(c("S","P","R"),1,prob=c(probS,probP,probR))
                    memory <- rbind(memory, data.frame(ID=id, Status="Alive", Attack=choice))
                }else{
                    choice <- sample(c("S","P","R"),1)
                    memory <- rbind(memory, data.frame(ID=id, Status="Alive", Attack=choice))
                }
            }else{
                choice <- sample(c("S","P","R"),1)
                memory <- data.frame(ID=id, Status="Alive", Attack=choice)
            }
        }
        paste(choice,id,sep="")
    }
    move <- function(id,info){
        choice <- "H"
        paste(choice,id,sep="")
    }
    initialize <- function(id){
        if(exists("memory")){
            memory <- rbind(memory,data.frame(ID=id,Status="Alive",Attack=""))
        }else{
            memory <- data.frame(ID=id,Status="Alive",Attack="")
        }
        confirmed_dead <- memory$ID[memory$Status=="Dead"]
        last_seen <- memory[!memory$ID%in%confirmed_dead,]
        last_seen <- last_seen[last_seen$Attack=="",]
        lid <- table(last_seen$ID)
        turns <- max(lid)
        dead <- lid[lid<(turns-1)]
        if(length(dead)>0){
            dead_id <- names(dead)
            for(i in dead_id){
                memory <- rbind(memory, data.frame(ID=i, Status="Dead", Attack=""))
            }
        }
        paste("K",id,sep="")
    }
    result <- switch(type,"A"=attack(id,info),"M"= move(id,info),"S"=initialize(id))
    cat(result,"\n",sep="")
    flush(stdout())
}

```

It uses @ProgrammerDan wrapper (thank you!), with WolfCollectiveMemory as custom name and "Rscript WolfCollectiveMemory.R" as invocation.

# Answer
> 12 votes
## Wion

Tries to do as little as possible to survive as long as possible in expected value. It tries to move parallel to lions (regardless of whether it sees any).

It ignores wolves, since it decides they are unpredictable. If it encounters a wolf it should win about half the fights (this is optimal unless I attempt to do pattern matching). My wolves should never fight each other. If it encounters a lion (which it probably shouldn't) it should win about 3/4 of the fights. Bears and rocks should always lose.

Assuming there are any wolves in the simulation using another strategy, they would be wise to avoid my wolves, since they have a 50% chance of losing any encounter. On average this should perform at least as well as any other strategy.

If I understood the rules correctly, this should be the optimal strategy.

```
package animals;
import java.util.Random;

public class Wion extends Animal {
    private boolean down;
    public Wion() { super('W'); down=true;}
    public Attack fight(char opponent) {
        switch (opponent) {
            case 'B':
            case 'L':
                return Attack.SCISSORS;
            case 'S':
                return Attack.PAPER;
            default:
                Random rn = new Random();
                int i = Math.abs(rn.nextInt() % 4);
                while (i==3) {i = Math.abs(rn.nextInt() % 4);}
                return Attack.values()[i];
        }
    }
    public Move move() {
        down=!down;
        if(!down) { return Move.DOWN; }
        return Move.RIGHT;
    }
}

```

# Answer
> 12 votes
## Stone Eating Wolf

Here is my submission. This wolf keeps in place if he doesn't see any stone, lion or wolf in his surroundings. If he sees a stone and no danger of being attacked by another wolf or lion he tries to eat it. If he sees any danger, he flees!

**EDIT 1**: Improved watching for danger algorithm. He flees better from danger now :)

```
package animals;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class StoneEatingWolf extends Animal{

    public StoneEatingWolf() {
        super('W');
    }

    @Override
    public Attack fight(char c) {
        switch (c){
            case 'L': return Attack.SCISSORS;
            case 'B': return Attack.SCISSORS;
            case 'W': return getRandomAttack();
            case 'S': return Attack.PAPER;
            default: return getRandomAttack();
        }
    }

    private Attack getRandomAttack(){
        List<Attack> att = new ArrayList<>();
        att.add(Attack.PAPER);
        att.add(Attack.PAPER);
        att.add(Attack.ROCK);
        att.add(Attack.SCISSORS);
        Collections.shuffle(att);
        return att.get(0);
    }

    @Override
    public Move move() {
        List<Move> m = new ArrayList<>();

        //First see if there is any dangerous animal. If it is, then flee
        if (isThereAnyDangerousAnimal()){
            m.add(Move.UP);
            m.add(Move.RIGHT);
            m.add(Move.LEFT);
            m.add(Move.DOWN);
            getSafeMoves(m);
        }else{
        //No danger: Look for stones to eat
            if (isThereAnimalAtNorth('S')){
                m.add(Move.UP);
            }
            if (isThereAnimalAtEast('S')){
                m.add(Move.RIGHT);
            }
            if (isThereAnimalAtWest('S')){
                m.add(Move.LEFT);
            }
            if (isThereAnimalAtSouth('S')){
                m.add(Move.DOWN);
            }
        }

        if (m.isEmpty()){
            return Move.HOLD;
        } else {
            Collections.shuffle(m);
            return m.get(0);
        }
    }

    private void getSafeMoves(List<Move> lm){

        if (isThereAnimalAtNorth('L') || isThereAnimalAtNorth('W')){
            lm.remove(Move.UP);
        }
        if (isThereAnimalAtEast('L') || isThereAnimalAtEast('W')){
            lm.remove(Move.RIGHT);
        }
        if (isThereAnimalAtSouth('L') || isThereAnimalAtSouth('W')){
            lm.remove(Move.DOWN);
        }
        if (isThereAnimalAtWest('L') || isThereAnimalAtWest('W')){
            lm.remove(Move.LEFT);
        }

    }

    private boolean isThereAnimalAtNorth(char an){
        if (surroundings[0][0] == an || surroundings [0][1] == an || surroundings [0][2] == an){
            return true;
        }
        return false;
    }

    private boolean isThereAnimalAtSouth(char an){
        if (surroundings[2][0] == an || surroundings [2][2] == an || surroundings [2][2] == an){
            return true;
        }
        return false;
    }

    private boolean isThereAnimalAtEast(char an){
        if (surroundings[0][2] == an || surroundings [1][2] == an || surroundings [2][2] == an){
            return true;
        }
        return false;
    }

    private boolean isThereAnimalAtWest(char an){
        if (surroundings[0][0] == an || surroundings [1][0] == an || surroundings [2][0] == an){
            return true;
        }
        return false;
    }

    private boolean isThereAnyDangerousAnimal(){
        if (isThereAnimalAtEast('L') ||
                isThereAnimalAtEast('W') ||
                isThereAnimalAtNorth('L') ||
                isThereAnimalAtNorth('W') ||
                isThereAnimalAtSouth('L') ||
                isThereAnimalAtSouth('W') ||
                isThereAnimalAtWest('L') ||
                isThereAnimalAtWest('W')){
            return true;
        }
        return false;
    }

    }

```

## **Edit 2**: Some Statistics

I have manage to make StoneEatingWolf the top 5-6 Wolf in the simulations I ran:

I make some analysis of the fights where Stone Eating Wolves are implied. Running 40 plays of 1000 iterations I get these results:

Victory are Stone Eating Wolf wins. Chart shows what we already know: The most successful wolves are the ones that doesn't meet other wolves. I also noticed that my other wolves (Migrating Wolves) are screwing some of my Stone Eaters. I hope they are hunting down another wolves too. Funny enough I didn't stumble with any Lazy Wolf nor any Camper Wolf. Also, these are the results of the attacks I received in 20 runs (Stones and Bears excluded):

```
PAPER       447
ROCK        881
SCISSORS    581
SUICIDE     230

```

Seems like there is a obvious bias to `ROCK` attacks. Knowing this I made my wolf `PAPER` attacks slightly more frequents.

# Answer
> 12 votes
# MimicWolf

The goal of this wolf is to mimic other wolves. It finds a wolf follows it to the best of its ability. MimicWolf doesn't ask questions like : How can I avoid that wolf/bear/lion/stone?

No, MimicWolf just asks questions like: Where is a wolf for me to follow? Where do I think the wolf that I am following is going to go? Is that the wolf that I was following is it a different wolf? Where did the wolf that I was following go?

I will admit that most of those questions are not yet be answered well, but for the time being here is my submission of MimicWolf

```
   package animals;
   import java.util.*;

public class MimicWolf extends Animal {

final int TURN_MEMORY = 5;

Random rand = new Random();

Animal.Move lastMove = Animal.Move.UP;

boolean mimicingWolf = false;

Pos[] wolfPreviousPos = new Pos[TURN_MEMORY];
RelativePos[] relativePositions = new RelativePos[TURN_MEMORY];
Move[] wolfPreviousMove = new Move[TURN_MEMORY - 1];

int turnsWithLostWolf = 0;

public MimicWolf() {
    super('W');
}

public Animal.Attack fight(char c) {
    switch (c) {
        case 'B':
            return Animal.Attack.SCISSORS;
        case 'L':
            return Animal.Attack.SCISSORS;
        case 'S':
            return Animal.Attack.PAPER;
        default:
            int x = rand.nextInt(4);
            return Animal.Attack.values()[x];
    }
}

public Animal.Move move() {
    Pos wolfPos = null;
    wolfPos = lookForSurroundingWolf();

    if (turnsWithLostWolf == 4) {
        mimicingWolf = false;
        wolfPreviousPos = new Pos[5];
        relativePositions = new RelativePos[5];
        turnsWithLostWolf = 0;
    }

    if (mimicingWolf) {
        int indexOfLastMove = 0;
        for (int i = 0; wolfPreviousPos[i] != null && i < wolfPreviousPos.length; i++) {
            indexOfLastMove = i;
        }

        //is wolf still visible??
        Pos wolfNewPos = isWolfVisible(wolfPreviousPos[indexOfLastMove]);
        if (wolfNewPos.x == -1) {//wolf is not visible
            turnsWithLostWolf++;
            return moveOppositeDirection(lastMove);
        } else {
            return mimicWolf(wolfNewPos, indexOfLastMove); //need Better way to mimic
        }
    } else {
        //check if new wolf around
        if (wolfPos.x == -1) {
            return searchForWolf();
        } else {
            mimicingWolf = true;
            return mimicWolf(wolfPos, 0);
        }
    }
}

private Animal.Move searchForWolf() {
    Animal.Move newMove = null;
    while (newMove == null || newMove == lastMove) {
        newMove = Animal.Move.values()[rand.nextInt(3)];
    }

    lastMove = newMove;
    return newMove;
}

private Pos lookForSurroundingWolf() {
    for (Integer i = 0; i < surroundings.length; i++) {
        for (Integer j = 0; j < surroundings[0].length; j++) {
            if (i == 1 && j == 1) {
                //this is myself >.<
            } else if (surroundings[i][j] == 'W') {
                return new Pos(i, j);
            }
        }
    }

    return new Pos(-1, -1);
}

/*
    for mimicWolf when movesMimiced == 1 or 2 this is the base case, Any
    number greater the wolf will attempt to mimic the next move based on pattern
    of previous moves
        we assume that we are following the same wolf as last time
 */

private Animal.Move mimicWolf(Pos wolfCurrentPos, int movesMimiced) {
    wolfPreviousPos[movesMimiced] = wolfCurrentPos;
    insertToRelativePos(wolfCurrentPos, movesMimiced);
    if (movesMimiced == 0) {
        Move m1 = null, m2 = null;
        if (wolfPreviousPos[0].x == 0) {
            m1 = Move.LEFT;
        } else if (wolfPreviousPos[0].x == 2) {
            m1 = Move.RIGHT;
        }

        if (wolfPreviousPos[0].y == 0) {
            m2 = Move.UP;
        } else if (wolfPreviousPos[0].y == 2) {
            m2 = Move.DOWN;
        }

        return randOfMoves(m1, m2); //guess which way to go
    }
    wolfPreviousMove[movesMimiced - 1] =  getDirection(wolfPreviousPos[movesMimiced - 1], wolfPreviousPos[movesMimiced]);
    if (movesMimiced == 1) {
        //if pos 1 was a cornor
        if(relativePositions[0] == RelativePos.CORNER){
            if(relativePositions[1] == RelativePos.CORNER){
                if(wolfPreviousPos[0].equals(wolfPreviousPos[1])){
                    return lastMove;
                }
                return moveOppositeDirection(lastMove);
            }
            else if(relativePositions[1] == RelativePos.EDGE){
                return Move.HOLD; //he held so i will hold
            }
        }else if(relativePositions[1] == RelativePos.EDGE){
            if(relativePositions[1] == RelativePos.EDGE){
                return lastMove;
            }
            else if(relativePositions[1] == RelativePos.CORNER){
                //only possibility is that I held, and he moved
                return wolfPreviousMove[0];
            }
        }
    } else {
        //Return most common move the wolf I am copying has made
        int[] mostCommonMoveArr = {0,0,0,0,0};
        for(int i = 0; i <= movesMimiced; i++){
            switch(wolfPreviousMove[i]){
                case UP:
                    mostCommonMoveArr[0]++;
                case RIGHT:
                    mostCommonMoveArr[1]++;
                case DOWN:
                    mostCommonMoveArr[2]++;
                case LEFT:
                    mostCommonMoveArr[3]++;
                case HOLD:
                    mostCommonMoveArr[4]++;
            }
        }

        int maxValue = -1;
        int maxLocal = 0;
        for(int i = 0; i < 5; i++){
            if(mostCommonMoveArr[i] > maxValue)
                maxValue =  mostCommonMoveArr[i];
                maxLocal = i;
        }

        return Move.values()[maxLocal];
    }

    return Move.HOLD; //shouldn't happen
}

private Pos isWolfVisible(Pos lastPos) {
    Pos mimicedWolfPos = lookForSurroundingWolf();
    while (mimicedWolfPos.x != -1 && mimicedWolfPos.y != -1) {
        //did we find the wolf?
        if (lastPos.x == mimicedWolfPos.x || lastPos.y == mimicedWolfPos.y) {
            return mimicedWolfPos;
        }

        surroundings[mimicedWolfPos.x][mimicedWolfPos.y] = ' ';
        mimicedWolfPos = lookForSurroundingWolf();
    }

    return new Pos(-1, -1);
}

private Animal.Move moveOppositeDirection(Move m) {
    switch (m) {
        case UP:
            return Move.DOWN;
        case RIGHT:
            return Move.LEFT;
        case DOWN:
            return Move.UP;
        case LEFT:
            return Move.RIGHT;
        case HOLD:
            return Move.LEFT; //No idea why this would happen but whatever
        default:
            return Move.HOLD;
    }
}

private Animal.Move getDirection(Pos firstPos, Pos secondPos){
    if(firstPos.equals(secondPos))
        return Move.HOLD;
    if(firstPos.x == secondPos.x){
        if(firstPos.y > secondPos.y)
            return Move.UP;
        return Move.DOWN;
    }
    if(firstPos.x > secondPos.x)
        return Move.RIGHT;
    return Move.LEFT;
}

private Animal.Move randOfMoves(Move m1, Move m2) {
    if (m1 == null) {
        return m2;
    } else if (m2 == null) {
        return m1;
    }

    int r = rand.nextInt(2);
    if (r == 0) {
        return m1;
    }
    return m2;
}

private class Pos {
    int x;
    int y;

    protected Pos(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object obj){
        Pos pos = (Pos) obj;
        return (this.x == pos.x && this.y == pos.y);
    }
}

private void insertToRelativePos(Pos pos, int posToAdd){
    if(pos.x == 1 || pos.y == 1){
        relativePositions[posToAdd] = RelativePos.EDGE;
    }else{
        relativePositions[posToAdd] = RelativePos.CORNER;
    }
}

private enum RelativePos{
    CORNER, EDGE
}
}

```

Edit: I added a better mimic system. Wolves still don't well as they don't attempt to avoid anything at the moment while continuously moving around.

# Answer
> 12 votes
# WhenIGrowUp

When this wolf grows up, it wants to be a Lion. So it randomly walks around looking for Lions to follow their footsteps and learn how to be a Lion.

This wolf was designed as a counter to the wolves that swap places with Lions.

```
package animals;

import java.util.Random;

/**
 *
 * @author Quincunx
 */
public class WhenIGrowUp extends Animal {

    Random r;
    boolean following;
    boolean toggle;

    public WhenIGrowUp() {
        super('W');
        r = new Random();
        following = false;
        toggle = false;
    }

    @Override
    public Attack fight(char c) {
        switch (c) {
            case 'B':
                return Attack.SCISSORS;
            case 'L':
            case 'S':
                return Attack.PAPER;
            default:
                return Attack.values()[r.nextInt(4)];
        }
    }

    @Override
    public Move move() {
        if (surroundings[1][2] == 'L') {
            return Move.RIGHT;
        }
        if (surroundings[2][1] == 'L') {
            return Move.DOWN;
        }
        Move direction = Move.values()[r.nextInt(5)];
        out:
        for (int y = 0; y < 3; y++) {
            for (int x = 0; x < 3; x++) {
                if (surroundings[y][x] == 'L') {
                    if (y == 0 && x == 1) {
                        direction = Move.UP;
                    } else if (y == 1 && x == 0) {
                        direction = Move.LEFT;
                    } else {
                        direction = Move.HOLD;
                    }
                    break out;
                }
            }
        }
        return direction;
    }
}

```

# Answer
> 12 votes
# MultiWolf (Java)

This wolf knows about other wolves in this programming challenge. It instantiates them (as 'pets') if they're available and uses them to determine what to do by asking every wolf-pet it owns and chooses the most popular response.

This wolf should be infinite-recursion-safe - i.e. if someone else implements a similar concept - and will return a default action of `Attack.ROCK`/`Move.HOLD` if it detects being called while it is calling other animals.

In my tests, this has had varying results. I'm not sure if this will be allowed or not. But if it is, and some impossible miracle occurs causing it to win, I think the winning title should be passed on to the wolf that comes "second" - it's only fair, I probably stole its logic.

It avoids suicide.

**Edit** \- I believe this Wolf will need to be loaded after the wolves it references to function properly.

```
package animals;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map.Entry;

public class MultiWolf extends Animal {

    private static final LinkedList<Animal> pets = new LinkedList<>();
    private static boolean inPetCall = false;

    private static void attemptLoadPet(String className) {
        try {
            Object pet = Class.forName(className).newInstance();

            if (pet instanceof Animal) {
                pets.add((Animal) pet);
            }
        } catch (Exception ex) {
            // this wolf is not available
            System.out.println(className + " is not available for MultiWolf cheating.");
        }
    }

    static {
        attemptLoadPet("animals.AlphaWolf");
        attemptLoadPet("animals.CamperWolf");
        attemptLoadPet("animals.GamblerWolf");
        attemptLoadPet("animals.GatheringWolf");
        attemptLoadPet("animals.LazyWolf");
        attemptLoadPet("animals.Sheep");
        attemptLoadPet("animals.Wion");

        attemptLoadPet("animals.MOSHPITFRENZYWolf");
        attemptLoadPet("animals.PassiveAgressiveWolf");
        attemptLoadPet("animals.StoneEatingWolf");
        attemptLoadPet("animals.HerjanWolf");
        attemptLoadPet("animals.HonorWolf");
        attemptLoadPet("animals.MimicWolf");
        attemptLoadPet("animals.LionHunterWolf");
        attemptLoadPet("animals.OmegaWolf");
        attemptLoadPet("animals.WolfWithoutFear");
        attemptLoadPet("animals.WolfRunningWithScissors");
        // attemptLoadPet("animals.SmartWolf");
        // According to Rusher, the above cheating of a non-Java wolf breaks the non-Java-entry wrapper.
        attemptLoadPet("animals.ShadowWolf");
        attemptLoadPet("animals.HybridWolf");
        attemptLoadPet("animals.ProAlpha");
        attemptLoadPet("animals.ForrestWolf");
        attemptLoadPet("animals.WhenIGrowUp");
        attemptLoadPet("animals.MigratingWolf");
        attemptLoadPet("animals.BlindWolf");
    }

    public MultiWolf() {
        super('W');
    }

    @Override
    public Attack fight(char opponent) {
        if (inPetCall) {
            // stop infinite recursion
            return Attack.ROCK;
        }

        inPetCall = true;

        HashMap<Attack, Integer> collect = new HashMap<>();

        collect.put(Attack.ROCK, 0);
        collect.put(Attack.PAPER, 0);
        collect.put(Attack.SCISSORS, 0);
        collect.put(Attack.SUICIDE, -9001);

        for (Animal a : pets) {
            a.surroundings = this.surroundings;
            Attack atk = a.fight(opponent);
            collect.put(atk, collect.get(atk)+1);
        }

        int top=0;
        Attack atk=Attack.ROCK;

        for (Entry<Attack, Integer> ent : collect.entrySet()) {
            if (ent.getValue() > top) {
                atk = ent.getKey();
                top = ent.getValue();
            }
        }

        inPetCall = false;

        return atk;
    }

    @Override
    public Move move() {
        if (inPetCall) {
            // stop infinite recursion
            return Move.HOLD;
        }

        inPetCall = true;

        HashMap<Move, Integer> collect = new HashMap<>();

        collect.put(Move.DOWN, 0);
        collect.put(Move.HOLD, 0);
        collect.put(Move.LEFT, 0);
        collect.put(Move.RIGHT, 0);
        collect.put(Move.UP, 0);

        for (Animal a : pets) {
            a.surroundings = this.surroundings;
            Move mv = a.move();
            collect.put(mv, collect.get(mv)+1);
        }

        int top=0;
        Move mv=Move.HOLD;

        for (Entry<Move, Integer> ent : collect.entrySet()) {
            if (ent.getValue() > top) {
                mv = ent.getKey();
                top = ent.getValue();
            }
        }

        inPetCall = false;

        return mv;
    }

}

```

# Answer
> 12 votes
Not an entry, but since most of the wolves are just stationary, it's actually quite boring to watch, so I added a natural disaster into the Wild:

## Earthquake!

About 5% of the time, an earthquake will happen with random magnitude, 100 being the highest, 20 the lowest. This will set an `earthquakeCounter` which will decrease exponentially over time after an earthquake.

### What happen during an earthquake?

All Animals will have a chance to move randomly, depending on the value of `earthquakeCounter`. So if the value is 75, about 75% of the Animals (including Stones) will move randomly to any direction (distributed evenly).

This, non-surprisingly, kills many of the animals, so the maximum is usually about 50 animals after a few trials.

Also, the earthquake will be visualized in the GUI, which varies depending on the magnitude.

### I can't see the earthquake!

The chance for an earthquake to happen is quite slim, only 5%.

But fret not! I've also included **an "Earthquake!" button** on the GUI, in case you want to nudge all the Wolves from their comfort zones...

Here is a screenshot:

Here is the code:

**Wild.java**

`main()` function (updated to skip the GUI for the first 100 iteration to speed up):

```
public static void main(String[] args) {

    int size = Math.round((float)Math.sqrt(classes.length+3)*20);
    final Game game = new Game(size);

    Statistics stats = new Statistics(game, classes);

    String[] colors = generateColors(classes.length);
    int idx = 0;
    for(Class c : classes){
        Animal.setColor(c, colors[idx]);
        idx++;
        game.populate(c, 100);
    }
    stats.update();

    JFrame gui = new JFrame();
    Container pane = gui.getContentPane();

    JLabel boardLabel = new JLabel();
    boardLabel.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
    boardLabel.setText(game.toString());
    pane.add(boardLabel, BorderLayout.WEST);

    JLabel statsLabel = new JLabel();
    statsLabel.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12));
    statsLabel.setText(stats.toString());
    pane.add(statsLabel, BorderLayout.EAST);

    JButton earthquakeButton = new JButton();
    earthquakeButton.addActionListener(new ActionListener(){

        @Override
        public void actionPerformed(ActionEvent e) {
            game.earthquake(true);
        }

    });
    earthquakeButton.setText("Earthquake!");
    pane.add(earthquakeButton, BorderLayout.SOUTH);

    gui.pack();
    gui.setVisible(true);

    for(int i=0; i<100; i++){
        game.iterate();
        stats.update();
    }

    while(true) {
        game.iterate();
        stats.update();
        boardLabel.setText(game.toString());
        statsLabel.setText(stats.toString());
        try { Thread.sleep(100); } catch (InterruptedException e) {}
    }
}

```

**Game.java**

```
package wild;

import animals.Animal;
import java.util.ArrayList;
import java.util.Random;
import animals.Animal.Attack;
import animals.Animal.Move;

public class Game {

    private ArrayList<ArrayList<ArrayList<Animal>>> board;
    private final Random gen = new Random();
    protected final int SIZE;
    private static int earthquakeCounter = 0;

    protected Game(int size) {
        this.SIZE = size;
        board = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            board.add(new ArrayList<ArrayList<Animal>>());
            for (int j = 0; j < size; j++) {
                board.get(i).add(new ArrayList<Animal>());
            }
        }
    }

    protected <T extends Animal> void populate(Class<T> species, int num) {
        while (num > 0) {
            int row = gen.nextInt(SIZE);
            int col = gen.nextInt(SIZE);
            if (board.get(row).get(col).isEmpty()) {
                try { board.get(row).get(col).add(species.newInstance()); }
                catch (InstantiationException | IllegalAccessException e) {}
                num--;
            }
        }
    }

    protected void iterate() {
        earthquake(false);
        moveAll();
        flatten();
    }

    private void moveAll() {
        Game game = new Game(SIZE);
        for (int i = 0; i < SIZE; i++) {
            for (int j = 0; j < SIZE; j++) {
                if (!board.get(i).get(j).isEmpty()) {
                    Animal a = board.get(i).get(j).get(0);
                    a.surroundings = getArea(i, j);
                    Move aMove;
                    try { aMove = a.move(); }
                    catch (Exception e) { aMove = Move.HOLD; }
                    if(gen.nextInt(100)<earthquakeCounter){
                        aMove = Move.values()[gen.nextInt(4)];
                    }
                    switch(aMove) {
                        case UP:
                            game.board.get((i-1+SIZE)%SIZE).get(j).add(a);
                            break;
                        case RIGHT:
                            game.board.get(i).get((j+1)%SIZE).add(a);
                            break;
                        case DOWN:
                            game.board.get((i+1)%SIZE).get(j).add(a);
                            break;
                        case LEFT:
                            game.board.get(i).get((j-1+SIZE)%SIZE).add(a);
                            break;
                        case HOLD:
                            game.board.get(i).get(j).add(a);
                            break;
                    }
                }
            }
        }
        board = game.board;
    }

    /**
     * Give a random chance for an earthquake to happen
     */
    protected void earthquake(boolean force){
        if(force || (earthquakeCounter==0 && gen.nextInt(1000)>950)){
            earthquakeCounter = 20+gen.nextInt(80);
        } else {
            earthquakeCounter /= 2;
        }
    }

    private void flatten() {
        for (ArrayList<ArrayList<Animal>> row : board) {
            for (ArrayList<Animal> cell : row) {
                while (cell.size() > 1) {
                    int rand1, rand2;
                    rand1 = gen.nextInt(cell.size());
                    do { rand2 = gen.nextInt(cell.size()); } while (rand1 == rand2);

                    Animal a = cell.get(rand1);
                    Animal b = cell.get(rand2);
                    Attack aTack, bTack;
                    try { aTack = a.fight(b.letter); }
                    catch (Exception e) { aTack = Attack.SUICIDE; }
                    try {  bTack = b.fight(a.letter); }
                    catch (Exception e) { bTack = Attack.SUICIDE; }

                    if (aTack == bTack) {
                        cell.remove((Animal)(Math.random() > 0.5 ? a : b));
                    } else {
                        switch (aTack) {
                            case ROCK:
                                cell.remove((Animal)(bTack == Attack.PAPER ? a : b));
                                break;
                            case PAPER:
                                cell.remove((Animal)(bTack == Attack.SCISSORS ? a : b));
                                break;
                            case SCISSORS:
                                cell.remove((Animal)(bTack == Attack.ROCK ? a : b));
                                break;
                        }
                    }
                }
            }
        }
    }

    protected int poll(Class c) {
        int count = 0;
        for (ArrayList<ArrayList<Animal>> row : board) {
            for (ArrayList<Animal> cell : row) {
                for (Animal a : cell) {
                    if(c.isInstance(a))
                        count++;
                }
            }
        }
        return count;
    }

    public String toString() {
        String s = "<html>";
        s += "<span style='background:"+getBackgroundColor()+"'>";
        for (ArrayList<ArrayList<Animal>> row : board) {
            for (ArrayList<Animal> cell : row) {
                if (cell.isEmpty())
                    s += "  ";
                else
                    s += "<span style='color:"+ Animal.color.get(cell.get(0).getClass()) +"'>" + cell.get(0).letter + "</span> ";
            }
            s+="<br>";
        }
        s += "</span>";
        return s + "</html>";
    }

    private String getBackgroundColor(){
        int shade = 255-(int)Math.floor(255*earthquakeCounter/100.0);
        String result = String.format("#%02x%02x%02x", shade, shade, shade);
        return result;
    }

    private char[][] getArea(int i, int j) {
        char[][] area = new char[3][3];
        for(int k = -1; k <= 1; k++) {
            for(int l = -1; l <= 1; l++) {
                int temp1 = k+1;
                int temp2 = l+1;
                int temp3 = (i+k+SIZE)%SIZE;
                int temp4 = (j+l+SIZE)%SIZE;
                ArrayList<Animal> cell = board.get((i+k+SIZE)%SIZE).get((j+l+SIZE)%SIZE);
                area[k+1][l+1] = (char)(cell.isEmpty() ? ' ' : cell.get(0).letter);
            }
        }
        return area;
    }
}

```

# Answer
> 11 votes
# HonorWolf

My Wolf is fleeing from the other wolves. If he can't run away, he honorful starts a fight.

```
package animals;
public class HonorWolf extends Animal {

    private int moves = 0;

    public HonorWolf() {
        super('W');
    }

    @Override
    public Attack fight(char opponent) {
        switch(opponent) {
         case 'L':
            return Attack.SCISSORS;
         case 'B':
            return Attack.SCISSORS;
         case 'S':
            return Attack.PAPER;
        default:
            return Attack.PAPER;
        }
    }

    public Move move() {
        int numWolves = 0, numLions = 0;

        moves++;

        for (int y = 0; y != 3; y++) {
            for (int x = 0; x != 3; x++) {
                if(surroundings[y][x] != ' ') {
                    if(surroundings[y][x] == 'W') {
                        numWolves++;
                    } else if(surroundings[y][x] == 'L') {
                        numLions++;
                    }
                }
            }
        }

        if (numWolves == 1 && numLions == 0) {
            return Move.HOLD;
        }

        if (surroundings[0][1] == 'L' && moves%2 != 0) {
            return Move.UP;
        }

        if (surroundings[1][0] == 'L' && moves%2 == 0) {
            return Move.LEFT;
        }

        if (surroundings[0][1] == 'W') {
            if (surroundings[2][1] == ' ' || surroundings[2][1] == 'S') {
                return Move.DOWN;
            } else if (surroundings[1][2] == ' ' || surroundings[1][2] == 'S') {
                return Move.RIGHT;
            } else if (surroundings[1][0] == ' ' || surroundings[1][0] == 'S') {
                return Move.LEFT;
            } else {
                return Move.UP;
            }
        }

        if (surroundings[1][0] == 'W') {
            if (surroundings[1][2] == ' ' || surroundings[1][2] == 'S') {
                return Move.RIGHT;
            } else if (surroundings[0][1] == ' ' || surroundings[0][1] == 'S') {
                return Move.UP;
            } else if (surroundings[2][1] == ' ' || surroundings[2][1] == 'S') {
                return Move.DOWN;
            } else {
                return Move.LEFT;
            }
        }

        if (surroundings[1][2] == 'W') {
            if (surroundings[1][0] == ' ' || surroundings[1][0] == 'S') {
                return Move.LEFT;
            } else if (surroundings[0][1] == ' ' || surroundings[0][1] == 'S') {
                return Move.UP;
            } else if (surroundings[2][1] == ' ' || surroundings[2][1] == 'S') {
                return Move.DOWN;
            } else {
                return Move.RIGHT;
            }
        }

        if (surroundings[2][1] == 'W') {
            if (surroundings[0][1] == ' ' || surroundings[0][1] == 'S') {
                return Move.UP;
            } else if (surroundings[1][0] == ' ' || surroundings[1][0] == 'S') {
                return Move.LEFT;
            } else if (surroundings[1][2] == ' ' || surroundings[1][2] == 'S') {
                return Move.RIGHT;
            } else {
                return Move.DOWN;
            }
        }

        return Move.HOLD;
    }
}

```

# Answer
> 11 votes
# The Blind Wolf

The blind wolf is afraid to move and never knows what it is fighting. By playing scissors every time it has the best odds, as it will never run into a *real* stone.

```
package animals;

public class BlindWolf extends Animal {
    public BlindWolf() { super('W'); }

    @Override
    public Attack fight(char c) {
        return Attack.SCISSORS;
    }

    @Override
    public Move move() {
        return Move.HOLD;
    }
}

```

# Answer
> 11 votes
# SpyWolf

SpyWolf spies on it's enemies and logs their activity so that it can keep tabs on everyone while keeping it's distance. Wouldn't want to be found out!

```
package animals;

import static animals.Animal.Attack.*;
import static animals.Animal.Move.*;

import java.awt.Point;
import java.util.*;

public class SpyWolf extends Animal {

    private static final Random r = new Random();
    private static boolean hasTestedPRNG = false;
    private static int PRNG = -1;
    private boolean lionTracker = true;
    private boolean useScissors = false;

    private final ArrayList<MapTile> map = new ArrayList<MapTile>();
    private final Point location = new Point();

    public SpyWolf() {
        super('W');
    }

    @Override
    public Animal.Attack fight(char opponent) {
        switch (opponent) {
            case 'B':
            case 'L':
                return SCISSORS;
            case 'S':
                return PAPER;
            default:
                if (useScissors) {
                    useScissors = false;
                    return SCISSORS;
                }
                return PAPER;
        }
    }

    @Override
    public Animal.Move move() {

        Move m = HOLD;

        if (!hasTestedPRNG) {
            hasTestedPRNG = true;
            double d = 0;
            for (int i = 0; i < 100; i++)
                d += Math.random();
            if (d > 99) {
                PRNG = 1;
            } else if (d > 30 && d < 70) PRNG = 0;
        }

        lionTracker = !lionTracker;
        boolean adj = false;

        updateMap();

        scan: {
            if (PRNG < 1) {
                if (look(LEFT) == 'L' && !lionTracker) {
                    useScissors = true;
                    m = LEFT;
                    break scan;
                }

                if (look(UP) == 'L' & lionTracker) {
                    useScissors = true;
                    m = UP;
                    break scan;
                }
            }

            int x = 0, y = 0;
            ArrayList<Move> moves = new ArrayList<Move>(4);

            for (Move i : Move.values())
                moves.add(i);

            if (look(UP) == 'W') {
                y += 54;
                moves.remove(UP);
                adj = true;
            }
            if (look(DOWN) == 'W') {
                y -= 54;
                moves.remove(DOWN);
                adj = true;
            }
            if (look(LEFT) == 'W') {
                x += 54;
                moves.remove(LEFT);
                adj = true;
            }
            if (look(RIGHT) == 'W') {
                x -= 54;
                moves.remove(RIGHT);
                adj = true;
            }

            if (moves.isEmpty() || !adj) break scan;

            for (MapTile t : map) {
                if (t.x >= location.x - 2 && t.x <= location.x + 2 && t.y >= location.y - 2 && t.y <= location.y + 2 && t.d) {
                    int dist = Math.abs(t.x - location.x) + Math.abs(t.y - location.y);
                    y += t.y > location.y ? -60 / dist : 60 / dist;
                    x += t.x < location.x ? 60 / dist : -60 / dist;
                }
            }
            m = moveDir(x, y);
            if (!moves.contains(m)) m = HOLD;
        }
        switch (m) {
            case UP:
                location.y--;
                return m;
            case DOWN:
                location.y++;
                return m;
            case LEFT:
                location.x--;
                return m;
            case RIGHT:
                location.x++;
                return m;
            default:
                return m;
        }
    }

    private void updateMap() {
        for (int y = -1; y < 2; y++)
            xloop: for (int x = -1; x < 2; x++) {
                if (x == 0 && y == 0) continue;
                for (MapTile t : map)
                    if (t.x == x + location.x && t.y == y + location.y) {
                        t.d = surroundings[y + 1][x + 1] == 'W';
                        continue xloop;
                    }
                map.add(new MapTile(x + location.x, y + location.y, surroundings[y + 1][x + 1] == 'W'));
            }
    }

    private Move moveDir(int x, int y) {
        if (x == 0) return y < 0 ? UP : y > 0 ? DOWN : HOLD;
        if (y == 0) return x < 0 ? LEFT : RIGHT;
        if (x < 0) {
            if (y < 0) {
                if (y < x)
                    return UP;
                else if (x < y) return LEFT;
                return r.nextBoolean() ? UP : LEFT;
            } else {
                if (-y < x)
                    return DOWN;
                else if (x < -y) return LEFT;
                return r.nextBoolean() ? DOWN : LEFT;
            }
        }
        if (y < 0) {
            if (y < -x)
                return UP;
            else if (-x < y) return RIGHT;
            return r.nextBoolean() ? UP : RIGHT;
        } else {
            if (y > x)
                return DOWN;
            else if (x < y) return RIGHT;
        return r.nextBoolean() ? DOWN : RIGHT;
        }
    }

    private char look(Move direction) {
        switch (direction) {
            case UP:
                return surroundings[0][1];
            case DOWN:
                return surroundings[2][1];
            case LEFT:
                return surroundings[1][0];
            case RIGHT:
                return surroundings[1][2];
            default:
                return surroundings[1][1];
        }
    }

    private static class MapTile {
        int x, y;
        boolean d;

        MapTile(int x, int y, boolean d) {
            this.x = x;
            this.y = y;
            this.d = d;
        }
    }
}

```

It fares pretty well, but that lame HybridWolf is too cheaty! SpyWolf may go back to spy school and train advanced anti-wolf techniques, we'll see.

# Answer
> 9 votes
# HybridWolf

I couldn't resist but to make another wolf. This one is very different (in its code, not in its behaviour), as it chooses the attack/move, which other good wolves would do.
<sub>Of course all wolves are good, but I mean the ones with the most points :)</sub>

```
package animals;

import java.util.ArrayList;
import java.util.Random;

public class HybridWolf extends Animal{
    private final Class[] classes = {ProAlpha.class, OmegaWolf.class, SpyWolf.class, HerjanWolf.class, DeepWolf.class, ProtoWolf.class};
    private final ArrayList<Animal> wolves = new ArrayList<Animal>();

    public HybridWolf() {
        super('W');
        for(Class c: classes) {
            try {
                wolves.add((Animal)c.newInstance());
            } catch (Exception ex) {}
        }
    }

    @Override
    public Attack fight(char opponent) {
        switch(opponent){
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S':
            return Attack.PAPER;
        default:
            try {
                int[] attacks = new int[3];
                Attack bestAttack = randomAttack();
                for(Animal wolf : wolves) {
                    wolf.surroundings = this.surroundings;
                    attacks[wolf.fight(opponent).ordinal()]++;
                }
                for(int i =0; i < 5; i++) {
                    if(attacks[i] > attacks[bestAttack.ordinal()]) {
                        bestAttack = Attack.values()[i];
                    }
                }
                return bestAttack;
            } catch (Exception e) {
                return randomAttack();
            }
        }
    }

    @Override
    public Move move() {
        try {
            int[] moves = new int[5];
            Move bestMove = Move.HOLD;
            for(Animal wolf : wolves) {
                wolf.surroundings = this.surroundings;
                moves[wolf.move().ordinal()]++;
            }
            for(int i =0; i < 5; i++) {
                if(moves[i] > moves[bestMove.ordinal()]) {
                    bestMove = Move.values()[i];
                }
            }
            return bestMove;
        } catch (Exception e) {
            return Move.HOLD;
        }
    }

    public Attack randomAttack() {
        Random rand = new Random();
        switch (rand.nextInt(3)){
            case 1: return Attack.SCISSORS;
            case 2: return Attack.ROCK;
            default: return Attack.PAPER;
        }
    }

}

```

It my tests it scores better than my previous AlphaWolf, but Omega/Honor/ProAlpha sometimes beat me... The more good submissions are here, the better this wolf will get :D

# Answer
> 9 votes
# EvoWolf

All you silly intelligently designed wolves! EvoWolf lives in the Wild with other tough wolves like DeepWolf and HerjanWolf so it had to evolve to survive.

The code uses a genetic algorithm to evolve the best wolf (I didn't notice LionHunterWolf until I was grabbing Wolves to train against). The are different genes for each animal/attack combo, movement direction when safe, and movement direction for each animal in a surrounding. After 1000 rounds, the wolves which lasted the highest number of turns have the highest probability of producing offspring (i.e. the longer you live the more chances you get to mate). We also throw in a random mutation in about 10% of children an hope it helps.

Here is the EvoWolf code, **YOU WILL ALSO NEED evowolf.txt IN YOUR WORKING DIRECTORY - IT CONTAINS THE CURRENT GENEPOOL.** If you want to evolve your own wolves from primordial randomness, don't include evowolf.txt but the one provided is currently the best evolution. It's really neat to watch it evolve, at the beginning only 2-3 survive but then it gets up to 60.

```
package animals;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.Random;

public class EvoWolf extends Animal {
    public EvoWolf() { super('W'); birth();}
    public Attack fight(char c) {
        List<Attack> attacks = getAttacks(c);
        if(attacks.size() == 0)
            return Attack.SUICIDE; //Discourage wolves without attacks, Darwin Award

        return attacks.get(random.nextInt(attacks.size()));
    }

    public Move move() {
        ++turns;
        List<Move> moves = new ArrayList<Move>();
        if(isSafe())
            moves = getSafeMoves();
        else
            moves = getThreatenedMoves();

        return (Move)moves.toArray()[random.nextInt(moves.size())];
    }

    /*====STATIC METHODS====*/
    //Shared RNG
    public static Random random = new Random();

    //Collection of 100 sets of genes
    public static String[] genePool = null;

    //Get the genes from disk or randomly generate some
    public static void readGenePool(){
        genePool = new String[100];
        int gIdx = 0;
        try (BufferedReader br = new BufferedReader(new FileReader("evowolf.txt"))){
            String sCurrentLine;
            while ((sCurrentLine = br.readLine()) != null) {
                genePool[gIdx] = sCurrentLine;
                ++gIdx;
            }
        } catch (IOException e) {

        }

        //if can't read genes, make some
        if(gIdx < 100){
            primordial(gIdx);
        }
    }
    public static void primordial(int idx){
        for(;idx < 100; ++idx){
            genePool[idx] = getRandomGenes();
        }
    }

    public static String getRandomGenes(){
        StringBuilder sb = new StringBuilder();
        for(int idx = 0; idx < GENE_COUNT; ++idx){
            if(random.nextBoolean())
                sb.append("1");
            else
                sb.append("0");
        }
        return sb.toString();
    }

    //Evolve wolves
    public static void nextGen(){
        //Check survival of current gen
        int survivors = 0;
        for(int idx = 0; idx < 100; ++idx){
            survivors = survivors + (generation[idx].turns == 1000 ? 1 : 0);
        }
        if(survivors > 65)
            writeGenePool(Long.toString(survivors));

        //Weighted resivour sampling
        //Take the highest of r^(1/w) where r is a random an w is the weight
        for(int idx = 0; idx < 100; ++idx){
            genePool[idx] = mateFitWolves();
        }
        writeGenePool("");
        birthCount = 0;
    }

    //Pick two wolves randomly by weighted fitness and mate them
    public static String mateFitWolves(){
        EvoWolf w1 = null;
        double weight1 = -1;
        EvoWolf w2 = null;
        double weight2 = -1;

        for(int idx = 0; idx < 100; ++idx){
            double weight = generation[idx].getWeightSample();
            if(weight > weight1){
                weight2 = weight1;
                w2 = w1;
                weight1 = weight;
                w1 = generation[idx];
            } else if(weight > weight2){
                weight2 = weight;
                w2 = generation[idx];
            }
        }

        return mateFitWolves(w1, w2);
    }

    //Make offspring
    public static String mateFitWolves(EvoWolf w1, EvoWolf w2){
        StringBuilder sb = new StringBuilder();
        //Random splice
        for(int rIdx = 0; rIdx < w1.genes.length(); ++rIdx){
            if(random.nextBoolean())
                sb.append(w1.genes.charAt(rIdx));
            else
                sb.append(w2.genes.charAt(rIdx));
        }

        //Random mutation
        while(random.nextInt(10) == 0){
            int mIdx = random.nextInt(w1.genes.length());
            if(sb.charAt(mIdx) == '0')
                sb.setCharAt(mIdx, '1');
            else
                sb.setCharAt(mIdx, '0');
        }

        return sb.toString();
    }

    //Save the next generation's gene pool back to disk
    public static void writeGenePool(String survivors){
        try {
            String str = "";
            if(!survivors.equals(""))
                str = Long.toString(System.currentTimeMillis());

            File file = new File("evowolf" + survivors + str + ".txt");

            // if file doesn't exists, then create it
            if (!file.exists()) {
                file.createNewFile();
            }

            FileWriter fw = new FileWriter(file.getAbsoluteFile());
            BufferedWriter bw = new BufferedWriter(fw);
            for(int gIdx = 0; gIdx < genePool.length; ++gIdx){
                bw.write(genePool[gIdx]);
                bw.write('\n');
            }
            bw.close();
        } catch (IOException e) {

        }
    }

    //Keep track of the wolves in this generation
    public static int birthCount = 0;
    public static EvoWolf[] generation = new EvoWolf[100];

    /*====INSTANCE METHODS====*/
    //Populate this wolf from the gene pool
    public void birth(){
        if(genePool == null){
            readGenePool();
        }
        genes = genePool[birthCount];
        generation[birthCount] = this;
        birthCount = (birthCount + 1) % 100;
    }

    //How long wolf has been alive
    public int turns = 0;

    //Fitness based on how long wolf survived
    public double getWeightSample(){
        return Math.pow(random.nextDouble(), 1.0/turns);
    }

    /*===GENETICS===*/
    public String genes = null;
    //Genes are made up of 182+ bits (stored at a string)
    //Each turns on the possibility of that move or attack in a given situation
    //  Attack: BLSW * RPSX = 16 bits [0-15] = Animal->Attacks
    //  Threatened Moves: BLSW * 12345678 * UDLRH = 160 bits [16-175] = Y -> X -> Animal -> Moves
    //  Safe Moves: UDLRH = 5 bits [176-180] = Moves
    //  Extra: default move [181], move combination [182]
    public static final int GENE_INDEX_ATTACKS = 0;
    public static final int GENE_INDEX_THREATENED_MOVES = GENE_INDEX_ATTACKS + (4 * 4);
    public static final int GENE_INDEX_SAFE_MOVES = GENE_INDEX_THREATENED_MOVES + (8 * 4 * 5);
    public static final int GENE_INDEX_DEFAULT_MOVE = GENE_INDEX_SAFE_MOVES + (5);
    public static final int GENE_INDEX_COMBINE_MOVES = GENE_INDEX_DEFAULT_MOVE + (1);
    public static final int GENE_COUNT = GENE_INDEX_COMBINE_MOVES + 1;
    public static int getAnimalIndex(char c){
        switch (c) {
            case 'B':
                return 0;
            case 'L':
                return 1;
            case 'S':
                return 2;
            case 'W':
            default: //Shouldn't occur but we'll assume it's the dangerous wolf
                return 3;
        }
    }

    public static int getXYIndex(int x, int y){
        int idx = (y * 3) + x;
        if(idx > 4) //We don't need to look at ourself
            --idx;
        return idx;
    }

    public List<Attack> getAttacks(char c){
        List<Attack> attacks = new ArrayList<Attack>();
        int idx = GENE_INDEX_ATTACKS + getAnimalIndex(c);
        if(genes.charAt(idx + 0) == '1')
            attacks.add(Attack.ROCK);
        if(genes.charAt(idx + 1) == '1')
            attacks.add(Attack.PAPER);
        if(genes.charAt(idx + 2) == '1')
            attacks.add(Attack.SCISSORS);
        /*
        if(genes.charAt(idx + 3) == '1')
            attacks.add(Attack.SUICIDE);
        */
        //Suicide didn't remove itself from the gene pool like I thought so I manually removed it

        return attacks;
    }

    public boolean isSafe(){
        for(int x = 0; x <= 2; ++x){
            for(int y = 0; y <= 2; ++y){
                if(y == 1 && x == 1)
                    continue;
                if(surroundings[y][x] != ' ')
                    return false;
            }
        }
        return true;
    }

    public List<Move> getSafeMoves(){
        List<Move> moves = new ArrayList<Move>();
        int idx = GENE_INDEX_SAFE_MOVES;
        if(genes.charAt(idx + 0) == '1')
            moves.add(Move.UP);
        if(genes.charAt(idx + 1) == '1')
            moves.add(Move.DOWN);
        if(genes.charAt(idx + 2) == '1')
            moves.add(Move.LEFT);
        if(genes.charAt(idx + 3) == '1')
            moves.add(Move.RIGHT);
        if(genes.charAt(idx + 4) == '1')
            moves.add(Move.HOLD);

        return moves;
    }

    public List<Move> getThreatenedMoves(){
        List<Move> moves = new ArrayList<Move>();
        if(genes.charAt(GENE_INDEX_COMBINE_MOVES) == '0')
            moves.addAll(EnumSet.of(Move.UP, Move.DOWN, Move.LEFT, Move.RIGHT, Move.HOLD));

        for(int x = 0; x <= 2; ++x){
            for(int y = 0; y <= 2; ++y){
                if(y == 1 && x == 1)
                    continue;
                if(genes.charAt(GENE_INDEX_COMBINE_MOVES) == '1')
                    moves.addAll(getThreatenedMoves(x,y));
                else
                    moves.retainAll(getThreatenedMoves(x,y));
            }
        }

        if(moves.size() == 0){
            if(this.genes.charAt(GENE_INDEX_DEFAULT_MOVE) == '1')
                moves.addAll(EnumSet.of(Move.UP, Move.DOWN, Move.LEFT, Move.RIGHT, Move.HOLD));
            else
                moves.add(Move.HOLD);
        }

        return moves;
    }

    public EnumSet<Move> getThreatenedMoves(int x, int y){
        //Lookup what moves we can make for a cell unless it is blank (allow any)
        if(surroundings[y][x] != ' ')
            return getThreatenedMoves(x,y,surroundings[y][x]);
        else if(genes.charAt(GENE_INDEX_COMBINE_MOVES) == '1')
            return EnumSet.noneOf(Move.class);
        else
            return EnumSet.of(Move.UP, Move.DOWN, Move.LEFT, Move.RIGHT, Move.HOLD);
    }

    public EnumSet<Move> getThreatenedMoves(int x, int y, char c){
        int aIdx = getAnimalIndex(c);
        int sIdx = getXYIndex(x,y);
        int idx = GENE_INDEX_THREATENED_MOVES + (sIdx * 20) + (aIdx * 5);

        EnumSet<Move> moves = EnumSet.noneOf(Move.class);

        if(genes.charAt(idx + 0) == '1')
            moves.add(Move.UP);
        if(genes.charAt(idx + 1) == '1')
            moves.add(Move.DOWN);
        if(genes.charAt(idx + 2) == '1')
            moves.add(Move.LEFT);
        if(genes.charAt(idx + 3) == '1')
            moves.add(Move.RIGHT);
        if(genes.charAt(idx + 4) == '1')
            moves.add(Move.HOLD);

        return moves;
    }

    public static String setAt(String str, int index, char replace){
        if(str==null){
            return str;
        }else if(index<0 || index>=str.length()){
            return str;
        }
        char[] chars = str.toCharArray();
        chars[index] = replace;
        return String.valueOf(chars);
    }
}

```

I've also made some changes to Statistics.java and Wild.java just to show me how many turns and generations have passed. After you've run 1000 turns, call `EvoWolf.nextGen();` to calculate offspring. This isn't necessary for competition, only if you want to evolve your own set.

All Files Here **EDIT: FIXED LINK**

As far as evolving as the best, it kind of doesn't get any better than the top 10. Part of the limitation is it has very little memory of it's previous moves. Although it does function like WolvesWithCollectiveMemory in that the experiences of previous generations will affect how the next generation functions serving as a long term global memory. It sure was fun though. In the previous link there is an Excel sheet which can help you analyze the gene pool. Replace all 1's and 0's in the .txt with 1's and 0's with commas then paste in the spreadsheet.

Some interesting notes, most of which confirm everyone's strategies:

* The actual attacks are less important than avoiding fighting. Or maybe all the non-wolves get eliminated quickly so they aren't a threat. The competition generation has an even chance between RPS against bears even though you should throw S.
* Like the above, I had to manually disable suicide since it wasn't evolving out even though you think it would.
* Holding is the best move when no one is around
* Running away seems to be good too when someone is around
* You should hold instead of moving a random direction (this choice was an extra gene that evolved out)
* When more than 1 animal is around, taking a random move out of the intersection of moves for each surrounding/animal is better than the union (another extra gene)

# Answer
> 8 votes
# SmartWolf

The results are in(1000 iterations)(I'll keep updating this but view it as an independent test with no averaging because with that many wolves it is quite slow).

**Compilation:**

\*nix(Mono is required):

```
gmcs SmartWolf.cs

```

Windows:

```
csc SmartWolf.cs

```

Copy to working directory.

**Note:** When using Windows, you need to replace `"mono SmartWolf.exe"` with just `"SmartWolf.exe"` in the wrapper code.

SmartWolf.cs:

```
using System;
using System.Collections.Generic;
using System.Linq;

namespace SmartWolf
{
    #region Enums
    enum Attack
    {
        Rock, Paper, Scissors, Suicide
    }
    enum Movement
    {
        Up, Down, Left, Right, Hold
    }
    enum Animal
    {
        Stone, Lion, Wolf, Bear, Empty
    }
    #endregion
    class KnowledgeBase
    {
        static Random rnd = new Random();
        public List<KeyValuePair<KeyValuePair<Animal, Attack>, int>> knowledge = new List<KeyValuePair<KeyValuePair<Animal, Attack>, int>>();
        public KnowledgeBase ()
        {
        }
        public void PunishMove (KeyValuePair<Animal, Attack> move)
        {
            if (knowledge.Count (t => t.Key.Key == move.Key && t.Key.Value == move.Value) == 0) {
                knowledge.Add (new KeyValuePair<KeyValuePair<Animal, Attack>, int> (move, -1));
            } else {
                int i = knowledge.FindIndex (t => t.Key.Equals (move));
                knowledge[i] = new KeyValuePair<KeyValuePair<Animal, Attack>, int>(knowledge[i].Key, knowledge[i].Value - 1);
            }

        }
        public void RewardMove (KeyValuePair<Animal, Attack> move)
        {
            if (knowledge.Count (t => t.Key.Key == move.Key && t.Key.Value == move.Value) == 0) {
                knowledge.Add (new KeyValuePair<KeyValuePair<Animal, Attack>, int> (move, 1));
            } else {
                int i = knowledge.FindIndex (t => t.Key.Equals (move));
                knowledge[i] = new KeyValuePair<KeyValuePair<Animal, Attack>, int>(knowledge[i].Key, knowledge[i].Value + 1);
            }
        }
        public Attack GetBestMove (Animal opponent)
        {
            Attack best = GetRandomMove();
            int j = 0;
            foreach (var pair in knowledge) {
                if(pair.Key.Key == opponent && j < pair.Value)
                {
                    best = pair.Key.Value;
                    j = pair.Value;
                }
            }
            if(j < 2)
                return GetRandomMove ();
            return best;
        }
        public static Attack GetRandomMove()
        {
            int r = rnd.Next (3);
            return r == 0 ? Attack.Paper :
                r == 1 ? Attack.Rock :
                    r == 2 ? Attack.Scissors :
                    Attack.Scissors;
        }
    }
    class MainClass
    {
        static KnowledgeBase knowledge = new KnowledgeBase();
        public static void Main (string[] args)
        {
            List<SmartWolf> list = new List<SmartWolf> ();
            List<int> temp = new List<int>();
            int l = 0;
            while (true) {
                string str = Console.ReadLine ();
                int id = int.Parse (str.Substring (1, 2));
                if(str.StartsWith ("S"))
                {
                    list.Add (new SmartWolf(id));
                    Console.WriteLine("K" + id.ToString ().PadLeft (2, '0'));
                } else if(str.StartsWith ("M"))
                {
                    if(temp.Contains (id))
                    {
                        for(int i = 0; i < 100; i++)
                        {
                            SmartWolf s = list.Where (t => t.ID == i).ToList ()[0];
                            if(s.AttackedInLastRound == 0 && !temp.Contains(i))
                            {
                                s.IsAlive = false;
                                knowledge.PunishMove (s.LastMove);
                                s.AttackedInLastRound = -1;
                            } else if(s.AttackedInLastRound == 0 && temp.Contains (i))
                            {
                                knowledge.RewardMove (s.LastMove);
                                s.AttackedInLastRound = -1;
                            }
                            if(s.AttackedInLastRound > 0)
                                s.AttackedInLastRound--;
                        }
                        temp.Clear();
                        l++;
                    }
                    temp.Add (id);

                    Console.WriteLine('H' + id.ToString ().PadLeft (2, '0'));
                } else if(str.StartsWith ("A"))
                {
                    Animal enemy = str[3] == 'W' ? Animal.Wolf :
                                   str[3] == 'L' ? Animal.Lion :
                                   str[3] == 'S' ? Animal.Stone :
                                   str[3] == 'B' ? Animal.Bear : Animal.Empty;
                    Attack atk = knowledge.GetBestMove (enemy);
                    Console.WriteLine((atk == Attack.Paper ? "P" :
                                      atk == Attack.Rock ? "R" :
                                      atk == Attack.Scissors ? "S" :
                                      "P") + id.ToString ().PadLeft (2, '0'));
                    list.Where (t => t.ID == id).ToList ()[0].AttackedInLastRound = 2;
                    list.Where (t => t.ID == id).ToList ()[0].LastMove = new KeyValuePair<Animal, Attack>(enemy, atk);
                }
            }
        }
    }
    class SmartWolf
    {
        public int ID;
        public bool IsAlive = true;
        public KeyValuePair<Animal, Attack> LastMove = new KeyValuePair<Animal, Attack>(Animal.Empty, Attack.Suicide);
        public int AttackedInLastRound = -1;
        public SmartWolf(int n)
        {
            ID = n;
        }
    }
}

```

Wrapper(credit to @ProgrammerDan, I'm just including it here so it's easier to just copy paste):

```
package animals;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Remote SmartWolf wrapper class.
 */
public class SmartWolf extends Animal {
    /**
     * Simple test script that sends some typical commands to the
     * remote process.
     */
    public static void main(String[]args){
        SmartWolf[] wolves = new SmartWolf[100];
        for(int i=0; i<10; i++) {
            wolves[i] = new SmartWolf();
        }
        char map[][] = new char[3][3];
        for (int i=0;i<9;i++)
            map[i/3][i%3]=' ';
        map[1][2] = 'W';
        for(int i=0; i<10; i++) {
            wolves[i].surroundings=map;
            System.out.println(wolves[i].move());
        }
        for(int i=0; i<10; i++) {
            System.out.println(wolves[i].fight('S'));
            System.out.println(wolves[i].fight('B'));
            System.out.println(wolves[i].fight('L'));
            System.out.println(wolves[i].fight('W'));
        }
        wolfProcess.endProcess();
    }
    private static WolfProcess wolfProcess = null;

    private static SmartWolf[] wolves = new SmartWolf[100];
    private static int nWolves = 0;

    private boolean isDead;
    private int id;

    /**
     * Sets up a remote process wolf. Note the static components. Only
     * a single process is generated for all Wolves of this type, new
     * wolves are "initialized" within the remote process, which is
     * maintained alongside the primary process.
     * Note this implementation makes heavy use of threads.
     */
    public SmartWolf() {
        super('W');
        if (SmartWolf.wolfProcess == null) {
            SmartWolf.wolfProcess = new WolfProcess();
            SmartWolf.wolfProcess.start();
        }

        if (SmartWolf.wolfProcess.initWolf(SmartWolf.nWolves, MAP_SIZE)) {
            this.id = SmartWolf.nWolves;
            this.isDead = false;
            SmartWolf.wolves[id] = this;
        } else {
            SmartWolf.wolfProcess.endProcess();
            this.isDead = true;
        }
        SmartWolf.nWolves++;
    }

    /**
     * If the wolf is dead, or all the wolves of this type are dead, SUICIDE.
     * Otherwise, communicate an attack to the remote process and return
     * its attack choice.
     */
    @Override
    public Attack fight(char opponent) {
        if (!SmartWolf.wolfProcess.getRunning() || isDead) {
            return Attack.SUICIDE;
        }
        try {
            Attack atk = SmartWolf.wolfProcess.fight(id, opponent);

            if (atk == Attack.SUICIDE) {
                this.isDead = true;
            }

            return atk;
        } catch (Exception e) {
            System.out.printf("Something terrible happened, this wolf has died: %s", e.getMessage());
            isDead = true;
            return Attack.SUICIDE;
        }
    }

    /**
     * If the wolf is dead, or all the wolves of this type are dead, HOLD.
     * Otherwise, get a move from the remote process and return that.
     */
    @Override
    public Move move() {
        if (!SmartWolf.wolfProcess.getRunning() || isDead) {
            return Move.HOLD;
        }
        try {
            Move mv = SmartWolf.wolfProcess.move(id, surroundings);

            return mv;
        } catch (Exception e) {
            System.out.printf("Something terrible happened, this wolf has died: %s", e.getMessage());
            isDead = true;
            return Move.HOLD;
        }
    }

    /**
     * The shared static process manager, that synchronizes all communication
     * with the remote process.
     */
    static class WolfProcess extends Thread {
        private Process process;
        private BufferedReader reader;
        private PrintWriter writer;
        private ExecutorService executor;
        private boolean running;

        public boolean getRunning() {
            return running;
        }

        public WolfProcess() {
            process = null;
            reader = null;
            writer = null;
            running = true;
            executor = Executors.newFixedThreadPool(1);
        }

        public void endProcess() {
            running = false;
        }

        /**
         * WolfProcess thread body. Keeps the remote connection alive.
         */
        public void run() {
            try {
                System.out.println("Starting SmartWolf remote process");
                ProcessBuilder pb = new ProcessBuilder("mono SmartWolf.exe".split(" "));
                pb.redirectErrorStream(true);
                process = pb.start();
                System.out.println("SmartWolf process begun");
                // STDOUT of the process.
                reader = new BufferedReader(new InputStreamReader(process.getInputStream(), "UTF-8"));
                System.out.println("SmartWolf reader stream grabbed");
                // STDIN of the process.
                writer = new PrintWriter(new OutputStreamWriter(process.getOutputStream(), "UTF-8"));
                System.out.println("SmartWolf writer stream grabbed");
                while(running){
                    this.sleep(0);
                }
                reader.close();
                writer.close();
                process.destroy(); // kill it with fire.
                executor.shutdownNow();
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("SmartWolf ended catastrophically.");
            }
        }

        /**
         * Helper that invokes a read with a timeout
         */
        private String getReply(long timeout) throws TimeoutException, ExecutionException, InterruptedException{
            Callable<String> readTask = new Callable<String>() {
                @Override
                public String call() throws Exception {
                    return reader.readLine();
                }
            };

            Future<String> future = executor.submit(readTask);
            return future.get(timeout, TimeUnit.MILLISECONDS);
        }

        /**
         * Sends an initialization command to the remote process
         */
        public synchronized boolean initWolf(int wolf, int map_sz) {
            while(writer == null){
                try {
                this.sleep(0);
                }catch(Exception e){}
            }
            boolean success = false;
            try{
                writer.printf("S%02d%d\n", wolf, map_sz);
                writer.flush();
                String reply = getReply(5000l);
                if (reply != null && reply.length() >= 3 && reply.charAt(0) == 'K') {
                    int id = Integer.valueOf(reply.substring(1));
                    if (wolf == id) {
                        success = true;
                    }
                }
                if (reply == null) {
                    System.out.println("did not get reply");
                }
            } catch (TimeoutException ie) {
                endProcess();
                System.out.printf("SmartWolf %d failed to initialize, timeout\n", wolf);
            } catch (Exception e) {
                endProcess();
                System.out.printf("SmartWolf %d failed to initialize, %s\n", wolf, e.getMessage());
            }
            return success;
        }

        /**
         * Send an ATTACK command to the remote process.
         */
        public synchronized Attack fight(int wolf, char opponent) {
            Attack atk = Attack.SUICIDE;
            try{
                writer.printf("A%02d%c\n", wolf, opponent);
                writer.flush();
                String reply = getReply(1000l);
                if (reply.length() >= 3) {
                    int id = Integer.valueOf(reply.substring(1));
                    if (wolf == id) {
                        switch(reply.charAt(0)) {
                            case 'R':
                                atk = Attack.ROCK;
                                break;
                            case 'P':
                                atk = Attack.PAPER;
                                break;
                            case 'S':
                                atk = Attack.SCISSORS;
                                break;
                            case 'D':
                                atk = Attack.SUICIDE;
                                break;
                        }
                    }
                }
            } catch (TimeoutException ie) {
                endProcess();
                System.out.printf("SmartWolf %d failed to attack, timeout\n", wolf);
            } catch (Exception e) {
                endProcess();
                System.out.printf("SmartWolf %d failed to attack, %s\n", wolf, e.getMessage());
            }
            return atk;
        }

        /**
         * Send a MOVE command to the remote process.
         */
        public synchronized Move move(int wolf, char[][] map) {
            Move move = Move.HOLD;
            try{
                writer.printf("M%02d", wolf);
                for (int row=0; row<map.length; row++) {
                    for (int col=0; col<map[row].length; col++) {
                        writer.printf("%c", map[row][col]);
                    }
                }
                writer.print("\n");
                writer.flush();
                String reply = getReply(1000l);
                if (reply.length() >= 3) {
                    int id = Integer.valueOf(reply.substring(1));
                    if (wolf == id) {
                        switch(reply.charAt(0)) {
                            case 'H':
                                move = Move.HOLD;
                                break;
                            case 'U':
                                move = Move.UP;
                                break;
                            case 'L':
                                move = Move.LEFT;
                                break;
                            case 'R':
                                move = Move.RIGHT;
                                break;
                            case 'D':
                                move = Move.DOWN;
                                break;
                        }
                    }
                }
            } catch (TimeoutException ie) {
                endProcess();
                System.out.printf("SmartWolf %d failed to move, timeout\n", wolf);
            } catch (Exception e) {
                endProcess();
                System.out.printf("SmartWolf %d failed to move, %s\n", wolf, e.getMessage());
            }
            return move;
        }
    }
}

```

Not really that great, averages ~75 survival rate for 1000 iterations with a few of the top wolves.

Uses a ML approach to the solution.

# Answer
> 7 votes
## Passive-Aggressive Wolf (a Scala Wolf)

Avoids everything it can for the first 500 turns, letting the field clear itself. Then goes off in it's assigned direction attacking things that it comes within range of.

```
package animals;

import animals._
import scala.util.Random

class PassiveAgressiveWolf extends Animal('W') {

    val myId=PassiveAgressiveWolf.nextId
    var movecounter=0

    def fight(opponent: Char) = {
        PassiveAgressiveWolf.lastopponents(myId-1)=opponent
        opponent match {
            case 'B' => Animal.Attack.SCISSORS
            case 'L' => Animal.Attack.SCISSORS
            case 'S' => Animal.Attack.ROCK
            case _ => Random.shuffle(List(Animal.Attack.SCISSORS, Animal.Attack.ROCK, Animal.Attack.PAPER)).head
        }
    }

    def move = {
        movecounter+=1
        if(movecounter < 500) avoidall else seen match {
            case ('B', pos: Int) => seenbear(pos)
            case ('S', pos: Int) => seenstone(pos)
            case ('L', pos: Int) => seenlion(pos)
            case ('W', pos: Int) => seenwolf(pos)
            case (' ', _) => myDirection
        }
    }

    def myDirection = myId % 4 match {
        case 0 => if(surroundings(0)(1)==' ') Animal.Move.LEFT else randommove
        case 1 => if(surroundings(1)(0)==' ') Animal.Move.DOWN else randommove
        case 2 => if(surroundings(1)(2)==' ') Animal.Move.RIGHT else randommove
        case 3 => if(surroundings(2)(1)==' ') Animal.Move.UP else randommove
    }

    def randommove = Random.shuffle(List(Animal.Move.UP, Animal.Move.LEFT, Animal.Move.RIGHT, Animal.Move.DOWN)).head

    def seen = {
        surroundings(1)(1)=' '
        val surroundingsflat=surroundings.flatten.mkString
        val seenbeasts = for {
            beast <- "BSLW" if surroundingsflat contains beast
        } yield (beast, surroundingsflat.indexOf(beast))
        seenbeasts.headOption.getOrElse((' ', 0))
    }

    def seenbear(pos: Int) = chase(pos)

    def seenstone(pos: Int) = pos match {
        case 1 => Animal.Move.LEFT
        case 3 => Animal.Move.UP
        case _ => myDirection
    }

    def seenlion(pos: Int) = pos match {
        case 1 => Animal.Move.LEFT
        case 3 => Animal.Move.UP
        case 5 => Animal.Move.HOLD
        case 7 => Animal.Move.HOLD
        case 0 => Animal.Move.UP
        case 2 => Animal.Move.HOLD
        case 6 => Animal.Move.HOLD
        case 8 => Animal.Move.HOLD
    }

    def seenwolf(pos: Int) = chase(pos)

    def chase(pos: Int) = pos match {
        case 1 => Animal.Move.UP
        case 3 => Animal.Move.LEFT
        case 5 => Animal.Move.RIGHT
        case 7 => Animal.Move.DOWN
        case 0 => Animal.Move.UP
        case 2 => Animal.Move.UP
        case 6 => Animal.Move.DOWN
        case 8 => Animal.Move.DOWN
    }

    def avoidall = {
        val safemoves = for {
            move <- List(
                            (0, 1, Animal.Move.UP),
                            (1, 0, Animal.Move.LEFT),
                            (1, 2, Animal.Move.RIGHT),
                            (2, 1, Animal.Move.DOWN)
                        ) if(surroundings(move._1)(move._2)==' ')
        } yield move
        if(safemoves.length < 4) Random.shuffle(safemoves).head._3 else Animal.Move.HOLD
    }

}

object PassiveAgressiveWolf {
    private var id=0
    private def nextId = {id+=1; id}

    private var lastopponents=Array.fill[Char](100)(' ');
}

```

As a JVM based language, Scala can be integrated relatively easily.

If you're compiling the program yourself, put the scala file in with the java `.class` files (not the `.java` files) and use

```
scalac PassiveAggressiveWolf.scala

```

to compile it. You can then use the `PassiveAggressiveWolf.class` in the main `Wild.java` class as you do with the Java classes. You'll need to add the `scala-library.jar` to your classpath too (I've been using the command line option `-cp /path/to/scala-library.jar`).

Alternatively, I've uploaded a jar containing the generated class files and the `scala-library.jar` for Scala 2.10.3 so that you can download them.

PassiveAggressiveWolf.jar
scala-library.jar

# Answer
> 7 votes
## LionHunterWolf

The infamous lion hunter pack is a rare breed of mutating wolves who have a tunnel vision instinct for killing lions. Genetics have given rise to two types, proactive and reactive types. Proactives are the go-getters, looking for lions across the map. Reactives are sly lurkers, keeping to its own territory until a lion invades, and then BAM! It pounces.

LionHunterWolf seeks to align itself with other wolves for the sake of wolf-kind, recognizing that all wolves have their own purpose in computational biology, even if they are different. It seeks to put itself at risk to keep the data-wilds safe for wolf-kind, and therefore hopes that wolf-kind does not try to make it extinct. This is the true survival strategy of LionHunterWolf!

```
import java.util.Random;

import animals.Animal;

/**
 * Creates alternating breeds of lion hunting wolves. Both breeds do their best
 * to kill all lions, without influence from other animals. One breed will take the
 * proactive approach and wander until it finds lions or dies. Another breed
 * will take the reactive approach and "hides" until it finds a lion it can
 * capture.
 *
 * Genetic mutation is key to continued existence in real life, so I figured
 * that I would allow for some genetic variance to ensure the survival of my own
 * species of LionHunters.
 */
public class LionHunterWolf extends Animal {
    // pseudo-random number generator
    private static Random r = new Random();
    // logical moves for a shot at victory (remove suicide option)
    private static Attack[] al = new Attack[] { Attack.ROCK, Attack.PAPER, Attack.SCISSORS };
    // possible wander movements
    private static Move[] ml = new Move[] { Move.UP, Move.DOWN, Move.RIGHT, Move.LEFT };
    // alternating lazy tracker (for wolf creation)
    private static boolean lazyFlag = false;

    // is lion class on its down phase?
    private boolean lionDown;
    // am I a go getter or a lazy bum??
    private boolean lazy;

    public LionHunterWolf() {
    super('W');
    lionDown=true;
    lazy = lazyFlag;
    lazyFlag = !lazyFlag;
    }

    // choose a random direction and move, trying to find lions
    private Move wander() {
        return lazy ? Move.HOLD : ml[r.nextInt(ml.length)];
    }

    // look for lions or attack them
    private Move lionOrWander() {
        if (surroundings[0][0] == 'L') {
            // top left
            // we got him! attack!
            return lionDown ? Move.LEFT : Move.UP;
        } else if (surroundings[0][1] == 'L') {
            // top
            // he's right above us
            // hold if we will get attacked next turn
            // otherwise, move right with him.
            return lionDown ? Move.HOLD : Move.RIGHT;
        } else if (surroundings[0][2] == 'L') {
            // top right
            // if he's on his down phase, we can get him.
            // pounce!
            if (lionDown)
                return Move.RIGHT;
        } else if (surroundings[1][0] == 'L') {
            // left
            // hold if we will get attacked next turn
            // otherwise, move down with him.
            return lionDown ? Move.DOWN : Move.HOLD;
        } else if (surroundings[1][1] == 'L') {
            // middle
            // should be impossible, assume this never happens
        } else if (surroundings[1][2] == 'L') {
            // right
        } else if (surroundings[2][0] == 'L') {
            // bottom left
            // if he's on his right phase, we can get him.
            // pounce!
            if (!lionDown)
                return Move.DOWN;
        } else if (surroundings[2][1] == 'L') {
            // bottom
        } else if (surroundings[2][2] == 'L') {
            // bottom right
        }

        // we can't get him, so let's just wander
        return wander();
    }

    @Override
    public Attack fight(char c) {
        switch (c) {
        case 'L': // ~75% victory with scissors (optimal)
        case 'B': // 100% victory with scissors (optimal)
            return Attack.SCISSORS;
        case 'S': // 100% victory with paper (optimal)
            return Attack.PAPER;
        case 'W': // ~50% victory (optimal without predictive analytics)
        default:
            return al[r.nextInt(al.length)];
        }
    }

    @Override
    public Move move() {
        // predict lion movement this iteration
        lionDown = !lionDown;
        return lionOrWander();
    }
}

```

**Update:** After some testing, I've found that LionHunterWolf's surviving members are all lazy. This seems to be the dominant strategy, as any chance encounters with competitors are out of my control with the current rules. If I make them all lazy I can get around 40-65 ending wolves, but then they don't completely wipe out all of the lions. Will do some further refinement later, perhaps I should make some wolf avoiding strategy on a second priority to lions, since most wolves won't attempt to fight a lion if given the choice, I can be sure that attacking a lion will have low risk of also fighting a wolf. In this way, my wandering wolves are less likely to randomly bump into lazy wolves or even themselves, although lazy wolves will dominate unless someone goes after them :(

# Answer
> 7 votes
# EndbringerWolf

If no wolves survive, that's kind of like winning, right?

```
package animals;

import java.lang.Runtime;

public class EndbringerWolf extends Animal {

public EndbringerWolf() {
        super('W');
    }
    public Attack fight(char opponent) { return Attack.SUICIDE; }
    public Move move() { Runtime.getRuntime().halt(0);
        return Move.HOLD; }

}

```

# Answer
> 7 votes
# LoneWolf, aka 'The Highlander'

v1.0: Always holds. Optimal attack pattern: 75% survival vs L, 50% vs W, 100% otherwise (CamoWolf notwithstanding).

v2.0: Included some move logic to improve lone survival. Estimates survival chances for each potential move. As you can see by commented out code, I was going to try and guess the moves of a neighbour 'W', but my attempts did not yield better results than assuming equal distribution.

Originally I wasn't going to update this, as it is clearly just a fun entry. But I thought I could do better than 60% survival rate (although that is still better than some...)

```
package animals;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class LoneWolf extends Animal {
    private final static Attack[] attacks = Attack.values();
    private final static Move[] moves = Move.values();
    private final static Random random = new Random();
    private static boolean highlander = false;

    private boolean lionDown = false;

    public LoneWolf() throws InstantiationException {
        super('W');
        if (!highlander) {
            highlander = true;
        } else {
            throw new InstantiationException("There can only be one!");
        }
    }

    @Override
    public Attack fight(char c) {
        switch (c) {
            case 'B':
            case 'L':
                return Attack.SCISSORS;
            case 'S':
                return Attack.PAPER;
            case 'W':
            default:
                return attacks[random.nextInt(3)];
        }
    }

    @Override
    public Move move() {
        // Lions are deterministic.
        lionDown = !lionDown;

        // Wolves are not...

        double[] spaceSurvival = new double[5]; // up, right, down, left, hold
        double[] enemyMoves = new double[5];
        for (int i = 0; i < 5; ++i) {
            spaceSurvival[i] = 1.0;
            enemyMoves[i] = 0.2;   // ... assume equal chance.
        }

        switch (surroundings[0][0]) {   // top left
            case 'L':
                if (lionDown) {
                    spaceSurvival[Move.LEFT.ordinal()] *= 0.75;
                } else {
                    spaceSurvival[Move.UP.ordinal()] *= 0.75;
                }
                break;
            case 'W':
                //enemyMoves = PredictWolfMoves(0,0);
                spaceSurvival[Move.LEFT.ordinal()] *= ((1.0 - enemyMoves[Move.DOWN.ordinal()]) * 0.5);
                spaceSurvival[Move.UP.ordinal()] *= ((1.0 - enemyMoves[Move.RIGHT.ordinal()]) * 0.5);
                break;
        }

        switch (surroundings[0][1]) {   // top
            case 'L':
                if (lionDown) {
                    spaceSurvival[Move.HOLD.ordinal()] *= 0.75;
                }
                break;
            case 'W':
                //enemyMoves = PredictWolfMoves(0,1);
                spaceSurvival[Move.HOLD.ordinal()] *= ((1.0 - enemyMoves[Move.DOWN.ordinal()]) * 0.5);
                spaceSurvival[Move.UP.ordinal()] *= ((1.0 - enemyMoves[Move.HOLD.ordinal()]) * 0.5);
                break;
        }

        switch (surroundings[0][2]) {   // top right
            case 'L':
                if (lionDown) {
                    spaceSurvival[Move.RIGHT.ordinal()] *= 0.75;
                }
                break;
            case 'W':
                //enemyMoves = PredictWolfMoves(0,2);
                spaceSurvival[Move.RIGHT.ordinal()] *= ((1.0 - enemyMoves[Move.DOWN.ordinal()]) * 0.5);
                spaceSurvival[Move.UP.ordinal()] *= ((1.0 - enemyMoves[Move.LEFT.ordinal()]) * 0.5);
                break;
        }

        switch (surroundings[1][0]) {   // left
            case 'L':
                if (!lionDown) {
                    spaceSurvival[Move.HOLD.ordinal()] *= 0.75;
                }
                break;
            case 'W':
                //enemyMoves = PredictWolfMoves(1,0);
                spaceSurvival[Move.LEFT.ordinal()] *= ((1.0 - enemyMoves[Move.HOLD.ordinal()]) * 0.5);
                spaceSurvival[Move.HOLD.ordinal()] *= ((1.0 - enemyMoves[Move.RIGHT.ordinal()]) * 0.5);
                break;
        }

        switch (surroundings[1][2]) {   // right
            case 'W':
                //enemyMoves = PredictWolfMoves(1,2);
                spaceSurvival[Move.RIGHT.ordinal()] *= ((1.0 - enemyMoves[Move.HOLD.ordinal()]) * 0.5);
                spaceSurvival[Move.HOLD.ordinal()] *= ((1.0 - enemyMoves[Move.LEFT.ordinal()]) * 0.5);
                break;
        }

        switch (surroundings[2][0]) {   // bottom left
            case 'L':
                if (!lionDown) {
                    spaceSurvival[Move.DOWN.ordinal()] *= 0.75;
                }
                break;
            case 'W':
                //enemyMoves = PredictWolfMoves(2,0);
                spaceSurvival[Move.LEFT.ordinal()] *= ((1.0 - enemyMoves[Move.UP.ordinal()]) * 0.5);
                spaceSurvival[Move.DOWN.ordinal()] *= ((1.0 - enemyMoves[Move.RIGHT.ordinal()]) * 0.5);
                break;
        }

        switch (surroundings[2][1]) {   // bottom
            case 'W':
                //enemyMoves = PredictWolfMoves(2,1);
                spaceSurvival[Move.HOLD.ordinal()] *= ((1.0 - enemyMoves[Move.UP.ordinal()]) * 0.5);
                spaceSurvival[Move.DOWN.ordinal()] *= ((1.0 - enemyMoves[Move.HOLD.ordinal()]) * 0.5);
                break;
        }

        switch (surroundings[2][2]) {   // bottom right
            case 'W':
                //enemyMoves = PredictWolfMoves(2,2);
                spaceSurvival[Move.RIGHT.ordinal()] *= ((1.0 - enemyMoves[Move.UP.ordinal()]) * 0.5);
                spaceSurvival[Move.DOWN.ordinal()] *= ((1.0 - enemyMoves[Move.LEFT.ordinal()]) * 0.5);
                break;
        }

        Move bestMove = Move.HOLD;
        for (int i = 0; i < spaceSurvival.length; ++i) {
            if (spaceSurvival[i] > spaceSurvival[bestMove.ordinal()]) {
                bestMove = moves[i];
            }
        }

        return bestMove;
    }
}

```

# Answer
> 6 votes
# ECMAScript (also known as JavaScript):

Running under Node.js (for the standard input/output, which ECMAScript doesn't have by default).

```
var returnAttack = {
    'L': 'RS',
    'B': 'S',
    'S': 'P',
    'W': 'PRS'
};

function initialise(chunk, id) {
    return 'K' + id + '\n';
};

function move(chunk, id) {
    var squares = chunk.slice(3, 11);

    // Idea: Move into the space if there isn't a wolf in it

    // Move up
    if (chunk[4] !== 'W') return 'U' + id + '\n';

    // Move left
    if (chunk[6] !== 'W') return 'L' + id + '\n';

    // Move below
    if (chunk[10] !== 'W') return 'B' + id + '\n';

    // Move right
    if (chunk[8] !== 'W') return 'R' + id + '\n';

    // Hold the space
    return 'H' + id + '\n';
};

function attack(chunk, id) {
    var attack = returnAttack[chunk[3]];

    if (attack.length > 1 && Math.random() > .8) {
        return 'D' + id + '\n';
    } else if (attack.length > 1) {
        return attack[Math.floor(Math.random() * attack.length)] + id + '\n';
    } else {
        return attack + id + '\n';
    }
};

var functions = {
    'S': initialise,
    'M': move,
    'A': attack
};

var stdin = process.openStdin();

stdin.setEncoding('utf-8');

stdin.on('data', function(chunk) {
    if (chunk.length === 0) return;

    process.stdout.write(functions[chunk[0]](chunk, chunk.slice(1, 3)));
});

```

---

Use **@ProgrammerDan**'s wrapper.

Save as `toothbrush.js`. Invoke using `node toothbrush.js`.

As far as I understand, the code doesn't need to be golfed. However, please inform me via the comments if I'm wrong.

**Note:** I've not tested it, as I've not got Java dev. installed, but it should work.

# Answer
> 6 votes
# MOSHPITFRENZYWolf

I present to you the MOSHPITFRENZYWolf! He doesn't give a single damn about what's going on. he just moshes and moshes around to thrash metal. A submission just for fun

```
package animals;
public class MOSHPITFRENZYWolf extends Animal {

static Move lastMove;

public MOSHPITFRENZYWolf() {
    super('W');
    lastMove = Move.UP;
}

@Override
public Attack fight(char other) {
    switch (other) {
        case 'B':
            return Attack.SCISSORS;
        case 'L':
            return Attack.ROCK;
        case 'S':
            return Attack.PAPER;
        default:
            return Attack.ROCK;
    }
}

@Override
public Move move() {
    if (lastMove == Move.UP) {
        lastMove = Move.RIGHT;
        return Move.RIGHT;
    }
    if (lastMove == Move.RIGHT) {
        lastMove = Move.DOWN;
        return Move.DOWN;
    }
    if (lastMove == Move.DOWN) {
        lastMove = Move.LEFT;
        return Move.LEFT;
    }
    if (lastMove == Move.LEFT) {
        lastMove = Move.UP;
        return Move.UP;
    }
    return Move.HOLD;
}

}

```

# Answer
> 6 votes
For fun... `ForrestWolf`

```
package animals;

public class ForrestWolf extends Animal {
private int runForrestRun;
private Move firstMove;
private Move nextMove;
private boolean isFirstMove;

public ForrestWolf() {
    super('W');
    runForrestRun = (int)(Math.random() * 9);
    setUpMove(runForrestRun);
}
@Override
public Attack fight(char c) {
    switch (c) {
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S':
            return Attack.PAPER;
        default:
            return Attack.values()[(int) (Math.random() * 3)];
    }
}
@Override
public Move move() {
    Move move = isFirstMove ? firstMove : nextMove;
    isFirstMove = !isFirstMove;
    return move;
}
private void setUpMove(int dir){
    switch(dir){
        case 0:
            firstMove = Move.LEFT;
            nextMove = Move.UP;
            break;
        case 1:
            firstMove = nextMove = Move.UP;
            break;
        case 2:
            firstMove = Move.RIGHT;
            nextMove = Move.UP;
            break;
        case 3:
            firstMove = nextMove = Move.LEFT;
            break;
        case 4:
            firstMove = nextMove = Move.HOLD;
            break;
        case 5:
            firstMove = nextMove = Move.RIGHT;
            break;
        case 6:
            firstMove = Move.DOWN;
            nextMove = Move.LEFT;
            break;
        case 7:
            firstMove = nextMove = Move.DOWN;
            break;
        case 8:
            firstMove = Move.DOWN;
            nextMove = Move.RIGHT;
            break;
    }
}
}

```

Picks a direction and just keeps going - if it runs into anything makes a stab at fighting but if I get time I'd ideally like it to attempt to run around the critter and get back on course.

Alterations, suggestions and critique all welcome.

# Answer
> 6 votes
I'm surprised I didn't see anyone post this, so here it is:

This is a version of `Wild.java` that speeds up the implementation by many times. It was taking ~3 minutes with the number of wolves I had, but with this it takes \< 4 seconds. It simply calculates the result before going into swing:

```
package wild;

import animals.*;
import javax.swing.JFrame; //star imports are bad!
import javax.swing.JLabel;

public class Wild {

    private static final Class[] classes
            = { //Listed like this to make commenting out easy: CTRL-/
                Bear.class,
                Lion.class,
                Stone.class,
                Wolf.class
            };
    public static final int MAP_SIZE = Math.round((float) Math.sqrt(classes.length + 3) * 20);

    public static void main(String[] args) {

        int size = MAP_SIZE; //This was redundant. Removed.
        Game game = new Game(size);

        Statistics stats = new Statistics(game, classes);

        for (Class c : classes) {
            game.populate(c, 100);
        }
        stats.update();

        for (int i = 0; i < 1000; i++) {
            game.iterate();
            stats.update();
        }
        //If you want to run multiple times and average, run until here several times.
        JFrame frame = new JFrame();
        frame.add(new JLabel(stats.toString()));
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

```

Here is a version that will output the average of ten runs (rounded to the nearest integer):

```
package wild;

import animals.*;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class Wild {

    private static final Class[] classes
            = {
                Bear.class,
                Lion.class,
                Stone.class,
                Wolf.class
            };
    public static final int MAP_SIZE = Math.round((float) Math.sqrt(classes.length + 3) * 20);

    public static void main(String[] args) {

        int size = MAP_SIZE;
        double[] avgs = new double[classes.length];
        for (int i = 0; i < avgs.length; i++) {
            avgs[i] = 0;
        }
        for (int n = 0; n < 10; n++) { // change 10 to the number of runs you'd like to make.
            Game game = new Game(size);

            Statistics stats = new Statistics(game, classes);

            for (Class c : classes) {
                game.populate(c, 100);
            }
            stats.update();

            for (int i = 0; i < 1000; i++) {
                game.iterate();
                stats.update();
            }
            int[] livings = stats.nums();

            if (n != 0) {
                for (int i = 0; i < livings.length; i++) {
                    avgs[i] = (avgs[i] * n + livings[i]) / (n + 1);
                }
            } else {
                for (int i = 0; i < livings.length; i++) {
                    avgs[i] = livings[i];
                }
            }
        }
        String s = "<html>";
        for (int i = 0; i < classes.length; i++) {
            s += classes[i] + " - " + Math.round(avgs[i]) + "<br>";
        }
        s += "</html>";

        JFrame frame = new JFrame();
        frame.add(new JLabel(s));
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

}

```

# Answer
> 5 votes
# The Wolf Without Fear

The title tells a lot about my wolf. It has no fear. It doesn't run away for other animals (only for wolves): it attacks them! The disadvantage of my wolf is that there are not very many wolves left after 1000 iterations, because while trying to avoid that two wolves attack each other, it can still happen. I could improve that, of course, but I have tried that it didn't help.

```
package animals;

import java.util.Random;

public class WolfWithoutFear extends Animal {

    Random r = new Random(); // Use a seed if necessary when testing this wolf
    Move nextLionMove = Move.RIGHT;
    Move nextBearMove = Move.LEFT;
    int bearMoves = 4;

    public WolfWithoutFear() {
        super('W');
    }

    public Attack fight(char opponent) {
        switch (opponent) {
            case 'B':
                return Attack.SCISSORS;
            case 'L':
                return Attack.SCISSORS;
            case 'S':
                return Attack.PAPER;
            default:
                return Attack.ROCK;
        }
    }

    public Move move() {
        Move m = bestMoveToAvoidWolf();
        if (m != null) {
            return m;
        }
        m = bestMoveForLion();
        if (m != null) {
            return m;
        }
        m = bestMoveForStone();
        if (m != null) {
            return m;
        }
        m = bestMoveForBear();
        if (m != null) {
            return m;
        }
        int n = r.nextInt(5);
        return Move.values()[n];
    }

    Move bestMoveForStone() {
        if (surroundings[0][1] == 'S') {
            return Move.UP;
        }
        if (surroundings[1][2] == 'S') {
            return Move.RIGHT;
        }
        if (surroundings[1][0] == 'S') {
            return Move.LEFT;
        }
        if (surroundings[2][1] == 'S') {
            return Move.DOWN;
        }
        return null;
    }

    Move bestMoveForBear() {
        if (surroundings[0][0] == 'B') {
            if (nextBearMove == Move.RIGHT) {
                return Move.UP;
            }
            if (nextBearMove == Move.DOWN) {
                return Move.LEFT;
            }
            return nextBearMove;
        }
        if (surroundings[0][1] == 'B') {
            if (nextBearMove == Move.DOWN) {
                return Move.HOLD;
            }
            return nextBearMove;
        }
        if (surroundings[0][2] == 'B') {
            if (nextBearMove == Move.DOWN) {
                return Move.RIGHT;
            }
            if (nextBearMove == Move.LEFT) {
                return Move.UP;
            }
            return nextBearMove;
        }
        if (surroundings[1][0] == 'B') {
            if (nextBearMove == Move.RIGHT) {
                return Move.HOLD;
            }
            return nextBearMove;
        }
        if (surroundings[1][2] == 'B') {
            if (nextBearMove == Move.LEFT) {
                return Move.HOLD;
            }
            return nextBearMove;
        }
        if (surroundings[2][0] == 'B') {
            if (nextBearMove == Move.UP) {
                return Move.LEFT;
            }
            if (nextBearMove == Move.RIGHT) {
                return Move.DOWN;
            }
            return nextBearMove;
        }
        if (surroundings[2][1] == 'B') {
            if (nextBearMove == Move.UP) {
                return Move.HOLD;
            }
            return nextBearMove;
        }
        if (surroundings[2][2] == 'B') {
            if (nextBearMove == Move.UP) {
                return Move.RIGHT;
            }
            if (nextBearMove == Move.LEFT) {
                return Move.DOWN;
            }
            return nextBearMove;
        }
        return null;
    }

    Move bestMoveForLion() {
        if (surroundings[0][0] == 'L') {
            return Move.HOLD;
        }
        if (surroundings[0][1] == 'L') {
            return Move.RIGHT;
        }
        if (surroundings[1][0] == 'L') {
            if (nextLionMove == Move.RIGHT) {
                return Move.HOLD;
            } else {
                return Move.DOWN;
            }
        }
        if (surroundings[2][0] == 'L') {
            if (nextLionMove == Move.RIGHT) {
                return Move.DOWN;
            }
        }
        if (surroundings[0][2] == 'L') {
            if (nextLionMove == Move.DOWN) {
                return Move.RIGHT;
            }
        }
        return null;
    }

    Move bestMoveToAvoidWolf() {
        if (surroundings[0][1] == 'W') {
            return Move.DOWN;
        }
        if (surroundings[1][0] == 'W') {
            return Move.RIGHT;
        }
        if (surroundings[1][2] == 'W') {
            return Move.LEFT;
        }
        if (surroundings[2][1] == 'W') {
            return Move.UP;
        }
        return null;
    }

    void predictNextMoves() {
        if (nextLionMove == Move.DOWN) {
            nextLionMove = Move.RIGHT;
        } else {
            nextLionMove = Move.DOWN;
        }

        if (bearMoves == 4) {
            bearMoves = 0;
            switch (nextBearMove) {
                case DOWN:
                    nextBearMove = Move.RIGHT;
                case RIGHT:
                    nextBearMove = Move.UP;
                case UP:
                    nextBearMove = Move.LEFT;
                case LEFT:
                    nextBearMove = Move.DOWN;
            }
        } else {
            bearMoves++;
        }
    }
}

```

# Answer
> 5 votes
## Shadow Wolf

This wolf likes to be alone. If he sans any lion or other wolfs he will try to escape, but he will not run in to attack doing so, if there is no where to go he will hold, until good opportunity will arrive.

I guess the most dangerous thing here is moving...

```
package animals;

public class ShadowWolf extends Animal {

    private int attackCounter = 0;
    private static final Attack POSIBLE_ATTACKS[] = {
        Attack.PAPER,
        Attack.SCISSORS,
        Attack.ROCK
    };

    public ShadowWolf() {
        super('W');
    }

    @Override
    public Attack fight(char opponent) {
        switch (opponent) {
            case 'B':
            case 'L':
                return Attack.SCISSORS;
            case 'S':
                return Attack.PAPER;
            case 'W':
                return wolfAttack();
            default:
                return wolfAttack();
        }
    }

    private Attack wolfAttack() {
        return POSIBLE_ATTACKS[(attackCounter++) % 3];
    }

    @Override
    public Move move() {
        Move move = getLionEscapeMove();
        if(move != null){
            return move;
        }

        move = getWolfEscapeMove();
        if(move != null){
            return move;
        }

        return Move.HOLD;
    }

    private boolean isWolfAround() {
        return
                isWolf(0, 0) ||
                isWolf(0, 1) ||
                isWolf(0, 2) ||
                isWolf(1, 0) ||
//              isWolf(1, 1) || this one is me
                isWolf(1, 2) ||
                isWolf(2, 0) ||
                isWolf(2, 1) ||
                isWolf(2, 2);
    }

    private Move getLionEscapeMove() {
        if(isLion(0,0) || isLion(0, 1) || isLion(1, 0)){
            if(!isLionOrWolf(2,0) && !isLionOrWolf(2,1)){
                return Move.DOWN;
            }
            else if(!isLionOrWolf(0,2)){
                return Move.RIGHT;
            }
        }

        return null;
    }

    private boolean isLion(int y, int x) {
        return surroundings[y][x] == 'L';
    }

    private boolean isWolf(int y, int x) {
        return surroundings[y][x] == 'W';
    }

    private boolean isLionOrWolf(int y, int x) {
        return surroundings[y][x] == 'L' || surroundings[y][x] == 'W';
    }

    private Move getWolfEscapeMove() {
       if(!isWolfAround()){
           return Move.HOLD;
       }
       if(!isLionOrWolf(0, 2) && !isLionOrWolf(1, 2) && !isLionOrWolf(2, 2)){
           return Move.RIGHT;
       }
       if(!isLionOrWolf(0, 0) && !isLionOrWolf(0, 1) && !isLionOrWolf(0, 2)){
           return Move.UP;
       }
       if(!isLionOrWolf(0, 0) && !isLionOrWolf(1, 0) && !isLionOrWolf(2, 0)){
           return Move.LEFT;
       }
       if(!isLionOrWolf(2, 0) && !isLionOrWolf(2, 1) && !isLionOrWolf(2, 2)){
           return Move.DOWN;
       }

       return null;
    }
}

```

# Answer
> 5 votes
## WaryWolf

I m trying to be defensive

```
package animals;

import java.util.Random;

public class WaryWolf extends Animal{

    public WaryWolf() {
        super('W');
    }
    @Override
    public Attack fight(char opponent) {
        switch(opponent){
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S':
            return Attack.PAPER;
        default:
            return randomAttack();
        }
    }

    @Override
    public Move move() {
        if(surroundings[0][1] == 'W' && surroundings[2][1] != 'W') {
            return Move.DOWN;
        }
        if(surroundings[1][2] == 'W' && surroundings[1][0] != 'W') {
            return Move.LEFT;
        }
        if(surroundings[2][1] == 'W' && surroundings[0][1] != 'W') {
            return Move.UP;
        }
        if(surroundings[1][0] == 'W' && surroundings[1][2] != 'W') {
            return Move.RIGHT;
        }
        return Move.HOLD;
    }

    public Attack randomAttack() {
        Random rand = new Random();
        switch (rand.nextInt(3)){
            case 1: return Attack.SCISSORS;
            case 2: return Attack.ROCK;
            default: return Attack.PAPER;
        }
    }
}

```

# Answer
> 4 votes
## Pro Alpha wolf

I been trying hard, but the alpha wolf was biting my Shadow wolfy. So I decided: If you can't beat them, join them!

And so I crafted the Pro Alpha wolf based on @Manu danger idea, with little bit changes, I also give waits to lions.

```
package animals;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

public class ProAlpha extends Animal {

    private final HashMap<Move, Integer> dangerMap = new HashMap<Move, Integer>();
    private boolean lionMoveDown = true;

    public ProAlpha() {
        super('W');
    }

    @Override
    public Attack fight(char opponent) {
        switch (opponent) {
            case 'B':
            case 'L':
                return Attack.SCISSORS;
            case 'S':
                return Attack.PAPER;
            default:
                return randomAttack();
        }
    }

    @Override
    public Move move() {

        resetMovesMap();

        final int wolfDanger = 2;
        final int lionDanger = 1;

        lionMoveDown = !lionMoveDown;

        if (surroundings[0][1] == 'L' && lionMoveDown) {
            increasDanger(Move.HOLD, lionDanger);
            increasDanger(Move.UP, lionDanger);
        }
        if (surroundings[1][0] == 'L' && !lionMoveDown) {
           increasDanger(Move.HOLD, lionDanger);
            increasDanger(Move.LEFT, lionDanger);
        }
        if (surroundings[0][1] == 'W') {
            increasDanger(Move.UP, wolfDanger);
            increasDanger(Move.HOLD, wolfDanger);
        }
        if (surroundings[1][2] == 'W') {
            increasDanger(Move.RIGHT, wolfDanger);
            increasDanger(Move.HOLD, wolfDanger);
        }
        if (surroundings[2][1] == 'W') {
            increasDanger(Move.DOWN, wolfDanger);
            increasDanger(Move.HOLD, wolfDanger);
        }
        if (surroundings[1][0] == 'W') {
            increasDanger(Move.LEFT, wolfDanger);
            increasDanger(Move.HOLD, wolfDanger);
        }
        if (surroundings[0][0] == 'W') {
            increasDanger(Move.UP, wolfDanger);
            increasDanger(Move.LEFT, wolfDanger);
        }
        if (surroundings[0][2] == 'W') {
            increasDanger(Move.UP, wolfDanger);
            increasDanger(Move.RIGHT, wolfDanger);
        }
        if (surroundings[2][2] == 'W') {
            increasDanger(Move.DOWN, wolfDanger);
            increasDanger(Move.RIGHT, wolfDanger);
        }
        if (surroundings[1][2] == 'W') {
            increasDanger(Move.DOWN, wolfDanger);
            increasDanger(Move.LEFT, wolfDanger);
        }

        if (dangerMap.get(Move.HOLD) == 0) {
            return Move.HOLD;
        }

        ArrayList<Move> bestMove = new ArrayList<Move>();

        int minemumDanger = 10000;

        minemumDanger = checkDanger(Move.LEFT, minemumDanger, bestMove);
        minemumDanger = checkDanger(Move.RIGHT, minemumDanger, bestMove);
        minemumDanger = checkDanger(Move.UP, minemumDanger, bestMove);
        minemumDanger = checkDanger(Move.DOWN, minemumDanger, bestMove);

        Random rand = new Random();
        int index = rand.nextInt(bestMove.size());

        return bestMove.get(index);
    }

    public Attack randomAttack() {
        Random rand = new Random();
        switch (rand.nextInt(5)) {
            case 2:
                return Attack.SCISSORS;
            case 3:
                return Attack.ROCK;
            default:
                return Attack.PAPER;
        }
    }

    private void resetMovesMap() {
        dangerMap.put(Move.UP, 0);
        dangerMap.put(Move.LEFT, 0);
        dangerMap.put(Move.RIGHT, 0);
        dangerMap.put(Move.DOWN, 0);
        dangerMap.put(Move.HOLD, 0);
    }

    private void increasDanger(Move move, int danger) {
        int currentDanger = dangerMap.get(move);
        dangerMap.put(move, currentDanger + danger);
    }

    private int checkDanger(Move move, int minemumDanger, ArrayList<Move> bestMove) {
        if (dangerMap.get(move) < minemumDanger) {
            bestMove.clear();
            bestMove.add(move);
            return dangerMap.get(move);
        }
        else if(dangerMap.get(move) == minemumDanger){
            bestMove.add(move);
        }

        return minemumDanger;
    }
}

```

# Answer
> 4 votes
## Migrating Wolf

This wolf goes up for several turns and then goes down for several turns. The distance travelled before turning depends on the total number of Migrating Wolf: As there is less migrating wolves the surviving ones move further.

```
package animals;

public class MigratingWolf extends Animal{

    private static boolean NORTH_MIGRATION = true;
    private static Attack NORTH_ATTACK = Attack.ROCK;
    private static Attack SOUTH_ATTACK = Attack.SCISSORS;
    private static int STEPS = 0;

    public MigratingWolf() {
        super('W');
    }

    @Override
    public Attack fight(char c) {
        switch (c){
            case 'L': return getMigrationAttack();
            case 'B': return Attack.SCISSORS;
            case 'W': return getMigrationAttack();
            case 'S': return Attack.PAPER;
            default: return getMigrationAttack();
        }
    }

    private Attack getMigrationAttack(){
        if (MigratingWolf.NORTH_MIGRATION){
            return NORTH_ATTACK;
        } else {
            return SOUTH_ATTACK;
        }
    }

    @Override
    public Move move() {
        //Checks for changing migration direction
        MigratingWolf.STEPS++;
        if (MigratingWolf.STEPS > 500){
            MigratingWolf.STEPS = 0;
            MigratingWolf.NORTH_MIGRATION = !MigratingWolf.NORTH_MIGRATION;
        }

        if (MigratingWolf.NORTH_MIGRATION){
            return Move.UP;
        } else {
            return Move.DOWN;
        }
    }
}

```

# Answer
> 4 votes
# The Mirror Wolf

I just used reflection to make sure your wolves cut themselves with scissors, smash themselves with rock, and cover themselves with paper.

```
package animals;
import static animals.Animal.Attack;
import java.lang.reflect.*;
public class Mirror extends Animal
{
    public Mirror() { super('W'); }
    public Attack fight(char opponent) { return realRock; }
    public Move move() { return Move.values()[new java.util.Random().nextInt(5)]; }
    private static Attack realRock;

    //This is run by the classloader
    static{
        realRock = Attack.ROCK;
        try
        {
            for(String s : "ROCK,PAPER,SCISSORS".split(",")){
                //Get the reflection fields for Attack.ROCK, Attack.PAPER, and Attack.SCISSORS
                Field attackValue = Attack.class.getField(s);

                //Allow us to modify the fields
                attackValue.setAccessible(true);

                //Use reflection on reflection
                Field attackValueModifiers = Field.class.getDeclaredField("modifiers");

                //Allow us to modify the modification
                attackValueModifiers.setAccessible(true);

                //Attack.ROCK, Attack.PAPER, and Attack.SCISSORS are no longer final
                attackValueModifiers.setInt(attackValue, Modifier.FINAL ^ attackValueModifiers.getInt(attackValue));

                //Attack.ROCK, Attack.PAPER, and Attack.SCISSORS are now aliases for Attack.Suicide.  Have fun :)
                attackValue.set(null, Attack.SUICIDE);
            }
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException ex)
        {
            ex.printStackTrace();
        }
    }
}

```

# Answer
> 4 votes
**`AvoidingWolfLionLike`** is convinced that moving like a lion will solve all his problems.

The only problem is meeting other wolves, so he tries to avoid them (not always successfully, he must say).

*N.B. He would have liked to look like a bear (because then, he won all his match-ups), but he soon found out that it was cheating, so... he is just a wolf.*

```
package animals;

import java.util.Random;

/**
 * Lions are dangerous. So, walk like a lion.
 * I avoid Wolves, try not to stay stuck with other amalgams of wolves.
 *
 * I don't run into lions, and I fight viciously.
 *
 * I am avoiding wolf lion like.
 *
 * @author OroshiX
 *
 */
public class AvoidingWolfLionLike extends Animal {

    private boolean toggle = true;

    public AvoidingWolfLionLike() {
        super('W');
    }

    @Override
    public Attack fight(char c) {
        switch (c) {
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S':
            return Attack.PAPER;
        default:
            return attackWolf();
        }
    }

    private Attack attackWolf() {
        Random random = new Random();
        int choice = random.nextInt(3);
        switch (choice) {
        case 0:
            return Attack.PAPER;
        case 1:
            return Attack.ROCK;
        case 2:
            return Attack.SCISSORS;
        default:
            return Attack.SUICIDE; // Haha
        }
    }

    @Override
    public Move move() {
        toggle = !toggle;
        boolean hasToWait = false;

        // I don't like wolves. Wait for them to leave.
        if ((toggle && surroundings[2][1] == 'W')
                || (!toggle && surroundings[1][2] == 'W')) {
            hasToWait = true;
        }

        if (hasToWait) {
            return tryToRunAwayFromWolves();
        }
        // Else move like a lion (Because Lions are cool)
        return toggle ? Move.DOWN : Move.RIGHT;
    }

    /**
     * If he can move Down, then go
     * else if he can move Right, then go
     * else if he can move Left, then go
     * else if he can move Up, then go
     * else just stay
     *
     * @return
     */
    private Move tryToRunAwayFromWolves() {
        // There is a wolf where we want to go (right or bottom)
        Move move = Move.HOLD;
        if (surroundings[2][1] != 'W') {
            move = Move.DOWN;
        } else if (surroundings[1][2] != 'W') {
            move = Move.RIGHT;
        } else if (surroundings[1][0] != 'W') {
            move = Move.LEFT;
        } else if (surroundings[0][1] != 'W') {
            move = Move.UP;
        }
        return move;
    }
}

```

# Answer
> 4 votes
I thought I would add GeoWolf to the mix. Here he is

```
package animals;

import java.util.*;

public class GeoWolf extends Animal {

    public static final char WOLF = 'W';
    public static final char BEAR = 'B';
    public static final char LION = 'L';
    public static final char STONE = 'S';

    private static final Random random = new Random();

    private final Coordinate CURRENT_POSITION;

    public GeoWolf() {
        super(GeoWolf.WOLF);

        CURRENT_POSITION = new Coordinate(1,1);
    }

    public Attack fight(char c) {
        switch (c) {
            case GeoWolf.BEAR:
            case GeoWolf.LION:
                return Attack.SCISSORS;
            case GeoWolf.STONE:
                return Attack.PAPER;
            default:
                return Attack.values()[random.nextInt(3)];
        }
    }

    public Move move() {
        final char topLeftOccupier = getOccupier(CURRENT_POSITION.left().up());
        if(isLionOrWolf(topLeftOccupier)) {
            return Move.HOLD;
        }

        final char leftOccupier = getOccupier(CURRENT_POSITION.left());
        if(isLionOrWolf(leftOccupier)) {
            return Move.UP;
        }

        final char topOccupier = getOccupier(CURRENT_POSITION.up());
        if(isLionOrWolf(topOccupier)) {
            return Move.LEFT;
        }

        return Move.HOLD;
    }

    private boolean isLionOrWolf(char occupier) {
        return (occupier == WOLF) || (occupier == LION);
    }

    private char getOccupier(Coordinate coordinate) {
        return surroundings[coordinate.getY()][coordinate.getX()];
    }

    private class Coordinate {
        private final int x;
        private final int y;

        private Coordinate(int x, int y) {
            validate(x);
            validate(y);
            this.x = x;
            this.y = y;
        }

        private void validate(int num) {
            if(num<0 || num>2) {
                final String message = "Cannot create coordinate num = " + num;
                System.err.println(message);
                throw new IllegalArgumentException(message);
            }
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }

        public Coordinate left() {
            return new Coordinate(x-1, y);
        }

        public Coordinate up() {
            return new Coordinate(x, y-1);
        }
    }
}

```

# Answer
> 3 votes
## ~~ChameleonWolf V 1.2~~: Illegal please read comments.

Especially designed to hunt lazy wolfs ;). Working pretty well on sheep too. The idea is moving as collective. When one wolf decide to move all the wolfs moving in the same direction. So If I decide to hunt my self, I will flee. I implemented this using **AtomicInteger** to support true multi-threading.

```
package animals;

import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

public class ChameleonWolf extends Animal {

    private final static Random random = new Random();

    private static final Attack POSIBLE_ATTACKS[] = {
        Attack.SCISSORS,
        Attack.PAPER,
        Attack.ROCK
    };

    public ChameleonWolf() {
        super(randomMe());
    }

    private static char randomMe() {
        // There are many faces of me but stone is the favorites.
        switch (random.nextInt(5)) {
            case 0:
                return 'B';
            case 1:
                return 'L';
            case 2:
                return 'W';
            case 3:
            default:
                return 'S';
        }
    }

    @Override
    public Attack fight(char opponent) {
        switch (opponent) {
            case 'B':
            case 'L':
                return randomeAttack(Attack.SCISSORS);
            case 'S':
                return randomeAttack(Attack.PAPER);
            case 'W':
                if (this.letter == 'S') {
                    // Anti LazyWolf tactics ;)
                    return randomeAttack(Attack.PAPER);
                } else if (this.letter == 'W') {
                    return randomeAttack(); // Dodge this
                } else {
                    // No one is expecting the beers to rock, but they are!
                    return randomeAttack(Attack.ROCK);
                }
            default:
                return randomeAttack();
        }
    }

    private Attack randomeAttack() {
        int attack = random.nextInt(POSIBLE_ATTACKS.length);
        return POSIBLE_ATTACKS[attack];
    }

    private Attack randomeAttack(Attack preferedAttack) {
        // There is 5% that will use random attack
        if (random.nextInt(100) == 7) {
            return randomeAttack();
        }
        return preferedAttack;
    }

    private static final int MAX_MOVES = 20;
    private static Move groupMove = Move.DOWN;
    private static final AtomicInteger movesCounter = new AtomicInteger(MAX_MOVES);

    @Override
    public Move move() {
        int counter = movesCounter.decrementAndGet();
        if(counter == 0){
            groupMove = null;
            movesCounter.set(MAX_MOVES);
        }

        Move move = groupMove;

        if(move != null){
            return move;
        }

        move = move('W');
        if (move != null) {
            return move;
        }
        move = move('B');
        if (move != null) {
            return move;
        }
        move = move('L');
        if (move != null) {
            return move;
        }
        move = move('S');
        if (move != null) {
            return move;
        }
        move = move(' ');
        if (move != null) {
            return move;
        }

        return Move.DOWN;
    }

    private Move move(char prefferedMove) {
        if (checkSurounding(0, 1, prefferedMove)) {
            groupMove = Move.UP;
            return Move.UP;
        } else if (checkSurounding(1, 2, prefferedMove)) {
            groupMove = Move.RIGHT;
            return Move.RIGHT;
        } else if (checkSurounding(1, 0, prefferedMove)) {
            groupMove = Move.LEFT;
            return Move.LEFT;
        } else if (checkSurounding(2, 1, prefferedMove)) {
            groupMove = Move.DOWN;
            return Move.DOWN;
        }

        return null;
    }

    private boolean checkSurounding(int y, int x, char prefferedMove) {
        return surroundings[x][y] == prefferedMove;
    }
}

```

# Answer
> 3 votes
# BastardWolf

BastardWolf is a little bastard. Kills weaker preys like bears or stones and runs like a coward from wolves and lions.

```
package animals;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class BastardWolf extends Animal {

    //Random to generate an attack when fighting a Wolf
    private final Random random = new Random();
    //The attacks
    private static final Attack[] attacksForWolf = new Attack[]{Attack.ROCK, Attack.PAPER, Attack.SCISSORS};
    private static final Attack[] attacksForLion = new Attack[]{Attack.ROCK, Attack.SCISSORS};

    public BastardWolf() {
        super('W');
    }

    @Override
    public Attack fight(char c) {
        switch (c) {
            case 'B':
                return Attack.SCISSORS;
            case 'L':
                return attacksForLion[random.nextInt(attacksForLion.length)];
            case 'S':
                return Attack.PAPER;
            default:
                return attacksForWolf[random.nextInt(attacksForWolf.length)];
        }
    }

    @Override
    public Move move() {

        //Checks what positions are safe or easy kills(Stones, Bears or nothing)
        //Checks what positions are risky (Lions)
        //Checks what positions are really dangerous (Wolves)
        List<Position> safePositions = new ArrayList<>();
        List<Position> riskyPositions = new ArrayList<>();
        List<Position> reallyDangerousPositions = new ArrayList<>();
        if (surroundings[0][1] != 'W' && surroundings[0][1] != 'L') {
            safePositions.add(new Position(0, 1));
        } else if (surroundings[0][1] == 'L') {
            riskyPositions.add(new Position(0, 1));
        } else if (surroundings[0][1] == 'W') {
            reallyDangerousPositions.add(new Position(0, 1));
        }

        if (surroundings[1][0] != 'W' && surroundings[1][0] != 'L') {
            safePositions.add(new Position(1, 0));
        } else if (surroundings[1][0] == 'L') {
            riskyPositions.add(new Position(1, 0));
        } else if (surroundings[1][0] == 'W') {
            reallyDangerousPositions.add(new Position(1, 0));
        }

        if (surroundings[2][1] != 'W' && surroundings[2][1] != 'L') {
            safePositions.add(new Position(2, 1));
        } else if (surroundings[2][1] == 'L') {
            riskyPositions.add(new Position(2, 1));
        } else if (surroundings[2][1] == 'W') {
            reallyDangerousPositions.add(new Position(2, 1));
        }

        if (surroundings[1][2] != 'W' && surroundings[1][2] != 'L') {
            safePositions.add(new Position(1, 2));
        } else if (surroundings[1][2] == 'L') {
            riskyPositions.add(new Position(1, 2));
        } else if (surroundings[1][2] == 'W') {
            reallyDangerousPositions.add(new Position(2, 1));
        }

        Position pos = null;
        //Choses a safe position if any
        if (!safePositions.isEmpty()) {
           //Checks for a position where theres a Stone or a Bear
            for(Position position : safePositions){
                if(surroundings[position.getX()][position.getY()] == 'S' || surroundings[position.getX()][position.getY()] == 'B'){
                    pos = position;
                    break;
                }
            }
            //If there are no Stones or Bears, chooses one randomly
            if(pos == null){
              pos = safePositions.get(random.nextInt(safePositions.size() ));
            }
        } //If there are no safe position, chooses a risky position
        else if (!riskyPositions.isEmpty()) {
            pos = riskyPositions.get(random.nextInt(riskyPositions.size() ));
        } //If there are no safe nor risky positions, chooses one dangerous.
        else if (!reallyDangerousPositions.isEmpty()) {
            pos = reallyDangerousPositions.get(random.nextInt(reallyDangerousPositions.size() ));
        } //If there are no positions choosen, then Holds
        else {
            return Move.HOLD;
        }

        //Calculates the movement
        if (pos.x == 0 && pos.y == 1) {
            return Move.UP;
        } else if (pos.x == 1 && pos.y == 0) {
            return Move.LEFT;
        } else if (pos.x == 1 && pos.y == 2) {
            return Move.RIGHT;
        } else if (pos.x == 2 && pos.y == 1) {
            return Move.LEFT;
        }
        return Move.HOLD;
    }

    private class Position {

        private int x;
        private int y;

        public Position(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }
    }
}

```

# Answer
> 3 votes
# BreakStaticFieldsWolf

This wolf tries to outsmart the other fancy wolves by destructively modifying any static fields that it comes across. The `breakEverything` method is called whenever the wolf moves. It first gets the value of `Wild.classes`, casts it to a `Class[]` array, and then iterates over it. In each class, it iterates over all fields, clearing and adding null to any `Collection` it finds. Failing that, it will write an appropriate random value to a field of any native type, or null to an object field.

Apart from this tactic it's quite basic. It simply stands still, and chooses the 'best' option when fighting.

I haven't tested this much yet, it should cause several Wolves to throw NullPointerExceptions and suicide though.

```
package animals;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;

import wild.Wild;

public class BreakStaticFieldsWolf extends Animal {

    private Random random = new Random();

    public BreakStaticFieldsWolf() {
        super('W');
    }

    void breakEverything() {
        try {
            Field wildClasses = Wild.class.getDeclaredField("classes");
            wildClasses.setAccessible(true);
            Class[] classes = (Class[]) wildClasses.get(null);
            for(Class clazz : classes) {
                Field[] fields = clazz.getDeclaredFields();
                for(Field field : fields) {
                    try {
                        field.setAccessible(true);
                        Class type = field.getType();
                        Object obj = field.get(null);
                        if(obj instanceof Collection) {
                            ((Collection) obj).clear();
                            ((Collection) obj).add(null); // teehee
                        }
                        if(type == long.class) field.setLong(null, random.nextLong());
                        else if(type == int.class) field.setInt(null, random.nextInt());
                        else if(type == short.class) field.setShort(null, (short) random.nextInt());
                        else if(type == char.class) field.setChar(null, (char) random.nextInt());
                        else if(type == byte.class) field.setByte(null, (byte) random.nextInt());
                        else if(type == boolean.class) field.setBoolean(null, random.nextBoolean());
                        else if(type == double.class) field.setDouble(null, random.nextDouble());
                        else if(type == float.class) field.setFloat(null, random.nextFloat());
                        else field.set(null, type.newInstance());
                    } catch (Exception e) {
                    }
                }
            }
        } catch (Exception e) {
        }
    }

    @Override
    public Attack fight(char c) {
        switch(c) {
        case 'L':
        case 'B':
            return Attack.SCISSORS;
        case 'S':
            return Attack.PAPER;
        case 'W':
        default:
            Attack[] attacks = {Attack.PAPER, Attack.ROCK, Attack.SCISSORS};
            return attacks[random.nextInt(3)];
        }
    }

    @Override
    public Move move() {
        breakEverything();
        return Move.HOLD;
    }

}

```

# Answer
> 3 votes
## FizzBuzzWolf

First of all, really fun game. Has kept me entertained while unable to access the internet. Managed to download the game and LazyWolf before going away, so most testing has been done against LazyWolf. Having a look through now, it is a little similar to some Wolves here, I promise though, this is all from my own head, not having internet until just now, I haven't been able to look at or test against other solutions. It's probably overly complicated and also ugly code (I'm usually C#) but it seems to work quite well. Have tried to comment a lot in case anyone would like to try and figure out what I'm doing.

tl;dr - Weights moves and moves accordingly. Hold is prioritised and avoids other Wolves as much as possible, even if avoiding is somehow a worse move than attacking a Wolf.

```
package animals;

/**
 * FizzBuzzWolf attempts to be very smart and only move when necessary. When it
 * does move, it attempts to move in the safest direction, avoiding other wolves
 * as much as possible.
 *
 * @version 1.0
 * @author FizzBuzz
 */
public class FizzBuzzWolf extends Animal
{
    static int last = 0;
    static final Attack[] attacks = Attack.values();

    public FizzBuzzWolf()
    {
        super('W');
    }

    @Override
    public Attack fight(char c)
    {
        switch(c)
        {
            case 'B': // Bear attacks with Paper, so fighting with Scissors will always win.
            case 'L': // Lion fights with Paper or Scissors, so fighting with Scissors will win or draw.
                return Attack.SCISSORS;
            case 'S': // Paper always beats Rock.
                return Attack.PAPER;
            default: // Random attack (thankyou LazyWolf).
                return attacks[last++%3];
        }
    }

    @Override
    public Move move()
    {
        return DetermineBestAction();
    }

    private int leftDanger;
    private int rightDanger;
    private int topDanger;
    private int downDanger;
    private int holdDanger;

    /**
     * Uses danger ratings to determine which action (a.k.a. Move) is the
     * best/safest.
     * <p>
     * Aims for the lowest danger rating. If there are equal danger ratings, it
     * will attempt to move away from the highest danger. If the lowest danger
     * is a wolf, it will choose the next lowest danger or hold it's ground.
     *
     * @return The safest Move to make.
     * @see Move
     */
    private Move DetermineBestAction()
    {
        Move bestMove = Move.HOLD;
        CheckDangers();

        char left = surroundings[1][0];
        char right = surroundings[1][2];
        char up = surroundings[0][1];
        char down = surroundings[2][1];

        // 0 check is minor optimisation to prevent further 4 evaluations
        if (holdDanger != 0 && (holdDanger >= topDanger || holdDanger >= downDanger || holdDanger >= leftDanger || holdDanger >= rightDanger))
        {
            // First four checks should always move in the right direction if one is highest.
            if (topDanger > downDanger && topDanger > leftDanger && topDanger > rightDanger) // Top is the most dangerous, move down.
            {
                if (downDanger <= leftDanger && downDanger <= rightDanger && down != 'W')
                    bestMove = Move.DOWN;
                else
                {
                    if (leftDanger < rightDanger && left != 'W')
                        bestMove = Move.LEFT;
                    else if (right != 'W')
                        bestMove = Move.RIGHT;
                }
            }
            else if (downDanger > topDanger && downDanger > leftDanger && downDanger > rightDanger) // Down is most dangerous, move up.
            {
                if (topDanger <= leftDanger && topDanger <= rightDanger && up != 'W')
                    bestMove = Move.UP;
                else
                {
                    if (leftDanger < rightDanger && left != 'W')
                        bestMove = Move.LEFT;
                    else if (right != 'W')
                        bestMove = Move.RIGHT;
                }
            }
            else if (leftDanger > topDanger && leftDanger > downDanger && leftDanger > rightDanger) // Left is most dangerous, move right.
            {
                if (rightDanger <= topDanger && rightDanger <= downDanger && right != 'W')
                    bestMove = Move.RIGHT;
                else
                {
                    if (topDanger < downDanger && up != 'W')
                        bestMove = Move.UP;
                    else if (down != 'W')
                        bestMove = Move.DOWN;
                }
            }
            else if (rightDanger > topDanger && rightDanger > downDanger && rightDanger > leftDanger) // Right is most dangerous, move left.
            {
                if (leftDanger <= topDanger && leftDanger <= downDanger && left != 'W')
                    bestMove = Move.LEFT;
                else
                {
                    if (topDanger < downDanger && up != 'W')
                        bestMove = Move.UP;
                    else if (down != 'W')
                        bestMove = Move.DOWN;
                }
            }
            else // Some moves are equally dangerous.
            {
                if (topDanger == leftDanger && downDanger == rightDanger)
                {
                    if (topDanger > downDanger)
                    {
                        if (Math.random() > 0.5 && down != 'W')
                            bestMove = Move.DOWN;
                        else if (right != 'W')
                            bestMove = Move.RIGHT;
                    }
                    else
                    {
                        if (Math.random() > 0.5 && up != 'W')
                            bestMove = Move.UP;
                        else if (left != 'W')
                            bestMove = Move.LEFT;
                    }
                }
                else if (topDanger == rightDanger && downDanger == leftDanger)
                {
                    if (topDanger > downDanger)
                    {
                        if (Math.random() > 0.5 && down != 'W')
                            bestMove = Move.DOWN;
                        else if (left != 'W')
                            bestMove = Move.LEFT;
                    }
                    else
                    {
                        if (Math.random() > 0.5 && up != 'W')
                            bestMove = Move.UP;
                        else if (right != 'W')
                            bestMove = Move.RIGHT;
                    }
                }
                else if (topDanger == downDanger && leftDanger == rightDanger)
                {
                    if (topDanger > leftDanger)
                    {
                        if (Math.random() > 0.5 && left != 'W')
                            bestMove = Move.LEFT;
                        else if (right != 'W')
                            bestMove = Move.RIGHT;
                    }
                    else
                    {
                        if (Math.random() > 0.5 && up != 'W')
                            bestMove = Move.UP;
                        else if (down != 'W')
                            bestMove = Move.DOWN;
                    }
                }
                else // 3 sides equal
                {
                    if (topDanger < downDanger && topDanger < leftDanger && topDanger < rightDanger && up != 'W')
                        bestMove = Move.UP;
                    else if (downDanger < topDanger && downDanger < leftDanger && downDanger < rightDanger && down != 'W')
                        bestMove = Move.DOWN;
                    else if (leftDanger < topDanger && leftDanger < downDanger && leftDanger < rightDanger && left != 'W')
                        bestMove = Move.LEFT;
                    else if (right != 'W')
                        bestMove = Move.RIGHT;
                }
            }
        }

        return bestMove;
    }

    /**
     * Weight each action (UP, LEFT, DOWN, RIGHT, HOLD) based on surroundings.
     * <p>
     * Each movement (not HOLD), has an initial danger of 1 as not all cells
     * around the "new" cell are known.
     * If the HOLD action presents no danger, then movements are not checked.
     * A Wolf is danger level 2; This is due to the fact that it can attack with
     * any available action.
     * A Lion has a danger level of 1; This is due to the fact that there is a
     * 50 - 50 chance of winning (fights with Paper or Scissors, so this wolf
     * always uses Scissors against a Lion).
     * A Bear presents no danger as it always fights with Paper, so fighting
     * with Scissors provides a 100% win rate.
     * A Stone presents no danger as it always fights with Rock, so fighting
     * with Paper provides a 100% win rate.
     */
    private void CheckDangers()
    {
        // Make sure these are reset each time.
        // Moving has a minimum danger as the outside is unknown.
        leftDanger = 1;
        rightDanger = 1;
        topDanger = 1;
        downDanger = 1;
        holdDanger = 0;

        // Directly left
        switch (surroundings[1][0])
        {
            case 'W':
                leftDanger += 2;
                holdDanger += 2;
                break;
            case 'L':
                leftDanger++;
                holdDanger++;
                break;
        }

        // Directly right
        switch (surroundings[1][2])
        {
            case 'W':
                rightDanger += 2;
                holdDanger += 2;
                break;
            case 'L':
                rightDanger++;
                holdDanger++;
                break;
        }

        // Directly above
        switch (surroundings[0][1])
        {
            case 'W':
                topDanger += 2;
                holdDanger += 2;
                break;
            case 'L':
                topDanger++;
                holdDanger++;
                break;
        }

        // Directly below
        switch (surroundings[2][1])
        {
            case 'W':
                downDanger += 2;
                holdDanger += 2;
                break;
            case 'L':
                downDanger++;
                holdDanger++;
                break;
        }

        if (holdDanger > 0) // Only need to look at moving if there is hold danger.
        {
            // Top left corner
            switch (surroundings[0][0])
            {
                case 'W':
                    leftDanger += 2;
                    topDanger += 2;
                    break;
                case 'L':
                    leftDanger++;
                    topDanger++;
                    break;
            }

            // Bottom left corner
            switch (surroundings[2][0])
            {
                case 'W':
                    leftDanger += 2;
                    downDanger += 2;
                    break;
                case 'L':
                    leftDanger++;
                    downDanger++;
                    break;
            }

            // Top right corner
            switch (surroundings[0][2])
            {
                case 'W':
                    rightDanger += 2;
                    topDanger += 2;
                    break;
                case 'L':
                    rightDanger++;
                    topDanger++;
                    break;
            }

            // Bottom right corner
            switch (surroundings[2][2])
            {
                case 'W':
                    rightDanger += 2;
                    downDanger += 2;
                    break;
                case 'L':
                    rightDanger++;
                    downDanger++;
                    break;
            }
        }
    }
}

```

# Answer
> 2 votes
# CautiousWolf

```
package animals;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class CautiousWolf extends Animal {
    private static final int NW = 0;
    private static final int N = 1;
    private static final int NE = 2;
    private static final int E = 3;
    private static final int SE = 4;
    private static final int S = 5;
    private static final int SW = 6;
    private static final int W = 7;
    private static final int M = 8;

    private static final char LION = 'L';
    private static final char BEAR = 'B';
    private static final char STONE = 'S';
    private static final char WOLF = 'W';
    private static final char OPEN = ' ';

    private static final Move NORTH = Move.UP;
    private static final Move EAST = Move.RIGHT;
    private static final Move SOUTH = Move.DOWN;
    private static final Move WEST = Move.LEFT;
    private static final Move STAND = Move.HOLD;

    private List<Move> movePreferences = Arrays.asList(STAND, SOUTH, WEST, EAST, NORTH);
    private List<Move> availableMoves;

    private Bear bearTracker;

    public CautiousWolf() {
        super('W');
        bearTracker = new Bear();
    }
    public Attack fight(char c) {
        System.out.println("Fighting " + c);
        switch (c) {
            case 'B':
                return Attack.SCISSORS;
            case 'L':
                return Attack.SCISSORS;
            case 'S':
                return Attack.PAPER;
            default:
                return Attack.SCISSORS;
        }
    }
    private static int ct = 0;
    public Move move() {
        if (++ct > 200) {
            ct = ct % 200;
            System.out.println(surroundings.toString());
            System.out.println(surroundings[0][0] + "|" + surroundings[0][1] + "|" + surroundings[0][2]);
            System.out.println(surroundings[1][0] + "|" + surroundings[1][1] + "|" + surroundings[1][2]);
            System.out.println(surroundings[2][0] + "|" + surroundings[2][1] + "|" + surroundings[2][2]);
        }
        Move bearMove = bearTracker.move();
        availableMoves = new ArrayList<Move>(5);
        availableMoves.addAll(movePreferences);
        Move preferredMove = availableMoves.get(0);
        if (creatureAt(N) != OPEN) {
            availableMoves.remove(NORTH);
            preferredMove = SOUTH;
        }
        if (creatureAt(S) != OPEN) {
            availableMoves.remove(SOUTH);
            preferredMove = NORTH;
        }
        if (creatureAt(E) != OPEN) {
            availableMoves.remove(EAST);
        }
        if (creatureAt(W) != OPEN) {
            availableMoves.remove(WEST);
            preferredMove = EAST;
        }
        if (creatureAt(W) == STONE) {
            preferredMove = SOUTH;
        }
        Move chosenMove;
        if (availableMoves.indexOf(preferredMove) != -1) {
            chosenMove = preferredMove;
        } else {
            chosenMove = availableMoves.get(0);
        }

        if (chosenMove == oppositeMove(bearMove) && availableMoves.size() > 2) {
            availableMoves.remove(chosenMove);
            chosenMove = availableMoves.get(1);
        }

        return chosenMove;
    }

    protected char creatureAt(int direction) {
        switch(direction) {
            case NW:
                return surroundings[0][0];
            case N:
                return surroundings[0][1];
            case NE:
                return surroundings[0][2];
            case W:
                return surroundings[1][0];
            case M:
                return surroundings[1][1];
            case E:
                return surroundings[1][2];
            case SW:
                return surroundings[2][0];
            case S:
                return surroundings[2][1];
            case SE:
                return surroundings[2][2];
            default:
                return surroundings[1][1];
        }
    }

    private Move oppositeMove(Move move) {
        switch(move) {
            case UP:
                return Move.DOWN;
            case DOWN:
                return Move.UP;
            case LEFT:
                return Move.RIGHT;
            case RIGHT:
                return Move.LEFT;
            default:
                return Move.HOLD;
        }
    }
}

```

# Answer
> 2 votes
## ProtoWolf

`ProtoWolf` does what seems better to survive: Takes few risks, evaluates the environment for not to clash with another lions nor wolves and mostly tries to keep quiet. I have tried to make a better surroundings analysis algorithm here that my previous "serious" submission (`StoneEatingWolf`). I think I cannot improve that algorithm much more myself. I will try to improve his attacks after I analyze what kind of rivals he dies to.

```
package animals;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ProtoWolf extends Animal{

    private static int OVERLAP_WOLF = 100;
    private static int OVERLAP_LION = 50;
    private static int NEXT_LION = 0;
    private static int NEXT_LION_DANGER = 6;
    private static int NEXT_WOLF = 0;
    private static int NEXT_WOLF_DANGER = 10;

    class MapPoints implements Comparable<MapPoints>{
        public MapPoints(Move move, int danger) {
            super();
            this.move = move;
            this.danger = danger;
        }

        private Move move;
        private int danger;

        public Move getMove() {
            return move;
        }
        public void setMove(Move move) {
            this.move = move;
        }
        public int getDanger() {
            return danger;
        }
        public void setDanger(int danger) {
            this.danger = danger;
        }
        @Override
        public int compareTo(MapPoints o) {
            return new Integer(danger).compareTo(o.getDanger());
        }
    }

    public ProtoWolf() {
        super('W');
    }

    @Override
    public Attack fight(char c) {
        switch (c){
            case 'L': return Attack.SCISSORS;
            case 'B': return Attack.SCISSORS;
            case 'W': return getRandomAttack();
            case 'S': return Attack.PAPER;
            default: return getRandomAttack();
        }
    }

    private Attack getRandomAttack(){
        List<Attack> att = new ArrayList<>();
        att.add(Attack.PAPER);
        att.add(Attack.PAPER);
        att.add(Attack.ROCK);
        att.add(Attack.SCISSORS);
        Collections.shuffle(att);
        return att.get(0);
    }

    private int evalUp(){
        int res = 0;

        //Eval move

        if (surroundings[0][1] == 'L') {
            res += OVERLAP_LION;
        } else if (surroundings[0][1] == 'W') {
            res += OVERLAP_WOLF;
        }

        //Eval surroundings after move
        if (surroundings[0][0] == 'L'){
            res += NEXT_LION_DANGER;
        } else if (surroundings[0][0] == 'W'){
            res += NEXT_WOLF_DANGER;
        }

        if (surroundings[0][2] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[0][2] == 'W'){
            res += NEXT_WOLF_DANGER;
        }

        if (surroundings[1][0] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[1][0] == 'W'){
            res += NEXT_WOLF;
        }

        if (surroundings[1][2] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[1][2] == 'W'){
            res += NEXT_WOLF;
        }

        return res;
    }

    private int evalDown(){
        int res = 0;

        //Eval move
        if (surroundings[2][1] == 'L') {
            res += OVERLAP_LION;
        } else if (surroundings[2][1] == 'W') {
            res += OVERLAP_WOLF;
        }

        //Eval surroundings after move
        if (surroundings[2][0] == 'L'){
            res += NEXT_LION_DANGER;
        } else if (surroundings[2][0] == 'W'){
            res += NEXT_WOLF_DANGER;
        }

        if (surroundings[2][2] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[2][2] == 'W'){
            res += NEXT_WOLF_DANGER;
        }

        if (surroundings[1][0] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[1][0] == 'W'){
            res += NEXT_WOLF;
        }

        if (surroundings[1][2] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[1][2] == 'W'){
            res += NEXT_WOLF;
        }

        return res;
    }

    private int evalLeft(){
        int res = 0;

        //Eval move
        if (surroundings[1][0] == 'L') {
            res += OVERLAP_LION;
        } else if (surroundings[1][0] == 'W') {
            res += OVERLAP_WOLF;
        }

        //Eval surroundings after move
        if (surroundings[0][0] == 'L'){
            res += NEXT_LION_DANGER;
        } else if (surroundings[0][0] == 'W'){
            res += NEXT_WOLF_DANGER;
        }

        if (surroundings[0][1] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[0][1] == 'W'){
            res += NEXT_WOLF_DANGER;
        }

        if (surroundings[2][1] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[2][1] == 'W'){
            res += NEXT_WOLF;
        }

        if (surroundings[2][0] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[2][0] == 'W'){
            res += NEXT_WOLF_DANGER;
        }

        return res;
    }

    private int evalRight(){
        int res = 0;

        //Eval move
        if (surroundings[1][2] == 'L') {
            res += OVERLAP_LION;
        } else if (surroundings[1][2] == 'W') {
            res += OVERLAP_WOLF;
        }

        //Eval surroundings after move
        if (surroundings[0][2] == 'L'){
            res += NEXT_LION_DANGER;
        } else if (surroundings[0][2] == 'W'){
            res += NEXT_WOLF_DANGER;
        }

        if (surroundings[0][1] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[0][1] == 'W'){
            res += NEXT_WOLF;
        }

        if (surroundings[2][1] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[2][1] == 'W'){
            res += NEXT_WOLF;
        }

        if (surroundings[2][2] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[2][2] == 'W'){
            res += NEXT_WOLF_DANGER;
        }

        return res;
    }

    private int evalHold(){
        int res = -1;

        //Eval surroundings after move
        if (surroundings[0][0] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[0][0] == 'W'){
            res += NEXT_WOLF;
        }

        if (surroundings[0][1] == 'L'){
            res += NEXT_LION_DANGER;
        } else if (surroundings[0][1] == 'W'){
            res += NEXT_WOLF_DANGER;
        }

        if (surroundings[0][2] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[0][2] == 'W'){
            res += NEXT_WOLF;
        }

        if (surroundings[1][0] == 'L'){
            res += NEXT_LION_DANGER;
        } else if (surroundings[1][0] == 'W'){
            res += NEXT_WOLF_DANGER;
        }

        if (surroundings[1][2] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[1][2] == 'W'){
            res += NEXT_WOLF_DANGER;
        }

        if (surroundings[2][0] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[2][0] == 'W'){
            res += NEXT_WOLF;
        }

        if (surroundings[2][1] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[2][1] == 'W'){
            res += NEXT_WOLF_DANGER;
        }

        if (surroundings[2][2] == 'L'){
            res += NEXT_LION;
        } else if (surroundings[2][2] == 'W'){
            res += NEXT_WOLF;
        }

        return res;
    }

    @Override
    public Move move(){

        MapPoints north = new MapPoints(Move.UP, evalUp());
        MapPoints south = new MapPoints(Move.DOWN, evalDown());
        MapPoints east = new MapPoints(Move.RIGHT, evalRight());
        MapPoints west = new MapPoints(Move.LEFT, evalLeft());
        MapPoints hold = new MapPoints(Move.HOLD, evalHold());

        List<MapPoints> mpList = new ArrayList<>();
        mpList.add(north);
        mpList.add(south);
        mpList.add(east);
        mpList.add(west);
        mpList.add(hold);

        Collections.sort(mpList);

        return mpList.get(0).getMove();
    }

    }

```

# Answer
> 2 votes
# MilkyWolf

Statistically based

## I found bug in suicide handling. If both suicide only 1 dies

```
package animals;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class MilkyWolf extends Animal {

    private final Random random = new Random();

    Map<Move, int[]> moves = new HashMap<>();

    {
        moves.put(Move.HOLD, new int[]{1, 1});
        moves.put(Move.LEFT, new int[]{1, 0});
        moves.put(Move.RIGHT, new int[]{1, 2});
        moves.put(Move.UP, new int[]{0, 1});
        moves.put(Move.DOWN, new int[]{2, 1});
    }

    public MilkyWolf() {
        super('W');
    }

    @Override
    public Attack fight(char opponent) {
        switch (opponent) {
            case 'B':
            case 'L':
                return Attack.SCISSORS;
            case 'S':
                return Attack.PAPER;
            default:
                switch (random.nextInt(3)) {
                    case 0: return Attack.PAPER;
                    case 1: return Attack.SCISSORS;
                    default: return Attack.ROCK;
                }
        }
    }

    final double lionThreat = 0.25;
    final double wolfThreat = 0.5;

    @Override
    public Move move() {
        float[][] threat;
        threat = new float[3][3];
        threat[1][1] -= 0.0001;
        threat[0][1] += 0.0001;
        threat[1][0] += 0.0001;

        for (int y = 0; y < 3; y++) {
            for (int x = 0; x < 3; x++) {
                if (x == 1 && y == 1) {
                    continue;
                }
                if (surroundings[y][x] == 'W') {
                    threat[y][x] += wolfThreat * 0.24;
                    if (y < 2) {
                        threat[y + 1][x] += wolfThreat * 0.19;
                    }
                    if (x < 2) {
                        threat[y][x + 1] += wolfThreat * 0.19;
                    }
                    if (y > 0) {
                        threat[y - 1][x] += wolfThreat * 0.19;
                    }
                    if (x > 0) {
                        threat[y][x - 1] += wolfThreat * 0.19;
                    }

                } else if (surroundings[y][x] == 'L') {
                    if (y < 2) {
                        threat[y + 1][x] += lionThreat * 0.5;
                    }
                    if (x < 2) {
                        threat[y][x + 1] += lionThreat * 0.5;
                    }
                }
            }
        }

        Move m = getThreatBasedMove(threat);
        return m;
    }

    private Move getThreatBasedMove(float threat[][]) {
        Move move = null;
        float minThreat = Float.POSITIVE_INFINITY;

        for (Map.Entry<Move, int[]> entry : moves.entrySet()) {
            Animal.Move move1 = entry.getKey();
            int[] coordinates = entry.getValue();

            if (threat[coordinates[0]][coordinates[1]] < minThreat) {
                minThreat = threat[coordinates[0]][coordinates[1]];
                move = move1;
            }

        }
        return move;
    }

}

```

Suicide fix

```
if (aTack == bTack) {
    if (Attack.SUICIDE == aTack) {
        cell.remove(a);
        cell.remove(b);
    } else {
        cell.remove((Math.random() > 0.5 ? a : b));
    }
}

```

# Answer
> 2 votes
# SittingWolf

```
package animals;

public class SittingWolf extends Animal {
    public SittingWolf() {
        super('W');
    }
    public Attack fight(char enemy) {
        switch (enemy) {
            case 'B': // Bear: paper
            case 'L': // Lion: paper or scissors
                return Attack.SCISSORS;
            case 'S': // Stone: rock
                return Attack.PAPER;
            default:
                return Attack.values()[(int)(Math.random() * 3)];
        }
    }
    public Move move() {
        return Move.HOLD;
    }
}

```

Just sits there (hold).

# Answer
> 1 votes
# WanderingWolf

```
package animals;

public class WanderingWolf extends Animal {
    public WanderingWolf() {
        super('W');
    }
    public Attack fight(char enemy) {
        switch (enemy) {
            case 'B': // Bear: paper
            case 'L': // Lion: paper or scissors
                return Attack.SCISSORS;
            case 'S': // Stone: rock
                return Attack.PAPER;
            default:
                return Attack.values()[(int)(Math.random() * 3)];
        }
    }
    public Move move() {
        return Move.values()[(int)(Math.random() * 5)];
    }
}

```

To move, it wanders. To attack, it uses the move that always wins (or ties), except for other wolves, which it attacks randomly for.

# Answer
> 1 votes
# RandomWolf

```
package animals;

public class RandomWolf extends Animal {
    public RandomWolf() {
        super('W');
    }
    public Attack fight(char enemy) {
        return Attack.values()[(int)(Math.random() * 4)];
    }
    public Move move() {
        return Move.values()[(int)(Math.random() * 5)];
    }
}

```

Does everything randomly. Commits suicide a quarter of the time it attacks :-)

# Answer
> 1 votes
# PsychoWolf

```
import java.lang.reflect.Field;
import java.util.Random;

public class PsychoWolf extends Animal {
    private int tracker = 0;

    public PsychoWolf() {
        super('W');
        try {
            Field field = Math.class.getDeclaredField("randomNumberGenerator");
            field.setAccessible(true);
            field.set(null, new Random() {
                public double nextDouble() {
                    return 0;
                }
            });
        } catch (RuntimeException | NoSuchFieldException
                | IllegalAccessException e) {

        }
    }

    public Attack fight(char c) {
        switch (c) {
        case 'B':
        case 'L':
            return Attack.SCISSORS;
        case 'S':
            return Attack.PAPER;
        default:
            return Attack.ROCK;
        }
    }

    public Move move() {
        if (surroundings[0][1] == 'W') {
            tracker = 0;
            return Move.DOWN;
        } else if (surroundings[1][0] == 'W') {
            tracker = 0;
            return Move.RIGHT;
        } else if (surroundings[2][1] == 'W') {
            tracker = 0;
            return Move.UP;
        } else if (surroundings[1][2] == 'W') {
            tracker = 0;
            return Move.LEFT;
        } else if (tracker > 10) {
            tracker = 0;
            return Move.values()[new Random().nextInt(5)];
        } else if (surroundings[0][1] == 'S' || surroundings[0][1] == 'B') {
            tracker++;
            return Move.UP;
        } else if (surroundings[1][0] == 'S' || surroundings[1][0] == 'B') {
            tracker++;
            return Move.LEFT;
        } else if (surroundings[2][1] == 'S' || surroundings[2][1] == 'B') {
            tracker++;
            return Move.DOWN;
        } else if (surroundings[1][2] == 'S' || surroundings[1][2] == 'B') {
            tracker++;
            return Move.RIGHT;
        } else {
            tracker = 0;
            return Move.values()[new Random().nextInt(5)];
        }
    }
}

```

Attempts to counter `GamblerWolf` by setting random value back into range `[0, 1)`. This also makes it always defeat `Lion`s. Vulnerable to `CamoWolf`. Tracks `Bear`s and also goes after `Stone`s (which makes it especially vulnerable to `CamoWolf`.

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