Jeu de survie - AlienWar


96

AlienWar

Ce jeu se déroule sur une planète très peuplée où les extraterrestres sont la race supérieure. Votre tâche est de créer votre propre extraterrestre et de battre tous les autres.

Le tableau

C'est un tableau en 2 dimensions.
La longueur d'un côté du tableau est Math.ceil(sqrt(species * 100 * 2.5))= ~ 40% du tableau utilisé. Le tableau est une planète, donc si vous sortez de la carte à l'ouest, vous revenez à l'est. Si vous vous promenez dans le nord, vous vous retrouverez dans le sud.

Les capacités

Chaque espèce sur la planète a des capacités. Les voici:

Nom         Bénéfice Durée de 
vie HP = LifeLVL * 5 (réduit à chaque frappe, 0 = mort), HP de base = 10
force Vos coups infligent des dégâts aléatoires de 1 à 3
defense choisit al inter ent dans la plage [0 a (50 / defenseLVL + 1)], si int == 0 alors esquive la prochaine attaque
vision Vous donne une visionLVL / 2 champs autour de vous vision
ingéniosité Brouille (augmente) chaque capacité de manière aléatoire dans la plage [0 à ingéniositéLVL / 2] lors de l'envoi à d'autres extraterrestres.

Le jeu

  • Il y aura 100 instances de chaque soumission.
  • Après instanciation, chaque étranger peut définir 10 points de capacité au total. Vous pouvez définir différents points pour chaque instance.
  • Si vous définissez plus de 10 points, l'instance meurt.
  • Un jeu consiste en 1000 tours. Chaque tour:
    • Chaque étranger doit retourner un mouvement via move(char[] fields). Cela inclut Move.STAY.
    • Si plusieurs étrangers se trouvent sur un champ, 2 seront choisis au hasard:
      • Si les deux sont d’accord sur la paix (retourne faux wantToFight), ils resteront là où ils sont, sinon ils se battront.
      • Cela boucle jusqu’à ce qu’un seul étranger reste sur un champ ou que tous s’accordent pour la paix.
  • Si un extraterrestre tue quelque chose, il obtient 1/5 de chacune des capacités de son ennemi . Les gagnants HP seront remplis avec 2 * ennemisLifeLVL .

  • Le gagnant est celui qui a le plus de capacités (somme des capacités des extraterrestres vivants).

Combats

Les deux extraterrestres vont se frapper "en même temps", cela signifie que si vous tuez l'autre extraterrestre, il peut toujours vous frapper une fois.

