Esempio n. 1
0
        public IAccountStateDelta WeeklyArenaRankingBoard(IActionContext ctx, IAccountStateDelta states)
        {
            var gameConfigState = states.GetGameConfigState();
            var index           = Math.Max((int)ctx.BlockIndex / gameConfigState.WeeklyArenaInterval, 0);
            var weekly          = states.GetWeeklyArenaState(index);
            var nextIndex       = index + 1;
            var nextWeekly      = states.GetWeeklyArenaState(nextIndex);

            if (nextWeekly is null)
            {
                nextWeekly = new WeeklyArenaState(nextIndex);
                states     = states.SetState(nextWeekly.address, nextWeekly.Serialize());
            }

            // Beginning block of a new weekly arena.
            if (ctx.BlockIndex % gameConfigState.WeeklyArenaInterval == 0 && index > 0)
            {
                var prevWeekly = states.GetWeeklyArenaState(index - 1);
                if (!prevWeekly.Ended)
                {
                    prevWeekly.End();
                    weekly.Update(prevWeekly, ctx.BlockIndex);
                    states = states.SetState(prevWeekly.address, prevWeekly.Serialize());
                    states = states.SetState(weekly.address, weekly.Serialize());
                }
            }
            else if (ctx.BlockIndex - weekly.ResetIndex >= gameConfigState.DailyArenaInterval)
            {
                weekly.ResetCount(ctx.BlockIndex);
                states = states.SetState(weekly.address, weekly.Serialize());
            }

            return(states);
        }
