Jogo de Sobrevivência - AlienWar


96

AlienWar

Este jogo se passa em um planeta muito movimentado, onde os alienígenas são a raça superior. Sua tarefa é criar seu próprio alienígena e vencer todos os outros.

O quadro

É uma placa bidimensional.
O comprimento de um lado da placa é Math.ceil(sqrt(species * 100 * 2.5))= ~ 40% da placa usada. O tabuleiro é um planeta; portanto, se você sair do mapa a oeste, voltará a leste. Se você sair no norte, se encontrará no sul.

Habilidades

Cada espécie do planeta tem habilidades. Aqui estão eles:

Nome         Benefício 
vida HP = lifeLVL * 5 (reduz a cada golpe que você recebe, 0 = morto), HP base = 10
força Seus acertos causam um int aleatório no intervalo [1 a StrengthLVL] de dano
defesa Selecione aleatoriamente int no intervalo [0 a (50 / defenceLVL + 1)], se int == 0, desvie do próximo ataque
vision Dá-lhe visionLVL campos / 2 à sua volta
cleverness Desfoca (aumenta) todas as habilidades aleatoriamente no intervalo [0 a clevernessLVL / 2] ao enviar para outros alienígenas

O jogo

  • Haverá 100 instâncias de cada envio.
  • Após instanciar, cada alienígena pode definir 10 pontos de habilidade no total. Você pode definir pontos diferentes para cada instância.
  • Se você definir mais de 10 pontos, a instância morre.
  • Um jogo consiste em 1000 rodadas. Cada rodada:
    • Todo alienígena tem que retornar uma jogada via move(char[] fields). Isso inclui Move.STAY.
    • Se vários alienígenas estiverem em um campo, 2 serão selecionados aleatoriamente:
      • Se ambos concordarem com a paz (retornarem falsos wantToFight), eles permanecerão onde estão, ou então lutarão.
      • Isso ocorre até que apenas um alienígena permaneça no campo ou todos concordem em paz.
  • Se um alienígena mata alguma coisa, ele recebe 1/5 de cada uma das habilidades de seus inimigos . Os vencedores HP serão recarregados com 2 * enemyLifeLVL .

  • Vencedor é aquele com mais habilidades (soma de habilidades de alienígenas vivos).

Lutas

Os dois alienígenas vão se acertar "ao mesmo tempo", isso significa que se você matar o outro alienígena, ele ainda poderá atingi-lo uma vez.

Esquivando: Antes de ser atingido, o jogo irá calcular se você pode evitar o ataque usando rand.nextInt(50 / defenseLvl + 1) == 0. defenseLvl nunca será maior que 50 ao calcular suas habilidades de esquiva (portanto, a chance máxima de esquiva é de 50%).

Bater: Se você não se esquivar do ataque, será atingido e seu HP será reduzido em rand.nextInt(enemy.getStrengthLvl()) + 1.

Uma luta termina quando um ou os dois alienígenas envolvidos estão mortos. O vencedor, se houver, recebe a recompensa.

Regras do jogo

  • O nível básico para cada habilidade (sem fornecer pontos de habilidade) é 1 (o HP base é 10).
  • Os valores enviados quando solicitados a lutar são os níveis de vida (não HP!), Força, defesa e visão .
  • A esperteza NÃO é enviada quando solicitado a lutar.
  • Todos os números flutuantes serão ROUNDADOS para o número inteiro mais próximo ao usá-los / enviá-los, mas armazenados e aumentados como flutuantes.
  • A chance máxima de esquiva é de 50%. Caso contrário, as brigas nunca poderão terminar.

A presa

Existem 5 espécies que já estão em campo. Por serem presas, optam por não lutar quando solicitadas.

Baleia: lvl 10 vida permanece   
Vaca: força nív. 10 movimento aleatório
Tartaruga: defesa lvl 10 sudoeste
Águia: visão lvl 10 Examina campos, tenta evitar o perigo      
Humano: inteligência nvl 10 Nordeste

Eles serão representados com a primeira letra (ou seja, Wpara baleia) no mapa (Aliens com A, campos vazios com espaço em branco ' ').

