Überlebensspiel - AlienWar


96

AlienWar

Dieses Spiel findet auf einem sehr überfüllten Planeten statt, auf dem Aliens die überlegene Rasse sind. Deine Aufgabe ist es, dein eigenes Alien zu erschaffen und alle anderen zu besiegen.

Die Tafel

Es ist eine zweidimensionale Tafel.
Die Länge einer Seite der Platte beträgt Math.ceil(sqrt(species * 100 * 2.5))= ~ 40% der verwendeten Platte. Das Brett ist ein Planet. Wenn Sie also im Westen aus der Karte herausgehen, kehren Sie im Osten zurück. Wenn Sie im Norden spazieren gehen, befinden Sie sich im Süden.

Fähigkeiten

Jede Spezies auf dem Planeten hat Fähigkeiten. Hier sind sie:

Name         Nutzen 
Leben HP = LebenLVL * 5 (verringert sich mit jedem Treffer, 0 = tot), Basis HP = 10
Stärke Deine Treffer verursachen einen zufälligen int im Bereich [1 to strengthLVL] Schaden
Verteidigung Wähle zufällig int im Bereich [0 bis (50 / defenseLVL + 1)] aus. Wenn int == 0 ist, weiche dem nächsten Angriff aus
vision Gibt Ihnen visionLVL / 2-Felder um Ihre Vision
Klugheit Verwischt (erhöht) jede Fähigkeit zufällig im Bereich [0 bis KlugheitLVL / 2], wenn sie an andere Aliens
 gesendet wird

Das Spiel

  • Jede Einreichung wird 100 Mal eingereicht.
  • Nach dem Instanzen kann jeder Alien insgesamt 10 Fähigkeitspunkte setzen. Sie können für jede Instanz unterschiedliche Punkte festlegen.
  • Wenn Sie mehr als 10 Punkte setzen, stirbt die Instanz.
  • Ein Spiel besteht aus 1000 Runden. Jede Runde:
    • Jeder Alien muss einen Zug über zurückgeben move(char[] fields). Dies beinhaltet Move.STAY.
    • Wenn sich mehrere Aliens auf einem Feld befinden, werden 2 zufällig ausgewählt:
      • Wenn beide sich auf Frieden einigen (falsch eintreffen wantToFight), bleiben sie, wo sie sind, sonst kämpfen sie.
      • Dies wiederholt sich, bis nur ein Alien auf einem Feld bleibt oder sich alle auf Frieden einigen.
  • Wenn ein Außerirdischer etwas tötet, erhält er 1/5 seiner feindlichen Fähigkeiten . Die HP der Gewinner werden mit 2 * enemyLifeLVL aufgefüllt .

  • Gewinner ist derjenige mit den meisten Fähigkeiten (Summe der Fähigkeiten lebender Aliens).

Kämpfe

Beide Aliens treffen sich "zur gleichen Zeit". Wenn Sie den anderen Alien töten, kann er Sie trotzdem einmal treffen.

Ausweichen: Bevor du getroffen wirst, berechnet das Spiel, ob du dem Angriff mit ausweichen kannst rand.nextInt(50 / defenseLvl + 1) == 0. Die Verteidigungsstufe wird bei der Berechnung Ihrer Ausweichfähigkeiten niemals höher als 50 sein (daher beträgt die maximale Ausweichchance 50%).

Treffer: Wenn Sie dem Angriff nicht ausweichen, werden Sie getroffen und Ihre HP werden um reduziert rand.nextInt(enemy.getStrengthLvl()) + 1.

Ein Kampf endet, wenn einer oder beide beteiligten Aliens tot sind. Der Gewinner, falls vorhanden, erhält die Belohnung.

Spielregeln

  • Das Basislevel für jede Fähigkeit (ohne Angabe von Fähigkeitspunkten) ist 1 (Basis-HP sind 10).
  • Die Werte, die gesendet werden, wenn man zum Kampf aufgefordert wird, sind Leben (nicht HP!), Stärke, Verteidigung und Sicht .
  • Cleverness wird NICHT gesendet, wenn Sie zum Kampf aufgefordert werden.
  • Alle Gleitkommazahlen werden beim Verwenden / Senden auf die nächste Ganzzahl gerundet, aber als Gleitkommazahlen gespeichert und erhöht.
  • Die maximale Ausweichchance beträgt 50%. Andernfalls können Kämpfe niemals enden.