Esempio n. 2
0
        public void Execute(bool backward)
        {
            const int slotStateUnlockStage = 1;

            var avatarState = _initialState.GetAvatarState(_avatarAddress);

            avatarState.worldInformation = new WorldInformation(
                0,
                _initialState.GetSheet <WorldSheet>(),
                slotStateUnlockStage);

            var row = _tableSheets.MaterialItemSheet.Values.First(r =>
                                                                  r.ItemSubType == ItemSubType.Hourglass);

            avatarState.inventory.AddItem(ItemFactory.CreateMaterial(row), 83);
            avatarState.inventory.AddItem(ItemFactory.CreateTradableMaterial(row), 100);
            Assert.True(avatarState.inventory.HasFungibleItem(row.ItemId, 0, 183));

            var firstEquipmentRow = _tableSheets.EquipmentItemSheet.First;

            Assert.NotNull(firstEquipmentRow);

            var gameConfigState    = _initialState.GetGameConfigState();
            var requiredBlockIndex = gameConfigState.HourglassPerBlock * 200;
            var equipment          = (Equipment)ItemFactory.CreateItemUsable(
                firstEquipmentRow,
                Guid.NewGuid(),
                requiredBlockIndex);

            avatarState.inventory.AddItem(equipment);

            var result = new CombinationConsumable5.ResultModel
            {
                actionPoint = 0,
                gold        = 0,
                materials   = new Dictionary <Material, int>(),
                itemUsable  = equipment,
                recipeId    = 0,
                itemType    = ItemType.Equipment,
            };

            var mail = new CombinationMail(result, 0, default, requiredBlockIndex);
Esempio n. 3
0
        public IAccountStateDelta ResetChallengeCount(IActionContext ctx, IAccountStateDelta states)
        {
            var gameConfigState = states.GetGameConfigState();
            var index           = Math.Max((int)ctx.BlockIndex / gameConfigState.WeeklyArenaInterval, 0);
            var weeklyAddress   = WeeklyArenaState.DeriveAddress(index);
            var rawWeekly       = (Dictionary)states.GetState(weeklyAddress);
            var resetIndex      = rawWeekly["resetIndex"].ToLong();

            if (ctx.BlockIndex - resetIndex >= gameConfigState.DailyArenaInterval)
            {
                var weekly = new WeeklyArenaState(rawWeekly);
                if (resetIndex >= RankingBattle.UpdateTargetBlockIndex)
                {
                    // Reset count each ArenaInfo.
                    weekly.ResetIndex = ctx.BlockIndex;
                    var listAddress = weeklyAddress.Derive("address_list");
                    if (states.TryGetState(listAddress, out List rawList))
                    {
                        var addressList = rawList.ToList(StateExtensions.ToAddress);
                        foreach (var address in addressList)
                        {
                            var infoAddress = weeklyAddress.Derive(address.ToByteArray());
                            if (states.TryGetState(infoAddress, out Dictionary rawInfo))
                            {
                                var info = new ArenaInfo(rawInfo);
                                info.ResetCount();
                                states = states.SetState(infoAddress, info.Serialize());
                            }
                        }
                    }
                }
                else
                {
                    // Run legacy ResetCount.
                    weekly.ResetCount(ctx.BlockIndex);
                }
                states = states.SetState(weeklyAddress, weekly.Serialize());
            }
            return(states);
        }
Esempio n. 4
0
        public IAccountStateDelta WeeklyArenaRankingBoard2(IActionContext ctx, IAccountStateDelta states)
        {
            var gameConfigState = states.GetGameConfigState();
            var index           = Math.Max((int)ctx.BlockIndex / gameConfigState.WeeklyArenaInterval, 0);
            var weeklyAddress   = WeeklyArenaState.DeriveAddress(index);
            var rawWeekly       = (Dictionary)states.GetState(weeklyAddress);
            var nextIndex       = index + 1;
            var nextWeekly      = states.GetWeeklyArenaState(nextIndex);

            if (nextWeekly is null)
            {
                nextWeekly = new WeeklyArenaState(nextIndex);
                states     = states.SetState(nextWeekly.address, nextWeekly.Serialize());
            }
            var resetIndex = rawWeekly["resetIndex"].ToLong();

            // Beginning block of a new weekly arena.
            if (ctx.BlockIndex % gameConfigState.WeeklyArenaInterval == 0 && index > 0)
            {
                var prevWeeklyAddress = WeeklyArenaState.DeriveAddress(index - 1);
                var rawPrevWeekly     = (Dictionary)states.GetState(prevWeeklyAddress);
                if (!rawPrevWeekly["ended"].ToBoolean())
                {
                    rawPrevWeekly = rawPrevWeekly.SetItem("ended", true.Serialize());
                    var weekly     = new WeeklyArenaState(rawWeekly);
                    var prevWeekly = new WeeklyArenaState(rawPrevWeekly);
                    weekly.Update(prevWeekly, ctx.BlockIndex);
                    states = states.SetState(prevWeeklyAddress, rawPrevWeekly);
                    states = states.SetState(weeklyAddress, weekly.Serialize());
                }
            }
            else if (ctx.BlockIndex - resetIndex >= gameConfigState.DailyArenaInterval)
            {
                var weekly = new WeeklyArenaState(rawWeekly);
                weekly.ResetCount(ctx.BlockIndex);
                states = states.SetState(weeklyAddress, weekly.Serialize());
            }
            return(states);
        }
Esempio n. 5
0
        public void Case(int randomSeed, int[] optionNumbers)
        {
            var gameConfigState = _initialState.GetGameConfigState();

            Assert.NotNull(gameConfigState);

            var recipeRow    = _tableSheets.EquipmentItemRecipeSheet.OrderedList.First(e => e.SubRecipeIds.Any());
            var subRecipeRow = _tableSheets.EquipmentItemSubRecipeSheetV2[recipeRow.SubRecipeIds.First()];
            var combinationEquipmentAction = new CombinationEquipment
            {
                avatarAddress = _avatarAddress,
                slotIndex     = 0,
                recipeId      = recipeRow.Id,
                subRecipeId   = subRecipeRow.Id,
            };

            var inventoryValue = _initialState.GetState(_inventoryAddress);

            Assert.NotNull(inventoryValue);
            var inventoryState = new Inventory((List)inventoryValue);

            inventoryState.AddFungibleItem(
                ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, recipeRow.MaterialId),
                recipeRow.MaterialCount);
            foreach (var materialInfo in subRecipeRow.Materials)
            {
                inventoryState.AddFungibleItem(
                    ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, materialInfo.Id),
                    materialInfo.Count);
            }

            var worldInformation = new WorldInformation(
                0,
                _tableSheets.WorldSheet,
                recipeRow.UnlockStage);

            var nextState = _initialState
                            .SetState(_inventoryAddress, inventoryState.Serialize())
                            .SetState(_worldInformationAddress, worldInformation.Serialize());

            var random = new TestRandom(randomSeed);

            nextState = combinationEquipmentAction.Execute(new ActionContext
            {
                PreviousStates = nextState,
                BlockIndex     = 0,
                Random         = random,
                Signer         = _agentAddress,
            });

            var slot0Value = nextState.GetState(_slot0Address);

            Assert.NotNull(slot0Value);
            var slot0State = new CombinationSlotState((Dictionary)slot0Value);

            Assert.NotNull(slot0State.Result.itemUsable);
            var equipment       = (Equipment)slot0State.Result.itemUsable;
            var additionalStats = equipment.StatsMap
                                  .GetAdditionalStats(true)
                                  .ToArray();
            var skills = equipment.Skills;

            Assert.Equal(optionNumbers.Length, equipment.optionCountFromCombination);
            var optionSheet           = _tableSheets.EquipmentItemOptionSheet;
            var mainAdditionalStatMin = 0;
            var mainAdditionalStatMax = 0;
            var requiredBlockIndex    = 0;

            foreach (var optionNumber in optionNumbers)
            {
                var optionInfo = subRecipeRow.Options[optionNumber - 1];
                requiredBlockIndex += optionInfo.RequiredBlockIndex;
                var optionRow = optionSheet[optionInfo.Id];
                if (optionRow.StatMin > 0 || optionRow.StatMax > 0)
                {
                    if (optionRow.StatType == equipment.UniqueStatType)
                    {
                        mainAdditionalStatMin += optionRow.StatMin;
                        mainAdditionalStatMax += optionRow.StatMax;
                        continue;
                    }

                    var additionalStatValue = additionalStats
                                              .First(e => e.statType == optionRow.StatType)
                                              .additionalValue;
                    Assert.True(additionalStatValue >= optionRow.StatMin);
                    Assert.True(additionalStatValue <= optionRow.StatMax + 1);
                }
                else if (optionRow.SkillId != default)
                {
                    var skill = skills.First(e => e.SkillRow.Id == optionRow.SkillId);
                    Assert.True(skill.Chance >= optionRow.SkillChanceMin);
                    Assert.True(skill.Chance <= optionRow.SkillChanceMax + 1);
                    Assert.True(skill.Power >= optionRow.SkillDamageMin);
                    Assert.True(skill.Power <= optionRow.SkillDamageMax + 1);
                }
            }

            var mainAdditionalStatValue = additionalStats
                                          .First(e => e.statType == equipment.UniqueStatType)
                                          .additionalValue;

            Assert.True(mainAdditionalStatValue >= mainAdditionalStatMin);
            Assert.True(mainAdditionalStatValue <= mainAdditionalStatMax + 1);
            Assert.Equal(requiredBlockIndex + 1, slot0State.RequiredBlockIndex);

            // FIXME
            // https://github.com/planetarium/lib9c/pull/517#discussion_r679218764
            // The tests after this line should be finished. However, since then the logic is being developed by
            // different developers in different branches. I wrote a test beforehand, but it's failing.
            // I plan to move to another branch after this PR is merged and finish writing the tests.
            return;

            if (requiredBlockIndex == 0)
            {
                return;
            }

            var hourglassRow = _tableSheets.MaterialItemSheet
                               .First(pair => pair.Value.ItemSubType == ItemSubType.Hourglass)
                               .Value;

            inventoryValue = nextState.GetState(_inventoryAddress);
            Assert.NotNull(inventoryValue);
            inventoryState = new Inventory((List)inventoryValue);
            Assert.False(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out _));

            var hourglassCount = requiredBlockIndex * gameConfigState.HourglassPerBlock;

            inventoryState.AddFungibleItem(
                ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, hourglassRow.Id),
                hourglassCount);
            Assert.True(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out var hourglasses));
            Assert.Equal(hourglassCount, hourglasses.Sum(e => e.count));
            nextState = nextState.SetState(_inventoryAddress, inventoryState.Serialize());

            var rapidCombinationAction = new RapidCombination
            {
                avatarAddress = _avatarAddress,
                slotIndex     = 0,
            };

            nextState = rapidCombinationAction.Execute(new ActionContext
            {
                PreviousStates = nextState,
                BlockIndex     = 1,
                Random         = random,
                Signer         = _agentAddress,
            });
            inventoryValue = nextState.GetState(_inventoryAddress);
            Assert.NotNull(inventoryValue);
            inventoryState = new Inventory((List)inventoryValue);
            Assert.False(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out _));
        }
