Игра на выживание - AlienWar


96

AlienWar

Эта игра разворачивается на очень людной планете, где инопланетяне являются превосходной расой. Твоя задача - создать своего собственного пришельца и победить всех остальных.

Доска

Это двухмерная доска.
Длина одной стороны доски составляет Math.ceil(sqrt(species * 100 * 2.5))~ 40% используемой платы. Доска - это планета, поэтому если вы выйдете из карты на западе, вы вернетесь на восток. Если вы выйдете на север, вы окажетесь на юге.

способности

У каждого вида на планете есть способности. Они здесь:

Имя         Преимущество 
life HP = lifeLVL * 5 (уменьшается с каждым полученным вами ударом, 0 = мертвый), базовый HP = 10
сила Ваши удары наносят случайный урон в диапазоне от [1 до forceLVL]
защита Случайным образом выбирайте int в диапазоне [0 - (50 / defenseLVL + 1)], если int == 0, то избегайте следующей атаки
зрение Дает вам видение LVL / 2 поля вокруг вашего зрения
умение Размывает (увеличивает) каждую способность случайным образом в диапазоне [от 0 до умения LVL / 2] при отправке другим инопланетянам

Игра

  • Там будет 100 экземпляров каждого представления.
  • После инстанции каждый иностранец может установить 10 очков способностей. Вы можете установить разные точки для каждого экземпляра.
  • Если вы установите более 10 очков, экземпляр умирает.
  • Игра состоит из 1000 раундов. Каждый раунд:
    • Каждый пришелец должен вернуть ход через move(char[] fields). Это включает Move.STAY.
    • Если на поле находятся несколько пришельцев, 2 будут выбраны случайным образом:
      • Если оба договорились о мире (верните ложь wantToFight), они останутся там, где они есть, иначе они будут сражаться.
      • Это происходит до тех пор, пока на поле не останется только один инопланетянин или пока все не согласятся на мир.
  • Если инопланетянин что-то убивает, он получает 1/5 от каждой способности своего врага . HP победителей будут пополнены 2 * врагаLifeLVL .

  • Победителем считается тот, у кого больше способностей (сумма способностей живых инопланетян).

Поединки

Оба пришельца будут бить друг друга "одновременно", это означает, что если вы убьете другого пришельца, он все равно может ударить вас один раз.

Уклоняясь: Перед тем, как попасть, игра будет вычислить , если вы можете уклониться от атаки с помощью rand.nextInt(50 / defenseLvl + 1) == 0. defenseLvl никогда не будет больше 50 при расчете ваших навыков уклонения (следовательно, максимальный шанс уклонения составляет 50%).

Удар: если вы не уклоняетесь от атаки, вы получите удар, и ваш HP будет уменьшен на rand.nextInt(enemy.getStrengthLvl()) + 1.

Бой заканчивается, когда один или оба вовлеченных пришельца мертвы. Победитель, если таковой существует, получает вознаграждение.

Правила игры

  • Базовый уровень для каждой способности (без начисления очков способностей) равен 1 (базовый уровень здоровья равен 10).
  • Ценности, которые посылают, когда их просят сражаться, - это уровень жизни (не HP!), Сила, защита и уровень видения .
  • Ум не посылается, когда его просят сражаться.
  • Все числа с плавающей запятой округляются до ближайшего целого числа при их использовании / отправке, но сохраняются и увеличиваются как числа с плавающей запятой.
  • Максимальный шанс уклонения составляет 50%. В противном случае бои могут никогда не закончиться.

Добыча

Есть 5 видов, которые уже на поле. Поскольку они являются добычей, они предпочитают не сражаться, когда их об этом просят.

Кит: 10 уровень жизни   
Корова: 10 уровень силы Случайный ход
Черепаха: 10 уровень защиты юго-запад
Орел: зрение 10 уровня Исследует поля, пытается избежать опасности      
Человек: 10 уровень ловкости Северо-восток

Они будут представлены своей первой буквой (т.е. Wдля кита) на карте («Чужие с» A, пустые поля с пробелами ' ').