Die Beute

Es gibt 5 Arten, die bereits auf dem Feld sind. Da sie Beute sind, ziehen sie es vor, nicht zu kämpfen, wenn sie darum gebeten werden.

Wal: lvl 10 Leben bleibt   
Kuh: Stufe 10 Stärke Zufälliger Zug
Schildkröte: Stufe 10 Verteidigung Südwesten
Adler: Stufe 10 Vision Untersucht Felder, versucht Gefahren zu entgehen      
Mensch: Stufe 10 Cleverness North East

Sie werden mit ihrem Anfangsbuchstaben (dh Wfür Wal) in der Karte dargestellt (Außerirdische mit A, leere Felder mit einem Leerzeichen ' ').

Zusätzliche Regeln

  • Reflexion ist nicht erlaubt.
  • Interaktion (Instanzen usw.) mit anderen Außerirdischen ist nicht gestattet.
  • Das Schreiben / Lesen von externen Ressourcen wie Dateien oder Datenbanken ist ebenfalls nicht zulässig.
  • Nur Java-Einsendungen (Version 1.8) sind zulässig (Java ist recht einfach und Sie müssen kein Experte für dieses Spiel sein).
  • Alle Einsendungen müssen die Alien-Klasse erweitern und werden in das Alien-Paket aufgenommen.
  • Ich werde den besten Außerirdischen am 19. Juli annehmen. Alle bis 12:00 UTC an diesem Tag eingereichten Aliens werden getestet.
  • Maximal 3 Einsendungen pro Benutzer, da es bereits sehr viele Aliens gibt.

Beispiel eines Ausländers

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

}

Steuerungsprogramm

Quellcode für das Steuerungsprogramm finden Sie hier . Jetzt aktualisiert mit allen Aliens, die im letzten Lauf enthalten sind.

Endergebnisse (20.07.2014, Durchschnitt von 10 Spielen)

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
alien.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
Beute.Kuh 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
Beute.Wal 10.5
alien.Gamer 4.5
alien.Randomite 0
alien.Guard 0
prey.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
Beute. Mensch 0
alien.BlindBully 0
Beute. Schildkröte 0
alien.AimlessWanderer 0

14
Drei Abstimmungen, was in aller Welt? Und ich sehe keinen einzigen negativen Kommentar. Sind Leute, die passiv aggressiv sind, genervt, dass dies auf Java beschränkt ist?
Martin Ender

6
@ m.buettner Mein Downvote ist für die Beschränkung auf das Gute, was Java ist (obwohl ich es immer noch ablehnen würde, wenn es auf die schönste Sprache beschränkt wäre, die jemals erstellt wurde). Ich habe keinen Sinn darin gesehen, einen Kommentar hinzuzufügen, da es offensichtlich war, wofür die Ablehnungen sein würden.
Gareth

6
Hmmm, ich habe gemischte Gefühle hier
Mr. Alien

5
@ user3334871 Ich halte es nicht für eine gute Idee, die Regeln zu ändern, nachdem 17 Antworten vorliegen (und möglicherweise ein Dutzend weitere Personen an Einsendungen arbeiten). Da nur die wenigsten von uns professionelle Spieledesigner sind, mag so ziemlich jedes selbstgemachte KotH ein paar ausgleichende Probleme haben - aber wenn das Erforschen des Raums möglicher Strategien immer noch Spaß macht (was es anscheinend ist, wenn man nach Antworten urteilt, Ich glaube nicht, dass es ein großes Problem ist.
Martin Ender

5
@Manu Für den Mathematiker ist die Beschreibung, wie das Board umhüllt, etwas irreführend. Du sagst, es ist ein Planet und er hüllt Ost / West ein. Nichts deutet wirklich darauf hin, dass es auch Nord / Süd umgibt. In der Tat ist es dann technisch gesehen keine Kugel mehr, sondern ein Torus: kotaku.com/classic-jrpg-worlds-are-actually-donuts-1239882216 . Sie können dies auch erkennen, indem Sie feststellen, dass Sie nicht am unteren Rand (dem Südpol) erscheinen, wenn Sie von der Oberseite einer Weltkarte (dem Nordpol) "abgehen". Daher ist Michaels Vorschlag definitiv gültig, denke ich.
Martin Ender

Antworten:


11

PredicatClaw (rawr)

Dieser katzenartige Alien wird dich komplett verschlingen (okay, vielleicht kaut sie dich zuerst ein bisschen) ... wenn du aufgrund ihrer Vorhersagealgorithmen schwach wirkst.

Eine Rasse von Prädikaten mit schärferen Krallen und Zähnen als ihre Gegenstücke.

EDIT: Neue Zielprioritäten

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
Verdammt! Diese Prädikate sind wild! Ich stelle fest, dass wir uns beide auf mehr oder weniger den gleichen wantToFightAlgorithmus geeinigt haben.
James_pic

@ James_pic, ich sehe, dass große Köpfe gleich denken. : D
Mark Gabriel

27

Manager

Hier ist ein Manager. Natürlich ist die Klugheit 0 und er bemüht sich immer dorthin zu gehen, wo die Sonne nicht scheint. Und natürlich wird er nur gegen die Schwachen kämpfen und ist sehr gut darin, Schwierigkeiten auszuweichen:

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, wenn auch nur für das Intro. : P
Apnorton

6
Jedes Mal, wenn ich diesen Kommentar lese ("nur um sicher zu gehen"), muss ich lachen :-D
Matthias


@ 11684 jeder anständige Entwickler weiß das natürlich, aber in meinem Fall meine ich eigentlich einen Manager;)
Ingo Bürk

