Advertisement
Guest User

Untitled

a guest
Apr 23rd, 2017
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 68.57 KB | None | 0 0
  1. using System;
  2. using System.Linq;
  3. using System.IO;
  4. using System.Text;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using System.Diagnostics;
  8.  
  9.  
  10. // rank 5
  11. /**
  12.  * Auto-generated code below aims at helping you parse
  13.  * the standard input according to the problem statement.
  14.  **/
  15. class CotC
  16. {
  17.     public static bool shootMines = false; //shoot near enemy
  18.     public static bool clearMines = false; //clear for myself
  19.     public static bool layMines = false; // lay mines
  20.  
  21.  
  22.     public static bool logging = true;
  23.     #region props
  24.     public static int width = 23;
  25.     public static int height = 21;
  26.     public static List<Rum> rum = new List<Rum>();
  27.     public static List<Ship> ships = new List<Ship>();
  28.     public static List<Cannonball> balls = new List<Cannonball>();
  29.     public static List<Mine> mines = new List<Mine>();
  30.  
  31.     public static int round = 0;
  32.  
  33.     private static int MAP_WIDTH = 23;
  34.     private static int MAP_HEIGHT = 21;
  35.     private static int COOLDOWN_CANNON = 2;
  36.     private static int COOLDOWN_MINE = 5;
  37.     private static int INITIAL_SHIP_HEALTH = 100;
  38.     private static int MAX_SHIP_HEALTH = 100;
  39.     private static int MAX_SHIP_SPEED;
  40.     private static int MIN_SHIPS = 1;
  41.     private static int MAX_SHIPS = 3;
  42.     private static int MIN_RUM_BARRELS = 10;
  43.     private static int MAX_RUM_BARRELS = 26;
  44.     private static int MIN_RUM_BARREL_VALUE = 10;
  45.     private static int MAX_RUM_BARREL_VALUE = 20;
  46.     private static int REWARD_RUM_BARREL_VALUE = 30;
  47.     private static int MINE_VISIBILITY_RANGE = 5;
  48.     private static int FIRE_DISTANCE_MAX = 10;
  49.     private static int LOW_DAMAGE = 25;
  50.     private static int HIGH_DAMAGE = 50;
  51.     private static int MINE_DAMAGE = 25;
  52.     private static int NEAR_MINE_DAMAGE = 10;
  53.     private static bool CANNONS_ENABLED = true;
  54.     private static bool MINES_ENABLED = true;
  55.  
  56.     #endregion props
  57.  
  58.     static void Main(string[] args)
  59.     {
  60.         //map = new int[width,height];
  61.         // game loop
  62.         Stopwatch watch = new Stopwatch();
  63.         while (true)
  64.         {
  65.  
  66.             watch.Start();
  67.             #region setup
  68.             round++;
  69.  
  70.             int myShipCount = int.Parse(Console.ReadLine()); // the number of remaining ships
  71.             int entityCount = int.Parse(Console.ReadLine()); // the number of entities (e.g. ships, mines or cannonballs)
  72.  
  73.             rum = new List<Rum>();
  74.             List<Ship> currentShips = new List<Ship>();
  75.             balls = new List<Cannonball>();
  76.             mines = new List<Mine>();
  77.  
  78.             for (int i = 0; i < entityCount; i++)
  79.             {
  80.                 string[] inputs = Console.ReadLine().Split(' ');
  81.                 int entityId = int.Parse(inputs[0]);
  82.                 string entityType = inputs[1];
  83.                 int x = int.Parse(inputs[2]);
  84.                 int y = int.Parse(inputs[3]);
  85.                 int arg1 = int.Parse(inputs[4]);
  86.                 int arg2 = int.Parse(inputs[5]);
  87.                 int arg3 = int.Parse(inputs[6]);
  88.                 int arg4 = int.Parse(inputs[7]);
  89.  
  90.                 switch (entityType)
  91.                 {
  92.                     case "BARREL":
  93.                         var tempRum = new Rum()
  94.                         {
  95.                             x = x,
  96.                             y = y,
  97.                             id = entityId,
  98.                             type = entityType,
  99.                             rum = arg1,
  100.  
  101.                         };
  102.                         rum.Add(tempRum);
  103.                         break;
  104.                     case "SHIP":
  105.                         var oldShip = ships.FirstOrDefault(a => a.id == entityId);
  106.                         if (oldShip != null)
  107.                         {
  108.                             oldShip.x = x;
  109.                             oldShip.y = y;
  110.                             oldShip.id = entityId;
  111.                             oldShip.type = entityType;
  112.                             oldShip.orientation = arg1;
  113.                             oldShip.speed = arg2;
  114.                             oldShip.rum = arg3;
  115.                             oldShip.owner = arg4;
  116.                             oldShip.cannonCooldown--;
  117.                             oldShip.mineCooldown--;
  118.                             currentShips.Add(oldShip);
  119.                         }
  120.                         else
  121.                         {
  122.                             var tempShip = new Ship()
  123.                             {
  124.                                 x = x,
  125.                                 y = y,
  126.                                 id = entityId,
  127.                                 type = entityType,
  128.                                 orientation = arg1,
  129.                                 speed = arg2,
  130.                                 rum = arg3,
  131.                                 owner = arg4,
  132.                                 layMines = layMines,
  133.                             };
  134.                             currentShips.Add(tempShip);
  135.                         }
  136.                         break;
  137.                     case "CANNONBALL":
  138.                         var tempBall = new Cannonball()
  139.                         {
  140.                             x = x,
  141.                             y = y,
  142.                             id = entityId,
  143.                             type = entityType,
  144.                             shipId = arg1,
  145.                             turns = arg2,
  146.                         };
  147.                         balls.Add(tempBall);
  148.                         break;
  149.                     case "MINE":
  150.                         var tempMine = new Mine()
  151.                         {
  152.                             x = x,
  153.                             y = y,
  154.                             id = entityId,
  155.                             type = entityType,
  156.                         };
  157.                         mines.Add(tempMine);
  158.                         break;
  159.                 }
  160.             }//end for
  161.  
  162.             ships.Clear();
  163.             ships.AddRange(currentShips);
  164.             #endregion setup
  165.  
  166.             #region MAIN LOGIC
  167.             var myShips = ships.Where(a => a.owner == 1).ToArray();
  168.             //sim first round
  169.  
  170.             List<Ship> cloneShips = new List<Ship>();
  171.             foreach (var tShip in ships) { cloneShips.Add(tShip.Clone()); };
  172.             var myCloneShips = cloneShips.Where(a => a.owner == 1).ToArray();
  173.  
  174.             for (int i = 0; i < myCloneShips.Length; i++)
  175.             {
  176.                 var ship = myCloneShips[i];
  177.                 var goodActions = testActions(ship, cloneShips, rum, mines, balls);
  178.                 ship.priorities = goodActions;
  179.  
  180.                 myShips[i].priorities = goodActions;
  181.  
  182.                 ship.PerformAction(Action.WAIT, false);
  183.                 ship.TheoryMove(ship.action);
  184.             }
  185.  
  186.             for (int i = 0; i < myShipCount; i++)
  187.             {
  188.                 var ship = myShips[i];
  189.                 // Write an action using Console.WriteLine()
  190.                 // To debug: Console.Error.WriteLine("Debug messages...");
  191.                 Random rand = new Random();
  192.  
  193.  
  194.                 var enemies = ships.Where(a => a.owner == 0).OrderBy(b => b.DistFront(ship));
  195.                 var enemy = enemies.FirstOrDefault();
  196.                 var dist = enemy != null ? ship.DistFront(enemy) : 999;
  197.  
  198.                 bool dontFire = false;
  199.                 //dontFire = testFire(ship);
  200.  
  201.                 if (ship.rum + ship.priorities.Max(a => a.Value) <= 0)
  202.                 {
  203.                     log("will die regardless, GO OUT BLAZING");
  204.                     dontFire = false;
  205.                 }
  206.                 else
  207.                 {
  208.                     var fireScore = ship.priorities[Action.WAIT];
  209.                     if (ship.priorities.Max(a => a.Value) > fireScore + 4)
  210.                     {
  211.                         dontFire = true;
  212.                     }
  213.                 }
  214.  
  215.  
  216.                 var mineHit = mines.Where(a => myShips.Min(c => c.Dist(a)) > 4 && enemies.Min(c => c.Dist(a)) <= 4 && !balls.Any(b => b.x == a.x && b.y == a.y)).FirstOrDefault();
  217.                 var clearMine = mines.Where(a => myShips.Min(c => c.Dist(a)) > 4 && enemies.Min(c => c.Dist(a)) <= 4 && !balls.Any(b => b.x == a.x && b.y == a.y)).OrderBy(d => ship.DistFront(d)).FirstOrDefault();
  218.  
  219.                 rum = rum.OrderBy(a => ship.DistFront(a)).ToList();
  220.  
  221.  
  222.                 if (rum.Count() == 0 && ship.rum >= enemies.Max(c => c.rum) && enemies.Min(c => ship.Dist(c)) > 10)
  223.                 {
  224.                     EndGameStrat(ship);
  225.                 }
  226.                 else if (ship.cannonCooldown <= 0)
  227.                 {
  228.  
  229.                     var closeRum = rum.Where(a => ship.DistFront(a) > enemy.DistFront(a) && ship.DistFront(a) <= 10 && !balls.Any(b => b.Pos().Equals(a.Pos()))).FirstOrDefault();
  230.  
  231.                     if (!dontFire && closeRum != null
  232.                         && myShips.Min(a => a.DistFront(closeRum)) > enemies.Min(a => a.DistFront(closeRum)))
  233.                     {
  234.                         ship.Fire(closeRum);
  235.                         rum.Remove(closeRum);
  236.                         balls.Add(new Cannonball()
  237.                         {
  238.                             x = closeRum.x,
  239.                             y = closeRum.y,
  240.                             id = -1,
  241.                             turns = ship.shotDuration(new Coord(closeRum.x, closeRum.y)),
  242.                         });
  243.                         ship.cannonCooldown = 2;
  244.                     }
  245.                     else if (!dontFire && ship.Fire(enemy, ships, rum, balls))
  246.                     {
  247.                         balls.Add(new Cannonball()
  248.                         {
  249.                             x = ship.target.x,
  250.                             y = ship.target.y,
  251.                             turns = ship.shotDuration(ship.target),
  252.                         });
  253.                         ship.cannonCooldown = 2;
  254.                     }
  255.                     else if (shootMines && !dontFire && mineHit != null)
  256.                     {
  257.                         ship.Fire(mineHit);
  258.                         balls.Add(new Cannonball()
  259.                         {
  260.                             x = mineHit.x,
  261.                             y = mineHit.y,
  262.                             turns = ship.shotDuration(new Coord(mineHit.x, mineHit.y)),
  263.                         });
  264.                         ship.cannonCooldown = 2;
  265.                         continue;
  266.                     }
  267.                     else if (shootMines && !dontFire && clearMine != null)
  268.                     {
  269.                         ship.Fire(clearMine);
  270.                         balls.Add(new Cannonball()
  271.                         {
  272.                             x = clearMine.x,
  273.                             y = clearMine.y,
  274.                             turns = ship.shotDuration(new Coord(clearMine.x, clearMine.y)),
  275.                         });
  276.                         ship.cannonCooldown = 2;
  277.                         continue;
  278.                     }
  279.                     else
  280.                     {
  281.                         var closeRumNotTargeted = rum.FirstOrDefault(a => ship.DistFront(a) <= enemy.DistFront(a) && !balls.Any(b => b.Pos().equals(a.Pos())));
  282.                         if (closeRumNotTargeted != null)
  283.                         {
  284.                             ship.Move(closeRumNotTargeted);
  285.                             rum.Remove(closeRumNotTargeted);
  286.                         }
  287.                         else
  288.                         {
  289.                             EndGameStrat(ship);
  290.                         }
  291.                     }
  292.  
  293.                 }
  294.                 else if (rum.Count > 0)
  295.                 {
  296.  
  297.                     var target = rum.FirstOrDefault(a => !balls.Any(b => b.x == a.x && b.y == a.y));
  298.  
  299.                     if (target != null && target.rum + ship.rum > 100 && target.Dist(ship) < 2 && !ship.BallsWillHit(balls))
  300.                     {
  301.                         if (ship.speed > 0)
  302.                         {
  303.                             ship.Slower();
  304.                         }
  305.                         else
  306.                         {
  307.                             ship.Wait();
  308.                         }
  309.                     }
  310.                     else if (target != null)
  311.                     {
  312.                         ship.Move(target.x, target.y);
  313.                         rum.Remove(target);
  314.                     }
  315.                     else
  316.                     {
  317.                         EndGameStrat(ship);
  318.                     }
  319.                 }
  320.                 else
  321.                 {
  322.                     EndGameStrat(ship);
  323.                 }
  324.             }//end for
  325.             #endregion MAIN LOGIC
  326.  
  327.             watch.Stop();
  328.             log(watch.ElapsedMilliseconds + "ms");
  329.             watch.Reset();
  330.         }//end while
  331.     }
  332.     #region print/log
  333.     public static double GetDistance(int x1, int y1, int x2, int y2)
  334.     {
  335.         return Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2));
  336.     }
  337.  
  338.     public static bool testFire(Ship ship)
  339.     {
  340.         if (ship.cannonCooldown > 0)
  341.         {
  342.             return true;
  343.         }
  344.  
  345.         Ship tempShip = ship.Clone();
  346.  
  347.         if (tempShip.speed == 2)
  348.         {
  349.             tempShip.TheoryMove(Action.FIRE);
  350.             tempShip.TheoryMove(Action.SLOWER);
  351.         }
  352.         else
  353.         {
  354.             tempShip.TheoryMove(Action.FIRE);
  355.             tempShip.TheoryMove(Action.WAIT);
  356.         }
  357.  
  358.         var front = tempShip.GetFront();
  359.         var back = tempShip.GetBack();
  360.         var middle = tempShip.GetMiddle();
  361.  
  362.         bool mineHits = mines.Any(a => a.Pos().equals(front) || a.Pos().equals(middle) || a.Pos().equals(back));
  363.         bool cannonHits = balls.Any(a => a.Pos().equals(front) || a.Pos().equals(middle) || a.Pos().equals(back));
  364.  
  365.         if (mineHits || cannonHits)
  366.             log("dont fire " + (mineHits || cannonHits));
  367.         return mineHits || cannonHits;
  368.     }
  369.  
  370.     public static Dictionary<Action, int> testActions(Ship ship, List<Ship> shipsOld, List<Rum> rumOld, List<Mine> minesOld, List<Cannonball> ballsOld)
  371.     {
  372.         var results = new Dictionary<Action, int>();
  373.         var actions = new List<Action>() { Action.WAIT, Action.PORT, Action.STARBOARD, Action.SLOWER, Action.FASTER };
  374.  
  375.         //repeat this for each depth
  376.         foreach (var act in actions)
  377.         {
  378.             bool performSim = true;
  379.  
  380.             //reset variables per action
  381.             List<Ship> ships = new List<Ship>();
  382.             foreach (var tShip in shipsOld) { ships.Add(tShip.Clone()); };
  383.             List<Rum> rum = new List<Rum>();
  384.             foreach (var tRum in rumOld) { rum.Add(tRum.Clone()); };
  385.             List<Mine> mines = new List<Mine>();
  386.             foreach (var tMine in minesOld) { mines.Add(tMine.Clone()); };
  387.             List<Cannonball> balls = new List<Cannonball>();
  388.             foreach (var tBall in ballsOld) { balls.Add(tBall.Clone()); };
  389.  
  390.             var score = 0;
  391.             Ship tempShip = ship.Clone();
  392.  
  393.             //prevent useless commands
  394.             if (ship.speed == 2 && act == Action.FASTER)
  395.             {
  396.                 score -= 2;
  397.             }
  398.             if (ship.speed == 0 && act == Action.SLOWER)
  399.             {
  400.                 score -= 2;
  401.             }
  402.  
  403.             if (ship.speed == 0)
  404.             {
  405.                 if (act == Action.WAIT)
  406.                     score -= 2;
  407.                 if (act == Action.FASTER)
  408.                     score += 2;
  409.             }
  410.  
  411.  
  412.             //front ship collides (in case i cant move)
  413.  
  414.             if (ships.Any(a => a.id != ship.id && a.GetFront().equals(tempShip.GetFront().neighbor(tempShip.orientation))) ||
  415.                 ships.Any(a => a.id != ship.id && a.GetMiddle().equals(tempShip.GetFront().neighbor(tempShip.orientation))) ||
  416.                 ships.Any(a => a.id != ship.id && a.GetBack().equals(tempShip.GetFront().neighbor(tempShip.orientation))))
  417.             {
  418.                 tempShip.speed = 0;
  419.                 if (act == Action.WAIT || act == Action.FASTER) { score -= 5; performSim = false; }
  420.             }
  421.             if (ships.Any(a => a.id != ship.id && a.GetFront().neighbor(a.orientation).equals(tempShip.GetFront().neighbor(tempShip.orientation)))
  422.                 && ((ship.speed == 2 && act != Action.SLOWER) || (ship.speed == 1 && act == Action.FASTER)))
  423.             {
  424.                 tempShip.speed = 0;
  425.                 if (act == Action.WAIT || act == Action.FASTER)
  426.                 {
  427.                     score -= 5; performSim = false;
  428.                 }
  429.             }
  430.  
  431.             if (!tempShip.GetFront().isInsideMap() && (act == Action.WAIT || act == Action.FASTER || act == Action.SLOWER))
  432.             {
  433.                 score -= 15;
  434.                 tempShip.speed = 0;
  435.                 performSim = false;
  436.             }
  437.  
  438.  
  439.             #region mines
  440.             var mine1 = mines.FirstOrDefault(a => a.Pos().equals(tempShip.GetFront().neighbor(ship.orientation)));
  441.             var mine2 = mines.FirstOrDefault(a => a.Pos().equals(tempShip.GetFront().neighbor(ship.orientation).neighbor(ship.orientation)));
  442.             var mine3 = mines.FirstOrDefault(a => a.Pos().equals(tempShip.GetFront().neighbor(ship.orientation).neighbor(ship.orientation).neighbor(ship.orientation)));
  443.  
  444.             //run into mines prior to turn
  445.             if ((tempShip.speed == 1 && act == Action.FASTER))
  446.             {
  447.                 if (mine1 != null)
  448.                 {
  449.                     score -= 25;
  450.                     mines.Remove(mine1);
  451.                 }
  452.                 if (mine2 != null)
  453.                 {
  454.                     score -= 25;
  455.                     mines.Remove(mine1);
  456.                 }
  457.                 if (mine3 != null)
  458.                 {
  459.                     score -= 25;
  460.                     mines.Remove(mine1);
  461.                 }
  462.             }
  463.             else if ((tempShip.speed == 1 && act != Action.SLOWER && act != Action.FASTER) || (tempShip.speed == 2 && act == Action.SLOWER) || (tempShip.speed == 0 && act == Action.FASTER))
  464.             {
  465.                 if (mine1 != null)
  466.                 {
  467.                     score -= 25;
  468.                     mines.Remove(mine1);
  469.                 }
  470.             }
  471.             else if (tempShip.speed == 1 && act == Action.SLOWER)
  472.             {
  473.                 if (mine1 != null)
  474.                 {//wont hit, but dont want to slow down
  475.                     score -= 5;
  476.                 }
  477.             }
  478.             else if (tempShip.speed == 2 && act != Action.SLOWER)
  479.             {
  480.                 if (mine1 != null)
  481.                 {
  482.                     score -= 25;
  483.                     mines.Remove(mine1);
  484.                 }
  485.                 if (mine2 != null)
  486.                 {
  487.                     score -= 25;
  488.                     mines.Remove(mine1);
  489.                 }
  490.                 if (mine3 != null)
  491.                 {
  492.                     score -= 25;
  493.                     mines.Remove(mine1);
  494.                 }
  495.             }
  496.             else if (tempShip.speed == 2 && act == Action.SLOWER)
  497.             {
  498.                 if (mine3 != null)
  499.                 {
  500.                     score -= 5;
  501.                 }
  502.             }
  503.            
  504.  
  505.             #endregion mines
  506.  
  507.  
  508.             if (performSim)
  509.             {
  510.                 tempShip.TheoryMove(act);
  511.             }
  512.             else
  513.             {
  514.                 log("skip sim");
  515.             }
  516.  
  517.  
  518.             //mines hit
  519.             var hitMine = mines.FirstOrDefault(a => a.Pos().equals(tempShip.GetFront()));
  520.             if (hitMine != null)
  521.             {
  522.                 score -= 25;
  523.                 mines.Remove(hitMine);
  524.             }
  525.             hitMine = mines.FirstOrDefault(a => a.Pos().equals(tempShip.GetMiddle()));
  526.             if (hitMine != null)
  527.             {
  528.                 score -= 25;
  529.                 mines.Remove(hitMine);
  530.             }
  531.             hitMine = mines.FirstOrDefault(a => a.Pos().equals(tempShip.GetBack()));
  532.             if (hitMine != null)
  533.             {
  534.                 score -= 25;
  535.                 mines.Remove(hitMine);
  536.             }
  537.  
  538.             //future hit
  539.             hitMine = mines.FirstOrDefault(a => a.Pos().equals(tempShip.GetFront().neighbor(tempShip.orientation)));
  540.             if (hitMine != null && tempShip.speed == 0)
  541.             {//wont hit, but stops movement
  542.                 score -= 6;
  543.             }
  544.  
  545.  
  546.             //run into mines prior to turn
  547.             hitMine = mines.FirstOrDefault(a => a.Pos().equals(tempShip.GetFront().neighbor(ship.orientation)));
  548.             if (hitMine != null && (tempShip.speed == 2 || (tempShip.speed == 1 && act != Action.SLOWER)))
  549.             {
  550.                 score -= 25;
  551.                 mines.Remove(hitMine);
  552.             }
  553.  
  554.  
  555.  
  556.             //balls hit
  557.             var tempBallsHit = balls.Where(a => a.Pos().equals(tempShip.GetFront()) && a.turns <= 2);
  558.             if (tempBallsHit.Count() > 0)
  559.             {
  560.                 var numBalls = tempBallsHit.Count();
  561.                 balls = balls.Except(tempBallsHit).ToList();
  562.                 score -= 25 * numBalls;
  563.             }
  564.             tempBallsHit = balls.Where(a => a.Pos().equals(tempShip.GetBack()) && a.turns <= 2);
  565.             if (tempBallsHit.Count() > 0)
  566.             {
  567.                 var numBalls = tempBallsHit.Count();
  568.                 balls = balls.Except(tempBallsHit).ToList();
  569.                 score -= 25 * numBalls;
  570.             }
  571.             tempBallsHit = balls.Where(a => a.Pos().equals(tempShip.GetMiddle()) && a.turns <= 2);
  572.             if (tempBallsHit.Count() > 0)
  573.             {
  574.                 var numBalls = tempBallsHit.Count();
  575.                 balls = balls.Except(tempBallsHit).ToList();
  576.                 score -= 50 * numBalls;
  577.             }
  578.  
  579.             if (tempShip.speed == 0)
  580.             {
  581.                 tempBallsHit = balls.Where(a => a.Pos().equals(tempShip.GetMiddle()) && a.turns <= 3);
  582.                 if (tempBallsHit.Count() > 0)
  583.                 {
  584.                     var numBalls = tempBallsHit.Count();
  585.                     score -= 20 * numBalls;
  586.                 }
  587.             }
  588.             else if (tempShip.speed == 2)
  589.             {
  590.                 var tempShip2 = tempShip.Clone();
  591.                 var tempShip3 = tempShip.Clone();
  592.                 tempShip2.TheoryMove(Action.WAIT);
  593.                 tempShip3.TheoryMove(Action.SLOWER);
  594.  
  595.                 var tempBalls = balls.Where(a => a.turns > 1 && a.turns <= 4);
  596.                 tempBallsHit = tempBalls.Where(a => a.Pos().equals(tempShip2.GetFront()));
  597.                 if (tempBallsHit.Count() > 0)
  598.                 {
  599.                     var numBalls = tempBallsHit.Count();
  600.                     tempBalls = tempBalls.Except(tempBallsHit).ToList();
  601.                     score -= 25 * numBalls;
  602.                 }
  603.                 tempBallsHit = tempBalls.Where(a => a.Pos().equals(tempShip2.GetBack()));
  604.                 if (tempBallsHit.Count() > 0)
  605.                 {
  606.                     var numBalls = tempBallsHit.Count();
  607.                     tempBalls = tempBalls.Except(tempBallsHit).ToList();
  608.                     score -= 25 * numBalls;
  609.                 }
  610.                 tempBallsHit = tempBalls.Where(a => a.Pos().equals(tempShip2.GetMiddle()));
  611.                 if (tempBallsHit.Count() > 0)
  612.                 {
  613.                     var numBalls = tempBallsHit.Count();
  614.                     tempBalls = tempBalls.Except(tempBallsHit).ToList();
  615.                     score -= 50 * numBalls;
  616.                 }
  617.  
  618.                 tempBallsHit = tempBalls.Where(a => a.Pos().equals(tempShip3.GetFront()));
  619.                 if (tempBallsHit.Count() > 0)
  620.                 {
  621.                     var numBalls = tempBallsHit.Count();
  622.                     tempBalls = tempBalls.Except(tempBallsHit).ToList();
  623.                     score -= 25 * numBalls;
  624.                 }
  625.                 tempBallsHit = tempBalls.Where(a => a.Pos().equals(tempShip3.GetBack()));
  626.                 if (tempBallsHit.Count() > 0)
  627.                 {
  628.                     var numBalls = tempBallsHit.Count();
  629.                     tempBalls = tempBalls.Except(tempBallsHit).ToList();
  630.                     score -= 25 * numBalls;
  631.                 }
  632.                 tempBallsHit = tempBalls.Where(a => a.Pos().equals(tempShip3.GetMiddle()));
  633.                 if (tempBallsHit.Count() > 0)
  634.                 {
  635.                     var numBalls = tempBallsHit.Count();
  636.                     tempBalls = tempBalls.Except(tempBallsHit).ToList();
  637.                     score -= 50 * numBalls;
  638.                 }
  639.  
  640.                 hitMine = mines.FirstOrDefault(a => a.Pos().equals(tempShip.GetFront().neighbor(tempShip.orientation)));
  641.                 if (hitMine != null)
  642.                 {
  643.                     score -= 25;
  644.                     mines.Remove(hitMine);
  645.                 }
  646.                 hitMine = mines.FirstOrDefault(a => a.Pos().equals(tempShip.GetFront().neighbor(tempShip.orientation).neighbor(tempShip.orientation)));
  647.                 if (hitMine != null)
  648.                 {
  649.                     score -= 25;
  650.                     mines.Remove(hitMine);
  651.                 }
  652.                 hitMine = mines.FirstOrDefault(a => a.Pos().equals(tempShip.GetFront().neighbor(tempShip.orientation).neighbor(tempShip.orientation).neighbor(tempShip.orientation)));
  653.                 if (hitMine != null)
  654.                 {//wont hit, but avoid slowing down
  655.                     score -= 5;
  656.                     //mines.Remove(hitMine);
  657.                 }
  658.             }
  659.             else if (tempShip.speed == 2)
  660.             {
  661.                 hitMine = mines.FirstOrDefault(a => a.Pos().equals(tempShip.GetFront().neighbor(tempShip.orientation)));
  662.                 if (hitMine != null)
  663.                 {//wont hit, but avoid slowing down
  664.                     score -= 5;
  665.                     //mines.Remove(hitMine);
  666.                 }
  667.             }
  668.  
  669.  
  670.             //front ship collides
  671.             if (ships.Any(a => a.id != ship.id && a.GetFront().equals(tempShip.GetFront())))
  672.             {
  673.                 score -= 1;
  674.             }
  675.             if (ships.Any(a => a.id != ship.id && a.GetMiddle().equals(tempShip.GetFront())))
  676.             {
  677.                 score -= 1;
  678.             }
  679.             if (ships.Any(a => a.id != ship.id && a.GetBack().equals(tempShip.GetFront())))
  680.             {
  681.                 score -= 1;
  682.             }
  683.             //back ship collides
  684.             if (ships.Any(a => a.id != ship.id && a.GetFront().equals(tempShip.GetBack())))
  685.             {
  686.                 score -= 1;
  687.             }
  688.             if (ships.Any(a => a.id != ship.id && a.GetMiddle().equals(tempShip.GetBack())))
  689.             {
  690.                 score -= 1;
  691.             }
  692.             if (ships.Any(a => a.id != ship.id && a.GetBack().equals(tempShip.GetBack())))
  693.             {
  694.                 score -= 1;
  695.             }
  696.  
  697.  
  698.             //barrels hit
  699.             var rumHit = rum.FirstOrDefault(a => a.Pos().equals(tempShip.GetFront()));
  700.             if (rumHit != null)
  701.             {
  702.                 var rumAmount = rumHit.rum;
  703.                 var diff = (100 - ship.rum);
  704.                 var rumInc = diff >= rumAmount ? rumAmount : diff;
  705.                 ship.rum += rumInc;
  706.                 score += rumInc * 2;
  707.                 rum.Remove(rumHit);
  708.             }
  709.             rumHit = rum.FirstOrDefault(a => a.Pos().equals(tempShip.GetMiddle()));
  710.             if (rumHit != null)
  711.             {
  712.                 var rumAmount = rumHit.rum;
  713.                 var diff = (100 - ship.rum);
  714.                 var rumInc = diff >= rumAmount ? rumAmount : diff;
  715.                 ship.rum += rumInc;
  716.                 score += rumInc * 2;
  717.                 rum.Remove(rumHit);
  718.             }
  719.             rumHit = rum.FirstOrDefault(a => a.Pos().equals(tempShip.GetBack()));
  720.             if (rumHit != null)
  721.             {
  722.                 var rumAmount = rumHit.rum;
  723.                 var diff = (100 - ship.rum);
  724.                 var rumInc = diff >= rumAmount ? rumAmount : diff;
  725.                 ship.rum += rumInc;
  726.                 score += rumInc * 2;
  727.                 rum.Remove(rumHit);
  728.             }
  729.  
  730.  
  731.             if (rum.Count() > 0)
  732.             {
  733.                 var minDist = rum.Min(a => tempShip.DistFront(a));
  734.                 if (minDist < 5)
  735.                 {
  736.                     score += (10 - minDist);
  737.                 }
  738.  
  739.             }
  740.  
  741.             if (!tempShip.GetFront().isInsideMap())
  742.             {
  743.                 score -= 5;
  744.             }
  745.             else if (!tempShip.GetFront().isInsideEdge())
  746.             {
  747.                 if (rum.Count() > 0)
  748.                 {
  749.                     var minDist = rum.Min(a => tempShip.DistFront(a));
  750.                     if (minDist > 3)
  751.                     {
  752.                         score -= 4;
  753.                     }
  754.                 }
  755.                 else
  756.                 {
  757.                     score -= 4;
  758.                 }
  759.             }
  760.  
  761.             //run into rum prior to turn
  762.  
  763.             rumHit = rum.FirstOrDefault(a => a.Pos().equals(tempShip.GetMiddle().neighbor(ship.orientation)));
  764.             if (rumHit != null)
  765.             {
  766.                 var rumAmount = rumHit.rum;
  767.                 var diff = (100 - ship.rum);
  768.                 var rumInc = diff >= rumAmount ? rumAmount : diff;
  769.                 ship.rum += rumInc;
  770.                 score += rumInc * 2;
  771.                 rum.Remove(rumHit);
  772.             }
  773.  
  774.  
  775.             results.Add(act, score);
  776.         }
  777.  
  778.         if (logging)
  779.         {
  780.             foreach (var result in results)
  781.             {
  782.                 log(result.Key.ToString() + ": " + result.Value.ToString());
  783.             }
  784.         }
  785.         return results;
  786.     }
  787.  
  788.     public static int Dist(int x1, int y1, int x2, int y2)
  789.     {
  790.         int xp1 = x1 - (y1 - (y1 & 1)) / 2;
  791.         int zp1 = y1;
  792.         int yp1 = -(xp1 + zp1);
  793.         int xp2 = x2 - (y2 - (y2 & 1)) / 2;
  794.         int zp2 = y2;
  795.         int yp2 = -(xp2 + zp2);
  796.         return (Math.Abs(xp1 - xp2) + Math.Abs(yp1 - yp2) + Math.Abs(zp1 - zp2)) / 2;
  797.     }
  798.  
  799.     public static void log(string str)
  800.     {
  801.         Console.Error.WriteLine(str);
  802.     }
  803.  
  804.     public static void log(int str)
  805.     {
  806.         Console.Error.WriteLine(str);
  807.     }
  808.  
  809.     public static void log(double str)
  810.     {
  811.         Console.Error.WriteLine(str);
  812.     }
  813.  
  814.     public static void print(string str)
  815.     {
  816.         Console.WriteLine(str);
  817.     }
  818.  
  819.     public static void Move(int x, int y)
  820.     {
  821.         Console.WriteLine("MOVE {0} {1}", x, y);
  822.     }
  823.  
  824.     public static void Fire(int x, int y)
  825.     {
  826.         Console.WriteLine("FIRE {0} {1}", x, y);
  827.     }
  828.  
  829.     public static void Mine()
  830.     {
  831.         print("MINE");
  832.     }
  833.  
  834.     public static void Slower()
  835.     {
  836.         print("SLOWER");
  837.     }
  838.     public static void Faster()
  839.     {
  840.         print("FASTER");
  841.     }
  842.     public static void Wait()
  843.     {
  844.         print("WAIT");
  845.     }
  846.  
  847.     public static void EndGameStrat(Ship ship)
  848.     {
  849.         log("end game strat");
  850.         var enemies = ships.Where(a => a.owner == 0).OrderBy(b => b.Dist(ship));
  851.         var enemy = enemies.FirstOrDefault();
  852.  
  853.         var myShips = ships.Where(a => a.owner == 1 && a.id != ship.id && !a.suicide && a.Dist(ship) < 5);
  854.         var myShipsFar = ships.Where(a => a.owner == 1 && a.id != ship.id && !a.suicide).OrderBy(b => b.Dist(ship));
  855.         var myShipsFarSuicide = ships.Where(a => a.owner == 1 && a.id != ship.id).OrderBy(b => b.Dist(ship));
  856.  
  857.  
  858.         if (rum.Count() == 0 && myShipsFar.Count() > 0 && enemies.Min(e => e.Dist(ship) > 5))
  859.         {
  860.             if (myShipsFar.Max(a => a.rum) >= ship.rum && ship.rum <= 50 && (enemies.Max(a => a.rum) >= myShipsFar.Max(a => a.rum)))
  861.             {//other ship has more rum
  862.                 ship.suicide = true;
  863.                 log("suicide");
  864.             }
  865.         }
  866.  
  867.         if (ship.suicide && myShips.Count() > 0)
  868.         {
  869.             if (ship.rum > myShipsFar.Max(a => a.rum))
  870.             {
  871.                 log("no suicide anymore");
  872.                 ship.suicide = false;
  873.             }
  874.             else if (ship.speed > 0)
  875.             {
  876.                 ship.Slower();
  877.                 return;
  878.             }
  879.             else
  880.             {
  881.                 if (balls.Any(b => b.Pos().equals(ship.GetMiddle())))
  882.                 {//going to die anyway, wait it out
  883.                     ship.Wait();
  884.                 }
  885.                 else
  886.                 {
  887.                     ship.Fire(ship.x, ship.y);
  888.                 }
  889.                 return;
  890.             }
  891.         }
  892.         else if (ship.suicide && myShipsFar.Count() > 0)
  893.         {
  894.             var first = myShipsFar.First();
  895.             ship.Move(first);
  896.             return;
  897.         }
  898.         else if (!ship.suicide && myShipsFarSuicide.Count() > 0)
  899.         {
  900.             var first = myShipsFarSuicide.First();
  901.             ship.Move(first);
  902.             return;
  903.         }
  904.         else if (ship.suicide)
  905.         {
  906.             ship.suicide = false;
  907.         }
  908.  
  909.  
  910.  
  911.  
  912.         if (ship.rum > enemies.Max(c => c.rum) || (Math.Min(myShips.Sum(a => a.rum), (myShips.Count() * 30)) + ship.rum) > enemies.Max(c => c.rum))
  913.         {
  914.             log("will hit: " + ship.BallsWillHit(balls));
  915.             if (enemies.Min(c => ship.Dist(c)) > 10 && !ship.BallsWillHit(balls))
  916.             {
  917.                 if (ship.speed > 0)
  918.                 {
  919.                     ship.PerformAction(Action.SLOWER);
  920.                     return;
  921.                 }
  922.                 else
  923.                 {
  924.                     ship.PerformAction(Action.WAIT);
  925.                     //ship.Wait();
  926.                     return;
  927.                 }
  928.             }
  929.             else
  930.             {
  931.                 var avgX = enemies.Sum(c => c.x) / enemies.Count();
  932.                 var avgY = enemies.Sum(c => c.y) / enemies.Count();
  933.                 var tX = avgX < 6 ? 18 : avgX > 15 ? 4 : 18;
  934.                 var tY = avgY < 6 ? 17 : avgY > 14 ? 4 : 17;
  935.                 log("move away from enemy");
  936.                 ship.Move(tX, tY);
  937.             }
  938.         }
  939.         else
  940.         {
  941.             ship.Move(enemy);
  942.         }
  943.     }
  944.     #endregion
  945.  
  946.  
  947. }
  948.  
  949. #region classes
  950. class Unit
  951. {
  952.     public int x;
  953.     public int y;
  954.     public int id;
  955.     public string type;
  956.     public Action action;
  957.  
  958.     public Coord Pos()
  959.     {
  960.         return new Coord(x, y);
  961.     }
  962.  
  963.     public double GetDistance(int x1, int y1)
  964.     {
  965.         return Math.Sqrt(Math.Pow(x - x1, 2) + Math.Pow(y - y1, 2));
  966.     }
  967.  
  968.     public double GetDistance(Unit unit)
  969.     {
  970.         return Math.Sqrt(Math.Pow(x - unit.x, 2) + Math.Pow(y - unit.y, 2));
  971.     }
  972.  
  973.     public int Dist(Unit unit)
  974.     {
  975.         int xp1 = this.x - (this.y - (this.y & 1)) / 2;
  976.         int zp1 = this.y;
  977.         int yp1 = -(xp1 + zp1);
  978.         int xp2 = unit.x - (unit.y - (unit.y & 1)) / 2;
  979.         int zp2 = unit.y;
  980.         int yp2 = -(xp2 + zp2);
  981.         return (Math.Abs(xp1 - xp2) + Math.Abs(yp1 - yp2) + Math.Abs(zp1 - zp2)) / 2;
  982.     }
  983.  
  984.     public int Dist(Coord unit)
  985.     {
  986.         int xp1 = this.x - (this.y - (this.y & 1)) / 2;
  987.         int zp1 = this.y;
  988.         int yp1 = -(xp1 + zp1);
  989.         int xp2 = unit.x - (unit.y - (unit.y & 1)) / 2;
  990.         int zp2 = unit.y;
  991.         int yp2 = -(xp2 + zp2);
  992.         return (Math.Abs(xp1 - xp2) + Math.Abs(yp1 - yp2) + Math.Abs(zp1 - zp2)) / 2;
  993.     }
  994.  
  995.  
  996.     public int Dist(int x2, int y2)
  997.     {
  998.         int xp1 = this.x - (this.y - (this.y & 1)) / 2;
  999.         int zp1 = this.y;
  1000.         int yp1 = -(xp1 + zp1);
  1001.         int xp2 = x2 - (y2 - (y2 & 1)) / 2;
  1002.         int zp2 = y2;
  1003.         int yp2 = -(xp2 + zp2);
  1004.         return (Math.Abs(xp1 - xp2) + Math.Abs(yp1 - yp2) + Math.Abs(zp1 - zp2)) / 2;
  1005.     }
  1006.  
  1007.     public int Dist(Coord point, int x2, int y2)
  1008.     {
  1009.         int xp1 = point.x - (point.y - (point.y & 1)) / 2;
  1010.         int zp1 = point.y;
  1011.         int yp1 = -(xp1 + zp1);
  1012.         int xp2 = x2 - (y2 - (y2 & 1)) / 2;
  1013.         int zp2 = y2;
  1014.         int yp2 = -(xp2 + zp2);
  1015.         return (Math.Abs(xp1 - xp2) + Math.Abs(yp1 - yp2) + Math.Abs(zp1 - zp2)) / 2;
  1016.     }
  1017.  
  1018.     public int Dist(Coord point1, Coord point2)
  1019.     {
  1020.         int xp1 = point1.x - (point1.y - (point1.y & 1)) / 2;
  1021.         int zp1 = point1.y;
  1022.         int yp1 = -(xp1 + zp1);
  1023.         int xp2 = point2.x - (point2.y - (point2.y & 1)) / 2;
  1024.         int zp2 = point2.y;
  1025.         int yp2 = -(xp2 + zp2);
  1026.         return (Math.Abs(xp1 - xp2) + Math.Abs(yp1 - yp2) + Math.Abs(zp1 - zp2)) / 2;
  1027.     }
  1028.  
  1029. }
  1030. class Ship : Unit
  1031. {
  1032.     private static int MAP_WIDTH = 23;
  1033.     private static int MAP_HEIGHT = 21;
  1034.  
  1035.     public int orientation;
  1036.     public int speed;
  1037.     public int rum;
  1038.     public int owner;
  1039.     public int xOffset;
  1040.     public int yOffset;
  1041.     public bool layMines;
  1042.  
  1043.     public bool suicide;
  1044.     public Dictionary<Action, int> priorities = null;
  1045.  
  1046.     public Coord target;
  1047.  
  1048.     public int cannonCooldown;
  1049.     public int mineCooldown;
  1050.  
  1051.     public Ship Clone()
  1052.     {
  1053.         return new Ship()
  1054.         {
  1055.             id = this.id,
  1056.             x = this.x,
  1057.             y = this.y,
  1058.             orientation = this.orientation,
  1059.             speed = this.speed,
  1060.             rum = this.rum,
  1061.             owner = this.owner,
  1062.             action = this.action,
  1063.             mineCooldown = this.mineCooldown,
  1064.             cannonCooldown = this.cannonCooldown,
  1065.             target = this.target != null ? this.target.Clone() : null,
  1066.             layMines = this.layMines,
  1067.         };
  1068.     }
  1069.  
  1070.     public Coord GetFront()
  1071.     {
  1072.         Coord front = new Coord(x, y).neighbor(orientation);
  1073.         return front;
  1074.     }
  1075.  
  1076.     public Coord GetMiddle()
  1077.     {
  1078.         Coord middle = new Coord(x, y);
  1079.         return middle;
  1080.     }
  1081.  
  1082.     public Coord GetBack()
  1083.     {
  1084.         Coord back = new Coord(x, y).neighbor((orientation + 3) % 6);
  1085.         return back;
  1086.     }
  1087.  
  1088.     public bool BallsWillHit(List<Cannonball> balls)
  1089.     {
  1090.         var result = (balls.Any(a => GetFront().equals(a) || GetMiddle().equals(a) || GetBack().equals(a)));
  1091.         return result;
  1092.     }
  1093.  
  1094.     public Coord GetFront(int turns)
  1095.     {
  1096.         Coord currentCoord = new Coord(x, y);
  1097.         this.yOffset = 0;
  1098.         this.xOffset = 0;
  1099.  
  1100.         //first turn
  1101.         Coord newPosition = currentCoord.neighbor(orientation);
  1102.         //extra turns
  1103.         for (int i = 1; i < turns; i++)
  1104.         {
  1105.             newPosition = newPosition.neighbor(orientation);
  1106.         }
  1107.  
  1108.         return newPosition.neighbor(orientation);
  1109.     }
  1110.  
  1111.     public Coord GetBack(int turns)
  1112.     {
  1113.         Coord currentCoord = new Coord(x, y);
  1114.         this.yOffset = 0;
  1115.         this.xOffset = 0;
  1116.  
  1117.         //first turn
  1118.         Coord newPosition = currentCoord.neighbor(orientation);
  1119.         //extra turns
  1120.         for (int i = 1; i < turns; i++)
  1121.         {
  1122.             newPosition = newPosition.neighbor(orientation);
  1123.         }
  1124.  
  1125.         return newPosition.neighbor((orientation + 3) % 6);
  1126.     }
  1127.  
  1128.     public Coord GetMiddle(int turns)
  1129.     {
  1130.         Coord currentCoord = new Coord(x, y);
  1131.         this.yOffset = 0;
  1132.         this.xOffset = 0;
  1133.  
  1134.         //first turn
  1135.         Coord newPosition = currentCoord.neighbor(orientation);
  1136.         //extra turns
  1137.         for (int i = 1; i < turns; i++)
  1138.         {
  1139.             newPosition = newPosition.neighbor(orientation);
  1140.         }
  1141.  
  1142.         return newPosition;
  1143.     }
  1144.  
  1145.     public Coord GetOffsetFront()
  1146.     {
  1147.         Coord front = GetFront().neighbor(orientation);
  1148.         return front;
  1149.     }
  1150.     public Coord GetOffsetBack()
  1151.     {
  1152.         Coord back = GetBack().neighbor((orientation + 3) % 6);
  1153.         return back;
  1154.     }
  1155.  
  1156.     public bool Fire(Rum rum)
  1157.     {
  1158.         Console.WriteLine("Fire {0} {1}", rum.x, rum.y);
  1159.         return true;
  1160.     }
  1161.  
  1162.     public bool Fire(Mine mine)
  1163.     {
  1164.         Console.WriteLine("Fire {0} {1}", mine.x, mine.y);
  1165.         return true;
  1166.     }
  1167.  
  1168.     public bool Fire(Coord coord)
  1169.     {
  1170.         Console.WriteLine("Fire {0} {1}", coord.x, coord.y);
  1171.         return true;
  1172.     }
  1173.  
  1174.     public bool Fire(int X, int Y)
  1175.     {
  1176.         Console.WriteLine("Fire {0} {1}", X, Y);
  1177.         return true;
  1178.     }
  1179.  
  1180.     public bool Fire()
  1181.     {
  1182.         if (target == null)
  1183.             throw new NullReferenceException("no target set");
  1184.         Console.WriteLine("Fire {0} {1}", target.x, target.y);
  1185.         return true;
  1186.     }
  1187.  
  1188.     public bool Fire(Ship unit)
  1189.     {
  1190.         if (cannonCooldown > 0 || DistFront(unit) > 10)
  1191.         {
  1192.             return false;
  1193.         }
  1194.  
  1195.         var tempShip = unit.Clone();
  1196.         var tempThisShip = Clone();
  1197.  
  1198.         var xTar = unit.x;
  1199.         var yTar = unit.y;
  1200.  
  1201.         tempThisShip.TheoryMove(Action.WAIT);
  1202.         if (tempShip.speed < 2)
  1203.         {
  1204.             tempShip.TheoryMove(Action.FASTER);
  1205.         }
  1206.         else
  1207.         {
  1208.             tempShip.TheoryMove(Action.WAIT);
  1209.         }
  1210.  
  1211.         int estimateTime = shotDuration(tempShip.GetMiddle());
  1212.  
  1213.         if (estimateTime > 1)
  1214.         {
  1215.             tempThisShip.TheoryMove(Action.WAIT);
  1216.             if (tempShip.speed < 2)
  1217.             {
  1218.                 tempShip.TheoryMove(Action.FASTER);
  1219.             }
  1220.             else
  1221.             {
  1222.                 tempShip.TheoryMove(Action.WAIT);
  1223.             }
  1224.             estimateTime = shotDuration(tempShip.GetMiddle());
  1225.         }
  1226.  
  1227.         if (shotDuration(unit.GetMiddle()) != 1 && unit.speed != 0)
  1228.         {
  1229.  
  1230.             xTar = tempShip.x;
  1231.             yTar = tempShip.y;
  1232.         }
  1233.  
  1234.         if (!unit.GetFront().isInsideMap() || !unit.GetFront().neighbor(unit.orientation).isInsideMap())
  1235.         {
  1236.             xTar = unit.x;
  1237.             yTar = unit.y;
  1238.         }
  1239.  
  1240.         target = new Coord(xTar, yTar);
  1241.         Cannonball tempBall = new Cannonball() { x = xTar, y = yTar, turns = shotDuration(target) };
  1242.         List<Cannonball> tempBalls = new List<Cannonball>();
  1243.         tempBalls.Add(tempBall);
  1244.  
  1245.         if (tempThisShip.BallsWillHit(tempBalls))
  1246.         {
  1247.             Console.Error.WriteLine("would shoot self");
  1248.             return false;
  1249.         }
  1250.  
  1251.         if (DistFront(target) > 10)
  1252.         {
  1253.             return false;
  1254.         }
  1255.         if (shotDuration(target) > 3 && (unit.speed != 0 || tempShip.speed != 0))
  1256.         {
  1257.             return false;
  1258.         }
  1259.  
  1260.         return Fire();
  1261.     }
  1262.  
  1263.     public bool Fire(Ship unit, List<Ship> ships, List<Rum> rum, List<Cannonball> balls)
  1264.     {
  1265.         if (cannonCooldown > 0 || DistFront(unit) > 4)
  1266.         {
  1267.             return false;
  1268.         }
  1269.         int yTarOffset = 0;
  1270.         int xTarOffset = 0;
  1271.         int eSpeed = unit.speed;
  1272.         int dist = DistFront(unit);
  1273.         int distToTarget = 0;
  1274.         int attempts = 0;
  1275.         int maxAttempts = 10;
  1276.  
  1277.  
  1278.         Ship tempShip = unit.Clone();
  1279.  
  1280.         var closestRum = rum.Where(a => !balls.Any(b => b.x == a.x && b.y == a.y)).OrderBy(c => c.Dist(tempShip)).FirstOrDefault();
  1281.  
  1282.         var front = tempShip.GetFront().neighbor(tempShip.orientation);
  1283.         if (ships.Any(a => a.GetMiddle().equals(front) || a.GetFront().equals(front) || a.GetBack().equals(front)))
  1284.         {//going to be speed 0, fire at center
  1285.             Console.Error.WriteLine("block enemy, fire center");
  1286.             this.target = tempShip.GetMiddle();
  1287.             return Fire();
  1288.         }
  1289.  
  1290.         return Fire(unit);
  1291.  
  1292.         //dont use yet
  1293.         if (closestRum == null)
  1294.         {
  1295.             return Fire(unit);
  1296.         }
  1297.  
  1298.         var targetRum = new Coord(closestRum.x, closestRum.y);
  1299.         bool fired = false;
  1300.         while (attempts < maxAttempts)
  1301.         {
  1302.             attempts++;
  1303.             //TODO: THIS
  1304.             Console.Error.WriteLine("loop {0}", attempts);
  1305.             tempShip.TheoryMove(targetRum, false);
  1306.  
  1307.             var frontDist = shotDuration(tempShip.GetFront());
  1308.             var middletDist = shotDuration(tempShip.GetMiddle());
  1309.             var backDist = shotDuration(tempShip.GetBack());
  1310.  
  1311.             if (attempts == frontDist)
  1312.             {
  1313.                 Console.Error.WriteLine("predict front shot");
  1314.                 this.target = tempShip.GetFront();
  1315.                 return Fire();
  1316.             }
  1317.             else if (attempts == middletDist)
  1318.             {
  1319.                 Console.Error.WriteLine("predict middle shot");
  1320.                 this.target = tempShip.GetMiddle();
  1321.                 return Fire();
  1322.             }
  1323.             else if (attempts == backDist)
  1324.             {
  1325.                 Console.Error.WriteLine("predict back shot");
  1326.                 this.target = tempShip.GetBack();
  1327.                 return Fire();
  1328.             }
  1329.         }
  1330.         if (!fired)
  1331.         {
  1332.             return Fire(unit);
  1333.         }
  1334.         return false;
  1335.     }
  1336.  
  1337.     public void Avoid(Cannonball ball, List<Cannonball> balls, List<Mine> mines)
  1338.     {
  1339.         SetOffsets(ball.turns + 1);
  1340.         var front = GetOffsetFront();
  1341.         var back = GetOffsetBack();
  1342.         var middle = new Coord(x + speed * xOffset, y + speed * yOffset);
  1343.  
  1344.         if (ball.x == front.x && ball.y == front.y)
  1345.         {
  1346.             Console.Error.WriteLine("avoid front!");
  1347.             Swivel();
  1348.         }
  1349.         else if (ball.x == back.x && ball.y == back.y && speed < 2)
  1350.         {
  1351.             Console.Error.WriteLine("avoid back!");
  1352.             Swivel();
  1353.             //Console.WriteLine("FASTER");
  1354.         }
  1355.         else if (ball.x == middle.x && ball.y == middle.y && speed < 2)
  1356.         {
  1357.             Console.Error.WriteLine("avoid middle!");
  1358.             if (GetFront().x > 21 || GetFront().x < 1 || GetFront().y < 1 || GetFront().y > 19)
  1359.             {
  1360.                 Swivel();
  1361.             }
  1362.             else
  1363.             {
  1364.                 Faster();
  1365.             }
  1366.         }
  1367.         else
  1368.         {
  1369.             //Console.WriteLine("SLOWER");
  1370.             Console.Error.WriteLine("avoid something!");
  1371.             Swivel();
  1372.         }
  1373.     }
  1374.  
  1375.     public void Swivel(int? option = 0)
  1376.     {//1 right, -1 left
  1377.         if (option != 0)
  1378.         {
  1379.             Random rand = new Random();
  1380.             var dir = rand.Next(2) == 0 ? "PORT" : "STARBOARD";
  1381.             Console.WriteLine(dir);
  1382.         }
  1383.         else
  1384.         {
  1385.             var dir = option == 1 ? "STARBOARD" : "PORT";
  1386.             Console.WriteLine(dir);
  1387.         }
  1388.     }
  1389.  
  1390.     public void PerformAction(Action act, bool doAction = true)
  1391.     {
  1392.  
  1393.         if (priorities.ContainsKey(act))
  1394.         {
  1395.             var currentScore = priorities[act];
  1396.             if (priorities.Any(b => b.Value > currentScore))
  1397.             {
  1398.                 var waitScore = priorities.ContainsKey(Action.WAIT) ? priorities[Action.WAIT] : -100;
  1399.                 var portScore = priorities.ContainsKey(Action.PORT) ? priorities[Action.PORT] : -100;
  1400.                 var starboardScore = priorities.ContainsKey(Action.STARBOARD) ? priorities[Action.STARBOARD] : -100;
  1401.                 var fasterScore = priorities.ContainsKey(Action.FASTER) ? priorities[Action.FASTER] : -100;
  1402.                 var slowerScore = priorities.ContainsKey(Action.SLOWER) ? priorities[Action.SLOWER] : -100;
  1403.  
  1404.                 var sortedPairList = priorities.OrderByDescending(a => a.Value);
  1405.                 if (!(sortedPairList.First().Value > 0) && (act == Action.PORT || act == Action.STARBOARD))
  1406.                 {
  1407.                     if (slowerScore == 0)
  1408.                     {
  1409.                         act = Action.SLOWER;
  1410.                         Console.Error.WriteLine("Action Override - SLOWER 0");
  1411.                     }
  1412.                     else if (fasterScore == 0)
  1413.                     {
  1414.                         act = Action.FASTER;
  1415.                         Console.Error.WriteLine("Action Override - FASTER 0");
  1416.                     }
  1417.                     else if (waitScore == 0)
  1418.                     {
  1419.                         act = Action.WAIT;
  1420.                         Console.Error.WriteLine("Action Override - WAIT 0");
  1421.                     }
  1422.                     else
  1423.                     {
  1424.                         act = sortedPairList.First().Key;
  1425.                         Console.Error.WriteLine("Action Override - " + sortedPairList.First().Key.ToString() + ": " + sortedPairList.First().Value);
  1426.                     }
  1427.                 }
  1428.                 else
  1429.                 {
  1430.                     act = sortedPairList.First().Key;
  1431.                     Console.Error.WriteLine("Action Override - " + sortedPairList.First().Key.ToString() + ": " + sortedPairList.First().Value);
  1432.  
  1433.                 }
  1434.             }
  1435.         }
  1436.         if (doAction)
  1437.         {
  1438.             switch (act)
  1439.             {
  1440.                 case Action.WAIT:
  1441.                 case Action.MINE:
  1442.                 case Action.NONE:
  1443.                     if (layMines && mineCooldown <= 0)
  1444.                     {
  1445.                         Mine();
  1446.                         mineCooldown = 5;
  1447.                     }
  1448.                     else
  1449.                     {
  1450.                         Wait();
  1451.                     }
  1452.                     break;
  1453.                 case Action.FASTER:
  1454.                     Faster();
  1455.                     break;
  1456.                 case Action.SLOWER:
  1457.                     Slower();
  1458.                     break;
  1459.                 case Action.PORT:
  1460.                     Port();
  1461.                     break;
  1462.                 case Action.STARBOARD:
  1463.                     Starboard();
  1464.                     break;
  1465.             }
  1466.         }
  1467.     }
  1468.     public void Move(Ship unit)
  1469.     {
  1470.         //TODO
  1471.         var tempShip = unit.Clone();
  1472.  
  1473.         tempShip.TheoryMove(Action.WAIT);
  1474.         var front = tempShip.GetFront().neighbor(tempShip.orientation);
  1475.         if (!front.isInsideMap())
  1476.             front = tempShip.GetMiddle();
  1477.         MoveTo(front.x, front.y);
  1478.  
  1479.         PerformAction(action);
  1480.     }
  1481.  
  1482.     public void Move(Rum unit)
  1483.     {
  1484.         //TODO
  1485.         MoveTo(unit.x, unit.y);
  1486.         PerformAction(action);
  1487.     }
  1488.  
  1489.     public void Move(int x1, int y1)
  1490.     {
  1491.         //TODO
  1492.         x1 = Math.Min(x1, 22);
  1493.         x1 = Math.Max(x1, 0);
  1494.  
  1495.         y1 = Math.Min(y1, 20);
  1496.         y1 = Math.Max(y1, 0);
  1497.  
  1498.  
  1499.         MoveTo(x1, y1);
  1500.         PerformAction(action);
  1501.     }
  1502.  
  1503.     public void Slower()
  1504.     {
  1505.         print("SLOWER");
  1506.     }
  1507.     public void Faster()
  1508.     {
  1509.         print("FASTER");
  1510.     }
  1511.  
  1512.     public void Port()
  1513.     {
  1514.         print("PORT");
  1515.     }
  1516.     public void Starboard()
  1517.     {
  1518.         print("STARBOARD");
  1519.     }
  1520.  
  1521.     public void Wait()
  1522.     {
  1523.         print("WAIT");
  1524.     }
  1525.     public void Mine()
  1526.     {
  1527.         print("MINE");
  1528.     }
  1529.  
  1530.     public void print(string str)
  1531.     {
  1532.         Console.WriteLine(str);
  1533.     }
  1534.  
  1535.     public int GetFX()
  1536.     {
  1537.         SetOffsets();
  1538.         return x + xOffset;
  1539.     }
  1540.     public int GetFY()
  1541.     {
  1542.         SetOffsets();
  1543.         return y + yOffset;
  1544.     }
  1545.     //TODO: THIS
  1546.     public void TheoryMove(int x, int y, bool custom = true)
  1547.     {
  1548.         MoveTo(x, y, custom);
  1549.         //adjust speed
  1550.         switch (action)
  1551.         {
  1552.             case Action.SLOWER:
  1553.                 if (speed > 0)
  1554.                     speed--;
  1555.                 break;
  1556.             case Action.FASTER:
  1557.                 if (speed < 2)
  1558.                     speed++;
  1559.                 break;
  1560.         }
  1561.         //move
  1562.         switch (speed)
  1563.         {
  1564.             case 2:
  1565.                 var futurePos = GetFront().neighbor(orientation);
  1566.                 if (futurePos.isInsideMap())
  1567.                 {
  1568.                     x = futurePos.x;
  1569.                     y = futurePos.y;
  1570.                 }
  1571.                 else if (GetFront().isInsideMap())
  1572.                 {
  1573.                     futurePos = GetFront();
  1574.                     x = futurePos.x;
  1575.                     y = futurePos.y;
  1576.                 }
  1577.                 else
  1578.                 {
  1579.                     speed = 0;
  1580.                 }
  1581.                 break;
  1582.             case 1:
  1583.                 var front = GetFront();
  1584.                 if (front.isInsideMap())
  1585.                 {
  1586.                     x = front.x;
  1587.                     y = front.y;
  1588.                 }
  1589.                 else
  1590.                 {
  1591.                     speed = 0;
  1592.                 }
  1593.                 break;
  1594.             case 0:
  1595.                 break;
  1596.         }
  1597.         //rorate
  1598.         switch (action)
  1599.         {
  1600.             case Action.PORT:
  1601.                 orientation++;
  1602.                 if (orientation > 5)
  1603.                     orientation = 0;
  1604.  
  1605.                 break;
  1606.             case Action.STARBOARD:
  1607.                 orientation--;
  1608.                 if (orientation < 0)
  1609.                     orientation = 5;
  1610.                 break;
  1611.         }
  1612.     }
  1613.  
  1614.     public void TheoryMove(Action action)
  1615.     {
  1616.         //adjust speed
  1617.         switch (action)
  1618.         {
  1619.             case Action.SLOWER:
  1620.                 if (speed > 0)
  1621.                     speed--;
  1622.                 break;
  1623.             case Action.FASTER:
  1624.                 if (speed < 2)
  1625.                     speed++;
  1626.                 break;
  1627.         }
  1628.         //move
  1629.         //Console.Error.WriteLine("before: {0}, {1}", x, y);
  1630.         switch (speed)
  1631.         {
  1632.             case 2:
  1633.                 var futurePos = GetFront().neighbor(orientation);
  1634.                 if (futurePos.isInsideMap())
  1635.                 {
  1636.                     x = futurePos.x;
  1637.                     y = futurePos.y;
  1638.                 }
  1639.                 else if (GetFront().isInsideMap())
  1640.                 {
  1641.                     futurePos = GetFront();
  1642.                     x = futurePos.x;
  1643.                     y = futurePos.y;
  1644.                 }
  1645.                 else
  1646.                 {
  1647.                     speed = 0;
  1648.                 }
  1649.                 break;
  1650.             case 1:
  1651.                 var front = GetFront();
  1652.                 if (front.isInsideMap())
  1653.                 {
  1654.                     x = front.x;
  1655.                     y = front.y;
  1656.                 }
  1657.                 else
  1658.                 {
  1659.                     speed = 0;
  1660.                 }
  1661.                 break;
  1662.             case 0:
  1663.                 break;
  1664.         }
  1665.         //Console.Error.WriteLine("after: {0}, {1}", x, y);
  1666.         //rorate
  1667.         switch (action)
  1668.         {
  1669.             case Action.PORT:
  1670.                 orientation++;
  1671.                 if (orientation > 5)
  1672.                     orientation = 0;
  1673.  
  1674.                 break;
  1675.             case Action.STARBOARD:
  1676.                 orientation--;
  1677.                 if (orientation < 0)
  1678.                     orientation = 5;
  1679.                 break;
  1680.         }
  1681.     }
  1682.  
  1683.     public void TheoryMove(Coord coord, bool custom = true)
  1684.     {
  1685.         TheoryMove(coord.x, coord.y, custom);
  1686.     }
  1687.  
  1688.     public void SetOffsets(int turns)
  1689.     {
  1690.         Coord currentCoord = new Coord(x, y);
  1691.         this.yOffset = 0;
  1692.         this.xOffset = 0;
  1693.  
  1694.         //first turn
  1695.         Coord newPosition = currentCoord.neighbor(orientation);
  1696.         //extra turns
  1697.         for (int i = 1; i < turns; i++)
  1698.         {
  1699.             newPosition = newPosition.neighbor(orientation);
  1700.         }
  1701.  
  1702.         this.xOffset = newPosition.x - currentCoord.x;
  1703.         this.yOffset = newPosition.y - currentCoord.y;
  1704.     }
  1705.  
  1706.  
  1707.     public void SetOffsets()
  1708.     {
  1709.         Coord currentCoord = new Coord(x, y);
  1710.         this.yOffset = 0;
  1711.         this.xOffset = 0;
  1712.  
  1713.         Coord newPosition = currentCoord.neighbor(orientation);
  1714.         this.xOffset = newPosition.x - currentCoord.x;
  1715.         this.yOffset = newPosition.y - currentCoord.y;
  1716.     }
  1717.  
  1718.     public int DistFront(Unit unit)
  1719.     {
  1720.         var front = GetFront();
  1721.         int xp1 = front.x - (front.y - (front.y & 1)) / 2;
  1722.         int zp1 = front.y;
  1723.         int yp1 = -(xp1 + zp1);
  1724.         int xp2 = unit.x - (unit.y - (unit.y & 1)) / 2;
  1725.         int zp2 = unit.y;
  1726.         int yp2 = -(xp2 + zp2);
  1727.         return (Math.Abs(xp1 - xp2) + Math.Abs(yp1 - yp2) + Math.Abs(zp1 - zp2)) / 2;
  1728.     }
  1729.  
  1730.     public int DistFront(Coord unit)
  1731.     {
  1732.         var front = GetFront();
  1733.         int xp1 = front.x - (front.y - (front.y & 1)) / 2;
  1734.         int zp1 = front.y;
  1735.         int yp1 = -(xp1 + zp1);
  1736.         int xp2 = unit.x - (unit.y - (unit.y & 1)) / 2;
  1737.         int zp2 = unit.y;
  1738.         int yp2 = -(xp2 + zp2);
  1739.         return (Math.Abs(xp1 - xp2) + Math.Abs(yp1 - yp2) + Math.Abs(zp1 - zp2)) / 2;
  1740.     }
  1741.  
  1742.     public int shotDuration(Coord coord)
  1743.     {
  1744.         return 1 + (int)Math.Round(DistFront(coord) / 3.0);
  1745.     }
  1746.  
  1747.  
  1748.  
  1749.     public void MoveTo(int X, int Y, bool custom = true)
  1750.     {
  1751.         Coord currentPosition = new Coord(this.x, this.y);
  1752.         Coord targetPosition = new Coord(X, Y);
  1753.  
  1754.         if (currentPosition.equals(targetPosition))
  1755.         {
  1756.             this.action = Action.FASTER;
  1757.             return;
  1758.         }
  1759.  
  1760.         double targetAngle, angleStraight, anglePort, angleStarboard, centerAngle, anglePortCenter, angleStarboardCenter;
  1761.  
  1762.         switch (speed)
  1763.         {
  1764.             case 2:
  1765.             case 1:
  1766.                 if (!custom && speed == 2)
  1767.                 {
  1768.                     this.action = Action.SLOWER;
  1769.                     break;
  1770.                 }
  1771.                 // Suppose we've moved first
  1772.                 currentPosition = currentPosition.neighbor(orientation);
  1773.                 if (!currentPosition.isInsideMap())
  1774.                 {
  1775.                     this.action = Action.SLOWER;
  1776.                     break;
  1777.                 }
  1778.  
  1779.                 // Target reached at next turn
  1780.                 if (currentPosition.equals(targetPosition))
  1781.                 {
  1782.                     this.action = Action.FASTER;
  1783.                     break;
  1784.                 }
  1785.  
  1786.                 // For each neighbor cell, find the closest to target
  1787.                 targetAngle = currentPosition.angle(targetPosition);
  1788.                 angleStraight = Math.Min(Math.Abs(orientation - targetAngle), 6 - Math.Abs(orientation - targetAngle));
  1789.                 anglePort = Math.Min(Math.Abs((orientation + 1) - targetAngle), Math.Abs((orientation - 5) - targetAngle));
  1790.                 angleStarboard = Math.Min(Math.Abs((orientation + 5) - targetAngle), Math.Abs((orientation - 1) - targetAngle));
  1791.  
  1792.                 centerAngle = currentPosition.angle(new Coord(MAP_WIDTH / 2, MAP_HEIGHT / 2));
  1793.                 anglePortCenter = Math.Min(Math.Abs((orientation + 1) - centerAngle), Math.Abs((orientation - 5) - centerAngle));
  1794.                 angleStarboardCenter = Math.Min(Math.Abs((orientation + 5) - centerAngle), Math.Abs((orientation - 1) - centerAngle));
  1795.  
  1796.                 // Next to target with bad angle, slow down then rotate (avoid to turn around the target!)
  1797.                 if (currentPosition.distanceTo(targetPosition) == 1 && angleStraight > 1.5)
  1798.                 {
  1799.                     this.action = Action.SLOWER;
  1800.                     break;
  1801.                 }
  1802.  
  1803.                 int? distanceMin = null;
  1804.  
  1805.                 // Test forward
  1806.                 Coord nextPosition = currentPosition.neighbor(orientation);
  1807.                 if (nextPosition.isInsideMap())
  1808.                 {
  1809.                     distanceMin = nextPosition.distanceTo(targetPosition);
  1810.                     this.action = Action.WAIT;
  1811.  
  1812.                     int distance = nextPosition.distanceTo(targetPosition);
  1813.                     if (custom && distance > 5)
  1814.                     {
  1815.                         this.action = Action.FASTER;
  1816.                     }
  1817.                 }
  1818.  
  1819.                 // Test port
  1820.                 nextPosition = currentPosition.neighbor((orientation + 1) % 6);
  1821.                 if (nextPosition.isInsideMap())
  1822.                 {
  1823.                     int distance = nextPosition.distanceTo(targetPosition);
  1824.                     if (distanceMin == null || distance < distanceMin || distance == distanceMin && anglePort < angleStraight - 0.5)
  1825.                     {
  1826.                         distanceMin = distance;
  1827.  
  1828.                         if (distance <= 5 && speed == 2 && custom)
  1829.                         {
  1830.                             this.action = Action.SLOWER;
  1831.                         }
  1832.                         else
  1833.                         {
  1834.                             this.action = Action.PORT;
  1835.                         }
  1836.                     }
  1837.                 }
  1838.  
  1839.                 // Test starboard
  1840.                 nextPosition = currentPosition.neighbor((orientation + 5) % 6);
  1841.                 if (nextPosition.isInsideMap())
  1842.                 {
  1843.                     int distance = nextPosition.distanceTo(targetPosition);
  1844.                     if (distanceMin == null || distance < distanceMin
  1845.                             || (distance == distanceMin && angleStarboard < anglePort - 0.5 && this.action == Action.PORT)
  1846.                             || (distance == distanceMin && angleStarboard < angleStraight - 0.5 && this.action == Action.NONE)
  1847.                             || (distance == distanceMin && this.action == Action.PORT && angleStarboard == anglePort
  1848.                                     && angleStarboardCenter < anglePortCenter)
  1849.                             || (distance == distanceMin && this.action == Action.PORT && angleStarboard == anglePort
  1850.                                     && angleStarboardCenter == anglePortCenter && (orientation == 1 || orientation == 4)))
  1851.                     {
  1852.                         distanceMin = distance;
  1853.                         if (distance <= 5 && speed == 2 && custom)
  1854.                         {
  1855.                             this.action = Action.SLOWER;
  1856.                         }
  1857.                         else
  1858.                         {
  1859.                             this.action = Action.STARBOARD;
  1860.                         }
  1861.                     }
  1862.                 }
  1863.                 break;
  1864.             case 0:
  1865.                 // Rotate ship towards target
  1866.                 targetAngle = currentPosition.angle(targetPosition);
  1867.                 angleStraight = Math.Min(Math.Abs(orientation - targetAngle), 6 - Math.Abs(orientation - targetAngle));
  1868.                 anglePort = Math.Min(Math.Abs((orientation + 1) - targetAngle), Math.Abs((orientation - 5) - targetAngle));
  1869.                 angleStarboard = Math.Min(Math.Abs((orientation + 5) - targetAngle), Math.Abs((orientation - 1) - targetAngle));
  1870.  
  1871.                 centerAngle = currentPosition.angle(new Coord(MAP_WIDTH / 2, MAP_HEIGHT / 2));
  1872.                 anglePortCenter = Math.Min(Math.Abs((orientation + 1) - centerAngle), Math.Abs((orientation - 5) - centerAngle));
  1873.                 angleStarboardCenter = Math.Min(Math.Abs((orientation + 5) - centerAngle), Math.Abs((orientation - 1) - centerAngle));
  1874.  
  1875.                 Coord forwardPosition = currentPosition.neighbor(orientation);
  1876.  
  1877.                 this.action = Action.FASTER;
  1878.  
  1879.                 if (anglePort <= angleStarboard)
  1880.                 {
  1881.                     this.action = Action.PORT;
  1882.                 }
  1883.  
  1884.                 if (angleStarboard < anglePort || angleStarboard == anglePort && angleStarboardCenter < anglePortCenter
  1885.                         || angleStarboard == anglePort && angleStarboardCenter == anglePortCenter && (orientation == 1 || orientation == 4))
  1886.                 {
  1887.                     this.action = Action.STARBOARD;
  1888.                 }
  1889.  
  1890.                 if (forwardPosition.isInsideMap() && angleStraight <= anglePort && angleStraight <= angleStarboard)
  1891.                 {
  1892.                     this.action = Action.FASTER;
  1893.                 }
  1894.                 break;
  1895.         }
  1896.  
  1897.     }
  1898.  
  1899. }
  1900. class Rum : Unit
  1901. {
  1902.     public int rum;
  1903.     public bool taken;
  1904.  
  1905.     public Rum Clone()
  1906.     {
  1907.         return new Rum()
  1908.         {
  1909.             id = this.id,
  1910.             x = this.x,
  1911.             y = this.y,
  1912.             rum = this.rum,
  1913.             type = this.type,
  1914.         };
  1915.     }
  1916. }
  1917.  
  1918. class Cannonball : Unit
  1919. {
  1920.     public int shipId;
  1921.     public int turns;
  1922.  
  1923.     public Cannonball() { }
  1924.     public Cannonball(int X, int Y, int Turns)
  1925.     {
  1926.         x = X;
  1927.         y = Y;
  1928.         turns = Turns;
  1929.     }
  1930.  
  1931.     public Cannonball Clone()
  1932.     {
  1933.         return new Cannonball()
  1934.         {
  1935.             x = this.x,
  1936.             y = this.y,
  1937.             id = this.id,
  1938.             type = this.type,
  1939.             shipId = this.shipId,
  1940.             turns = this.turns,
  1941.         };
  1942.     }
  1943.  
  1944.     public bool WillHit(Ship ship)
  1945.     {
  1946.  
  1947.         //ship.SetOffsets(turns * ship.speed);
  1948.         var front = ship.GetFront(turns);
  1949.         var back = ship.GetBack(turns);
  1950.         var middle = ship.GetMiddle(turns);
  1951.  
  1952.         if (Pos().equals(front))
  1953.         {
  1954.             return true;
  1955.         }
  1956.         if (Pos().equals(back))
  1957.         {
  1958.             return true;
  1959.         }
  1960.         if (Pos().equals(middle))
  1961.         {
  1962.             return true;
  1963.         }
  1964.         return false;
  1965.     }
  1966. }
  1967.  
  1968. class Mine : Unit
  1969. {
  1970.     public bool hit;
  1971.  
  1972.     public Mine Clone()
  1973.     {
  1974.         return new Mine()
  1975.         {
  1976.             id = this.id,
  1977.             x = this.x,
  1978.             y = this.y,
  1979.             type = this.type,
  1980.         };
  1981.     }
  1982.  
  1983.     public bool WillHit(Ship ship)
  1984.     {
  1985.         //var advTurns = ship.speed == 2 ? 1 : 2;
  1986.  
  1987.         var front = ship.GetFront(ship.speed + 1);
  1988.         var back = ship.GetBack(ship.speed + 1);
  1989.         var middle = ship.GetMiddle(ship.speed + 1);
  1990.  
  1991.         if (Pos().equals(front))
  1992.         {
  1993.             return true;
  1994.         }
  1995.         if (Pos().equals(back))
  1996.         {
  1997.             return true;
  1998.         }
  1999.         if (Pos().equals(middle))
  2000.         {
  2001.             return true;
  2002.         }
  2003.         return false;
  2004.     }
  2005. }
  2006.  
  2007. public enum Action
  2008. {
  2009.     FASTER, SLOWER, PORT, STARBOARD, FIRE, MINE, NONE, WAIT
  2010. }
  2011. public class Coord
  2012. {
  2013.     private int MAP_WIDTH = 23;
  2014.     private int MAP_HEIGHT = 21;
  2015.     public int[,] DIRECTIONS_EVEN = new int[,] { { 1, 0 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 }, { 0, 1 } };
  2016.     public int[,] DIRECTIONS_ODD = new int[,] { { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, 0 }, { 0, 1 }, { 1, 1 } };
  2017.     public int x;
  2018.     public int y;
  2019.  
  2020.     public Coord(int x, int y)
  2021.     {
  2022.         this.x = x;
  2023.         this.y = y;
  2024.     }
  2025.  
  2026.     public Coord Clone()
  2027.     {
  2028.         return new Coord(x, y);
  2029.     }
  2030.  
  2031.     public Coord(Coord other)
  2032.     {
  2033.         this.x = other.x;
  2034.         this.y = other.y;
  2035.     }
  2036.  
  2037.     public double angle(Coord targetPosition)
  2038.     {
  2039.         double dy = (targetPosition.y - this.y) * Math.Sqrt(3) / 2;
  2040.         double dx = targetPosition.x - this.x + ((this.y - targetPosition.y) & 1) * 0.5;
  2041.         double angle = -Math.Atan2(dy, dx) * 3 / Math.PI;
  2042.         if (angle < 0)
  2043.         {
  2044.             angle += 6;
  2045.         }
  2046.         else if (angle >= 6)
  2047.         {
  2048.             angle -= 6;
  2049.         }
  2050.         return angle;
  2051.     }
  2052.  
  2053.     public CubeCoordinate toCubeCoordinate()
  2054.     {
  2055.         int xp = x - (y - (y & 1)) / 2;
  2056.         int zp = y;
  2057.         int yp = -(xp + zp);
  2058.         return new CubeCoordinate(xp, yp, zp);
  2059.     }
  2060.  
  2061.     public Coord neighbor(int orientation)
  2062.     {
  2063.         int newY, newX;
  2064.         if (this.y % 2 == 1)
  2065.         {
  2066.             newY = this.y + DIRECTIONS_ODD[orientation, 1];
  2067.             newX = this.x + DIRECTIONS_ODD[orientation, 0];
  2068.         }
  2069.         else
  2070.         {
  2071.             newY = this.y + DIRECTIONS_EVEN[orientation, 1];
  2072.             newX = this.x + DIRECTIONS_EVEN[orientation, 0];
  2073.         }
  2074.  
  2075.         return new Coord(newX, newY);
  2076.     }
  2077.  
  2078.     public bool isInsideEdge()
  2079.     {
  2080.         return x >= 3 && x < MAP_WIDTH - 3 && y >= 3 && y < MAP_HEIGHT - 3;
  2081.     }
  2082.  
  2083.     public bool isInsideMap()
  2084.     {
  2085.         return x >= 0 && x < MAP_WIDTH && y >= 0 && y < MAP_HEIGHT;
  2086.     }
  2087.  
  2088.     public int distanceTo(Coord dst)
  2089.     {
  2090.         return this.toCubeCoordinate().distanceTo(dst.toCubeCoordinate());
  2091.     }
  2092.  
  2093.  
  2094.     public bool equals(Object obj)
  2095.     {
  2096.         if (obj == null || this.GetType() != obj.GetType())
  2097.         {
  2098.             return false;
  2099.         }
  2100.         Coord other = (Coord)obj;
  2101.         return y == other.y && x == other.x;
  2102.     }
  2103.  
  2104.     public bool equals(Coord other)
  2105.     {
  2106.         return y == other.y && x == other.x;
  2107.     }
  2108.  
  2109.     public bool equals(int X, int Y)
  2110.     {
  2111.         return y == Y && x == X;
  2112.     }
  2113.  
  2114.     public override string ToString()
  2115.     {
  2116.         return string.Format("{0} {1}", x, y);
  2117.     }
  2118. }
  2119.  
  2120. public class CubeCoordinate
  2121. {
  2122.     int[,] directions = new int[,] { { 1, -1, 0 }, { +1, 0, -1 }, { 0, +1, -1 }, { -1, +1, 0 }, { -1, 0, +1 }, { 0, -1, +1 } };
  2123.     int x, y, z;
  2124.  
  2125.     public CubeCoordinate(int x, int y, int z)
  2126.     {
  2127.         this.x = x;
  2128.         this.y = y;
  2129.         this.z = z;
  2130.     }
  2131.  
  2132.     public CubeCoordinate Clone()
  2133.     {
  2134.         return new CubeCoordinate(x, y, z);
  2135.     }
  2136.  
  2137.     public Coord toOffsetCoordinate()
  2138.     {
  2139.         int newX = x + (z - (z & 1)) / 2;
  2140.         int newY = z;
  2141.         return new Coord(newX, newY);
  2142.     }
  2143.  
  2144.     public CubeCoordinate neighbor(int orientation)
  2145.     {
  2146.         int nx = this.x + directions[orientation, 0];
  2147.         int ny = this.y + directions[orientation, 1];
  2148.         int nz = this.z + directions[orientation, 2];
  2149.  
  2150.         return new CubeCoordinate(nx, ny, nz);
  2151.     }
  2152.  
  2153.     public int distanceTo(CubeCoordinate dst)
  2154.     {
  2155.         return (Math.Abs(x - dst.x) + Math.Abs(y - dst.y) + Math.Abs(z - dst.z)) / 2;
  2156.     }
  2157.  
  2158.  
  2159.     public override string ToString()
  2160.     {
  2161.         return string.Format("{0} {1} {2}", x, y, z);
  2162.     }
  2163. }
  2164.  
  2165. #endregion
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement