Пример #1
0
        internal void RenderFastForward(
            bool render,
            Block <T> oldTip,
            Block <T> newTip,
            Block <T> branchpoint,
            IReadOnlyList <Block <T> > fastForwardPath,
            StateCompleterSet <T> stateCompleters)
        {
            if (render && ActionRenderers.Any())
            {
                _logger.Debug("Rendering actions in new chain.");

                long count = 0;
                foreach (Block <T> block in fastForwardPath)
                {
                    ImmutableList <ActionEvaluation> evaluations =
                        ActionEvaluator.Evaluate(block, stateCompleters).ToImmutableList();

                    count += RenderActions(
                        evaluations: evaluations,
                        block: block,
                        stateCompleters: stateCompleters);
                }

                _logger.Debug(
                    $"{nameof(Swap)}() completed rendering {{Count}} actions.",
                    count);

                foreach (IActionRenderer <T> renderer in ActionRenderers)
                {
                    renderer.RenderBlockEnd(oldTip, newTip);
                }
            }
        }
Пример #2
0
        internal void RenderRewind(
            bool render,
            Block <T> oldTip,
            Block <T> newTip,
            Block <T> branchpoint,
            IReadOnlyList <Block <T> > rewindPath,
            StateCompleterSet <T> stateCompleters)
        {
            if (render && ActionRenderers.Any())
            {
                // Unrender stale actions.
                _logger.Debug("Unrendering abandoned actions...");

                long count = 0;

                foreach (Block <T> block in rewindPath)
                {
                    ImmutableList <ActionEvaluation> evaluations =
                        ActionEvaluator.Evaluate(block, stateCompleters)
                        .ToImmutableList().Reverse();

                    count += UnrenderActions(
                        evaluations: evaluations,
                        block: block,
                        stateCompleters: stateCompleters);
                }

                _logger.Debug(
                    $"{nameof(Swap)}() completed unrendering {{Actions}} actions.",
                    count);
            }
        }
Пример #3
0
        public void StateDeepCopyTest()
        {
            var game = new GameInstance(3);

            var ability   = new AbilityInfo(3, 1, 1, 0);
            var abilityId = game.AddAbilityWithInfo(ability);

            var abilities1 = new List <int>();
            var abilities2 = new List <int> {
                abilityId
            };

            var info1 = new MobInfo(TeamColor.Red, 5, 1, 0, abilities1);
            var info2 = new MobInfo(TeamColor.Blue, 5, 1, 1, abilities2);

            var m1 = game.AddMobWithInfo(info1);
            var m2 = game.AddMobWithInfo(info2);

            game.PrepareEverything();

            var copy = game.CopyStateOnly();

            TestHelpers.GameInstancesEqual(game, copy);

            var copy2 = copy.CopyStateOnly();

            ActionEvaluator.F(copy2, UctAction.AbilityUseAction(abilityId, m1, m2));

            TestHelpers.GameInstancesEqual(game, copy);

            TestHelpers.MobManagersEqual(game.MobManager, copy2.MobManager);
            TestHelpers.MapsEqual(game.Map, copy2.Map);
        }
Пример #4
0
        public void BasicIniciativeTest()
        {
            var game = new GameInstance(3);
            var m2   = game.AddMobWithInfo(new MobInfo(TeamColor.Blue, 10, 10, 2, new List <int>()));
            var m3   = game.AddMobWithInfo(new MobInfo(TeamColor.Blue, 10, 10, 3, new List <int>()));
            var m4   = game.AddMobWithInfo(new MobInfo(TeamColor.Red, 10, 10, 4, new List <int>()));
            var m1   = game.AddMobWithInfo(new MobInfo(TeamColor.Red, 10, 10, 1, new List <int>()));

            game.PrepareEverything();

            Assert.AreEqual(game.CurrentMob, m1);

            ActionEvaluator.FNoCopy(game, UctAction.EndTurnAction());
            Assert.AreEqual(game.CurrentMob, m2);

            ActionEvaluator.FNoCopy(game, UctAction.EndTurnAction());
            Assert.AreEqual(game.CurrentMob, m3);

            ActionEvaluator.FNoCopy(game, UctAction.EndTurnAction());
            Assert.AreEqual(game.CurrentMob, m4);

            // At this point a new turn should start

            ActionEvaluator.FNoCopy(game, UctAction.EndTurnAction());
            Assert.AreEqual(game.CurrentMob, m1);

            ActionEvaluator.FNoCopy(game, UctAction.EndTurnAction());
            Assert.AreEqual(game.CurrentMob, m2);

            ActionEvaluator.FNoCopy(game, UctAction.EndTurnAction());
            Assert.AreEqual(game.CurrentMob, m3);

            ActionEvaluator.FNoCopy(game, UctAction.EndTurnAction());
            Assert.AreEqual(game.CurrentMob, m4);
        }
Пример #5
0
        /// <summary>
        /// Runs a playout with two given controllers and reports the result.
        /// </summary>
        public static PlayoutResult Playout(GameInstance game, IMobController ai1, IMobController ai2)
        {
            var hub = new GameEventHub(game);

            game.MobManager.Teams[TeamColor.Red]  = ai1;
            game.MobManager.Teams[TeamColor.Blue] = ai2;

            const int maxIterations = 100;
            int       i             = 0;

            for (; i < maxIterations && !game.IsFinished; i++)
            {
                game.CurrentController.FastPlayTurn(hub);
                ActionEvaluator.FNoCopy(game, UctAction.EndTurnAction());
            }

            float totalMaxHp     = 0;
            float totalCurrentHp = 0;

            foreach (var mobId in game.MobManager.Mobs)
            {
                totalMaxHp     += game.MobManager.MobInfos[mobId].MaxHp;
                totalCurrentHp += Math.Max(0, game.State.MobInstances[mobId].Hp);
            }

            int red  = 0;
            int blue = 0;

            Utils.Log(LogSeverity.Error, nameof(GameEvaluator),
                      $"Playout time limit reached at {maxIterations} rounds");

            if (i < maxIterations && game.VictoryTeam.HasValue)
            {
                if (game.VictoryTeam.Value == TeamColor.Red)
                {
                    red++;
                }
                else
                {
                    blue++;
                }

                Accounting.IncrementWinner(game.VictoryController);
            }


            var gamePercentage = totalCurrentHp / totalMaxHp;

            Debug.Assert(gamePercentage >= 0);

            var mobsCount = game.MobManager.Mobs.Count;

            var dis = new Normal(mobsCount * 2, mobsCount);

            dis.Density(mobsCount * 2);

            return(new PlayoutResult(i, gamePercentage, game.State.AllPlayed, i == maxIterations, red, blue));
        }
