public void cuttingposibilities(int maxwide)
        {
            // take the x best values
            List <Playfield> temp = new List <Playfield>();
            Dictionary <Int64, Playfield> tempDict = new Dictionary <Int64, Playfield>();

            posmoves.Sort((a, b) => - (botBase.getPlayfieldValue(a)).CompareTo(botBase.getPlayfieldValue(b)));//want to keep the best

            if (this.useComparison)
            {
                int i   = 0;
                int max = Math.Min(posmoves.Count, maxwide);

                Playfield p = null;
                //foreach (Playfield p in posmoves)
                for (i = 0; i < max; i++)
                {
                    p = posmoves[i];
                    Int64 hash = p.GetPHash();
                    p.hashcode = hash;
                    if (!tempDict.ContainsKey(hash))
                    {
                        tempDict.Add(hash, p);
                    }
                }
                foreach (KeyValuePair <Int64, Playfield> d in tempDict)
                {
                    temp.Add(d.Value);
                }
            }
            else
            {
                temp.AddRange(posmoves);
            }
            posmoves.Clear();
            posmoves.AddRange(temp.GetRange(0, Math.Min(maxwide, temp.Count)));
        }
示例#2
0
        private void startEnemyTurnSimThread(List <Playfield> source, int startIndex, int endIndex)
        {
            int threadnumber = 0;

            lock (threadnumberLocker)
            {
                threadnumber = threadnumberGlobal++;
                Monitor.Pulse(threadnumberLocker);
            }
            if (threadnumber > Ai.Instance.maxNumberOfThreads - 2)
            {
                threadnumber = Ai.Instance.maxNumberOfThreads - 2;
                Helpfunctions.Instance.ErrorLog("You need more threads!");
                return;
            }


            int berserk    = Settings.Instance.berserkIfCanFinishNextTour;
            int printRules = Settings.Instance.printRules;

            for (int i = startIndex; i < endIndex; i++)
            {
                Playfield p = source[i];
                if (p.complete || p.ownHero.HealthPoints <= 0)
                {
                }
                else if (!enoughCalculations)
                {
                    //gernerate actions and play them!
                    List <Action> actions = movegen.GetMoveList(p, usePenalityManager, useCutingTargets, true);

                    if (printRules > 0)
                    {
                        p.endTurnState = new Playfield(p);
                    }
                    foreach (Action a in actions)
                    {
                        Playfield pf = new Playfield(p);
                        pf.doAction(a);
                        pf.evaluatePenality += -pf.ruleWeight + RulesEngine.Instance.getRuleWeight(pf);
                        if (pf.ownHero.HealthPoints > 0 && pf.evaluatePenality < 500)
                        {
                            p.nextPlayfields.Add(pf);
                        }
                    }
                }

                if (isLethalCheck)
                {
                    if (berserk > 0)
                    {
                        p.endTurn();
                        if (p.enemyHero.HealthPoints > 0)
                        {
                            bool needETS = true;
                            if (p.anzEnemyTaunt < 1)
                            {
                                foreach (Minion m in p.ownMinions)
                                {
                                    if (m.Ready)
                                    {
                                        needETS = false; break;
                                    }
                                }
                            }
                            else
                            {
                                if (p.anzOwnTaunt < 1)
                                {
                                    foreach (Minion m in p.ownMinions)
                                    {
                                        if (m.Ready)
                                        {
                                            needETS = false; break;
                                        }
                                    }
                                }
                            }
                            if (needETS)
                            {
                                Ai.Instance.enemyTurnSim[threadnumber].simulateEnemysTurn(p, simulateSecondTurn, playaround, false, playaroundprob, playaroundprob2);
                            }
                        }
                    }

                    p.complete = true;
                }
                else
                {
                    p.endTurn();

                    if (p.enemyHero.HealthPoints > 0)
                    {
                        Ai.Instance.enemyTurnSim[threadnumber].simulateEnemysTurn(p, simulateSecondTurn, playaround, false, playaroundprob, playaroundprob2);
                        if (p.value <= -10000)
                        {
                            bool secondChance = false;
                            foreach (Action a in p.playactions)
                            {
                                if (a.actionType == actionEnum.playcard)
                                {
                                    if (pen.cardDrawBattleCryDatabase.ContainsKey(a.card.card.name))
                                    {
                                        secondChance = true;
                                    }
                                }
                            }

                            if (secondChance)
                            {
                                p.value += 1500;
                            }
                        }
                    }
                    p.complete = true;
                }
                botBase.getPlayfieldValue(p);
            }
        }
