From 5ed13dac6c78a1c7d4eab55416063f1568b840b1 Mon Sep 17 00:00:00 2001 From: hyeon Date: Thu, 28 Mar 2024 11:54:13 +0900 Subject: [PATCH 1/6] Update RuneEnhancement action: Multi level up - version 2 to 3 - Update TryEnhancement - Loop for maxTryCount - Calculates level up result and used costs - Check balance after enhancement --- Lib9c/Action/RuneEnhancement.cs | 54 +++++++++++++++++++---------- Lib9c/Helper/RuneHelper.cs | 61 +++++++++------------------------ Lib9c/Model/State/RuneState.cs | 4 +-- 3 files changed, 54 insertions(+), 65 deletions(-) diff --git a/Lib9c/Action/RuneEnhancement.cs b/Lib9c/Action/RuneEnhancement.cs index f2ed4f09f2..6e8ab9cfa9 100644 --- a/Lib9c/Action/RuneEnhancement.cs +++ b/Lib9c/Action/RuneEnhancement.cs @@ -17,7 +17,7 @@ namespace Nekoyume.Action { [Serializable] - [ActionType("runeEnhancement2")] + [ActionType("runeEnhancement3")] public class RuneEnhancement : GameAction, IRuneEnhancementV1 { public Address AvatarAddress; @@ -64,6 +64,7 @@ public override IWorld Execute(IActionContext context) typeof(RuneCostSheet), }); + // Validation if (TryCount < 1) { throw new TryCountIsZeroException( @@ -89,11 +90,11 @@ public override IWorld Execute(IActionContext context) $"[{nameof(RuneEnhancement)}] my avatar address : {AvatarAddress}"); } - var targetLevel = runeState.Level + 1; + var targetLevel = runeState.Level + TryCount; if (!costRow.TryGetCost(targetLevel, out var cost)) { - throw new RuneCostDataNotFoundException( - $"[{nameof(RuneEnhancement)}] my avatar address : {AvatarAddress}"); + throw new RuneCostNotFoundException( + $"[{nameof(RuneEnhancement)}] my avatar address : {AvatarAddress} : Maybe max level reached"); } var runeSheet = sheets.GetSheet(); @@ -110,34 +111,51 @@ public override IWorld Execute(IActionContext context) var crystalBalance = states.GetBalance(context.Signer, crystalCurrency); var runeBalance = states.GetBalance(AvatarAddress, runeCurrency); var random = context.GetRandom(); - if (RuneHelper.TryEnhancement(ncgBalance, crystalBalance, runeBalance, - ncgCurrency, crystalCurrency, runeCurrency, - cost, random, TryCount, out var tryCount)) + if (!RuneHelper.TryEnhancement(runeState, costRow, random, TryCount, + out var levelUpResult)) { - runeState.LevelUp(); - states = states.SetLegacyState(runeStateAddress, runeState.Serialize()); + // Rune cost not found while level up + throw new RuneCostNotFoundException( + $"[{nameof(RuneEnhancement)}] my avatar address : {AvatarAddress} : Maybe max level reached"); } + // Check final balance + if (ncgBalance < levelUpResult.ncgCost * ncgCurrency || + crystalBalance < levelUpResult.crystalCost * crystalCurrency || + runeBalance < levelUpResult.runeCost * runeCurrency) + { + throw new NotEnoughFungibleAssetValueException( + $"{nameof(RuneEnhancement)}" + + $"[ncg:{ncgBalance} < {levelUpResult.ncgCost * ncgCurrency}] " + + $"[crystal:{crystalBalance} < {levelUpResult.crystalCost * crystalCurrency}] " + + $"[rune:{runeBalance} < {levelUpResult.runeCost * runeCurrency}]" + ); + } + + runeState.LevelUp(levelUpResult.levelUpCount); + states = states.SetLegacyState(runeStateAddress, runeState.Serialize()); + var arenaSheet = sheets.GetSheet(); var arenaData = arenaSheet.GetRoundByBlockIndex(context.BlockIndex); var feeStoreAddress = Addresses.GetBlacksmithFeeAddress(arenaData.ChampionshipId, arenaData.Round); - var ncgCost = cost.NcgQuantity * tryCount * ncgCurrency; - if (cost.NcgQuantity > 0) + // Burn costs + if (levelUpResult.ncgCost > 0) { - states = states.TransferAsset(context, context.Signer, feeStoreAddress, ncgCost); + states = states.TransferAsset(context, context.Signer, feeStoreAddress, + levelUpResult.ncgCost * ncgCurrency); } - var crystalCost = cost.CrystalQuantity * tryCount * crystalCurrency; - if (cost.CrystalQuantity > 0) + if (levelUpResult.crystalCost > 0) { - states = states.TransferAsset(context, context.Signer, feeStoreAddress, crystalCost); + states = states.TransferAsset(context, context.Signer, feeStoreAddress, + levelUpResult.crystalCost * crystalCurrency); } - var runeCost = cost.RuneStoneQuantity * tryCount * runeCurrency; - if (cost.RuneStoneQuantity > 0) + if (levelUpResult.runeCost > 0) { - states = states.TransferAsset(context, AvatarAddress, feeStoreAddress, runeCost); + states = states.TransferAsset(context, AvatarAddress, feeStoreAddress, + levelUpResult.runeCost * runeCurrency); } return states; diff --git a/Lib9c/Helper/RuneHelper.cs b/Lib9c/Helper/RuneHelper.cs index ee25a43ff1..4ff5302e4f 100644 --- a/Lib9c/Helper/RuneHelper.cs +++ b/Lib9c/Helper/RuneHelper.cs @@ -4,8 +4,8 @@ using Lib9c; using Libplanet.Action; using Libplanet.Types.Assets; -using Nekoyume.Action; using Nekoyume.Battle; +using Nekoyume.Model.State; using Nekoyume.TableData; namespace Nekoyume.Helper @@ -86,61 +86,32 @@ IRandom random } public static bool TryEnhancement( - FungibleAssetValue ncg, - FungibleAssetValue crystal, - FungibleAssetValue rune, - Currency ncgCurrency, - Currency crystalCurrency, - Currency runeCurrency, - RuneCostSheet.RuneCostData cost, + RuneState runeState, + RuneCostSheet.Row costRow, IRandom random, int maxTryCount, - out int tryCount) + out (int levelUpCount, int ncgCost, int crystalCost, int runeCost) levelUpResult) { - tryCount = 0; - var value = cost.LevelUpSuccessRate + 1; - while (value > cost.LevelUpSuccessRate) - { - tryCount++; - if (tryCount > maxTryCount) - { - tryCount = maxTryCount; - return false; - } + levelUpResult = (0, 0, 0, 0); - if (!CheckBalance(ncg, crystal, rune, ncgCurrency, crystalCurrency, runeCurrency, cost, tryCount)) + for (var i = 0; i < maxTryCount; i++) + { + // No cost Found : throw exception at caller + if (!costRow.TryGetCost(runeState.Level + levelUpResult.levelUpCount + 1, + out var cost)) { return false; } - value = random.Next(1, GameConfig.MaximumProbability + 1); - } - - return true; - } + // Cost burns in every try + levelUpResult.ncgCost += cost.NcgQuantity; + levelUpResult.crystalCost += cost.CrystalQuantity; + levelUpResult.runeCost += cost.RuneStoneQuantity; - private static bool CheckBalance( - FungibleAssetValue ncg, - FungibleAssetValue crystal, - FungibleAssetValue rune, - Currency ncgCurrency, - Currency crystalCurrency, - Currency runeCurrency, - RuneCostSheet.RuneCostData cost, - int tryCount) - { - var ncgCost = tryCount * cost.NcgQuantity * ncgCurrency; - var crystalCost = tryCount * cost.CrystalQuantity * crystalCurrency; - var runeCost = tryCount * cost.RuneStoneQuantity * runeCurrency; - if (ncg < ncgCost || crystal < crystalCost || rune < runeCost) - { - if (tryCount == 1) + if (random.Next(0, GameConfig.MaximumProbability) < cost.LevelUpSuccessRate) { - throw new NotEnoughFungibleAssetValueException($"{nameof(RuneHelper)}" + - $"[ncg:{ncg} < {ncgCost}] [crystal:{crystal} < {crystalCost}] [rune:{rune} < {runeCost}]"); + levelUpResult.levelUpCount++; } - - return false; } return true; diff --git a/Lib9c/Model/State/RuneState.cs b/Lib9c/Model/State/RuneState.cs index cf4507ce80..59ee1ff24b 100644 --- a/Lib9c/Model/State/RuneState.cs +++ b/Lib9c/Model/State/RuneState.cs @@ -31,9 +31,9 @@ public IValue Serialize() return result; } - public void LevelUp() + public void LevelUp(int level = 1) { - Level++; + Level += level; } } } From 29acbb542565587a57ed654bab515077d894c2aa Mon Sep 17 00:00:00 2001 From: hyeon Date: Fri, 29 Mar 2024 12:20:58 +0900 Subject: [PATCH 2/6] Misc: conventions --- Lib9c/Action/RuneEnhancement.cs | 12 +++--------- Lib9c/Helper/RuneHelper.cs | 2 ++ 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/Lib9c/Action/RuneEnhancement.cs b/Lib9c/Action/RuneEnhancement.cs index 6e8ab9cfa9..e9df7ab054 100644 --- a/Lib9c/Action/RuneEnhancement.cs +++ b/Lib9c/Action/RuneEnhancement.cs @@ -72,16 +72,10 @@ public override IWorld Execute(IActionContext context) $"current TryCount : {TryCount}"); } - RuneState runeState; var runeStateAddress = RuneState.DeriveAddress(AvatarAddress, RuneId); - if (states.TryGetLegacyState(runeStateAddress, out List rawState)) - { - runeState = new RuneState(rawState); - } - else - { - runeState = new RuneState(RuneId); - } + var runeState = states.TryGetLegacyState(runeStateAddress, out List rawState) + ? new RuneState(rawState) + : new RuneState(RuneId); var costSheet = sheets.GetSheet(); if (!costSheet.TryGetValue(runeState.RuneId, out var costRow)) diff --git a/Lib9c/Helper/RuneHelper.cs b/Lib9c/Helper/RuneHelper.cs index 4ff5302e4f..e65e3d407a 100644 --- a/Lib9c/Helper/RuneHelper.cs +++ b/Lib9c/Helper/RuneHelper.cs @@ -46,6 +46,7 @@ IRandom random { rr.SetRune(random); } + var total = 0; var dictionary = new Dictionary(); while (total < rewardRow.Rune) @@ -82,6 +83,7 @@ IRandom random { result.Add(rewardRow.Crystal * CrystalCalculator.CRYSTAL); } + return result; } From 1dbec412d308d2cc87031b62356ffbebb2b45311 Mon Sep 17 00:00:00 2001 From: hyeon Date: Fri, 29 Mar 2024 17:38:24 +0900 Subject: [PATCH 3/6] Pass just level, not whole state --- Lib9c/Action/RuneEnhancement.cs | 2 +- Lib9c/Helper/RuneHelper.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib9c/Action/RuneEnhancement.cs b/Lib9c/Action/RuneEnhancement.cs index e9df7ab054..16dc47f924 100644 --- a/Lib9c/Action/RuneEnhancement.cs +++ b/Lib9c/Action/RuneEnhancement.cs @@ -105,7 +105,7 @@ public override IWorld Execute(IActionContext context) var crystalBalance = states.GetBalance(context.Signer, crystalCurrency); var runeBalance = states.GetBalance(AvatarAddress, runeCurrency); var random = context.GetRandom(); - if (!RuneHelper.TryEnhancement(runeState, costRow, random, TryCount, + if (!RuneHelper.TryEnhancement(runeState.Level, costRow, random, TryCount, out var levelUpResult)) { // Rune cost not found while level up diff --git a/Lib9c/Helper/RuneHelper.cs b/Lib9c/Helper/RuneHelper.cs index e65e3d407a..cc5cafddf3 100644 --- a/Lib9c/Helper/RuneHelper.cs +++ b/Lib9c/Helper/RuneHelper.cs @@ -88,7 +88,7 @@ IRandom random } public static bool TryEnhancement( - RuneState runeState, + int startRuneLevel, RuneCostSheet.Row costRow, IRandom random, int maxTryCount, @@ -99,7 +99,7 @@ public static bool TryEnhancement( for (var i = 0; i < maxTryCount; i++) { // No cost Found : throw exception at caller - if (!costRow.TryGetCost(runeState.Level + levelUpResult.levelUpCount + 1, + if (!costRow.TryGetCost(startRuneLevel + levelUpResult.LevelUpCount + 1, out var cost)) { return false; From edba762c5b584ee45c5b79942b1e00963c76c7f7 Mon Sep 17 00:00:00 2001 From: hyeon Date: Fri, 29 Mar 2024 17:39:09 +0900 Subject: [PATCH 4/6] Create struct for convenience --- Lib9c/Action/RuneEnhancement.cs | 59 ++++++++++++++++++++------------- Lib9c/Helper/RuneHelper.cs | 18 +++++----- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/Lib9c/Action/RuneEnhancement.cs b/Lib9c/Action/RuneEnhancement.cs index 16dc47f924..9f96431993 100644 --- a/Lib9c/Action/RuneEnhancement.cs +++ b/Lib9c/Action/RuneEnhancement.cs @@ -24,6 +24,17 @@ public class RuneEnhancement : GameAction, IRuneEnhancementV1 public int RuneId; public int TryCount = 1; + public struct LevelUpResult + { + public int LevelUpCount { get; set; } + public int NcgCost { get; set; } + public int CrystalCost { get; set; } + public int RuneCost { get; set; } + + public override string ToString() => + $"{LevelUpCount} level up with cost {NcgCost} NCG, {CrystalCost} Crystal, {RuneCost} Runestone."; + } + Address IRuneEnhancementV1.AvatarAddress => AvatarAddress; int IRuneEnhancementV1.RuneId => RuneId; int IRuneEnhancementV1.TryCount => TryCount; @@ -85,9 +96,9 @@ public override IWorld Execute(IActionContext context) } var targetLevel = runeState.Level + TryCount; - if (!costRow.TryGetCost(targetLevel, out var cost)) + if (!costRow.TryGetCost(targetLevel, out _)) { - throw new RuneCostNotFoundException( + throw new RuneCostDataNotFoundException( $"[{nameof(RuneEnhancement)}] my avatar address : {AvatarAddress} : Maybe max level reached"); } @@ -98,58 +109,60 @@ public override IWorld Execute(IActionContext context) $"[{nameof(RuneEnhancement)}] my avatar address : {AvatarAddress}"); } - var ncgCurrency = states.GetGoldCurrency(); - var crystalCurrency = CrystalCalculator.CRYSTAL; - var runeCurrency = Currency.Legacy(runeRow.Ticker, 0, minters: null); - var ncgBalance = states.GetBalance(context.Signer, ncgCurrency); - var crystalBalance = states.GetBalance(context.Signer, crystalCurrency); - var runeBalance = states.GetBalance(AvatarAddress, runeCurrency); var random = context.GetRandom(); if (!RuneHelper.TryEnhancement(runeState.Level, costRow, random, TryCount, out var levelUpResult)) { // Rune cost not found while level up - throw new RuneCostNotFoundException( + throw new RuneCostDataNotFoundException( $"[{nameof(RuneEnhancement)}] my avatar address : {AvatarAddress} : Maybe max level reached"); } // Check final balance - if (ncgBalance < levelUpResult.ncgCost * ncgCurrency || - crystalBalance < levelUpResult.crystalCost * crystalCurrency || - runeBalance < levelUpResult.runeCost * runeCurrency) + var ncgCurrency = states.GetGoldCurrency(); + var crystalCurrency = CrystalCalculator.CRYSTAL; + var runeCurrency = Currency.Legacy(runeRow.Ticker, 0, minters: null); + var ncgBalance = states.GetBalance(context.Signer, ncgCurrency); + var crystalBalance = states.GetBalance(context.Signer, crystalCurrency); + var runeBalance = states.GetBalance(AvatarAddress, runeCurrency); + + if (ncgBalance < levelUpResult.NcgCost * ncgCurrency || + crystalBalance < levelUpResult.CrystalCost * crystalCurrency || + runeBalance < levelUpResult.RuneCost * runeCurrency) { throw new NotEnoughFungibleAssetValueException( $"{nameof(RuneEnhancement)}" + - $"[ncg:{ncgBalance} < {levelUpResult.ncgCost * ncgCurrency}] " + - $"[crystal:{crystalBalance} < {levelUpResult.crystalCost * crystalCurrency}] " + - $"[rune:{runeBalance} < {levelUpResult.runeCost * runeCurrency}]" + $"[ncg:{ncgBalance} < {levelUpResult.NcgCost * ncgCurrency}] " + + $"[crystal:{crystalBalance} < {levelUpResult.CrystalCost * crystalCurrency}] " + + $"[rune:{runeBalance} < {levelUpResult.RuneCost * runeCurrency}]" ); } - runeState.LevelUp(levelUpResult.levelUpCount); + runeState.LevelUp(levelUpResult.LevelUpCount); states = states.SetLegacyState(runeStateAddress, runeState.Serialize()); var arenaSheet = sheets.GetSheet(); var arenaData = arenaSheet.GetRoundByBlockIndex(context.BlockIndex); - var feeStoreAddress = Addresses.GetBlacksmithFeeAddress(arenaData.ChampionshipId, arenaData.Round); + var feeStoreAddress = + Addresses.GetBlacksmithFeeAddress(arenaData.ChampionshipId, arenaData.Round); // Burn costs - if (levelUpResult.ncgCost > 0) + if (levelUpResult.NcgCost > 0) { states = states.TransferAsset(context, context.Signer, feeStoreAddress, - levelUpResult.ncgCost * ncgCurrency); + levelUpResult.NcgCost * ncgCurrency); } - if (levelUpResult.crystalCost > 0) + if (levelUpResult.CrystalCost > 0) { states = states.TransferAsset(context, context.Signer, feeStoreAddress, - levelUpResult.crystalCost * crystalCurrency); + levelUpResult.CrystalCost * crystalCurrency); } - if (levelUpResult.runeCost > 0) + if (levelUpResult.RuneCost > 0) { states = states.TransferAsset(context, AvatarAddress, feeStoreAddress, - levelUpResult.runeCost * runeCurrency); + levelUpResult.RuneCost * runeCurrency); } return states; diff --git a/Lib9c/Helper/RuneHelper.cs b/Lib9c/Helper/RuneHelper.cs index cc5cafddf3..c741586273 100644 --- a/Lib9c/Helper/RuneHelper.cs +++ b/Lib9c/Helper/RuneHelper.cs @@ -4,8 +4,8 @@ using Lib9c; using Libplanet.Action; using Libplanet.Types.Assets; +using Nekoyume.Action; using Nekoyume.Battle; -using Nekoyume.Model.State; using Nekoyume.TableData; namespace Nekoyume.Helper @@ -91,12 +91,12 @@ public static bool TryEnhancement( int startRuneLevel, RuneCostSheet.Row costRow, IRandom random, - int maxTryCount, - out (int levelUpCount, int ncgCost, int crystalCost, int runeCost) levelUpResult) + int tryCount, + out RuneEnhancement.LevelUpResult levelUpResult) { - levelUpResult = (0, 0, 0, 0); + levelUpResult = new RuneEnhancement.LevelUpResult(); - for (var i = 0; i < maxTryCount; i++) + for (var i = 0; i < tryCount; i++) { // No cost Found : throw exception at caller if (!costRow.TryGetCost(startRuneLevel + levelUpResult.LevelUpCount + 1, @@ -106,13 +106,13 @@ public static bool TryEnhancement( } // Cost burns in every try - levelUpResult.ncgCost += cost.NcgQuantity; - levelUpResult.crystalCost += cost.CrystalQuantity; - levelUpResult.runeCost += cost.RuneStoneQuantity; + levelUpResult.NcgCost += cost.NcgQuantity; + levelUpResult.CrystalCost += cost.CrystalQuantity; + levelUpResult.RuneCost += cost.RuneStoneQuantity; if (random.Next(0, GameConfig.MaximumProbability) < cost.LevelUpSuccessRate) { - levelUpResult.levelUpCount++; + levelUpResult.LevelUpCount++; } } From ebe8b1045c824b38731f13c9ecab6657f12e8912 Mon Sep 17 00:00:00 2001 From: hyeon Date: Fri, 29 Mar 2024 17:39:22 +0900 Subject: [PATCH 5/6] Update tests - Level up success - Multiple level up success - Partial level up success from multiple try - Level up fail - Exceeding max level --- .Lib9c.Tests/Action/RuneEnhancementTest.cs | 154 ++++++++------------- 1 file changed, 59 insertions(+), 95 deletions(-) diff --git a/.Lib9c.Tests/Action/RuneEnhancementTest.cs b/.Lib9c.Tests/Action/RuneEnhancementTest.cs index ec108d4b75..5395b93701 100644 --- a/.Lib9c.Tests/Action/RuneEnhancementTest.cs +++ b/.Lib9c.Tests/Action/RuneEnhancementTest.cs @@ -26,10 +26,34 @@ public RuneEnhancementTest() } [Theory] - [InlineData(10000)] - [InlineData(1)] - public void Execute(int seed) + // All success + [InlineData(1, 1, 2, 0, 0, 1, null, 0)] + [InlineData(1, 2, 3, 0, 0, 2, null, 0)] + // Success 1 of 2 + [InlineData(202, 2, 203, 0, 1000, 40, null, 2)] + // All fail + [InlineData(202, 2, 202, 0, 1000, 40, null, 0)] + // Reaching max level + [InlineData(299, 1, 300, 0, 500, 20, null, 1)] + // Cannot exceed max level + [InlineData(299, 2, 299, 0, 0, 0, typeof(RuneCostDataNotFoundException), 0)] + [InlineData(300, 1, 300, 0, 0, 0, typeof(RuneCostDataNotFoundException), 0)] + public void Execute( + int startLevel, + int tryCount, + int expectedLevel, + int expectedNcgCost, + int expectedCrystalCost, + int expectedRuneCost, + Type expectedException, + int seed + ) { + const int initialNcg = 10_000; + const int initialCrystal = 1_000_000; + const int initialRune = 1_000; + var s = seed; + // Set states var agentAddress = new PrivateKey().Address; var avatarAddress = new PrivateKey().Address; var sheets = TableSheetsImporter.ImportSheets(); @@ -66,55 +90,22 @@ public void Execute(int seed) var runeId = runeListSheet.First().Value.Id; var runeStateAddress = RuneState.DeriveAddress(avatarState.address, runeId); var runeState = new RuneState(runeId); + runeState.LevelUp(startLevel); state = state.SetLegacyState(runeStateAddress, runeState.Serialize()); - var costSheet = state.GetSheet(); - if (!costSheet.TryGetValue(runeId, out var costRow)) - { - throw new RuneCostNotFoundException($"[{nameof(Execute)}] "); - } - - if (!costRow.TryGetCost(runeState.Level + 1, out var cost)) - { - throw new RuneCostDataNotFoundException($"[{nameof(Execute)}] "); - } - - var runeSheet = state.GetSheet(); - if (!runeSheet.TryGetValue(runeId, out var runeRow)) - { - throw new RuneNotFoundException($"[{nameof(Execute)}] "); - } - + // Prepare materials var ncgCurrency = state.GetGoldCurrency(); var crystalCurrency = CrystalCalculator.CRYSTAL; - var runeCurrency = Currency.Legacy(runeRow.Ticker, 0, minters: null); - - var ncgBal = cost.NcgQuantity * ncgCurrency * 10000; - var crystalBal = cost.CrystalQuantity * crystalCurrency * 10000; - var runeBal = cost.RuneStoneQuantity * runeCurrency * 10000; - - var rand = new TestRandom(seed); - if (!RuneHelper.TryEnhancement(ncgBal, crystalBal, runeBal, ncgCurrency, crystalCurrency, runeCurrency, cost, rand, 99, out var tryCount)) - { - throw new RuneNotFoundException($"[{nameof(Execute)}] "); - } - - if (ncgBal.Sign > 0) - { - state = state.MintAsset(context, agentAddress, ncgBal); - } + var runeTicker = tableSheets.RuneSheet.Values.First(r => r.Id == runeId).Ticker; + var runeCurrency = Currency.Legacy(runeTicker, 0, minters: null); + var r = new TestRandom(seed: 1); - if (crystalBal.Sign > 0) - { - state = state.MintAsset(context, agentAddress, crystalBal); - } + state = state.MintAsset(context, agentAddress, ncgCurrency * initialNcg); + state = state.MintAsset(context, agentAddress, crystalCurrency * initialCrystal); + state = state.MintAsset(context, avatarAddress, runeCurrency * initialRune); - if (runeBal.Sign > 0) - { - state = state.MintAsset(context, avatarState.address, runeBal); - } - - var action = new RuneEnhancement() + // Action + var action = new RuneEnhancement { AvatarAddress = avatarState.address, RuneId = runeId, @@ -124,62 +115,35 @@ public void Execute(int seed) { BlockIndex = blockIndex, PreviousState = state, - RandomSeed = rand.Seed, + RandomSeed = seed, Signer = agentAddress, }; - var nextState = action.Execute(ctx); - if (!nextState.TryGetLegacyState(runeStateAddress, out List nextRuneRawState)) - { - throw new Exception(); - } - - var nextRunState = new RuneState(nextRuneRawState); - var nextNcgBal = nextState.GetBalance(agentAddress, ncgCurrency); - var nextCrystalBal = nextState.GetBalance(agentAddress, crystalCurrency); - var nextRuneBal = nextState.GetBalance(agentAddress, runeCurrency); - - if (cost.NcgQuantity != 0) - { - Assert.NotEqual(ncgBal, nextNcgBal); - } - - if (cost.CrystalQuantity != 0) + if (expectedException is not null) { - Assert.NotEqual(crystalBal, nextCrystalBal); + Assert.Throws(expectedException, () => { action.Execute(ctx); }); } - - if (cost.RuneStoneQuantity != 0) + else { - Assert.NotEqual(runeBal, nextRuneBal); - } - - var costNcg = tryCount * cost.NcgQuantity * ncgCurrency; - var costCrystal = tryCount * cost.CrystalQuantity * crystalCurrency; - var costRune = tryCount * cost.RuneStoneQuantity * runeCurrency; - - if (costNcg.Sign > 0) - { - nextState = nextState.MintAsset(context, agentAddress, costNcg); - } - - if (costCrystal.Sign > 0) - { - nextState = nextState.MintAsset(context, agentAddress, costCrystal); - } - - if (costRune.Sign > 0) - { - nextState = nextState.MintAsset(context, avatarState.address, costRune); + var nextState = action.Execute(ctx); + if (!nextState.TryGetLegacyState(runeStateAddress, out List nextRuneRawState)) + { + throw new Exception(); + } + + var nextRuneState = new RuneState(nextRuneRawState); + var nextNcgBal = nextState.GetBalance(agentAddress, ncgCurrency); + var nextCrystalBal = nextState.GetBalance(agentAddress, crystalCurrency); + var nextRuneBal = nextState.GetBalance(avatarAddress, runeCurrency); + + Assert.Equal((initialNcg - expectedNcgCost) * ncgCurrency, nextNcgBal); + Assert.Equal( + (initialCrystal - expectedCrystalCost) * crystalCurrency, + nextCrystalBal + ); + Assert.Equal((initialRune - expectedRuneCost) * runeCurrency, nextRuneBal); + Assert.Equal(expectedLevel, nextRuneState.Level); } - - var finalNcgBal = nextState.GetBalance(agentAddress, ncgCurrency); - var finalCrystalBal = nextState.GetBalance(agentAddress, crystalCurrency); - var finalRuneBal = nextState.GetBalance(avatarState.address, runeCurrency); - Assert.Equal(ncgBal, finalNcgBal); - Assert.Equal(crystalBal, finalCrystalBal); - Assert.Equal(runeBal, finalRuneBal); - Assert.Equal(runeState.Level + 1, nextRunState.Level); } [Fact] From d1495d969c8fc4500349a36cf810dc39f88ef5b3 Mon Sep 17 00:00:00 2001 From: hyeon Date: Fri, 29 Mar 2024 17:40:31 +0900 Subject: [PATCH 6/6] Version not need to be updated --- Lib9c/Action/RuneEnhancement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib9c/Action/RuneEnhancement.cs b/Lib9c/Action/RuneEnhancement.cs index 9f96431993..c02afe0e0a 100644 --- a/Lib9c/Action/RuneEnhancement.cs +++ b/Lib9c/Action/RuneEnhancement.cs @@ -17,7 +17,7 @@ namespace Nekoyume.Action { [Serializable] - [ActionType("runeEnhancement3")] + [ActionType("runeEnhancement2")] public class RuneEnhancement : GameAction, IRuneEnhancementV1 { public Address AvatarAddress;