18

KartografieLongVisionAlien

Dieser Außerirdische ist eine beständige Variante meines Versuchs, einen Außerirdischen zu erschaffen, der das Potenzial hat, zu gewinnen.

Es verfügt über eine anfängliche 5x5-Sicht, mit der es eine interne Karte der Umgebung erstellt, die es überlegenen Möglichkeiten zum Ausweichen des Feindes gibt.

Bei meinen Tests mit durchschnittlich 100 Runden schleicht es sich vor allen anderen Außerirdischen durch. (09.07.2014)

AKTUALISIERTES GIF, das den Repell- / Attract-Feldeffekt anzeigt

Ich habe den Spielcode geändert, um animierte GIFs der Simulation zu erstellen. Sie können eine solche Simulation hier ansehen

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

 }

Aktualisiert, um zukünftige
Beutevorhersagen

4
Yay! Endlich gewinnt ein Außerirdischer, der nicht nur auf Stärke und Leben, sondern auch auf Vision setzt :)
CommonGuy

3
Es war sehr schwierig, einen Außerirdischen zu finden, der konsequent auftrat! Die anderen Top-Teilnehmer verfolgen meistens alle die gleichen Ideen: Vermeiden Sie Aliens, greifen Sie Beute an und leiten Sie nur Kämpfe ein, bei denen Sie fast garantiert gewinnen. Dieser Außerirdische folgt den gleichen Ideen, jedoch mit besserer Vermeidung von Außerirdischen. Dies gibt ihm den geringsten Vorteil, da es "teurer" ist, mehr Fähigkeiten zu erlangen, wenn Sie einen Kampf verlieren.
Moogie

Ich habe andere exotischere Ideen ausprobiert, aber es sind einfach nicht genügend Informationen verfügbar.
Dh

Gut gemacht! Auch ich war ein wenig frustriert über den Mangel an Informationen - das Extrahieren zusätzlicher Informationen aus der Vergangenheit ist kreativ.
Benny

15

Wählen Sie Ihre Schlachten

Dieser Außerirdische rennt vor anderen Außerirdischen davon, aber er rennt auf die Beute zu (solange dies nicht zu Außerirdischen führt).

Ich habe einen genetischen Algorithmus verwendet, um die Startwerte zu bestimmen. Die Ergebnisse legen nahe, dass wir uns auf Kraft und Leben verlassen sollten, um durch frühe Kämpfe zu kommen. Das Sehen ist später nützlich, aber wir können es von besiegten Feinden aufgreifen.

Wir führen nur Schlachten, von denen wir glauben, dass wir sie bequem gewinnen können - wir schätzen, wie viele Schritte erforderlich wären, um unseren Alien zu töten, wie viele, um unseren Feind zu töten unser Gegner.

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

Wenn Sie Ihren eigenen genetischen Algorithmus / Ihr eigenes Züchtungsprogramm ausführen möchten, habe ich eine gegabelte Kopie des Kontrollprogramms für diesen Zweck .


Wie umgeht dies die Überprüfung der checkAbilitesOkMethode?
FreeAsInBeer

