生存游戏-AlienWar


96

异形战争

这场比赛发生在一个非常拥挤的星球上,外星人是最出色的种族。您的任务是创建自己的外星人并击败其他所有外星人。

董事会

这是一个二维板。
木板一侧的长度Math.ceil(sqrt(species * 100 * 2.5))约为所用木板的40%。棋盘是一颗行星,因此,如果您走出西部的地图,便会回到东部。如果您在北部走出去,就会发现自己在南部。

能力

地球上的每个物种都有能力。他们来了:

名称        受益 
寿命HP = lifeLVL * 5(每次击中都会减少,0 =死亡),基本HP = 10
强度你的命中值在[1至强度LVL]伤害范围内随机产生一个整数
防御在[0到(50 / 防御LVL + 1)] 范围内随机选择int ,如果int == 0,则躲避下一次攻击
视力带给您视力LVL / 2视野
机灵当发送给其他外星人时,会随机模糊(增加)[从0到clevernessLVL / 2]
 范围内的每个能力

游戏

  • 每个提交将有100个实例。
  • 实例化后,每个外星人总共可以设置10个能力点。您可以为每个实例设置不同的点。
  • 如果设置的点数超过10,实例将死亡。
  • 一场比赛包括1000发回合。每轮:
    • 每个外星人都必须通过来退回行动move(char[] fields)。这包括Move.STAY。
    • 如果有几个外星人在场上,将随机选择2个:
      • 如果双方都同意和平(返回错误wantToFight),他们将留在原地,否则他们将战斗。
      • 这样循环直到只有一个外星人留在田野上或者所有人都同意和平。
  • 如果一个外星人杀死了某些东西,他将获得每一种敌人技能的1/5。获胜者HP将被补充2 * 敌意生命LVL

  • 胜利者是最有能力的人(活着的外星人的能力之和)。

打架

两个外星人都将“同时打对方”,这意味着如果您杀死另一个外星人,他仍然可以打您一次。

躲避:在您被击中之前,游戏会计算您是否可以使用躲避攻击rand.nextInt(50 / defenseLvl + 1) == 0。在计算道奇技能时,defenceLvl绝不会大于50(因此,最大道奇机会为50%)。

击中:如果不躲避攻击,则会受到打击,并且HP会降低rand.nextInt(enemy.getStrengthLvl()) + 1

当涉及的一个或两个外国人死亡时,战斗结束。获胜者(如果存在)获得奖励。

游戏规则

  • 每个技能的基本等级(不给出任何技能点)为1(基本HP为10)。
  • 当要求战斗时发送的值是生命(不是生命!),力量,防御力和视野水平。
  • 当要求战斗时,不会发送聪明。
  • 使用/发送所有浮点数时,它们都会被舍入到最接近的整数,但会以浮点数形式存储和增加。
  • 最大闪避几率是50%。否则,战斗可能永远不会终止。

猎物

已有5种在场上。由于它们是猎物,因此他们在被要求时选择不战斗。

鲸鱼:10级生命住宿   
牛:10级力量随机移动
海龟:10级防御西南
鹰:10级视野检查领域,试图避免危险      
人类:10级智慧东北

它们将W在地图中以他们的第一个字母(即鲸鱼)表示(外星人带有A,空格为空白' ')。

附加规则

  • 禁止反思。
  • 禁止与其他外星人互动(实例化等)。
  • 也不允许读写文件或数据库之类的外部资源。
  • 仅允许Java(版本1.8)提交(Java非常简单,您不必是此游戏的专家)。
  • 所有提交的内容都必须扩展外星人类别,并将其放入外星人包中。
  • 我将在7月19日接受最佳外星人的邀请。在当天UTC 12:00之前提交的所有外国人都将接受测试。
  • 由于已经有很多外星人,因此每位用户最多只能提交3个信息。

外星人的例子

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;
    }

}

控制程序

控制程序的源代码可以在这里找到。现在更新了最新运行中包含的所有外星人。

最终比分(20.07.2014,平均10场比赛)

异族PredicatClaw 1635.4
懒人1618.8
漫画家LongVisionAlien 1584.6
选择你的战斗1571.2
弯曲者1524.5
外星人HerjanAlien 1507.5
外星人.FunkyBob 1473.1
Alien.SecretWeapon2 1467.9
外国人眼1457.1
Alien.CorporateAlien 1435.9
外星人GentleGiant 1422.4
Alien.CropCircleAlien 1321.2
VanPelt 1312.7
NewGuy 1270.4外星人
香蕉皮1162.6
1159.2号外星人
外星人.BullyAlien 1106.3
杰弗里778.3
秘密武器754.9
Alien.SecretWeapon3 752.9
外星人.FunkyJack 550.3
石头369.4
刺客277.8
外星人Predicoward 170.1
捕食者牛155.2
外星人变形105.3
埃里99.6
战士69.7
猎人56.3
外星人37.6
冲绳生活14.2
捕食鲸10.5
外星人玩家4.5
Alien.Randomite 0
守卫者0
猎物。鹰0
外星人0
Alien.WeakestLink 0
外国人0   
幸存者0
速度0
外星人。垃圾0
外星人Co夫0
Alien.CleverAlien 0
猎物人类0
外星人盲目的0
猎物。海龟0
Alien.AimlessWanderer 0

14
三票,到底是什么?而且我没有看到任何负面评论。那些被动地激怒了这仅限于Java的人吗?
Martin Ender 2014年

6
@ m.buettner我的不赞成意见是对Java令人讨厌的限制(尽管如果它仅限于有史以来创建的最好的语言,我仍然会对其进行投票以将其限制为一种语言)。我看不出要添加评论的意义,因为显而易见的是,反对投票的目的是什么。
Gareth 2014年

6
嗯,我的心情很复杂
Alien先生2014年

5
@ user3334871我不认为在提交17个答案(可能还会有十几个人从事提交工作)之后更改任何规则是一个好主意。由于我们当中只有最少的人(如果有的话)是专业的游戏设计师,因此几乎所有的自制KotH都可能存在一些平衡问题-但是如果探索可行策略的空间仍然很有趣(显然是根据答案来判断,投票和加注星标),我认为这没什么大问题。
Martin Ender 2014年

5
@Manu对于数学上的偏见,有关如何包装纸板的描述有些误导。您是说它是一颗行星,它包裹着东西。也没有什么真正表明它确实向北/向南包裹。实际上,如果确实如此,从技术上讲它不再是一个球体,而是一个圆环:kotaku.com/classic-jrpg-worlds-are-actually-donuts-1239882216。您还可以注意到,当您“走开”世界地图的顶部(北极)时,您不会出现在底部(南极)。因此,我认为迈克尔的建议绝对正确。
Martin Ender 2014年

Answers:


11

PredicatClaw(原始)

如果您根据她的预测算法看起来很虚弱,那么这个猫科动物的外星人将整个吞下您(好吧,也许她会先给您一点咀嚼)。

一种比其他同类具有更尖的爪和尖牙的谓词。

编辑:新的目标优先事项

package alien;

import planet.Move;

/* Predict + Cat = Predicat! */
public class PredicatClaw extends Alien {
    private static final int LIF=0, STR=1, DEF=2;
    private static final int WHALE=6, COW=1, TURTLE=4, EAGLE=3, HUMAN=2, ALIEN=-1, NONE=0;

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

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

        /* Some credits to Eagle for letting me learn how to do the moves */
        int vision = getVisionFieldsCount(); //count of fields / middle
        int fieldX;
        int fieldY;
        Move bestMove=Move.STAY;
        int bestScore=-1;

       for (Move move : Move.values()) {
            fieldX = vision + move.getXOffset();
            fieldY = vision + move.getYOffset();
            switch(fields[fieldX][fieldY]){
            case 'W' : 
                if(bestScore<WHALE){
                    bestMove=move;
                    bestScore=WHALE;
                }
                break;
            case 'C' :
                if(bestScore<COW){
                    bestMove=move;
                    bestScore=COW;
                }
                break;
            case 'T' :
                if(bestScore<TURTLE){
                    bestMove=move;
                    bestScore=TURTLE;
                }
                break;
            case 'E' :
                if(bestScore<EAGLE){
                    bestMove=move;
                    bestScore=EAGLE;
                }
                break;
            case 'H' :
                if(bestScore<HUMAN){
                    bestMove=move;
                    bestScore=HUMAN;
                }
                break;
            case 'A' :
                if(bestScore<ALIEN){
                    bestMove=move;
                    bestScore=ALIEN;
                }
                break;
            case ' ' :
                if(bestScore<NONE){
                    bestMove=move;
                    bestScore=NONE;
                }
                break;
            }
        }

        if(vision==1 && bestScore>1){
            return bestMove;
        }

        //check immediate outer field
        for (int i=vision-2; i<=vision+2; i++) {
            for(int j=vision-2; j<=vision+2; j++){
                if(i==0 || i==4 || j==0 || j==4){
                    switch(fields[i][j]){
                    case 'W' :
                        bestMove = this.getBestMoveTo(i,j);
                        bestScore = WHALE;
                        break;
                    case 'C' :
                        if(bestScore<COW){
                            bestMove = this.getBestMoveTo(i,j);
                            bestScore = COW;
                        }
                        break;
                    case 'T' :
                        if(i>=vision && j<=vision){
                            return this.getBestMoveTo(i-1,j+1);
                        }
                        if(bestScore<TURTLE){
                            bestMove = this.getBestMoveTo(i,j);
                            bestScore = TURTLE;
                        }
                        break;
                    case 'E' :
                        if(bestScore<EAGLE){
                            bestMove = this.getBestMoveTo(i,j);
                            bestScore = EAGLE;
                        }
                        break;
                    case 'H' :
                        if(i<=vision && j>=vision){
                            return this.getBestMoveTo(i+1,j-1);
                        }
                        if(bestScore<HUMAN){
                            bestMove = this.getBestMoveTo(i,j);
                            bestScore = HUMAN;
                        }
                        break;
                    case 'A' :
                        if(bestScore<ALIEN){
                            bestMove = this.getBestMoveTo(i,j);
                            bestScore = ALIEN;
                        }
                        break;
                    case ' ' :
                        if(bestScore<NONE){
                            bestMove = this.getBestMoveTo(i,j);
                            bestScore = NONE;
                        }
                        break;
                    }
                }
            }
        }