Esquive: Avant de vous faire toucher, le jeu déterminera si vous pouvez esquiver l'attaque en utilisant rand.nextInt(50 / defenseLvl + 1) == 0. defenseLvl ne sera jamais supérieur à 50 lors du calcul de vos compétences d'esquive (le risque d'esquive maximum est donc de 50%).

Frapper: Si vous n'esquivez pas l'attaque, vous serez touché et votre HP sera réduit de rand.nextInt(enemy.getStrengthLvl()) + 1.

Un combat prend fin lorsque l'un ou l'autre ou les deux étrangers impliqués sont morts. Le gagnant, s'il en existe un, reçoit la récompense.

Regles du jeu

  • Le niveau de base pour chaque capacité (sans donner de points de capacité) est égal à 1 (HP de base est de 10).
  • Les valeurs envoyées lorsqu'on demande de se battre sont la vie (pas HP!), La force, la défense et la vision .
  • L'intelligence n'est PAS envoyée lorsqu'on lui demande de se battre.
  • Tous les nombres flottants seront arrondis au nombre entier le plus proche lors de leur utilisation / envoi, mais stockés et augmentés sous forme de nombres flottants.
  • Dodge-chance maximum est de 50%. Sinon, les combats ne peuvent jamais se terminer.

La proie

Il y a 5 espèces qui sont déjà sur le terrain. Comme ils sont une proie, ils choisissent de ne pas se battre quand on le leur demande.

Baleine: 10 séjours de la vie   
Vache: force 10 Mouvement aléatoire
Tortue: niveau 10, défense sud ouest
Eagle: lvl 10 vision Examine les champs, tente d'éviter le danger      
Humain: niveau 10 intelligence nord est

Ils seront représentés avec leur première lettre (par exemple Wpour la baleine) sur la carte (Aliens avec A, champs vides avec un espace ' ').

Règles supplémentaires

  • La réflexion est interdite.
  • Interagir (instancer, etc.) avec d'autres extraterrestres est interdit.
  • Écrire / lire des ressources externes telles que des fichiers ou des bases de données est également interdit.
  • Seules les soumissions Java (version 1.8) sont autorisées (Java est assez simple et vous n'avez pas besoin d'être un expert pour ce jeu).
  • Toutes les soumissions doivent s'étendre à la classe alien et seront placées dans le paquet alien.
  • J'accepterai le meilleur extraterrestre le 19 juillet. Tous les étrangers soumis avant 12h00 ce jour-là seront testés.
  • Maximum de 3 soumissions par utilisateur car il y a déjà beaucoup d'extraterrestres.

Exemple d'alien

package alien;

import planet.Move;

public class YourUniqueNameHere extends Alien {

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

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

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

}

Programme de contrôle

Le code source du programme de contrôle peut être trouvé ici . Maintenant mis à jour avec tous les extraterrestres inclus dans la dernière exécution.

Score final (20.07.2014, moyenne de 10 jeux)

alien.PredicatClaw 1635.4
alien.LazyBee 1618.8
alien.CartographerLongVisionAlien 1584.6
alien.ChooseYourBattles 1571.2
alien.Bender 1524.5
alien.HerjanAlien 1507.5
alien.FunkyBob 1473.1
alien.SecretWeapon2 1467.9
alien.PredicatEyes 1457.1
alien.CorporateAlien 1435.9
alien.GentleGiant 1422.4
alien.CropCircleAlien 1321.2
alien.VanPelt 1312.7
alien.NewGuy 1270.4
alien.BananaPeel 1162.6
alien.Rock 1159.2
alien.BullyAlien 1106.3
étranger.Geoffrey 778.3
alien.SecretWeapon 754.9
alien.SecretWeapon3 752.9
alien.FunkyJack 550.3
alien.Stone 369.4
Alien.Assassin 277.8
alien.Predicoward 170.1
proie.Cow 155.2
alien.Morphling 105.3
alien.Eli 99,6
Alien.Warrior 69.7
alien.Hunter 56.3
alien.Manager 37.6
alien.OkinawaLife 14.2
proie.Baleine 10.5
alien.Gamer 4.5
alien.Randomite 0
alien.Guard 0
proie.Eagle 0
alien.Rogue 0
alien.WeakestLink 0
alien.Fleer 0   
alien.Survivor 0
alien.Sped 0
alien.Junkie 0
alien.Coward 0
alien.CleverAlien 0
proie.humain 0
alien.BlindBully 0
proie.Turtle 0
alien.AimlessWanderer 0

14
Trois votes négatifs, quoi de neuf? Et je ne vois pas un seul commentaire négatif. Les gens passifs sont-ils agressivement agacés par le fait que cela se limite à Java?
Martin Ender

6
@ m.buettner Mon vote vers le bas est pour la limitation à la divinité qu'est Java (cependant, s'il était limité au langage le plus sympathique jamais créé, je le voterais quand même pour le limiter à 1 langage). Je n’ai pas compris l’intérêt d’ajouter un commentaire car il était évident de savoir à quoi serviraient les votes négatifs.
Gareth

6
Hmmm, j'ai des sentiments mitigés ici
M. Alien

5
@ user3334871 Je ne pense pas que changer les règles après 17 réponses soit (et potentiellement une douzaine de personnes travaillant sur des soumissions) est une bonne idée. Puisque seuls quelques-uns d’entre nous sont (le cas échéant) des concepteurs de jeux professionnels, pratiquement tous les KotH de leur propre chef peuvent avoir des problèmes d’équilibre - mais si explorer l’espace des stratégies possibles est toujours amusant (ce qui est apparemment le cas, à en juger par les réponses, upvotes et étoiles), je ne pense pas que ce soit vraiment un problème.
Martin Ender