checkAbilitiesOkÜberprüft, ob die Gleitkommazahlen im Array 10.0 ergeben. Die Float-Werte werden jedoch in der Spielelogik auf Ints gerundet, und Java rundet 0,5 auf.
James_pic

@justhalf setzt noch 10 Punkte, sie sind nur intelligent verteilt.
CommonGuy

1
Ich sollte sagen, dass es ursprünglich nicht meine Idee war - ich habe es von PredicatClaw ausgeliehen
James_pic

1
Sehr schön. Ihre stat Konstanten sind wahrscheinlich besser als meine und Ihr wantToFight ist definitiv schlauer, ich war nur faul. :)
Benny

12

Junkie

Dieser Außerirdische ist süchtig nach etwas . Er beginnt den Krieg mit einer ziemlich üblen Verlegenheit.

Während sein Fix stark wird ( fix > 3), ist er angenehm zufrieden damit, in seiner Betäubung zu sitzen und ist für alles bereit.

Sobald sein Fix jedoch nachlässt ( fix <= 3), stolpert er in keiner erkennbaren Richtung herum und versucht herauszufinden, was passiert ist. Wenn er zum Kampf aufgefordert wird, wird er vorsichtig und kämpft nur, wenn er glaubt, gewinnen zu können.

Sobald sein Problem behoben ist, muss er als Süchtiger den Teufelskreis neu starten.

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

Ich bin mir ziemlich sicher, dass es && fix > 0aufgrund von Redundanz sicher ist, es zu entfernen .
Timtech

10

Bananenschale

Versucht nur, Leute zu stolpern, die ein bisschen Prügel brauchen. Wenn du es besiegst, wirst du nicht gesünder.

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

Es ist auch wichtig zu bemerken, dass [0] eher Leben als Gesundheit ist, also wären 100 510 PS (oder weniger, abhängig vom bereits erlittenen Schaden), aber ich weiß nicht, ob ein Alien so hoch werden würde.
Gigala

@Gigala Gutes Denken, ich habe es ein bisschen geändert.
Timtech

9

Van Pelt

Der Jäger aus Jumanji. Er jagt, wenn er nicht verletzt ist, vermeidet, wenn er ist, und ist ein anständiger Richter darüber, was er töten kann. Bananenschalen stolperten ihn immer wieder, brachten ihm aber einige neue Tricks bei.

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

}

Gelernt, Bananenschalen zu vermeiden, nicht wahr? : P
Timtech

8

Okinawa Leben

Kein Wunder, dass ich der letzte bin, der noch steht.

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

Jäger

Ich habe auch nur ein bisschen die Bewegung des Adlers gestohlen, außer jetzt will er auf alles außer auf andere Aliens zugehen. Versucht, so viel Beute wie möglich zu jagen und zu züchten, und kämpft nur, wenn es so aussieht, als hätte es eine gute Gewinnchance.

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

Es ist über 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
    }
}

Ja, es ist ein offensichtlicher Versuch zu betrügen, aber es geht durch die Regeln. Wenn die Eroberer planet.Specieendgültig wären, würde sich diese Lücke schließen.


4
Ach nein! Ich wusste, ich habe etwas vergessen ... Ich werde die Lücke schließen und +1;)
CommonGuy

Ich bin etwas enttäuscht darüber, dass diese Antwort mehr positive Stimmen erhalten hat als mein anderer, älterer, derzeit siegreicher Beitrag.
James_pic

7

Fels, Felsen

Ich denke, es greift nur schwache und "kluge" Leute an.

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
Ich bin mir nicht sicher, wie gut Rock aushalten wird, wenn seine Feinde aufgrund von Siegen einige Buffs bekommen. Sieht aber gut aus.
Kyle Kanos

@KyleKanos Ich verstehe; Ich gehe jedoch davon aus, dass ich die meisten Beutetiere / Aliens bekämpfen werde, solange sie nicht schlau sind. Gibt ihm das nicht auch ein paar Buffs?
Timtech

Wenn ich jetzt auf meinen Kommentar zurückblicke, denke ich, dass es überhaupt nicht das war, was ich sagen wollte. Ich wollte sagen, dass die wantToFightBedingung nicht gegeben ist, truewenn die Feinde anfangen, mit Levels zu polieren. Sie werden sich schnell einem starken Pazifisten zuwenden.
Kyle Kanos

@KyleKanos Oh, ich verstehe. Ich habe es ein bisschen geändert.
Timtech

