96
\$\begingroup\$

AlienWar

This game takes place in a very crowded planet where aliens are the superior race. Your task is to create your own alien and beat all other.

The Board

It is a 2 dimensional board.
The length of one side of the board is Math.ceil(sqrt(species * 100 * 2.5)) = ~40% of board used. The board is a planet, so if you walk out of the map in the west, you come back in the east. If you walk out in the north, you will find yourself in the south.

Abilities

Each species on the planet has abilities. Here they are:

Name        Benefit
life        HP = lifeLVL * 5 (reduces with every hit you take, 0 = dead), base HP = 10
strength    Your hits do a random int in range [1 to strengthLVL] damage
defense     Randomly select int in range [0 to (50 / defenseLVL + 1)], if int == 0 then dodge next attack
vision      Gives you visionLVL/2 fields around you vision
cleverness  Blurs (increases) every ability randomly in range [0 to clevernessLVL/2] when sending to other aliens

The Game

  • There will be 100 instances of each submission.
  • After instancing, each alien can set 10 ability points in total. You can set different points for every instance.
  • If you set more than 10 points, the instance dies.
  • A game consists of 1000 rounds. Each round:
    • Every alien has to return a move via move(char[] fields). This includes Move.STAY.
    • If several aliens are on a field, 2 will be randomly selected:
      • If both agree on peace (return false in wantToFight) they will stay where they are, else they will fight.
      • This loops until only one alien stays on a field or all agree on peace.
  • If an alien kills something, he gets 1/5 of each of his enemies abilities. The winners HP will be refilled with 2*enemyLifeLVL.

  • Winner is the one with the most abilities (sum of abilities of living aliens).

Fights

Both aliens will hit each other "at the same time", this means if you kill the other alien, he still can hit you one time.

Dodging: Before you get hit, the game will calculate if you can dodge the attack by using rand.nextInt(50 / defenseLvl + 1) == 0. defenseLvl will never be greater than 50 when calculating your dodge-skills (hence maximum dodge-chance is 50%).

Hitting: If you don't dodge the attack, you will get hit and your HP will be reduced by rand.nextInt(enemy.getStrengthLvl()) + 1.

A fight ends when either one or both alien involved are dead. The winner, if one exists, gets the reward.

Gamerules

  • Base level for every ability (without giving any ability points) is 1 (base HP is 10).
  • The values sent when asked to fight are life (not HP!), strength, defense and vision-levels.
  • Cleverness is NOT sent when asked to fight.
  • All floating numbers will be ROUNDED to nearest integer when using/sending them, but stored and increased as float.
  • Maximum dodge-chance is 50%. Otherwise fights may never terminate.

The Prey

There are 5 species which are already on the field. Since they are prey, they choose not to fight when asked to.

Whale:       lvl 10 life            Stays   
Cow:         lvl 10 strength        Random move
Turtle:      lvl 10 defense         South west
Eagle:       lvl 10 vision          Examines fields, tries to avoid danger      
Human:       lvl 10 cleverness      North east

They will be represented with their first letter (i.e. W for whale) in the map (Aliens with A, empty fields with a whitespace ' ').

