502 lines
15 KiB
Go
502 lines
15 KiB
Go
package gameserver
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"gac-hkrpg-go/internal/common"
|
|
kcplib "gac-hkrpg-go/pkg/kcp"
|
|
pb "gac-hkrpg-go/protocol/proto"
|
|
"google.golang.org/protobuf/proto"
|
|
"google.golang.org/protobuf/reflect/protoreflect"
|
|
)
|
|
|
|
func TestCurrencyWarsXaodevEncounterAdvancesSelectsAndDoesNotDuplicateGold(t *testing.T) {
|
|
c, err := common.LoadCurrencyWarsCatalog()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
refs, err := common.LoadCurrencyWarsReferenceNodes(c)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var route []common.CurrencyWarsRouteNode
|
|
var index int
|
|
for _, r := range c.StageRoutes {
|
|
rows, err := c.RouteNodes(r.RouteID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for i, n := range rows {
|
|
tmpl, err := refs.Template(n.NodeTemplateID)
|
|
if err == nil && tmpl.NodeType == "EliteBranch" && i > 0 {
|
|
route, index = rows, i
|
|
break
|
|
}
|
|
}
|
|
if route != nil {
|
|
break
|
|
}
|
|
}
|
|
if route == nil {
|
|
t.Fatal("no Encounter route")
|
|
}
|
|
// Build only typed components needed for a detached route transaction.
|
|
target, previous := route[index], route[index-1]
|
|
stage := &pb.BEEFLEJAOCN{EMOHLJHPOPC: target.RouteID, DCAHJELNJNP: previous.ChapterID, SectionId: previous.SectionID}
|
|
policy, err := cwLoadReferenceEnemies(c)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var campID uint32
|
|
x, err := common.LoadCurrencyWarsXaodev(c)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, camp := range c.MonsterCamps {
|
|
if camp.SeasonID != c.ActiveSeasonID {
|
|
continue
|
|
}
|
|
for _, id := range camp.Season.MonsterList {
|
|
if policy.MonsterTiers[id] == x.Policy.MonsterTier {
|
|
campID = camp.ID
|
|
break
|
|
}
|
|
}
|
|
if campID != 0 {
|
|
break
|
|
}
|
|
}
|
|
if campID == 0 {
|
|
t.Fatal("no eligible camp")
|
|
}
|
|
// Obtain camp-list element type from its descriptor instead of copying
|
|
// an obfuscated generated type name into the fixture.
|
|
field := stage.ProtoReflect().Descriptor().Fields().ByName("HEKMEJLMGFF")
|
|
list := stage.ProtoReflect().Mutable(field).List()
|
|
for i := uint32(0); i < target.ChapterID; i++ {
|
|
entry := list.NewElement()
|
|
f := entry.Message().Descriptor().Fields().ByName("LOGHLGKIFEN")
|
|
entry.Message().Set(f, protoreflect.ValueOfUint32(campID))
|
|
list.Append(entry)
|
|
}
|
|
for _, n := range route {
|
|
tmpl, err := refs.Template(n.NodeTemplateID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var kind uint32
|
|
for _, k := range c.NodeTypes {
|
|
if k.Name == tmpl.NodeType {
|
|
kind = k.Value
|
|
}
|
|
}
|
|
stage.OOMMIIKPHBC = append(stage.OOMMIIKPHBC, &pb.BCCIJHPLJOJ{DCAHJELNJNP: n.ChapterID, SectionId: n.SectionID, DisplayValue: &pb.OHMDHKGAEMM{StageId: tmpl.StageID, CJCCMAACJDB: kind, PICMDONCKCO: tmpl.BasicGoldRewardNum}})
|
|
}
|
|
player := &pb.NIHNGPKHEPC{Gold: 10}
|
|
var divisionID uint32
|
|
for _, d := range x.Divisions {
|
|
if d.BinaryNodeDiffAddRule != 0 {
|
|
divisionID = d.DivisionID
|
|
break
|
|
}
|
|
}
|
|
run := &pb.MPIMAEMCEFH{UniqueId: 1, DivisionId: c.CapturedStages[0].ID, LJNGPCKPJLF: c.ActiveSeasonID, FMIGOKIDKJL: &pb.CHCHAJIANIM{QueuePosition: 10}, NAGDJGMMCBE: []*pb.GridFightGameInfo{
|
|
{LEOIAOFBBFA: &pb.GridFightGameInfo_KLCPAAHDPJF{KLCPAAHDPJF: stage}},
|
|
{LEOIAOFBBFA: &pb.GridFightGameInfo_FAOCFBOFCJP{FAOCFBOFCJP: player}},
|
|
}}
|
|
runtime := &common.CurrencyWarsRuntimeState{RunID: run.UniqueId, Rules: map[string]uint32{}}
|
|
run.DivisionId = divisionID
|
|
if _, err := cwAdvanceRouteNode(c, run, runtime); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
layer := stage.GetIMPNAHBCADN().GetMPOBBIPMNNJ()
|
|
if len(layer.BPDABHGFBFO) != 2 || !cwXaodevGenerated(run, runtime) {
|
|
t.Fatal("generated branch/source missing")
|
|
}
|
|
_, display := cwStage(run)
|
|
again, err := cwGenerateXaodevEncounter(c, run, display)
|
|
if err != nil || !proto.Equal(stage.IMPNAHBCADN, again) {
|
|
t.Fatalf("Encounter generation unstable: %v", err)
|
|
}
|
|
pending, err := cwGeneratedRoundPreparation(c, run)
|
|
if err != nil || pending.GetBAKAKODKECM() == nil {
|
|
t.Fatalf("branch pending missing: %v", err)
|
|
}
|
|
run.FMIGOKIDKJL = pending
|
|
if _, err := cwSelectEncounter(c, run, &pb.OHAINOHGKCM{MOADBALHMFD: 3}, runtime); err == nil {
|
|
t.Fatal("unadvertised branch accepted")
|
|
}
|
|
notify, err := cwSelectEncounter(c, run, &pb.OHAINOHGKCM{MOADBALHMFD: 2}, runtime)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if notify.GCPNIHHBGGD[0].JKPJFKCBIEM[1].GetCEDMLOEDPEH() == nil {
|
|
t.Fatal("difficulty not synchronized with branch")
|
|
}
|
|
add, err := x.BranchDifficulty(run.DivisionId, layer.BPDABHGFBFO[1].CJADMFDOBAI)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
base, _ := c.CapturedStage(run.DivisionId)
|
|
if stage.ANJBLBEOJND.PIJBPDPEODG != base.EnemyHardLevel+add {
|
|
t.Fatal("branch difficulty differs")
|
|
}
|
|
if _, err := cwEncounterRewards(c, run, layer.BPDABHGFBFO[1], 100, 0, runtime); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if player.Gold != 10 {
|
|
t.Fatal("preview gold awarded twice")
|
|
}
|
|
before := proto.Clone(run)
|
|
if _, err := cwXaodevDifficulty(c, run, ^uint32(0)); err == nil || !proto.Equal(before, run) {
|
|
t.Fatal("invalid difficulty changed run")
|
|
}
|
|
}
|
|
|
|
func findRepoRoot() string {
|
|
dir, err := os.Getwd()
|
|
if err != nil {
|
|
return "."
|
|
}
|
|
for i := 0; i < 6; i++ {
|
|
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
|
|
return dir
|
|
}
|
|
parent := filepath.Dir(dir)
|
|
if parent == dir {
|
|
break
|
|
}
|
|
dir = parent
|
|
}
|
|
return "."
|
|
}
|
|
|
|
func TestCurrencyWarsSupplyToEncounterBattleSettlementPipeline(t *testing.T) {
|
|
repoRoot := findRepoRoot()
|
|
tempDir := filepath.Join(repoRoot, "test_tmp_cw_integration")
|
|
if err := os.MkdirAll(tempDir, 0755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Cleanup(func() {
|
|
_ = os.RemoveAll(tempDir)
|
|
})
|
|
t.Chdir(tempDir)
|
|
|
|
baseCfg, err := os.ReadFile(filepath.Join(repoRoot, "server.json"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile("server.json", baseCfg, 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile("persistent", []byte(`{}`), 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
t.Setenv("GAC_CONFIG", "server.json")
|
|
|
|
c, err := common.LoadCurrencyWarsCatalog()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
wd, _ := os.Getwd()
|
|
t.Logf("pipeline test wd=%s, repoRoot=%s", wd, repoRoot)
|
|
refs, err := common.LoadCurrencyWarsReferenceNodes(c)
|
|
if err != nil {
|
|
t.Fatalf("LoadCurrencyWarsReferenceNodes failed at wd=%s: %v", wd, err)
|
|
}
|
|
x, err := common.LoadCurrencyWarsXaodev(c)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
routeNodes, err := c.RouteNodes(2801)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
policy, err := cwLoadReferenceEnemies(c)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var campID uint32
|
|
for _, camp := range c.MonsterCamps {
|
|
if camp.SeasonID != c.ActiveSeasonID {
|
|
continue
|
|
}
|
|
for _, id := range camp.Season.MonsterList {
|
|
if policy.MonsterTiers[id] == x.Policy.MonsterTier {
|
|
campID = camp.ID
|
|
break
|
|
}
|
|
}
|
|
if campID != 0 {
|
|
break
|
|
}
|
|
}
|
|
if campID == 0 {
|
|
t.Fatal("no eligible camp")
|
|
}
|
|
|
|
var divisionID uint32
|
|
for _, d := range x.Divisions {
|
|
if d.BinaryNodeDiffAddRule != 0 {
|
|
divisionID = d.DivisionID
|
|
break
|
|
}
|
|
}
|
|
if divisionID == 0 {
|
|
t.Fatal("no division with difficulty add rules")
|
|
}
|
|
|
|
stage := &pb.BEEFLEJAOCN{EMOHLJHPOPC: 2801, DCAHJELNJNP: 2, SectionId: 2}
|
|
field := stage.ProtoReflect().Descriptor().Fields().ByName("HEKMEJLMGFF")
|
|
list := stage.ProtoReflect().Mutable(field).List()
|
|
for i := uint32(0); i < 4; i++ {
|
|
entry := list.NewElement()
|
|
f := entry.Message().Descriptor().Fields().ByName("LOGHLGKIFEN")
|
|
entry.Message().Set(f, protoreflect.ValueOfUint32(campID))
|
|
list.Append(entry)
|
|
}
|
|
for _, n := range routeNodes {
|
|
tmpl, err := refs.Template(n.NodeTemplateID)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var kind uint32
|
|
for _, k := range c.NodeTypes {
|
|
if k.Name == tmpl.NodeType {
|
|
kind = k.Value
|
|
}
|
|
}
|
|
stage.OOMMIIKPHBC = append(stage.OOMMIIKPHBC, &pb.BCCIJHPLJOJ{
|
|
DCAHJELNJNP: n.ChapterID,
|
|
SectionId: n.SectionID,
|
|
DisplayValue: &pb.OHMDHKGAEMM{
|
|
StageId: tmpl.StageID,
|
|
CJCCMAACJDB: kind,
|
|
PICMDONCKCO: tmpl.BasicGoldRewardNum,
|
|
},
|
|
})
|
|
}
|
|
|
|
firstLevel := c.PlayerLevels[0]
|
|
maxLevel := c.PlayerLevels[len(c.PlayerLevels)-1].Level
|
|
player := &pb.NIHNGPKHEPC{
|
|
Gold: 50,
|
|
GridFightLineupHp: 100,
|
|
PPKKHHNEOHB: 100,
|
|
AFFCFLFIFPH: firstLevel.AvatarMaxNumber,
|
|
MICEOJBAKGN: 8,
|
|
EHNJDIDABHD: firstLevel.Level,
|
|
NDAINFLOLPJ: maxLevel,
|
|
}
|
|
var sampleVariant common.CurrencyWarsRoleVariant
|
|
for _, v := range c.CapturedVariants {
|
|
if v.Star == 1 {
|
|
sampleVariant = v
|
|
break
|
|
}
|
|
}
|
|
if sampleVariant.Config.ID == 0 {
|
|
t.Fatal("no star 1 role variant found")
|
|
}
|
|
|
|
team := &pb.HKFECLCHBFJ{
|
|
GridGameRoleList: []*pb.CDEAABODKCP{
|
|
{
|
|
Id: sampleVariant.Config.ID, RoleStar: sampleVariant.Star, Pos: 1, UniqueId: 1,
|
|
ConvertPropertyToFixpoint: map[uint32]uint32{1: 1000},
|
|
},
|
|
},
|
|
}
|
|
shop := &pb.POCJDMMANBM{}
|
|
bag := &pb.CONONEALNOF{}
|
|
run := &pb.MPIMAEMCEFH{
|
|
UniqueId: 101,
|
|
DivisionId: divisionID,
|
|
LJNGPCKPJLF: c.ActiveSeasonID,
|
|
NAGDJGMMCBE: []*pb.GridFightGameInfo{
|
|
{LEOIAOFBBFA: &pb.GridFightGameInfo_KLCPAAHDPJF{KLCPAAHDPJF: stage}},
|
|
{LEOIAOFBBFA: &pb.GridFightGameInfo_FAOCFBOFCJP{FAOCFBOFCJP: player}},
|
|
{LEOIAOFBBFA: &pb.GridFightGameInfo_EJIPINIKNCK{EJIPINIKNCK: team}},
|
|
{LEOIAOFBBFA: &pb.GridFightGameInfo_EBHDIOGALIE{EBHDIOGALIE: shop}},
|
|
{LEOIAOFBBFA: &pb.GridFightGameInfo_GCKLIONKMJC{GCKLIONKMJC: bag}},
|
|
},
|
|
}
|
|
|
|
s := &Session{kcp: kcplib.New(1, 1, false, func([]byte) error { return nil })}
|
|
_ = s.kcp.Update(s.kcp.Now())
|
|
s.Token = 1
|
|
s.json = &common.FreesrData{
|
|
Avatars: map[uint32]*common.AvatarJson{
|
|
sampleVariant.Config.AvatarID: {AvatarID: sampleVariant.Config.AvatarID, Level: 80, Data: common.AvatarData{Rank: 6}},
|
|
},
|
|
}
|
|
|
|
data, err := newCurrencyWarsData(c)
|
|
if err != nil {
|
|
t.Fatalf("newCurrencyWarsData: %v", err)
|
|
}
|
|
data.DHFOFLFCLAH = run
|
|
data.LFLCDNGALME.HFPEJIDDDJG.DivisionId = divisionID
|
|
|
|
supplyOffer, err := cwGenerateSupplyOffer(c, run)
|
|
if err != nil {
|
|
t.Fatalf("generate supply offer: %v", err)
|
|
}
|
|
run.FMIGOKIDKJL = &pb.CHCHAJIANIM{
|
|
QueuePosition: 1,
|
|
FGLIODAJFML: &pb.CHCHAJIANIM_FIKAGBAEOAP{FIKAGBAEOAP: supplyOffer},
|
|
}
|
|
|
|
runtime := &common.CurrencyWarsRuntimeState{RunID: run.UniqueId, Rules: map[string]uint32{}}
|
|
if err := s.saveCurrencyWarsDataWithRuntime(data, c, runtime); err != nil {
|
|
t.Fatalf("initial save: %v", err)
|
|
}
|
|
|
|
// 1. Supply Selection -> Advances to Chapter 2 Section 3 (EliteBranch)
|
|
supplyReq := &pb.HMNMJKCHABE{LOAFKKAFBOK: []uint32{1}}
|
|
if _, err := cwSelectSupply(c, run, supplyReq, runtime); err != nil {
|
|
t.Fatalf("select supply: %v", err)
|
|
}
|
|
if stage.DCAHJELNJNP != 2 || stage.SectionId != 3 {
|
|
t.Fatalf("expected advance to Ch2 Sec3, got Ch%d Sec%d", stage.DCAHJELNJNP, stage.SectionId)
|
|
}
|
|
if !cwXaodevGenerated(run, runtime) {
|
|
t.Fatal("expected xaodev generated marker on Encounter node")
|
|
}
|
|
if err := s.saveCurrencyWarsDataWithRuntime(data, c, runtime); err != nil {
|
|
t.Fatalf("save after supply: %v", err)
|
|
}
|
|
|
|
// 2. Round preparation sets pending to SelectingEncounter
|
|
prepPending, err := cwGeneratedRoundPreparation(c, run)
|
|
if err != nil || prepPending.GetBAKAKODKECM() == nil {
|
|
t.Fatalf("prepare encounter pending: %v", err)
|
|
}
|
|
run.FMIGOKIDKJL = prepPending
|
|
if err := s.saveCurrencyWarsDataWithRuntime(data, c, runtime); err != nil {
|
|
t.Fatalf("save prep pending: %v", err)
|
|
}
|
|
|
|
// 3. Player selects Encounter Branch 2 (powerful branch)
|
|
encounterLayer := stage.GetIMPNAHBCADN().GetMPOBBIPMNNJ()
|
|
if len(encounterLayer.BPDABHGFBFO) != 2 {
|
|
t.Fatalf("expected 2 encounter branches, got %d", len(encounterLayer.BPDABHGFBFO))
|
|
}
|
|
selReq := &pb.OHAINOHGKCM{MOADBALHMFD: 2}
|
|
selNotify, err := cwSelectEncounter(c, run, selReq, runtime)
|
|
if err != nil {
|
|
t.Fatalf("select encounter branch: %v", err)
|
|
}
|
|
if selNotify == nil || len(selNotify.GCPNIHHBGGD) == 0 {
|
|
t.Fatal("expected selection notify")
|
|
}
|
|
branchAdd, err := x.BranchDifficulty(run.DivisionId, encounterLayer.BPDABHGFBFO[1].CJADMFDOBAI)
|
|
if err != nil {
|
|
t.Fatalf("branch difficulty: %v", err)
|
|
}
|
|
baseStage, _ := c.CapturedStage(run.DivisionId)
|
|
expectedHardLevel := baseStage.EnemyHardLevel + branchAdd
|
|
if stage.ANJBLBEOJND.PIJBPDPEODG != expectedHardLevel {
|
|
t.Fatalf("difficulty got %d, want %d", stage.ANJBLBEOJND.PIJBPDPEODG, expectedHardLevel)
|
|
}
|
|
if run.FMIGOKIDKJL.GetLGNPHHBGKFH() == nil {
|
|
t.Fatal("expected pending ReturnPreparation after branch selection")
|
|
}
|
|
if err := s.saveCurrencyWarsDataWithRuntime(data, c, runtime); err != nil {
|
|
t.Fatalf("save after encounter select: %v", err)
|
|
}
|
|
|
|
// 4. ReturnPreparation clears pending action
|
|
if _, err := cwReturnPreparation(run); err != nil {
|
|
t.Fatalf("return preparation: %v", err)
|
|
}
|
|
if run.FMIGOKIDKJL != nil {
|
|
t.Fatal("expected pending cleared after ReturnPreparation")
|
|
}
|
|
if err := s.saveCurrencyWarsDataWithRuntime(data, c, runtime); err != nil {
|
|
t.Fatalf("save after ReturnPreparation: %v", err)
|
|
}
|
|
|
|
// 5. Build Battle with buildCurrencyWarsBattle
|
|
battleInfo, err := buildCurrencyWarsBattle(s, c, run)
|
|
if err != nil {
|
|
t.Fatalf("buildCurrencyWarsBattle: %v", err)
|
|
}
|
|
if battleInfo == nil || battleInfo.EIGMKOJOEEI == nil {
|
|
t.Fatal("battle info or grid missing")
|
|
}
|
|
if battleInfo.EIGMKOJOEEI.LODNFLMBIEH != expectedHardLevel {
|
|
t.Fatalf("battle grid hard level = %d, want %d", battleInfo.EIGMKOJOEEI.LODNFLMBIEH, expectedHardLevel)
|
|
}
|
|
if len(battleInfo.BattleAvatarList) == 0 {
|
|
t.Fatal("battle avatar list empty")
|
|
}
|
|
|
|
// 6. Settlement with finishCurrencyWarsBattle
|
|
CURRENT_BATTLE.Store(s.Token, battleInfo)
|
|
settleReq := &pb.PVEBattleResultCsReq{
|
|
BattleId: battleInfo.BattleId,
|
|
StageId: battleInfo.StageId,
|
|
EndStatus: pb.BattleEndStatus_BATTLE_END_WIN,
|
|
Stt: &pb.BattleStatistics{
|
|
APAGMJNECCN: &pb.MGMJOPHJCNL{
|
|
HFLPDCJDIAC: cwPercentScale,
|
|
DOGMMGLBJIJ: []*pb.CPNCAPLOIHI{
|
|
{RoleId: sampleVariant.Config.ID, Damage: 50000},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
goldBefore := player.Gold
|
|
if err := finishCurrencyWarsBattle(s, settleReq, battleInfo); err != nil {
|
|
t.Fatalf("finishCurrencyWarsBattle: %v", err)
|
|
}
|
|
|
|
// 7. Verify state after settlement & next node transition
|
|
data, _, err = readCurrencyWarsData(c)
|
|
if err != nil {
|
|
t.Fatalf("load reloaded data: %v", err)
|
|
}
|
|
run = data.DHFOFLFCLAH
|
|
stage, _ = cwStage(run)
|
|
player, _, _ = cwComponents(run)
|
|
|
|
if stage.DCAHJELNJNP != 2 || stage.SectionId != 4 {
|
|
t.Fatalf("expected advance to Ch2 Sec4, got Ch%d Sec%d", stage.DCAHJELNJNP, stage.SectionId)
|
|
}
|
|
if stage.ANJBLBEOJND.PIJBPDPEODG != baseStage.EnemyHardLevel {
|
|
t.Fatalf("expected hard level reset to base %d, got %d", baseStage.EnemyHardLevel, stage.ANJBLBEOJND.PIJBPDPEODG)
|
|
}
|
|
if stage.ANJBLBEOJND.PIFNOKAMBLL[cwDifficultySourceBranch] != 0 {
|
|
t.Fatalf("expected branch diff add 0, got %d", stage.ANJBLBEOJND.PIFNOKAMBLL[cwDifficultySourceBranch])
|
|
}
|
|
if player.Gold <= goldBefore {
|
|
t.Fatalf("gold should have increased from %d, got %d", goldBefore, player.Gold)
|
|
}
|
|
if player.GridFightCurLevelExp == 0 && player.EHNJDIDABHD <= 1 {
|
|
t.Fatal("player exp should have increased from settlement")
|
|
}
|
|
|
|
// 8. Full CAS roundtrip verification from persistent storage
|
|
reloadedData, _, err := readCurrencyWarsData(c)
|
|
if err != nil {
|
|
t.Fatalf("load reloaded data: %v", err)
|
|
}
|
|
reloadedStage, _ := cwStage(reloadedData.DHFOFLFCLAH)
|
|
if reloadedStage.DCAHJELNJNP != 2 || reloadedStage.SectionId != 4 {
|
|
t.Fatalf("reloaded stage = Ch%d Sec%d, want Ch2 Sec4", reloadedStage.DCAHJELNJNP, reloadedStage.SectionId)
|
|
}
|
|
if reloadedStage.ANJBLBEOJND.PIJBPDPEODG != baseStage.EnemyHardLevel {
|
|
t.Fatalf("reloaded hard level = %d, want %d", reloadedStage.ANJBLBEOJND.PIJBPDPEODG, baseStage.EnemyHardLevel)
|
|
}
|
|
if reloadedStage.ANJBLBEOJND.PIFNOKAMBLL[cwDifficultySourceBranch] != 0 {
|
|
t.Fatalf("reloaded branch diff = %d, want 0", reloadedStage.ANJBLBEOJND.PIFNOKAMBLL[cwDifficultySourceBranch])
|
|
}
|
|
if s.currencyWarsRevision < 5 {
|
|
t.Fatalf("expected monotonic CAS revisions >= 5, got %d", s.currencyWarsRevision)
|
|
}
|
|
}
|