示例#3
0
        public float DoAllMoves(Playfield playf)
        {
            print              = playf.print;
            isLethalCheck      = playf.isLethalCheck;
            enoughCalculations = false;
            botBase            = Ai.Instance.botBase;
            posmoves.Clear();
            twoturnfields.Clear();
            addToPosmoves(playf);
            bool             havedonesomething = true;
            List <Playfield> temp = new List <Playfield>();
            int deep = 0;

            calculated = 0;
            Playfield bestold = null;

            bestoldval = -20000000;
            while (havedonesomething)
            {
                if (printNormalstuff)
                {
                    LogHelper.WriteCombatLog($"ailoop{deep}");
                }
                GC.Collect();
                temp.Clear();
                temp.AddRange(posmoves);
                posmoves.Clear();
                havedonesomething  = false;
                threadnumberGlobal = 0;

                if (print)
                {
                    startEnemyTurnSimThread(temp, 0, temp.Count);
                }
                else
                {
                    Parallel.ForEach(Partitioner.Create(0, temp.Count),
                                     range =>
                    {
                        startEnemyTurnSimThread(temp, range.Item1, range.Item2);
                    });
                }

                foreach (Playfield p in temp)
                {
                    if (totalboards > 0)
                    {
                        calculated += p.nextPlayfields.Count;
                    }
                    if (calculated <= totalboards)
                    {
                        posmoves.AddRange(p.nextPlayfields);
                        p.nextPlayfields.Clear();
                    }

                    //get the best Playfield
                    float pVal = botBase.getPlayfieldValue(p);
                    if (pVal > bestoldval)
                    {
                        bestoldval = pVal;
                        bestold    = p;
                        bestoldDuplicates.Clear();
                    }
                    else if (Math.Abs(pVal - bestoldval) < 0.001f)
                    {
                        bestoldDuplicates.Add(p);
                    }
                }

                if (isLethalCheck && bestoldval >= 10000)
                {
                    posmoves.Clear();
                }

                if (posmoves.Count > 0)
                {
                    havedonesomething = true;
                }

                if (printNormalstuff)
                {
                    int donec = 0;
                    foreach (Playfield p in posmoves)
                    {
                        if (p.complete)
                        {
                            donec++;
                        }
                    }
                    LogHelper.WriteCombatLog("deep " + deep + " len " + posmoves.Count + " dones " + donec);
                }

                cuttingposibilities(isLethalCheck);//will update posmoves

                if (printNormalstuff)
                {
                    LogHelper.WriteCombatLog("cut to len " + posmoves.Count);
                }

                int itemPlayfieldIndex = 0;
                foreach (var itemPlayfield in posmoves)
                {
                    itemPlayfieldIndex++;
                    var actionsCount = itemPlayfield.playactions.Count;
                    LogHelper.WriteTestCombatLog($"{nameof(itemPlayfield)}{itemPlayfieldIndex} with {actionsCount} actions");
                    itemPlayfield.printActions();
                }
                deep++;
                temp.Clear();

                if (calculated > totalboards)
                {
                    enoughCalculations = true;
                }

                if (deep >= maxdeep)
                {
                    enoughCalculations = true;
                }
            }

            if (dirtyTwoTurnSim > 0 && !twoturnfields.Contains(bestold))
            {
                twoturnfields.Add(bestold);
            }
            posmoves.Clear();
            posmoves.Add(bestold);
            posmoves.AddRange(bestoldDuplicates);

            // search the best play...........................................................
            //do dirtytwoturnsim first :D
            if (!isLethalCheck && bestoldval < 10000)
            {
                doDirtyTwoTurnsim();
            }

            if (posmoves.Count >= 1)
            {
                posmoves.Sort((a, b) => botBase.getPlayfieldValue(b).CompareTo(botBase.getPlayfieldValue(a)));
                Playfield bestplay = posmoves[0];
                float     bestval  = botBase.getPlayfieldValue(bestplay);
                int       pcount   = posmoves.Count;
                for (int i = 1; i < pcount; i++)
                {
                    float val = botBase.getPlayfieldValue(posmoves[i]);
                    if (bestval > val)
                    {
                        break;
                    }
                    if (posmoves[i].cardsPlayedThisTurn > bestplay.cardsPlayedThisTurn)
                    {
                        continue;
                    }
                    if (posmoves[i].cardsPlayedThisTurn == bestplay.cardsPlayedThisTurn)
                    {
                        if (bestplay.optionsPlayedThisTurn > posmoves[i].optionsPlayedThisTurn)
                        {
                            continue;
                        }
                        if (bestplay.optionsPlayedThisTurn == posmoves[i].optionsPlayedThisTurn && bestplay.enemyHero.HealthPoints <= posmoves[i].enemyHero.HealthPoints)
                        {
                            continue;
                        }
                    }
                    bestplay = posmoves[i];
                    bestval  = val;
                }
                bestmove                 = bestplay.getNextAction();
                bestmoveValue            = bestval;
                bestboard                = new Playfield(bestplay);
                bestboard.guessingHeroHP = bestplay.guessingHeroHP;
                bestboard.value          = bestplay.value;
                bestboard.hashcode       = bestplay.hashcode;
                bestoldDuplicates.Clear();
                return(bestval);
            }
            bestmove      = null;
            bestmoveValue = -100000;
            bestboard     = playf;

            return(-10000);
        }
        public float doallmoves(Playfield playf, bool print = false)
        {
            //todo only one time!
            bool isLethalCheck   = playf.isLethalCheck;
            int  totalboards     = Settings.Instance.nextTurnTotalBoards;
            int  maxwide         = Settings.Instance.nextTurnMaxWide;
            int  maxdeep         = Settings.Instance.nextTurnDeep;
            bool playaround      = Settings.Instance.playaround;
            int  playaroundprob  = Settings.Instance.playaroundprob;
            int  playaroundprob2 = Settings.Instance.playaroundprob2;

            botBase = Ai.Instance.botBase;
            this.posmoves.Clear();
            this.posmoves.Add(new Playfield(playf));
            bool             havedonesomething = true;
            List <Playfield> temp = new List <Playfield>();
            int deep = 0;

            this.calculated = 0;
            Playfield bestold    = null;
            float     bestoldval = -20000000;

            while (havedonesomething)
            {
                //GC.Collect();
                temp.Clear();
                temp.AddRange(this.posmoves);
                havedonesomething = false;
                foreach (Playfield p in temp)
                {
                    if (p.complete || p.ownHero.HealthPoints <= 0)
                    {
                        continue;
                    }

                    List <Action> actions = movegen.GetMoveList(p, usePenalityManager, useCutingTargets, true);
                    foreach (Action a in actions)
                    {
                        havedonesomething = true;
                        Playfield pf = new Playfield(p);
                        pf.doAction(a);
                        if (pf.ownHero.HealthPoints > 0)
                        {
                            this.posmoves.Add(pf);
                        }
                        if (totalboards > 0)
                        {
                            this.calculated++;
                        }
                    }


                    p.endTurn();

                    if (!isLethalCheck)
                    {
                        this.startEnemyTurnSim(p, this.simulateSecondTurn, false, playaround, playaroundprob, playaroundprob2);
                    }

                    //sort stupid stuff ouf

                    if (botBase.getPlayfieldValue(p) > bestoldval)
                    {
                        bestoldval = botBase.getPlayfieldValue(p);
                        bestold    = p;
                    }
                    posmoves.Remove(p);

                    if (this.calculated > totalboards)
                    {
                        break;
                    }
                }
                cuttingposibilities(maxwide);

                deep++;

                if (this.calculated > totalboards)
                {
                    break;
                }
                if (deep >= maxdeep)
                {
                    break;
                }
            }

            posmoves.Add(bestold);
            foreach (Playfield p in posmoves)
            {
                if (!p.complete)
                {
                    p.endTurn();
                    if (!isLethalCheck)
                    {
                        this.startEnemyTurnSim(p, this.simulateSecondTurn, false, playaround, playaroundprob, playaroundprob2);
                    }
                }
            }
            // find best

            if (posmoves.Count >= 1)
            {
                posmoves.Sort((a, b) => botBase.getPlayfieldValue(b).CompareTo(botBase.getPlayfieldValue(a)));

                Playfield bestplay = posmoves[0];
                float     bestval  = botBase.getPlayfieldValue(bestplay);
                int       pcount   = posmoves.Count;
                for (int i = 1; i < pcount; i++)
                {
                    float val = botBase.getPlayfieldValue(posmoves[i]);
                    if (bestval > val)
                    {
                        break;
                    }
                    if (bestplay.playactions.Count <= posmoves[i].playactions.Count)
                    {
                        continue;                                                              //priority to the minimum acts
                    }
                    bestplay = posmoves[i];
                    bestval  = val;
                }
                this.bestmove      = bestplay.getNextAction();
                this.bestmoveValue = bestval;
                this.bestboard     = new Playfield(bestplay);
                return(bestval);
            }
            this.bestmove      = null;
            this.bestmoveValue = -100000;
            this.bestboard     = playf;
            return(-10000);
        }