        return bestMove;
    }

    @Override
    public boolean wantToFight( int[] enemyAbilities ) {
        /*
            Fight IF
                1) I CAN BEAT YOU
                2) ????
                3) MEOW!
        */
        float e_hp = enemyAbilities[LIF]*5+10;
        float e_dmg = 1 + enemyAbilities[STR]/2;
        float e_hit = 1 - (1/(50/this.getDefenseLvl()+1));

        float m_hp = this.getCurrentHp();
        float m_dmg = 1 + this.getStrengthLvl()/2;
        float m_hit = 1 - (1/(50/enemyAbilities[DEF]+1));

        return (e_hp/(m_dmg*m_hit) < m_hp/(e_dmg*e_hit));
    }

    private Move getBestMoveTo(int visionX, int visionY){
        int vision = getVisionFieldsCount();

        if(visionX < vision && visionY < vision){
            return Move.NORTHWEST;
        }
        else if(visionX > vision && visionY < vision){
            return Move.NORTHEAST;
        }
        else if(visionX < vision && visionY > vision){
            return Move.SOUTHWEST;
        }
        else if(visionX > vision && visionY < vision){
            return Move.SOUTHEAST;
        }
        else if(visionX == vision && visionY < vision){
            return Move.NORTH;
        }
        else if(visionX == vision && visionY > vision){
            return Move.SOUTH;
        }
        else if(visionX > vision && visionY == vision){
            return Move.EAST;
        }
        else if(visionX < vision && visionY == vision){
            return Move.WEST;
        }
        else{
            return Move.WEST;
        }

    }
}

1
该死的!那些谓词很厉害!我注意到我们俩或多或少都采用了相同的wantToFight算法。
James_pic

@James_pic,我看到伟大的思想家也有相同的想法。:D
Mark Gabriel 2014年

27

经理

这是一个经理。自然,聪明是0,他总是努力去朝着太阳不发光的地方。而且,当然,他只会与弱者抗争,并且善于规避麻烦:

public class Manager extends Alien {

    private static final int STRENGTH = 5;

    @Override
    public void setAbilityPoints( float[] abilities ) {
        abilities[/* strength   */ 1] = STRENGTH;
        abilities[/* defense    */ 2] = 5;
        abilities[/* cleverness */ 4] = 0; // just to make sure
    }

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

    @Override
    public boolean wantToFight( int[] enemyAbilities ) {
        return enemyAbilities[1] < STRENGTH;
    }
}

+1(如果仅用于介绍)。:P
apnorton 2014年

6
每次我读到该评论(“只是为了确保”)时,我都必须笑:-D
Matthias

有趣的是,我只是在阅读以下内容:blog.codinghorror.com/i-shall-call-it-somethingmanager
1

@ 11684任何像样的开发人员都知道,当然,但对我来说其实我的意思是经理;)
英戈·伯克

18

制图LongVisionAlien

这个外星人是我尝试生产具有获胜潜力的外星人的尝试之一,表现一致。

它具有最初的5x5视野,可用于构建周围区域的内部地图,从而具有出色的躲避敌人的能力。

在我对100发子弹的测试中,它平均比其他所有外星人都先行。(09/07/2014)

更新的GIF显示排斥/吸引场效应

我修改了游戏代码,以生成模拟的动画GIF。您可以在这里查看这样的模拟

 package alien;

 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Random;
 import planet.Move;
 import planet.Planet;

 /**
  * Created by moogie on 09/07/14.
  * 
  * This Alien attempts to map the visible and guess the movements within the immediate non-visible area around the alien.
  * To this end, the alien can initially see 5x5 grid. It applies weights on the cells of its internal map based on the 
  * prey/alien/blanks within its field of view. It then performs a simple blur to guess movements and then chooses the optimum move
  * based on the contents of its internal map.
  * 
  * If it is asked to fight, it performs battle simulations to determine whether it should nominate to fight.
  */
 public class CartographerLongVisionAlien extends Alien
 {
   private final static byte LIFE = 0, STR = 1, DEF = 2, VIS = 3, CLV = 4;

   // Plant Entity symbols
   private static final char TURTLE = 'T';
   private static final char HUMAN = 'H';
   private static final char WHALE = 'W';
   private static final char COW = 'C';
   private static final char EAGLE = 'E';
   private static final char ALIEN = 'A';
   private static final HashMap<Character, Move> preyMovement = new HashMap<>();

   static 
   {
     preyMovement.put(WHALE, Move.STAY);
     preyMovement.put(TURTLE, Move.SOUTHWEST);
     preyMovement.put(HUMAN, Move.NORTHEAST);
   };

   // Map constants
   public static final int MAP_SIZE_DIV_2 = 10;
   public static final int MAP_SIZE = MAP_SIZE_DIV_2 * 2 + 1;
   private static final int MAP_SIZE_MINUS_ONE = MAP_SIZE - 1;
   private static final double FADE_FACTOR=0.85;

   // Planet constants
   private static final int STARTING_HP = 10;
   private static final int START_HEALING_FACTOR = 5;
   private static final int MAX_DEFENCE = 50;

   // Battle Simulation constants
   private static final double AMBIGUOUS_ENEMY_HP_FACTOR = 2;
   private static final int SIMULATED_BATTLE_COUNT = 100;
   private static final int SIMULATED_BATTLE_THREASHOLD = (int)(SIMULATED_BATTLE_COUNT*1.0);

   private Random rand = new Random(Planet.rand.nextLong());

   /** The alien's map of the immediate and mid-range area */
   public double[][] map = new double[MAP_SIZE][MAP_SIZE];

   public void setAbilityPoints( float[] abilities )
   {
     // +0.5 gain due to rounding trick "borrowed" from PredicatClaw http://codegolf.stackexchange.com/a/32925/20193
     abilities[LIFE] = 3.5f; // We do need some hit points to ensure that we can survive the melee of the beginning game.
     abilities[STR] = 4.5f; // A Moderate attack strength means that we do not have to go through as many fight rounds.
     abilities[DEF] = 0; // We will get from prey and other aliens
     abilities[VIS] = 2; // A minimum of 2 is required to get a 5x5 field of view
     abilities[CLV] = 0; // We will get from prey and other aliens
   }

   /**
    * simulate alien memory fade. This allows an alien to eventually venture back to areas already traversed.
    */
   private void fadeMap()
   {
     for ( int y = 0; y < MAP_SIZE; y++ )
     {
       for ( int x = 0; x < MAP_SIZE; x++ )
       {
         map[x][y] *= FADE_FACTOR;
       }
     }
   }

   /**
    * shift the maps with the movement of the alien so that the alien is always at the centre of the map
    * 
    * @param move
    */
   private void shiftMaps( Move move )
   {
     int i, j;
     final int offsetX = -move.getXOffset();
     final int offsetY = -move.getYOffset();
     double[][] tempMap = new double[MAP_SIZE][MAP_SIZE];
     for ( int y = 0; y < MAP_SIZE; y++ )
     {
       for ( int x = 0; x < MAP_SIZE; x++ )
       {
         i = x + offsetX;
         j = y + offsetY;

         if ( i >= 0 && i <= MAP_SIZE_MINUS_ONE && j >= 0 && j <= MAP_SIZE_MINUS_ONE )
         {
           tempMap[i][j] = map[x][y];
         }
       }
     }
     map = tempMap;
   }

   /**
    * Updates a cell in the alien's map with the desirability of the entity in the cell
    * 
    * @param x
    * @param y
    * @param chr
    */
   private void updateMap( int x, int y, char chr )
   {
     // Note that these desire values are just guesses... I have not performed any analysis to determine the optimum values!
     // That said, they seem to perform adequately.
     double desire = 0;

     int i=x;
     int j=y;
     switch ( chr )
     {
       case WHALE:
         desire=2;
         break;
       case TURTLE:
       case HUMAN:
         desire=1;
         Move preyMove = preyMovement.get( chr );

         // predict movement into the future
         while ( i >= 0 && i <= MAP_SIZE_MINUS_ONE && j >= 0 && j <= MAP_SIZE_MINUS_ONE )
         {
           map[i][j] = ( map[i][j] + desire ) / 2;
           i+=preyMove.getXOffset();
           j+=preyMove.getYOffset();
           desire/=2;
         }
         break;
       case COW:
         desire = 0.5;
         break;
       case EAGLE:
         desire = 1;
         break;
       case ALIEN:
         desire = -10;
         break;
     }

     map[x][y] = ( map[x][y] + desire ) / 2;
   }

   /**
    * Apply a blur the map to simulate the movement of previously seen entities that are no longer within the field of view.
    */
   private void convolve()
   {
     double[][] tempMap = new double[MAP_SIZE][MAP_SIZE];

     int count;
     double temp;
     for ( int y = 0; y < MAP_SIZE; y++ )
     {
       for ( int x = 0; x < MAP_SIZE; x++ )
       {
         count = 0;
         temp = 0;
         for ( int i = x - 1; i < x + 2; i++ )
         {
           for ( int j = y - 1; j < y + 2; j++ )
           {
             if ( i >= 0 && i <= MAP_SIZE_MINUS_ONE && j >= 0 && j <= MAP_SIZE_MINUS_ONE )
             {
               temp += map[i][j];
               count++;
             }
           }
         }
         temp += map[x][y] * 2;
         count += 2;

         tempMap[x][y] = temp / count;
       }
     }
     map = tempMap;
   }

   /**
    * Determine the move that minimises the risk to this alien and maximises any potential reward.
    * 
    * @param fields
    * @return
    */
   private Move findBestMove( char[][] fields )
   {
     List<Move> moveOptions = new ArrayList<>();
     double bestMoveScore = -Double.MAX_VALUE;
     double score;

     // find the moves that have the best score using the alien's map
     for ( Move move : Move.values() )
     {
       int x = MAP_SIZE_DIV_2 + move.getXOffset();
       int y = MAP_SIZE_DIV_2 + move.getYOffset();
       score = map[x][y];
       if ( score == bestMoveScore )
       {
         moveOptions.add( move );
       }
       else if ( score > bestMoveScore )
       {
         bestMoveScore = score;
         moveOptions.clear();
         moveOptions.add( move );
       }
     }

     Move move = moveOptions.get( rand.nextInt( moveOptions.size() ) );

     // if the best move is to stay...
     if ( move == Move.STAY )
     {
       // find whether there are no surrounding entities in field of vision...
       int midVision = getVisionFieldsCount();
       boolean stuck = true;
       out: for ( int i = 0; i < fields.length; i++ )
       {
         for ( int j = 0; j < fields.length; j++ )
         {
           if ( !( i == midVision && j == midVision ) && fields[i][j] != ' ' )
           {
             stuck = false;
             break out;
           }
         }
       }

       // there there are no other entities within field of vision and we are healthy... choose a random move
       if ( stuck && getCurrentHp() > getLifeLvl() * 2 )
       {
         move = Move.getRandom();
       }
     }
     return move;
   }

   /**
    * Update the alien's map with the current field of vision
    * 
    * @param fields
    */
   private void mapVisibleSurroundings( char[][] fields )
   {
     int midVision = getVisionFieldsCount();

     // update the map with currently visible information
     for ( int y = -midVision; y <= midVision; y++ )
     {
       for ( int x = -midVision; x <= midVision; x++ )
       {
         char chr = fields[midVision + x][midVision + y];
         updateMap( MAP_SIZE_DIV_2 + x, MAP_SIZE_DIV_2 + y, chr );
       }
     }

     // ensure that the map where this alien currently sits is marked as empty.
     updateMap( MAP_SIZE_DIV_2, MAP_SIZE_DIV_2, ' ' );
   }

   public Move move( char[][] fields )
   {
     Move returnMove = null;

     // pre-move decision processing
     mapVisibleSurroundings( fields );
     convolve();

     returnMove = findBestMove( fields );

     // post-move decision processing
     fadeMap();
     shiftMaps( returnMove );

     return returnMove;
   }

   public boolean wantToFight( final int[] enemyAbilities )
   {
     double toughnessFactor =((double) enemyAbilities[STR])/(enemyAbilities[LIFE]*10); // a fudge-factor to ensure that whales are attacked.
     if (enemyAbilities[VIS]>=3 && enemyAbilities[LIFE]>4.5f) toughnessFactor*=3.5; // make sure that we do not attack other Cartogapher aliens 
     return winsBattleSimulation( enemyAbilities, toughnessFactor );
   }

   /**
    * Perform simulations to determine whether we will win against the enemy most of the time.
    * 
    * @param enemyAbilities
    * @return
    */
   private boolean winsBattleSimulation( int[] enemyAbilities, double toughnessFactor )
   {
     int surviveCount = 0;
     for ( int i = 0; i < SIMULATED_BATTLE_COUNT; i++ )
     {
       int estimatedEnemyHitPoints =
           STARTING_HP + (int)( enemyAbilities[LIFE] * START_HEALING_FACTOR * AMBIGUOUS_ENEMY_HP_FACTOR * toughnessFactor );
       int enemyPoints = estimatedEnemyHitPoints;
       int myHitPoints = getCurrentHp();
       int myDefenceLevel = getDefenseLvl() < MAX_DEFENCE ? getDefenseLvl() : MAX_DEFENCE;
       int enemyDefenceLevel = enemyAbilities[DEF] < MAX_DEFENCE ? enemyAbilities[DEF] : MAX_DEFENCE;

       while ( !( myHitPoints <= 0 || enemyPoints <= 0 ) )
       {
         if ( rand.nextInt( MAX_DEFENCE / myDefenceLevel + 1 ) != 0 )
         {
           myHitPoints -= rand.nextInt( enemyAbilities[STR] ) + 1;
         }

         if ( rand.nextInt( MAX_DEFENCE / enemyDefenceLevel + 1 ) != 0 )
         {
           enemyPoints -= rand.nextInt( getStrengthLvl() ) + 1;
         }
       }
       if ( myHitPoints > 0 )
       {
         surviveCount++;
       }
     }
     return ( surviveCount >= SIMULATED_BATTLE_THREASHOLD );
   }

 }