Regras adicionais

  • A reflexão não é permitida.
  • Interagir (instanciar etc.) com outros alienígenas não é permitido.
  • A gravação / leitura de recursos externos, como arquivos ou bancos de dados, também não é permitida.
  • Somente envios de Java (versão 1.8) são permitidos (Java é bastante fácil e você não precisa ser um especialista para este jogo).
  • Todos os envios devem estender a classe alienígena e serão colocados no pacote alienígena.
  • Aceitarei o melhor alienígena no dia 19 de julho. Todos os estrangeiros enviados até às 12:00 UTC daquele dia serão testados.
  • Máximo de 3 envios por usuário, pois já existem muitos alienígenas.

Exemplo de um alienígena

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

}

Programa de controle

O código fonte do programa de controle pode ser encontrado aqui . Agora atualizado com todos os alienígenas incluídos na última corrida.

Pontuação final (20.07.2014, média de 10 jogos)

Alien.PredicatClaw 1635.4
alien.LazyBee 1618.8
alien.CartographerLongVisionAlien 1584.6
alien.ChooseYourBattles 1571,2
alien.Bender 1524.5
alien.HerjanAlien 1507.5
alien.FunkyBob 1473.1
alien.SecretWeapon2 1467,9
O que outras pessoas estão dizendo
alienígena.CorporateAlien 1435.9
alien.GentleGiant 1422.4
alienígena.CropCircleAlien 1321.2
alien.VanPelt 1312.7
alienígena.NewGuy 1270.4
alien.BananaPeel 1162.6
alien.Rock 1159.2
alien.BullyAlien 1106.3
alien.Geoffrey 778.3
alien.SecretWeapon 754.9
alien.SecretWeapon3 752,9
alien.FunkyJack 550.3
pedra alienígena 369,4
alien.Assassino 277,8
Alienígena.Predicoward 170.1
vaca 155,2
alienígena.Morphling 105.3
alien.Eli 99.6
alien.Warrior 69.7
alien.Hunter 56.3
alien.Manager 37.6
alien.OkinawaLife 14.2
baleia 10.5
alien.Gamer 4.5
alien.Randomite 0
alien.Guard 0
águia 0
alien.Rogue 0
alien.WeakestLink 0
alien.Fleer 0   
alien.Survivor 0
alien.Sped 0
alien.Junkie 0
alien.Coward 0
alien.CleverAlien 0
humano 0
alien.BlindBully 0
Tartaruga 0
alien.AimlessWanderer 0

14
Três votos negativos, o que na terra? E não vejo um único comentário negativo. As pessoas que são passivas agressivamente irritam que isso seja limitado ao Java?
Martin Ender

6
@ m.buettner Meu voto negativo é pela limitação à maldade que é o Java (embora, se fosse limitado à linguagem mais agradável já criada, eu ainda o rebaixaria por limitá-lo a 1 idioma). Não vi sentido em adicionar um comentário, pois era óbvio para que serviriam os votos negativos.
Gareth

6
Hmmm, estou tendo sentimentos mistos aqui
Sr. Estrangeiro

5
@ user3334871 Não acho que alterar nenhuma das regras após 17 respostas (e potencialmente uma dúzia de pessoas trabalhando nos envios) seja uma boa idéia. Como apenas o menor número de nós aqui (se houver) é designer de jogos profissional, praticamente qualquer KotH criado por si pode ter alguns problemas de equilíbrio - mas se explorar o espaço de possíveis estratégias ainda é divertido (o que, aparentemente, a julgar pelas respostas, votos e estrelas), não acho que seja um problema.
Martin Ender

5
@Manu Para os que estão inclinados matematicamente, a descrição de como o painel se envolve é um pouco enganadora. Você está dizendo que é um planeta e envolve leste / oeste. Não há nada que realmente indique que também envolve o norte / sul. De fato, se isso acontecer, tecnicamente não é mais uma esfera, mas um toro: kotaku.com/classic-jrpg-worlds-are-actually-donuts-1239882216 . Você também pode ver que, ao notar que, quando "desce" do topo de um mapa do mundo (o polo norte), você não aparece na parte inferior (o polo sul). Portanto, a sugestão de Michael é definitivamente válida, eu acho.
Martin Ender

Respostas:


11

PredicatClaw (rawr)

