11describe (" Foulborn generation" , function ()
2- it (" generates Foulborn items from foulbornMap " , function ()
2+ it (" generates correct number of Foulborn items " , function ()
33 local foulbornCount = 0
44 for _ , raw in ipairs (data .uniques .generated ) do
55 if raw :match (" ^Foulborn " ) then
66 foulbornCount = foulbornCount + 1
77 end
88 end
9- assert .is_true (foulbornCount > 200 , " Expected 200+ Foulborn items, got " .. foulbornCount )
9+ -- PR #9432 has 440 items total; Skin of the Lords is tree-dependent (separate function)
10+ -- so we expect ~439 non-tree-dependent items
11+ assert .is_true (foulbornCount >= 430 , " Expected 430+ Foulborn items, got " .. foulbornCount )
1012 print (" Foulborn items generated: " .. foulbornCount )
1113 end )
1214
13- it (" generates valid Foulborn Alpha's Howl" , function ()
15+ it (" generates correct number of Headhunter items (2^3-1=7)" , function ()
16+ local count = 0
17+ for _ , raw in ipairs (data .uniques .generated ) do
18+ if raw :match (" ^Foulborn Headhunter %d+\n " ) then
19+ count = count + 1
20+ end
21+ end
22+ assert .are .equals (7 , count , " Headhunter should have 7 Foulborn items (3 slots)" )
23+ end )
24+
25+ it (" generates correct number of Alpha's Howl items (2^2-1=3)" , function ()
26+ local count = 0
27+ for _ , raw in ipairs (data .uniques .generated ) do
28+ if raw :match (" ^Foulborn Alpha's Howl %d+\n " ) then
29+ count = count + 1
30+ end
31+ end
32+ assert .are .equals (3 , count , " Alpha's Howl should have 3 Foulborn items (2 slots)" )
33+ end )
34+
35+ it (" verifies mod replacement in Headhunter 1" , function ()
1436 local raw
1537 for _ , r in ipairs (data .uniques .generated ) do
16- if r :match (" ^Foulborn Alpha " ) then raw = r ; break end
38+ if r :match (" ^Foulborn Headhunter 1 \n " ) then raw = r ; break end
1739 end
18- assert .is_truthy (raw , " Foulborn Alpha's Howl not found" )
40+ assert .is_truthy (raw , " Foulborn Headhunter 1 not found" )
41+ -- Should have Culling Strike (mutated) as the added mod
42+ assert .truthy (raw :match (" Culling Strike %(mutated%)" ), " Missing added mod 'Culling Strike (mutated)'" )
43+ -- Should NOT have the removed mod
44+ assert .is_falsy (raw :match (" increased Damage with Hits against Rare monsters" ), " Removed mod should not be present" )
45+ -- Should still have other original mods
46+ assert .truthy (raw :match (" When you Kill a Rare monster" ), " Missing original mod that should be preserved" )
47+ assert .truthy (raw :match (" Leather Belt" ), " Missing base type" )
48+ end )
49+
50+ it (" verifies Headhunter 7 has all three mutations" , function ()
51+ local raw
52+ for _ , r in ipairs (data .uniques .generated ) do
53+ if r :match (" ^Foulborn Headhunter 7\n " ) then raw = r ; break end
54+ end
55+ assert .is_truthy (raw , " Foulborn Headhunter 7 not found" )
56+ assert .truthy (raw :match (" Culling Strike %(mutated%)" ), " Missing Culling Strike" )
57+ assert .truthy (raw :match (" Eat a Soul.-%(mutated%)" ), " Missing Eat a Soul" )
58+ assert .truthy (raw :match (" Minimap Icons.-%(mutated%)" ), " Missing Minimap Icons" )
59+ -- All three original mods should be removed
60+ assert .is_falsy (raw :match (" increased Damage with Hits against Rare monsters" ), " Removed mod still present" )
61+ assert .is_falsy (raw :match (" When you Kill a Rare monster, you gain its Modifiers" ), " Removed mod still present" )
62+ end )
63+
64+ it (" generates valid Foulborn Alpha's Howl 1" , function ()
65+ local raw
66+ for _ , r in ipairs (data .uniques .generated ) do
67+ if r :match (" ^Foulborn Alpha's Howl 1\n " ) then raw = r ; break end
68+ end
69+ assert .is_truthy (raw , " Foulborn Alpha's Howl 1 not found" )
1970 assert .truthy (raw :match (" Sinner Tricorne" ), " Missing base type" )
20- assert .truthy (raw :match (" Variant:" ), " Missing variant declarations" )
21- assert .truthy (raw :match (" {variant:1}" ), " Missing variant-tagged mod" )
2271 assert .truthy (raw :match (" Requires Level" ), " Missing requires line" )
72+ -- Should have added mod and NOT have removed mod
73+ assert .truthy (raw :match (" Life Reservation Efficiency.-%(mutated%)" ), " Missing added mutation mod" )
74+ assert .is_falsy (raw :match (" 16%% increased Mana Reservation Efficiency" ), " Removed mod should not be present" )
2375 end )
2476
2577 it (" parses Foulborn item with foulborn flag" , function ()
2678 newBuild ()
2779 local raw
2880 for _ , r in ipairs (data .uniques .generated ) do
29- if r :match (" ^Foulborn Alpha" ) then raw = r ; break end
81+ if r :match (" ^Foulborn Alpha's Howl 1 \n " ) then raw = r ; break end
3082 end
3183 local item = new (" Item" , raw )
3284 assert .is_true (item .foulborn , " foulborn flag not set" )
3385 assert .are .equals (" Sinner Tricorne" , item .baseName )
34- assert .are .equals (" Foulborn Alpha's Howl" , item .title )
35- assert .is_true (# item .variantList > 0 , " No variants parsed" )
36- print (" Variants: " .. # item .variantList )
86+ assert .are .equals (" Foulborn Alpha's Howl 1" , item .title )
3787 end )
3888
3989 it (" generates Foulborn item with existing variants correctly" , function ()
4090 local raw
4191 for _ , r in ipairs (data .uniques .generated ) do
42- if r :match (" ^Foulborn The Formless Flame" ) then raw = r ; break end
92+ if r :match (" ^Foulborn The Formless Flame %d+ \n " ) then raw = r ; break end
4393 end
4494 assert .is_truthy (raw , " Foulborn The Formless Flame not found" )
45- -- Should use Current variant base (Royal Burgonet, not Siege Helmet)
46- assert .truthy (raw :match (" Royal Burgonet" ), " Wrong base type - should be Royal Burgonet (Current variant)" )
95+ -- Should use current variant base (Royal Burgonet, not Siege Helmet)
96+ assert .truthy (raw :match (" Royal Burgonet" ), " Wrong base type - should be Royal Burgonet (current variant)" )
4797 assert .is_falsy (raw :match (" Siege Helmet" ), " Should not contain old variant base" )
4898 end )
4999
50100 it (" generates Foulborn item with implicits" , function ()
51101 local raw
52102 for _ , r in ipairs (data .uniques .generated ) do
53- if r :match (" ^Foulborn Call of the Brotherhood" ) then raw = r ; break end
103+ if r :match (" ^Foulborn Call of the Brotherhood %d+ \n " ) then raw = r ; break end
54104 end
55105 assert .is_truthy (raw , " Foulborn Call of the Brotherhood not found" )
56106 assert .truthy (raw :match (" Implicits: 1" ), " Missing implicits declaration" )
@@ -61,7 +111,7 @@ describe("Foulborn generation", function()
61111 newBuild ()
62112 local raw
63113 for _ , r in ipairs (data .uniques .generated ) do
64- if r :match (" ^Foulborn Call of the Brotherhood" ) then raw = r ; break end
114+ if r :match (" ^Foulborn Call of the Brotherhood %d+ \n " ) then raw = r ; break end
65115 end
66116 assert .is_truthy (raw , " Foulborn Call of the Brotherhood not found" )
67117 local item = new (" Item" , raw )
@@ -117,4 +167,18 @@ describe("Foulborn generation", function()
117167 assert .is_true (# item .variantList > 30 , " Not enough variants parsed" )
118168 print (" Parsed variants: " .. # item .variantList .. " , hasAltVariant: " .. tostring (item .hasAltVariant ))
119169 end )
170+
171+ it (" generates items with (mutated) tag on all added mods" , function ()
172+ local issues = {}
173+ for _ , raw in ipairs (data .uniques .generated ) do
174+ if raw :match (" ^Foulborn " ) and not raw :match (" ^Foulborn Skin of the Lords" ) then
175+ local hasMutated = raw :match (" %(mutated%)" )
176+ if not hasMutated then
177+ local name = raw :match (" ^(.-)\n " )
178+ table.insert (issues , name )
179+ end
180+ end
181+ end
182+ assert .are .equals (0 , # issues , " Items without (mutated) tag: " .. table.concat (issues , " , " ))
183+ end )
120184end )
0 commit comments