public static void Main(string[] args) { Console.SetIn(Console.In); Console.SetOut(Console.Out); var map = Networking.getInit(out _MyID); DarrekLog.LogFileName = String.Format("log{0}.txt", _MyID); const ushort MAX_STRENGTH = 255; const ushort HALF_STRENGTH = 128; /* ------ * Do more prep work, see rules for time limit * ------ */ Networking.SendInit(MyBotName); // Acknoweldge the init and begin the game var random = new Random(); DarrekLog.AppendLog("Starting battle!"); int frameNumber = 0; var movesTowardHighProductionByDirection = new Dictionary <Direction, ushort>(); movesTowardHighProductionByDirection.Add(Direction.North, 0); movesTowardHighProductionByDirection.Add(Direction.South, 0); movesTowardHighProductionByDirection.Add(Direction.East, 0); movesTowardHighProductionByDirection.Add(Direction.West, 0); while (true) { //try //{ Networking.getFrame(ref map); // Update the map to reflect the moves before this turn //} //catch (Exception) //{ // return; //} #region Check Production if (frameNumber == 0) { var sb = new StringBuilder(); sb.Append("production values:"); //TODO: find nearest high production zone and head there. for (ushort y = 0; y < map.Height; y++) { sb.Append("\r\n"); for (ushort x = 0; x < map.Width; x++) { var prodVal = map[x, y].Production; sb.Append(prodVal + " "); if (_MaxProductionValue < prodVal) { _MaxProductionValue = prodVal; } } } DarrekLog.AppendLog(sb.ToString()); _TopProductionValuesGreaterThan = (ushort)(_MaxProductionValue * .70); DarrekLog.AppendLog(string.Format("Max Production Value Found = {0}", _MaxProductionValue)); DarrekLog.AppendLog(string.Format("Top Production Values >= {0}", _TopProductionValuesGreaterThan)); } #endregion frameNumber++; DarrekLog.AppendLog(string.Format("Frame {0}", frameNumber)); movesTowardHighProductionByDirection[Direction.North] = 0; movesTowardHighProductionByDirection[Direction.South] = 0; movesTowardHighProductionByDirection[Direction.East] = 0; movesTowardHighProductionByDirection[Direction.West] = 0; var moves = new List <Move>(); for (ushort x = 0; x < map.Width; x++) { for (ushort y = 0; y < map.Height; y++) { if (map[x, y].Owner == _MyID) { var activeSite = new SiteEx(map, x, y); if (activeSite.Strength < MAX_STRENGTH / 10) { continue; } var neighbors = new List <SiteEx>() { GetNeighbor(map, activeSite, Direction.West), GetNeighbor(map, activeSite, Direction.East), GetNeighbor(map, activeSite, Direction.North), GetNeighbor(map, activeSite, Direction.South) }; var friendlySites = neighbors.Where(c => c.Owner == _MyID); var neutralNeighbors = neighbors.Where(c => c.Owner == 0); var potentialLunchSites = neighbors.Where(c => c.Strength < activeSite.Strength && c.Owner == 0); //1. Try to grow if (potentialLunchSites.Any()) { if (neutralNeighbors.Count() >= 3 || potentialLunchSites.Count() > 1) { var directionToMove = GetNearestFreeHighProductionDirection(map, activeSite); movesTowardHighProductionByDirection[directionToMove]++; if (GetNeighbor(map, activeSite, directionToMove).Strength < activeSite.Strength) { moves.Add(new Move { Location = activeSite.Location, Direction = directionToMove }); } } else { var lunchSite = potentialLunchSites.OrderByDescending(s => s.Production).First(); var directionToMove = GetMoveDirection(map, activeSite, lunchSite); moves.Add(new Move { Location = activeSite.Location, Direction = directionToMove }); continue; } } //2. If all neighbors are friendly, move where most of the blob is moving (toward high production) if (friendlySites.Count() == neighbors.Count && ((activeSite.Strength >= (activeSite.Production * 5)) || activeSite.Strength > HALF_STRENGTH)) { ushort distanceFromEdge; var nearestNonPlayerDirection = GetNearestNonPlayerDirection(map, activeSite, _MyID, out distanceFromEdge); if (movesTowardHighProductionByDirection.All(m => m.Value == 0) || distanceFromEdge > 3) { if (nearestNonPlayerDirection != Direction.Still) { moves.Add(new Move { Location = activeSite.Location, Direction = nearestNonPlayerDirection }); } else //All orthagonal directions are occupied. { //TODO: could have logic here to find enemies or something, or go diagonally. } } else { var blobMoveDirection = movesTowardHighProductionByDirection.First(m => m.Value == movesTowardHighProductionByDirection.Max(n => n.Value)).Key; DarrekLog.AppendLog(string.Format("Moving with blob to the {0}", blobMoveDirection)); moves.Add(new Move { Location = activeSite.Location, Direction = blobMoveDirection }); } } } } } Networking.SendMoves(moves); // Send moves } }
private static Direction GetNearestFreeHighProductionDirection(Map map, SiteEx activeSite) //TODO: This needs to take into account the allowed directions. { //DarrekLog.AppendLog(string.Format("GetNearestFreeHighProductionDirection... Active site is [{0},{1}]", activeSite.X, activeSite.Y)); for (ushort distanceFromOrigin = 1; distanceFromOrigin < map.Width / 2; distanceFromOrigin++) { //DarrekLog.AppendLog("Distance 1..."); //make a square around the origin. for (var x = distanceFromOrigin * -1; x <= distanceFromOrigin; x++) { for (var y = distanceFromOrigin * -1; y <= distanceFromOrigin; y++) { if ((Math.Abs(y) != distanceFromOrigin) && (Math.Abs(x) != distanceFromOrigin)) { continue; // don't need to check this space again } //DarrekLog.AppendLog("Relative: " + x + ", " + y); var mapX = (ushort)((((int)activeSite.X) + x + map.Width) % map.Width); var mapY = (ushort)((((int)activeSite.Y) + y + map.Height) % map.Height); //DarrekLog.AppendLog(string.Format("Checking map[{0},{1}]...", mapX, mapY)); var toCheck = map[mapX, mapY]; if (toCheck.Owner != _MyID)// == 0) { //DarrekLog.AppendLog("Found neutral production area!"); if (toCheck.Production >= _TopProductionValuesGreaterThan) { DarrekLog.AppendLog(string.Format("Found acceptable neutral production area at [{1},{2}], value = {0}", toCheck.Production, mapX, mapY)); if (Math.Abs(x) <= Math.Abs(y)) { //DarrekLog.AppendLog("Moving Horizontally towards high production area"); if (x < 0) { DarrekLog.AppendLog("Heading West to HPA"); return(Direction.West); } else if (x > 0) { DarrekLog.AppendLog("Heading East to HPA"); return(Direction.East); } } else if (Math.Abs(x) > Math.Abs(y)) { //DarrekLog.AppendLog("Moving Vertically towards high production area"); if (y < 0) { DarrekLog.AppendLog("Heading North to HPA"); return(Direction.North); } else if (y > 0) { DarrekLog.AppendLog("Heading South to HPA"); return(Direction.South); } } else { DarrekLog.AppendLog("dammit!"); return(Direction.Still); } } } } } } return(Direction.Still); }
public static void Main(string[] args) { Console.SetIn(Console.In); Console.SetOut(Console.Out); var map = Networking.getInit(out _MyID); DarrekLog.LogFileName = String.Format("log{0}.txt", _MyID); const ushort MAX_STRENGTH = 255; const ushort HALF_STRENGTH = 128; /* ------ * Do more prep work, see rules for time limit * ------ */ Networking.SendInit(MyBotName); // Acknoweldge the init and begin the game var random = new Random(); DarrekLog.AppendLog("Starting battle!"); int frameNumber = 0; while (true) { try { Networking.getFrame(ref map); // Update the map to reflect the moves before this turn } catch (Exception) { return; } #region Check Production if (frameNumber == 0) { var sb = new StringBuilder(); sb.Append("production values:"); //TODO: find nearest high production zone and head there. for (ushort y = 0; y < map.Height; y++) { sb.Append("\r\n"); for (ushort x = 0; x < map.Width; x++) { var prodVal = map[x, y].Production; sb.Append(prodVal + " "); if (_MaxProductionValue < prodVal) { _MaxProductionValue = prodVal; } } } DarrekLog.AppendLog(sb.ToString()); _TopProductionValuesGreaterThan = (ushort)(_MaxProductionValue * .70); DarrekLog.AppendLog(string.Format("Max Production Value Found = {0}", _MaxProductionValue)); DarrekLog.AppendLog(string.Format("Top Production Values >= {0}", _TopProductionValuesGreaterThan)); } #endregion frameNumber++; DarrekLog.AppendLog(string.Format("Frame {0}", frameNumber)); var moves = new List <Move>(); for (ushort x = 0; x < map.Width; x++) { for (ushort y = 0; y < map.Height; y++) { if (map[x, y].Owner == _MyID) { var activeSite = new SiteEx(map, x, y); if ((activeSite.Strength < activeSite.Production * 3) && (activeSite.Strength < MAX_STRENGTH / 12)) { continue; } var neighbors = new List <SiteEx>() { GetNeighbor(map, activeSite, Direction.West), GetNeighbor(map, activeSite, Direction.East), GetNeighbor(map, activeSite, Direction.North), GetNeighbor(map, activeSite, Direction.South) }; var friendlySites = neighbors.Where(c => c.Owner == _MyID); var friendlySitesWorthVisiting = friendlySites.Where( f => f.Strength > 0 && f.Strength + activeSite.Strength <MAX_STRENGTH && f.Production> (_MaxProductionValue / 4)); var neutralNeighbors = neighbors.Where(c => c.Owner == 0); var weakNeighborSites = neighbors.Where(c => (activeSite.Strength == MAX_STRENGTH || c.Production > 0) && c.Strength < activeSite.Strength && c.Owner == 0); bool shouldCombine = false; if (!weakNeighborSites.Any()) { if (activeSite.X + activeSite.Y % 2 == 1) //Only combine from every other square to prevent dancing. { shouldCombine = true; } } //Combine forces if we are a thin line. if (shouldCombine && friendlySitesWorthVisiting.Any()) { var destination = friendlySitesWorthVisiting.FirstOrDefault(f => f.Production > activeSite.Production); if (destination != null) { var directionToMove = GetMoveDirection(map, activeSite, destination); DarrekLog.AppendLog("Combine Forces!"); moves.Add(new Move { Location = activeSite.Location, Direction = directionToMove }); continue; } } //1. Try to grow if (weakNeighborSites.Any()) { SiteEx lunchSiteToAttack = null; //Move Between enemies if possible for maximum damage! foreach (var pls in weakNeighborSites) { var nW = GetNeighbor(map, pls, Direction.West); var nE = GetNeighbor(map, pls, Direction.East); var nS = GetNeighbor(map, pls, Direction.South); var nN = GetNeighbor(map, pls, Direction.North); var enemyNeighborsCount = ((nW.Owner != _MyID && nW.Owner != 0) ? 1 : 0) + ((nE.Owner != _MyID && nE.Owner != 0) ? 1 : 0) + ((nS.Owner != _MyID && nS.Owner != 0) ? 1 : 0) + ((nN.Owner != _MyID && nN.Owner != 0) ? 1 : 0); if (enemyNeighborsCount > 1) { lunchSiteToAttack = pls; } } if (lunchSiteToAttack == null) { lunchSiteToAttack = weakNeighborSites.OrderByDescending(s => s.Production - s.Strength / 10).First(); } var directionToMove = GetMoveDirection(map, activeSite, lunchSiteToAttack); if (lunchSiteToAttack.Strength < activeSite.Strength) { moves.Add(new Move { Location = activeSite.Location, Direction = directionToMove }); continue; } } //2. If all neighbors are friendly, move towards nearest edge. else if (activeSite.Strength > 0 && friendlySites.Count() == neighbors.Count && ((activeSite.Strength >= (activeSite.Production * 3)) || activeSite.Strength > HALF_STRENGTH / 2)) { ushort distanceFromEdge; var nearestNonPlayerDirection = GetNearestNonPlayerDirection(map, activeSite, _MyID, out distanceFromEdge); if (nearestNonPlayerDirection != Direction.Still) { moves.Add(new Move { Location = activeSite.Location, Direction = nearestNonPlayerDirection }); } else //All orthagonal directions are occupied. { moves.Add(new Move { Location = activeSite.Location, Direction = x % 2 == 1 ? Direction.North : Direction.South }); //TODO: could have logic here to find enemies or something, or go diagonally. } } } } } Networking.SendMoves(moves); // Send moves } }