6

Morphling

Konnte sich keinen anderen Namen vorstellen, dieser Typ verteilt zufällig 10 Punkte auf seine Fähigkeiten. Fast bewegt sich wie Okinawa Life (danke für deine Mühe) und will nur kämpfen, wenn seine Stärke größer ist als die Stärke des Feindes.

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, du weißt, du hast recht. Die schließenden Klammern haben mich bei dieser Herausforderung umgebracht (musste mich deswegen ein paar Mal bearbeiten). Ich sehe es jetzt und es ist richtig. Vielen Dank für den Hinweis!
user3334871

@ user3334871 obwohl ich mit deinem Vorschlag getestet habe und mein Morphing gerade besser überlebt habe: D
Sikorski

@Sikorski Nun, ich bin froh, dass ich helfen konnte, nicht sicher, warum es besser laufen würde, haha.
user3334871

@Sikorski Ich denke, das bedeutet nur, dass es oft sicherer ist, auf dem Platz zu bleiben, als den ungefährlichsten Zug zu machen, wenn alle Züge gefährlich sind.
Martin Ender

Ahh, die Strategie "Deer in the Headlights" gefällt mir.
user3334871

6

Bender "Bending" Rodriguez

Ich war ziemlich liberal mit Code-Kommentaren. Sie können sie im Kontext lesen, um zu sehen, was los ist, aber ich werde auch einige Ausschnitte unten hinzufügen.

Zusammenfassung

Dieser Außerirdische arbeitet nach dem Prinzip, dass es einfach ist, mickrige Menschen zu töten, und erhöht Ihre wahrgenommene Stärke, wodurch andere Außerirdische davon abgehalten werden, sich freizumachen.

Wale und Adler sind auch biegbar. =)

Bewegung

Bewege dich entweder nach Westen oder Süden, es sei denn, du hast etwas Interessantes zum Angreifen gefunden:

  • Für die Beute, deren Bewegung bekannt ist, fügen wir ihre Begehrlichkeit dem Quadrat hinzu, an dem sie sich in der nächsten Runde befinden werden.
  • Für diejenigen, die wir nicht tun, teilen wir ihre Wünschbarkeit zu gleichen Teilen auf die Quadrate auf, auf die sie sich möglicherweise in der nächsten Runde bewegen.
    • Aliens erhalten aufgrund von Bananenschalen einen negativen Bonus auf ihr bestehendes Quadrat.

Wenn Sie in der Nähe nichts Interessantes finden, können Sie sich ein Bild davon machen, ob Süd, West oder Südwest eine vielversprechendere Option ist.

Das Auswählen einer oder zweier vorherrschender Richtungen verringert die Wahrscheinlichkeit, dass ein bestimmter Bender auf einen seiner Landsleute stößt, und das Auswählen einer Richtung, die seiner Hauptbeute widerspricht, sollte ihm helfen, alle Menschen schneller zu töten.

Ich könnte wahrscheinlich die Zahlen in der Erwünschtheitsmatrix mit dem genetischen Algorithmus von James_pic optimieren, um noch bessere Ergebnisse zu erzielen , aber ich weiß nicht, wie ich das machen soll.

Aggressivität

Bender zielt hauptsächlich auf Beute ab und ist mit seiner ziemlich konservativ wantToFight. Jeder über Stärke 4 wird gemieden, es sei denn, Sie denken, Sie haben es mit einem klugen Menschen zu tun. Clevere Menschlichkeit zeigt sich darin, dass sie mehr Verteidigung und Vision besitzt als ein Alien. Es wird im Verlauf einer Instanz durch Benders eigene Fähigkeitsstatistiken angepasst, um zu berücksichtigen, dass Außerirdische Schildkröten und Adler töten.

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