Additional Rules

  • Reflection is disallowed.
  • Interacting (instancing etc.) with other aliens is disallowed.
  • Writing/Reading external resources like files or databases is also disallowed.
  • Only Java (version 1.8) submissions allowed (Java is rather easy, and you don't have to be an expert for this game).
  • All submissions must extend the alien-class and will be placed in the alien-package.
  • I will accept the best alien on 19th of July. All aliens submitted by 12:00 UTC that day will be tested.
  • Maximum 3 submissions per user since there are already very many aliens.

Example of an alien

package alien;

import planet.Move;

public class YourUniqueNameHere extends Alien {

    public void setAbilityPoints(float[] abilities) {
        abilities[0] = 2; //life
        abilities[1] = 2; //strength
        abilities[2] = 2; //defense
        abilities[3] = 2; //vision
        abilities[4] = 2; //cleverness
    }

    public Move move(char[][] fields) {
        //you are in the middle of the fields, say fields[getVisionFieldsCount()][getVisionFieldsCount()]
        return Move.STAY;
    }

    public boolean wantToFight(int[] enemyAbilities) {
        //same order of array as in setAbilityPoints, but without cleverness
        return true;
    }

}

Control program

Source code for the control program can be found here. Now updated with all aliens included in the latest run.

Final scores (20.07.2014, average of 10 games)

alien.PredicatClaw                  1635.4
alien.LazyBee                       1618.8
alien.CartographerLongVisionAlien   1584.6
alien.ChooseYourBattles             1571.2
alien.Bender                        1524.5
alien.HerjanAlien                   1507.5
alien.FunkyBob                      1473.1
alien.SecretWeapon2                 1467.9
alien.PredicatEyes                  1457.1
alien.CorporateAlien                1435.9
alien.GentleGiant                   1422.4
alien.CropCircleAlien               1321.2
alien.VanPelt                       1312.7
alien.NewGuy                        1270.4
alien.BananaPeel                    1162.6
alien.Rock                          1159.2
alien.BullyAlien                    1106.3
alien.Geoffrey                      778.3
alien.SecretWeapon                  754.9
alien.SecretWeapon3                 752.9
alien.FunkyJack                     550.3
alien.Stone                         369.4
alien.Assassin                      277.8
alien.Predicoward                   170.1
prey.Cow                            155.2
alien.Morphling                     105.3
alien.Eli                           99.6
alien.Warrior                       69.7
alien.Hunter                        56.3
alien.Manager                       37.6
alien.OkinawaLife                   14.2
prey.Whale                          10.5
alien.Gamer                         4.5
alien.Randomite                     0
alien.Guard                         0
prey.Eagle                          0
alien.Rogue                         0
alien.WeakestLink                   0
alien.Fleer                         0   
alien.Survivor                      0
alien.Sped                          0
alien.Junkie                        0
alien.Coward                        0
alien.CleverAlien                   0
prey.Human                          0
alien.BlindBully                    0
prey.Turtle                         0
alien.AimlessWanderer               0
\$\endgroup\$
  • 14
    \$\begingroup\$ Three downvotes, what on earth? And I don't see a single negative comment. Are people that passive aggressively annoyed that this is limited to Java? \$\endgroup\$ – Martin Ender Jul 2 '14 at 9:11
  • 6
    \$\begingroup\$ @m.buettner My downvote is for the limitation to the godawfulness that is Java (though if it was limited to the nicest language ever created I'd still downvote it for limiting it to 1 language). I didn't see the point in adding a comment since it was obvious what the downvotes would be for. \$\endgroup\$ – Gareth Jul 2 '14 at 14:41
  • 6
    \$\begingroup\$ Hmmm, am having mixed feelings here \$\endgroup\$ – Mr. Alien Jul 3 '14 at 9:15
  • 5
    \$\begingroup\$ @user3334871 I don't think changing any of the rules after 17 answers are in (and potentially a dozen more people working on submissions) is a good idea. Since only the fewest of us here (if any) are professional game designers, pretty much any self-made KotH may have some balancing issues - but if exploring the space of possible strategies is still fun (which apparently it is, judging by answers, upvotes and stars), I don't think it's much of a problem. \$\endgroup\$ – Martin Ender Jul 3 '14 at 9:17
  • 5
    \$\begingroup\$ @Manu For the mathematically inclined the description of how the board wraps is somewhat misleading. You're saying it's a planet and it wraps east/west. There is nothing that really indicates that it does wrap north/south, too. In fact, if it does, it's technically not a sphere any more, but a torus: kotaku.com/classic-jrpg-worlds-are-actually-donuts-1239882216. You can also see that by noticing that when you walk "off" the top of a world map (the north pole), you don't appear at the bottom (the south pole). Hence, Michael's suggestion is definitely valid, I think. \$\endgroup\$ – Martin Ender Jul 4 '14 at 16:52

44 Answers 44

2
\$\begingroup\$

SecretWeapon

package alien;

import planet.Move;

/**
 * Created by Vaibhav Jatar on 02/07/14.
 */
public class SecretWeapon extends Alien {

    private final static byte LIFE=0, STR=1, DEF=2, VIS=3, CLV=4;

    public void setAbilityPoints(float[] abilities) {
        abilities[LIFE] = 1;
        abilities[STR] = 9;
        abilities[DEF] = 0;
        abilities[VIS] = 0;
        abilities[CLV] = 0;
    }

    public Move move(char[][] fields)   {
        int vision = getVisionFieldsCount(); //count of fields / middle
        char me = fields[vision][vision]; //middle of fields
        int leastDanger = Integer.MAX_VALUE;
        Move bestMove = Move.STAY;
        for (Move move : Move.values()) {
            int danger = 0;
            for (int i = 1; i <= vision; i++) { //loop through fields in specific direction
                int fieldX = vision + (i * move.getXOffset());
                int fieldY = vision + (i * move.getYOffset());
                switch(fields[fieldX][fieldY])  {
                    case 'A': danger--;
                    case ' ': danger--;
                    case 'C': danger--;
                    case 'E': danger++;
                    case 'H': danger++;
                    case 'T': danger--;
                    case 'W': danger++;
                    default: danger--;
                }
            }
            if (danger < leastDanger) {
                bestMove = move;
                leastDanger = danger;
            }
        }
        return bestMove;
    }

    public boolean wantToFight(int[] enemyAbilities)    {
        return (enemyAbilities[1]+ enemyAbilities[2]  ) < 7;
    }
}
\$\endgroup\$
  • \$\begingroup\$ what shall it do? \$\endgroup\$ – Joshua Jul 3 '14 at 15:23
  • 1
    \$\begingroup\$ @Joshua it's a secret \$\endgroup\$ – Martin Ender Jul 3 '14 at 15:33
2
\$\begingroup\$

Weakest Link

This bot is strong in what appears to be the most useless1 categories: visual & cleverness. He stays put because fights will come to him and he'll fight anything that comes his way.

public class weakestLink extends Alien{
    public void setAbilityPoints(float[] abilities){
        abilities[0] = 0;  // life
        abilities[1] = 0;  // str
        abilities[2] = 0;  // def
        abilities[3] = 7;  // vis
        abilities[4] = 3;  // clv
    }

    // the fights will come to you
    public Move move(char[][] fields){
        return Move.STAY; 
    }

    public boolean wantToFight(int[] enemyAbilities){
        return true;
    }
}



1 I say useless because most of the current bots do not use visual or cleverness. However, cleverness appears to be an intrinsic thing, so I gave it just enough so that a win for the opponent gets nothing.

\$\endgroup\$
  • \$\begingroup\$ Nope, they will be stored and increased as float. \$\endgroup\$ – Gigala Jul 3 '14 at 8:06
  • \$\begingroup\$ @Gigala: True, but Specie.java has int and Math.round for all the stats. Giving my opponent 4/5 would be equivalent to giving them no buffs. \$\endgroup\$ – Kyle Kanos Jul 3 '14 at 14:09
  • \$\begingroup\$ But isn't it like that the next win will probably give the opponent enough to make the jump from X.6 to the next level? \$\endgroup\$ – Gigala Jul 3 '14 at 15:44
  • 1
    \$\begingroup\$ @Gigala: Assuming that their cleverness is that large, of course. That's a chance this death-wishing bot is willing to take. \$\endgroup\$ – Kyle Kanos Jul 3 '14 at 15:46
2
\$\begingroup\$

AimlessWanderer

RandomStringUtils.randomAlphanumeric(100); //Flavor text

 public class AimlessWanderer extends Alien{

    private final Random rand = new Random();

    @Override
    public void setAbilityPoints(float[] abilities) {
        int cap = 10; 
        for(int i = 0;i<abilities.length; i++){
            abilities[i] = rand.nextInt(cap);
            cap -= abilities [i];
        }
        abilities[rand.nextInt(4)] += cap > 0 ? cap : 0;
    }

    @Override
    public Move move(char[][] fields) {
        return Move.getRandom();
    }

    @Override
    public boolean wantToFight(int[] enemyAbilities) {  
        rand.setSeed(rand.nextLong());
        return rand.nextBoolean();
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Please, format your code properly. \$\endgroup\$ – AJMansfield Jul 1 '14 at 20:51
  • 6
    \$\begingroup\$ The RandomStringUtils.randomAlphanumeric(100); //Flavor text line is not part of the code. \$\endgroup\$ – Undeserved Jul 1 '14 at 21:26
  • 1
    \$\begingroup\$ Out of curiosity, is there a point to reseeding rand each time wantToFight is called? \$\endgroup\$ – Kyle Kanos Jul 3 '14 at 14:18
  • \$\begingroup\$ You can never be too sure. \$\endgroup\$ – Undeserved Jul 3 '14 at 14:53
  • \$\begingroup\$ Reseeding the RNG on every call probably makes it less random - depends on the algorithm, but you're preventing its state space from being any larger than a single long. I'd suggest creating one Random object as an instance variable and then reusing it for everything. (BlindBully seems to do this, if you need an example.) \$\endgroup\$ – zwol Jul 6 '14 at 14:45
2
\$\begingroup\$

HerjanAlien

About my alien breed, he is nothing new, dodging stuff and trying to kill prey if he can. The only thing is that if his vision ability increases he immediately uses the vision he gained. I haven't given him vision levels at the start though, that worked out really bad for his survivability :S. (Just upgrading it by one level will cost him 2 of his strength/life).

My alien can't wait anymore, so enough talk, he makes his entrance:

package alien;

import planet.Move;

public class HerjanAlien extends Alien{

    private final int LIFE = 0, STR = 1;

    private final int UP = 0, LEFT = 1, DOWN = 2, RIGHT = 3, DOWNLEFT = 4, DOWNRIGHT = 5, UPLEFT = 6, UPRIGHT = 7;

    @Override
    public void setAbilityPoints(float[] abilities) {
        abilities[LIFE] = 4.5f;
        abilities[STR] = 5.5f;
    }

    @Override
    public Move move(char[][] fields) {     

        int middle = getVisionFieldsCount();

        int neededAttacksToWin = 60/((getStrengthLvl()-1)/2+1);
        if(getCurrentHp()-2 > neededAttacksToWin){
            if(fields[middle-1][middle-1] == 'W')
                return Move.NORTHWEST;
            if(fields[middle][middle-1] == 'W')
                return Move.NORTH;
            if(fields[middle+1][middle-1] == 'W')
                return Move.NORTHEAST;
            if(fields[middle+1][middle] == 'W')
                return Move.EAST;
            if(fields[middle+1][middle+1] == 'W')
                return Move.SOUTHEAST;
            if(fields[middle][middle+1] == 'W')
                return Move.SOUTH;
            if(fields[middle-1][middle+1] == 'W')
                return Move.SOUTHWEST;
            if(fields[middle-1][middle] == 'W')
                return Move.EAST;
        }

        if(getCurrentHp() > 5){
            if(fields[middle+1][middle-1] == 'T')
                return Move.STAY;
            if(fields[middle][middle-1] == 'T')
                return Move.WEST;
            if(fields[middle+1][middle] == 'T')
                return Move.SOUTH;

            if(fields[middle-1][middle-1] == 'H')
                return Move.STAY;
            if(fields[middle][middle-1] == 'H')
                return Move.EAST;
            if(fields[middle-1][middle] == 'H')
                return Move.NORTH;
        }

        int[] danger = new int[8];
        for(int i = 0; i < 8; i++){
            danger[i] = 0;
        }

        for(int x = -getVisionFieldsCount(); x <= getVisionFieldsCount(); x++){
            for(int y = -getVisionFieldsCount(); y <= getVisionFieldsCount(); y++){

                if(fields[middle - x][middle - y] == 'A'){
                    int dangerFactor = getVisionFieldsCount();
                    if(x <= 1 && x >= -1 && y <= 1 && y >= -1)
                        dangerFactor = getVisionFieldsCount()*4;

                    if(x<0)
                        danger[LEFT] += dangerFactor;
                    if(x>0)
                        danger[RIGHT] += dangerFactor;
                    if(y<0)
                        danger[UP] += dangerFactor;
                    if(y>0)
                        danger[DOWN] += dangerFactor;

                    if(x<=0 && y<=0)
                        danger[UPLEFT] += dangerFactor;
                    if(x>=0 && y<=0)
                        danger[UPRIGHT] += dangerFactor;
                    if(x<=0 && y>=0)
                        danger[DOWNLEFT] += dangerFactor;
                    if(x>=0 && y>=0)
                        danger[DOWNRIGHT] += dangerFactor;
                }
            }
        }
        boolean safe = true;
        for(int i = 0; i < 4; i++){
            if(danger[i] > 3){
                safe = false;
                break;
            }
        }
        if(safe)
            return Move.STAY;

        int leastDanger = 50;
        int bestWay = 0;
        if(getVisionFieldsCount()>1){
            for(int j = 8; j >= 0; j--){
                if(danger[j] < leastDanger){
                    leastDanger = danger[j];
                    bestWay = j;
                }
            }
        }else{
            for(int j = 4; j >= 0; j--){
                if(danger[j] < leastDanger){
                    leastDanger = danger[j];
                    bestWay = j;
                }
            }
        }

        if(bestWay == LEFT)
            return Move.WEST;
        if(bestWay == UP)
            return Move.NORTH;
        if(bestWay == RIGHT)
            return Move.EAST;
        if(bestWay == DOWN)
            return Move.SOUTH;
        if(bestWay == DOWNLEFT)
            return Move.SOUTHWEST;
        if(bestWay == DOWNRIGHT)
            return Move.SOUTHEAST;
        if(bestWay == UPLEFT)
            return Move.NORTHWEST;
        if(bestWay == UPRIGHT)
            return Move.NORTHEAST;

        return Move.getRandom();
    }

    @Override
    public boolean wantToFight(int[] enemyAbilities) {

        int enemyLifeLvl = enemyAbilities[LIFE];
        int enemyStrengthLvl = enemyAbilities[STR];

        int neededAttacksToWin = (enemyLifeLvl*5+10)/((getStrengthLvl()-1)/2+1);
        int enemyAttacksToLose = (getCurrentHp()/5/((enemyStrengthLvl-1)/2+1));

        if(getCurrentHp() <= enemyStrengthLvl)
            return false;
        if(enemyAttacksToLose-neededAttacksToWin > enemyStrengthLvl/enemyLifeLvl+1)
            return true;
        return false;
    }

    @Override
    public String toString(){ // for some testing
        return "Herjan";
    }
}
\$\endgroup\$
2
\$\begingroup\$

Randomite

Designed to be as random as possible.

package alien;

import planet.Move;

public class Randomite extends Alien {

    private static int max = 10;

    @Override
    public void setAbilityPoints(float[] abilities) {
        int r1;
        while (max > 0) {
            if (max == 1) {
                r1 = 1;
            } else {
                r1 = Math.floor(Math.random() * max);
            }
            int r2 = Math.floor(Math.random() * 5);
            abilities[r2] += r1;
            max -= r1;
        }
    }

    @Override
    public Move move(char[][] fields) {
        return Move.getRandom();
    }

    @Override
    public boolean wantToFight(int[] enemyAbilities) {
        int r3 = Math.floor(Math.random() * 100);
        return r3 > 50;
    }
}

Simulation of random abilities in JavaScript: http://pastebin.com/mmjVpzGU

\$\endgroup\$
  • \$\begingroup\$ It is as random as it possibly can be. (claps slowly) \$\endgroup\$ – Mark Gabriel Jul 4 '14 at 12:06
  • \$\begingroup\$ @MarkGabriel Well nearly every other idea has been done and I thought it would make for an interesting opponent. Granted it could lose straight away. \$\endgroup\$ – Spedwards Jul 4 '14 at 12:18
  • \$\begingroup\$ Actually the interesting thing about random stuff is that you can expect that you won't be in the extremes. I'm quite interested to see the results of this. Haha. \$\endgroup\$ – Mark Gabriel Jul 4 '14 at 12:43
  • \$\begingroup\$ @MarkGabriel I ran 10 simulations and they are seriously random. pastebin.com/GTkHkVDf \$\endgroup\$ – Spedwards Jul 4 '14 at 13:41
  • 1
    \$\begingroup\$ This doesn't compile. Your using variable r1 outside of the block its declared in \$\endgroup\$ – rdans Jul 4 '14 at 21:12
2
\$\begingroup\$

The Book of Eli

He just keeps going west guided only by the book of Eli, knowing that a force greater than himself will protect him. He is peaceful and will only fight when attacked.

package alien;

import planet.Move;

public class Eli extends Alien {

    public void setAbilityPoints(float[] abilities) {
        abilities[0] = 3; //life
        abilities[1] = 3; //strength
        abilities[2] = 4; //defense
        abilities[3] = 0; //vision
        abilities[4] = 0; //cleverness
    }

    public Move move(char[][] fields) {
        //Just keep going west as that is the way to salvation
        return Move.WEST;
    }

    public boolean wantToFight(int[] enemyAbilities) {
        //Will not fight as it's not the moral thing to do
        return false;
    }

}
\$\endgroup\$
1
\$\begingroup\$

SecretWeapon3

package alien;

import planet.Move;

/**
 * Created by VJA1075 on 02/07/14.
 */
public class SecretWeapon3 extends Alien {

    private final static byte LIFE=0, STR=1, DEF=2, VIS=3, CLV=4;

    public void setAbilityPoints(float[] abilities) {
        abilities[LIFE] = 1;
        abilities[STR] = 9;
        abilities[DEF] = 0;
        abilities[VIS] = 0;
        abilities[CLV] = 0;
    }

    public Move move(char[][] fields)   {
        int vision = getVisionFieldsCount(); //count of fields / middle
        char me = fields[vision][vision]; //middle of fields
        int leastDanger = Integer.MAX_VALUE;
        Move bestMove = Move.STAY;
        for (Move move : Move.values()) {
            int danger = 0;
            for (int i = 1; i <= vision; i++) { //loop through fields in specific direction
                int fieldX = vision + (i * move.getXOffset());
                int fieldY = vision + (i * move.getYOffset());
                switch(fields[fieldX][fieldY])  {
                    case 'A': danger--;
                    case ' ': danger++;
                    case 'C': danger++;
                    case 'E': danger++;
                    case 'H': danger++;
                    case 'T': danger++;
                    case 'W': danger++;
                    default: danger++;
                }
            }
            if (danger < leastDanger) {
                bestMove = move;
                leastDanger = danger;
            }
        }
        return bestMove;
    }

    public boolean wantToFight(int[] enemyAbilities)    {
        // LIFE=0, STR=1, DEF=2, VIS=3, CLV=4;
        //abilities[STR]=abilities[STR]*100;
        //((double)this.getCurrentHp() * this.getDefenseLvl()) / (double)enemyAbilities[STR] > (enemyAbilities[LIFE] * enemyAbilities[DEF]) / this.getStrengthLvl()
        return (enemyAbilities[1]+ enemyAbilities[2]  ) < 7;
    }
}
\$\endgroup\$
1
\$\begingroup\$

Geoffrey

package alien;

import planet.Move;

public class Geoffrey extends Alien{
    public void setAbilityPoints(float[] abilities){
        abilities[0] = 5;  
        abilities[1] = 5;  
        abilities[2] = 0; 
        abilities[3] = 0;  
        abilities[4] = 0;  
    }

    public Move move(char[][] fields){      
        return Move.getRandom();
    }

    public boolean wantToFight(int[] enemyAbilities){
        return (this.getStrengthLvl() * this.getCurrentHp() * 0.15 > enemyAbilities[0] * enemyAbilities[1]);
    }
}
\$\endgroup\$
1
\$\begingroup\$

Sped

He's clumsy and a little brain dead.

package alien;

import planet.Move;

public class Sped extends Alien {

    private final int LIF = 0, STR = 1, DEF = 2, VIS = 3, CLV = 4;

    public void setAbilityPoints(float[] abilities) {
        abilities[LIF]  = 8;
        abilities[DEF]  = 2;
    }

    public Move move(char[][] fields) {
        // He's a little clumsy so he doesn't move because he knows he'll fall and trip.
        return Move.STAY;
    }

    public boolean wantToFight(int[] enemyAbilities) {
        // He's a, well, me... a sped. He doesn't know if he wants to fight or not.
        int r = Math.floor(Math.random() * 100);
        return r > 50;
    }

}
\$\endgroup\$
1
\$\begingroup\$

CorporateAlien
Tries to maximize value by avoiding other alien and hunt for prey that has good boosts (Whale, Cow, Turtle and Eagle)

package alien;

import planet.Move;

public class CorporateAlien extends Alien {

    float[] abilities = new float[5];

    public void setAbilityPoints(float[] abilities) {
        abilities[0] = 4.5; // life
        abilities[1] = 5.5; // strength
        abilities[2] = 0; // defense
        abilities[3] = 0; // vision
        abilities[4] = 0; // cleverness
    }

    public Move move(char[][] fields) {
        int vision = getVisionFieldsCount();
        char me = fields[vision][vision]; // middle of fields
        int potentialPrey = Integer.MAX_VALUE;
        Move bestMove = Move.getRandom();
        for (Move move : Move.values()) {
            int goodPrey = 0;
            for (int i = 1; i <= vision; i++) { // loop through fields in specific direction
                int fieldX = vision + (i * move.getXOffset());
                int fieldY = vision + (i * move.getYOffset());


                // Try to ignore other aliens
                if (fields[fieldX][fieldY] == 'A') {
                    goodPrey--;
                } else if (fields[fieldX][fieldY] != ' ') { // Look for interesting prey that gives good stat boosts: whale, cow or turtle
                    if(getLifeLvl() > 10){
                        goodPrey++;
                        if (getLifeLvl() < (10 + abilities[0] * 5) * 0.4 && fields[fieldX][fieldY] != 'W') //start prioritizing whales once at 40% health in order to heal
                            goodPrey++;
                    } else goodPrey--; // Always run away when near death
                }

            }
            if (goodPrey > potentialPrey) {
                bestMove = move;
                potentialPrey = goodPrey;
            }
        }
        return bestMove;

    }

    public boolean wantToFight(int[] enemyAbilities) {
        // if it's a whale, always engage when above 10hp
        int combatLvl = enemyAbilities[0] + enemyAbilities[1] + enemyAbilities[2];

        if (getLifeLvl() > 10 && enemyAbilities[0] == 10 && enemyAbilities[1] != 10 && enemyAbilities[2] != 10 && combatLvl == 10){
            return true;
        } else 
            // if it's a cow, always engage when above 15hp
            if(getLifeLvl() > 15 && enemyAbilities[0] != 10 && enemyAbilities[1] == 10 && enemyAbilities[2] != 10 && combatLvl == 10) {
            return true;
        } else 
            // if it's a turtle, always engage when above 10hp
            if(getLifeLvl() > 10 && enemyAbilities[0] != 10 && enemyAbilities[1] != 10 && enemyAbilities[2] == 10 && combatLvl == 10) {
            return true;
        } else 
            //Puny Eagle is weak; CorporateAlien crush puny eagle
            if (combatLvl == 0 && getLifeLvl() > 10) {
                return true;
            } else {
            float dodgeChance = (float) (abilities[2] +1 <= 33 ? 1.333 : 1.5);
            if(getLifeLvl() / ((enemyAbilities[1]/2)+1) > (((enemyAbilities[0]*5)+10) * dodgeChance) / abilities[1]/2 )
                return true;
        }           
        return false;
    }
}
\$\endgroup\$
  • 2
    \$\begingroup\$ Good idea! But killing humans and eagles is also good, because you get their abilities (which is all that counts at the end of the game). \$\endgroup\$ – CommonGuy Jul 4 '14 at 11:28
  • 1
    \$\begingroup\$ Yeah, just thought of that. Already modified it. \$\endgroup\$ – Andreas Jul 4 '14 at 11:31
  • \$\begingroup\$ Nooo. Leave Bender the humans. }:D \$\endgroup\$ – Michael Jul 4 '14 at 22:54
  • \$\begingroup\$ @Manu Small update - Stole the .5 ability idea from the choose your battles alien (give him/her an upvote as thanks). Currently reworking my avoid and combat algorithms \$\endgroup\$ – Andreas Jul 8 '14 at 11:22
  • \$\begingroup\$ @Andreas What's the .5 ability idea? o.O \$\endgroup\$ – Spedwards Jul 8 '14 at 11:22
1
\$\begingroup\$

Assassin

Goes for turtles to gain extra defense, then goes for humans, then he's satisfied and moves randomly. In all this he's open to fighting whales.

package alien;

import planet.Move;

public class Assassin extends Alien {

    public void setAbilityPoints(float[] abilities) {
        abilities[1] = 10; //strength
        abilities[3] = 0; //vision
    }

    public Move move(char[][] fields) {
        // Get yo' priorities sorted!
        int dir = 0;
        if (getDefenseLvl() < 30) {
            if (dir == 0) {
                dir++;
                return Move.WEST;
            } else if (dir == 1) {
                dir--;
                return Move.SOUTH;
            }
        } else if (getClevernessLvl() < 30) {
            if (dir == 0) {
                dir++;
                return Move.EAST;
            } else if (dir == 1) {
                dir--;
                return Move.NORTH;
            }
        } 
        return Move.getRandom();
    }

    public boolean wantToFight(int[] enemyAbilities) {
        return enemyAbilities[2] >= 10 || enemyAbilities[0] >= 10;
    }

}
\$\endgroup\$
  • \$\begingroup\$ You could use return enemyAbilities[2] >= 10;, which would produce the same behaviour as your code but is easier to read ;) \$\endgroup\$ – CommonGuy Jul 8 '14 at 10:50
  • \$\begingroup\$ @Manu I usually spot those tricks... Surprised I missed it this time. \$\endgroup\$ – Spedwards Jul 8 '14 at 10:51
  • \$\begingroup\$ what is dir for? \$\endgroup\$ – Joshua Jul 8 '14 at 11:43
  • \$\begingroup\$ @Joshua Alternate between south and west \$\endgroup\$ – Spedwards Jul 8 '14 at 11:49
  • 1
    \$\begingroup\$ @Spedwards You alien had some compilation errors. I have fixed them on your behalf. Feel free to revert/change the fix if not desired. \$\endgroup\$ – Moogie Jul 11 '14 at 22:02
1
\$\begingroup\$

GentleGiant

The GentleGiant has high life and strength, but chooses not to fight unless the enemy is an eagle. He doesn't like eagles. They can fly up to his head and peck on his tender nose.

package alien;

import planet.Move;

public class GentleGiant extends Alien {

    public void setAbilityPoints(float[] abilities) {
        abilities[0] = 3.5; //life
        abilities[1] = 5.5; //strength
        abilities[2] = 0; //defense
        abilities[3] = 1; //vision
        abilities[4] = 0; //cleverness
    }

    public Move move(char[][] fields) {
        //you are in the middle of the fields, say fields[getVisionFieldsCount()][getVisionFieldsCount()]
        int vision = getVisionFieldsCount(); 
        Move bestMove=Move.STAY;
         for (Move move : Move.values()) {
            for (int i = 1; i <= vision; i++) {
                int fieldX = vision + (i * move.getXOffset());
                int fieldY = vision + (i * move.getYOffset());
                if (fields[fieldX][fieldY] == 'E') {
                    bestMove=move;
                }
            }
         }
        return bestMove;
    }

    public boolean wantToFight(int[] enemyAbilities) {
        if(enemyAbilities[3]==10 && sumAbilities(enemyAbilities)==10){
            return true;
        }
        else return false;
    }

    int sumAbilities(int[] abilities){
        int sum=0;
        for(int ability : abilities){
            sum+=ability;
        }
        return sum;
    }

}
\$\endgroup\$
1
\$\begingroup\$

Stone

Note that code is taken from @TimTech : Bananapeel

public class Stone extends Alien{
    public void setAbilityPoints(float[] abilities){
        abilities[0] = 0;  // Stones are not alive
        abilities[1] = 10;  // Stones are strong
        abilities[2] = 0;  // Stones can't defend themselves
        abilities[3] = 0;  // Stones can't see
        abilities[4] = 0;  // Stones peels can't think
    }

    public Move move(char[][] fields){
        return Move.SOUTH; // Stones just fall down
    }

    public boolean wantToFight(int[] enemyAbilities){
        return enemyAbilities[1] <=2 ; // Stones don't pick fights often.
    }
}
\$\endgroup\$
-1
\$\begingroup\$

My Alien species are so advanced that can alter the reality with their conscience.

At first I wanted to name them 'Q', but then I called them 'Cheater' because I'm gonna be disqualified anyways.

package alien;

import planet.Move;

public class Cheater extends Alien {
    @Override
    public void setAbilityPoints(float[] abilities) {
        abilities[0] = 2; //life
        abilities[1] = 2; //strength
        abilities[2] = 2; //defense
        abilities[3] = 2; //vision
        abilities[4] = 2; //cleverness
    }

    @Override
    public Move move(char[][] fields) {
        return Move.getRandom();
    }

    @Override
    public boolean wantToFight(int[] enemyAbilities) {
        return true;
    }

    @Override
    public int getStrengthLvl() {
        return Integer.MAX_VALUE;
    }

    @Override
    public int getLifeLvl() {
        return Integer.MAX_VALUE;
    }

    @Override
    public int getDefenseLvl() {
        return Integer.MAX_VALUE;
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ This 'cheat' was already used. \$\endgroup\$ – Spedwards Jul 4 '14 at 11:29
  • 3
    \$\begingroup\$ actually, you get instakilled if you start of with more than 10 bonus attribute points \$\endgroup\$ – Andreas Jul 4 '14 at 11:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.