Гра на виживання - AlienWar


96

AlienWar

Ця гра відбувається в дуже переповненій планеті, де прибульці є вищою расою. Ваше завдання - створити власного прибульця і ​​перемогти всіх інших.

Дошка

Це двовимірна дошка.
Довжина однієї сторони дошки Math.ceil(sqrt(species * 100 * 2.5))= ~ 40% використовуваної дошки. Дошка - це планета, тож якщо ви виходите з карти на заході, ви повернетесь на схід. Якщо ви вийдете на північ, ви опинитесь на півдні.

Здібності

Кожен вид планети має здібності. Ось вони:

Найменування         Користь 
життя HP = lifeLVL * 5 (зменшується з кожним ударом, який ви отримуєте, 0 = мертвий), базовий HP = 10
сила Ваші удари завдають випадкового int в межах [1 до jakoсті LVL]
Захист Випадково виберіть int у діапазоні [0 до (50 / захистLVL + 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 (базовий HP - 10).
  • Цінності, що їх посилають на боротьбу, - це життєвий рівень (а не HP!), Сила, захист і зір .
  • Розумність НЕ надсилається, коли її просять боротися.
  • Усі плаваючі числа будуть ОКРЕМЕННІ до найближчого цілого числа при використанні / відправці, але зберігаються та збільшуються як плаваючі.
  • Максимальний шанс ухилення - 50%. Інакше бійки можуть ніколи не припинятися.

Здобич

Є 5 видів, які вже є на полі. Оскільки вони є здобиччю, вони вирішують не битися, коли їх просять.

Кит: lvl 10 життя   
Корова: lvl 10 сила Випадковий хід
Черепаха: lvl 10 оборона південний захід
Орел: lvl 10 зір Оглядає поля, намагається уникнути небезпеки      
Людина: lvl 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 ігор)

чужий.PredicatClaw 1635.4
інопланетянин.ЛазиБее 1618.8
інопланетянин.Картограф Лонг ВізіонАлієн 1584.6
чужий.Вибір Ваших Битв 1571.2
чужий.Бендер 1524.5
інопланетянин.ГерджанАлієн 1507,5
інопланетянин.FunkyBob 1473.1
інопланетянин.SecretWeapon2 1467.9
іноземець.PredicatEyes 1457.1
інопланетянин.Корпоративнеалієн 1435.9
інопланетянин.Гендерний велетень 1422.4
чужий.CropCircleAlien 1321.2
чужорідний.VanPelt 1312.7
інопланетянин.НовийGuy 1270.4
інопланетянин.BananaPeel 1162.6
чужорідний.Рок 1159.2
чужий.БулліАлієн 1106.3
інопланетянин.Джеффрі 778.3
інопланетянин.SecretWeapon 754.9
інопланетянин.SecretWeapon3 752.9
інопланетянин.FunkyJack 550.3
чужорідний.Стон 369.4
чужинець.Асссасін 277.8
чужорідний.Predicoward 170.1
здобич.Корова 155.2
інопланетянин Морфлінг 105.3
чужорідний.Елі 99.6
інопланетянин. Воїн 69.7
інопланетянин. Мисливець 56.3
інопланетянин. Менеджер 37.6
інопланетянин.OkinawaLife 14.2
здобич.Кіт 10.5
чужий.Гамер 4.5
alien.Randomite 0
чужий.Гуард 0
здобич.Орел 0
чужорідний.Рога 0
alien.WeakestLink 0
інопланетянин. Флер 0   
чужий.Сервівор 0
чужий.Спед 0
чужий.Junkie 0
інопланетянин
alien.CleverAlien 0
здобич.Людина 0
alien.BlindBully 0
здобич.Турець 0
alien.AimlessWanderer 0

14
Три низовини, що на землі? І я не бачу жодного негативного коментаря. Чи люди, які пасивно агресивно дратують, що це обмежується Явою?
Мартін Ендер

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

6
Гммм, у мене тут змішані почуття
містер Чужий

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

5
@Manu Для математично схильних опис того, як дошка обгортає, дещо вводить в оману. Ви говорите, що це планета, і вона охоплює схід / захід. Немає нічого, що насправді вказує на те, що воно також переносить північ / південь. Насправді, якщо це так, технічно це вже не сфера, а торус: kotaku.com/classic-jrpg-worlds-are-actically-donuts-1239882216 . Ви також можете бачити, що помітивши, що коли ви йдете "з" вершини карти світу (північний полюс), ви не з'являєтесь внизу (південний полюс). Отже, пропозиція Майкла, безумовно, справедлива.
Мартін Ендер

Відповіді:


11

PredicatClaw (rawr)

Цей котячий інопланетянин проковтне вас цілком (гаразд, вона спочатку трохи пожує вас) ... якщо вам здасться слабкою на основі її алгоритмів прогнозування.

Порода Predicats, яка має більш жорстокі кігті та ікла, ніж її аналоги.

EDIT: Нові цільові пріоритети

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

КартографіяLongVisionAlien

Цей Чужеземець - це незмінний варіант однієї з моїх спроб створити прибульця, який має виграшний потенціал.

Він має початкове бачення 5x5, яке використовує для складання внутрішньої карти навколишнього району, надаючи йому чудову можливість уникнення ворога.

У моєму тестуванні 100 раундів, в середньому, він підкрадається до всіх інших прибульців. (07.07.2014)

ОНОВЛЕНИЙ GIF, що показує ефект відштовхування / залучення поля

Я змінив ігровий код, щоб створити анімовані GIF-файли моделювання. Ви можете переглянути таке моделювання тут

 package alien;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

     returnMove = findBestMove( fields );

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

     return returnMove;
   }

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

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

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

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

 }