Пример #6
0
        internal long RenderActions(
            IReadOnlyList <ActionEvaluation> evaluations,
            Block <T> block,
            StateCompleterSet <T> stateCompleters)
        {
            DateTimeOffset startTime = DateTimeOffset.UtcNow;

            _logger.Debug(
                "Rendering actions in block #{BlockIndex} {BlockHash}...",
                block.Index,
                block.Hash);

            if (evaluations is null)
            {
                evaluations = ActionEvaluator.Evaluate(block, stateCompleters);
            }

            long count = 0;

            foreach (var evaluation in evaluations)
            {
                foreach (IActionRenderer <T> renderer in ActionRenderers)
                {
                    if (evaluation.Exception is null)
                    {
                        renderer.RenderAction(
                            evaluation.Action,
                            evaluation.InputContext.GetUnconsumedContext(),
                            evaluation.OutputStates);
                    }
                    else
                    {
                        renderer.RenderActionError(
                            evaluation.Action,
                            evaluation.InputContext.GetUnconsumedContext(),
                            evaluation.Exception);
                    }

                    count++;
                }
            }

            TimeSpan renderDuration = DateTimeOffset.Now - startTime;

            _logger
            .ForContext("Tag", "Metric")
            .ForContext("Subtag", "BlockRenderDuration")
            .Debug(
                "Finished rendering {RenderCount} renders for actions in " +
                "block #{BlockIndex} {BlockHash} in {DurationMs:F0}ms.",
                count,
                block.Index,
                block.Hash,
                renderDuration.TotalMilliseconds);
            return(count);
        }
Пример #7
0
        public void Idempotent()
        {
            // NOTE: This test checks that blocks can be evaluated idempotently. Also it checks
            // the action results in pre-evaluation step and in evaluation step are equal.
            const int repeatCount = 2;
            var       signer      = new PrivateKey();
            var       timestamp   = DateTimeOffset.UtcNow;
            var       txAddress   = signer.ToAddress();
            var       txs         = new[]
            {
                Transaction <RandomAction> .Create(
                    nonce : 0,
                    privateKey : signer,
                    genesisHash : null,
                    actions : new[] { new RandomAction(txAddress), }),
            };
            var stateStore = new TrieStateStore(new MemoryKeyValueStore());
            HashAlgorithmGetter hashAlgorithmGetter            = _ => HashAlgorithmType.Of <SHA256>();
            PreEvaluationBlock <RandomAction> noStateRootBlock = MineGenesis(
                hashAlgorithmGetter: hashAlgorithmGetter,
                miner: GenesisMiner.PublicKey,
                timestamp: timestamp,
                transactions: txs
                );
            Block <RandomAction> stateRootBlock =
                noStateRootBlock.Evaluate(GenesisMiner, null, stateStore);
            var actionEvaluator =
                new ActionEvaluator <RandomAction>(
                    hashAlgorithmGetter: hashAlgorithmGetter,
                    policyBlockAction: null,
                    stateGetter: ActionEvaluator <RandomAction> .NullStateGetter,
                    balanceGetter: ActionEvaluator <RandomAction> .NullBalanceGetter,
                    trieGetter: null);
            var generatedRandomNumbers = new List <int>();

            AssertPreEvaluationBlocksEqual(stateRootBlock, noStateRootBlock);

            for (int i = 0; i < repeatCount; ++i)
            {
                var actionEvaluations = actionEvaluator.Evaluate(
                    noStateRootBlock,
                    StateCompleterSet <RandomAction> .Reject);
                generatedRandomNumbers.Add(
                    (Integer)actionEvaluations[0].OutputStates.GetState(txAddress));
                actionEvaluations = actionEvaluator.Evaluate(
                    stateRootBlock,
                    StateCompleterSet <RandomAction> .Reject);
                generatedRandomNumbers.Add(
                    (Integer)actionEvaluations[0].OutputStates.GetState(txAddress));
            }

            for (int i = 1; i < generatedRandomNumbers.Count; ++i)
            {
                Assert.Equal(generatedRandomNumbers[0], generatedRandomNumbers[i]);
            }
        }
Пример #8
0
        /// <summary>
        /// Simulates the playout till the end and calculates a reward.
        /// </summary>
        public static float DefaultPolicy(GameInstance game, TeamColor startingTeam)
        {
            if (game.IsFinished)
            {
                Debug.Assert(game.VictoryTeam.HasValue || game.AllDead, "game.VictoryTeam.HasValue");
                return(CalculateDeltaReward(game, startingTeam, game.VictoryTeam));
            }

            Debug.Assert(game.CurrentTeam.HasValue, "game.CurrentTeam.HasValue");

            var       copy = game.CopyStateOnly();
            const int maxDefaultPolicyIterations = 200;
            int       iterations = maxDefaultPolicyIterations;

            ReplayRecorder.Instance.Clear();
            bool wasMove = false;

            while (!copy.IsFinished && iterations-- > 0)
            {
                var action = ActionGenerator.DefaultPolicyAction(copy);
                if (action.Type == UctActionType.Move)
                {
                    if (wasMove)
                    {
                        action = UctAction.EndTurnAction();
                    }
                    wasMove = true;
                }

                if (action.Type == UctActionType.EndTurn)
                {
                    wasMove = false;
                }

                if (action.Type == UctActionType.Null)
                {
                    throw new InvalidOperationException();
                }

                ActionEvaluator.FNoCopy(copy, action);
            }

            if (iterations <= 0)
            {
                ReplayRecorder.Instance.SaveAndClear(game, 0);
                //throw new InvariantViolationException("MCTS playout timeout");
                Utils.Log(LogSeverity.Error, nameof(UctAlgorithm),
                          $"DefaultPolicy ran out of time (over {maxDefaultPolicyIterations} iterations for playout), computed results are likely wrong.");
                return(0);
            }

            TeamColor?victoryTeam = copy.VictoryTeam;

            return(CalculateDeltaReward(game, startingTeam, victoryTeam));
        }
Пример #9
0
        /// <summary>
        /// Returns a list of best possible actions until the end of a turn.
        /// </summary>
        private List <UctAction> SelectBestActions(UctNode root)
        {
            var     result  = new List <UctAction>();
            UctNode current = root;

            do
            {
                if (current.Children.Count == 0)
                {
                    break;
                }

                UctNode max = current.Children.FastMax(c => c.Q / c.N);
                if (max.Q / max.N < 0.2)
                {
                    var state = current.State.CopyStateOnly();
                    do
                    {
                        var action = ActionGenerator.RuleBasedAction(state);
                        state = ActionEvaluator.F(state, action);
                        if (action.Type == UctActionType.EndTurn)
                        {
                            goto done;
                        }
                        else
                        {
                            result.Add(action);

                            if (action.Type == UctActionType.DefensiveMove)
                            {
                                goto done;
                            }
                        }
                    } while (true);
                }

                if (max.Action.Type != UctActionType.EndTurn)
                {
                    if (max.IsTerminal)
                    {
                        //Console.WriteLine("Found terminal");
                    }
                    result.Add(max.Action);
                }

                current = max;
            } while (current.Action.Type != UctActionType.EndTurn);

done:

            return(result);
        }
