private bool TryBuildNewComponent(out AiMoveDecision move)
        {
            var queue = new Queue <BuildQueueItem>();
            var used  = new Dictionary <int, BuildQueueItem>();

            foreach (var mineV in graph.GetNotOwnedMines(state.punter))
            {
                var queueItem = new BuildQueueItem
                {
                    CurrentVertex = mineV,
                    SourceMine    = mineV,
                    FirstEdge     = null
                };

                queue.Enqueue(queueItem);
                used.Add(mineV.Id, queueItem);
            }

            while (queue.Count > 0)
            {
                var current = queue.Dequeue();
                foreach (var edge in current.CurrentVertex.Edges.Where(x => x.CanBeOwnedBy(state.punter, allowToUseOptions)))
                {
                    var            next = graph.Vertexes[edge.To];
                    BuildQueueItem prev;
                    if (used.TryGetValue(next.Id, out prev))
                    {
                        if (prev.SourceMine != current.SourceMine)
                        {
                            var bestMine = SelectBestMine(prev.SourceMine, current.SourceMine);
                            if (bestMine == prev.SourceMine)
                            {
                                var edge1 = prev.FirstEdge ?? edge;
                                move = AiMoveDecision.ClaimOrOption(edge1, state.punter, allowToUseOptions);
                                return(true);
                            }
                            if (bestMine == current.SourceMine)
                            {
                                var edge1 = current.FirstEdge ?? edge;
                                move = AiMoveDecision.ClaimOrOption(edge1, state.punter, allowToUseOptions);
                                return(true);
                            }
                        }
                    }
                    else
                    {
                        var queueItem = new BuildQueueItem
                        {
                            CurrentVertex = next,
                            SourceMine    = current.SourceMine,
                            FirstEdge     = current.FirstEdge ?? edge
                        };
                        queue.Enqueue(queueItem);
                        used.Add(next.Id, queueItem);
                    }
                }
            }
            move = null;
            return(false);
        }
