Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
214 changes: 162 additions & 52 deletions RobotPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ public class RobotPlayer{
static Team opponentTeam;
static int[] zombieRounds;
static MapLocation[] zombieDenLocations;
static Collection<Integer> enemyArchonIDs;
static ArrayList<Integer> enemyArchonIDs = new ArrayList<Integer>();
// Collection of <Archon ID, Archon Location, Round that measurement was taken>
static Collection<Triple<Integer,MapLocation,Integer>> mostRecentEnemyArchonLocations;
static ArrayList<Triple<Integer,MapLocation,Integer>> mostRecentEnemyArchonLocations = new ArrayList<Triple<Integer,MapLocation,Integer>>();
static Direction[] DIRECTIONS = new Direction[]{Direction.NORTH,Direction.NORTH_EAST,Direction.EAST,Direction.SOUTH_EAST,Direction.SOUTH,Direction.SOUTH_WEST,Direction.WEST,Direction.NORTH_WEST};

/**
Expand Down Expand Up @@ -253,6 +253,17 @@ public Archon(){
public void run(){
while(true){
try{
Signal[] signals = rc.emptySignalQueue();
for(int i = 0; i < signals.length; i++){
if(signals[i].getTeam() == ourTeam){
FancyMessage x = FancyMessage.getFromRecievedSignal(signals[i]);
if(x.isMessage){
if(x.type == 2){
mostRecentEnemyArchonLocations.add(new Triple<Integer,MapLocation,Integer>(0,new MapLocation(x.ints.first,x.ints.second),rc.getRoundNum()));
}
}
}
}
//If it can, always tries to build Scouts.
if(rc.isCoreReady()){
RESOURCE_FUNCTIONS.escapeEnemy();
Expand All @@ -263,7 +274,8 @@ public void run(){
if(RESOURCE_FUNCTIONS.tryBuild(type)){ //See function in RESOURCE_FUNCTIONS to know what it does
//After building scout, waits a turn, then signals it the location, so it has a good idea of where base is
Clock.yield();
FancyMessage.sendMessage(0,0b11101,31,30);
Triple<Integer,Integer,Integer> scoutType = getScoutInitType();
FancyMessage.sendMessage(0,scoutType.first | scoutType.second,scoutType.third,3);
}
}
Clock.yield();
Expand All @@ -272,6 +284,10 @@ public void run(){
}
}
}

public Triple<Integer,Integer,Integer> getScoutInitType(){
return new Triple<Integer,Integer,Integer>(0,0,0);
}
}

/**
Expand All @@ -285,9 +301,10 @@ public void run(){
*
*/
private class Scout{
MapLocation base;
MapLocation base = null;
int disciples;
MapLocation last;
MapLocation last = null;
MapLocation mostRecentArchonLocation = null;

/**
* Constructor
Expand All @@ -309,61 +326,111 @@ public Scout(){
*/
public void run(){
while(true){
if(base == null){
Signal[] signals = rc.emptySignalQueue();
if(signals.length > 0){
for(int i = 0; i < signals.length; i++){
if(signals[i].getTeam() == ourTeam){
FancyMessage x = FancyMessage.getFromRecievedSignal(signals[i]);
if(x.isMessage){
if(x.type == 0){
base = x.senderLocation;
if((x.ints.first & 3) == 0){
runAsArchonSearcher();
}else if((x.ints.first & 3) == 1){
if(x.bits[2]){
mostRecentArchonLocation = new MapLocation(x.ints.first >> 16,x.ints.second);
}
runAsZombieHerder();
}else if((x.ints.first & 3) == 2){
runAsTurretSights(x.ints.second);
}
}
}
}
}
}
}
}
}

public void runAsArchonSearcher(){
boolean foundArchon = false;
while(!foundArchon){
try{
MapLocation enemyArchonLocation = RESOURCE_FUNCTIONS.scanArchonLocation();
if(enemyArchonLocation != null){
int xPos = enemyArchonLocation.x;
int yPos = enemyArchonLocation.y;
FancyMessage.sendMessage(2, xPos, yPos, 1000);
FancyMessage.sendMessage(2, xPos + 16000, yPos + 16000, 1000);
foundArchon = true;
}else if(rc.isCoreReady()){
RESOURCE_FUNCTIONS.moveAsFarAwayAsPossibleFrom(base);
}
//Do nothing until base-line information is gathered: ie, where are the archons. in future, archons may also give message assigning role
if(base == null){
Signal[] signals = rc.emptySignalQueue();
if(signals.length > 0){ //if == 0, no signals, so not ready
Tuple<Integer,Integer> approxxCoordinates = new Tuple<Integer,Integer>(0,0);
//averages the signal's origins
int counted = 0;
for(int i = 0; i < signals.length; i++){
if(signals[i].getTeam() == rc.getTeam() && rc.senseRobot(signals[i].getID()).type == RobotType.ARCHON){
FancyMessage f = FancyMessage.getFromRecievedSignal(signals[i]);
rc.setIndicatorString(0,"Type:" + f.type + "::Key:" + f.key);
//rc.setIndicatorString(1,"Info:" + Arrays.toString(f.bits));
approxxCoordinates.first += f.senderLocation.x;
approxxCoordinates.second += f.senderLocation.y;
counted++;
}
}
if(counted > 0){
approxxCoordinates.first /= counted;
approxxCoordinates.second /= counted;
}catch(Exception e){
e.printStackTrace();
}
Clock.yield();
}
runAsZombieBomber();
}

//sets @base to this
base = new MapLocation(approxxCoordinates.first,approxxCoordinates.second);
//rc.setIndicatorString(0,"x:" + base.x + "::y:" + base.y);
public void runAsZombieHerder(){
while(true){
try{
Signal[] signals = rc.emptySignalQueue();
for(Signal s : signals){
if(s.getTeam() == ourTeam){
FancyMessage x = FancyMessage.getFromRecievedSignal(s);
if(x.type == 2){
mostRecentArchonLocation = new MapLocation(x.ints.first - 16000,x.ints.second - 16000);
}
}
}else{
//If initialized, checks to make sure it isn't losing its herd
}
if(rc.isCoreReady()){
if(stillHerding()){
//if they're still following, it tries to move
if(rc.isCoreReady()){
MapLocation temp = rc.getLocation();
if(RESOURCE_FUNCTIONS.moveAsFarAwayAsPossibleFrom(base)){//See RESOURCE_FUNCTIONS for details
last = temp;
}
if(mostRecentArchonLocation != null){
wiggle(mostRecentArchonLocation);
}else{
RESOURCE_FUNCTIONS.moveAsFarAwayAsPossibleFrom(base);
}
//Otherwise, moves back to where it last was to try to regain them
}else if(last != null){
if(rc.isCoreReady()){
}else{
if(last != null){
if(rc.canMove(rc.getLocation().directionTo(last))){
MapLocation temp = rc.getLocation();
rc.move(temp.directionTo(last));
last = temp;
rc.move(rc.getLocation().directionTo(last));
}
}
}
}
Clock.yield();
}catch(Exception e){
e.printStackTrace();
}
Clock.yield();
}
}

public void runAsTurretSights(int turretID){
while(true){
try{

}catch(Exception e){
e.printStackTrace();
}
}
}

public void runAsZombieBomber(){
while(true){
try{
if(mostRecentArchonLocation != null){
if(rc.getLocation().distanceSquaredTo(mostRecentArchonLocation) < 25 && rc.getInfectedTurns() > 0){
rc.disintegrate();
}else if(rc.isCoreReady()){
wiggle(mostRecentArchonLocation);
}
}else{
runAsArchonSearcher();
}
}catch(Exception e){
e.printStackTrace();
}
Expand Down Expand Up @@ -394,6 +461,19 @@ public boolean stillHerding(){
}
return false;
}

public boolean wiggle(MapLocation target) throws GameActionException{
int[] tryOrder = new int[]{0,1,-1,2,-2,3,-3,4};
int toTarget = RESOURCE_FUNCTIONS.dirToInt(rc.getLocation().directionTo(target));
for(int i = 0; i < tryOrder.length; i++){
if(rc.canMove(RESOURCE_FUNCTIONS.intToDir(toTarget + tryOrder[i]))){
last = rc.getLocation();
rc.move(RESOURCE_FUNCTIONS.intToDir(toTarget + tryOrder[i]));
return true;
}
}
return false;
}
}

/**
Expand Down Expand Up @@ -662,6 +742,9 @@ public static void collectEnemyArchonID() {
* Get most recent enemy archon location
*/
public static MapLocation mostRecentEnemyArchonLocation() {
if(mostRecentEnemyArchonLocations.size() == 0){
return null;
}
MapLocation latestArchonLocation = new MapLocation(0,0);
int latestRound = 0;
for (Triple<Integer, MapLocation, Integer> trip : mostRecentEnemyArchonLocations) {
Expand Down Expand Up @@ -934,13 +1017,35 @@ public static class FancyMessage{
public int senderID;
public MapLocation senderLocation;
public boolean[] bits;
public boolean isMessage;
public Tuple<Integer,Integer> ints;
private static Tuple<Integer,Integer> hiddenInts;
public int type;
public int key;
public FancyMessage(){
}

/**
* int getIntFromBitsInRange
*
* gets the int stored from bits @lower to @upper
*
* @param lower: the lower bound of the int (first bit to be counted, least significant)
* @param upper: the upper bound of the int (not counted, all bits below though)
*
* @return the int represented by these bits
*
*/
public int getIntFrombitsInRange(int lower,int upper){
int ret = 0;
for(int i = 0; i < upper - lower && i < 32 && i + upper < bits.length; i++){
if(bits[i + lower]){
ret |= 1 << i;
}
}
return ret;
}

/**
* FancyMessage getFromRecievedSignal
*
Expand All @@ -956,12 +1061,17 @@ public static FancyMessage getFromRecievedSignal(Signal s){
ret.senderID = s.getID();
ret.senderLocation = s.getLocation();
int[] is = s.getMessage();
Tuple<Integer,boolean[]> info = decrypt(new Tuple<Integer,Integer>(is[0],is[1]));
ret.type = info.first;
ret.bits = info.second;
ret.ints = hiddenInts;
hiddenInts = null;
ret.key = (is[0] & 0b11110000) >> 4;
if(is == null){
ret.isMessage = false;
}else{
ret.isMessage = true;
Tuple<Integer,boolean[]> info = decrypt(new Tuple<Integer,Integer>(is[0],is[1]));
ret.type = info.first;
ret.bits = info.second;
ret.ints = hiddenInts;
hiddenInts = null;
ret.key = (is[0] & 0b11110000) >> 4;
}
return ret;
}

Expand Down Expand Up @@ -1296,7 +1406,7 @@ public ArrayList<MapLocation> getAllRightCanditates(){
int forwardInt = RESOURCE_FUNCTIONS.dirToInt(forward); //Only perform this once, for optimization
//Next line is long. Gets an array of all directions considered "left" relative to @forward
Direction[] rights = new Direction[]{RESOURCE_FUNCTIONS.intToDir((forwardInt + 5) % 8),RESOURCE_FUNCTIONS.intToDir((forwardInt + 6) % 8),RESOURCE_FUNCTIONS.intToDir((forwardInt + 7) % 8)};
if(!branchPoint.equals(options[i]) && rc.senseRubble(options[i]) < 100 && rc.onTheMap(options[i])){ //checks this option to be: not current position, traversable, and on the map
if(!branchPoint.equals(options[i]) && rc.canMove(forward) && rc.onTheMap(options[i])){ //checks this option to be: not current position, traversable, and on the map
for(int j = 0; j < rights.length && !isRight; j++){ //as long as we're not sure it's right, loop through "left" directions and see if any are walls (rubble > 100)
if(rc.senseRubble(options[i].add(rights[j])) > 100 && !last.contains(options[i])){ //right only if we haven't visited it recently, and there is rubble > 100 on "left"
isRight = true;
Expand Down Expand Up @@ -1332,7 +1442,7 @@ public ArrayList<MapLocation> getAllLeftCanditates(){
int forwardInt = RESOURCE_FUNCTIONS.dirToInt(forward); //Only perform this once, for optimization
//Next line is long. Gets an array of all directions considered "right" relative to @forward
Direction[] lefts = new Direction[]{RESOURCE_FUNCTIONS.intToDir((forwardInt + 1) % 8),RESOURCE_FUNCTIONS.intToDir((forwardInt + 2) % 8),RESOURCE_FUNCTIONS.intToDir((forwardInt + 3) % 8)};
if(rc.senseRubble(options[i]) < 100 && rc.onTheMap(options[i]) && !branchPoint.equals(options[i])){ //checks this option to be: not current position, traversable, and on the map
if(rc.canMove(forward) && rc.onTheMap(options[i]) && !branchPoint.equals(options[i])){ //checks this option to be: not current position, traversable, and on the map
for(int j = 0; j < lefts.length && !isLeft; j++){ //as long as we're not sure it's left, loop through "right" directions and see if any are walls (rubble > 100)
if(rc.senseRubble(options[i].add(lefts[j])) > 100&& !last.contains(options[i])){ //left only if we haven't visited it recently, and there is rubble > 100 on "right"
isLeft = true;
Expand Down