已更新,以增加对猎物的未来预测并确保鲸鱼很可能受到攻击
Moogie 2014年

4
好极了!最后,一个外星人获胜,他不仅依靠力量和生命,而且还
依靠

3
要获得表现出色的外星人非常困难!其他头号进入者大多都遵循相同的想法:避开外星人,攻击猎物,仅发起几乎可以保证自己获胜的战斗。这个外星人遵循相同的想法,但是更好地避免了外星人。这给了它一点优势,因为如果打败了,获得更多的能力就更“昂贵”了。
Moogie 2014年

我曾尝试过其他更奇特的想法,但没有足够的信息公开。即地图大小,外星人数量等
Moogie 2014年

很好!我也对缺乏信息感到有些沮丧-从过去中提取更多信息很有创意。
Benny

15

选择你的战斗

这个外星人与其他外星人背道而驰,但是却朝着猎物奔跑(只要这不会把它带向外星人)。

我使用遗传算法来帮助我选择起始值。结果表明,我们应该依靠力量和生活来度过早期的蝙蝠。视觉在以后很有用,但我们可以从战败的敌人中了解。

我们只打那些我们认为可以轻松获胜的战斗-我们估计杀死敌人需要多少步,杀死敌人需要多少步,并且只有在我们“努力两次”的情况下才加入战斗我们的对手。

package alien;

import planet.Move;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import static java.lang.Math.*;

public class ChooseYourBattles extends Alien {
    private static final boolean DEBUG = false;
    private static final int LIFE = 0;
    private static final int STRENGTH = 1;
    private static final int DEFENCE = 2;
    private static final int VISION = 3;
    private static final int CLEVERNESS = 4;
    private static final Set<Character> prey = new HashSet<>();
    {
        Collections.addAll(prey, 'H', 'T', 'W', 'C', 'E');
    }

    public void setAbilityPoints(float[] abilities) {
        // Rounding promotes these to 4 and 7 - 11 points!
        abilities[LIFE] = 3.5f;
        abilities[STRENGTH] = 6.5f;
    }

    @Override
    public Move move(char[][] fields) {
        if (DEBUG) {
            StringBuilder sb = new StringBuilder();
            for (int j = 0; j < 2 * getVisionFieldsCount() + 1; j++) {
                for (int i = 0; i < 2 * getVisionFieldsCount() + 1; i++) {
                    char chr = fields[i][j];
                    if (chr == ' ') chr = '.';
                    if (i == getVisionFieldsCount() && j == getVisionFieldsCount()) chr = 'X';
                    sb.append(chr);
                }
                sb.append('\n');
            }
            String view = sb.toString();
            System.out.println(this.toString());
            System.out.println(view);
        }

        Move bestMove = null;
        int bestEnemyDistance = Integer.MIN_VALUE;
        int bestPreyDistance = Integer.MAX_VALUE;

        for (Move tryMove: Move.values()) {
            int currentDistanceToEnemy = Integer.MAX_VALUE;
            int currentDistanceToPrey = Integer.MAX_VALUE;
            int x = getVisionFieldsCount() + tryMove.getXOffset();
            int y = getVisionFieldsCount() + tryMove.getYOffset();
            for (int i = 0; i < 2 * getVisionFieldsCount() + 1; i++) {
                for (int j = 0; j < 2 * getVisionFieldsCount() + 1; j++) {
                    char chr = fields[i][j];
                    if (chr == 'A' && (i != getVisionFieldsCount() || j != getVisionFieldsCount())) {
                        // Use L-infinity distance, but fll back to L-1 distance
                        int distance = max(abs(i - x), abs(j - y)) * 100 + abs(i -x) + abs(j - y);
                        if (distance < currentDistanceToEnemy) currentDistanceToEnemy = distance;
                    } else if (prey.contains(chr)) {
                        int distance = max(abs(i - x), abs(j - y)) * 100 + abs(i -x) + abs(j - y);
                        if (distance < currentDistanceToPrey) currentDistanceToPrey = distance;
                    }
                }
            }
            if (currentDistanceToEnemy > bestEnemyDistance
                    || (currentDistanceToEnemy == bestEnemyDistance && currentDistanceToPrey < bestPreyDistance)) { // Prefer to stay put
                bestMove = tryMove;
                bestEnemyDistance = currentDistanceToEnemy;
                bestPreyDistance = currentDistanceToPrey;
            }
        }

        if (DEBUG) {
            System.out.println("Going " + bestMove);
            System.out.println();
        }
        return bestMove;
    }

    @Override
    public boolean wantToFight(int[] enemyAbilities) {
        // Estimate whether likely to survive the encounter - are we at least "twice as hard" as our opponent
        return getCurrentHp() * (50.0 + getDefenseLvl()) / (enemyAbilities[STRENGTH])
                > 2.0 * (enemyAbilities[LIFE] * 5 + 10) * (50.0 + enemyAbilities[DEFENCE])/ (getStrengthLvl());
    }

    @Override
    public String toString() {
        return "ChooseYourBattles" + System.identityHashCode(this)
                + ": HP " + getCurrentHp()
                + ", LFE " + getLifeLvl()
                + ", STR " + getStrengthLvl()
                + ", DEF " + getDefenseLvl()
                + ", VIS " + getVisionLvl()
                + ", CLV " + getClevernessLvl();
    }
}

如果您想运行自己的遗传算法/育种程序,我将为此目的提供一份控制程序分叉副本


这如何绕过checkAbilitesOk方法检查?
FreeAsInBeer 2014年

checkAbilitiesOk检查数组中的浮点数总计为10.0。但是,float值在游戏逻辑中四舍五入为int,而Java四舍五入为0.5。
2014年

@justhalf仍然设置10点,它们只是智能分配。
CommonGuy 2014年

1
我应该说这最初不是我的想法-我是从PredicatClaw借来的
James_pic 2014年

1
非常好。您的统计常数可能比我的好,而您的wantToFight肯定更聪明,我只是懒惰。:)
Benny

12

容基

这个外星人沉迷于某种东西。他以令人讨厌的解决方法开始战争。

当他的动作变得强壮(fix > 3)时,他很高兴坐在自己的木凳上,为任何事情准备。

但是,一旦他的修复程序开始fix <= 3失效(),他就开始朝着无法分辨的方向绊倒,试图找出发生了什么。如果要求打架,他会变得谨慎,只有在认为自己可以赢的情况下才打架。

一旦他的修复用尽,成为瘾君子,他必须重新开始恶性循环。

public class Junkie extends Alien {
    private int fix = 10;

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

    public Move move(char[][] fields) {
        fix -= 1;
        if (fix == 0) {
            fix = 10;
        }
        else if(fix <= 3 && fix > 0) {
            return Move.getRandom();
        }

        return Move.STAY;
    }

    public boolean wantToFight(int[] enemyAbilities) {
        if(fix > 3) {
            return true;
        }
        // Am I stronger than their defense and can I withstand their attack?
        else if(enemyAbilities[2] < getStrength() && enemyAbilities[1] < getDefense()) {
            return true;
        }

        return false;
    }
}

我很确定,&& fix > 0由于冗余,可以安全删除。
Timtech

10

香蕉皮

只尝试绊倒需要重击的人。击败它不会使您更健康。

package alien;

import planet.Move;
public class BananaPeel extends Alien{
    public void setAbilityPoints(float[] abilities){
        abilities[0] = 0.5f;  // banana peels barely hold themselves together
        abilities[1] = 9.5f;  // banana peels can't help tripping people up
        abilities[2] = 0;  // banana peels can't defend themselves
        abilities[3] = 0;  // banana peels can't see
        abilities[4] = 0;  // banana peels can't think
    }

    public Move move(char[][] fields){
        return Move.STAY; // banana peels can't move
    }

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

它也是非常重要的发现,[0]是生活,而不是健康,那么100就是510 HP(或更少,根据已经采取的损坏),但我不知道,如果一个外国人会得到高..
Gigala

@Gigala好主意,我已经对其进行了一些更改。
Timtech

9

范佩尔特

来自Jumanji的猎人。当他没有受伤时,他会打猎;当他受伤时,他会回避。他是他能杀人的好法官。香蕉皮不断使他绊倒,但教会了他一些新技巧。

package alien;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

import planet.Move;

public class VanPelt extends Alien {

    private static final int LIFE = 0;
    private static final int STRENGTH = 1;
    private static final int DEFENSE = 2;
    private static final int VISION = 3;
    private static final int CLEVER = 4;

    // we all agreed before starting to move a certain direction if we're not
    // hunting or avoiding, helps avoid self-collisions... since we can't tell 
    // who we're fighting
    private static Move randomMove = Move.getRandom();

    @Override
    public void setAbilityPoints(float[] abilities) {
        abilities[LIFE] = 3.5f;
        abilities[STRENGTH] = 6f;
        abilities[VISION] = 0.5f;
    }

    @Override
    public Move move(char[][] fields) {
        int curHealth = this.getCurrentHp();
        List<Target> targets = new LinkedList<Target>();
        int vision = getVisionFieldsCount();
        boolean foundMe = false;
        for (int x = 0; x < fields.length; x++) {
            for (int y = 0; y < fields[x].length; y++) {
                switch (fields[x][y]) {
                case ' ' :
                    continue;
                case 'A' :
                    if (!foundMe && x == vision && y == vision) {
                        foundMe = true;
                        continue;
                    }
                    break;
                }
                targets.add(new Target(-vision + x, -vision + y, fields[x][y]));
            }
        }
        // if we're low health we need to move away from danger
        double desiredX = 0;
        double desiredY = 0;
        if (curHealth < this.getLifeLvl() * 7) {
            for (Target t : targets) {
                if (t.id == 'A') {
                    // closer aliens are more dangerous
                    desiredX -= vision / t.x;
                    desiredY -= vision / t.y;
                }
            }
        } else {
            // seek and destroy closest prey
            Collections.sort(targets);
            for (Target t : targets) {
                if (t.id != 'A') {
                    desiredX = t.x;
                    desiredY = t.y;
                    break;
                }
            }
        }
        desiredX = (int)Math.signum(desiredX);
        desiredY = (int)Math.signum(desiredY);
        for (Move m : Move.values()) {
            if (m.getXOffset() == desiredX && m.getYOffset() == desiredY) {
                return m;
            }
        }

        return randomMove;
    }

    @Override
    public boolean wantToFight(int[] enemyAbilities) {
        // we don't want to fight if we're hurt
        int curHealth = this.getCurrentHp();
        if (curHealth < this.getLifeLvl() * 4) {
            return false;
        }
        // determine if we're fighting prey
        int count = 0;
        int abilityMaxed = 0;
        int total = 0;
        for (int i = 0; i < enemyAbilities.length; i++) {
            total += enemyAbilities[i];
            if (enemyAbilities[i] == 11) {
                count++;
                abilityMaxed = i;
            }
        }
        // very likely to be prey, ignoring cows... they're dangerous
        if (abilityMaxed != STRENGTH && (count == 1 || total < 10)) {
            return true;
        }

        // else use a scoring system with tinkered constants
        double score = enemyAbilities[LIFE] * 4.0 
                + enemyAbilities[DEFENSE] * 0.5 
                + enemyAbilities[STRENGTH] * 5.0;

        double myScore = this.getDefenseLvl() * 0.5 +
                this.getStrengthLvl() * 5.0 +
                this.getCurrentHp() * 2.5;

        return myScore > score * 2;
    }



    private class Target implements Comparable<Target> {
        public int x, y;
        public char id;
        public int distanceSq;

        public Target(int x, int y, char id) {
            // adjust for known movement patterns
            switch(id) {
            case 'T' :
                x += Move.SOUTHWEST.getXOffset();
                y += Move.SOUTHWEST.getYOffset();
                break;
            case 'H' :
                x += Move.NORTHEAST.getXOffset();
                y += Move.NORTHEAST.getYOffset();
                break;
            }
            this.x = x;
            this.y = y;
            this.id = id;

            distanceSq = x * x + y * y;
        }

        @Override
        public int compareTo(Target other) {
            return distanceSq - other.distanceSq;
        }
    }

}

学会避免香蕉皮,是吗?:P
Timtech

8

冲绳生活

难怪我会成为最后一名。

package alien;

import planet.Move;


public class OkinawaLife extends Alien{
    public void setAbilityPoints(float[] abilities){
        abilities[0] = 8.5f;
        abilities[1] = 0.5f;
        abilities[3] = 1;
    }

    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 ' ': break;
                    case 'C': break;
                    case 'E': break;
                    case 'H': break;
                    default: danger--;
                }
            }
            if (danger < leastDanger) {
                bestMove = move;
                leastDanger = danger;
            }
        }
        return bestMove;
    }

    public boolean wantToFight(int[] enemyAbilities){
        return enemyAbilities[1] == 0;
    }
}

7

猎人

我也只是偷走了老鹰的运动,除了现在他想去探寻其他外星人以外的一切。尝试狩猎并尽可能多地捕获猎物,并且仅在看起来有很大获胜机会时才进行战斗。

package alien;

import planet.Move;

public class Hunter extends Alien   {
    private final static byte LIFE=0, STR=1, DEF=2, VIS=3, CLV=4;

    public void setAbilityPoints(float[] abilities) {
        abilities[LIFE] = 0;
        abilities[STR] = 9;
        abilities[DEF] = 0;
        abilities[VIS] = 1;
        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 ' ': break;
                    default: danger--;
                }
            }
            if (danger < leastDanger) {
                bestMove = move;
                leastDanger = danger;
            }
        }
        return bestMove;
    }

    public boolean wantToFight(int[] enemyAbilities)    {
        return ((double)this.getCurrentHp() * this.getDefenseLvl()) / (double)enemyAbilities[STR] > (enemyAbilities[LIFE] * enemyAbilities[DEF]) / this.getStrengthLvl();
    }
}

7

超过9000!

package alien;

import planet.Move;

public class Over9000 extends Alien {
    public void setAbilityPoints(float[] abilities) {
        abilities[0] = 10;
    }

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

    public boolean wantToFight(int[] enemyAbilities) {
        return enemyAbilities[1] <= 9000;
    }

    @Override
    public int getStrengthLvl() {
        return 9001; // It's over 9000!!!!!!111
    }
}

是的,这是对作弊的公然尝试,但确实会破坏规则。如果planet.Specie最终的吸气剂被制止,这个漏洞将会关闭。


4
不好了!我知道我忘记了什么...我将关闭漏洞并+1;)
CommonGuy 2014年

我有点失望的是,这个答案比我的其他更老的,目前获奖的作品具有更多的赞誉。
James_pic 2014年

7

岩石

我认为它只会攻击弱者和“聪明”的人。

package alien;

import planet.Move;

public class Rock extends Alien{
    public void setAbilityPoints(float[] abilities){
        abilities[0] = 0.5f;
        abilities[1] = 9.5f;
    }

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

    public boolean wantToFight(int[] enemyAbilities){
        return enemyAbilities[0] + enemyAbilities[1] + enemyAbilities[2] + enemyAbilities[3] < 10;
    }
}

3
我不确定一旦赢得胜利,一旦敌人开始获得一些增益,Rock会持续多久。看起来不错。
Kyle Kanos 2014年

@KyleKanos我了解;但是,我假设我会与大多数猎物/外星人战斗,只要它们不聪明。这也不会给他一些爱好者吗?
Timtech

现在回头看我的评论,我认为这根本不是我想说的。我想说的wantToFight是,true当敌人开始以水平方式进行抛光时,情况将不会消失。您会很快转向坚强的和平主义者。
凯尔·坎诺斯

@KyleKanos哦,知道了。我把它改了一下。
Timtech

6

变形

没想到别的名字了,这个家伙随机分配10点能力。几乎像冲绳生命(需要您的努力)一样移动,并且只想在他的力量大于敌人的力量时战斗。

package alien;

import planet.Move;
import java.util.Random;


public class Morphling extends Alien {

    @Override
    public void setAbilityPoints(float[] abilities) {
        Random rand = new Random();
        for(int attr = 0, maxPoints = 10, value = rand.nextInt(maxPoints); attr <5 && maxPoints > 0 ; attr++, maxPoints -=value, value = rand.nextInt(maxPoints)){
            abilities[attr] = value;
            if(attr == 4 && (maxPoints-=value) > 0){
                abilities[1]+=maxPoints;
            }
        }
    }

    @Override
    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 ' ': break;
                    case 'T': break;
                    case 'E': break;
                    case 'H': break;
                    default: danger--;
                }
            }
            if (danger < leastDanger) {
                bestMove = move;
                leastDanger = danger;
            }
        }
        return bestMove;
    }

    @Override
    public boolean wantToFight(int[] enemyAbilities) {
        return getStrengthLvl() > enemyAbilities[1];
    }

}

啊,你知道,你是对的。结束括号一直使我难以接受这个挑战(因此不得不编辑我的几次)。我现在看到了,这是正确的。感谢您指出了这一点!
user3334871 2014年

@ user3334871虽然我测试了您的建议,但我的变形效果更好:D
Sikorski 2014年

@Sikorski好吧,很高兴我能提供帮助,但不确定为什么会更好,哈哈。
user3334871 2014年

@Sikorski我想这只是意味着,如果所有举动都是危险的,停留姿势通常比做出最小危险的动作更安全。
Martin Ender 2014年

啊,“头灯鹿”策略,我喜欢。
user3334871 2014年

6

弯曲者“弯曲”罗德里格斯

我对代码注释相当宽容。您可以在上下文中阅读它们,以了解发生了什么,但是我还将在下面添加一些片段。

摘要

该外星人的工作原理是杀死微不足道的人类很容易,并夸大了您的感知力,这会吓other其他外星人以避开。

鲸鱼和老鹰也是可弯曲的。=)

运动

向西或向南移动,除非您发现有什么有趣的东西可攻击:

  • 对于已知运动的猎物,我们将它们的期望值添加到下一轮的位置。
  • 对于那些我们不喜欢的人,我们将它们的期望值平均分配到可能移至下一回合的正方形之间。
    • 由于香蕉皮,外星人获得的奖励对他们现有的正方形为负。