Essa alienígena felina engolirá você inteiro (tudo bem, talvez ela o morda um pouco primeiro) ... se você parecer fraco com base nos algoritmos de previsão dela.

Uma raça de predicados que têm garras e presas mais ferozes do que suas contrapartes.

EDIT: Novas prioridades de destino

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
Droga! Esses predicados são ferozes! Percebo que ambos decidimos mais ou menos o mesmo wantToFightalgoritmo.
James_pic

@ James_pic, vejo que grandes mentes pensam da mesma forma. : D
Mark Gabriel

27

Gerente

Aqui está um gerente. Naturalmente, a inteligência é 0 e ele sempre se esforça para ir aonde o sol não brilha. E, é claro, ele lutará apenas contra os fracos e é muito bom em evitar problemas:

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, apenas para a introdução. : P
apnorton

6
Cada vez que leio que o comentário ( "só para garantir") Eu tenho que rir :-D
Matthias


@ 11684 qualquer desenvolvedor decente sabe disso, é claro, mas no meu caso, eu realmente quero dizer um gerente;)
Ingo Bürk

18

CartographyLongVisionAlien

Este Alien é uma variante de desempenho consistente de uma de minhas tentativas de produzir um alienígena com potencial de ganho.

Possui visão 5x5 inicial que é usada para criar um mapa interno da área circundante, dando-lhe uma capacidade superior de evitar o inimigo.

Nos meus testes de 100 rodadas, em média, ele foge à frente de todos os outros alienígenas. (09/07/2014)

GIF ATUALIZADO mostrando o efeito de campo repelir / atrair

Modifiquei o código do jogo para produzir GIFs animados da simulação. Você pode ver essa simulação aqui

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

 }

Atualizado para adicionar presa previsão futuro e garantir que as baleias são susceptíveis de ser atacados
Moogie

4
Yay! Finalmente um estrangeiro está ganhando que não contar apenas com a força e vida, mas também a visão :)
CommonGuy

3
Foi muito difícil conseguir um alienígena que apresentasse um desempenho consistente! Os outros participantes principais seguem todos as mesmas idéias: evite alienígenas, ataque presas e inicie lutas que você quase ganhará. Este alienígena segue as mesmas idéias, mas com uma melhor evasão alienígena. Isso dá a menor vantagem, porque é mais "caro" ganhar mais habilidades se você perder uma luta.
Moogie

Tentei outras idéias mais exóticas, mas simplesmente não há informações suficientes expostas. ou seja, o tamanho do mapa, número de estrangeiros etc
Moogie

Bom trabalho! Eu também fiquei um pouco frustrado com a falta de informações - extrair informações adicionais do passado é criativo.
Benny

15

Escolha suas batalhas

Este alienígena foge de outros alienígenas, mas corre em direção a presas (desde que isso não leve em direção a alienígenas).

Eu usei um algoritmo genético para me ajudar a escolher os valores iniciais. Os resultados sugerem que devemos confiar na força e na vida para superar as brigas. A visão é útil mais tarde, mas podemos captá-la dos inimigos vencidos.

Nós apenas lutamos batalhas que achamos que podemos vencer confortavelmente - estimamos quantos movimentos seriam necessários para matar nosso alienígena, quantos seriam necessários para matar nosso inimigo, e só ingressaremos na batalha se formos "duas vezes mais difícil" nosso oponente.

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

Se você deseja executar seu próprio programa de reprodução / algoritmo genético, eu tenho uma cópia bifurcada do programa de controle para esse fim .


Como isso ignora a verificação do checkAbilitesOkmétodo?
FreeAsInBeer

checkAbilitiesOkverifica se os flutuadores na matriz somam 10,0. No entanto, os valores flutuantes são arredondados para ints na lógica do jogo, e Java arredonda 0,5 para cima.
James_pic

@justhalf ainda define 10 pontos, eles são distribuídos de forma inteligente.
precisa saber é o seguinte

1
Devo dizer que não era minha ideia inicialmente - I emprestado de PredicatClaw
James_pic

1
Muito agradável. Suas constantes de estatísticas são provavelmente melhores que as minhas e seu wantToFight é definitivamente mais inteligente, eu era apenas preguiçoso. :)
Benny

12

Junkie