Esempio n. 6
0
        public IAccountStateDelta PrepareNextArena(IActionContext ctx, IAccountStateDelta states)
        {
            var gameConfigState = states.GetGameConfigState();
            var index           = Math.Max((int)ctx.BlockIndex / gameConfigState.WeeklyArenaInterval, 0);
            var weeklyAddress   = WeeklyArenaState.DeriveAddress(index);
            var rawWeekly       = (Dictionary)states.GetState(weeklyAddress);
            var nextIndex       = index + 1;
            var nextWeekly      = states.GetWeeklyArenaState(nextIndex);

            if (nextWeekly is null)
            {
                nextWeekly = new WeeklyArenaState(nextIndex);
                states     = states.SetState(nextWeekly.address, nextWeekly.Serialize());
            }

            // Beginning block of a new weekly arena.
            if (ctx.BlockIndex % gameConfigState.WeeklyArenaInterval == 0 && index > 0)
            {
                var prevWeeklyAddress = WeeklyArenaState.DeriveAddress(index - 1);
                var rawPrevWeekly     = (Dictionary)states.GetState(prevWeeklyAddress);
                if (!rawPrevWeekly["ended"].ToBoolean())
                {
                    rawPrevWeekly = rawPrevWeekly.SetItem("ended", true.Serialize());
                    var weekly      = new WeeklyArenaState(rawWeekly);
                    var prevWeekly  = new WeeklyArenaState(rawPrevWeekly);
                    var listAddress = weekly.address.Derive("address_list");
                    // Set ArenaInfo, address list for new RankingBattle.
                    var addressList = states.TryGetState(listAddress, out List rawList)
                        ? rawList.ToList(StateExtensions.ToAddress)
                        : new List <Address>();
                    if (ctx.BlockIndex >= RankingBattle.UpdateTargetBlockIndex)
                    {
                        weekly.ResetIndex = ctx.BlockIndex;

                        // Copy Map to address list.
                        if (ctx.BlockIndex == RankingBattle.UpdateTargetBlockIndex)
                        {
                            foreach (var kv in prevWeekly.Map)
                            {
                                var address  = kv.Key;
                                var lazyInfo = kv.Value;
                                var info     = new ArenaInfo(lazyInfo.State);
                                states = states.SetState(
                                    weeklyAddress.Derive(address.ToByteArray()), info.Serialize());
                                if (!addressList.Contains(address))
                                {
                                    addressList.Add(address);
                                }
                            }
                        }
                        else
                        {
                            // Copy addresses from prev weekly address list.
                            var prevListAddress = prevWeekly.address.Derive("address_list");

                            if (states.TryGetState(prevListAddress, out List prevRawList))
                            {
                                var prevList = prevRawList.ToList(StateExtensions.ToAddress);
                                foreach (var address in prevList.Where(address => !addressList.Contains(address)))
                                {
                                    addressList.Add(address);
                                }
                            }

                            // Copy ArenaInfo from prev ArenaInfo.
                            foreach (var address in addressList)
                            {
                                if (states.TryGetState(
                                        prevWeekly.address.Derive(address.ToByteArray()),
                                        out Dictionary rawInfo))
                                {
                                    var prevInfo = new ArenaInfo(rawInfo);
                                    var info     = new ArenaInfo(prevInfo);
                                    states = states.SetState(
                                        weeklyAddress.Derive(address.ToByteArray()),
                                        info.Serialize());
                                }
                            }
                        }

                        // Set address list.
                        states = states.SetState(listAddress,
                                                 addressList.Aggregate(List.Empty,
                                                                       (current, address) => current.Add(address.Serialize())));
                    }
                    // Run legacy Update.
                    else
                    {
                        weekly.Update(prevWeekly, ctx.BlockIndex);
                    }

                    states = states.SetState(prevWeeklyAddress, rawPrevWeekly);
                    states = states.SetState(weeklyAddress, weekly.Serialize());
                }
            }
            return(states);
        }
        public void Case(int randomSeed, int[] optionNumbers)
        {
            var gameConfigState = _initialState.GetGameConfigState();

            Assert.NotNull(gameConfigState);

            var subRecipeRow = _tableSheets.EquipmentItemSubRecipeSheetV2.OrderedList.First(e =>
                                                                                            e.Options.Count == 4 &&
                                                                                            e.RequiredBlockIndex > GameConfig.RequiredAppraiseBlock &&
                                                                                            e.RequiredGold == 0);
            var recipeRow =
                _tableSheets.EquipmentItemRecipeSheet.OrderedList.First(e => e.SubRecipeIds.Contains(subRecipeRow.Id));
            var combinationEquipmentAction = new CombinationEquipment
            {
                avatarAddress = _avatarAddress,
                slotIndex     = 0,
                recipeId      = recipeRow.Id,
                subRecipeId   = subRecipeRow.Id,
            };

            var inventoryValue = _initialState.GetState(_inventoryAddress);

            Assert.NotNull(inventoryValue);

            var inventoryState = new Inventory((List)inventoryValue);

            inventoryState.AddFungibleItem(
                ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, recipeRow.MaterialId),
                recipeRow.MaterialCount);
            foreach (var materialInfo in subRecipeRow.Materials)
            {
                inventoryState.AddFungibleItem(
                    ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, materialInfo.Id),
                    materialInfo.Count);
            }

            var worldInformation = new WorldInformation(
                0,
                _tableSheets.WorldSheet,
                recipeRow.UnlockStage);

            var nextState = _initialState
                            .SetState(_inventoryAddress, inventoryState.Serialize())
                            .SetState(_worldInformationAddress, worldInformation.Serialize());

            var random = new TestRandom(randomSeed);

            nextState = combinationEquipmentAction.Execute(new ActionContext
            {
                PreviousStates = nextState,
                BlockIndex     = 0,
                Random         = random,
                Signer         = _agentAddress,
            });

            var slot0Value = nextState.GetState(_slot0Address);

            Assert.NotNull(slot0Value);

            var slot0State = new CombinationSlotState((Dictionary)slot0Value);

            Assert.NotNull(slot0State.Result.itemUsable);

            var equipment       = (Equipment)slot0State.Result.itemUsable;
            var additionalStats = equipment.StatsMap
                                  .GetAdditionalStats(true)
                                  .ToArray();
            var skills = equipment.Skills;

            Assert.Equal(optionNumbers.Length, equipment.optionCountFromCombination);

            var optionSheet           = _tableSheets.EquipmentItemOptionSheet;
            var mainAdditionalStatMin = 0;
            var mainAdditionalStatMax = 0;
            var requiredBlockIndex    = recipeRow.RequiredBlockIndex + subRecipeRow.RequiredBlockIndex;
            var orderedOptions        = subRecipeRow.Options
                                        .OrderByDescending(e => e.Ratio)
                                        .ThenBy(e => e.RequiredBlockIndex)
                                        .ThenBy(e => e.Id)
                                        .ToArray();

            foreach (var optionNumber in optionNumbers)
            {
                var optionInfo = orderedOptions[optionNumber - 1];
                requiredBlockIndex += optionInfo.RequiredBlockIndex;
                var optionRow = optionSheet[optionInfo.Id];
                if (optionRow.StatMin > 0 || optionRow.StatMax > 0)
                {
                    if (optionRow.StatType == equipment.UniqueStatType)
                    {
                        mainAdditionalStatMin += optionRow.StatMin;
                        mainAdditionalStatMax += optionRow.StatMax;
                        continue;
                    }

                    var additionalStatValue = additionalStats
                                              .First(e => e.statType == optionRow.StatType)
                                              .additionalValue;
                    Assert.True(additionalStatValue >= optionRow.StatMin);
                    Assert.True(additionalStatValue <= optionRow.StatMax + 1);
                }
                else if (optionRow.SkillId != default)
                {
                    var skill = skills.First(e => e.SkillRow.Id == optionRow.SkillId);
                    Assert.True(skill.Chance >= optionRow.SkillChanceMin);
                    Assert.True(skill.Chance <= optionRow.SkillChanceMax + 1);
                    Assert.True(skill.Power >= optionRow.SkillDamageMin);
                    Assert.True(skill.Power <= optionRow.SkillDamageMax + 1);
                }
            }

            var mainAdditionalStatValue = additionalStats
                                          .First(e => e.statType == equipment.UniqueStatType)
                                          .additionalValue;

            Assert.True(mainAdditionalStatValue >= mainAdditionalStatMin);
            Assert.True(mainAdditionalStatValue <= mainAdditionalStatMax + 1);
            Assert.Equal(requiredBlockIndex, slot0State.RequiredBlockIndex);

            if (requiredBlockIndex == 0)
            {
                return;
            }

            var hourglassRow = _tableSheets.MaterialItemSheet
                               .First(pair => pair.Value.ItemSubType == ItemSubType.Hourglass)
                               .Value;

            inventoryValue = nextState.GetState(_inventoryAddress);
            Assert.NotNull(inventoryValue);
            inventoryState = new Inventory((List)inventoryValue);
            Assert.False(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out _));

            var diff           = slot0State.RequiredBlockIndex - GameConfig.RequiredAppraiseBlock;
            var hourglassCount = RapidCombination0.CalculateHourglassCount(gameConfigState, diff);

            inventoryState.AddFungibleItem(
                ItemFactory.CreateMaterial(_tableSheets.MaterialItemSheet, hourglassRow.Id),
                hourglassCount);
            Assert.True(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out var hourglasses));
            Assert.Equal(hourglassCount, hourglasses.Sum(e => e.count));
            nextState = nextState.SetState(_inventoryAddress, inventoryState.Serialize());

            var rapidCombinationAction = new RapidCombination
            {
                avatarAddress = _avatarAddress,
                slotIndex     = 0,
            };

            nextState = rapidCombinationAction.Execute(new ActionContext
            {
                PreviousStates = nextState,
                BlockIndex     = GameConfig.RequiredAppraiseBlock,
                Random         = random,
                Signer         = _agentAddress,
            });
            inventoryValue = nextState.GetState(_inventoryAddress);
            Assert.NotNull(inventoryValue);
            inventoryState = new Inventory((List)inventoryValue);
            Assert.False(inventoryState.TryGetFungibleItems(hourglassRow.ItemId, out _));
        }