Пример #10
0
        public static Transaction <T> CreateUnsigned(
            long nonce,
            PublicKey publicKey,
            BlockHash?genesisHash,
            IEnumerable <T> actions,
            IImmutableSet <Address> updatedAddresses = null,
            DateTimeOffset?timestamp = null
            )
        {
            var signer = new Address(publicKey);

            if (ReferenceEquals(updatedAddresses, null))
            {
                updatedAddresses = ImmutableHashSet <Address> .Empty;
            }

            DateTimeOffset ts = timestamp ?? DateTimeOffset.UtcNow;

            ImmutableArray <T> actionsArray = actions.ToImmutableArray();

            if (!actionsArray.IsEmpty)
            {
                // FIXME: Although we are assuming all block hashes are SHA256 digest, we should
                // parametrize this in the future.
                BlockHash emptyBlockHash = BlockHash.FromHashDigest(default(HashDigest <SHA256>));

                var evalUpdatedAddresses = ActionEvaluator <T> .GetUpdatedAddresses(
                    new Transaction <T>(
                        nonce,
                        signer,
                        publicKey,
                        genesisHash,
                        updatedAddresses,
                        ts,
                        actionsArray));

                if (!updatedAddresses.IsSupersetOf(evalUpdatedAddresses))
                {
                    updatedAddresses = updatedAddresses.Union(evalUpdatedAddresses);
                }
            }

            return(new Transaction <T>(
                       nonce,
                       signer,
                       publicKey,
                       genesisHash,
                       updatedAddresses,
                       ts,
                       actionsArray));
        }
Пример #11
0
        public void FastPlayTurn(GameEventHub eventHub)
        {
            do
            {
                var possibleActions = ActionGenerator.PossibleActions(_gameInstance, null, true, true);
                var chosenAction    = possibleActions[Generator.Random.Next(possibleActions.Count)];

                if (chosenAction.Type == UctActionType.EndTurn)
                {
                    break;
                }

                ActionEvaluator.FNoCopy(_gameInstance, chosenAction);
            } while (!_gameInstance.IsFinished);
        }
Пример #12
0
        public void IsFinishedFastAutoUpdateTest()
        {
            var game = new GameInstance(3);

            var a1 = game.AddAbilityWithInfo(new AbilityInfo(5, 1, 5, 0));

            var m1 = game.AddMobWithInfo(new MobInfo(TeamColor.Red, 1, 10, 0, new[] { a1 }));
            var m2 = game.AddMobWithInfo(new MobInfo(TeamColor.Blue, 1, 10, 0, new[] { a1 }));

            game.PrepareEverything();

            Assert.IsFalse(game.IsFinished);

            ActionEvaluator.FNoCopy(game, UctAction.AbilityUseAction(a1, m1, m2));
            Assert.IsTrue(game.IsFinished);
        }
Пример #13
0
        public void FastPlayTurn(GameEventHub eventHub)
        {
            var uct    = new UctAlgorithm(_thinkTime, _expoExplo);
            var result = uct.UctSearch(_gameInstance);

            foreach (var action in result.Actions)
            {
                Debug.Assert(action.Type != UctActionType.EndTurn, "node.Action.Type != UctActionType.EndTurn");

                ActionEvaluator.FNoCopy(_gameInstance, action);
            }

            ExponentialMovingAverage.Instance.Average(result.MillisecondsPerIteration);

            LogActions(result);
        }
Пример #14
0
        /// <summary>
        /// Expands a given node, adding a new possible state.
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        public static UctNode Expand(UctNode node)
        {
            var type = node.Action.Type;

            var allowMove = type != UctActionType.Move && type != UctActionType.DefensiveMove;

            node.PrecomputePossibleActions(allowMove, true || type != UctActionType.EndTurn);

            var action = node.PossibleActions[node.Children.Count];
            var child  = new UctNode(0, 0, action, ActionEvaluator.F(node.State, action));

            child.Parent = node;

            node.Children.Add(child);

            return(child);
        }
Пример #15
0
        public void FastPlayTurn(GameEventHub eventHub)
        {
            do
            {
                var action = ActionGenerator.RuleBasedAction(_gameInstance);

                if (action.Type == UctActionType.EndTurn)
                {
                    break;
                }

                ActionEvaluator.FNoCopy(_gameInstance, action);

                if (action.Type == UctActionType.DefensiveMove)
                {
                    break;
                }
            } while (!_gameInstance.IsFinished);
        }
Пример #16
0
        internal long UnrenderActions(
            IReadOnlyList <ActionEvaluation> evaluations,
            Block <T> block,
            StateCompleterSet <T> stateCompleters)
        {
            _logger.Debug(
                "Unrender actions in block #{BlockIndex} {BlockHash}", block?.Index, block?.Hash);

            if (evaluations is null)
            {
                evaluations =
                    ActionEvaluator.Evaluate(block, stateCompleters)
                    .Reverse().ToImmutableList();
            }

            long count = 0;

            foreach (ActionEvaluation evaluation in evaluations)
            {
                foreach (IActionRenderer <T> renderer in ActionRenderers)
                {
                    if (evaluation.Exception is null)
                    {
                        renderer.UnrenderAction(
                            evaluation.Action,
                            evaluation.InputContext.GetUnconsumedContext(),
                            evaluation.OutputStates);
                    }
                    else
                    {
                        renderer.UnrenderActionError(
                            evaluation.Action,
                            evaluation.InputContext.GetUnconsumedContext(),
                            evaluation.Exception);
                    }
                }

                count++;
            }

            return(count);
        }
Пример #17
0
        public void DefaultPolicyTest()
        {
            var game = new GameInstance(3);

            var ability1 = new AbilityInfo(1, 1, 1, 0);
            var a1       = game.AddAbilityWithInfo(ability1);

            var ability2 = new AbilityInfo(3, 1, 1, 0);
            var a2       = game.AddAbilityWithInfo(ability2);

            var abilities1 = new List <int>();
            var abilities2 = new List <int> {
                a1,
                a2
            };

            var info1 = new MobInfo(TeamColor.Red, 5, 1, 0, abilities1);
            var info2 = new MobInfo(TeamColor.Blue, 5, 1, 1, abilities2);

            game.AddMobWithInfo(info1);
            game.AddMobWithInfo(info2);
            game.PrepareEverything();

            Assert.IsFalse(game.IsFinished);

            var uct    = new UctAlgorithm(100);
            var result = UctAlgorithm.DefaultPolicy(game, TeamColor.Red);

            Assert.AreEqual(0, result);
            ActionEvaluator.FNoCopy(game, UctAction.EndTurnAction());

            Assert.AreEqual(TeamColor.Blue, game.CurrentTeam);

            var bestAction = ActionGenerator.DefaultPolicyAction(game);

            Console.WriteLine($"Best: {bestAction}");

            var node = uct.UctSearch(game);

            Console.WriteLine(node);
        }
Пример #18
0
 // This initializes the Bot.
 // Finds the spawner, player and grid. Also creates the
 // evaluators
 public override void Init()
 {
     spawner = GameObject.FindObjectOfType <Spawner>();
     player  = GetComponentInParent <PlayerController>();
     if (!enemy)
     {
         PlayerController[] allplayer = FindObjectsOfType <PlayerController>();
         foreach (PlayerController pl in allplayer)
         {
             if (!pl.Equals(player))
             {
                 enemy = pl;
             }
         }
     }
     gridEvaluator  = new GridEvaluator(gridMaker.GetComponent <GridMaker>().GetGrid());
     towerEvaluator = new TowerEvaluator();
     towerEvaluator.SetTowerList(GetTowerStructureList());
     actionEvaluator = new ActionEvaluator();
     enemyEvaluator  = new EnemyEvaluator(GetEnemyStructureList());
 }
