Last active
August 29, 2015 14:03
-
-
Save apsillers/bbe1a22ba62fd059400f to your computer and use it in GitHub Desktop.
Java BftPD sample cell
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Sample code for a "Battle for the Petri Dish" cell | |
Released under the terms of the WTF Public License | |
No warranty express or implied is granted, etc, etc. | |
I just hacked this together very quickly; improvements are welcome, so please fork the Gist if you like. | |
*/ | |
import java.io.BufferedReader; | |
import java.io.IOException; | |
import java.io.InputStreamReader; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
public class CellTemplate { | |
public static final int MAX_HP = 5; | |
public static final int MAX_ENERGY = 5; | |
public static final int ACIDITY = 2; | |
// given arena state and cell stats, return an action string (e.g., "ATTACK NW 2", "DIVIDE S") | |
public static String decide(Arena arena, Point cell, int hp, int energy) { | |
// empty and corpses are free for movement and division | |
ArrayList<Point> nearbyEmpty = arena.getAdjacentMatches(cell, "."); | |
nearbyEmpty.addAll(arena.getAdjacentMatches(cell, "c")); | |
ArrayList<Point> nearbyEnemies = arena.getAdjacentMatches(cell, "x"); | |
ArrayList<Point> nearbyCorpses = arena.getAdjacentMatches(cell, "c"); | |
ArrayList<Point> nearbyFriends = arena.getAdjacentMatches(cell, "o"); | |
// if you have energy and space to divide, divide into a random space | |
if(energy >= 5 && nearbyEmpty.size() > 0) { | |
Point randomEmpty = nearbyEmpty.get((int)Math.floor(nearbyEmpty.size()*Math.random())); | |
return "DIVIDE " + arena.getDirection(cell, randomEmpty); | |
} | |
// if you have two or more nearby enemies, explode if possible | |
if(nearbyEnemies.size() > 1 && energy > hp && hp <= 3) { | |
return "EXPLODE"; | |
} | |
// if at least one adjacent enemy, attack if possible | |
if(energy > 0 && nearbyEnemies.size() > 0) { | |
int attackStrength = Math.min(energy, 3); | |
Point enemy = nearbyEnemies.get((int)Math.floor(nearbyEnemies.size()*Math.random())); | |
return "ATTACK " + arena.getDirection(cell, enemy) + " " + attackStrength; | |
} | |
// if there's a nearby corpse, eat it if your energy is below max | |
if(nearbyCorpses.size() > 0) { | |
Point corpse = nearbyCorpses.get((int)Math.floor(nearbyCorpses.size()*Math.random())); | |
return "EAT " + arena.getDirection(cell, corpse); | |
} | |
return "REST"; | |
} | |
public static void main(String[] args) throws IOException { | |
BufferedReader br = | |
new BufferedReader(new InputStreamReader(System.in)); | |
String firstLine; | |
firstLine = br.readLine(); | |
if(firstLine.equals("BEGIN")) { | |
System.out.println(MAX_HP + " " + MAX_ENERGY + " " + ACIDITY); | |
} else { | |
String[] dimensions = firstLine.split(" "); | |
int width = Integer.parseInt(dimensions[0]); | |
int height = Integer.parseInt(dimensions[1]); | |
Point[][] arena = new Point[height][]; | |
String input; | |
int lineno = 0; | |
while(!(input=br.readLine()).equals("")) { | |
String[] charList = input.substring(1).split(""); | |
arena[lineno] = new Point[width]; | |
for(int i=0; i<charList.length; ++i) { | |
arena[lineno][i] = new Point(i, lineno, charList[i]); | |
} | |
lineno++; | |
} | |
String[] stats = br.readLine().split(" "); | |
int x = Integer.parseInt(stats[0]); | |
int y = Integer.parseInt(stats[1]); | |
int hp = Integer.parseInt(stats[2]); | |
int energy = Integer.parseInt(stats[3]); | |
Arena arenaObj = new Arena(arena, width, height); | |
System.out.print(decide(arenaObj, arenaObj.get(x,y), hp, energy)); | |
} | |
} | |
public static class Arena { | |
public Point[][] array; | |
public HashMap<String, String> c2d; | |
public int height; | |
public int width; | |
public Arena(Point[][] array, int width, int height) { | |
this.array = array; | |
this.width = width; | |
this.height = height; | |
this.c2d = new HashMap<String, String>(); | |
this.c2d.put("0,0", "-"); | |
this.c2d.put("0,-1", "N"); | |
this.c2d.put("0,1", "S"); | |
this.c2d.put("1,0", "E"); | |
this.c2d.put("-1,0", "W"); | |
this.c2d.put("-1,-1", "NW"); | |
this.c2d.put("1,-1", "NE"); | |
this.c2d.put("-1,1", "SW"); | |
this.c2d.put("1,1", "SE"); | |
} | |
// get the character at x,y | |
// or return empty string if out of bounds | |
public Point get(int x, int y) { | |
if(y < 0 || y >= this.array.length){ | |
return null; | |
} | |
Point[] row = this.array[y]; | |
if(x < 0 || x >= row.length) { | |
return null; | |
} | |
return row[x]; | |
} | |
// get arraylist of Points for each adjacent space that matches the target string | |
public ArrayList<Point> getAdjacentMatches(Point p, String match) { | |
ArrayList<Point> result = new ArrayList<Point>(); | |
for(int i=-1; i<=1; ++i) { | |
for(int j=-1; j<=1; ++j) { | |
Point found = this.get(p.x+i, p.y+j); | |
if((i!=0 || j!=0) && found != null && found.symbol.equals(match)) { | |
result.add(found); | |
} | |
} | |
} | |
return result; | |
} | |
// get the direction string from point 1 to point 2 | |
public String getDirection(Point p1, Point p2) { | |
int dx = p2.x - p1.x; | |
int dy = p2.y - p1.y; | |
dx = Math.abs(dx) / (dx==0?1:dx); | |
dy = Math.abs(dy) / (dy==0?1:dy); | |
return this.c2d.get(dx + "," + dy); | |
} | |
} | |
public static class Point { | |
int x, y; | |
String symbol; | |
public Point(int x, int y, String sym) { | |
this.x=x; | |
this.y=y; | |
this.symbol=sym; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment