To test it I declared all the elves as mine and declared the two (seemly) broken ogres as good ones and ran it for 1000 turns. Elves win about 80% of the time. At 8000+ turns elves never win.
My code:
- Code: Select all
import javax.imageio.*;
import java.io.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.*;
import javax.swing.*;
import javax.swing.JOptionPane;
public class Elf_14 extends ElfPlayer
{
final int NUM_ELVES = AdventureDrawer.NUMBER_ELVES;
final int BASE_ELF_MOTION = AdventureDrawer.BASELINE_ELF_MOTION;
final int WIDTH = AdventureDrawer.DEFAULT_WIDTH;
final int HEIGHT = AdventureDrawer.DEFAULT_HEIGHT;
private enum state
{
RUN, // Run away from enemy
HIDE, // Hiding in a hole
FIND_TREASURE, // Searching for treasure in vision
FIND_COVER, // Searching for hiding spot in vision
ROAM_COOP, // Roam around with Coop
ROAM_UNCOOP // Roam around without Coop (Faster movement, smaller vision)
}
private enum entity
{
OGRE,
ELF,
TREASURE,
HOLE
}
private Point currentPoint = new Point(this.getX(), this.getY()); // Current point
private double lastAngle = 0.0; // Last angle of direction
private Point lastPoint = new Point(-1, -1); // Last point I was at
private int holeTurns = 0; // Number of turns in a hole
private int runTurns = 0; // Number of turns running away
private state mine = state.ROAM_COOP; // My state
private int numCoopElves = NUM_ELVES; // Number of elves I'm cooperating with
private ElfPlayer_Data visibleElves[]; // Current visible elves
private OgrePlayer_Data visibleOgres[]; // Current visible ogres
private Treasure_Data visibleTreasure[]; // Current visible treasure
private Hole_Data visibleHoles[]; // Current visible holes
private BufferedImage bufferedImage = null;
public Elf_14(int t, int seq, int x, int y)
{
super(t, seq, x, y); // invoke the parent class constructor
try
{
// Modify this line for your preferred player image.
// Images must be 32 x 32 pixels, in BMP format, and tasteful photo.
bufferedImage = ImageIO.read(new File("Elf_14.bmp"));
}
catch (IOException e) { bufferedImage = null; }
setWealth(0);
}
/** Return the string of choice for the display of your player.
*/
public String getString()
{
return "Ferlisi";
}
/** Return the image of choice for the display of your player.
*/
public BufferedImage getImage() { return bufferedImage; }
public void update(ElfPlayer_Data visibleElves[], OgrePlayer_Data visibleOgres[], Treasure_Data visibleTreasure[], Hole_Data visibleHoles[]) // Update the position of the player
{
//System.out.println("Before Real x: "+this.getX()+" - Before Real y: "+this.getY());
this.visibleElves = visibleElves;
this.visibleOgres = visibleOgres;
this.visibleTreasure = visibleTreasure;
this.visibleHoles = visibleHoles;
this.UpdateState();
switch (mine)
{
case RUN:
this.Run();
break;
case HIDE:
this.Hide();
break;
case FIND_TREASURE:
this.FindTreasure();
break;
case FIND_COVER:
this.FindCover();
break;
case ROAM_COOP:
this.RoamCoop();
break;
case ROAM_UNCOOP:
this.RoamUnCoop();
break;
default: break;
}
super.setPos(currentPoint.x, currentPoint.y);
//System.out.println("Max Movement: "+this.MaxMovement()+" - Last x: "+lastPoint.x+" - Last y: "+lastPoint.y+" - Current x: "+currentPoint.x+" - Current y: "+currentPoint.y);
//System.out.println("After Real x: "+getX()+" - After Real y: "+getY());
}
private void Run()
{
this.UnCoopAll(); // Drop Coop and run faster
entity temp = entity.OGRE;
this.FindBestPathAway(temp); // Find best escape vector and move
}
private void FindTreasure()
{
entity temp = entity.TREASURE;
this.FindBestPathTo(temp); // Find best vector towards treasure
}
private void FindHole()
{
entity temp = entity.HOLE;
this.FindBestPathTo(temp);
}
private void RoamCoop()
{
this.CoopAll(); // Cooperate with all
/* Move to a random spot in (sorta) the direction I'm heading. Take last
* angle and and add a random change of 45 degrees in either direction. */
/* Get angle of movement */
double deviation = Math.random() * 90 - 45;
if(deviation < 0.0) deviation += 360;
if(deviation >= 360.0) deviation -= 360.0;
lastAngle = lastAngle + deviation;
/* Get new point, move to it, and update variables */
int newX = (int)(this.MaxMovement()*Math.cos(Math.toRadians(lastAngle)));
int newY = (int)(this.MaxMovement()*Math.sin(Math.toRadians(lastAngle)));
lastPoint.x = currentPoint.x;
lastPoint.y = currentPoint.y;
currentPoint.x = this.getX() + newX;
currentPoint.y = this.getY() + newY;
//System.out.println("Max Movement: "+this.MaxMovement()+" - Last x: "+lastPoint.x+" - Last y: "+lastPoint.y+" - Current x: "+currentPoint.x+" - Current y: "+currentPoint.y);
this.BoundsCheck();
//System.out.println("Max Movement: "+this.MaxMovement()+" - Last x: "+lastPoint.x+" - Last y: "+lastPoint.y+" - Current x: "+currentPoint.x+" - Current y: "+currentPoint.y);
}
private void Hide()
{
this.CoopAll();
}
private void FindCover()
{
this.UnCoopAll();
}
private void RoamUnCoop()
{
this.UnCoopAll();
}
private void UpdateState()
{
if(visibleOgres.length > 0)
{
mine = state.RUN;
runTurns++;
}
else if (runTurns > 1)
{
mine = state.RUN;
runTurns--;
}
else if(visibleTreasure.length > 0)
{
runTurns = -1;
mine = state.FIND_TREASURE;
}
else
{
runTurns = -1;
mine = state.ROAM_COOP;
}
}
private void FindBestPathAway(entity e)
{
Point goal = this.SetGoal(e);
lastAngle = currentPoint.calcAngle(goal);
if(lastAngle >= 180)
lastAngle = lastAngle - 180;
else
lastAngle = lastAngle + 180;
int newX = (int)(this.MaxMovement()*Math.cos(Math.toRadians(lastAngle)));
int newY = (int)(this.MaxMovement()*Math.sin(Math.toRadians(lastAngle)));
lastPoint.x = currentPoint.x;
lastPoint.y = currentPoint.y;
currentPoint.x = this.getX() + newX;
currentPoint.y = this.getY() + newY;
//System.out.println("Max Movement: "+this.MaxMovement()+" - Last x: "+lastPoint.x+" - Last y: "+lastPoint.y+" - Current x: "+currentPoint.x+" - Current y: "+currentPoint.y);
this.BoundsCheck();
//System.out.println("Max Movement: "+this.MaxMovement()+" - Last x: "+lastPoint.x+" - Last y: "+lastPoint.y+" - Current x: "+currentPoint.x+" - Current y: "+currentPoint.y);
}
private void FindBestPathTo(entity e)
{
Point goal = this.SetGoal(e);
lastAngle = currentPoint.calcAngle(goal);
if(currentPoint.calcDist(goal) <= this.MaxMovement())
{
currentPoint.x = goal.x;
currentPoint.y = goal.y;
}
else
{
int newX = (int)(this.MaxMovement()*Math.cos(Math.toRadians(lastAngle)));
int newY = (int)(this.MaxMovement()*Math.sin(Math.toRadians(lastAngle)));
lastPoint.x = currentPoint.x;
lastPoint.y = currentPoint.y;
currentPoint.x = this.getX() + newX;
currentPoint.y = this.getY() + newY;
//System.out.println("Max Movement: "+this.MaxMovement()+" - Last x: "+lastPoint.x+" - Last y: "+lastPoint.y+" - Current x: "+currentPoint.x+" - Current y: "+currentPoint.y);
this.BoundsCheck();
//System.out.println("Max Movement: "+this.MaxMovement()+" - Last x: "+lastPoint.x+" - Last y: "+lastPoint.y+" - Current x: "+currentPoint.x+" - Current y: "+currentPoint.y);
}
}
private double MaxMovement()
{
return BASE_ELF_MOTION + BASE_ELF_MOTION * (NUM_ELVES - numCoopElves) / NUM_ELVES;
}
private void BoundsCheck()
{
/* If we go out at a corner */
if(currentPoint.x < 0 && currentPoint.y < 0)
{
currentPoint.x = 0;
currentPoint.y = 0;
}
else if(currentPoint.x < 0 && currentPoint.y > HEIGHT)
{
currentPoint.x = 0;
currentPoint.y = HEIGHT;
}
else if(currentPoint.x > WIDTH && currentPoint.y < 0)
{
currentPoint.x = WIDTH;
currentPoint.y = 0;
}
else if(currentPoint.x > WIDTH && currentPoint.y > HEIGHT)
{
currentPoint.x = WIDTH;
currentPoint.y = HEIGHT;
}
/* If we go off the right side */
else if(currentPoint.x < 0)
{
int xDiff = Math.abs(currentPoint.x - 0);
currentPoint.x = 0;
if(lastAngle > 90 && lastAngle <= 180)
{
currentPoint.y = currentPoint.y - xDiff;
if(currentPoint.y < 0)
currentPoint.y = 0;
}
if(lastAngle > 180 && lastAngle < 270)
{
currentPoint.y = currentPoint.y + xDiff;
if(currentPoint.y > HEIGHT)
currentPoint.y = HEIGHT;
}
}
/* If we go off the left side */
else if(currentPoint.x > WIDTH)
{
int xDiff = Math.abs(currentPoint.x - WIDTH);
currentPoint.x = WIDTH;
if(lastAngle > 90 && lastAngle <= 180)
{
currentPoint.y = currentPoint.y - xDiff;
if(currentPoint.y < 0)
currentPoint.y = 0;
}
if(lastAngle > 180 && lastAngle < 270)
{
currentPoint.y = currentPoint.y + xDiff;
if(currentPoint.y > HEIGHT)
currentPoint.y = HEIGHT;
}
}
/* If we go off the top side */
else if(currentPoint.y < 0)
{
int yDiff = Math.abs(currentPoint.y - 0);
currentPoint.y = 0;
if(lastAngle > 0 && lastAngle <= 90)
{
currentPoint.x = currentPoint.x + yDiff;
if(currentPoint.x > WIDTH)
currentPoint.x = WIDTH;
}
if(lastAngle > 90 && lastAngle < 180)
{
currentPoint.x = currentPoint.x - yDiff;
if(currentPoint.x < 0)
currentPoint.x = 0;
}
}
/* If we go off the bottom side */
else if(currentPoint.y > HEIGHT)
{
int yDiff = Math.abs(currentPoint.y - HEIGHT);
currentPoint.y = HEIGHT;
if(lastAngle > 0 && lastAngle <= 90)
{
currentPoint.x = currentPoint.x + yDiff;
if(currentPoint.x < WIDTH)
currentPoint.x = WIDTH;
}
if(lastAngle > 90 && lastAngle < 180)
{
currentPoint.x = currentPoint.x - yDiff;
if(currentPoint.x > 0)
currentPoint.x = 0;
}
}
else
{
currentPoint.x = currentPoint.x;
currentPoint.y = currentPoint.y;
}
}
private void BoundsCheckOgre()
{
/* If we go out at a corner */
if(currentPoint.x < 0 && currentPoint.y < 0)
{
currentPoint.x = 0;
currentPoint.y = 0;
}
else if(currentPoint.x < 0 && currentPoint.y > HEIGHT)
{
currentPoint.x = 0;
currentPoint.y = HEIGHT;
}
else if(currentPoint.x > WIDTH && currentPoint.y < 0)
{
currentPoint.x = WIDTH;
currentPoint.y = 0;
}
else if(currentPoint.x > WIDTH && currentPoint.y > HEIGHT)
{
currentPoint.x = WIDTH;
currentPoint.y = HEIGHT;
}
/* If we go off the right side */
else if(currentPoint.x < 0)
{
int xDiff = Math.abs(currentPoint.x - 0);
currentPoint.x = 0;
if(lastAngle > 90 && lastAngle <= 180)
{
currentPoint.y = currentPoint.y - xDiff;
if(currentPoint.y < 0)
currentPoint.y = 0;
}
if(lastAngle > 180 && lastAngle < 270)
{
currentPoint.y = currentPoint.y + xDiff;
if(currentPoint.y > HEIGHT)
currentPoint.y = HEIGHT;
}
}
/* If we go off the left side */
else if(currentPoint.x > WIDTH)
{
int xDiff = Math.abs(currentPoint.x - WIDTH);
currentPoint.x = WIDTH;
if(lastAngle > 90 && lastAngle <= 180)
{
currentPoint.y = currentPoint.y - xDiff;
if(currentPoint.y < 0)
currentPoint.y = 0;
}
if(lastAngle > 180 && lastAngle < 270)
{
currentPoint.y = currentPoint.y + xDiff;
if(currentPoint.y > HEIGHT)
currentPoint.y = HEIGHT;
}
}
/* If we go off the top side */
else if(currentPoint.y < 0)
{
int yDiff = Math.abs(currentPoint.y - 0);
currentPoint.y = 0;
if(lastAngle > 0 && lastAngle <= 90)
{
currentPoint.x = currentPoint.x + yDiff;
if(currentPoint.x > WIDTH)
currentPoint.x = WIDTH;
}
if(lastAngle > 90 && lastAngle < 180)
{
currentPoint.x = currentPoint.x - yDiff;
if(currentPoint.x < 0)
currentPoint.x = 0;
}
}
/* If we go off the bottom side */
else if(currentPoint.y > HEIGHT)
{
int yDiff = Math.abs(currentPoint.y - HEIGHT);
currentPoint.y = HEIGHT;
if(lastAngle > 0 && lastAngle <= 90)
{
currentPoint.x = currentPoint.x + yDiff;
if(currentPoint.x < WIDTH)
currentPoint.x = WIDTH;
}
if(lastAngle > 90 && lastAngle < 180)
{
currentPoint.x = currentPoint.x - yDiff;
if(currentPoint.x > 0)
currentPoint.x = 0;
}
}
else
{
currentPoint.x = currentPoint.x;
currentPoint.y = currentPoint.y;
}
}
private Point SetGoal(entity thing)
{
Point goal = new Point(5000,5000);
switch(thing)
{
case OGRE:
for(int i = 0; i < visibleOgres.length; i++)
{
Point currentOgre = new Point(visibleOgres[i].getX(), visibleOgres[i].getY());
if(currentPoint.calcDist(currentOgre) < currentPoint.calcDist(goal))
goal = currentOgre;
}
break;
case ELF:
for(int i = 0; i < visibleElves.length; i++)
{
Point currentElf = new Point(visibleElves[i].getX(), visibleElves[i].getY());
if(currentPoint.calcDist(currentElf) < currentPoint.calcDist(goal))
goal = currentElf;
}
break;
case TREASURE:
for(int i = 0; i < visibleTreasure.length; i++)
{
Point currentTreasure = new Point(visibleTreasure[i].getX(), visibleTreasure[i].getY());
if(currentPoint.calcDist(currentTreasure) < currentPoint.calcDist(goal))
goal = currentTreasure;
}
break;
case HOLE:
for(int i = 0; i < visibleHoles.length; i++)
{
Point currentHole = new Point(visibleHoles[i].getX(), visibleHoles[i].getY());
if(currentPoint.calcDist(currentHole) < currentPoint.calcDist(goal))
goal = currentHole;
}
break;
default: break;
}
return goal;
}
private void CoopAll()
{
for (int j = 0; j < AdventureDrawer.NUMBER_ELVES; j++)
{
this.setCoop(j);
}
numCoopElves = NUM_ELVES;
}
private void UnCoopAll()
{
for (int j = 0; j < AdventureDrawer.NUMBER_ELVES; j++)
{
this.removeAllCoop();
}
numCoopElves = 0;
}
class Point
{
protected int x;
protected int y;
public Point()
{
x = 0;
y = 0;
}
public Point(int x, int y)
{
this.x = x;
this.y = y;
}
public double calcDist(Point two)
{
return Math.sqrt(Math.pow((double)this.x - (double)two.x, 2.0) + Math.pow((double)this.y - (double)two.y, 2.0));
}
public double calcAngle(Point two)
{
int xDiff = two.x - this.x;
int yDiff = two.y - this.y;
double angle = Math.toDegrees(Math.atan((double)yDiff / (double)xDiff));
if(xDiff < 0) // In quad 2 or 3
angle += 180.0;
else if(yDiff < 0) // In quad 3 or 4
angle += 360.0;
return angle;
}
}
}