Este alienígena é viciado em alguma coisa . Ele começa a guerra com uma correção bastante desagradável.

Enquanto sua correção está forte ( fix > 3), ele fica agradavelmente satisfeito em sentar-se em seu estupor e está disposto a tudo.

No entanto, quando sua correção começa a desaparecer ( fix <= 3), ele começa a tropeçar em nenhuma direção discernível, tentando descobrir o que aconteceu. Se for solicitado a lutar, ele se torna cauteloso e só luta se acha que pode vencer.

Uma vez que sua correção se esgota, sendo o viciado que ele é, ele deve reiniciar o ciclo vicioso.

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

Tenho certeza de que é seguro removê-lo && fix > 0por causa de redundância.
Timtech

10

Casca de banana

Só tenta enganar pessoas que precisam de um pouco de pancada. Derrotar não o deixará mais saudável.

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

Também é importante notar que [0] é vida e não saúde, então 100 seriam 510 HP (ou menos, dependendo do dano já sofrido), mas não sei se um alienígena ficaria tão alto ..
Gigala

@Gigala Bom pensamento, eu mudei um pouco.
Timtech

9

Van Pelt

O caçador de Jumanji. Ele caça quando não está ferido, evita quando está e é um juiz decente do que pode matar. Cascas de banana continuavam tropeçando nele, mas lhe ensinaram alguns truques novos.

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

}

Aprendeu a evitar cascas de banana, não é? : P
Timtech

8

Okinawa Life

Não é de admirar que eu seja o último em pé.

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

Caçador

Eu também roubei o movimento da águia, só que agora ele quer ir em direção a tudo, além de outros alienígenas. Tenta caçar e cultivar o máximo de presas possível e luta apenas quando parece que tem uma boa chance de vencer.

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

É mais que 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
    }
}

Sim, é uma tentativa flagrante de trapacear, mas ela estraga as regras. Se os recebedores planet.Speciefossem finalizados, essa brecha seria fechada.


4
Ah não! Eu sabia que esqueci uma coisa ... vou fechar a brecha e +1;)
CommonGuy 4/14/14

Estou um pouco decepcionado que esta resposta tenha sido mais positiva do que minha outra entrada mais antiga e atualmente vencedora.
11446 JamesJpic

7

Rocha

Eu acho que apenas ataca pessoas fracas e "inteligentes".

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
Eu não tenho certeza de quão bem o Rock vai durar quando seus inimigos começarem a receber alguns buffs devido a vitórias em batalhas. Parece bom embora.
Kyle Kanos

@KyleKanos eu entendo; no entanto, presumo que lutarei com a maioria das presas / alienígenas, desde que não sejam inteligentes. Isso não vai lhe dar alguns lustres também?
Timtech

Agora, olhando para o meu comentário, acho que realmente não era o que eu queria dizer. Eu queria dizer que a wantToFightcondição não estará dando truequando os inimigos começarem a melhorar com os níveis; você rapidamente se tornará um forte pacifista.
Kyle Kanos

@KyleKanos Oh, entendi. Eu mudei um pouco.
Timtech

6

Morphling

Não conseguia pensar em outro nome, esse cara distribui aleatoriamente 10 pontos em suas habilidades. Quase se move como Okinawa Life (thx pelo seu esforço) e só quer lutar se a força dele for maior que a do inimigo.

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

}

Ahh, você sabe, você está certo. Os colchetes estão me matando esse desafio (tive que editar o meu algumas vezes por causa disso). Eu vejo agora, e está correto. Obrigado por apontar isso!
user3334871

@ user3334871 embora i testado com a sua sugestão e meu Morphling apenas sobreviveram melhor: D
Sikorski

@Sikorski Bem, feliz por poder ajudar, sem saber por que isso se sairia melhor, haha.
precisa saber é o seguinte

@Sikorski Acho que isso significa apenas que ficar parado é geralmente mais seguro do que fazer a jogada menos perigosa se todas as jogadas forem perigosas.
Martin Ender

Ahh, a estratégia "Deer in the Headlights", eu gosto.
precisa saber é o seguinte

6

Bender "flexão" Rodriguez

Eu era bastante liberal com comentários de código. Você pode lê-los em contexto para ver o que está acontecendo, mas também adicionarei alguns trechos abaixo.

