1local silent = true -- change to false to look at the result of stress tests
2local mut_iterations = 500 -- mutate each try this many times
3local tries = 40
4
5local chance_temporary = 10 -- in 100.
6local chance_clear = 2 -- in 100. Chance to clear some temporary mutations. Note that some mutations clear others anyways.
7
8local eol = string.char(13)
9
10local function print_mutstate(prefix)
11    if not silent then
12        crawl.stderr(prefix ..
13                you.how_mutated(true, true, true) .. " mutations. result: " ..
14                you.mutation_overview() .. eol)
15    end
16end
17
18-- could still add more things in here.
19-- see mut_species.lua for testing of innate mutations & their interactions
20local function test_basic_mutation_stuff()
21    you.delete_all_mutations("mutation test")
22    ------------------
23    -- test some mutation interactions (see mutation.cc:conflict)
24    -- test trading off (type 1)
25    you.mutate("robust", "basic mutation test", false)
26    you.mutate("frail", "basic mutation test", false)
27    assert(you.get_base_mutation_level("robust", true, true, true) == 0)
28    for i=1, 10 do
29        you.mutate("robust", "basic mutation test", false)
30    end
31    assert(you.get_base_mutation_level("robust", true, true, true) == 3)
32    you.mutate("frail", "basic mutation test", true) -- should now have robust 3, temp frail 1
33    assert(you.get_base_mutation_level("robust", true, true, true) == 3)
34    assert(you.get_base_mutation_level("frail", true, true, true) == 1)
35    -- quick test of the lua binding while we're here since default args with booleans are a bit tricky
36    assert(you.get_base_mutation_level("frail") == you.get_base_mutation_level("frail", true, true, true))
37    assert(you.get_base_mutation_level("frail") == you.get_base_mutation_level("frail", false, true, false))
38    assert(you.get_base_mutation_level("frail", false, true) == you.get_base_mutation_level("frail", false, true))
39
40    -- test forced clearing for mutations that can't coexist (type -1)
41    assert(you.mutate("fire resistance", "basic mutation test", false))
42    assert(you.mutate("fire resistance", "basic mutation test", false))
43    assert(not you.mutate("heat vulnerability", "basic mutation test", false, false)) -- non-forced mutation should fail
44    assert(you.get_base_mutation_level("fire resistance") == 2)
45    assert(you.get_base_mutation_level("heat vulnerability") == 0)
46    assert(you.mutate("heat vulnerability", "basic mutation test", false, true)) -- forced mutation should fully clear fire resistance
47    assert(you.get_base_mutation_level("fire resistance") == 0)
48    assert(you.get_base_mutation_level("heat vulnerability") == 1)
49
50    -- test mutations that can simply coexist
51    assert(you.mutate("fire resistance", "basic mutation test", false))
52    assert(you.mutate("fire resistance", "basic mutation test", false))
53    assert(you.mutate("cold resistance", "basic mutation test", false, false))
54    assert(you.get_base_mutation_level("fire resistance") == 2)
55    assert(you.get_base_mutation_level("cold resistance") == 1)
56    assert(you.mutate("cold resistance", "basic mutation test", false, true))
57    assert(you.get_base_mutation_level("fire resistance") == 2)
58    assert(you.get_base_mutation_level("cold resistance") == 2)
59
60    ------------------
61    -- test some physiology conflicts interactions (see mutation.cc:physiology_mutation_conflict)
62    -- this isn't exhaustive
63    assert(not you.mutate("spit poison", "basic mutation test")) -- only for nagas
64    -- could add other species conditions here using you.change_species
65
66    assert(you.mutate("talons", "basic mutation test"))
67    assert(not you.mutate("hooves", "basic mutation test")) -- covered by physiology conflict
68
69    print_mutstate("basic results: ")
70    you.delete_all_mutations("mutation test")
71end
72
73
74local function give_random_mutation(chance_temporary)
75    local temp = crawl.x_chance_in_y(chance_temporary, 100)
76    you.mutate("any", "mutation test", temp)
77end
78
79local function try_all_mutation_categories()
80    you.mutate("any", "mutation test", false)
81    you.mutate("good", "mutation test", false)
82    you.mutate("bad", "mutation test", false)
83    you.mutate("xom", "mutation test", false)
84    you.mutate("slime", "mutation test", false)
85    you.mutate("corrupt", "mutation test", true)
86    you.mutate("qazlal", "mutation test", false)
87end
88
89-- TODO: better way to do this in lua so that it doesn't duplicate code
90local function simulate_mutation_pot()
91    remove = crawl.random_range(2, 3)
92    add = crawl.random_range(1, 3)
93    for i=1, remove do
94        you.delete_mutation("any", "mutation test")
95    end
96    for i=1, add do
97        you.mutate("any", "mutation test", false)
98    end
99    if crawl.coinflip() then
100        you.mutate("good", "mutation test", false)
101    end
102end
103
104-- simulate drinking `iterations` mutation potions in a row, a bunch of times
105-- (determined by `tries`) this is mostly useful when looking at the output,
106-- doesn't really do much that test_random_mutations doesn't
107local function test_potion(tries, iterations, premutate)
108    sum = 0
109    for i=1, tries do
110        you.delete_all_mutations("mutation test")
111        assert(you.how_mutated(true, true, true) == 0,
112                "Clearing mutations failed, currently: " .. you.mutation_overview())
113        for i=1, premutate do
114            -- note: won't guarantee `premutate` mutations, because some will
115            -- cancel each other out. This tops out at around 10 mutation
116            -- levels by this method.
117            give_random_mutation(0.0)
118        end
119        for j=1, iterations do
120            simulate_mutation_pot()
121        end
122        print_mutstate("Potion test try " .. i .. ", ")
123        sum = sum + you.how_mutated(true, true, true)
124    end
125    mean = sum / tries
126    if not silent then
127        crawl.stderr("Mean resulting mutations: " .. mean .. eol)
128    end
129end
130
131-- relies largely an asserts in the mutation code.
132local function test_random_mutations(tries, iterations, chance_temporary, chance_clear)
133    for i=1, tries do
134        you.delete_all_mutations("mutation test")
135        assert(you.how_mutated(true, true, true) == 0,
136                "Clearing mutations failed, currently: " .. you.mutation_overview())
137        for j=1, iterations do
138            if crawl.x_chance_in_y(chance_clear, 100) then
139                if crawl.coinflip() then
140                    you.delete_temp_mutations(true, "Mutation test")
141                    assert(you.temp_mutations() == 0,
142                        "Clearing temporary mutations failed, currently at " ..
143                        you.temp_mutations() .. ": " .. you.mutation_overview())
144                else
145                    you.delete_temp_mutations(false, "Mutation test")
146                end
147            end
148            give_random_mutation(chance_temporary)
149        end
150        print_mutstate("Random test try " .. i .. ", ")
151    end
152end
153
154test_basic_mutation_stuff()
155try_all_mutation_categories()
156test_potion(5, mut_iterations, 0)
157test_random_mutations(tries, mut_iterations, chance_temporary, chance_clear)
158you.delete_all_mutations("Mutation test")
159