diff --git a/java/src/v3/Constants.java b/java/src/v3/Constants.java index 401f0c7..97257cf 100644 --- a/java/src/v3/Constants.java +++ b/java/src/v3/Constants.java @@ -27,7 +27,7 @@ public class Constants { entry(PaintType.ENEMY_SECONDARY, -2) ); public static final Random rng = new Random(3407); - public static final double PERCENT_COIN = 0.35; + public static final double PERCENT_COIN = 0.45; public static final int RESIGN_AFTER = 2005; public static final int lowPaintThreshold = 20; public static final double INIT_PROBABILITY_DEVELOP = 60; @@ -36,9 +36,11 @@ public class Constants { public static final double DEVELOP_BOT_PROB_SCALING = 200; public static final double DEFENSE_RANGE = 0.3; public static final double SRP_DEV_BOT_SPLIT = 0.25; - public static final int DEV_LIFE_CYCLE_TURNS = 150; - public static final int SRP_LIFE_CYCLE_TURNS = 100; - public static final int ADV_LIFE_CYCLE_TURNS = 50; + + public static final int DEV_LIFE_CYCLE_TURNS = 30; + public static final int SRP_LIFE_CYCLE_TURNS = 50; + public static final int MIN_PAINT_GIVE = 50; + public static final Set primarySRP = Set.of(new HashableCoords(2,0), new HashableCoords(1,1),new HashableCoords(2,1),new HashableCoords(3,1), diff --git a/java/src/v3/Helper.java b/java/src/v3/Helper.java index f636e00..ddc95d9 100644 --- a/java/src/v3/Helper.java +++ b/java/src/v3/Helper.java @@ -32,4 +32,18 @@ public static void tryCompleteResourcePattern(RobotController rc) throws GameAct } } } + /** + * Check if a MapLocation m is in the rectangle with c1 and c2 as its corners + */ + public static boolean isBetween(MapLocation m, MapLocation c1, MapLocation c2) { + // Determine the min and max bounds for x and y coordinates + int minX = Math.min(c1.x, c2.x); + int maxX = Math.max(c1.x, c2.x); + int minY = Math.min(c1.y, c2.y); + int maxY = Math.max(c1.y, c2.y); + + // Check if m is within these bounds + return m.x >= minX && m.x <= maxX && m.y >= minY && m.y <= maxY; + } + } diff --git a/java/src/v3/Mopper.java b/java/src/v3/Mopper.java index e8f1743..391cabb 100644 --- a/java/src/v3/Mopper.java +++ b/java/src/v3/Mopper.java @@ -14,13 +14,13 @@ public static void receiveLastMessage(RobotController rc) throws GameActionExcep } if (Communication.isRobotInfo(bytes)) { RobotInfo message = RobotInfoCodec.decode(bytes); - continue; } else { MapInfo message = MapInfoCodec.decode(bytes); if (message.getPaint().isEnemy()) { MapLocation robotLoc = rc.getLocation(); if (RobotPlayer.removePaint == null || robotLoc.distanceSquaredTo(message.getMapLocation()) < robotLoc.distanceSquaredTo(removePaint.getMapLocation())){ removePaint = message; + Robot.resetVariables(); } } // If enemy tower, then go to enemy tower location @@ -28,6 +28,7 @@ else if (message.hasRuin()) { MapLocation robotLoc = rc.getLocation(); if (removePaint == null || robotLoc.distanceSquaredTo(message.getMapLocation()) < robotLoc.distanceSquaredTo(removePaint.getMapLocation())){ removePaint = message; + Robot.resetVariables(); } } } @@ -39,6 +40,7 @@ public static void removePaint(RobotController rc, MapInfo enemyPaint) throws Ga if (rc.canAttack(enemyLoc) && enemyPaint.getPaint().isEnemy()){ rc.attack(enemyLoc); removePaint = null; + Robot.resetVariables(); } else { Direction moveDir = Pathfinding.pathfind(rc, enemyLoc); diff --git a/java/src/v3/Pathfinding.java b/java/src/v3/Pathfinding.java index ccfafbb..9ab40a3 100644 --- a/java/src/v3/Pathfinding.java +++ b/java/src/v3/Pathfinding.java @@ -196,8 +196,8 @@ public static Direction exploreUnpainted(RobotController rc) throws GameActionEx /** * How we choose exploration weights: * Check each of the 8 blocks around the robot - * +2 if block is closer to target than starting point - * +1 if block is equidistant to target than starting point + * +5 if block is closer to target than starting point + * +3 if block is equidistant to target than starting point * For each block, check the 3x3 area centered at that block * +1 for each unpainted tile (including ruins) * -4 for each tile with an ally robot (including towers) @@ -222,9 +222,9 @@ public static Direction betterExplore(RobotController rc, MapLocation curLocatio score = Sensing.scoreTile(rc, possibleTarget); int newDistance = possibleTarget.distanceSquaredTo(target); if (curDistance > newDistance) { - score += 2; + score += 5; } else if (curDistance == newDistance) { - score += 1; + score += 3; } } if (minScore == -1 || score < minScore) { @@ -309,6 +309,59 @@ public static Direction getUnstuck(RobotController rc) throws GameActionExceptio return pathfind(rc, oppositeCorner); } } + /** + * bug(?) pathfinding algorithm + */ + public static Direction bugidk(RobotController rc, MapLocation target) throws GameActionException { + if (!isTracing){ + //proceed as normal + Direction dir = rc.getLocation().directionTo(target); + if(rc.canMove(dir)){ + return dir; + } else { + if (rc.canSenseRobotAtLocation(rc.getLocation().add(dir))) { + if (Constants.rng.nextDouble() >= 0.8) { + //treat robot as passable 20% of the time + return null; + } + } + isTracing = true; + tracingDir = dir; + stoppedLocation = rc.getLocation(); + tracingTurns = 0; + } + } else { + if ((Helper.isBetween(rc.getLocation(), stoppedLocation, target) && tracingTurns != 0) + || tracingTurns > 2*(rc.getMapWidth() + rc.getMapHeight())) { + Soldier.resetVariables(); + } else { + // go along perimeter of obstacle + if(rc.canMove(tracingDir)){ + //move forward and try to turn right + Direction returnDir = tracingDir; + tracingDir = tracingDir.rotateRight(); + tracingDir = tracingDir.rotateRight(); + tracingTurns++; + return returnDir; + } + else{ + // turn left because we cannot proceed forward + // keep turning left until we can move again + for (int i=0; i<8; i++){ + tracingDir = tracingDir.rotateLeft(); + if(rc.canMove(tracingDir)){ + Direction returnDir = tracingDir; + tracingDir = tracingDir.rotateRight(); + tracingDir = tracingDir.rotateRight(); + tracingTurns++; + return returnDir; + } + } + } + } + } + return null; + } /** * bug1 pathfinding algorithm @@ -369,6 +422,7 @@ public static Direction bug1(RobotController rc, MapLocation target) throws Game } public static Direction pathfind(RobotController rc, MapLocation target) throws GameActionException{ + MapLocation curLocation = rc.getLocation(); int dist = curLocation.distanceSquaredTo(target); if (dist == 0){ @@ -387,6 +441,8 @@ public static Direction pathfind(RobotController rc, MapLocation target) throws } else { return bug1(rc, target); } + + //return bugidk(rc, target); } public static Direction randomPaintedWalk(RobotController rc) throws GameActionException{ diff --git a/java/src/v3/Robot.java b/java/src/v3/Robot.java index 4e329d1..c9ca9ca 100644 --- a/java/src/v3/Robot.java +++ b/java/src/v3/Robot.java @@ -25,6 +25,12 @@ public static void lowPaintBehavior(RobotController rc) throws GameActionExcepti MapLocation towerLocation = lastTower.getMapLocation(); Robot.completeRuinIfPossible(rc, towerLocation); int amtToTransfer = rc.getPaint()-rc.getType().paintCapacity; + if (rc.canSenseRobotAtLocation(towerLocation)){ + int towerPaint = rc.senseRobotAtLocation(towerLocation).paintAmount; + if (rc.getPaint() < 5 && rc.canTransferPaint(towerLocation, -towerPaint) && towerPaint > Constants.MIN_PAINT_GIVE){ + rc.transferPaint(towerLocation, -towerPaint); + } + } if (rc.canTransferPaint(towerLocation, amtToTransfer)) { rc.transferPaint(towerLocation, amtToTransfer); } @@ -131,7 +137,7 @@ public static void completeRuinIfPossible(RobotController rc, MapLocation ruinLo } } /** - * Resets bug1 variables + * Resets pathfinding variables * Meant to be called when the robot has found else to do */ public static void resetVariables() { @@ -142,6 +148,7 @@ public static void resetVariables() { stuckTurnCount = 0; closestPath = -1; fillTowerType = null; - numTurnsStuck = 0; + stoppedLocation = null; + tracingTurns = 0; } } diff --git a/java/src/v3/RobotPlayer.java b/java/src/v3/RobotPlayer.java index ef4c532..f1bfa1e 100644 --- a/java/src/v3/RobotPlayer.java +++ b/java/src/v3/RobotPlayer.java @@ -3,6 +3,7 @@ import battlecode.common.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import scala.collection.Map; import java.util.*; @@ -60,7 +61,7 @@ public class RobotPlayer { static MapInfo fillEmpty = null; static int soldierMsgCooldown = -1; - static int numTurnsStuck = 0; + static int numTurnsAlive = 0; // Variable keeping track of how many turns alive for the soldier lifecycle // Key Soldier Location variables static MapInfo enemyTile = null; // location of an enemy paint/tower for a develop/advance robot to report @@ -91,11 +92,13 @@ public class RobotPlayer { static boolean alertRobots = false; static boolean alertAttackSoldiers = false; - // Bug 1 Variables + // BugNav Variables static boolean isTracing = false; static int smallestDistance = 10000000; static MapLocation closestLocation = null; static Direction tracingDir = null; + static MapLocation stoppedLocation = null; + static int tracingTurns = 0; /** * run() is the method that is called when a robot is instantiated in the Battlecode world. @@ -115,6 +118,7 @@ public static void run(RobotController rc) throws GameActionException { // loop. If we ever leave this loop and return from run(), the robot dies! At the end of the // loop, we call Clock.yield(), signifying that we've done everything we want to do. turnCount += 1; // We have now been alive for one more turn! + numTurnsAlive++; if (turnCount == Constants.RESIGN_AFTER) { rc.resign(); } @@ -225,7 +229,7 @@ else if (!spawnQueue.isEmpty() && rc.getMoney() > 400 && rc.getPaint() > 300){ } } - else if (rc.getMoney() > 1200 && rc.getPaint() > 400) { + else if (rc.getMoney() > 1200 && rc.getPaint() > 400 && spawnQueue.size() < 3) { Tower.buildCompletelyRandom(rc); } } @@ -294,8 +298,7 @@ public static void runSoldier(RobotController rc) throws GameActionException { switch (soldierType) { case SoldierType.BINLADEN: { - RobotInfo[] nearbyRobots = rc.senseNearbyRobots(-1, rc.getTeam().opponent()); - if (rc.getRoundNum() >= (rc.getMapHeight() + rc.getMapWidth())/2 || nearbyRobots.length != 0) { + if (rc.getRoundNum() >= (rc.getMapHeight() + rc.getMapWidth())/2) { soldierType = SoldierType.ADVANCE; return; } @@ -346,8 +349,11 @@ public static void runSoldier(RobotController rc) throws GameActionException { case SoldierType.DEVELOP: { Soldier.updateState(rc, initLocation, nearbyTiles); Helper.tryCompleteResourcePattern(rc); - // after being alive for long enough, cycles into SRP bot if stuck - if (turnCount > Constants.DEV_LIFE_CYCLE_TURNS && SoldierState.STUCK == soldierState) { + + if (numTurnsAlive > Constants.DEV_LIFE_CYCLE_TURNS && soldierState == SoldierState.STUCK) { + numTurnsAlive = 0; + soldierState = SoldierState.FILLINGSRP; + soldierType = SoldierType.SRP; Soldier.resetVariables(); } @@ -387,8 +393,6 @@ public static void runSoldier(RobotController rc) throws GameActionException { if (Sensing.findPaintableTile(rc, rc.getLocation(), 20) != null) { soldierState = SoldierState.EXPLORING; Soldier.resetVariables(); - } else { - numTurnsStuck++; } break; } @@ -399,11 +403,6 @@ public static void runSoldier(RobotController rc) throws GameActionException { case SoldierType.ADVANCE: { Soldier.updateState(rc, initLocation, nearbyTiles); - // lifecycle moves to SRP - if (numTurnsStuck > Constants.ADV_LIFE_CYCLE_TURNS){ - soldierType = SoldierType.SRP; - Soldier.resetVariables(); - } switch (soldierState) { case SoldierState.LOWONPAINT: { rc.setIndicatorString("LOWONPAINT"); @@ -440,7 +439,6 @@ public static void runSoldier(RobotController rc) throws GameActionException { } case SoldierState.STUCK: { rc.setIndicatorString("STUCK"); - numTurnsStuck++; Soldier.stuckBehavior(rc); } @@ -496,9 +494,10 @@ public static void runSoldier(RobotController rc) throws GameActionException { Soldier.updateSRPState(rc, initLocation, nearbyTiles); Helper.tryCompleteResourcePattern(rc); // if stuck for too long, become attack bot - if (numTurnsStuck > Constants.SRP_LIFE_CYCLE_TURNS){ + if (numTurnsAlive > Constants.SRP_LIFE_CYCLE_TURNS && soldierState == SoldierState.STUCK){ soldierType = SoldierType.ADVANCE; soldierState = SoldierState.EXPLORING; + numTurnsAlive = 0; Soldier.resetVariables(); } switch (soldierState) { @@ -538,13 +537,12 @@ public static void runSoldier(RobotController rc) throws GameActionException { } case SoldierState.STUCK: { rc.setIndicatorString("STUCK"); - numTurnsStuck++; Soldier.stuckBehavior(rc); for (MapInfo map: nearbyTiles) { if (map.getPaint().isAlly() && !map.getPaint().equals(Helper.resourcePatternType(rc, map.getMapLocation()))){ Soldier.resetVariables(); soldierState = SoldierState.FILLINGSRP; - numTurnsStuck = 0; + numTurnsAlive = 0; break; } } diff --git a/java/src/v3/Soldier.java b/java/src/v3/Soldier.java index 351a769..22c2ccf 100644 --- a/java/src/v3/Soldier.java +++ b/java/src/v3/Soldier.java @@ -82,10 +82,8 @@ public static void readNewMessages(RobotController rc) throws GameActionExceptio enemyTower = tile; soldierType = SoldierType.ATTACK; Soldier.resetVariables(); - } else { - wanderTarget = tile.getMapLocation(); } - + wanderTarget = tile.getMapLocation(); } } } @@ -168,13 +166,10 @@ public static void updateStateOsama(RobotController rc, MapLocation curLocation, } } else if (soldierState != SoldierState.DELIVERINGMESSAGE && soldierState != SoldierState.LOWONPAINT) { // Update enemy towers as necessary - enemyTower = updateEnemyTowers(rc, nearbyTiles); - if (enemyTower != null) { - intermediateTarget = null; + enemyTile = updateEnemyTowers(rc, nearbyTiles); + if (enemyTile != null) { + soldierType = SoldierType.ADVANCE; Soldier.resetVariables(); - storedState = soldierState; - soldierState = SoldierState.DELIVERINGMESSAGE; - return; } if (soldierState != SoldierState.FILLINGTOWER) { MapInfo bestRuin = Sensing.findBestRuin(rc, curLocation, nearbyTiles); @@ -208,7 +203,6 @@ public static void updateSRPState(RobotController rc, MapLocation curLocation, M if (map.getPaint().isAlly() && !map.getPaint().equals(Helper.resourcePatternType(rc, map.getMapLocation()))){ Soldier.resetVariables(); soldierState = SoldierState.FILLINGSRP; - numTurnsStuck = 0; } } } @@ -230,6 +224,7 @@ public static void msgTower(RobotController rc) throws GameActionException { soldierState = SoldierState.STUCK; } Soldier.resetVariables(); + return; } Direction dir = Pathfinding.returnToTower(rc); if (dir != null){ @@ -282,7 +277,7 @@ public static void fillInRuin(RobotController rc, MapLocation ruinLocation) thro rc.attack(tile, ruinPattern[tileToPaint[0]+2][tileToPaint[1]+2] == PaintType.ALLY_SECONDARY); } // Move to the ruin - Direction moveDir = Pathfinding.originalPathfind(rc, ruinLocation); + Direction moveDir = Pathfinding.pathfind(rc, ruinLocation); if (moveDir != null) { rc.move(moveDir); } @@ -326,7 +321,7 @@ else if (rc.canMark(northTower) && towerType != UnitType.LEVEL_ONE_DEFENSE_TOWER } // Otherwise, pathfind towards location until can mark it else{ - Direction moveDir = Pathfinding.originalPathfind(rc, ruinLocation); + Direction moveDir = Pathfinding.pathfind(rc, ruinLocation); if (moveDir != null) { rc.move(moveDir); } @@ -335,7 +330,7 @@ else if (rc.canMark(northTower) && towerType != UnitType.LEVEL_ONE_DEFENSE_TOWER } // Otherwise, pathfind to ruin location since we can't sense the location of the ruin else{ - Direction moveDir = Pathfinding.originalPathfind(rc, ruinLocation); + Direction moveDir = Pathfinding.pathfind(rc, ruinLocation); if (moveDir != null) { rc.move(moveDir); } @@ -348,7 +343,7 @@ else if (rc.canMark(northTower) && towerType != UnitType.LEVEL_ONE_DEFENSE_TOWER } // Otherwise, pathfind to the tower else{ - Direction moveDir = Pathfinding.originalPathfind(rc, ruinLocation); + Direction moveDir = Pathfinding.pathfind(rc, ruinLocation); if (moveDir != null) { rc.move(moveDir); } diff --git a/java/src/v3/Splasher.java b/java/src/v3/Splasher.java index f49e980..40b9680 100644 --- a/java/src/v3/Splasher.java +++ b/java/src/v3/Splasher.java @@ -22,12 +22,14 @@ public static void receiveLastMessage(RobotController rc) throws GameActionExcep MapLocation robotLoc = rc.getLocation(); if (removePaint == null || robotLoc.distanceSquaredTo(message.getMapLocation()) < robotLoc.distanceSquaredTo(removePaint.getMapLocation())){ removePaint = message; + Robot.resetVariables(); } } // If enemy tower, then go to enemy tower location else if (message.hasRuin()) { if (removePaint == null){ removePaint = message; + Robot.resetVariables(); } } } diff --git a/java/src/v3/Tower.java b/java/src/v3/Tower.java index 9902780..cacef59 100644 --- a/java/src/v3/Tower.java +++ b/java/src/v3/Tower.java @@ -52,8 +52,12 @@ else if (msg.getPaint().isEnemy()){ // towers. Additionally, spawn a splasher and a mopper if (Sensing.isRobot(rc, message.getSenderID())){ broadcast = true; - spawnQueue.add(4); // Spawns a splasher - spawnQueue.add(3); // Spawns a mopper + if (Constants.rng.nextDouble() <= 0.5) { + spawnQueue.add(4); // Spawns a splasher + } else { + + spawnQueue.add(3); // Spawns a mopper + } numEnemyVisits += 1; // Increases probability of spawning a splasher }