Пример #19
0
        /// <summary>
        /// Render actions of the given <paramref name="block"/>.
        /// </summary>
        /// <param name="evaluations"><see cref="ActionEvaluation"/>s of the block.  If it is
        /// <c>null</c>, evaluate actions of the <paramref name="block"/> again.</param>
        /// <param name="block"><see cref="Block{T}"/> to render actions.</param>
        /// <param name="stateCompleters">The strategy to complement incomplete block states.
        /// <see cref="StateCompleterSet{T}.Recalculate"/> by default.</param>
        /// <returns>The number of actions rendered.</returns>
        internal long RenderActions(
            IReadOnlyList <ActionEvaluation> evaluations,
            Block <T> block,
            StateCompleterSet <T> stateCompleters)
        {
            _logger.Debug("Render actions in block {blockIndex}: {block}", block?.Index, block);

            if (evaluations is null)
            {
                evaluations = ActionEvaluator.Evaluate(block, stateCompleters);
            }

            long count = 0;

            foreach (var evaluation in evaluations)
            {
                foreach (IActionRenderer <T> renderer in ActionRenderers)
                {
                    if (evaluation.Exception is null)
                    {
                        renderer.RenderAction(
                            evaluation.Action,
                            evaluation.InputContext.GetUnconsumedContext(),
                            evaluation.OutputStates);
                    }
                    else
                    {
                        renderer.RenderActionError(
                            evaluation.Action,
                            evaluation.InputContext.GetUnconsumedContext(),
                            evaluation.Exception);
                    }

                    count++;
                }
            }

            return(count);
        }
        /// <summary>
        /// Recalculates and complements all <i>missing</i> block states including and upto given
        /// <paramref name="blockHash"/> starting from the genesis block.
        /// </summary>
        /// <param name="blockHash">The inclusive limit of target hash to terminate complementation.
        /// </param>
        /// <remarks>
        /// <para>
        /// If a complementation of the entire blockchain is needed, call with the tip hash of the
        /// <see cref="BlockChain{T}"/>.
        /// </para>
        /// <para>
        /// Unlike <see cref="RecalculateBlockStates"/>, this method skips recalculations if states
        /// are found for intermediate blocks. This may not be fully secure if states for
        /// blocks in <see cref="IStateStore"/> are somehow corrupted.
        /// </para>
        /// </remarks>
        internal void ComplementAllBlockStates(BlockHash blockHash)
        {
            _logger.Verbose("Complementing all block states upto {BlockHash}...", blockHash);

            // Prevent recursive trial to recalculate & complement incomplete block states by
            // mistake; if the below code works as intended, these state completers must never
            // be invoked.
            StateCompleterSet <T> stateCompleters = StateCompleterSet <T> .Reject;

            // Calculates and fills the incomplete states on the fly.
            foreach (BlockHash hash in BlockHashes)
            {
                Block <T> block = this[hash];
                if (StateStore.ContainsStateRoot(block.StateRootHash))
                {
                    continue;
                }

                IReadOnlyList <ActionEvaluation> evaluations = ActionEvaluator.Evaluate(
                    block,
                    stateCompleters);

                _rwlock.EnterWriteLock();
                try
                {
                    SetStates(block, evaluations);
                }
                finally
                {
                    _rwlock.ExitWriteLock();
                }

                if (blockHash.Equals(hash))
                {
                    break;
                }
            }
        }
Пример #21
0
        /// <summary>
        /// Runs a playout with the given encounter defined by a DNA pair and both controllers.
        /// </summary>
        public static int Playout(GameInstance game, DNA d1, DNA d2, IMobController c1, IMobController c2)
        {
            GameSetup.OverrideGameDna(game, d1, d2);

            game.AssignAiControllers(c1, c2);

            int iterations = Constants.MaxPlayoutEvaluationIterations;

            var hub = new GameEventHub(game);

            while (!game.IsFinished && iterations-- > 0)
            {
                game.CurrentController.FastPlayTurn(hub);
                ActionEvaluator.FNoCopy(game, UctAction.EndTurnAction());
            }

            if (Constants.GetLogBuffer().ToString().Length != 0)
            {
                Console.WriteLine(Constants.GetLogBuffer());
            }
            Constants.ResetLogBuffer();

            return(Constants.MaxPlayoutEvaluationIterations - iterations);
        }
Пример #22
0
        // FIXME it's very dangerous because replacing Id means
        // ALL blocks (referenced by MineBlock(), etc.) will be changed.
        internal System.Action Swap(
            BlockChain <T> other,
            bool render,
            StateCompleterSet <T>?stateCompleters = null)
        {
            if (other is null)
            {
                throw new ArgumentNullException(nameof(other));
            }

            // As render/unrender processing requires every step's states from the branchpoint
            // to the new/stale tip, incomplete states need to be complemented anyway...
            StateCompleterSet <T> completers = stateCompleters ?? StateCompleterSet <T> .Recalculate;

            if (Tip.Equals(other.Tip))
            {
                // If it's swapped for a chain with the same tip, it means there is no state change.
                // Hence render is unnecessary.
                render = false;
            }
            else
            {
                _logger.Debug(
                    "The blockchain was reorged from " +
                    "{OldChainId} (#{OldTipIndex} {OldTipHash}) " +
                    "to {NewChainId} (#{NewTipIndex} {NewTipHash}).",
                    Id,
                    Tip.Index,
                    Tip.Hash,
                    other.Id,
                    other.Tip.Index,
                    other.Tip.Hash);
            }

            System.Action renderSwap = () => { };

            _rwlock.EnterUpgradeableReadLock();
            try
            {
                // Finds the branch point.
                Block <T> branchpoint = FindTopCommon(this, other);

                if (branchpoint is null)
                {
                    const string msg =
                        "A chain cannot be reorged into a heterogeneous chain with a " +
                        "different genesis.";
                    throw new InvalidGenesisBlockException(Genesis.Hash, other.Genesis.Hash, msg);
                }

                _logger.Debug(
                    "The branchpoint is #{BranchpointIndex} {BranchpointHash}.",
                    branchpoint.Index,
                    branchpoint
                    );

                Block <T> oldTip = Tip, newTip = other.Tip;

                ImmutableList <Block <T> > rewindPath      =
                    GetRewindPath(this, branchpoint.Hash);
                ImmutableList <Block <T> > fastForwardPath =
                    GetFastForwardPath(other, branchpoint.Hash);

                // If there is no rewind, it is not considered as a reorg.
                bool reorg = rewindPath.Count > 0;

                _rwlock.EnterWriteLock();
                try
                {
                    IEnumerable <Transaction <T> >
                    GetTxsWithRange(BlockChain <T> chain, Block <T> start, Block <T> end)
                    => Enumerable
                    .Range((int)start.Index + 1, (int)(end.Index - start.Index))
                    .SelectMany(x =>
                    {
                        // FIXME: Change the type of IBlockContent<T>.Transactions to
                        // IImmutableSet<Transaction<T>>, and define a distinct property
                        // to Block<T> for this ordering.
                        Block <T> block = chain[x];
                        return(ActionEvaluator <T> .OrderTxsForEvaluation(
                                   block.ProtocolVersion,
                                   block.Transactions,
                                   block.PreEvaluationHash
                                   ));
                    });

                    // It assumes reorg is small size. If it was big, this may be heavy task.
                    ImmutableHashSet <Transaction <T> > unstagedTxs =
                        GetTxsWithRange(this, branchpoint, Tip).ToImmutableHashSet();
                    ImmutableHashSet <Transaction <T> > stageTxs =
                        GetTxsWithRange(other, branchpoint, other.Tip).ToImmutableHashSet();
                    ImmutableHashSet <Transaction <T> > restageTxs = unstagedTxs.Except(stageTxs);
                    foreach (Transaction <T> restageTx in restageTxs)
                    {
                        StagePolicy.Stage(this, restageTx);
                    }

                    Guid obsoleteId = Id;
                    Id = other.Id;
                    Store.SetCanonicalChainId(Id);
                    _blocks = new BlockSet <T>(Policy.GetHashAlgorithm, Store);
                    TipChanged?.Invoke(this, (oldTip, newTip));

                    Store.DeleteChainId(obsoleteId);
                }
                finally
                {
                    _rwlock.ExitWriteLock();
                }

                renderSwap = () => RenderSwap(
                    render: render,
                    oldTip: oldTip,
                    newTip: newTip,
                    branchpoint: branchpoint,
                    rewindPath: rewindPath,
                    fastForwardPath: fastForwardPath,
                    stateCompleters: completers);
            }
            finally
            {
                _rwlock.ExitUpgradeableReadLock();
            }

            return(renderSwap);
        }
