Ejemplo n.º 1
0
 public int ComputeScore(MineDistances distances)
 {
     return(distances.GetMines().Sum(mine =>
                                     this.Trees.Sum(tree =>
                                                    tree.Contains(mine) ? tree.Sum(site => distances.GetSquaredDistance(mine, site)) : 0)));
 }
Ejemplo n.º 2
0
        static Move V4Strategy(
            MoveMessage message,
            SolverState solverState)
        {
            var startTime = DateTime.UtcNow;

            var deadLine = startTime.AddMilliseconds(900);

            var myId = solverState.initialState.punter.Value;

            var initialMap = solverState.initialState.map;

            var takenRivers = Utils.ConvertMovesToRivers(initialMap, solverState.moves, (id) => true)
                              .ToLookup(river => river, river => true);

            var availableRivers = initialMap.rivers
                                  .Where(river => !takenRivers.Contains(river))
                                  .ToList();

            var canUseOptions =
                solverState.initialState.settings.options &&
                solverState.moves.Count(move => move.option != null && move.option.punter == myId) < initialMap.mines.Count;

            var adjacencyMap = new AdjacencyMap(initialMap.rivers);

            var mineDistances = new MineDistances(initialMap, adjacencyMap);

            var setupDoneTime = DateTime.UtcNow;

            // if we see a choke, take it
            var chokeFindTask = Task.Run(() =>
            {
                var punters = new List <int>()
                {
                    myId
                };
                if (solverState.initialState.punters.Value == 2)
                {
                    punters.Add(1 - myId);
                }

                foreach (var punter in punters)
                {
                    var availableOptions = new List <River>();
                    if (canUseOptions && punter == myId)
                    {
                        var takenOptions = Utils.ConvertMovesToRivers(initialMap, solverState.moves.Where(move => move.option != null), (id) => true)
                                           .ToLookup(river => river, river => true);

                        availableOptions =
                            Utils.ConvertMovesToRivers(initialMap, solverState.moves, (id) => id != myId)
                            .Where(river => !takenOptions.Contains(river))
                            .ToList();
                    }

                    var chokes = FindChokes(
                        initialMap.mines,
                        Utils.ConvertMovesToRivers(initialMap, solverState.moves, (id) => id == punter).ToList(),
                        availableRivers.Concat(availableOptions).ToList(),
                        deadLine.AddMilliseconds(-100));

                    if (chokes.Any())
                    {
                        var river = chokes[0][0];

                        var chokeAnalysisDoneTime = DateTime.UtcNow;

                        Log(myId, string.Format("[{0}] [{1}] [{2}/{3}]",
                                                punter == myId ? "TakeChoke " : "BlockChoke",
                                                (int)(chokeAnalysisDoneTime - startTime).TotalMilliseconds,
                                                (int)(setupDoneTime - startTime).TotalMilliseconds,
                                                (int)(chokeAnalysisDoneTime - setupDoneTime).TotalMilliseconds));

                        return(availableOptions.Contains(river) ? CreateOptionMove(myId, river) : CreateClaimMove(myId, river));
                    }
                }

                return(null);
            });

            // otherwise just play a move that joins two trees, increases liberty, or increases score
            var trees = new TreeSet(
                Utils.ConvertMovesToRivers(initialMap, solverState.moves, (id) => id == myId),
                initialMap.mines);

            var riversToConsider = availableRivers
                                   .Where(river => trees.Contains(river.source) || trees.Contains(river.target))
                                   .DefaultIfEmpty(availableRivers.First());

            var riversConsidered =
                from river in riversToConsider
                where DateTime.UtcNow < deadLine
                let newTrees = trees.AddRiver(river)
                               let treeCount = newTrees.Trees.Count
                                               let liberty                         = newTrees.ComputeLiberty(availableRivers, adjacencyMap)
                                                                         let score = newTrees.ComputeScore(mineDistances)
                                                                                     select new { river = river, liberty = liberty, score = score, treeCount = treeCount };

            var rankedRivers = riversConsidered
                               .ToList()
                               .OrderBy(i => i.treeCount)
                               .ThenByDescending(i => i.liberty)
                               .ThenByDescending(i => i.score);

            var ans = CreateClaimMove(myId, rankedRivers.First().river);

            var analysisDoneTime = DateTime.UtcNow;

            var zero     = TimeSpan.FromTicks(0);
            var waitTime = deadLine - DateTime.UtcNow;

            waitTime = waitTime < zero ? zero : waitTime;
            chokeFindTask.Wait(waitTime);

            if (chokeFindTask.IsCompleted && chokeFindTask.Result != null)
            {
                return(chokeFindTask.Result);
            }

            var doneTime = DateTime.UtcNow;

            Log(myId, string.Format("[NormalMove] [{0}] [{1}/{2}/{3}] [Trees:{4}] [Liberties:{5}] [Score:{6}]",
                                    (int)(doneTime - startTime).TotalMilliseconds,
                                    (int)(setupDoneTime - startTime).TotalMilliseconds,
                                    (int)(analysisDoneTime - setupDoneTime).TotalMilliseconds,
                                    (int)(doneTime - analysisDoneTime).TotalMilliseconds,
                                    rankedRivers.First().treeCount,
                                    rankedRivers.First().liberty,
                                    rankedRivers.First().score));

            return(ans);
        }
Ejemplo n.º 3
0
        static void Main(string[] args)
        {
            var mapFile = Path.Combine(RootPath, "maps", args[0] + ".json");

            var ais = args.Skip(1).ToList();

            var map = JsonConvert.DeserializeObject <Map>(File.ReadAllText(mapFile));

            var states = Enumerable.Range(0, ais.Count)
                         .Select(idx => RunAi <ReadyMessage>(
                                     0,
                                     ais[idx],
                                     new ServerMessage()
            {
                punter   = idx,
                punters  = ais.Count,
                map      = map,
                settings = new Settings()
                {
                    options = true
                }
            }).state)
                         .ToList();

            var lastMoves = Enumerable.Range(0, ais.Count)
                            .Select(idx => new Move()
            {
                pass = new PassMove()
                {
                    punter = idx
                }
            })
                            .ToList();

            var allMoves = new List <Move>();

            foreach (var moveNumber in Enumerable.Range(0, map.rivers.Count))
            {
                var aiIdx = moveNumber % ais.Count;

                var ch =
                    aiIdx == 0 ? '.' :
                    aiIdx == 1 ? ':' :
                    '*';

                Console.Error.Write(ch);
                Console.Error.Flush();

                var move = RunAi <Move>(
                    moveNumber,
                    ais[aiIdx],
                    new ServerMessage()
                {
                    move = new MoveMessage()
                    {
                        moves = lastMoves
                    },
                    state = states[aiIdx]
                });

                states[aiIdx]    = move.state;
                move.state       = null;
                lastMoves[aiIdx] = move;
                allMoves.Add(move);
            }

            var mineDistances = new MineDistances(map, new AdjacencyMap(map.rivers));

            var scores = Enumerable.Range(0, ais.Count)
                         .Select(idx => (new TreeSet(Utils.ConvertMovesToRivers(map, allMoves, (id) => id == idx))).ComputeScore(mineDistances))
                         .ToList();

            var output = new Output()
            {
                score   = Math.Sign(scores[0] - scores[1]),
                scores  = scores,
                map     = args[0],
                verbose = new VerboseOutput()
                {
                    moves = allMoves
                }
            };

            Console.Error.WriteLine();
            Console.WriteLine(JsonConvert.SerializeObject(output, Formatting.Indented, Parser.SerializerSettings));
        }