5
@Manu Pour ceux qui ont une inclination mathématique, la description de la façon dont le conseil enveloppe est quelque peu trompeuse. Vous dites que c'est une planète et qu'elle enveloppe l'est / l'ouest. Il n'y a rien qui indique vraiment que cela enveloppe le nord / sud, aussi. En fait, s’il le fait, ce n’est techniquement plus une sphère, mais un tore: kotaku.com/classic-jrpg-worlds-are-actually-donuts-1239882216 . Vous pouvez également constater qu'en remarquant que lorsque vous vous promenez "en haut" d'une carte du monde (le pôle nord), vous n'apparaissez pas en bas (le pôle sud). Par conséquent, la suggestion de Michael est définitivement valable, je pense.
Martin Ender

Réponses:


11

PredicatClaw (rawr)

Cette alienne féline va t'avaler toute entière (d'accord, peut-être qu'elle te mâchera un peu en premier) ... si tu sembles faible d'après ses algorithmes de prédiction.

Une race de prédicats qui ont des griffes et des crocs plus féroces que leurs homologues.

EDIT: Nouvelles priorités cibles

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
Zut! Ces prédicats sont féroces! Je remarque que nous avons tous deux opté pour plus ou moins le même wantToFightalgorithme.
James_pic

@James_pic, je vois que les grands esprits se rencontrent. : D
Mark Gabriel

27

Directeur

Voici un gestionnaire. Naturellement, l'intelligence est nulle et il s'efforce toujours d'aller où le soleil ne brille pas. Et, bien sûr, il ne combattra que les faibles et saura éviter les ennuis:

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, si ce n'est que pour l'intro. : P
apnorton

6
Chaque fois que je lis ce commentaire ("juste pour être sûr"), je dois rire :-D
Matthias

C'est marrant, je viens de lire ceci: blog.codinghorror.com/i-shall-call-it-somethingmanager
11684

@ 11684 Tout bon développeur le sait, bien sûr, mais dans mon cas, je parle en réalité d'un manager;)
Ingo Bürk

18

CartographieLongVisionAlien

Cet Alien est une variante performante et consistante de l'une de mes tentatives pour produire un extraterrestre au potentiel gagnant.

Il a une vision initiale de 5 x 5 qu'il utilise pour créer une carte interne de la zone environnante lui donnant une capacité d'évitement supérieure de l'ennemi.

Lors de mes tests de 100 rounds en moyenne, il devance tous les autres extraterrestres. (09/07/2014)

GIF MIS À JOUR montrant l'effet de champ répulsif / attractif

J'ai modifié le code du jeu pour produire des GIF animés de la simulation. Vous pouvez voir une telle simulation ici

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

 }

Mise à jour pour ajouter les prévisions futures des proies et faire en sorte que les baleines soient susceptibles d'être attaquées
Moogie

4
Yay! Enfin, un extraterrestre gagne qui ne compte pas seulement sur la force et la vie, mais aussi sur la vision :)
CommonGuy

3
Il était très difficile de trouver un extraterrestre qui soit un interprète régulier! Les autres principaux entrants suivent généralement les mêmes idées: évitez les extraterrestres, attaquez les proies et ne lancez que des combats que vous êtes presque certain de gagner. Cet étranger suit les mêmes idées, mais avec une meilleure évitement des extraterrestres. Cela lui donne le moindre avantage car il est plus "coûteux" d’acquérir plus de capacités si vous perdez un combat.
Moogie

J'ai essayé d'autres idées plus exotiques, mais il n'y a tout simplement pas assez d'informations exposées. c'est-à-dire la taille de la carte, le nombre d'étrangers, etc.
Moogie

Bon travail! Moi aussi, j'étais un peu frustré par le manque d'informations - extraire des informations supplémentaires du passé est créatif.
Benny

15