Sumário

Este alienígena opera com o princípio de que matar seres humanos insignificantes é fácil e aumenta a sua força percebida, o que intimidará outros alienígenas a se desviar.

Baleias e águias também são dobráveis. =)

Movimento

Mova-se para oeste ou sul, a menos que tenha encontrado algo interessante para atacar:

  • Para as presas cujo movimento é conhecido, adicionamos sua conveniência ao quadrado em que elas serão no próximo turno.
  • Para aqueles que não o fazemos, dividimos sua conveniência igualmente entre os quadrados que eles podem mover para o próximo turno.
    • Os estrangeiros recebem um bônus negativo ao quadrado existente por causa das cascas de banana.

Se você não encontrar nada de interessante nas proximidades, tenha uma idéia de se o sul, oeste ou sudoeste é uma opção mais promissora.

Escolher uma ou duas direções predominantes diminui a chance de qualquer Bender encontrar qualquer um de seus compatriotas, e escolher um contador de direção para sua presa principal deve ajudá-lo a matar todos os humanos mais rapidamente.

Provavelmente eu poderia ajustar os números na matriz de desejabilidade com o algoritmo genético de James_pic para obter resultados ainda melhores, mas não sei como fazer isso.

Agressividade

Bender mira principalmente a presa e é bastante conservador com a dele wantToFight. Qualquer pessoa acima de Força 4 é evitada, a menos que você pense que está lidando com um humano inteligente. A humanidade inteligente é demonstrada por ter mais Defesa e Visão do que um alienígena provavelmente terá. É ajustado ao longo de uma instância pelas próprias estatísticas de habilidade de Bender, para explicar que alienígenas matam tartarugas e águias.

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

Percebi que havia um erro de lógica de loop em que a variável incrementada não era a que estava sendo comparada diretamente e evita recursões infinitas por meio do empacotamento de estouro inteiro. Espero que você esteja bem comigo atualizando sua resposta. (estava fazendo com que a simulação parasse de tempos em tempos)
Moogie

@Moogie Heh. Então, eu só estava indo bem por acidente? Obrigado por capturar isso.
Michael Michael

Examinei a coisa toda e consertei mais alguns problemas.
Michael

5

Guerreiro

Este é um alienígena de mente muito simples que só quer lutar. Ele não se importa com seus inimigos nem com o ambiente.

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

Agora você tem alguém para testar seu próprio alienígena.


4

Covarde

Eu basicamente roubei o padrão de movimento da Águia para evitar o perigo e a defesa empilhada no caso de ser atacado.

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

Corrija-me se eu estiver errado, mas como toda habilidade tem um ponto base 1, colocar vision=1deve ser suficiente?
justhalf

@ justhalf: Minha breve leitura do código parecia sugerir que sobrescrevemos setAbilityPointsos valores de 1, mas, olhando mais profundamente, acho que você está correto. Vou deixar como está, porque uma visão maior me permite ver mais longe e evitar o perigo, mas obrigado pela captura.
Kyle Kanos

Além disso, Math.round sempre arredonda-se em 0,5, de modo a obter uma visão extra se você tem um número ímpar
Andreas

@Manu: Troquei meus valores de visão e defesa para melhorar a fuga.
Kyle Kanos

4

Fleer

PÂNICO

APOCALIPSE

RUUUUUUUUUUN

AAAAAAAAAAAAAAAAAAAAAA


Evita batalhas sempre que possível.

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

Você deve dar a este um nome diferente ... e dar algum crédito para a resposta que você copiou: codegolf.stackexchange.com/a/32787/9498
Justin

2
@Quincunx Isso é uma coincidência, não viu que um ...
stommestack

Desculpe, acabei de perceber que ambas as respostas são copiadas da Eagle. Você não copiou a outra resposta, apenas não li com atenção suficiente. No entanto, um nome diferente seria apropriado.
Justin

1
Mudou o nome!
Stommestack

2
Deve ser nomeado Rincewind.
Magus

4

Predicoward (ronronar)

Uma raça de predicados que viveram (até agora) com medo e se afastam de problemas. Devido ao seu estilo de vida, eles não desenvolveram instintos de luta, mas sua percepção é excepcional.