예제 #2
0
        public AiMoveDecision GetNextMove(State state, IServices services)
        {
            var myStrategy      = StrategyProvider(state, services);
            var enemyStrategies = Enumerable.Range(0, state.punters)
                                  .Except(new[] { state.punter })
                                  .Select(enemyId => StrategyProvider(state, services))
                                  .ToArray();
            var bestTurn       = GetMyBestTurn(myStrategy);
            var enemyBestTurns = enemyStrategies
                                 .Select(s => s.NextTurns())
                                 .Where(ts => ts.Count >= 2)
                                 .Select(ts => ts.OrderByDescending(x => x.Estimation).Take(2).ToArray())
                                 .ToArray();

            if (enemyBestTurns.Any())
            {
                var bestestEnemyTurns = enemyBestTurns.MaxBy(ts => ts[0].Estimation - ts[1].Estimation);
                if (bestestEnemyTurns[0].Estimation > Settings.EnemyTurnEstimationDifferenceWeight *
                    bestestEnemyTurns[1].Estimation &&
                    bestestEnemyTurns[0].Estimation > Settings.MyTurnEsimationWeight * bestTurn.Estimation)
                {
                    bestTurn = bestestEnemyTurns[0];
                }
            }
            if (bestTurn.Estimation < 0)
            {
                return(AiMoveDecision.Pass(state.punter));
            }
            return(bestTurn.Move);
        }
        public List <TurnResult> NextTurns()
        {
            var result = new List <TurnResult>();
            var mines  = Graph.Mines.Keys.ToList();

            for (var i = 0; i < mines.Count; i++)
            {
                for (var j = i + 1; j < mines.Count; j++)
                {
                    var denic = new Dinic(Graph, PunterId, mines[i], mines[j], out int flow);
                    if (flow == 0 || flow == Dinic.INF)
                    {
                        continue;
                    }
                    var cut = denic.GetMinCut();
                    foreach (var edge in cut)
                    {
                        result.Add(
                            new TurnResult
                        {
                            Estimation = Random.Value.NextDouble(),
                            Move       = AiMoveDecision.Claim(edge, PunterId, "Because I'm crazy!")
                        });
                    }
                }
            }
            return(result);
        }
        private List <TurnResult> GetTurnsForComponents(Graph graph, ConnectedComponent[] connectedComponents, ConnectedComponent currentComponent)
        {
            EdgeWeighter.Init(connectedComponents, currentComponent);

            var vertices = currentComponent.Vertices
                           .SelectMany(v => graph.Vertexes[v].Edges)
                           .ToList();

            var claimVertices = vertices
                                .Where(e => e.Owner == -1 && !AreConnected(currentComponent, e.From, e.To))
                                .Select(e => new TurnResult
            {
                Estimation = EdgeWeighter.EstimateWeight(e),
                Move       = AiMoveDecision.Claim(e, PunterId)
            });

            var optionVertices = !State.settings.options || State.map.OptionsLeft(State.punter) <= 0
                ? Enumerable.Empty <TurnResult>()
                : vertices
                                 .Where(e => e.Owner != -1 && e.OptionOwner == -1 && !AreConnected(currentComponent, e.From, e.To))
                                 .Select(e => new TurnResult
            {
                Estimation = EdgeWeighter.EstimateWeight(e) * OptionPenaltyMultiplier,
                Move       = AiMoveDecision.Option(e, PunterId)
            }).ToList();

            return(claimVertices.Concat(optionVertices)
                   .Where(t => t.Estimation > 0)
                   .ToList());
        }
        public List <TurnResult> NextTurns()
        {
            var claimedVertexes = Graph.Vertexes.Values
                                  .SelectMany(x => x.Edges)
                                  .Where(edge => edge.Owner == PunterId)
                                  .SelectMany(edge => new[] { edge.From, edge.To })
                                  .Distinct()
                                  .ToArray();

            if (claimedVertexes.Length == 0)
            {
                return(Graph.Mines.Values
                       .SelectMany(v => v.Edges)
                       .Where(e => e.Owner == -1)
                       .Select(
                           e => new TurnResult
                {
                    Estimation = 1,
                    Move = AiMoveDecision.Claim(e, PunterId, "No edges yet, selecting first mine")
                })
                       .ToList());
            }

            var connectedComponents = ConnectedComponentsService.For(PunterId);
            var maxComponent        = connectedComponents.MaxBy(comp => comp.Vertices.Count);

            EdgeWeighter.Init(connectedComponents, maxComponent);

            var vertices = maxComponent.Vertices
                           .SelectMany(v => Graph.Vertexes[v].Edges)
                           .ToList();

            var claimVertices = vertices
                                .Where(e => e.Owner == -1 && !AreConnected(maxComponent, e.From, e.To))
                                .Select(
                e => new TurnResult
            {
                Estimation = EdgeWeighter.EstimateWeight(e),
                Move       = AiMoveDecision.Claim(e, PunterId)
            });


            var optionVertices = !State.settings.options || State.map.OptionsLeft(State.punter) <= 0
                ? Enumerable.Empty <TurnResult>()
                : vertices
                                 .Where(e => e.Owner != -1 && e.OptionOwner == -1 && !AreConnected(maxComponent, e.From, e.To))
                                 .Select(e => new TurnResult
            {
                Estimation = EdgeWeighter.EstimateWeight(e) * OptionPenaltyMultiplier,
                Move       = AiMoveDecision.Option(e, PunterId)
            }).ToList();

            return(claimVertices.Concat(optionVertices)
                   .Where(t => t.Estimation > 0)
                   .ToList());
        }
        private AiMoveDecision TryGetNextMove()
        {
            var sitesToDefend = state.aiSetupDecision.futures.SelectMany(f => new[] { f.source, f.target }).ToArray();
            var edge          = new MovesSelector(allowToUseOptions, state.map, graph, sitesToDefend, state.punter).GetNeighbourToGo();

            if (edge != null)
            {
                return(AiMoveDecision.ClaimOrOption(edge, state.punter, allowToUseOptions, "futures cant wait!!1"));
            }
            return(null);
        }
예제 #7
0
        public AiMoveDecision GetNextMove(State state, IServices services)
        {
            var strategy = StrategyProvider(state, services);
            var turns    = strategy.NextTurns();

            if (!turns.Any())
            {
                return(AiMoveDecision.Pass(state.punter));
            }
            return(turns.MaxBy(x => x.Estimation).Move);
        }
            public List <TurnResult> NextTurns()
            {
                Init();

                return(edgesToBlock.Keys
                       .Select(
                           edge => new TurnResult
                {
                    Estimation = EstimateWeight(edge),
                    Move = AiMoveDecision.ClaimOrOption(edge, PunterId, allowToUseOptions)
                })
                       .Where(river => river.Estimation > 0)
                       .ToList());
            }
예제 #9
0
        public List <TurnResult> NextTurns()
        {
            Init();

            return(Graph.Vertexes.Values
                   .SelectMany(v => v.Edges)
                   .Select(
                       edge => edge.IsFree ? new TurnResult
            {
                Estimation = EstimateWeight(edge),
                Move = AiMoveDecision.Claim(edge, PunterId),
            } : null)
                   .Where(river => river != null && river.Estimation > 0)
                   .ToList());
        }
 private static AiMoveDecision GetNextMove(IAi ai, State state, bool eatExceptions, Dictionary <IAi, Exception> lastException)
 {
     try
     {
         return(ai.GetNextMove(state, new Services(state)));
     }
     catch (Exception e)
     {
         lastException[ai] = e;
         if (eatExceptions)
         {
             return(AiMoveDecision.Pass(state.punter, e.ToString()));
         }
         else
         {
             throw;
         }
     }
 }
예제 #11
0
        private bool TryExtendComponent(out AiMoveDecision move)
        {
            //TODO Сейчас увеличивает первую попавшуюся компоненту. А может быть нужно расширять самую большую компоненту.
            var queue = new Queue <ExtendQueueItem>();
            var used  = new HashSet <int>();

            foreach (var mineV in graph.GetNotOwnedMines(state.punter))
            {
                var queueItem = new ExtendQueueItem
                {
                    CurrentVertex = mineV,
                    Edge          = null
                };

                queue.Enqueue(queueItem);
                used.Add(mineV.Id);
            }
            while (queue.Count > 0)
            {
                var current = queue.Dequeue();
                if (current.CurrentVertex.Edges.Any(x => x.IsOwnedBy(state.punter)))
                {
                    move = AiMoveDecision.ClaimOrOption(current.Edge, state.punter, allowToUseOptions);
                    return(true);
                }
                foreach (var edge in current.CurrentVertex.Edges.Where(x => x.CanBeOwnedBy(state.punter, allowToUseOptions)))
                {
                    var next = graph.Vertexes[edge.To];
                    if (!used.Contains(next.Id))
                    {
                        var queueItem = new ExtendQueueItem
                        {
                            CurrentVertex = next,
                            Edge          = edge
                        };
                        queue.Enqueue(queueItem);
                        used.Add(next.Id);
                    }
                }
            }
            move = null;
            return(false);
        }
        private AiMoveDecision TryGetNextMove()
        {
            var meetingPoint = meetingPointService.MeetingPoint;

            var toDo = graph.GetNotOwnedMines(state.punter).Select(x => x.Id);

            var myVerts = graph.Vertexes.Values.Where(
                v =>
                v.Edges.Any(e => e.IsOwnedBy(state.punter)) || v.Id == meetingPoint)
                          .Select(x => x.Id)
                          .ToList();

            var shortest = new ShortestPathFinder(graph, state.punter, myVerts);

            var skip = false;

            foreach (var mine in toDo)
            {
                var path = shortest.GetPath(mine);

                if (path == null)
                {
                    continue;
                }

                int len = path.Count - 1;
                if (len > state.credits[state.punter])
                {
                    skip = true;
                    continue;
                }

                return(AiMoveDecision.Splurge(state.punter, path.ToArray()));
            }

            if (skip)
            {
                return(AiMoveDecision.Pass(state.punter, "wait"));
            }
            return(null);
        }
        public List <TurnResult> NextTurns()
        {
            var calculator = new ConnectedCalculator(Graph, PunterId);
            var result     = new List <TurnResult>();

            foreach (var vertex in Graph.Vertexes.Values)
            {
                foreach (var edge in vertex.Edges.Where(x => x.CanBeOwnedBy(PunterId, allowToUseOptions)))
                {
                    var fromMines = calculator.GetConnectedMines(edge.From);
                    var toMines   = calculator.GetConnectedMines(edge.To);
                    var fromScore = CalcVertexScore(toMines, fromMines, edge.From);
                    var toScore   = CalcVertexScore(fromMines, toMines, edge.To);
                    var addScore  = AggregateEdgeScores(fromScore, toScore);
                    result.Add(
                        new TurnResult
                    {
                        Estimation = addScore,
                        Move       = AiMoveDecision.ClaimOrOption(edge, PunterId, allowToUseOptions)
                    });
                }
            }
            return(result);
        }