public List<DeployArmies> AttackHard(BotState state, int armiesLeft)
        {
            string myName = state.MyPlayerName;
            string opponentName = state.OpponentPlayerName;
            List<DeployArmies> deployArmies = new List<DeployArmies>();

            // pick the target with most strategic value (position and stack advantage)
            foreach (Region rr in state.EnemyBorders)
            {
                rr.tempSortValue = 0;

                // give higher count if positioned in top ranked expansion
                if (rr.SuperRegion.ArmiesReward == 2) rr.tempSortValue += 2;

                // give higher count if we have stack advantage
                int maxarmies = 0;
                foreach (Region rn in rr.Neighbors)
                {
                    if (rn.OwnedByPlayer(myName))
                    {
                        if (rn.Armies > maxarmies) maxarmies = rn.Armies;
                    }
                }
                rr.tempSortValue += maxarmies - rr.Armies;
            }
            var lst = state.EnemyBorders.OrderByDescending(p => p.tempSortValue).ToList();
            Region target = state.FullMap.GetRegion(lst[0].Id);

            // pick the neighbour (our territory) with the highest army count
            foreach (Region rn in target.Neighbors)
            {
                int ac = 0;
                if (rn.OwnedByPlayer(myName))
                {
                    ac += rn.Armies;
                }
                rn.tempSortValue = ac;
            }
            lst = target.Neighbors.OrderByDescending(p => p.tempSortValue).ToList();
            Region attacker = lst[0];

            // validate
            if (target.OwnedByPlayer(opponentName) && attacker.OwnedByPlayer(myName))
            {
                deployArmies.Add(new DeployArmies(myName, attacker, armiesLeft));
                state.ScheduleAttack(attacker, target, armiesLeft, attacker.Armies - 1 + armiesLeft);
                //state.scheduledAttack.Add(new Tuple<int, int, int>(attacker.Id, target.Id, attacker.Armies - 1 + armiesLeft));
                armiesLeft = 0;
            }

            return deployArmies;
        }
        // is only called when no enemy is in sight
        public List<DeployArmies> ExpandTowardsEnemyWithFullStack(BotState state, int armiesLeft)
        {
            string myName = state.MyPlayerName;
            //string opponentName = state.OpponentPlayerName;
            List<DeployArmies> deployArmies = new List<DeployArmies>();

            // determine the best region the opponent is most likely in
            if (state.OpponentStartRegions.Count > 0)
            {

                // find next step on shortest path to get there
                // and schedule an attack in that direction

                int nextstep = state.FullMap.FindNextStep(state.OpponentStartRegions[0].Id);
                if (nextstep != -1)
                {
                    Region region = state.FullMap.GetRegion(nextstep);

                    // find our neighbour with highest available armies
                    foreach (Region a in region.Neighbors)
                    {
                        int aArmies = a.Armies + a.PledgedArmies - a.ReservedArmies;
                        if (aArmies < 0) aArmies = 0;
                        if (!a.OwnedByPlayer(myName)) aArmies = -1;
                        a.tempSortValue = aArmies;
                    }
                    var lst = region.Neighbors.OrderByDescending(p => p.tempSortValue).ToList();
                    Region neigh = state.FullMap.GetRegion(lst[0].Id);
                    if (neigh.OwnedByPlayer(myName))
                    {
                        deployArmies.Add(new DeployArmies(myName, neigh, armiesLeft));
                        int armiesCount = neigh.Armies + neigh.PledgedArmies - neigh.ReservedArmies + armiesLeft - 1;
                        state.ScheduleAttack(neigh, region, armiesLeft, armiesCount );
                    }
                }
            }

            return deployArmies;
        }
        public List<DeployArmies> GetDeployArmiesMoves(BotState state, long timeOut)
        {
            string myName = state.MyPlayerName;
            string opponentName = state.OpponentPlayerName;
            bool enemySighted = state.EnemySighted;
            List<DeployArmies> deployArmies = new List<DeployArmies>();
            int armiesLeft = state.StartingArmies;

            // figure out if the best listed superregion is finishable on this turn
            bool finishableSuperRegion = FinishableSuperRegion(state);

            if (enemySighted)
            {

                // on first rounds, attack any enemies on sight, unless we can finish a super region or have already attacked neutrals
                if ((state.RoundNumber < 5) && !finishableSuperRegion && !state.AttackedOneNeutral)
                {
                    // if we have atleast 2 enemy sightings, pick one and hit it hard
                    List<DeployArmies> deploy = AttackHard(state, armiesLeft);
                    foreach (DeployArmies da in deploy)
                    {
                        deployArmies.Add(da);
                        armiesLeft -= da.Armies;
                    }

                }

                // if we are SABased, northafrica is ours, enemy is in africa, NA is not finished and enemy is not in NA,
                Region northafrica = state.FullMap.GetRegion(21);
                SuperRegion africa = state.FullMap.GetSuperRegion(northafrica.SuperRegion.Id);
                SuperRegion na = state.FullMap.GetSuperRegion(1);

                if (state.SABased && northafrica.OwnedByPlayer(myName) && africa.HasPlayer(state.FullMap, opponentName) &&
                    !na.HasPlayer(state.FullMap, opponentName) && (na.OwnedByPlayer(state.FullMap) != myName) &&
                    state.ExpansionTargets.Count > 0)
                {
                    // do minimum expansion (should be NA or australia)
                    List<DeployArmies> deploy = ExpandMinimum(state, armiesLeft);
                    foreach (DeployArmies da in deploy)
                    {
                        deployArmies.Add(da);
                        armiesLeft -= da.Armies;
                    }

                    // deploy all else on northafrica
                    deployArmies.Add(new DeployArmies(myName, northafrica, armiesLeft));
                    armiesLeft = 0;
                }

                // if game is stuck with high stacks expand to get more income
                if (armiesLeft > 0)
                {
                    bool bigstack = false;
                    foreach (Region reg in state.VisibleMap.Regions)
                    {
                        if (reg.OwnedByPlayer(myName))
                        {
                            if (reg.Armies > 180)
                            {
                                bigstack = true;
                            }
                        }
                    }
                    if (bigstack)
                    {
                        List<DeployArmies> expand = ExpandGameStalled(state, armiesLeft);
                        foreach (DeployArmies da in expand)
                        {
                            deployArmies.Add(da);
                            armiesLeft -= da.Armies;
                        }
                    }
                }

                if (finishableSuperRegion)
                {
                    List<DeployArmies> deploy = FinishSuperRegion(state, armiesLeft);
                    foreach (DeployArmies da in deploy)
                    {
                        deployArmies.Add(da);
                        armiesLeft -= da.Armies;
                    }

                } else {

                    // used to have full attack against spotted enemy super region here, but it's now being taken care of during the next phase

                    // minimum expansion
                    if ((armiesLeft > 0) && (state.ExpansionTargets.Count > 0))
                    {
                        // do minimum expansion, but only on expansiontargets that are close to being finished
                        // or we know the game has been stalled for a while (stacks bigger then, lets say 60)
                        // or we have no superregion at all, so we really need one
                        //todo: and we are fairly certain the target sr is not already being bordered by enemy

                        // check how many territories of the expansion target we already own
                        int count = 0;
                        foreach (Region reg in state.ExpansionTargets[0].SubRegions)
                        {
                            Region rn = state.FullMap.GetRegion(reg.Id);
                            if (rn.OwnedByPlayer(myName)) count++;
                        }

                        bool issafe = true;
                        // check if there are any estimated opponentstartingregions in or bordering this superregion
                        // only check for south america, australia and africa, rest can be considered safe by default
                        if (state.ExpansionTargets[0].ArmiesReward <= 3) {
                            foreach (Region border in state.OpponentStartRegions)
                            {
                                foreach (Region n in border.Neighbors)
                                {
                                    Region b = state.FullMap.GetRegion(n.Id);
                                    if (b.SuperRegion.Id == state.ExpansionTargets[0].Id) issafe = false;
                                }
                            }
                        }

                        // check if the game is starting to have big stacks
                        bool bigstack = false;
                        foreach (Region reg in state.VisibleMap.Regions)
                        {
                            if (reg.OwnedByPlayer(myName))
                            {
                                if (reg.Armies > 60)
                                {
                                    bigstack = true;

                                    // todo: refactor code below to find best path without region hardcoded logic

                                    // check if we are building a bigstack in middle of africa without having eyes on SA and northafrica doesnt belong to the enemy
                                    //Region northafrica = state.FullMap.GetRegion(21);
                                    if ((reg.SuperRegion.Id == 4) && state.FullMap.GetRegion(12).OwnedByPlayer("unknown") && !northafrica.OwnedByPlayer(opponentName))
                                    {
                                        int nextstep = -1;
                                        if (northafrica.OwnedByPlayer("neutral")) nextstep = 21;

                                        if (northafrica.OwnedByPlayer("unknown"))
                                        {
                                            // go through east africa
                                            nextstep = 23;
                                            Region ea = state.FullMap.GetRegion(23);

                                            // if ea is taken by enemy, rethink
                                            if (ea.OwnedByPlayer(opponentName)) {
                                                // if congo is neutral, go through congo
                                                if (state.FullMap.GetRegion(24).OwnedByPlayer("neutral"))
                                                {
                                                    nextstep = 24;
                                                }
                                                // if congo is unknown then i guess we're stuck in madagascar and have to flank through south africa
                                                if (state.FullMap.GetRegion(24).OwnedByPlayer("unknown"))
                                                {
                                                    nextstep = 25;
                                                }
                                            }
                                        }

                                        if (nextstep != -1)
                                        {
                                            Region region = state.FullMap.GetRegion(nextstep);

                                            // find our neighbour with highest available armies
                                            foreach (Region a in region.Neighbors)
                                            {
                                                int aArmies = a.Armies + a.PledgedArmies - a.ReservedArmies;
                                                if (aArmies < 0) aArmies = 0;
                                                if (!a.OwnedByPlayer(myName)) aArmies = -1;
                                                a.tempSortValue = aArmies;
                                            }
                                            var lst = region.Neighbors.OrderByDescending(p => p.tempSortValue).ToList();
                                            Region neigh = state.FullMap.GetRegion(lst[0].Id);
                                            if (neigh.OwnedByPlayer(myName))
                                            {
                                                deployArmies.Add(new DeployArmies(myName, neigh, armiesLeft));
                                                state.ScheduleAttack(neigh, region, armiesLeft, neigh.Armies + armiesLeft - 1);
                                                armiesLeft = 0;
                                            }
                                        }

                                    }
                                }
                            }
                        }

                        // do minimum expansion only when we have a big stack and have safe superregions
                        if ((armiesLeft > 0) && issafe) {
                            if ((count > state.ExpansionTargets[0].SubRegions.Count * 0.5) || (bigstack) || (state.StartingArmies == 5))
                            {
                                List<DeployArmies> deploy = ExpandMinimum(state, armiesLeft);
                                foreach (DeployArmies da in deploy)
                                {
                                    deployArmies.Add(da);
                                    armiesLeft -= da.Armies;
                                }
                            }
                        }
                    }

                }

                // deploy rest of your income bordering the enemy
                List<DeployArmies> placings = DeployBorderingEnemy(state, armiesLeft);
                foreach (DeployArmies da in placings)
                {
                    deployArmies.Add(da);
                    armiesLeft -= da.Armies;
                }

            } else {

                // no enemy in sight, expand normally / strategically

                if (finishableSuperRegion)
                {
                    List<DeployArmies> deploy = FinishSuperRegion(state, armiesLeft);
                    foreach (DeployArmies da in deploy)
                    {
                        deployArmies.Add(da);
                        armiesLeft -= da.Armies;
                    }

                } else {

                    if (state.OZBased)
                    {
                        // if we are based in australia and have no territory in africa, europe or south america
                        // we should be making our way into africa

                        bool thereyet = false;
                        foreach (Region reg in state.VisibleMap.Regions)
                        {
                            if ((reg.SuperRegion.Id == 2) || //SA
                                (reg.SuperRegion.Id == 3) || //europe
                                (reg.SuperRegion.Id == 4)) //africa
                            {
                                thereyet = true;
                            }
                        }

                        if (!thereyet)
                        {
                            // we dont have egypt (22) but have middle east (36)
                            if (!state.FullMap.GetRegion(22).OwnedByPlayer(myName) && state.FullMap.GetRegion(36).OwnedByPlayer(myName))
                            {
                                deployArmies.Add(new DeployArmies(myName, state.FullMap.GetRegion(36), armiesLeft));
                                state.ScheduleAttack(state.FullMap.GetRegion(36), state.FullMap.GetRegion(22), armiesLeft, state.FullMap.GetRegion(36).Armies - 1 + armiesLeft);
                                //state.scheduledAttack.Add(new Tuple<int, int, int>(36, 22, state.FullMap.GetRegion(36).Armies - 1 + armiesLeft));
                                armiesLeft = 0;
                            }
                            else // we dont have middle east (36) but have india (37)
                                if (!state.FullMap.GetRegion(36).OwnedByPlayer(myName) && state.FullMap.GetRegion(37).OwnedByPlayer(myName))
                                {
                                    deployArmies.Add(new DeployArmies(myName, state.FullMap.GetRegion(37), armiesLeft));
                                    state.ScheduleAttack(state.FullMap.GetRegion(37), state.FullMap.GetRegion(36), armiesLeft, state.FullMap.GetRegion(37).Armies - 1 + armiesLeft);
                                    //state.scheduledAttack.Add(new Tuple<int, int, int>(37, 36, state.FullMap.GetRegion(37).Armies - 1 + armiesLeft));
                                    armiesLeft = 0;
                                }
                                else // we dont have india (37) but have siam (38)
                                    if (!state.FullMap.GetRegion(37).OwnedByPlayer(myName) && state.FullMap.GetRegion(38).OwnedByPlayer(myName))
                                    {
                                        deployArmies.Add(new DeployArmies(myName, state.FullMap.GetRegion(38), armiesLeft));
                                        state.ScheduleAttack(state.FullMap.GetRegion(38), state.FullMap.GetRegion(37), armiesLeft, state.FullMap.GetRegion(38).Armies - 1 + armiesLeft);
                                        //state.scheduledAttack.Add(new Tuple<int, int, int>(38, 37, state.FullMap.GetRegion(38).Armies - 1 + armiesLeft));
                                        armiesLeft = 0;
                                    }
                                    else // we dont have siam (38) but have indonesia (39)
                                        if (!state.FullMap.GetRegion(38).OwnedByPlayer(myName) && state.FullMap.GetRegion(39).OwnedByPlayer(myName))
                                        {
                                            deployArmies.Add(new DeployArmies(myName, state.FullMap.GetRegion(39), armiesLeft));
                                            state.ScheduleAttack(state.FullMap.GetRegion(39), state.FullMap.GetRegion(38), armiesLeft, state.FullMap.GetRegion(39).Armies - 1 + armiesLeft);
                                            //state.scheduledAttack.Add(new Tuple<int, int, int>(39, 38, state.FullMap.GetRegion(39).Armies - 1 + armiesLeft));
                                            armiesLeft = 0;
                                        }
                                        else
                                        {
                                            Console.Error.WriteLine("ozbased turn without any action?! (round " + state.RoundNumber + ")");
                                        }
                        }
                        else
                        {
                            // lets go check north africa
                            Region northafrica = state.FullMap.GetRegion(21);
                            if (northafrica.OwnedByPlayer("unknown") || northafrica.OwnedByPlayer("neutral"))
                            {
                                int nextstep = state.FullMap.FindNextStep(12);
                                if (nextstep != -1)
                                {
                                    Region region = state.FullMap.GetRegion(nextstep);

                                    // find our neighbour with highest available armies
                                    foreach (Region a in region.Neighbors)
                                    {
                                        int aArmies = a.Armies + a.PledgedArmies - a.ReservedArmies;
                                        if (aArmies < 0) aArmies = 0;
                                        if (!a.OwnedByPlayer(myName)) aArmies = -1;
                                        a.tempSortValue = aArmies;
                                    }
                                    var lst = region.Neighbors.OrderByDescending(p => p.tempSortValue).ToList();
                                    Region neigh = state.FullMap.GetRegion(lst[0].Id);
                                    if (neigh.OwnedByPlayer(myName))
                                    {
                                        deployArmies.Add(new DeployArmies(myName, neigh, armiesLeft));
                                        state.ScheduleAttack(neigh, region, armiesLeft, neigh.Armies + armiesLeft - 1);
                                        armiesLeft = 0;
                                    }
                                }
                            }

                            //todo: we have foot in africa/europe/south america but enemy could be expanding safely on north america...

                            //todo: how can we be sure we are not wasting armies going to alaska? need to track historic of enemy deployments...

                        }
                    }

                    if (state.AfricaBased) {
                        // if africaBased and not saBased, go hard into brazil
                        if (!state.SABased)
                        {
                            Region rnn = state.FullMap.GetRegion(21); // deploy all on north africa
                            Region r = state.FullMap.GetRegion(12); // attack brazil
                            state.ScheduleFullAttack(rnn, r, armiesLeft);
                            deployArmies.Add(new DeployArmies(myName, rnn, armiesLeft));
                            armiesLeft = 0;

                        }
                        else if (state.FullMap.GetRegion(12).OwnedByPlayer(myName))
                        {
                            // we have brazil and no enemy bordering, so we can predict enemy is coming at us from oz
                            // so go hard into middle east
                            Region rnn = state.FullMap.GetRegion(22); // deploy all on egypt
                            Region r = state.FullMap.GetRegion(36); // attack middle east
                            if (!r.OwnedByPlayer(myName))
                            {
                                state.ScheduleFullAttack(rnn, r, armiesLeft);
                                deployArmies.Add(new DeployArmies(myName, rnn, armiesLeft));
                                armiesLeft = 0;
                            }
                        }
                    }

                    // if saBased and no enemy on north africa, go hard into north africa from brazil
                    if (state.SABased && !state.FullMap.GetRegion(21).OwnedByPlayer(opponentName))
                    {
                        Region rnn = state.FullMap.GetRegion(12); // deploy all on brazil
                        Region r = state.FullMap.GetRegion(21); // attack north africa
                        if (!r.OwnedByPlayer(myName))
                        {
                            state.ScheduleFullAttack(rnn, r, armiesLeft);
                            deployArmies.Add(new DeployArmies(myName, rnn, armiesLeft));
                            armiesLeft = 0;
                        }
                    }

                    if (state.SABased && state.FullMap.GetRegion(21).OwnedByPlayer(myName) && !state.NABased)
                    {
                        // do minimum expansion into north america
                        // expansion target 0 should already be pointing at it
                        if (armiesLeft > 0)
                        {
                            List<DeployArmies> deploy = ExpandMinimum(state, armiesLeft);
                            foreach (DeployArmies da in deploy)
                            {
                                deployArmies.Add(da);
                                armiesLeft -= da.Armies;
                            }
                        }

                        // deploy rest on North Africa
                        if (armiesLeft > 0) {
                            deployArmies.Add(new DeployArmies(myName, state.FullMap.GetRegion(21), armiesLeft));
                            armiesLeft = 0;
                        }
                    }

                }

                // if no priority predictions occurs
                if (armiesLeft > 0)
                {
                    List<DeployArmies> expand = ExpandTowardsEnemyWithFullStack(state, armiesLeft);
                    foreach (DeployArmies da in expand)
                    {
                        deployArmies.Add(da);
                        armiesLeft -= da.Armies;
                    }
                }

            }

            return deployArmies;
        }