Дополнительные правила

  • Отражение запрещено.
  • Взаимодействие (создание экземпляров и т. Д.) С другими инопланетянами запрещено.
  • Запись / чтение внешних ресурсов, таких как файлы или базы данных, также запрещено.
  • Допускается только отправка Java (версия 1.8) (Java довольно прост, и вам не нужно быть экспертом в этой игре).
  • Все материалы должны быть расширены для инопланетного класса и будут помещены в инопланетный пакет.
  • Я приму лучшего инопланетянина 19 июля. Все иностранцы, представленные до 12:00 UTC в этот день, будут проверены.
  • Максимум 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 игр)

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
Чужой. BananaPeel 1162.6
Alien.Rock 1159.2
Alien.BullyAlien 1106,3
Чужой. Джеффри 778,3
Alien.SecretWeapon 754,9
Alien.SecretWeapon3 752,9
Alien.FunkyJack 550.3
Чужой. Камень 369,4
Чужеземец. Ассасин 277,8
Alien.Predicoward 170,1
prey.Cow 155.2
Alien.Morphling 105,3
Alien.Eli 99,6
Чужой. Воин 69.7
Alien.Hunter 56,3
Alien.Manager 37,6
Alien.OkinawaLife 14,2
добыча. Кит 10,5
Alien.Gamer 4.5
Alien.Randomite 0
Alien.Guard 0
добыча.Орел 0
Alien.Rogue 0
Alien.WeakestLink 0
Alien.Fleer 0   
Alien.Survivor 0
Alien.Sped 0
Alien.Junkie 0
Чужой.Ковард 0
Alien.CleverAlien 0
добыча.Человек 0
alien.BlindBully 0
prey.Turtle 0
Alien.AimlessWanderer 0

14
Три отрицательных голоса, что на земле? И я не вижу ни одного отрицательного комментария. Люди, которые пассивно агрессивно раздражены тем, что это ограничивается Java?
Мартин Эндер

6
@ m.buettner Мое отрицательное замечание относится к ограничению божественной ценности Java (хотя, если бы оно было ограничено самым прекрасным языком из когда-либо созданных, я бы все равно понизил его за ограничение 1 языком). Я не видел смысла в добавлении комментария, так как было очевидно, для чего нужны отрицательные голоса.
Гарет

6
Хммм, у меня смешанные чувства здесь
г-н Чужой

5
@ user3334871 Я не думаю, что изменение какого-либо из правил после 17 ответов (и, возможно, еще дюжина людей, работающих над представлениями) - это хорошая идея. Поскольку только немногие из нас здесь (если таковые имеются) являются профессиональными гейм-дизайнерами, почти любой самодельный KotH может иметь некоторые проблемы с балансировкой - но если исследовать пространство возможных стратегий все еще весело (что, очевидно, так и есть, судя по ответам, Я не думаю, что это большая проблема.
Мартин Эндер

5
@Manu Для математически наклонного описания того, как доска оборачивается, вводит в заблуждение. Вы говорите, что это планета, и она охватывает восток / запад. Нет ничего, что действительно указывало бы на то, что оно также охватывает север / юг. На самом деле, если это так, то технически это уже не сфера, а тор: kotaku.com/classic-jrpg-worlds-are-actually-donuts-1239882216 . Вы также можете заметить, что, заметив, что когда вы уходите с вершины карты мира (северный полюс), вы не появляетесь внизу (южный полюс). Следовательно, предложение Майкла определенно верно, я думаю.
Мартин Эндер

Ответы:


11

PredicatClaw (rawr)

Этот инопланетный инопланетянин поглотит вас целиком (хорошо, может, она сначала немного вас разжует) ... если вы покажетесь слабым из-за ее алгоритмов предсказания.

Порода Предикатов, которые имеют более жесткие когти и клыки, чем его коллеги.

РЕДАКТИРОВАТЬ: новые целевые приоритеты

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
Марк Габриэль

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

6
Каждый раз, когда я читаю этот комментарий («просто чтобы убедиться»), мне приходится смеяться :-D
Матиас

Забавно, я только что прочитал это: blog.codinghorror.com/i-shall-call-it-somethingmanager
11684

@ 11684 любой порядочный разработчик знает, что, конечно, но в моем случае я действительно имею в виду менеджера;)
Ingo Bürk

18

CartographyLongVisionAlien

Этот Инопланетянин является последовательным вариантом одной из моих попыток создать инопланетянина с потенциальным выигрышем.

Он имеет начальное видение 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 );
   }

 }

Обновлен, чтобы добавить прогноз добычи в будущем и обеспечить возможность нападения на
китов

4
Ура! Наконец-то победил инопланетянин, который рассчитывает не только на силу и жизнь, но и на зрение :)
CommonGuy

3
Было очень трудно найти инопланетянина, который был бы последовательным исполнителем! Все остальные участники в основном придерживаются тех же идей: избегайте инопланетян, атакуйте добычу и начинайте только те бои, которые вы почти гарантированно выиграете. Этот инопланетянин следует тем же идеям, но лучше избегает инопланетян. Это дает ему малейшее преимущество, потому что дороже получить больше способностей, если вы проиграете бой.
Муги

Я попробовал другие, более экзотические идеи, но информации недостаточно. то есть размер карты, количество инопланетян и т. д.
Moogie

Отличная работа! Я тоже был немного расстроен отсутствием информации - извлечение дополнительной информации из прошлого - это творчество.
Бенни

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

checkAbilitiesOkпроверяет, что число с плавающей точкой в ​​массиве составляет до 10.0. Однако значения с плавающей запятой округляются до целых в игровой логике, а Java округляется до 0,5.
James_pic

@justhalf все еще выставляет 10 баллов, они просто разумно распределены.
CommonGuy

1
Я должен сказать, что это была не моя идея изначально - я позаимствовал ее у PredicatClaw
James_pic

1
Очень хорошо. Ваши статические константы, вероятно, лучше моих, а ваш wantToFight определенно умнее, мне просто лень. :)
Бенни

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 Хорошо подумав, я немного изменил это.
Timtech

9

Ван Пелт

Охотник из Джуманджи. Он охотится, когда ему не больно, избегает, когда он есть, и является достойным судьей того, что он может убить. Банановая кожура продолжала сбивать его с толку, но научила его новым трюкам.

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
о нет! Я знал, что что-то забыл ... Я
закрою

Я несколько разочарован тем, что в этом ответе было больше голосов, чем в моей, более старой, в настоящее время выигрышной записи.
James_pic

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
Я не уверен, насколько хорошо Рок продержится, как только его враги начнут получать некоторые баффы из-за победы в битвах. Выглядит хорошо, хотя.
Кайл Канос

@KyleKanos я понимаю; тем не менее, я предполагаю, что буду сражаться с большинством жертв / инопланетян, пока они не умны. Разве это не даст ему несколько положительных эффектов?
Timtech

Теперь, оглядываясь назад на мой комментарий, я думаю, что это было совсем не то, что я хотел сказать. Я хотел сказать, что wantToFightусловия не будут давать, trueкогда враги начнут накапливать уровни; Вы быстро превратитесь в сильного пацифиста.
Кайл Канос,

@KyleKanos О, я понял. Я немного изменил это.
Timtech

6

Morphling

Не мог придумать другое имя, этот парень случайным образом распределяет 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

@ user3334871, хотя я проверил с твоим предложением, и мой морфлинг просто выжил лучше: D
Sikorski

@Sikorski Ну, рад, что смог помочь, не уверен, почему так будет лучше, хаха.
user3334871

@Sikorski Я думаю, это просто означает, что оставаться на месте часто безопаснее, чем делать наименее опасный ход, если все ходы опасны.
Мартин Эндер

Ааа, стратегия "Олень в фарах", мне нравится.
user3334871

6

Бендер "Изгиб" Родригес

Я был довольно либеральным с комментариями кода. Вы можете прочитать их в контексте, чтобы увидеть, что происходит, но я также добавлю некоторые фрагменты ниже.

Резюме

Этот инопланетянин действует по принципу «убить маленького Человека» легко и раздувает вашу воспринимаемую силу, что запугает других инопланетян, заставляя их держаться подальше.

Киты и Орлы также сгибаемы. знак равно

движение

Двигайтесь на запад или на юг, если вы не нашли что-то интересное для атаки:

  • Для жертвы, чье движение известно, мы добавляем их желательность в квадрат, на котором они будут в следующем ходу.
  • Для тех, кто этого не делает, мы делим их желательность поровну между квадратами, чтобы они могли перейти к следующему ходу.
    • Инопланетяне получают отрицательный бонус к существующей площади из-за банановой кожуры.