Sua espécie é odiada por seus colegas predicados.

EDIT: Mudou a distância de Manhattan para a distância ponderada

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
Parece bom! Mas, por favor, retire suas declarações impressas, elas me confundirão quando eu dirijo o concurso.
precisa saber é o seguinte

Ah, eu deixei as declarações impressas? Eu vou mudar depois. Haha Além disso, isso ainda não está finalizado. No momento, Predicoward é péssimo. Seus algoritmos de evasão alienígena serão aprimorados em breve. :) EDIT: Obrigado por quem removeu as declarações de impressão. : D (Jop?)
Mark Gabriel

EDIT: Predicowards agora são muito melhores em fugir do que os incômodos predicowards não competitivos que foram ontem. > :)
Mark Gabriel

Curiosidades: Este é o meu Predicat favorito <3
Mark Gabriel

4

PredicatEyes (miau)

Uma raça de predicados que têm visão mais nítida do que suas contrapartes, o que lhe permite curar bem seus inimigos.

EDIT: Novas prioridades de destino

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

Crop Circle Alien

Círculos no sentido horário indefinidamente, e nunca quer lutar, ele está feliz fazendo círculos na colheita. No entanto, se você realmente quer lutar, ele vai bater em você.

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
Isso seria mais limpo se você repetisse o Move.
Não que Charles seja o

4
Por que não mudar toda getI()a ie simplesmente remover getI()? Você também pode mudar setI(int i)para this.i = i % 8;, e desde que você só usá-lo naquele lugar, basta alterar cada chamada para setI(getI() + 1)ai = (i + 1) % 8;
Justin

3

CleverAlien

O alienígena inteligente depende apenas de sua inteligência. Ele caminha aleatoriamente e decide lutar aleatoriamente. Ele espera ser capaz de enganar seus inimigos com sorte. (perdoe-me se eu tiver algum erro de sintaxe, eu não sou um cara de 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? Por que não (tmp == 1) == true ? true : false? ;) (Dica: é o mesmo que apenas tmp == 1 ).
Martin Ender

3

Vampiro

Como outros já disseram, estou usando o movimento da Águia até certo ponto. Em vez de tentar fazer um alienígena vencedor (Minhas melhores idéias já foram tiradas D :), decidi fazer um alienígena com algum personagem! Meu alienígena é uma arma contratada, alheia à guerra alienígena, e está apenas neste planeta para caçar o humano imundo que pagou sua dívida com o bastão de morte. Meu alienígena procurará o humano pelo planeta e continuará a seguir o humano sem matá-lo. Uma vez que um alienígena é visto perto dele, ele tentará matar rapidamente o humano e enfrentar esse novo inimigo com "sorte do lado" da tarefa concluída.

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

O código está centrado na idéia de que eu devo correr em direção ao humano. Depois de vencê-lo, volto para o sudoeste, onde procurarei a tartaruga.

EDIT: Ah, e sobre a coisa da tartaruga ... meu alienígena não gosta deles, então é totalmente canônico para vocês.


Acabei de perceber que também posso correr em direção à tartaruga. Quem não ama high dodge ladinos?
precisa saber é o seguinte

2
está usando int diretamente como booleano no bloco if parte do Java 8? porque ele não é compilado na minha máquina (Java 7). Dica: humanPresent
Sikorski

Heck, se eu sei, minha experiência em Java se limitou principalmente a scripts e aulas de nível universitário. Eu apenas farei as comparações, para que tudo fique pêssego. Obrigado pela atenção!
user3334871