Mir ist aufgefallen, dass ein Schleifenlogikfehler aufgetreten ist, bei dem die inkrementierte Variable nicht direkt verglichen wurde und nur eine unendliche Rekursion durch Integer-Überlauf verhindert. Hoffe, Sie sind in Ordnung, wenn ich Ihre Antwort aktualisiere. (Die Simulation wurde von Zeit zu Zeit
angehalten

@ Moogie Heh. Mir ging es also nur zufällig gut? Danke, dass du das verstanden hast.
Michael

Ich habe die ganze Sache durchgesehen und ein paar weitere Probleme behoben.
Michael

5

Krieger

Dies ist ein sehr einfach gesinnter Alien, der nur kämpfen will. Er kümmert sich weder um seine Feinde noch um seine Umgebung.

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

Sie haben jetzt jemanden, gegen den Sie Ihren eigenen Alien testen können.


4

Feigling

Ich habe im Grunde genommen das Bewegungsmuster des Adlers gestohlen, um eine Gefahr und eine gestapelte Verteidigung für den Fall, dass ich angegriffen werde, zu vermeiden.

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

Korrigieren Sie mich, wenn ich falsch liege, aber da jede Fähigkeit einen Basispunkt von 1 hat, vision=1sollte das Putten ausreichen?
Nur die Hälfte des

@justhalf: Meine kurze Lektüre des Codes schien darauf hinzudeuten, dass setAbilityPointsdie Werte von 1 überschrieben wurden , aber wenn ich es mir genauer ansehe, denke ich, dass Sie Recht haben. Ich werde es so lassen, wie es ist, weil eine größere Vision es mir ermöglicht, weiter zu sehen und Gefahren zu vermeiden, aber danke für den Haken.
Kyle Kanos

Außerdem wird math.round immer auf 0,5 gerundet, sodass Sie eine zusätzliche Vision erhalten, wenn Sie eine ungerade Zahl haben
Andreas

@Manu: Ich habe meine Werte für Vision und Verteidigung ausgetauscht, um die Laufunruhe zu verbessern.
Kyle Kanos

4

Fleer

PANIK

APOKALYPSE

RUUUUUUUUUUN

AAAAAAAAAAAAAAAAAAAAAAA


Vermeidet nach Möglichkeit Schlachten.

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

Sie sollten diesem einen anderen Namen geben ... und der Antwort, die Sie kopiert haben, etwas Anerkennung zollen
Justin

2
@ Quincunx Das ist ein Zufall, habe nicht gesehen, dass man ...
Stommestack

Sorry, mir ist gerade aufgefallen, dass beide Antworten von Eagle stammen. Sie haben die andere Antwort nicht kopiert, ich habe sie nur nicht sorgfältig genug gelesen. Ein anderer Name wäre jedoch angebracht.
Justin

1
Änderte den Namen!
Stommestack

2
Sollte Rincewind heißen.
Magus

4

Predicoward (Schnurren)

Eine Rasse von Prädikaten, die (bisher) von Angst gelebt haben und sich von Ärger fernhalten. Aufgrund ihres Lebensstils haben sie keinen Kampftrieb entwickelt, aber ihre Wahrnehmung ist außergewöhnlich.

Ihre Art wird von ihren Predicats-Kollegen verabscheut.

BEARBEITEN: Die Manhattan-Entfernung wurde stattdessen in die gewichtete Entfernung geändert

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
Sieht gut aus! Aber bitte nimm deine Print-Statements raus, sie würden mich verwirren, wenn ich den Wettbewerb leite.
CommonGuy

Oh, ich habe die Druckaussagen hinterlassen? Ich werde sie später ändern. Haha. Außerdem ist dies noch nicht endgültig. Im Moment ist Predicoward scheiße. Seine Ausweichalgorithmen werden in Kürze verbessert. :) EDIT: Danke für denjenigen, der die Druckanweisungen entfernt hat. : D (Jop?)
Mark Gabriel

EDIT: Predicowards sind jetzt viel besser in der Flucht als die nervigen kleinen nicht konkurrierenden Predicowards, die sie gestern waren. > :)
Mark Gabriel

Wissenswertes: Dies ist mein Lieblings-Predicat <3
Mark Gabriel

4

PredicatEyes (meow)

Eine Rasse von Prädikaten, die eine schärfere Sicht haben als ihre Gegenstücke, was es ihnen ermöglicht, ihre Feinde gut aufzuspüren.

EDIT: Neue Zielprioritäten

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

Kornkreis Alien

Unbegrenzt im Uhrzeigersinn kreisen und nie kämpfen wollen, freut er sich, Kornkreise zu machen. Wenn du jedoch wirklich kämpfen willst, wird er dich fertig machen.

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
Dies wäre sauberer, wenn Sie Move durchlaufen hätten.
Nicht dass Charles

4
Warum jeder nicht ändern getI()zu iund einfach entfernen getI()? Sie können auch ändern setI(int i)zu this.i = i % 8;, und da Sie es nur in diesem einen Ort bedienen, einfach jeden Anruf ändern , um setI(getI() + 1)zui = (i + 1) % 8;
Justin