Choisis tes combats

Cet extraterrestre s'enfuit des autres extraterrestres, mais se dirige vers la proie (tant que cela ne le mènera pas vers des extraterrestres).

J'ai utilisé un algorithme génétique pour m'aider à choisir les valeurs de départ. Les résultats suggèrent que nous devrions compter sur la force et la vie pour passer à travers les premières matrices. La vision est utile plus tard, mais nous pouvons la récupérer parmi les ennemis vaincus.

Nous ne combattons que des batailles que nous pensons pouvoir gagner confortablement. Nous estimons le nombre de mouvements nécessaires pour tuer notre extraterrestre, le nombre de mouvements nécessaires pour tuer notre ennemi, et nous ne participerons à la bataille que si nous sommes "deux fois plus difficiles" que notre adversaire.

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

Si vous souhaitez exécuter votre propre algorithme génétique / programme de sélection, j'ai une copie du programme de contrôle fourchue à cet effet .


Comment cela évite-t-il la vérification de la checkAbilitesOkméthode?
FreeAsInBeer

checkAbilitiesOkvérifie que les flottants du tableau totalisent 10.0. Cependant, les valeurs de float sont arrondies aux entiers dans la logique de jeu et Java est arrondi à 0,5.
James_pic

@justhalf cela fixe toujours 10 points, ils sont juste distribués intelligemment.
CommonGuy

1
Je devrais dire que ce n'était pas mon idée à l'origine - je l'ai empruntée à PredicatClaw
James_pic le

1
Très agréable. Vos constantes statistiques sont probablement meilleures que les miennes et votre wantToFight est définitivement plus intelligent, j'étais juste paresseux. :)
Benny

12

Junkie

Cet étranger est accro à quelque chose . Il commence la guerre sur une jolie solution.

Pendant que sa dose va fort ( fix > 3), il est agréablement content de rester assis dans sa stupeur et est prêt à tout.

Cependant, une fois que son correctif commence à s'estomper ( fix <= 3), il commence à trébucher dans aucune direction perceptible pour essayer de comprendre ce qui s'est passé. Si on lui demande de se battre, il devient prudent et ne combat que s'il pense pouvoir gagner.

Une fois que son problème est épuisé, étant le toxicomane, il doit recommencer le cercle vicieux.

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

Je suis presque sûr qu'il est sécuritaire de le retirer en && fix > 0raison de la redondance.
Timtech

10

Pelure de banane

N'essaie que de faire trébucher les gens qui ont besoin d'un petit coup. Le vaincre ne vous rendra pas en meilleure santé.

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

Il est également important de noter que [0] est la vie plutôt que la santé alors 100 serait de 510 CV (ou moins, en fonction des dégâts déjà subis) mais je ne sais pas si un extraterrestre atteindrait un niveau aussi élevé ..
Gigala

@Gigala Bien pensé, je l'ai un peu modifié.
Timtech

9

Van Pelt

Le chasseur de Jumanji. Il chasse quand il n'est pas blessé, évite quand il est et est un bon juge de ce qu'il peut tuer. Les peaux de banane continuaient de le faire trébucher, mais lui apprenaient de nouvelles astuces.

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

}

J'ai appris à éviter les peaux de banane, hein? : P
Timtech

8

Vie d'Okinawa

Pas étonnant que je sois le dernier à rester debout.

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

chasseur

Je viens aussi de voler un peu le mouvement de l'aigle, sauf que maintenant il veut aller vers tout sauf les extraterrestres. Essaie de chasser et de cultiver le plus de proies possible et ne se bat que lorsqu'il semble avoir de bonnes chances de gagner.

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

C'est plus de 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
    }
}

Oui, c'est une tentative flagrante de tricherie, mais elle enfreint les règles. Si les getters planet.Specieétaient rendus définitifs, cette échappatoire serait supprimée.


4
Oh non! Je savais que j'avais oublié quelque chose ... Je vais fermer la faille et +1;)
CommonGuy

Je suis un peu déçu que cette réponse ait eu plus de votes positifs que mon autre entrée, plus ancienne, qui gagne actuellement.
James_pic

7

Roche

Je pense que cela n’attaque que les personnes faibles et "intelligentes".

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
Je ne sais pas si Rock durera bien une fois que ses ennemis commenceront à se procurer des améliorations en raison de leurs victoires. Ça a l'air bien cependant.
Kyle Kanos

@KyleKanos je comprends; Cependant, je suppose que je combattrai la plupart des proies / extraterrestres, tant qu'ils ne sont pas intelligents. Est-ce que cela ne va pas lui donner des buffs aussi?
Timtech

En repensant à mon commentaire, je pense que ce n’était pas du tout ce que je voulais dire. Je voulais dire que la wantToFightcondition ne sera pas donnée truelorsque les ennemis commenceront à améliorer les niveaux; vous allez rapidement vous tourner vers un pacifiste fort.
Kyle Kanos

@KyleKanos Oh, je comprends. Je l'ai un peu changé.
Timtech

6

Morphling

Impossible de penser à un autre nom, ce gars distribue au hasard 10 points à ses capacités. Il se déplace presque comme Okinawa Life (merci de votre effort) et ne veut se battre que si sa force est supérieure à celle de l'ennemi.

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, vous savez, vous avez raison. La fermeture des crochets m'a tué ce défi (dû éditer le mien une ou deux fois à cause de cela). Je le vois maintenant, et c'est correct. Merci d'avoir fait remarquer cela!
user3334871

@ user3334871 si j'ai testé avec votre suggestion et mon morphling a mieux survécu: D
Sikorski

@Sikorski Eh bien, je suis heureux d'avoir pu aider, je ne sais pas pourquoi cela irait mieux, haha.
user3334871

@Sikorski Je suppose que cela signifie simplement que rester sur place est souvent plus sûr que de faire le moins dangereux des mouvements si tous les mouvements sont dangereux.
Martin Ender

Ahh, la stratégie "Deer in the Headlights", j'aime bien.
user3334871

6

Bender "Bending" Rodriguez

J'étais assez libéral avec des commentaires de code. Vous pouvez les lire en contexte pour voir ce qui se passe, mais je vais aussi ajouter quelques extraits ci-dessous.

Sommaire

Cet extraterrestre fonctionne sur le principe qu'il est facile de tuer des Humains chétifs et gonfle votre force perçue, ce qui intimidera d'autres extraterrestres pour qu'ils se dirigent clairement.

Les baleines et les aigles sont également flexibles. =)

Mouvement

Déplacez-vous vers l'ouest ou le sud à moins que vous n'ayez trouvé quelque chose d'intéressant à attaquer:

  • Pour les proies dont le mouvement est connu, nous ajoutons leur désirabilité au carré où elles se tourneront.
  • Pour ceux que nous ne connaissons pas, nous divisons leur opportunité en parts égales entre les carrés sur lesquels ils peuvent se déplacer au tour suivant.
    • Les extraterrestres reçoivent un bonus négatif à leur carré actuel à cause des pelures de banane.

Si vous ne trouvez rien d’intéressant à proximité, déterminez si le sud, l’ouest ou le sud-ouest est une option plus prometteuse.

Choisir une ou deux directions prédominantes diminue les chances qu'un certain Bender rencontre l'un de ses compatriotes, et choisir une direction opposée à sa principale proie devrait l'aider à tuer tous les humains plus rapidement.

Je pourrais probablement modifier les chiffres de la matrice de désirabilité avec l'algorithme génétique de James_pic pour obtenir de meilleurs résultats, mais je ne sais pas comment faire.

Agressivité

Bender cible principalement ses proies et est assez conservateur avec les siennes wantToFight. Toute personne au-dessus de la force 4 est évitée à moins que vous ne pensiez avoir affaire à un humain intelligent. L’humanité intelligente est démontrée par plus de défense et de vision qu’un étranger est susceptible d’avoir. Au fil d'une instance, Bender a ajusté ses statistiques de capacités pour tenir compte du fait que des extraterrestres ont tué des tortues et des aigles.

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