Além disso, @Sikorski, você criou sua própria função main ou init para executar seus testes? Ou isso pode ser feito apenas através do código fornecido? Eu juro, tem sido assim por muito tempo desde que eu codificado em um ambiente Java verdade, que eu esqueci as regras para a execução de código Java :(
user3334871

não basta baixar o código que o OP forneceu no link do github, adicionar outras classes e iniciar o teste. Oh, você terá que adicionar entradas para cada classe alienígena na classe Planet.
Sikorski

3

Crash pousou e apenas tentando sobreviver. Sobrevive principalmente por sua agilidade e inteligência e conta todas as cicatrizes, considerando com cuidado se vale a pena começar uma briga ou não. O sobrevivente começa apenas caçando e tentando evitar todos os outros alienígenas com suas grandes armas, mas à medida que fica mais ousado, pode começar a persegui-los. Quando realmente começa, não se importa mais com quem está enfrentando.

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
Tenho certeza de que for(int ability in enemyAbilities){é um erro de sintaxe - tentarfor(int ability : enemyAbilities){
Joshua

3

FunkyBob

A primeira prioridade é a sobrevivência, caso contrário, tentará encontrar algumas presas. Avalia a área visível para encontrar a direção geral com menos ameaças ou mais presas. Parece ter uma taxa de sobrevivência de 85 a 90% durante o meu teste.

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

Apenas para brincadeiras, aqui está outra entrada com uma abordagem ligeiramente diferente. Este está focado apenas em evitar brigas. Esta não é realmente uma estratégia viável devido a estar cercada por inimigos nas primeiras rodadas. 40% dos quadrados estão ocupados no primeiro turno, então, em média, você será imediatamente adjacente a 3-4 inimigos. Porém, ao aumentar os quadrados vazios iniciais para 12,5 vezes a espécie, em vez de 2,5 vezes a espécie, obtém uma taxa de sobrevivência média de 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% é imenso. Até meus Predicowards obtêm apenas cerca de 65% de taxa de sobrevivência em média. Haha Edit: Meus Predicowards têm a mesma filosofia do FunkyJack - apenas fique longe. Eu tenho 10 visões e 0 estatísticas de luta.
Mark Gabriel

3

LazyBee

Comecei a tentar fazer uma aula de abelha inteligente, que usava movimentos de padrões e raciocínio dedutivo, mas depois fiquei com sono, então o renomeei LazyBee e a encerrei. Na verdade, ele parece ter um desempenho muito bom nos meus testes (média de ~ 1645 com alienígenas no 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
Excelente trabalho! Estou muito surpreso por você ter marcado tão bem com uma direção codificada.
Michael

@ Michael, você não tem idéia de como fiquei agradavelmente surpreso quando descobri! Eu tinha me esforçado muito no código de movimento, depois o executei contra o HOLD como uma espécie de grupo de controle. então percebi que o grupo de controle estava chutando a bunda, então comecei a experimentar com diferentes tons de preguiça!
thefistopher

3

Cara novo

Tenta engajar alvos "fáceis" no início da agricultura. Caso contrário, basta mover-se esporadicamente.

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

Essa return true;linha flutuante parece supérflua devido à elsecondição.
Kyle Kanos

@KyleKanos True. Problema resolvido.
FreeAsInBeer

seu teste isHuman () não parece muito certo. Não encontrará aliens que nivelaram também?
Não que Charles,

@ Charles Você está certo. É difícil (impossível?) Descobrir se o inimigo é um humano ou um alienígena nivelado devido à maneira como o mecânico da 'esperteza' funciona, e ao fato de que não podemos determinar a esperteza durante uma consulta de luta. Mesmo usando alguma matemática básica, é muito provável que um palpite sobre se é humano ou não seja impreciso. Acho que vou mudá-lo para fugir de humanos.
FreeAsInBeer

Seus isSpecie-testes olhar fresco, mas ainda luta presa e esses testes em breve falhar ...
CommonGuy

2

Guarda

Empilhe a vida, a força e a defesa de buffs e fique parado. Somente ataque se o oponente parecer agressivo (definido como strengthmaior que 2):

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

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

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

2

Bully Alien

O valentão Alien vai andar por aí ignorando os inimigos até encontrar alguém fraco para mexer.

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
Aww, o alienígena valentão só quer ser amigo.
user3334871

3
@ user3334871 Mais como: "o alien bully só quer ter um erro de sintaxe"
Justin

O wantToFight não deveria olhar para as habilidades do inimigo?
Ingo Bürk

@ IngoBürk Ele já fez pelo tempo que você comentou
William Barbosa

Deve ter me levado muito tempo para percorrer a discussão então. :)
Ingo Bürk

2

BlindBully

Não se importa com quem ou o que está à sua volta, apenas tenta decidir se o alienígena que está enfrentando agora é mais forte ou mais fraco que ele próprio e ataca os mais fracos.

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

Então este é o melhor? haha
justhalf
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.