如果您在附近找不到任何有趣的事物,请了解一下南,西还是西南是一个更有希望的选择。

选择一个或两个主要方向会减少任何给定的本德尔碰到任何同胞的机会,并且选择一个与他的主要猎物相反的方向应该有助于他更快地杀死所有人类。

我可能可以使用James_pic的遗传算法调整可取性矩阵中的数字,以获得更好的结果,但是我不知道该怎么做。

好斗

班德主要瞄准猎物,并且对他非常保守wantToFight除非您认为自己正在与一个聪明的人打交道,否则任何超越“力量4”的人都会被回避。拥有比外星人更多的防御力和视野,可以证明聪明的人性。在某个实例的过程中,它会根据Bender自身的能力统计数据进行调整,以考虑到杀死海龟和老鹰的外星人。

package alien;

import planet.Move;
import java.util.HashMap;

/// The Bender "Kill All Humans" Alien
///
/// This alien operates on the principle that killing puny
/// Humans is easy and inflates your perceived strength,
/// which will intimidate other aliens into steering clear.
///
/// Whales and Eagles are also bendable. =)
public class Bender extends Alien {

    private static final boolean DEBUG = false;
    private final int LIF = 0, STR = 1, DEF = 2, VIS = 3, CLV = 4;
    protected static HashMap<Character, Integer> preyDesirability = new HashMap<Character, Integer>() {{
        put('A', -5);
        put('W',  5);
        put('C',  0); // Originally -2, but Cows don't attack
        put('T',  2);
        put('E',  3);
        put('H',  4);
    }};
    private static final int bananaTweak = -2;

    private static final HashMap<Character, Move> preyMovement = new HashMap<Character, Move>() {{
        put('W', Move.STAY);
        put('T', Move.SOUTHWEST);
        put('H', Move.NORTHEAST);
    }};

    public void setAbilityPoints(float[] abilities) {
        abilities[LIF] = 3.5f; // Shiny metal ass
        abilities[STR] = 5.5f; // Bending strength
        abilities[DEF] = 0;
        abilities[VIS] = 1;    // Binocular eyes
        abilities[CLV] = 0;
    }

    /// Looks for humans to intercept!
    ///
    /// Generally speaking, move either west or south
    /// unless you have found something interesting to
    /// attack:
    /// - For the prey whose movement is known, we add
    ///   their desirability to the index at which they
    ///   will be next turn.
    /// - For those we do not, we divide their desirability
    ///   equally among the squares that they may move to
    ///   next turn. Aliens get a bonus negative to their
    ///   existing square because of banana peels.
    public Move move(char[][] fields) {

        int vision = getVisionFieldsCount();
        // I am at fields[vision][vision]

        if (DEBUG) {
            System.out.format("\n----- %s -----\n", this);
        }

        float[][] scoringMap = new float[fields.length][fields.length];
        for (int y = 0; y < fields.length; y++) {
            for (int x = 0; x < fields.length; x++) {

                // Ignore my square and blanks
                if (x == vision && y == vision ||
                    fields[x][y] == ' ') {
                    continue;
                }

                // Check out the prey 8^]
                char organism = fields[x][y];
                float desirability = preyDesirability.get(organism);

                // If we know where it's going, score tiles accordingly...
                if (preyMovement.containsKey(organism)) {
                    Move preyMove = preyMovement.get(organism);
                    if (DEBUG) {
                        System.out.println(String.format("Prey %s will move %s", organism, preyMove));
                    }
                    int newPreyX = x + preyMove.getXOffset();
                    int newPreyY = y + preyMove.getYOffset();
                    try {
                        scoringMap[newPreyX][newPreyY] += desirability;
                        if (DEBUG) {
                            System.out.println(String.format(
                                "Adding %.1f to %d, %d",
                                desirability,
                                newPreyX,
                                newPreyY));
                        }
                    }
                    catch(Exception e) {
                        if (DEBUG) {
                            System.out.println(String.format(
                                "Failed adding %.1f to %d, %d",
                                desirability,
                                newPreyX,
                                newPreyY));
                        }
                    }
                }
                // ...otherwise, divide its score between its
                //    available moves...
                else {
                    for (int j = y - 1; j <= y + 1; j++) {
                        for (int i = x - 1; i <= x + 1; i++) {
                            try {
                                scoringMap[i][j] += desirability / 9.;
                            }
                            catch (Exception e) {
                                if (DEBUG) {
                                    //System.out.println(e);
                                }
                            }
                        }
                    }
                }
                // ...and if it is an alien, add a handicap
                //    for bananas and rocks.
                if (organism == 'A') {
                    scoringMap[x][y] += bananaTweak;
                }
            }
        }

        // Evaluate immediate surroundings 8^|
        //
        // +-----------+
        // |           |
        // |   # # #   |
        // |   # B #   |
        // |   # # #   |
        // |           |
        // +-----------+
        float bestScore = -10;
        int[] bestXY = new int[2];
        for (int y = vision - 1; y <= vision + 1; y++) {
            for (int x = vision - 1; x <= vision + 1; x++) {

                if (DEBUG) {
                    System.out.format("\nx:%d, y:%d", x, y);
                }
                // Look for the best score, but if scores
                // are tied, try for most southwest high score
                if (scoringMap[x][y] > bestScore ||
                    scoringMap[x][y] == bestScore && (
                        x <= bestXY[0] && y > bestXY[1] ||
                        y >= bestXY[1] && x < bestXY[0])
                    ) {
                    bestScore = scoringMap[x][y];
                    bestXY[0] = x;
                    bestXY[1] = y;
                    if (DEBUG) {
                        System.out.format("\nBest score of %.1f found at %d, %d", bestScore, x, y);
                    }
                }
            }
        }

        if (DEBUG) {
            StringBuilder sb = new StringBuilder();
            sb.append("\n-----\n");
            for (int y = 0; y < fields.length; y++) {
                for (int x = 0; x < fields.length; x++) {
                    sb.append(String.format("%5s", fields[x][y]));
                }
                sb.append("\n");
            }
            for (int y = 0; y < scoringMap.length; y++) {
                for (int x = 0; x < scoringMap.length; x++) {
                    sb.append(String.format("%5.1f", scoringMap[x][y]));
                }
                sb.append("\n");
            }
            System.out.println(sb.toString());
        }

        // If something looks tasty, go for it :^F
        if (bestScore > 0.5) {
            for (Move m : Move.values()) {
                if (m.getXOffset() == bestXY[0] - vision &&
                    m.getYOffset() == bestXY[1] - vision) {
                    if (DEBUG) {
                        System.out.println("Using immediate circumstances.");
                        System.out.println(m);
                    }
                    return m;
                }
            }
        }

        // If nothing looks good, do a lookahead to
        // the south, west, and southwest to guess
        // which is best. 8^[
        //
        // There is potential in recursively applying our
        // vision data with updated score rankings, but
        // that would be hard. :P
        float westScore = 0, southScore = 0, southWestScore = 0;
        for (int y = vision - 1; y < vision + 1; y++) {
            for (int x = 0; x < vision; x++) {
                // +-----------+
                // |           |
                // | # # #     |
                // | # # B     |
                // | # # #     |
                // |           |
                // +-----------+
                westScore += scoringMap[x][y] / (vision - x);
            }
        }
        for (int y = vision; y < fields.length; y++) {
            for (int x = vision - 1; x < vision + 1; x++) {
                // +-----------+
                // |           |
                // |           |
                // |   # B #   |
                // |   # # #   |
                // |   # # #   |
                // +-----------+
                southScore += scoringMap[x][y] / (y - vision);
            }
        }
        for (int y = vision; y < fields.length; y++) {
            for (int x = 0; x < vision; x++) {
                // +-----------+
                // |           |
                // |           |
                // | # # B     |
                // | # # #     |
                // | # # #     |
                // +-----------+
                southWestScore += scoringMap[x][y] / Math.sqrt((y - vision) + (vision - x));
            }
        }
        if (southScore > westScore && southScore > southWestScore) {
            if (DEBUG) {
                System.out.println(Move.SOUTH);
            }
            return Move.SOUTH;
        }
        if (westScore > southScore && westScore > southWestScore) {
            if (DEBUG) {
                System.out.println(Move.WEST);
            }
            return Move.WEST;
        }
        if (DEBUG) {
            System.out.println(Move.SOUTHWEST);
        }
        return Move.SOUTHWEST;
    }

    public boolean wantToFight(int[] enemyAbilities) {

        // Be afraid...
        if (enemyAbilities[STR] > 4) {

            // ...unless you suspect you are being lied to
            if (enemyAbilities[DEF] + enemyAbilities[VIS] > 4 * sumMyAbilities() / 5.) {

                // Enemy has more than expected attribute levels of unhelpful
                // abilities. Assume you're dealing with a clever bastard.
                return true;
            }

            return false;
        }
        return true;
    }

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

    int sumMyAbilities(){
        return sumAbilities(new int[]{
            getLifeLvl(),
            getStrengthLvl(),
            getDefenseLvl(),
            getVisionLvl(),
            getClevernessLvl()
        });
    }
}

我注意到存在一个循环逻辑错误,其中递增的变量不是直接进行比较的变量,仅通过整数溢出包装避免了无限递归。希望您能接受我的答复。(这会导致模拟不时暂停)
Moogie 2014年

@Moogie Heh。所以我只是偶然地做得好?感谢您抓住这一点。
2014年

我仔细研究了整个问题,并修复了另外两个问题。
2014年

5

战士

这是一个很简单的外星人,只想打架。他不在乎敌人,也不在乎周围环境。

public class Warrior extends Alien {

    public void setAbilityPoints(float[] abilities) {
        abilities[0] = 5;
        abilities[1] = 5;
    }

    public Move move(char[][] fields) {
        return Move.getRandom(); //enemies are everywhere!
    }

    public boolean wantToFight(int[] enemyAbilities) {
        return true; //strong, therefore no stronger enemies.
    }
}

现在,您可以有人来测试自己的外星人。


4

懦夫

我基本上偷走了Eagle的行动方式,以防万一受到攻击时避免危险和堆积防御。

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

    // shamelessly stole Eagle's movement to avoid danger
    public Move move(char[][] fields){
        int vision = getVisionFieldsCount(); 
        char me = fields[vision][vision];
        int leastDanger = Integer.MAX_VALUE;
        Move bestMove = Move.STAY;
        for (Move move : Move.values()) {
            int danger = 0;
            for (int i = 1; i <= vision; i++) {
                int fieldX = vision + (i * move.getXOffset());
                int fieldY = vision + (i * move.getYOffset());
                if (fields[fieldX][fieldY] != ' ') {
                    danger++;
                }
            }
            if (danger < leastDanger) {
                bestMove = move;
                leastDanger = danger;
            }
        }
        return bestMove;
    }

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