Оновлено, щоб додати прогноз майбутньої здобичі та забезпечити, щоб кити були атаковані
Moogie

4
Так! Нарешті перемагає іноземець, який не розраховує лише на сили та життя, а й на бачення :)
CommonGuy

3
Дуже важко було отримати іноземця, який був послідовним виконавцем! Інші топ-учасники в основному всі дотримуються одних і тих же ідей: уникайте прибульців, атакуйте здобич і ініціюйте лише бійки, які ви майже гарантовано виграєте. Цей інопланетянин дотримується тих самих ідей, але з кращим униканням інопланетян. Це дає йому найменшу перевагу, тому що дорожче здобути більше здібностей, якщо ви програєте бій.
Moogie

Я робив спроби інших більш екзотичних ідей, але інформації просто не вистачає. тобто розмір карти, кількість іноземців тощо
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. Однак значення float округляються до ints в логіці гри, а 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 к.с. (або менше, залежно від уже нанесеної шкоди), але я не знаю, чи
прибуде

@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

Морфлінг

Не міг придумати іншого імені, цей хлопець випадковим чином розподіляє 10 балів за свої здібності. Майже рухається як Окінава Життя (thx за ваші зусилля) і хоче битися лише в тому випадку, якщо його сила більша, ніж сила противника.

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

}

Ах, ти знаєш, ти маєш рацію. Кінцеві дужки вбивали мене в цьому виклику (через це мені довелося відредагувати пару разів). Я це бачу зараз, і це правильно. Дякуємо, що вказали на це!
користувач3334871

@ user3334871, хоча я перевірив вашу пропозицію, і мій морфінг просто вижив: D
Sikorski

@Sikorski Ну, радий, що можу допомогти, не знаю, чому це стане краще, ха-ха.
користувач3334871

@Sikorski Я гадаю, що це просто означає, що залишатися на місці часто безпечніше, ніж робити найменш небезпечний хід, якщо всі рухи небезпечні.
Мартін Ендер

Ах, стратегія "Олень у фарах", мені це подобається.
користувач3334871

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

@Moogie Heh. Тож мені було добре лише випадково? Дякуємо, що це зробили.
Майкл

Я переглянув всю справу і виправив ще пару питань.
Майкл

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

@justhalf: Моє коротке прочитання коду начебто підказує, що перенаписали setAbilityPointsзначення 1, але дивлячись на це глибше, я вважаю, що ви правильні. Я збираюся залишити це так, як це тому, що більш широке бачення дозволяє мені бачити далі і уникати небезпеки, але дякую за улов.
Кайл Канос

Крім того, math.round завжди завершується на 0,5, тому ви отримуєте додатковий зір, якщо маєте непарне число
Andreas

@Manu: Я змінив свої бачення та захист, щоб поліпшити відсталість.
Кайл Канос

4

Флер

ПАНІКА

АПОКАЛІПС

RUUUUUUUUUUN

AAAAAAAAAAAAAAAAAAAAAAAA


Уникайте боїв, коли це можливо.

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