Пример #23
0
        /** <summary>
         *  To write out the value of an ASTExpr, invoke the evaluator in eval.g
         *  to walk the tree writing out the values.  For efficiency, don't
         *  compute a bunch of strings and then pack them together.  Write out directly.
         *  </summary>
         *
         *  <remarks>
         *  Compute separator and wrap expressions, save as strings so we don't
         *  recompute for each value in a multi-valued attribute or expression.
         *
         *  If they set anchor option, then inform the writer to push current
         *  char position.
         *  </remarks>
         */
        public override int Write( StringTemplate self, IStringTemplateWriter @out )
        {
            if ( _exprTree == null || self == null || @out == null )
            {
                return 0;
            }
            // handle options, anchor, wrap, separator...
            StringTemplateAST anchorAST = (StringTemplateAST)GetOption( "anchor" );
            if ( anchorAST != null )
            { // any non-empty expr means true; check presence
                @out.PushAnchorPoint();
            }
            @out.PushIndentation( Indentation );
            HandleExprOptions( self );
            //System.out.println("evaluating tree: "+exprTree.toStringList());
            ActionEvaluator eval = null;
            #if COMPILE_EXPRESSIONS
            bool compile = self.Group != null && self.Group.EnableCompiledExpressions;
            bool cache = compile && self.Group.EnableCachedExpressions;
            System.Func<StringTemplate, IStringTemplateWriter, int> evaluator = EvaluateAction;
            if (compile)
            {
                if (!cache || EvaluateAction == null)
                {
                    // caching won't help here because AST is read only
                    EvaluatorCacheMisses++;
                    evaluator = GetEvaluator(this, AST);
                    if (cache)
                        EvaluateAction = evaluator;
                }
                else
                {
                    EvaluatorCacheHits++;
                }
            }
            else
            #endif
            {
                eval = new ActionEvaluator(self, this, @out, _exprTree);
            }

            int n = 0;
            try
            {
                // eval and write out tree
            #if COMPILE_EXPRESSIONS
                if (compile)
                {
                    n = evaluator(self, @out);
                }
                else
            #endif
                {
                    n = eval.action();
                }
            }
            catch ( RecognitionException re )
            {
                self.Error( "can't evaluate tree: " + _exprTree.ToStringTree(), re );
            }
            @out.PopIndentation();
            if ( anchorAST != null )
            {
                @out.PopAnchorPoint();
            }
            return n;
        }
Пример #24
0
 public static UctNode FromAction(GameInstance game, UctAction action)
 {
     return(new UctNode(action, ActionEvaluator.F(game, action)));
 }
Пример #25
0
        static System.Func<StringTemplate, IStringTemplateWriter, bool> GetEvaluator( ASTExpr chunk, ITree condition )
        {
            if ( EnableDynamicMethods )
            {
                try
                {
                    DynamicMethod method = null;
            #if CACHE_FUNCTORS
                    if ( !_methods.TryGetValue( condition, out method ) )
            #endif
                    {
                        Type[] parameterTypes = { typeof( ASTExpr ), typeof( StringTemplate ), typeof( IStringTemplateWriter ) };
                        method = new DynamicMethod( "ConditionEvaluator" + _evaluatorNumber, typeof( bool ), parameterTypes, typeof( ConditionalExpr ), true );
                        method.DefineParameter( 1, ParameterAttributes.None, "chunk" );
                        method.DefineParameter( 2, ParameterAttributes.None, "self" );
                        method.DefineParameter( 3, ParameterAttributes.None, "writer" );
                        _evaluatorNumber++;

                        var gen = method.GetILGenerator();
                        ActionEvaluator evalCompiled = new ActionEvaluator( null, chunk, null, condition );
                        evalCompiled.ifConditionCompiled( gen );
                        gen.Emit( OpCodes.Ret );
            #if CACHE_FUNCTORS
                        _methods[condition] = method;
            #endif
                    }

                    var dynamicEvaluator = (System.Func<StringTemplate, IStringTemplateWriter, bool>)method.CreateDelegate( typeof( System.Func<StringTemplate, IStringTemplateWriter, bool> ), chunk );
                    return dynamicEvaluator;
                }
                catch
                {
                    // fall back to functional (or interpreted) version
                }
            }

            if ( EnableFunctionalMethods )
            {
                try
                {
                    ActionEvaluator evalFunctional = new ActionEvaluator( null, chunk, null, condition );
                    var functionalEvaluator = evalFunctional.ifConditionFunctional();
                    HoldsConditionFuncAndChunk holder = new HoldsConditionFuncAndChunk()
                    {
                        func = functionalEvaluator,
                        chunk = chunk
                    };
                    return (System.Func<StringTemplate, IStringTemplateWriter, bool>)System.Delegate.CreateDelegate( typeof( System.Func<StringTemplate, IStringTemplateWriter, bool> ), holder, typeof( ConditionalExpr ).GetMethod( "CallFunctionalConditionEvaluator" ) );
                }
                catch
                {
                    // fall back to interpreted version
                }
            }

            return new System.Func<StringTemplate, IStringTemplateWriter, bool>( ( self, @out ) =>
            {
                ActionEvaluator eval = new ActionEvaluator( self, chunk, @out, condition );
                return eval.ifCondition();
            } );
        }