3

CleverAlien

Kluger Außerirdischer verlässt sich nur auf seinen Verstand. Er geht nach dem Zufallsprinzip umher und beschließt, nach dem Zufallsprinzip zu kämpfen. Er hofft, seine Feinde mit etwas Glück austricksen zu können. (Verzeih mir, wenn ich irgendwelche Syntaxfehler habe, ich bin kein Java-Typ)

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? Warum nicht (tmp == 1) == true ? true : false? ;) (Hinweis: Es ist das gleiche wie nur tmp == 1 .)
Martin Ender

3

Schurke

Wie schon andere gesagt haben, benutze ich die Bewegung des Adlers zu einem gewissen Grad. Anstatt zu versuchen, einen siegreichen Außerirdischen zu erschaffen (meine besten Ideen wurden bereits aufgegriffen D :), habe ich mich entschieden, einen Außerirdischen mit Charakter zu erschaffen! Mein Außerirdischer ist eine gemietete Waffe, die den außerirdischen Krieg nicht mitbekommt und nur auf diesem Planeten ist, um den dreckigen Menschen zu jagen, der seine Todesschuld nicht mehr hat. Mein Außerirdischer wird den Planeten nach dem Menschen absuchen und ihm weiterhin folgen, ohne ihn zu töten. Sobald ein Außerirdischer in seiner Nähe gesehen wird, wird er versuchen, den Menschen schnell zu töten und sich diesem neuen Gegner mit "Glück auf seiner Seite" von seiner erledigten Aufgabe zu stellen.

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

Der Code dreht sich um die Idee, dass ich auf den Menschen zusprinten sollte. Sobald ich ihn geschlagen habe, wickle ich mich dann nach Südwesten um, wo ich nach der Schildkröte suchen werde.

EDIT: Oh, und was die Schildkröten angeht ... mein Alien mag sie nicht, also ist es absolut kanonisch, Leute.


Ich habe gerade gemerkt, dass ich auch auf die Schildkröte zusteuern kann. Wer liebt nicht High Dodge Rogues?
user3334871

2
verwendet man int direkt als booleschen Wert, wenn ein Teil von Java 8 blockiert wird? weil es überhaupt nicht auf meinem Computer kompiliert (Java 7). Hinweis: humanPresent
Sikorski

Wenn ich weiß, beschränkte sich meine Java-Erfahrung größtenteils auf Skripte und Kurse auf College-Niveau. Ich werde nur die Vergleiche anstellen, nur damit alles pfirsichfarben ist. Danke für die Warnung!
User3334871