Вибачте, я щойно зрозумів, що обидві відповіді копіюють з Eagle. Ви не скопіювали іншої відповіді, я просто не прочитав достатньо уважно. Однак інша назва була б доречною.
Джастін

1
Змінено ім’я!
stommestack

2
Слід назвати Rincewind.
Magus

4

Передбачуваність (муркання)

Порода Predicats, яка жила (поки що) на страху і тримаючись подалі від неприємностей. Через свій спосіб життя у них не розвинулися бойові інстинкти, але сприйняття їх виняткове.

Їх вид ненавидить їхні товариші-прогнози.

EDIT: Натомість змінено відстань Манхеттена на зважену відстань

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 смокче. Його алгоритми ухилення від прибульців незабаром будуть вдосконалені. :) EDIT: Дякую тому, хто видалив друковані заяви. : D (Jop?)
Марк Габріель

EDIT: Predicowards тепер набагато краще бігати, аніж прискіпливі маленькі неконкурентні передбачення, які були вчора. > :)
Марк Габріель

Загальна інформація: Це мій улюблений Predicat <3
Марк Габріель

4

PredicatEyes (мяу)

Порода Predicats, які мають більш чіткий зір, ніж його колеги, що дозволяє їй добре підглядати своїх ворогів.

EDIT: Нові цільові пріоритети

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
Це буде чистіше, якщо ви повторили перехід.
Не те, що Чарльз

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

Код зосереджений на ідеї, що я повинен спринтуватися до людини. Після того, як я його побив, я згортаюся на південний захід, де шукатиму черепаху.

EDIT: О, і про черепашку ... мій інопланетянин їх не любить, тож ви, хлопці, абсолютно канонічні.


Щойно зрозумів, що я можу спринтуватися і до черепахи. Хто не любить шахраїв?
користувач3334871

2
використовує Int безпосередньо як булевий, якщо блокувати частину Java 8? тому що він зовсім не компілюється на моїй машині (Java 7). Підказка: humanPresent
Sikorski

Чорт, якщо я знаю, мій досвід Java здебільшого обмежений сценаріями та класами на рівні коледжу. Я просто зроблю порівняння, просто так все персично. Дякую за голову вгору!
користувач3334871

Також, @Sikorski, ви створили власну головну чи функцію init для запуску тестів? Або це можна зробити лише за допомогою наданого коду? Я клянусь,
пройшло

не просто завантажуйте код, вказаний ОП у посиланні 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
Відмінна робота! Я дуже вражений, що ти так добре забиваєш із жорстким кодом напрямку.
Майкл

@Michael Ви не знаєте, як приємно здивувався я, коли дізнався! Я доклав багато зусиль до коду руху, тоді я мав його працювати проти HOLD як свого роду контрольної групи. потім я зрозумів, що контрольна група брикає попку, і я почала експериментувати з різними відтінками ледачих!
thefistopher

3

NewGuy

Намагається залучати "легкі" цілі для раннього ведення господарства. В іншому випадку просто рухайтеся спорадично.

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 () виглядає не зовсім правильно. Чи не знайдуть інопланетян, які також вирівнялися?
Не те, що Чарльз

@Charles Ви маєте рацію. Важко (неможливо?) З'ясувати, чи є ворог людиною, чи вирівняним прибульцем через те, як працює механік "кмітливості", і той факт, що ми не можемо визначити кмітливість під час бойового запиту. Навіть використовуючи якусь основну математику, дуже ймовірно, що невірна здогадка про те, чи це людина чи ні, буде неточною. Я думаю, я зміню його, щоб він бігав від людей.
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

Хуліган Чужий

Хуліган Чужий буде ходити навколо ігноруючи ворогів, поки не знайде когось слабкого, щоб зіпсуватись.

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
Авжеж, хуліган-іноземець просто хоче дружити.
користувач3334871

3
@ user3334871 Більше схожих на тему: "інопланетянин-хуліган просто хоче помилитися в синтаксисі"
Джастін

Чи не хочете, щоб Боротьба дивилася на здібності противника?
Інго Бюрк

@ IngoBürk Це вже було зроблено до моменту, коли ви коментували
Вільям Барбоса

Мабуть, мені знадобилося занадто довго, щоб потім прокрутити нитку. :)
Інго Бюрк

2

СліпийБуллі

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

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

public class BlindBully extends Alien {

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

    private Random rand = new Random();

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

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

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

}

2

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

Так це найкраще? ха-ха
justhalf
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.