Пример #26
0
 /** <summary>
  *  To write out the value of a condition expr, invoke the evaluator in eval.g
  *  to walk the condition tree computing the boolean value.  If result
  *  is true, then write subtemplate.
  *  </summary>
  */
 public override int Write( StringTemplate self, IStringTemplateWriter @out )
 {
     if ( AST == null || self == null || @out == null )
     {
         return 0;
     }
     //System.Console.Out.WriteLine( "evaluating conditional tree: " + AST.ToStringTree() );
     #if !COMPILE_EXPRESSIONS
     ActionEvaluator eval = null;
     #endif
     int n = 0;
     try
     {
         bool testedTrue = false;
         // get conditional from tree and compute result
     #if COMPILE_EXPRESSIONS
         if ( EvaluateCondition == null )
             EvaluateCondition = GetEvaluator( this, AST.GetChild( 0 ) );
         bool includeSubtemplate = EvaluateCondition( self, @out ); // eval and write out tree
     #else
         ITree cond = AST.GetChild( 0 );
         eval = new ActionEvaluator( self, this, @out, cond );
         // eval and write out trees
         bool includeSubtemplate = eval.ifCondition();
     #endif
         //System.Console.Out.WriteLine( "subtemplate " + _subtemplate );
         // IF
         if ( includeSubtemplate )
         {
             n = WriteSubTemplate( self, @out, _subtemplate );
             testedTrue = true;
         }
         // ELSEIF
         else if ( _elseIfSubtemplates != null && _elseIfSubtemplates.Count > 0 )
         {
             for ( int i = 0; i < _elseIfSubtemplates.Count; i++ )
             {
                 ElseIfClauseData elseIfClause = _elseIfSubtemplates[i];
     #if COMPILE_EXPRESSIONS
                 if ( elseIfClause.EvaluateCondition == null )
                     elseIfClause.EvaluateCondition = GetEvaluator( this, elseIfClause.expr.AST );
                 includeSubtemplate = elseIfClause.EvaluateCondition( self, @out );
     #else
                 eval = new ActionEvaluator( self, this, @out, elseIfClause.expr.AST );
                 includeSubtemplate = eval.ifCondition();
     #endif
                 if ( includeSubtemplate )
                 {
                     WriteSubTemplate( self, @out, elseIfClause.st );
                     testedTrue = true;
                     break;
                 }
             }
         }
         // ELSE
         if ( !testedTrue && _elseSubtemplate != null )
         {
             // evaluate ELSE clause if present and IF condition failed
             StringTemplate s = _elseSubtemplate.GetInstanceOf();
             s.EnclosingInstance = self;
             s.Group = self.Group;
             s.NativeGroup = self.NativeGroup;
             n = s.Write( @out );
         }
         // cond==false and no else => Missing output not empty
         if (!testedTrue && _elseSubtemplate == null)
             n = Missing;
     }
     catch ( RecognitionException re )
     {
         self.Error( "can't evaluate tree: " + AST.ToStringTree(), re );
     }
     return n;
 }