J'ai remarqué qu'il y avait une erreur de logique de boucle dans laquelle la variable incrémentée n'était pas ce qui était comparé directement et n'évitait que la récursion infinie au moyen d'un retour à la ligne supérieur. J'espère que vous allez bien avec moi pour mettre à jour votre réponse. (la simulation
s'interrompait

@ Moogie Heh. Donc, je me débrouillais bien seulement par accident? Merci d'avoir attrapé ça.
Michael

J'ai revu le tout et résolu quelques problèmes supplémentaires.
Michael

5

guerrier

Ceci est un extraterrestre très simple d'esprit qui veut juste se battre. Il ne se soucie pas de ses ennemis ni de son environnement.

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

Vous avez maintenant quelqu'un contre lequel tester votre propre extraterrestre.


4

lâche

En gros, j'ai volé le schéma de mouvement de l'Aigle pour éviter les dangers et une défense empilée au cas où je serais attaqué.

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

Corrigez-moi si je me trompe, mais comme chaque capacité a un point de base de 1, le lancer vision=1devrait alors suffire.
moitié

@justhalf: Ma brève lecture du code semble suggérer que setAbilityPointsles valeurs de 1 ont été écrasées , mais en le regardant plus en profondeur, je pense que vous avez raison. Je vais le laisser tel quel car une vision plus large me permet de voir plus loin et d'éviter le danger, mais merci pour le piège.
Kyle Kanos

De plus, math.round arrondit toujours à 0,5, vous aurez donc une vision supplémentaire si vous avez un nombre impair
Andreas

@Manu: J'ai échangé mes valeurs de vision et de défense pour améliorer la fuite.
Kyle Kanos

4

Regard de mépris

PANIQUE

APOCALYPSE

RUUUUUUUUUUN

AAAAAAAAAAAAAAAAAAAAAAAAA


Évite les batailles dans la mesure du possible.

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

Vous devriez lui donner un nom différent ... et attribuer un mérite à la réponse que vous avez copiée: codegolf.stackexchange.com/a/32787/9498
Justin

2
@Quincunx C'est une coïncidence, je n'ai pas vu celui-là ...
stommestack

Désolé, je viens de me rendre compte que les deux réponses proviennent d'Eagle. Vous n'avez pas copié l'autre réponse, je n'ai pas lu assez attentivement. Cependant, un nom différent serait approprié.
Justin

1
Changé le nom!
Stommestack

2
Devrait être nommé Rincevent.
Magus

4

Predicoward (ronronnement)

Une race de prédicats qui ont vécu (jusqu'à présent) dans la peur et sont restés à l'écart des ennuis. En raison de leur style de vie, ils n'ont pas développé d'instinct de combat, mais leur perception est exceptionnelle.

Leur genre est détesté par leurs compagnons prédicats.

EDIT: changé de distance de Manhattan en distance pondérée à la place

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
Cela semble bon! Mais, s'il vous plaît, sortez vos relevés de notes, ils m'embrouilleraient lorsque je lancerais le concours.
CommonGuy

Oh, j'ai laissé les déclarations d'impression? Je les changerai plus tard. Haha. De plus, ce n'est pas encore définitif. En ce moment, Predicoward craint. Ses algorithmes d'évasion extraterrestre seront bientôt améliorés. :) EDIT: Merci pour celui qui a supprimé les déclarations d'impression. : D (Jop?)
Mark Gabriel le

EDIT: Les prédicowards sont maintenant beaucoup plus efficaces pour fuir que les ennuyeux petits prédicowards non compétitifs qu’ils ont été hier. > :)
Mark Gabriel

Anecdote: ceci est mon favori Predicat <3
Mark Gabriel

4

PredicatEyes (miaou)

Une race de prédicats qui ont une vision plus nette que ses homologues, ce qui lui permet de bien vaincre ses ennemis.

EDIT: Nouvelles priorités cibles

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