@Sikorski, haben Sie auch Ihre eigene Haupt- oder Initialisierungsfunktion erstellt, um Ihre Tests auszuführen? Oder kann es nur durch den bereitgestellten Code alleine gemacht werden? Ich schwöre, es ist so lange her, dass ich die Regeln für die Ausführung von Java-Code vergessen habe :(
user3334871

Nein, laden Sie einfach den von OP in github link angegebenen Code herunter, fügen Sie andere Klassen hinzu und starten Sie den Test. Oh, du musst einen Eintrag für jede Alien-Klasse in der Planet-Klasse hinzufügen.
Sikorski

3

Crash landete und versuchte nur zu überleben. Überlebt hauptsächlich durch seine Beweglichkeit und Intelligenz und zählt jede Narbe, wobei sorgfältig überlegt wird, ob es sich lohnt, einen Kampf zu beginnen oder nicht. Der Überlebende beginnt einfach mit der Jagd und versucht, all den anderen Aliens mit ihren großen Waffen auszuweichen, aber wenn es mutiger wird, kann er ihnen nachjagen. Wenn es wirklich losgeht, ist es egal, wem es gegenübersteht.

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
Ich bin mir ziemlich sicher, dass dies for(int ability in enemyAbilities){ein Syntaxfehler ist - versuchen Sie esfor(int ability : enemyAbilities){
Joshua

3

FunkyBob

Erste Priorität ist das Überleben, sonst wird versucht, eine Beute zu finden. Beurteilt den sichtbaren Bereich, um die allgemeine Richtung mit den geringsten Bedrohungen oder der meisten Beute zu finden. Scheint eine Überlebensrate von 85-90% während meiner Tests zu haben.

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

Nur zum Spaß, hier ist ein weiterer Eintrag mit einer etwas anderen Herangehensweise. Dieser konzentriert sich nur auf die Vermeidung von Kämpfen. Dies ist keine wirklich praktikable Strategie, da man in den ersten Runden von Feinden umgeben war. 40% der Felder sind in der ersten Runde belegt, sodass Sie im Durchschnitt unmittelbar an 3-4 Gegner angrenzt. Wenn man jedoch die anfänglichen leeren Quadrate auf das 12,5-fache der Art anstatt auf das 2,5-fache der Art erhöht, erhält man eine durchschnittliche Überlebensrate von 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% ist immens. Sogar meine Predicowards haben im Durchschnitt nur eine Überlebensrate von 65%. Haha. Edit: Meine Predicowards haben die gleiche Philosophie wie FunkyJack - nur wegbleiben. Ich habe 10 Visionen und 0 Kampfstatistiken.
Mark Gabriel

3

LazyBee

Ich habe angefangen, eine clevere Bee-Klasse zu erstellen, die Musterbewegungen und deduktives Denken verwendete, aber dann wurde ich schläfrig, also habe ich sie in LazyBee umbenannt und es eine Nacht genannt. Er scheint tatsächlich ziemlich gut bei meinen Tests abzuschneiden (Durchschnitt von ~ 1645 mit Außerirdischen auf dem 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
Ausgezeichnete Arbeit! Ich bin ziemlich erstaunt, dass Sie mit einer fest codierten Richtung so gut abschneiden.
Michael

@Michael Du hast keine Ahnung, wie angenehm überrascht ich war, als ich es herausfand! Ich hatte viel Mühe in den Bewegungscode gesteckt, dann lief er gegen HOLD als eine Art Kontrollgruppe. Dann bemerkte ich, dass die Kontrollgruppe in den Arsch trat, also fing ich an, mit verschiedenen Farben der Faulheit zu experimentieren!
Thefistopher

3

Neuer Typ

Versucht, "einfache" Ziele für die frühe Landwirtschaft zu erreichen. Ansonsten bewegen Sie sich nur sporadisch.

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

Diese Schwimmleine return true;erscheint aufgrund des elseZustands überflüssig .
Kyle Kanos

@KyleKanos Richtig. Problem behoben.
FreeAsInBeer

Ihr isHuman () -Test sieht nicht ganz richtig aus. Wird es nicht auch Außerirdische geben, die das Level erreicht haben?
Nicht dass Charles

@ Charles Du hast recht. Es ist schwierig (unmöglich?) Herauszufinden, ob der Feind ein Mensch oder ein Alien ist, aufgrund der Funktionsweise der 'Cleverness'-Mechanik und der Tatsache, dass wir die Cleverness während einer Kampfabfrage nicht bestimmen können. Selbst wenn man einige Grundrechenarten verwendet, ist es sehr wahrscheinlich, dass eine fundierte Vermutung, ob es sich um einen Menschen handelt oder nicht, ungenau ist. Ich schätze, ich werde ihn so ändern, dass er vor Menschen flieht.
FreeAsInBeer

Ihre isSpecie-Tests sehen cool aus, aber auch Beutekampf und diese Tests werden bald scheitern ...
CommonGuy

2

Bewachen

Stapeln Sie Leben, Stärke und Verteidigung, und bleiben Sie in Position. Nur angreifen, wenn der Gegner aggressiv zu sein scheint (definiert als strengthgrößer als 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 wird herumlaufen und die Feinde ignorieren, bis er jemanden findet, mit dem er sich nur schwer anlegen kann.

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, der Bully Alien will einfach nur Freunde sein.
user3334871

3
@ user3334871 Eher wie: "Der Bully Alien will nur einen Syntaxfehler haben"
Justin

Sollte wantToFight nicht auf die Fähigkeiten des Feindes schauen?
Ingo Bürk

@ IngoBürk Hat es schon getan, als du es kommentiert hast
William Barbosa

Ich muss zu lange gebraucht haben, um durch den Thread zu scrollen. :)
Ingo Bürk

2

BlindBully

Es ist egal, wer oder was sich in der Nähe befindet, es versucht nur zu entscheiden, ob das Alien, dem es gerade gegenübersteht, stärker oder schwächer ist als es selbst und greift die Schwächeren an.

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

Das ist also das Beste? haha
Hälfte
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.