如果我错了,请纠正我,但是既然每个能力的基点都是1,那么推杆vision=1应该足够了吗?
justhalf 2014年

@justhalf:我对代码的简短阅读似乎建议重写setAbilityPoints1的值,但更深入地研究它,我认为您是正确的。我将按原样保留它,因为更大的视野可以让我进一步看到并避免危险,但要感谢您。
Kyle Kanos 2014年

此外,math.round总是四舍五入为0.5,因此,如果您有奇数,则将获得更多的视野
Andreas

@Manu:我交换了视觉和防御的价值观,以提高逃跑能力。
Kyle Kanos 2014年

4

er

恐慌

启示录

RUUUUUUUUUUN

AAAAAAAAAAAAAAAAAAAAAAAAAA


尽可能避免战斗。

package alien; import planet.Move;

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

    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;
        ArrayList<Integer> dangerOnSides = new ArrayList<Integer>();
        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());
                if (fields[fieldX][fieldY] != ' ') {
                    danger++;
                }
            }
            if (danger < leastDanger) {
                bestMove = move;
                leastDanger = danger;
            }
            dangerOnSides.add(danger);
        }

        boolean noDanger = false;
        for (int i : dangerOnSides) {
           if (i == 0) {
              noDanger = true;
           }
           else { noDanger = false; break; }
        }

        if (noDanger) {
              // Hahhhhhhhh.......
              return Move.STAY;
        }

        int prev = -1;
        boolean same = false;
        for (int i : dangerOnSides) {
           if (prev == -1)
           { prev = i; continue; }
           if (i == prev) {
              same = true;
           }
           else { same = false; break; }

           prev = i;
        }

        if (same) {
              // PANIC
              return Move.getRandom();
        }

        return bestMove;
    }

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

您应该给它起一个不同的名字...并对您从以下内容中
Justin

2
@Quincunx这是一个巧合,没看到那个……
stommestack 2014年

抱歉,我只是意识到两个答案都来自Eagle。您没有复制其他答案,我只是没有足够仔细地阅读。但是,可以使用其他名称。
贾斯汀

1
改名!
stommestack 2014年

2
应命名为Rincewind。
Magus 2014年

4

捕食者(咕r声)

种类繁多的Predicats,(迄今为止)过着恐惧的生活,并且远离麻烦。由于他们的生活方式,他们没有发展战斗本能,但他们的感知力非同寻常。

他们的种类被同伴Predicats所憎恶。

编辑:改为改为曼哈顿距离为加权距离

package alien;

import planet.Move;
import java.util.ArrayList;
import java.awt.Point;

/* Predict + Cat = Predicat! */
public class Predicoward extends Alien {
    /*
        - - - - - - - - - - - - -
        - - - - - - - - - - - - -
        - - - - - - - - - - - - -
        - - - - - - - - - - - - -
        - - - - - - - - - - - - -
        - - - - - - - - - - - - -
        - - - - - - P - - - - - -
        - - - - - - - - - - - - -
        - - - - - - - - - - - - -
        - - - - - - - - - - - - -
        - - - - - - - - - - - - -
        - - - - - - - - - - - - -
        - - - - - - - - - - - - -

        Risk score = sum of weighted distances of all aliens within vision range
    */
    @Override
    public void setAbilityPoints( float[] abilities ) {
        abilities[3] = 10;
    }

    @Override
    public Move move( char[][] fields ) {
        /* Some credits to Eagle for letting me learn how to do the moves */
        int vision = getVisionFieldsCount(); //count of fields / middle

        Move bestMove=Move.STAY;
        int bestRiskScore=10000;
        int riskScore=0;
        ArrayList<Point> aliens = new ArrayList<Point>();

        //generate alien list
        for (int x=0; x<=vision*2; x++) {
            for(int y=0; y<=vision*2; y++){
                if(x==vision && y==vision) continue;
                if(fields[x][y]=='A'){
                    aliens.add(new Point(x,y));
                }
            }
        }

        for (Move move : Move.values()) {
            int x = vision + move.getXOffset();
            int y = vision + move.getYOffset();
            riskScore = 0;

            for(Point alienCoord : aliens){
                riskScore += this.getDistance(x, y, alienCoord);
            }

            if(riskScore < bestRiskScore){
                bestRiskScore = riskScore;
                bestMove = move;
            }
        }

        return bestMove;
    }

    @Override
    public boolean wantToFight( int[] enemyAbilities ) {
        //I don't want to fight :(
        return false;
    }

    //Return weighted distance (more weight for near opponents)
    private int getDistance(int x, int y, Point to){
        int xDist = Math.abs(x-(int)to.getX());
        int yDist = Math.abs(y-(int)to.getY());
        int numberOfMovesAway = Math.max(xDist, yDist);

        if(numberOfMovesAway==0){
            return 1000;
        }
        else if(numberOfMovesAway==1){
            return 100;
        }
        else if(numberOfMovesAway==2){
            return 25;
        }
        else{
            return 6-numberOfMovesAway;
        }
    }
}

2
看起来不错!但是,请拿出您的印刷陈述,当我进行竞赛时,它们会使我感到困惑。
CommonGuy 2014年

哦,我离开了打印报表?我稍后再更改。哈哈。另外,这还不是最终的。现在,Predicoward很烂。他的外星人逃避算法将很快得到改善。:)编辑:感谢删除打印声明的那一位。:D(Jop?)
马克·加布里埃尔

编辑:掠夺者现在比以前令人讨厌的不具竞争力的掠夺者要好得多。> :)
Mark Gabriel

琐事:这是我最喜欢的Predicat <3
Mark Gabriel

4

PredicatEyes(喵)

一种具有比同龄人更敏锐的视域,可以很好地撬动敌人。

编辑:新的目标优先事项

package alien;

import planet.Move;

/* Predict + Cat = Predicat! */
public class PredicatEyes extends Alien {
    private static final int LIF=0, STR=1, DEF=2, VIS=3;
    private static final int WHALE=6, COW=1, TURTLE=4, EAGLE=3, HUMAN=2, ALIEN=-1, NONE=0;

    @Override
    public void setAbilityPoints( float[] abilities ) {
        abilities[LIF] = 4.5f;
        abilities[STR] = 4.5f;
        abilities[VIS] = 1;
    }

    @Override
    public Move move( char[][] fields ) {
        /* Some credits to Eagle for letting me learn how to do the moves */
        int vision = getVisionFieldsCount(); //count of fields / middle
        int fieldX;
        int fieldY;
        Move bestMove=Move.STAY;
        int bestScore=-1;

       for (Move move : Move.values()) {
            fieldX = vision + move.getXOffset();
            fieldY = vision + move.getYOffset();
            switch(fields[fieldX][fieldY]){
            case 'W' : 
                return move;
            case 'C' :
                if(bestScore<COW){
                    bestMove=move;
                    bestScore=COW;
                }
                break;
            case 'T' :
                if(bestScore<TURTLE){
                    bestMove=move;
                    bestScore=TURTLE;
                }
                break;
            case 'E' :
                if(bestScore<EAGLE){
                    bestMove=move;
                    bestScore=EAGLE;
                }
                break;
            case 'H' :
                if(bestScore<HUMAN){
                    bestMove=move;
                    bestScore=HUMAN;
                }
                break;
            case 'A' :
                if(bestScore<ALIEN){
                    bestMove=move;
                    bestScore=ALIEN;
                }
                break;
            case ' ' :
                if(bestScore<NONE){
                    bestMove=move;
                    bestScore=NONE;
                }
                break;
            }
        }

        if(vision==1 && bestScore>1){
            return bestMove;
        }

        //check immediate outer field
        for (int i=vision-2; i<=vision+2; i++) {
            for(int j=vision-2; j<=vision+2; j++){
                if(i==0 || i==4 || j==0 || j==4){
                    switch(fields[i][j]){
                    case 'W' :
                        bestMove = this.getBestMoveTo(i,j);
                        bestScore = WHALE;
                        break;
                    case 'C' :
                        if(bestScore<COW){
                            bestMove = this.getBestMoveTo(i,j);
                            bestScore = COW;
                        }
                        break;
                    case 'T' :
                        if(i>=vision && j<=vision){
                            return this.getBestMoveTo(i-1,j+1);
                        }
                        if(bestScore<TURTLE){
                            bestMove = this.getBestMoveTo(i,j);
                            bestScore = TURTLE;
                        }
                        break;
                    case 'E' :
                        if(bestScore<EAGLE){
                            bestMove = this.getBestMoveTo(i,j);
                            bestScore = EAGLE;
                        }
                        break;
                    case 'H' :
                        if(i<=vision && j>=vision){
                            return this.getBestMoveTo(i+1,j-1);
                        }
                        if(bestScore<HUMAN){
                            bestMove = this.getBestMoveTo(i,j);
                            bestScore = HUMAN;
                        }
                        break;
                    case 'A' :
                        if(bestScore<ALIEN){
                            bestMove = this.getBestMoveTo(i,j);
                            bestScore = ALIEN;
                        }
                        break;
                    case ' ' :
                        if(bestScore<NONE){
                            bestMove = this.getBestMoveTo(i,j);
                            bestScore = NONE;
                        }
                        break;
                    }
                }
            }
        }

        return bestMove;
    }

    @Override
    public boolean wantToFight( int[] enemyAbilities ) {
        /*
            Fight IF
                1) I CAN BEAT YOU
                2) ????
                3) MEOW!
        */
        float e_hp = enemyAbilities[LIF]*5+10;
        float e_dmg = 1 + enemyAbilities[STR]/2;
        float e_hit = 1 - (1/(50/this.getDefenseLvl()+1));

        float m_hp = this.getCurrentHp();
        float m_dmg = 1 + this.getStrengthLvl()/2;
        float m_hit = 1 - (1/(50/enemyAbilities[DEF]+1));

        return (e_hp/(m_dmg*m_hit) < m_hp/(e_dmg*e_hit));
    }

    private Move getBestMoveTo(int visionX, int visionY){
        int vision = getVisionFieldsCount();

        if(visionX < vision && visionY < vision){
            return Move.NORTHWEST;
        }
        else if(visionX > vision && visionY < vision){
            return Move.NORTHEAST;
        }
        else if(visionX < vision && visionY > vision){
            return Move.SOUTHWEST;
        }
        else if(visionX > vision && visionY < vision){
            return Move.SOUTHEAST;
        }
        else if(visionX == vision && visionY < vision){
            return Move.NORTH;
        }
        else if(visionX == vision && visionY > vision){
            return Move.SOUTH;
        }
        else if(visionX > vision && visionY == vision){
            return Move.EAST;
        }
        else if(visionX < vision && visionY == vision){
            return Move.WEST;
        }
        else{
            return Move.getRandom();
        }

    }
}