Если вы не найдете ничего интересного поблизости, выясните, является ли более перспективным вариант - юг, запад или юго-запад.

Выбор одного или двух преобладающих направлений уменьшает вероятность того, что любой данный Бендер встретит кого-либо из своих соотечественников, а выбор указателя направления для своей основной добычи должен помочь ему быстрее убить всех людей.

Я мог бы, вероятно, настроить числа в матрице желательности с помощью генетического алгоритма James_pic для еще лучших результатов, но я не знаю, как это сделать.

Агрессивность

Бендер в основном нацелен на добычу, и довольно консервативен со своей wantToFight. Любой, кто выше Силы 4, избегает, если только вы не думаете, что имеете дело с умным человеком. Умное человечество демонстрирует, что у него больше Защиты и Видения, чем у инопланетян. Он корректируется в течение одного экземпляра собственными характеристиками Бендера, чтобы учесть, что инопланетяне убивают черепах и орлов.

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 Хех. Значит, я чувствовал себя хорошо только случайно? Спасибо, что поймали это.
Майкл

Я просмотрел все это и исправил еще пару проблем.
Майкл

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

трус

Я в основном украл схему движения Орла, чтобы избежать опасности и сложить защиту в случае нападения.

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: Мое краткое чтение кода показало, что я переписал setAbilityPointsзначения 1, но, посмотрев на него глубже, я думаю, что вы правы. Я собираюсь оставить все как есть, потому что большее зрение позволяет мне видеть дальше и избегать опасности, но спасибо за улов.
Кайл Канос

Кроме того, math.round всегда округляется до 0,5, поэтому вы получаете дополнительное видение, если у вас есть нечетное число
Andreas

@Manu: я поменял свои ценности зрения и защиты, чтобы улучшить бегство.
Кайл Канос

4

насмехаться

ПАНИКА

АПОКАЛИПСИС

RUUUUUUUUUUN

AAAAAAAAAAAAAAAAAAAAAAA


Избегает сражений, когда это возможно.

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

Вы должны дать этому другое имя ... и отдать должное ответу, который вы скопировали: codegolf.stackexchange.com/a/32787/9498
Джастин

2
@Quincunx Это совпадение, не видел этого ...
Stommestack

Извините, я только что понял, что оба ответа скопированы с орла. Вы не скопировали другой ответ, я просто недостаточно внимательно прочитал. Тем не менее, другое имя будет уместным.
Джастин

1
Поменял имя!
Stommestack

2
Должен быть назван Rincewind.
Волхв

4

Predicoward (мурлыкать)

Порода Предикатов, которые жили (до сих пор) на страхе и избегая неприятностей. Из-за их образа жизни у них не развиты боевые инстинкты, но их восприятие является исключительным.

Их вид ненавидят их товарищи Предикаты.

РЕДАКТИРОВАТЬ: вместо Манхэттена изменилось расстояние до взвешенного расстояния

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

О, я оставил печатные заявления? Я изменю их позже. Ха - ха. Плюс это еще не окончательно. Прямо сейчас, Predicoward отстой. Его алгоритмы уклонения от инопланетян будут улучшены в ближайшее время. :) РЕДАКТИРОВАТЬ: Спасибо за тот, кто удалил печатные заявления. : D (Джоп?)
Марк Габриэль

РЕДАКТИРОВАТЬ: Predicowards теперь намного лучше убегать, чем надоедливые маленькие неконкурентные предсказания, которые они были вчера. > :)
Марк Габриэль

Общая информация: Это мой любимый прогноз <3
Марк Габриэль,

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.
Не то, что Чарльз

4
Почему бы не изменить каждый getI()на iи просто удалить getI()? Вы также можете перейти setI(int i)на this.i = i % 8;, и, поскольку вы используете его только в одном месте, просто измените каждый вызов setI(getI() + 1)наi = (i + 1) % 8;
Джастин

3

CleverAlien