Пример #27
0
        public void EvaluateTxs()
        {
            DumbAction MakeAction(Address address, char identifier, Address?transferTo = null)
            {
                return(new DumbAction(
                           targetAddress: address,
                           item: identifier.ToString(),
                           recordRehearsal: false,
                           recordRandom: true,
                           transfer: transferTo is Address to
                        ? Tuple.Create <Address, Address, BigInteger>(address, to, 5)
                        : null));
            }

            Address[] addresses =
            {
                _txFx.Address1,
                _txFx.Address2,
                _txFx.Address3,
                _txFx.Address4,
                _txFx.Address5,
            };
            HashAlgorithmType   hashAlgorithm  = HashAlgorithmType.Of <SHA256>();
            HashAlgorithmGetter hashAlgoGetter = _ => hashAlgorithm;
            Block <DumbAction>  genesis        = MineGenesisBlock <DumbAction>(
                hashAlgoGetter,
                TestUtils.GenesisMiner
                );
            ActionEvaluator <DumbAction> actionEvaluator = new ActionEvaluator <DumbAction>(
                hashAlgorithmGetter: _ => HashAlgorithmType.Of <SHA256>(),
                policyBlockAction: null,
                stateGetter: ActionEvaluator <DumbAction> .NullStateGetter,
                balanceGetter: ActionEvaluator <DumbAction> .NullBalanceGetter,
                trieGetter: null);
            IAccountStateDelta previousStates = genesis.ProtocolVersion > 0
                ? new AccountStateDeltaImpl(
                ActionEvaluator <DumbAction> .NullAccountStateGetter,
                ActionEvaluator <DumbAction> .NullAccountBalanceGetter,
                genesis.Miner)
                : new AccountStateDeltaImplV0(
                ActionEvaluator <DumbAction> .NullAccountStateGetter,
                ActionEvaluator <DumbAction> .NullAccountBalanceGetter,
                genesis.Miner);

            Assert.Empty(
                actionEvaluator.EvaluateTxs(
                    block: genesis,
                    previousStates: previousStates));

            Transaction <DumbAction>[] block1Txs =
            {
                Transaction <DumbAction> .Create(
                    nonce: 0,
                    privateKey: _txFx.PrivateKey1,
                    genesisHash: genesis.Hash,
                    actions: new[]
                {
                    MakeAction(addresses[0],                          'A',  addresses[1]),
                    MakeAction(addresses[1],                          'B',  addresses[2]),
                },
                    timestamp: DateTimeOffset.MinValue.AddSeconds(2)),
                Transaction <DumbAction> .Create(
                    nonce: 0,
                    privateKey: _txFx.PrivateKey2,
                    genesisHash: genesis.Hash,
                    actions: new[] { MakeAction(addresses[2],         'C',  addresses[3]) },
                    timestamp: DateTimeOffset.MinValue.AddSeconds(4)),
                Transaction <DumbAction> .Create(
                    nonce: 0,
                    privateKey: _txFx.PrivateKey3,
                    genesisHash: genesis.Hash,
                    actions: new DumbAction[0],
                    timestamp: DateTimeOffset.MinValue.AddSeconds(7)),
            };
            int i = 0;

            foreach (Transaction <DumbAction> tx in block1Txs)
            {
                _logger.Debug("{0}[{1}] = {2}", nameof(block1Txs), i, tx.Id);
            }

            Block <DumbAction> block1 = MineNextBlock(
                genesis,
                hashAlgoGetter,
                GenesisMiner,
                block1Txs,
                new byte[] { }
                );

            previousStates = block1.ProtocolVersion > 0
                ? new AccountStateDeltaImpl(
                ActionEvaluator <DumbAction> .NullAccountStateGetter,
                ActionEvaluator <DumbAction> .NullAccountBalanceGetter,
                block1.Miner)
                : new AccountStateDeltaImplV0(
                ActionEvaluator <DumbAction> .NullAccountStateGetter,
                ActionEvaluator <DumbAction> .NullAccountBalanceGetter,
                block1.Miner);
            var evals = actionEvaluator.EvaluateTxs(
                block1,
                previousStates).ToImmutableArray();
            int randomValue = 0;

            (int TxIdx, int ActionIdx, string[] UpdatedStates, Address Signer)[] expectations =
Пример #28
0
        private void LogActions(UctSearchResult result)
        {
            float abilityUse    = ActionEvaluator.ActionCounts[UctActionType.AbilityUse];
            float attackMove    = ActionEvaluator.ActionCounts[UctActionType.AttackMove];
            float defensiveMove = ActionEvaluator.ActionCounts[UctActionType.DefensiveMove];
            float move          = ActionEvaluator.ActionCounts[UctActionType.Move];
            float endTurn       = ActionEvaluator.ActionCounts[UctActionType.EndTurn];

            float  useCounts        = abilityUse + attackMove + defensiveMove + move;
            string endRatio         = (endTurn / useCounts).ToString("0.00");
            string abilityMoveRatio = ((abilityUse + attackMove) / (move + defensiveMove)).ToString("0.00");

            if (Constants.MctsLogging)
            {
                foreach (var action in result.Actions)
                {
                    Console.WriteLine($"action: {action}");
                }

                Console.WriteLine(
                    $"#sum: {ActionEvaluator.Actions}[ability/move ratio: {abilityMoveRatio}] [end ratio: {endRatio}] {ActionEvaluator.ActionCountString()}");
            }
        }
Пример #29
0
        /// <summary>
        /// Generates possible attack move actions.
        /// </summary>
        public static void GenerateAttackMoveActions(GameInstance state, CachedMob mob, List <UctAction> result)
        {
            var mobInfo     = mob.MobInfo;
            var mobInstance = mob.MobInstance;

            foreach (var enemyId in state.MobManager.Mobs)
            {
                var target = state.CachedMob(enemyId);

                if (!GameInvariants.IsTargetableNoSource(state, mob, target))
                {
                    continue;
                }

                AxialCoord myCoord         = mobInstance.Coord;
                AxialCoord?closestCoord    = null;
                int?       distance        = null;
                int?       chosenAbilityId = null;

                foreach (var coord in state.Map.EmptyCoords)
                {
                    if (!state.Map.IsVisible(coord, target.MobInstance.Coord))
                    {
                        continue;
                    }

                    var possibleMoveAction = GameInvariants.CanMoveTo(state, mob, coord);

                    if (possibleMoveAction.Type == UctActionType.Null)
                    {
                        continue;
                    }
                    Debug.Assert(possibleMoveAction.Type == UctActionType.Move);

                    foreach (var abilityId in mobInfo.Abilities)
                    {
                        if (!GameInvariants.IsAbilityUsableFrom(state, mob, coord, target, abilityId))
                        {
                            continue;
                        }

                        int myDistance = state.Pathfinder.Distance(myCoord, coord);

                        if (!closestCoord.HasValue)
                        {
                            chosenAbilityId = abilityId;
                            closestCoord    = coord;
                            distance        = myDistance;
                        }
                        else if (distance.Value > myDistance)
                        {
                            chosenAbilityId = abilityId;
                            closestCoord    = coord;
                            distance        = myDistance;
                        }
                    }
                }

                if (closestCoord.HasValue)
                {
                    if (Constants.AttackMoveEnabled)
                    {
                        var action = UctAction.AttackMoveAction(mob.MobId,
                                                                closestCoord.Value,
                                                                chosenAbilityId.Value,
                                                                target.MobId);

                        var after = ActionEvaluator.F(state, action.ToPureMove());
                        GameInvariants.AssertValidAbilityUseAction(after, action.ToPureAbilityUse());

                        GameInvariants.AssertValidAction(state, action);

                        result.Add(action);
                    }
                    else
                    {
                        var action = UctAction.MoveAction(mob.MobId, closestCoord.Value);
                        GameInvariants.AssertValidAction(state, action);

                        result.Add(action);
                    }
                }
            }
        }
Пример #30
0
        private void ValidateReorgEnd(
            Block <T> oldTip,
            Block <T> newTip,
            Block <T> branchpoint)
        {
            if (!(BlockChain is BlockChain <T> chain))
            {
                return;
            }

            IBlockPolicy <T>           policy = chain.Policy;
            IStore                     store  = chain.Store;
            InvalidRenderException <T> heterogeneousGenesisError =
                Error(Records, "Reorg occurred from the chain with different genesis.");

            List <IAction>     expectedUnrenderedActions = new List <IAction>();
            BlockHeader        header = oldTip.Header;
            IEnumerable <TxId> txIds  = oldTip.Transactions.Select(tx => tx.Id);

            while (!header.Hash.Equals(branchpoint.Hash))
            {
                if (policy.BlockAction is IAction blockAction)
                {
                    expectedUnrenderedActions.Add(blockAction);
                }

                IEnumerable <Transaction <T> > transactions = txIds.Select(store.GetTransaction <T>);

                transactions = ActionEvaluator <T> .OrderTxsForEvaluation(
                    header.ProtocolVersion,
                    transactions,
                    header.PreEvaluationHash
                    );

                expectedUnrenderedActions.AddRange(
                    transactions.SelectMany(t => t.Actions).Cast <IAction>().Reverse());

                BlockDigest prevDigest = store.GetBlockDigest(
                    header.PreviousHash ?? throw heterogeneousGenesisError
                    ) ?? throw Error(Records, $"Failed to load block {header.PreviousHash}.");
                header = prevDigest.GetHeader(policy.GetHashAlgorithm);
                txIds  = prevDigest.TxIds.Select(b => new TxId(b.ToBuilder().ToArray()));
            }

            IEnumerable <IAction> expectedRenderedActionsBuffer = new List <IAction>();

            header = newTip.Header;
            txIds  = newTip.Transactions.Select(tx => tx.Id);
            while (!header.Hash.Equals(branchpoint.Hash))
            {
                IEnumerable <Transaction <T> > transactions = txIds.Select(store.GetTransaction <T>);
                transactions = ActionEvaluator <T> .OrderTxsForEvaluation(
                    header.ProtocolVersion,
                    transactions,
                    header.PreEvaluationHash
                    );

                IEnumerable <IAction> actions =
                    transactions.SelectMany(t => t.Actions).Cast <IAction>();
                if (policy.BlockAction is IAction blockAction)
                {
#if NET472 || NET471 || NET47 || NET462 || NET461
                    // Even though .NET Framework 4.6.1 or higher supports .NET Standard 2.0,
                    // versions lower than 4.8 lacks Enumerable.Append(IEnumerable<T>, T) method.
                    actions = actions.Concat(new IAction[] { blockAction });
#else
#pragma warning disable PC002
                    actions = actions.Append(blockAction);
#pragma warning restore PC002
#endif
                }

                expectedRenderedActionsBuffer = actions.Concat(expectedRenderedActionsBuffer);
                BlockDigest prevDigest = store.GetBlockDigest(
                    header.PreviousHash ?? throw heterogeneousGenesisError
                    ) ?? throw Error(Records, $"Failed to load block {header.PreviousHash}.");
                header = prevDigest.GetHeader(policy.GetHashAlgorithm);
                txIds  = prevDigest.TxIds.Select(b => new TxId(b.ToBuilder().ToArray()));
            }

            IAction[]      expectedRenderedActions = expectedRenderedActionsBuffer.ToArray();
            List <IAction> actualRenderedActions   = new List <IAction>();
            List <IAction> actualUnrenderedActions = new List <IAction>();
            foreach (var record in Records.Reverse())
            {
                if (record is RenderRecord <T> .Reorg b && b.Begin)
                {
                    break;
                }

                if (record is RenderRecord <T> .ActionBase a)
                {
                    if (a.Render)
                    {
                        actualRenderedActions.Add(a.Action);
                    }
                    else
                    {
                        actualUnrenderedActions.Add(a.Action);
                    }
                }
            }

            actualRenderedActions.Reverse();
            actualUnrenderedActions.Reverse();

            string ReprAction(IAction?action)
            {
                if (action is null)
                {
                    return("[N/A]");
                }

                return(action.PlainValue.Inspect(loadAll: true)
                       .Replace(" \n ", " ")
                       .Replace(" \n", " ")
                       .Replace("\n ", " ")
                       .Replace("\n", " "));
            }

            string MakeErrorMessage(string prefix, IList <IAction> expected, IList <IAction> actual)
            {
                int expectN = expected.Count;
                int actualN = actual.Count;

                if (expectN != actualN)
                {
                    prefix += $" (expected: {expectN} actions, actual: {actualN} actions):";
                }

                var buffer = new StringBuilder();

                for (int i = 0, count = Math.Max(expectN, actualN); i < count; i++)
                {
                    IAction?e = i < expectN ? expected[i] : null;
                    IAction?a = i < actualN ? actual[i] : null;
                    if (!(e is null || a is null) && e.PlainValue.Equals(a.PlainValue))
                    {
                        buffer.Append($"\n\t  {ReprAction(e)}");
                    }
Пример #31
0
        /** <summary>
         *  Evaluate an argument list within the context of the enclosing
         *  template but store the values in the context of self, the
         *  new embedded template.  For example, bold(item=item) means
         *  that bold.item should get the value of enclosing.item.
         *  </summary>
         */
        protected virtual void EvaluateArguments( StringTemplate self )
        {
            StringTemplateAST argumentsAST = self.ArgumentsAST;
            if ( argumentsAST == null || argumentsAST.GetChild( 0 ) == null )
            {
                // return immediately if missing tree or no actual args
                return;
            }

            // Evaluate args in the context of the enclosing template, but we
            // need the predefined args like 'it', 'attr', and 'i' to be
            // available as well so we put a dummy ST between the enclosing
            // context and the embedded context.  The dummy has the predefined
            // context as does the embedded.
            StringTemplate enclosing = self.EnclosingInstance;
            StringTemplate argContextST = new StringTemplate( self.Group, "" );
            argContextST.Name = "<invoke " + self.Name + " arg context>";
            argContextST.EnclosingInstance = enclosing;
            argContextST.ArgumentContext = self.ArgumentContext;

            ActionEvaluator eval =
                    new ActionEvaluator( argContextST, this, null, argumentsAST );
            /*
            System.out.println("eval args: "+argumentsAST.toStringList());
            System.out.println("ctx is "+self.getArgumentContext());
            */
            try
            {
                // using any initial argument context (such as when obj is set),
                // evaluate the arg list like bold(item=obj).  Since we pass
                // in any existing arg context, that context gets filled with
                // new values.  With bold(item=obj), context becomes:
                // {[obj=...],[item=...]}.
                Dictionary<string, object> ac = eval.argList( self, self.ArgumentContext );
                self.ArgumentContext = ac;
            }
            catch ( RecognitionException re )
            {
                self.Error( "can't evaluate tree: " + argumentsAST.ToStringTree(), re );
            }
        }
Пример #32
0
        /** <summary>
         *  A expr is normally just a string literal, but is still an AST that
         *  we must evaluate.  The expr can be any expression such as a template
         *  include or string cat expression etc...  Evaluate with its own writer
         *  so that we can convert to string and then reuse, don't want to compute
         *  all the time; must precompute w/o writing to output buffer.
         *  </summary>
         */
        public virtual string EvaluateExpression( StringTemplate self,
                                            object expr )
        {
            if ( expr == null )
            {
                return null;
            }

            StringTemplateAST exprAST = expr as StringTemplateAST;
            if ( exprAST != null )
            {
            #if COMPILE_EXPRESSIONS
                System.Func<StringTemplate, IStringTemplateWriter, int> value;
            #if CACHE_FUNCTORS
                if ( !_evaluators.TryGetValue( expr, out value ) )
            #endif
                {
                    value = GetEvaluator( this, exprAST );
            #if CACHE_FUNCTORS
                    _evaluators[expr] = value;
            #endif
                }
            #endif
                // must evaluate, writing to a string so we can hang on to it
                StringWriter buf = new StringWriter();
                IStringTemplateWriter sw =
                    self.Group.GetStringTemplateWriter( buf );
                {
                    try
                    {
            #if COMPILE_EXPRESSIONS
                        value( self, sw );
            #else
                        ActionEvaluator eval = new ActionEvaluator( self, this, sw, exprAST );
                        // eval tree
                        eval.action();
            #endif
                    }
                    catch ( RecognitionException re )
                    {
                        self.Error( "can't evaluate tree: " + _exprTree.ToStringTree(), re );
                    }
                }
                return buf.ToString();
            }
            else
            {
                // just in case we expand in the future and it's something else
                return expr.ToString();
            }
        }
Пример #33
0
 public static float PlayoutAction(GameInstance game, UctAction action, TeamColor startingTeam)
 {
     return(DefaultPolicy(ActionEvaluator.F(game, action), startingTeam));
 }
Пример #34
0
 /** <summary>
  *  To write out the value of an ASTExpr, invoke the evaluator in eval.g
  *  to walk the tree writing out the values.  For efficiency, don't
  *  compute a bunch of strings and then pack them together.  Write out directly.
  *  </summary>
  *
  *  <remarks>
  *  Compute separator and wrap expressions, save as strings so we don't
  *  recompute for each value in a multi-valued attribute or expression.
  *
  *  If they set anchor option, then inform the writer to push current
  *  char position.
  *  </remarks>
  */
 public override int Write( StringTemplate self, IStringTemplateWriter @out )
 {
     if ( _exprTree == null || self == null || @out == null )
     {
         return 0;
     }
     // handle options, anchor, wrap, separator...
     StringTemplateAST anchorAST = (StringTemplateAST)GetOption( "anchor" );
     if ( anchorAST != null )
     { // any non-empty expr means true; check presence
         @out.PushAnchorPoint();
     }
     @out.PushIndentation( Indentation );
     HandleExprOptions( self );
     //System.out.println("evaluating tree: "+exprTree.toStringList());
     #if COMPILE_EXPRESSIONS
     if ( EvaluateAction == null )
         EvaluateAction = GetEvaluator( this, AST );
     #else
     ActionEvaluator eval =
             new ActionEvaluator( self, this, @out, _exprTree );
     #endif
     int n = 0;
     try
     {
         // eval and write out tree
     #if COMPILE_EXPRESSIONS
         n = EvaluateAction( self, @out );
     #else
         n = eval.action();
     #endif
     }
     catch ( RecognitionException re )
     {
         self.Error( "can't evaluate tree: " + _exprTree.ToStringTree(), re );
     }
     @out.PopIndentation();
     if ( anchorAST != null )
     {
         @out.PopAnchorPoint();
     }
     return n;
 }