Cercles indéfiniment dans le sens des aiguilles d'une montre, et ne veut jamais se battre, il est heureux de faire des cercles de culture. Cependant, si vous voulez vraiment vous battre, il vous en mettra plein la gueule.

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
Ce serait plus propre si vous parcouriez Move.
Pas que Charles

4
Pourquoi ne pas changer tout getI()à iet simplement supprimer getI()? Vous pouvez également changer cette setI(int i)option this.i = i % 8;et, comme vous ne l'utilisez que dans un seul endroit, il suffit de changer chaque appel setI(getI() + 1)eni = (i + 1) % 8;
Justin

3

CleverAlien

Cien alien s'appuie uniquement sur son esprit. Il se promène au hasard et décide de se battre au hasard. Il espère pouvoir déjouer ses ennemis avec de la chance. (pardonnez-moi si j'ai des erreurs de syntaxe, je ne suis pas un gars 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? Pourquoi ne pas (tmp == 1) == true ? true : false? ;) (Indice: c'est pareil que juste tmp == 1 .)
Martin Ender

3

Coquin

Comme d'autres l'ont dit, j'utilise le mouvement de l'Aigle dans une certaine mesure. Plutôt que d'essayer de faire un extraterrestre gagnant (mes meilleures idées étaient déjà prises D :), j'ai décidé de faire un extraterrestre avec un caractère! Mon extraterrestre est un pistolet embauché, inconscient de la guerre extraterrestre, et n’est sur cette planète que pour chasser l’homme immonde qui a laissé tomber sa dette. Mon extra-terrestre va chercher l'homme sur la planète et continuera à traquer l'homme sans le tuer. Une fois qu'un étranger est vu près de lui, il essaiera ensuite de tuer rapidement l'humain et d'affronter ce nouvel ennemi avec "de la chance de son côté" grâce à sa tâche accomplie.

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

Le code est centré sur l'idée que je devrais sprinter vers l'humain. Une fois que je l'ai battu, je me suis ensuite dirigé vers le sud-ouest, où je chercherai la tortue.

EDIT: Oh, et à propos de la tortue ... mon extraterrestre ne les aime pas, donc c'est totalement canon, vous les gars.


Je viens juste de réaliser que je peux aussi courir vers la tortue. Qui n'aime pas les coquins Dodge?
user3334871

2
utilise-t-il directement int comme booléen dans if block part of Java 8? car il ne compile pas du tout sur ma machine (Java 7). Astuce: humanPresent
Sikorski le

Heck si je sais, mon expérience de Java a été principalement limitée à des scripts et des classes de niveau collégial. Je vais juste faire les comparaisons, juste pour que tout soit pêche. Merci pour l'information!
user3334871

Aussi, @Sikorski, avez-vous créé votre propre fonction principale ou init pour exécuter vos tests? Ou peut-on le faire uniquement par le code fourni? Je jure, cela fait tellement longtemps que je n'ai pas codé dans un véritable environnement Java, que j'ai oublié les règles pour l'exécution du code Java :(
user3334871.

non, il suffit de télécharger le code que l'OP a donné dans le lien github, d'ajouter d'autres classes et de commencer les tests. Oh, vous devrez ajouter une entrée pour chaque classe étrangère dans la classe Planète.
Sikorski

3

Crash a atterri et essayait juste de survivre. Survivre principalement par son agilité et son intelligence et compte chaque cicatrice, en considérant avec soin si cela vaut la peine de commencer un combat ou non. Le survivant commence juste à chasser et à essayer d'éviter tous ces autres extraterrestres avec leurs grandes armes, mais à mesure qu'il devient plus audacieux, il peut commencer à les poursuivre. Quand cela commencera vraiment, il ne se souciera plus de savoir à qui il fait face.

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
Je suis sûr que for(int ability in enemyAbilities){c'est une erreur de syntaxe - essayezfor(int ability : enemyAbilities){
Joshua

3

FunkyBob

La première priorité est la survie, sinon nous allons essayer de trouver une proie. Évalue la zone visible pour trouver la direction générale avec le moins de menaces ou le plus de proies. Il semble avoir un taux de survie d'environ 85 à 90% au cours de mes tests.

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

Juste pour le plaisir, voici une autre entrée avec une approche légèrement différente. Celui-ci est uniquement axé sur l’évitement des bagarres. Ce n'est pas vraiment une stratégie viable en raison du fait d'être entouré d'ennemis lors des premiers tours. 40% des cases sont occupées au premier tour, donc en moyenne, vous serez immédiatement adjacent à 3-4 ennemis. Toutefois, lorsque les carrés vides initiaux sont augmentés à 12,5 fois l'espèce plutôt que 2,5 fois l'espèce, le taux de survie moyen atteint 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% est immense. Même mes Predicowards n'obtiennent qu'un taux de survie d'environ 65% en moyenne. Haha. Edit: Mes Predicowards ont la même philosophie que FunkyJack - restez à l’écart. J'ai 10 vision cependant et 0 stats de combat.
Mark Gabriel le

3

LazyBee

J'ai commencé à essayer de créer une classe d'abeilles intelligente qui utilisait des mouvements de motifs et un raisonnement déductif, mais je suis devenu somnolent, alors je l'ai renommé LazyBee et je l'ai appelé une nuit. Il semble en fait très bien performer sur mes tests (moyenne de ~ 1645 avec des extraterrestres sur le 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
Excellent travail! Je suis assez étonné que vous marquiez si bien avec une direction codée en dur.
Michael

@ Michael, vous ne savez pas à quel point j'ai été agréablement surpris quand j'ai découvert ça! J'avais beaucoup travaillé sur le code de mouvement, puis je l'avais fait tourner contre HOLD comme une sorte de groupe de contrôle. puis j'ai réalisé que le groupe de contrôle était en train de botter des culs, alors j'ai commencé à expérimenter avec différentes nuances de paresseux!
thefistopher

3

Nouveau gars

Essaie d'engager des cibles "faciles" pour une agriculture précoce. Sinon, déplacez-vous sporadiquement.

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

Cette return true;ligne flottante semble superflue en raison de la elsecondition.
Kyle Kanos

@ KyleKanos True. Problème abordé.
FreeAsInBeer

Votre test isHuman () ne semble pas très correct. Ne trouvera-t-il pas des extraterrestres égalisés aussi?
Pas que Charles

@ Charles Vous avez raison. Il est difficile (impossible?) De savoir si l'ennemi est un humain ou un étranger de niveau en raison de la façon dont fonctionne le mécanisme de "l'intelligence" et du fait que nous ne pouvons pas déterminer l'intelligence lors d'une requête de combat. Même en utilisant quelques notions de base en mathématiques, il est très probable qu'une hypothèse éclairée sur le fait que ce soit ou non un humain sera inexacte. Je suppose que je vais le changer pour qu'il fuie les humains.
FreeAsInBeer

Vos tests isSpecie ont l'air cool, mais même les combats de proies et ces tests échoueront bientôt ...
CommonGuy

2

Garde

Empile la vie, améliore la force et la défense, puis reste sur place. N'attaque que si l'adversaire semble être agressif (défini comme strengthétant supérieur à 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

Bully Alien se promènera en ignorant les ennemis jusqu'à ce qu'il trouve une personne faible avec laquelle jouer.

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, le bully alien veut juste être amis.
user3334871

3
@ user3334871 Plus comme: "le bully alien veut juste avoir une erreur de syntaxe"
Justin

WantToFight ne devrait-il pas examiner les capacités de l'ennemi?
Ingo Bürk

@ IngoBürk Il l'a déjà fait au moment où vous avez commenté
William Barbosa

J'ai dû prendre trop de temps pour faire défiler le fil. :)
Ingo Bürk

2

BlindBully

Peu importe qui ou ce qui l’entoure, essaie simplement de décider si l’étranger auquel il fait face actuellement est plus fort ou plus faible que lui-même, et s’attaque à ceux qui sont plus faibles.

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

Donc c'est le meilleur? haha
mi-temps le
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.