Умный инопланетянин полагается исключительно на свое остроумие. Он случайно ходит вокруг и случайно решает драться. Он надеется, что сможет перехитрить своих врагов с удачей. (простите, если у меня есть какие-либо синтаксические ошибки, я не 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

Разбойник

Как уже говорили другие, я в какой-то степени использую движение Орла. Вместо того, чтобы попытаться сделать победившего пришельца (Мои лучшие идеи уже были приняты 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

2
использует int непосредственно как логическое значение, если блок часть Java 8? потому что он вообще не компилируется на моей машине (Java 7). Подсказка: человек-подарок
Сикорский,

Черт возьми, если я знаю, мой опыт Java был в основном ограничен сценариями и классами колледжа. Я просто сделаю сравнения, просто чтобы все было замечательно. Спасибо за головы!
user3334871

Кроме того, @Sikorski, ты создал собственную функцию main или init для запуска своих тестов? Или это может быть сделано только через предоставленный код? Клянусь, я так долго не кодировал в настоящей среде Java, что забыл правила выполнения кода Java :(
user3334871

не просто скачать код, который OP дал в ссылке на github, добавить другие классы и начать тестирование. О, вам нужно будет добавить запись для каждого класса инопланетян в классе Планета.
Сикорский

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){
Джошуа

3

FunkyBob

Первым приоритетом является выживание, в противном случае постараюсь найти добычу. Оценивает видимую область, чтобы найти общее направление с наименьшей угрозой или большей частью добычи. Кажется, во время моего тестирования выживаемость составила 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

FunkyJack

Просто для удовольствия, вот еще одна запись с немного другим подходом. Этот только сосредоточен на том, чтобы избежать боев. Это не совсем жизнеспособная стратегия из-за того, что в первые пару раундов вас окружают враги. 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 боевых характеристик.
Марк Габриэль

3

LazyBee

Я начал пытаться создать умный класс Пчелы, который использовал бы паттерны движений и дедуктивные рассуждения, но потом я стал спать, поэтому я переименовал его в LazyBee и назвал его ночью. Кажется, он действительно неплохо справляется с моими тестами (в среднем ~ 1645 с инопланетянами на github).

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
Превосходная работа! Я очень удивлен, что ты так хорошо забиваешь в жестком направлении.
Майкл

@ Майкл, ты не представляешь, как приятно я удивился, когда узнал! Я приложил много усилий к коду движения, затем он работал против HOLD как своего рода контрольная группа. затем я понял, что контрольная группа пинала задницу, поэтому я начал экспериментировать с различными оттенками ленивых!
thefistopher

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условия.
Кайл Канос

@KyleKanos Правда. Проблема устранена.
FreeAsInBeer

ваш тест isHuman () выглядит не совсем правильно. Разве это не найдет инопланетян, которые тоже выровнялись?
Не то чтобы Чарльз

@ Чарльз Ты прав. Трудно (невозможно?) Выяснить, является ли враг Человеком или выровненным инопланетянином из-за того, как работает механика «ловкости», и того факта, что мы не можем определить ловкость во время запроса на бой. Даже используя некоторую базовую математику, вполне вероятно обоснованное предположение о том, будет ли это человек неверным или нет. Я думаю, что я изменю его, чтобы убежать от людей.
FreeAsInBeer

Ваши isSpecie-тесты выглядят круто, но даже добыча сражается, и эти тесты скоро не пройдут ...
CommonGuy

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

Хулиган инопланетянин

Bully Alien будет ходить вокруг, игнорируя врагов, пока не найдет кого-то слабого, с кем можно связываться.

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

3
@ user3334871 Больше похоже на: «инопланетянин просто хочет иметь синтаксическую ошибку»
Джастин

Разве не хотите ToFight посмотреть на способности противника?
Инго Бюрк

@ IngoBürk К тому времени, как вы это прокомментировали, это уже было сделано
Уильям Барбоза,

Должно быть, мне понадобилось слишком много времени, чтобы пролистать нить. :)
Ingo Bürk

2

BlindBully

Неважно, кто или что вокруг него, просто пытается решить, является ли пришелец, с которым он сейчас сталкивается, сильнее или слабее, чем он сам, и атакует тех, кто слабее.

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

SecretWeapon2

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

Так это лучшее? хаха
полугодие
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.