3

麦田怪圈外星人

他无限期地顺时针旋转,并且从不愿意打架,他乐于制作农作物卷。但是,如果您真的想打架,他会击败您。

package alien;

import planet.Move;

public class CropCircleAlien extends Alien {

    private int i = 0;

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

    @Override
    public Move move(char[][] fields) {
        switch (getI()) {
        case 0:
            setI(getI() + 1);
            return Move.EAST;
        case 1:
            setI(getI() + 1);
            return Move.SOUTHEAST;
        case 2:
            setI(getI() + 1);
            return Move.SOUTH;
        case 3:
            setI(getI() + 1);
            return Move.SOUTHWEST;
        case 4:
            setI(getI() + 1);
            return Move.WEST;
        case 5:
            setI(getI() + 1);
            return Move.NORTHWEST;
        case 6:
            setI(getI() + 1);
            return Move.NORTH;
        case 7:
            setI(getI() + 1);
            return Move.NORTHEAST;
        default:
            return Move.STAY;
        }
    }

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

    public void setI(int i) {
        if (i < 8) {
            this.i = i;
        } else {
            this.i = 0;
        }
    }

    public int getI() {
        return this.i;
    }
}

2
如果通过Move进行迭代,这会更干净。
并非查尔斯(Charles)

4
为什么不将每个更改getI()i并简单地删除getI()呢?您也可以更改setI(int i)this.i = i % 8;,并且由于您仅在一个地方使用它,因此只需将每次通话都更改setI(getI() + 1)i = (i + 1) % 8;
Justin

3

聪明外星人

聪明的外星人完全依靠自己的智慧。他随机走动,并随机决定战斗。他希望自己能在运气方面胜过敌人。(请原谅我,如果我有任何语法错误,我不是一个Java家伙)

package alien;

import planet.Move;

public class CleverAlien extends Alien {

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

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

public boolean wantToFight(int[] enemyAbilities) {
    //same order of array as in setAbilityPoints, but without cleverness
    int tmp = (int) ( Math.random() * 2 + 1);
    return tmp == 1;
    }
}

8
tmp == 1 ? true : false?为什么不(tmp == 1) == true ? true : false呢?;)(提示:这是一样的 tmp == 1)。
马丁安德

3

流氓

就像其他人所说的,我在某种程度上正在使用Eagle的机芯。我没有尝试做一个成功的外星人(我的最佳想法已经被接受为D :),而是决定做一个有个性的外星人!我的外星人是外星人战争遗忘的租用枪支,只在这个星球上追捕逃避了死刑债务的肮脏人。我的外星人将在地球上寻找人类,并继续落后于人类而不会杀死他。一旦在他附近看到一个外星人,他将尝试迅速杀死该人,并在完成的任务中以“幸运的一面”面对这个新的敌人。

package alien;

import planet.Move;

public class Rogue extends Alien {

    private int threatPresent = 0;
    private int turnNorth = 0;

    public void setAbilityPoints(float[] abilities) {
        abilities[0] = 3;
        abilities[1] = 6;
        abilities[2] = 0;
        abilities[3] = 1;
        abilities[4] = 0;
    }

    public Move move(char[][] fields) {
        int vision = getVisionFieldsCount();
        char me = fields[vision][vision];
        int humanPresent = 0;            
        //This way, if there is no alien near, the current threat will not trigger attacking
        int isThereCurrThreat = 0;
        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] == 'A') {
                    isThereCurrThreat = 1;
                }

                if (fields[fieldX][fieldY] == 'T') {
                    humanPresent = 1;
                    //Turtles are basically dumb humans, right?
                }

                if (fields[fieldX][fieldY] == 'H') {
                    humanPresent = 1;
                }
            }

            //Alway follow that filthy human
            if (humanPresent == 1) {
                bestMove = move;
            }

           }

         if(humanPresent == 0) {
             //Alternate moving north and east towards the human
             //If I hit the edge of world, I search for the turtle as well
             if(turnNorth == 1) {
                bestMove = Move.NORTH;
                turnNorth = 0;
             }

             else {
                bestMove = Move.EAST;
                turnNorth = 1;
             }
         }

      //If a threat was found, attack accordingly.
      threatPresent = isThereCurrThreat;
      return bestMove;

    }

  public boolean wantToFight(int[] enemyAbilities) {
      //Only fight if another enemey is near
      if (threatPresent == 1) {
        return true;
        }

      else {
        return false;
      }
   }
}

该代码以我应该向人类冲刺的想法为中心。一旦击败他,我便绕到西南,在那里寻找海龟。

编辑:哦,关于乌龟的事情……我的外星人不喜欢他们,所以你们完全可以肯定了。


刚刚意识到我也可以向乌龟冲刺。谁不喜欢高躲闪的流氓?
user3334871 2014年

2
如果Java 8的块部分直接将int用作布尔值?因为它根本无法在我的机器上进行编译(Java 7)。提示:humanPresent
Sikorski

如果知道的话,我的Java经验主要限于脚本和大学课程。我只是进行比较,所以一切都是桃红色的。感谢您的注意!
user3334871 2014年

另外,@ Sikorski,您是否创建了自己的main或init函数来运行测试?还是可以仅通过提供的代码来完成?我发誓,自从我在一个真正的Java环境中编码以来已经很久了,以至于我忘记了执行Java代码的规则:(
user3334871 2014年

不只是下载OP在github链接中给出的代码,添加其他类并开始测试。哦,您将必须为Planet类中的每个外星人类添加条目。
西科斯基2014年

3

飞机坠毁并试图生存。它主要依靠敏捷性和智慧来生存,并计算每条伤疤,仔细考虑是否值得进行战斗。幸存者刚开始狩猎时就试图用大武器避开所有其他外星人,但随着它变得更大胆,它可能会开始追赶他们。当它真正开始时,它不再关心它面对的是谁。

package alien;

import planet.Move;

public class Survivor extends Alien {

    private int boldness = 0;
    private float life = 0;
    private float str = 1;
    private float def = 4;
    private float clever = 10 - life - str - def;

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

    public Move move(char[][] fields) {
        //you are in the middle of the fields, say fields[getVisionFieldsCount()][getVisionFieldsCount()]
        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':
                    if(boldness < 10)
                        danger++;
                    else
                        danger--;
                    break;
                case ' ':
                    break;
                default:
                    danger-=2;
            }
        }
        if (danger < leastDanger) {
            bestMove = move;
            leastDanger = danger;
        }
    }
    return bestMove;
    }

    public boolean wantToFight(int[] enemyAbilities) {
        //same order of array as in setAbilityPoints, but without cleverness
        bool fight = boldness < 50;//After 50 fights, believes self unstoppable            
        int huntable = 0;
        for(int ability : enemyAbilities){
            if(ability == 1)
                huntable++;
        }
        if(huntable >= 3){
             fight = true;
        }//if at least 3 of the visible stats are 1 then consider this prey and attack
        else if((float)enemyAbilities[1] / (float)getDefenseLvl() <= (float)getStrengthLvl() + (float)(getClevernessLvl() % 10) / (float)enemyAbilities[2] && enemyAbilities[0] / 5 < getLifeLvl() / 5)
            fight = true;//If I fancy my odds of coming out on top, float division for chance
        if(fight){//Count every scar
            boldness++;//get more bold with every battle
            life += enemyAbilities[0] / 5;
            str += enemyAbilities[1] / 5;
            def += enemyAbilities[2] / 5;
            clever += (10 - (enemyAbilities[0] + enemyAbilities[1] + enemyAbilities[2] + enemyAbilities[3] - 4)) / 5;//count the human cleverness attained or the enemies who buffed clever early
        }
        return fight;
    }

}

1
我非常确定这for(int ability in enemyAbilities){是一个语法错误-尝试for(int ability : enemyAbilities){
Joshua 2014年

3

时髦的鲍勃

生存是第一要务,否则将设法寻找猎物。评估可见区域,以找到威胁最小或猎物最多的一般方向。在我的测试过程中,存活率似乎约为85-90%。

package alien;
import planet.Move;

public class FunkyBob extends Alien {
    public void setAbilityPoints(float[] abilities) {
        abilities[0] = 2.5f;
        abilities[1] = 5.5f;
        abilities[3] = 2;
    }

    private int QtyInRange(char[][] fields, int x, int y, int numStepsOut, char specie)
    {
        int count = 0;
        for(int i = numStepsOut * -1; i <= numStepsOut; i++)
            for(int j = numStepsOut * -1; j <= numStepsOut; j++)
                if(fields[x+i][y+j] == specie)
                    count++;
        return count;
    }

    private int AssessSquare(char[][] fields, int x, int y, int visibility){
        int score = 0;

        for(int i = 0; i <= visibility; i++)
        {
            score += (-1000 / (i == 0 ? 0.3 : i)) * QtyInRange(fields, x, y, i, 'A');
            score += (100 / (i == 0 ? 0.3 : i)) * QtyInRange(fields, x, y, i, 'T');
            score += (100 / (i == 0 ? 0.3 : i)) * QtyInRange(fields, x, y, i, 'H');
            score += (100 / (i == 0 ? 0.3 : i)) * QtyInRange(fields, x, y, i, 'E');
            score += (50 / (i == 0 ? 0.3 : i)) * QtyInRange(fields, x, y, i, 'W');
            score += (50 / (i == 0 ? 0.3 : i)) * QtyInRange(fields, x, y, i, 'C');
        }

        return score;
    }

    public Move move(char[][] fields)   {
        int vision = getVisionFieldsCount();
        Move bestMove = Move.STAY;
        int bestMoveScore = AssessSquare(fields, vision, vision, vision - 1);

        for (Move move : Move.values()) {
            int squareScore = AssessSquare(fields, vision + move.getXOffset(), vision + move.getYOffset(), vision - 1);
            if(squareScore > bestMoveScore)
            {
                bestMoveScore = squareScore;
                bestMove = move;
            }

        }
        return bestMove;
    }

    public boolean wantToFight(int[] enemyAbilities)    {
        return ((getCurrentHp() + this.getStrengthLvl()) / 2) >
                ((enemyAbilities[0] * 3) + enemyAbilities[1]);
    }
}

3

时髦杰克

只是为了踢球,这是另一个略有不同的方法。这只专注于避免打架。由于在前两轮中被敌人包围,这并不是一个切实可行的策略。第一回合占据40%的方块,因此平均而言,您将立即与3-4个敌人相邻。但是,当将最初的空方块增加到物种的12.5倍而不是物种的2.5倍时,其平均成活率为98.5%。

package alien;
import planet.Move;

public class FunkyJack extends Alien {
    public void setAbilityPoints(float[] abilities) {
        abilities[0] = 4.5f;
        abilities[1] = 1.5f;
        abilities[3] = 4;
    }

    private int QtyInRange(char[][] fields, int x, int y, int numStepsOut, char specie)
    {
        int count = 0;
        for(int i = numStepsOut * -1; i <= numStepsOut; i++)
            for(int j = numStepsOut * -1; j <= numStepsOut; j++)
                if(fields[x+i][y+j] == specie)
                    count++;
        return count;
    }

    private int AssessSquare(char[][] fields, int x, int y, int visibility, int prevScore){
        int score = 0;
        score += -10000 * QtyInRange(fields, x, y, visibility, 'A');                
        if(visibility > 0)
            score = AssessSquare(fields, x, y, visibility - 1, ((score + prevScore) / 5));
        else
            score += prevScore;

        return score;
    }

    public Move move(char[][] fields)   {
        int vision = getVisionFieldsCount();
        Move bestMove = Move.STAY;
        int bestMoveScore = AssessSquare(fields, vision, vision, vision - 1, 0);

        for (Move move : Move.values()) {
            int squareScore = AssessSquare(fields, vision + move.getXOffset(), vision + move.getYOffset(), vision - 1, 0);
            if(squareScore > bestMoveScore)
            {
                bestMoveScore = squareScore;
                bestMove = move;
            }
        }
        return bestMove;
    }

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

1
98.5%是巨大的。即使是我的Predicowards,平均存活率也只有大约65%。哈哈。编辑:我的Predicowards具有与FunkyJack相同的理念-别走开。我确实有10个视野和0个战斗属性。
Mark Gabriel 2014年

3

懒蜂

我开始尝试制作一个聪明的Bee课程,该课程使用模式运动和演绎推理,但后来我很困,所以我将其重命名为LazyBee并将其命名为Night。实际上,在我的测试中,他的表现似乎还不错(在github上,外星人的平均得分约为1645)。

package alien;

import planet.Move;
public class LazyBee extends Alien{

    private static final int LIFE = 0;
    private static final int STRENGTH = 1;

    // Ran trials to figure out what stats were doing  best in sims
    // Lazily assumed that:
        // - Defense is negligeble compared to health
        // - Vision doesn't matter if I'm running east all the time
        // - Cleverness will be canceled out because dumb aliens (yum) won't care
            // and smart aliens probably account for it somehow
    public static float DARWINISM = 4.5f;
    public void setAbilityPoints(float[] abilities){
        abilities[LIFE] = DARWINISM;  
        abilities[STRENGTH] = 10f-DARWINISM;  
    }

    // If bananapeel is fine without trying to move cleverly, I probably am too
    public Move move(char[][] fields)
    {
        return Move.EAST; // This was giving me the best score of all arbitrary moves, for some reason
    }

    // inspired by ChooseYourBattles, tried to do some math, not sure if it worked
        // it seemed that Bee was doing better by being more selective
        // not accounting for cleverness because eh
    public boolean wantToFight(int[] enemyAbilities){
        // chance of hit (h) = (1-(1/((50/deflvl)+1)))) = 50/(deflvl+50)
        double my_h = 50.0/(this.getDefenseLvl() + 50), 
                their_h = (50.0 - enemyAbilities[STRENGTH])/50.0;
        // expected damage (d) = h * (strlvl+1)
        double my_d = /* long and thick */ my_h * (this.getStrengthLvl() + 1),
                their_d = their_h * (enemyAbilities[STRENGTH]); 
        // turns to die (t) = currhp / d
        double my_t = (this.getCurrentHp() / their_d),
                their_t = ((enemyAbilities[LIFE] * 5 + 10) / my_d); // Assume they're at full health because eh
        // worth it (w) = i outlast them by a decent number of turns
            // = my_t - their_t > threshold
            // threshold = 4.5
        boolean w = my_t - their_t > 4.5;

        return w;
    }
}

1
优秀作品!我很惊讶您在硬编码方向上的得分如此出色。
迈克尔

@Michael你不知道我被发现时有多么惊喜!我在运动代码上花了很多力气,然后让它作为一个控制组与HOLD对抗。然后我意识到对照组在踢屁股,所以我开始尝试不同程度的懒惰!
thefistopher 2014年

3

纽吉

尝试让“容易”的目标参与早期耕种。否则,只需零星移动。

package alien;

import planet.Move;

public class NewGuy extends Alien {
    private final static byte LIFE=0, STR=1, DEF=2, VIS=3, CLV=4;

    public void setAbilityPoints(float[] abilities) {
        abilities[LIFE] = 5;
        abilities[STR] = 5;
    }

    public Move move(char[][] fields) {
        // Very rudimentary movement pattern. Tries to engage all "easy" peaceful aliens.
        // Programmer got lazy, so he doesn't run away from danger, decreasing his odds of survival.
        // Afterall, if his species dies, that's one fewer specie that humans have to contend with.

        int vision = getVisionFieldsCount(); //count of fields / middle
        char me = fields[vision][vision]; //middle of fields
        for (Move move : Move.values()) {
            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());
                char alienType = fields[fieldX][fieldY];

                if (alienType == 'E' || alienType == 'H' || alienType == 'T' || alienType == 'W') {
                    return move;
                }
            }
        }

        return Move.getRandom();
    }

    public boolean wantToFight(int[] enemyAbilities) {
        if (isWhale(enemyAbilities)) {
            return true;
        } else if (isCow(enemyAbilities)) {
            return false; // Cows hit hard!
        } else if (isTurtle(enemyAbilities)) {
            return true;
        } else if (isEagle(enemyAbilities)) {
            return true;
        } else if (isHuman(enemyAbilities)) {
            if (enemyAbilities[STR] < 3) {
                return true;
            }
        }

        return false;
    }

    public boolean isWhale(int[] enemyAbilities) {
        return enemyAbilities[LIFE] == 10 && totalAbilityPoints(enemyAbilities) == 10;
    }

    public boolean isCow(int[] enemyAbilities) {
        return enemyAbilities[STR] == 10 && totalAbilityPoints(enemyAbilities) == 10;
    }

    public boolean isTurtle(int[] enemyAbilities) {
        return enemyAbilities[DEF] == 10 && totalAbilityPoints(enemyAbilities) == 10;
    }

    public boolean isEagle(int[] enemyAbilities) {
        return enemyAbilities[VIS] == 10 && totalAbilityPoints(enemyAbilities) == 10;
    }

    public boolean isHuman(int[] enemyAbilities) {
        return !(isWhale(enemyAbilities) || isCow(enemyAbilities) || isTurtle(enemyAbilities)) && totalAbilityPoints(enemyAbilities) >= 10;
    }

    public int totalAbilityPoints(int[] enemyAbilities) {
        return enemyAbilities[LIFE] + enemyAbilities[STR] + enemyAbilities[DEF] + enemyAbilities[VIS];
    }
}

return true;由于else条件的原因,该浮线似乎是多余的。
Kyle Kanos 2014年

@KyleKanos是的。问题已解决。
FreeAsInBeer 2014年

您的isHuman()测试看起来不太正确。它会不会也找到水平的外星人?
并不是查尔斯(Charles)

@查尔斯你是对的。由于“聪明”机制的工作方式以及我们在战斗查询中无法确定聪明的事实,很难(不可能)找到敌人是人类还是已升级的外星人。即使使用一些基本的数学运算,很有可能对它是否是人类的有根据的猜测也是不准确的。我想我会改变他,使之脱离人类。
FreeAsInBeer 2014年

您的isSpecie-tests看起来很酷,但是即使是猛烈的战斗,这些测试也很快会失败...
CommonGuy 2014年

2

守护

堆积生命,增强力量和防御,然后保持原状。仅在对手似乎具有攻击性(定义为strength大于2)时攻击:

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

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

    public boolean wantToFight(int[] enemyAbilities){
        return enemyAbilities[1] >= 3;
    }
}

2

恶霸外星人

欺负外星人会四处走走,无视敌人,直到他发现某个弱者可以与之交战。

package alien;

import planet.Move;

public class BullyAlien extends Alien {

    @Override
    public void setAbilityPoints(float[] abilities) {
        abilities[0] = 2;
        abilities[1] = 8;
        abilities[2] = 0;
        abilities[3] = 0;
        abilities[4] = 0;
    }

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

    @Override
    public boolean wantToFight(int[] enemyAbilities) {
        return enemyAbilities[1] < 3;
    }           
}

2
噢,外星人只是想成为朋友。
user3334871 2014年

3
@ user3334871更像:“欺负外星人只是想犯语法错误”
贾斯汀

不想战斗看敌人的能力吗?
IngoBürk'14

@IngoBürk在您发表评论时已经这样做了
William Barbosa

一定花了我很长时间才能滚动线程。:)
IngoBürk'14

2

盲目的

不在乎周围的人或周围的事物,只是尝试确定当前面对的外星人是否比自己强或更弱,然后攻击那些弱者。

package alien;
import planet.Move;
import java.util.Random;

public class BlindBully extends Alien {

    private final int LIFE = 0;
    private final int STRENGTH = 1;
    private final int DEFENSE = 2;
    private final int VISION = 3;
    private final int CLEVERNESS = 4;

    private Random rand = new Random();

    @Override
    public void setAbilityPoints(float[] abilities) {
        abilities[LIFE] = 6;
        abilities[STRENGTH] = 2;
        abilities[DEFENSE] = 2;
        abilities[VISION] = 0;
        abilities[CLEVERNESS] = 0;
    }

    @Override
    public Move move(char[][] fields) {
        // Go west! To meet interesting people, and kill them
        switch (rand.nextInt(3)) {
            case 0:
                return Move.NORTHWEST;
            case 1:
                return Move.SOUTHWEST;
            default:
                return Move.WEST;
        }
    }

    @Override
    public boolean wantToFight(int[] enemyAbilities) {
        int myFightRating = getLifeLvl() + getStrengthLvl() + getDefenseLvl();
        int enemyFightRating = enemyAbilities[LIFE] + enemyAbilities[STRENGTH] + enemyAbilities[DEFENSE];
        return myFightRating >= enemyFightRating;
    }

}

2

秘密武器2

package alien;

import planet.Move;

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

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

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

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

public boolean wantToFight(int[] enemyAbilities)    {

    return enemyAbilities[1] < 4;
  }
}

所以这是最好的?哈哈
justhalf 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.