Last active
March 19, 2019 02:39
-
-
Save lucasdicioccio/256f854a17320b13856b to your computer and use it in GitHub Desktop.
What an immutable GildedRose would look like
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- An alternative GildedRose using an immutable approach. | |
-- Context on the GildedRose: | |
-- * http://blog.lunarlogic.io/2015/what-ive-learned-by-doing-the-gilded-rose-kata-4-refactoring-tips/ | |
-- * my comment in the linked blog post | |
-- One could take this GildedTulip approach and encapsulate a similar "immutable API" | |
-- to re-create the "mutable API" of the GildedRose. | |
-- | |
-- This example is written in Haskell. This example uses three notable features (available in other languages): | |
-- - pattern matching: a way to hide a lot of "if" | |
-- - partial application: a (huge) syntax improvement over lambdas which are available in most languages | |
-- - list comprehension: like in Python | |
module GildedTulip where | |
----------------------------------------------------------------------------------- | |
-- data types to scope the problem | |
-- | |
-- The key idea of this whole program is that some features of an Item | |
-- can vary with time. | |
-- We capture this key idea with the TimeVarying type and illustrate the idea with two Item properties. | |
-- | |
-- We avoid two design flaws that our end-users probably do not care about: | |
-- * representing the time varying values using mutation | |
-- * representing time a hidden property of the program execution (i.e., how many times we called the "clock tick") | |
-- Instead, we represent time explicitly and recognize that some properties of an Item vary with time. | |
-- I claim that such a design is closer to the feature end-users need: query what is the current quality of an Item. | |
-- The proposed design also allows to query in the future and in the past (modulo causality). | |
-- I believe that it is nice to get a feature for free and I can charge for it anyway. | |
-- Simple type aliasing to make reasoning with type signatures less ambiguous. | |
type Day = Int | |
type Quality = Int | |
type Name = String | |
type Sellable = Bool | |
-- TimeVarying value can be represented by a "computed value at a given date". | |
type TimeVarying a = Day -> a | |
-- An Item has a name, and two time-varying properties: | |
-- - whether we are allowed to sell the item | |
-- - the quality of the item | |
data Item = Item { | |
name :: Name | |
, sellable :: (TimeVarying Sellable) | |
, quality :: (TimeVarying Quality) | |
} | |
----------------------------------------------------------------------------------- | |
-- We need to construct items and the pain-point is expressing TimeVarying values. | |
-- We ease the pain with some DSL-like functions that implement or transform | |
-- TimeVarying behaviors in a readable way. | |
-- Most items have a "best-before date" after which they are not sellable. | |
bestBefore :: Day -> TimeVarying Sellable | |
bestBefore deadline = \now -> now <= deadline | |
-- Some items may have a "not-sellable before date" (e.g., you wait for a | |
-- license to sell fermented coconut water). | |
maturity :: Day -> TimeVarying Sellable | |
maturity deadline = \now -> now >= deadline | |
-- A few items are timeless and will always be sellabled assets. | |
timeless :: TimeVarying Sellable | |
timeless = const True | |
-- Most items' quality have bounds (between 0 and 50). | |
-- We thus provide a function to cap a TimeVarying Quality. | |
-- | |
-- The code uses a lambda to show explicitly that we are "returning a | |
-- TimeVarying Quality object" but we could also pass the argument of the lambda as | |
-- an extra argument of the capToBounds function and use partial application. | |
-- See the commented implementation. Both implementations are equivalent. | |
-- In later code, we will use the same syntax as in the commented implementation here. | |
capToBounds :: TimeVarying Quality -> TimeVarying Quality | |
-- capToBounds f x = let r = f x in max 0 (min r 50) | |
capToBounds f = \x -> let r = f x in max 0 (min r 50) | |
-- A few items are unbreakable and hence have a fixed quality. | |
unbreakable :: Quality -> TimeVarying Quality | |
unbreakable x = const x | |
-- We need a few different rules to compute the item quality of objects. | |
-- We provide four broad classes of objects: | |
-- * Basic items: degrade of 1 Quality per day until their deadline where they degrade of 2 Quality per day. | |
-- * Conjured items: degrade twice as fast as basic items. | |
-- * Brie-cheese: increase of 1 Quality per day until their deadline, then | |
-- taste improves of 2 Quality per day. | |
-- * Passes: tickets are worthless after sell deadline. Otherwise the quality | |
-- increases as the concert approaches. See implementation for the exact | |
-- equations. | |
-- | |
-- Note that we use the trick of partial application that we illustrated in | |
-- `capToBounds` to improve readability. The capToBounds is better-understood | |
-- as an operation on a TimeVarying Quality value, here we un-alias the TimeVarying | |
-- to implement rules as quality in function of base quality, deadline, and current time. | |
-- an equivalent type for the 4 functions below is Quality -> Day -> Day -> Quality . | |
-- Pattern matching with guards make a good replacement of if/else. | |
basicItemQuality,conjuredItemQuality,brieQuality,passQuality :: | |
Quality -> Day -> TimeVarying Quality | |
basicItemQuality base deadline now | |
| deadline > now = base - now | |
| otherwise = (base - deadline) - 2 * (now - deadline) | |
conjuredItemQuality base deadline now | |
| deadline > now = base - 2*now | |
| otherwise = (base - deadline) - 4 * (now - deadline) | |
brieQuality base deadline now | |
| deadline > now = base + now | |
| otherwise = (base + deadline) + 2 * (now - deadline) | |
passQuality base deadline now | |
| deadline < now = 0 | |
| deadline - now <= 5 = base + 3 | |
| deadline - now <= 10 = base + 2 | |
| otherwise = base | |
----------------------------------------------------------------------------------- | |
-- We now are equipped with the basic building blocks to build items. | |
sulfuras = Item "Sulfuras" timeless (unbreakable 60) | |
brie = | |
let deadline = 10 | |
startQuality = 0 | |
in Item "Brie" (bestBefore deadline) (capToBounds $ brieQuality startQuality deadline) | |
pass = | |
let deadline = 30 | |
startQuality = 20 | |
in Item "Pass" (bestBefore deadline) (capToBounds $ passQuality startQuality deadline) | |
armor = | |
let deadline = 40 | |
startQuality = 30 | |
in Item "Armor" (bestBefore deadline) (capToBounds $ basicItemQuality startQuality deadline) | |
pie = | |
let deadline = 4 | |
startQuality = 10 | |
in Item "Conjured pie" (bestBefore deadline) (capToBounds $ conjuredItemQuality startQuality deadline) | |
-- A function to compute all we need to sell a given Item at a given Day. | |
type AllWeNeedToKnow = (Day, Name, Sellable, Quality) | |
getInfo :: Item -> Day -> AllWeNeedToKnow | |
getInfo i x = (x, name i, sellable i x, quality i x) | |
-- A function to generate a string representation of a list of things we need to know to sell items. | |
format :: [AllWeNeedToKnow] -> String | |
format xs = unlines (map formatOne xs) | |
where formatOne (day, name, sellable, quality) = | |
unwords [show day, show name, show sellable, show quality] | |
-- An example program | |
example :: IO () | |
example = | |
let inventory = [sulfuras, brie, brie, pass, armor, pie] | |
timeHorizon = [0 .. 100] | |
allWeNeedlist = [getInfo i t | i <- inventory, t <- timeHorizon] | |
in putStrLn $ format allWeNeedlist | |
{- Output of the example program: | |
0 "Sulfuras" True 60 | |
1 "Sulfuras" True 60 | |
2 "Sulfuras" True 60 | |
3 "Sulfuras" True 60 | |
4 "Sulfuras" True 60 | |
5 "Sulfuras" True 60 | |
6 "Sulfuras" True 60 | |
7 "Sulfuras" True 60 | |
8 "Sulfuras" True 60 | |
9 "Sulfuras" True 60 | |
10 "Sulfuras" True 60 | |
11 "Sulfuras" True 60 | |
12 "Sulfuras" True 60 | |
13 "Sulfuras" True 60 | |
14 "Sulfuras" True 60 | |
15 "Sulfuras" True 60 | |
16 "Sulfuras" True 60 | |
17 "Sulfuras" True 60 | |
18 "Sulfuras" True 60 | |
19 "Sulfuras" True 60 | |
20 "Sulfuras" True 60 | |
21 "Sulfuras" True 60 | |
22 "Sulfuras" True 60 | |
23 "Sulfuras" True 60 | |
24 "Sulfuras" True 60 | |
25 "Sulfuras" True 60 | |
26 "Sulfuras" True 60 | |
27 "Sulfuras" True 60 | |
28 "Sulfuras" True 60 | |
29 "Sulfuras" True 60 | |
30 "Sulfuras" True 60 | |
31 "Sulfuras" True 60 | |
32 "Sulfuras" True 60 | |
33 "Sulfuras" True 60 | |
34 "Sulfuras" True 60 | |
35 "Sulfuras" True 60 | |
36 "Sulfuras" True 60 | |
37 "Sulfuras" True 60 | |
38 "Sulfuras" True 60 | |
39 "Sulfuras" True 60 | |
40 "Sulfuras" True 60 | |
41 "Sulfuras" True 60 | |
42 "Sulfuras" True 60 | |
43 "Sulfuras" True 60 | |
44 "Sulfuras" True 60 | |
45 "Sulfuras" True 60 | |
46 "Sulfuras" True 60 | |
47 "Sulfuras" True 60 | |
48 "Sulfuras" True 60 | |
49 "Sulfuras" True 60 | |
50 "Sulfuras" True 60 | |
51 "Sulfuras" True 60 | |
52 "Sulfuras" True 60 | |
53 "Sulfuras" True 60 | |
54 "Sulfuras" True 60 | |
55 "Sulfuras" True 60 | |
56 "Sulfuras" True 60 | |
57 "Sulfuras" True 60 | |
58 "Sulfuras" True 60 | |
59 "Sulfuras" True 60 | |
60 "Sulfuras" True 60 | |
61 "Sulfuras" True 60 | |
62 "Sulfuras" True 60 | |
63 "Sulfuras" True 60 | |
64 "Sulfuras" True 60 | |
65 "Sulfuras" True 60 | |
66 "Sulfuras" True 60 | |
67 "Sulfuras" True 60 | |
68 "Sulfuras" True 60 | |
69 "Sulfuras" True 60 | |
70 "Sulfuras" True 60 | |
71 "Sulfuras" True 60 | |
72 "Sulfuras" True 60 | |
73 "Sulfuras" True 60 | |
74 "Sulfuras" True 60 | |
75 "Sulfuras" True 60 | |
76 "Sulfuras" True 60 | |
77 "Sulfuras" True 60 | |
78 "Sulfuras" True 60 | |
79 "Sulfuras" True 60 | |
80 "Sulfuras" True 60 | |
81 "Sulfuras" True 60 | |
82 "Sulfuras" True 60 | |
83 "Sulfuras" True 60 | |
84 "Sulfuras" True 60 | |
85 "Sulfuras" True 60 | |
86 "Sulfuras" True 60 | |
87 "Sulfuras" True 60 | |
88 "Sulfuras" True 60 | |
89 "Sulfuras" True 60 | |
90 "Sulfuras" True 60 | |
91 "Sulfuras" True 60 | |
92 "Sulfuras" True 60 | |
93 "Sulfuras" True 60 | |
94 "Sulfuras" True 60 | |
95 "Sulfuras" True 60 | |
96 "Sulfuras" True 60 | |
97 "Sulfuras" True 60 | |
98 "Sulfuras" True 60 | |
99 "Sulfuras" True 60 | |
100 "Sulfuras" True 60 | |
0 "Brie" True 0 | |
1 "Brie" True 1 | |
2 "Brie" True 2 | |
3 "Brie" True 3 | |
4 "Brie" True 4 | |
5 "Brie" True 5 | |
6 "Brie" True 6 | |
7 "Brie" True 7 | |
8 "Brie" True 8 | |
9 "Brie" True 9 | |
10 "Brie" True 10 | |
11 "Brie" False 12 | |
12 "Brie" False 14 | |
13 "Brie" False 16 | |
14 "Brie" False 18 | |
15 "Brie" False 20 | |
16 "Brie" False 22 | |
17 "Brie" False 24 | |
18 "Brie" False 26 | |
19 "Brie" False 28 | |
20 "Brie" False 30 | |
21 "Brie" False 32 | |
22 "Brie" False 34 | |
23 "Brie" False 36 | |
24 "Brie" False 38 | |
25 "Brie" False 40 | |
26 "Brie" False 42 | |
27 "Brie" False 44 | |
28 "Brie" False 46 | |
29 "Brie" False 48 | |
30 "Brie" False 50 | |
31 "Brie" False 50 | |
32 "Brie" False 50 | |
33 "Brie" False 50 | |
34 "Brie" False 50 | |
35 "Brie" False 50 | |
36 "Brie" False 50 | |
37 "Brie" False 50 | |
38 "Brie" False 50 | |
39 "Brie" False 50 | |
40 "Brie" False 50 | |
41 "Brie" False 50 | |
42 "Brie" False 50 | |
43 "Brie" False 50 | |
44 "Brie" False 50 | |
45 "Brie" False 50 | |
46 "Brie" False 50 | |
47 "Brie" False 50 | |
48 "Brie" False 50 | |
49 "Brie" False 50 | |
50 "Brie" False 50 | |
51 "Brie" False 50 | |
52 "Brie" False 50 | |
53 "Brie" False 50 | |
54 "Brie" False 50 | |
55 "Brie" False 50 | |
56 "Brie" False 50 | |
57 "Brie" False 50 | |
58 "Brie" False 50 | |
59 "Brie" False 50 | |
60 "Brie" False 50 | |
61 "Brie" False 50 | |
62 "Brie" False 50 | |
63 "Brie" False 50 | |
64 "Brie" False 50 | |
65 "Brie" False 50 | |
66 "Brie" False 50 | |
67 "Brie" False 50 | |
68 "Brie" False 50 | |
69 "Brie" False 50 | |
70 "Brie" False 50 | |
71 "Brie" False 50 | |
72 "Brie" False 50 | |
73 "Brie" False 50 | |
74 "Brie" False 50 | |
75 "Brie" False 50 | |
76 "Brie" False 50 | |
77 "Brie" False 50 | |
78 "Brie" False 50 | |
79 "Brie" False 50 | |
80 "Brie" False 50 | |
81 "Brie" False 50 | |
82 "Brie" False 50 | |
83 "Brie" False 50 | |
84 "Brie" False 50 | |
85 "Brie" False 50 | |
86 "Brie" False 50 | |
87 "Brie" False 50 | |
88 "Brie" False 50 | |
89 "Brie" False 50 | |
90 "Brie" False 50 | |
91 "Brie" False 50 | |
92 "Brie" False 50 | |
93 "Brie" False 50 | |
94 "Brie" False 50 | |
95 "Brie" False 50 | |
96 "Brie" False 50 | |
97 "Brie" False 50 | |
98 "Brie" False 50 | |
99 "Brie" False 50 | |
100 "Brie" False 50 | |
0 "Brie" True 0 | |
1 "Brie" True 1 | |
2 "Brie" True 2 | |
3 "Brie" True 3 | |
4 "Brie" True 4 | |
5 "Brie" True 5 | |
6 "Brie" True 6 | |
7 "Brie" True 7 | |
8 "Brie" True 8 | |
9 "Brie" True 9 | |
10 "Brie" True 10 | |
11 "Brie" False 12 | |
12 "Brie" False 14 | |
13 "Brie" False 16 | |
14 "Brie" False 18 | |
15 "Brie" False 20 | |
16 "Brie" False 22 | |
17 "Brie" False 24 | |
18 "Brie" False 26 | |
19 "Brie" False 28 | |
20 "Brie" False 30 | |
21 "Brie" False 32 | |
22 "Brie" False 34 | |
23 "Brie" False 36 | |
24 "Brie" False 38 | |
25 "Brie" False 40 | |
26 "Brie" False 42 | |
27 "Brie" False 44 | |
28 "Brie" False 46 | |
29 "Brie" False 48 | |
30 "Brie" False 50 | |
31 "Brie" False 50 | |
32 "Brie" False 50 | |
33 "Brie" False 50 | |
34 "Brie" False 50 | |
35 "Brie" False 50 | |
36 "Brie" False 50 | |
37 "Brie" False 50 | |
38 "Brie" False 50 | |
39 "Brie" False 50 | |
40 "Brie" False 50 | |
41 "Brie" False 50 | |
42 "Brie" False 50 | |
43 "Brie" False 50 | |
44 "Brie" False 50 | |
45 "Brie" False 50 | |
46 "Brie" False 50 | |
47 "Brie" False 50 | |
48 "Brie" False 50 | |
49 "Brie" False 50 | |
50 "Brie" False 50 | |
51 "Brie" False 50 | |
52 "Brie" False 50 | |
53 "Brie" False 50 | |
54 "Brie" False 50 | |
55 "Brie" False 50 | |
56 "Brie" False 50 | |
57 "Brie" False 50 | |
58 "Brie" False 50 | |
59 "Brie" False 50 | |
60 "Brie" False 50 | |
61 "Brie" False 50 | |
62 "Brie" False 50 | |
63 "Brie" False 50 | |
64 "Brie" False 50 | |
65 "Brie" False 50 | |
66 "Brie" False 50 | |
67 "Brie" False 50 | |
68 "Brie" False 50 | |
69 "Brie" False 50 | |
70 "Brie" False 50 | |
71 "Brie" False 50 | |
72 "Brie" False 50 | |
73 "Brie" False 50 | |
74 "Brie" False 50 | |
75 "Brie" False 50 | |
76 "Brie" False 50 | |
77 "Brie" False 50 | |
78 "Brie" False 50 | |
79 "Brie" False 50 | |
80 "Brie" False 50 | |
81 "Brie" False 50 | |
82 "Brie" False 50 | |
83 "Brie" False 50 | |
84 "Brie" False 50 | |
85 "Brie" False 50 | |
86 "Brie" False 50 | |
87 "Brie" False 50 | |
88 "Brie" False 50 | |
89 "Brie" False 50 | |
90 "Brie" False 50 | |
91 "Brie" False 50 | |
92 "Brie" False 50 | |
93 "Brie" False 50 | |
94 "Brie" False 50 | |
95 "Brie" False 50 | |
96 "Brie" False 50 | |
97 "Brie" False 50 | |
98 "Brie" False 50 | |
99 "Brie" False 50 | |
100 "Brie" False 50 | |
0 "Pass" True 20 | |
1 "Pass" True 20 | |
2 "Pass" True 20 | |
3 "Pass" True 20 | |
4 "Pass" True 20 | |
5 "Pass" True 20 | |
6 "Pass" True 20 | |
7 "Pass" True 20 | |
8 "Pass" True 20 | |
9 "Pass" True 20 | |
10 "Pass" True 20 | |
11 "Pass" True 20 | |
12 "Pass" True 20 | |
13 "Pass" True 20 | |
14 "Pass" True 20 | |
15 "Pass" True 20 | |
16 "Pass" True 20 | |
17 "Pass" True 20 | |
18 "Pass" True 20 | |
19 "Pass" True 20 | |
20 "Pass" True 22 | |
21 "Pass" True 22 | |
22 "Pass" True 22 | |
23 "Pass" True 22 | |
24 "Pass" True 22 | |
25 "Pass" True 23 | |
26 "Pass" True 23 | |
27 "Pass" True 23 | |
28 "Pass" True 23 | |
29 "Pass" True 23 | |
30 "Pass" True 23 | |
31 "Pass" False 0 | |
32 "Pass" False 0 | |
33 "Pass" False 0 | |
34 "Pass" False 0 | |
35 "Pass" False 0 | |
36 "Pass" False 0 | |
37 "Pass" False 0 | |
38 "Pass" False 0 | |
39 "Pass" False 0 | |
40 "Pass" False 0 | |
41 "Pass" False 0 | |
42 "Pass" False 0 | |
43 "Pass" False 0 | |
44 "Pass" False 0 | |
45 "Pass" False 0 | |
46 "Pass" False 0 | |
47 "Pass" False 0 | |
48 "Pass" False 0 | |
49 "Pass" False 0 | |
50 "Pass" False 0 | |
51 "Pass" False 0 | |
52 "Pass" False 0 | |
53 "Pass" False 0 | |
54 "Pass" False 0 | |
55 "Pass" False 0 | |
56 "Pass" False 0 | |
57 "Pass" False 0 | |
58 "Pass" False 0 | |
59 "Pass" False 0 | |
60 "Pass" False 0 | |
61 "Pass" False 0 | |
62 "Pass" False 0 | |
63 "Pass" False 0 | |
64 "Pass" False 0 | |
65 "Pass" False 0 | |
66 "Pass" False 0 | |
67 "Pass" False 0 | |
68 "Pass" False 0 | |
69 "Pass" False 0 | |
70 "Pass" False 0 | |
71 "Pass" False 0 | |
72 "Pass" False 0 | |
73 "Pass" False 0 | |
74 "Pass" False 0 | |
75 "Pass" False 0 | |
76 "Pass" False 0 | |
77 "Pass" False 0 | |
78 "Pass" False 0 | |
79 "Pass" False 0 | |
80 "Pass" False 0 | |
81 "Pass" False 0 | |
82 "Pass" False 0 | |
83 "Pass" False 0 | |
84 "Pass" False 0 | |
85 "Pass" False 0 | |
86 "Pass" False 0 | |
87 "Pass" False 0 | |
88 "Pass" False 0 | |
89 "Pass" False 0 | |
90 "Pass" False 0 | |
91 "Pass" False 0 | |
92 "Pass" False 0 | |
93 "Pass" False 0 | |
94 "Pass" False 0 | |
95 "Pass" False 0 | |
96 "Pass" False 0 | |
97 "Pass" False 0 | |
98 "Pass" False 0 | |
99 "Pass" False 0 | |
100 "Pass" False 0 | |
0 "Armor" True 30 | |
1 "Armor" True 29 | |
2 "Armor" True 28 | |
3 "Armor" True 27 | |
4 "Armor" True 26 | |
5 "Armor" True 25 | |
6 "Armor" True 24 | |
7 "Armor" True 23 | |
8 "Armor" True 22 | |
9 "Armor" True 21 | |
10 "Armor" True 20 | |
11 "Armor" True 19 | |
12 "Armor" True 18 | |
13 "Armor" True 17 | |
14 "Armor" True 16 | |
15 "Armor" True 15 | |
16 "Armor" True 14 | |
17 "Armor" True 13 | |
18 "Armor" True 12 | |
19 "Armor" True 11 | |
20 "Armor" True 10 | |
21 "Armor" True 9 | |
22 "Armor" True 8 | |
23 "Armor" True 7 | |
24 "Armor" True 6 | |
25 "Armor" True 5 | |
26 "Armor" True 4 | |
27 "Armor" True 3 | |
28 "Armor" True 2 | |
29 "Armor" True 1 | |
30 "Armor" True 0 | |
31 "Armor" True 0 | |
32 "Armor" True 0 | |
33 "Armor" True 0 | |
34 "Armor" True 0 | |
35 "Armor" True 0 | |
36 "Armor" True 0 | |
37 "Armor" True 0 | |
38 "Armor" True 0 | |
39 "Armor" True 0 | |
40 "Armor" True 0 | |
41 "Armor" False 0 | |
42 "Armor" False 0 | |
43 "Armor" False 0 | |
44 "Armor" False 0 | |
45 "Armor" False 0 | |
46 "Armor" False 0 | |
47 "Armor" False 0 | |
48 "Armor" False 0 | |
49 "Armor" False 0 | |
50 "Armor" False 0 | |
51 "Armor" False 0 | |
52 "Armor" False 0 | |
53 "Armor" False 0 | |
54 "Armor" False 0 | |
55 "Armor" False 0 | |
56 "Armor" False 0 | |
57 "Armor" False 0 | |
58 "Armor" False 0 | |
59 "Armor" False 0 | |
60 "Armor" False 0 | |
61 "Armor" False 0 | |
62 "Armor" False 0 | |
63 "Armor" False 0 | |
64 "Armor" False 0 | |
65 "Armor" False 0 | |
66 "Armor" False 0 | |
67 "Armor" False 0 | |
68 "Armor" False 0 | |
69 "Armor" False 0 | |
70 "Armor" False 0 | |
71 "Armor" False 0 | |
72 "Armor" False 0 | |
73 "Armor" False 0 | |
74 "Armor" False 0 | |
75 "Armor" False 0 | |
76 "Armor" False 0 | |
77 "Armor" False 0 | |
78 "Armor" False 0 | |
79 "Armor" False 0 | |
80 "Armor" False 0 | |
81 "Armor" False 0 | |
82 "Armor" False 0 | |
83 "Armor" False 0 | |
84 "Armor" False 0 | |
85 "Armor" False 0 | |
86 "Armor" False 0 | |
87 "Armor" False 0 | |
88 "Armor" False 0 | |
89 "Armor" False 0 | |
90 "Armor" False 0 | |
91 "Armor" False 0 | |
92 "Armor" False 0 | |
93 "Armor" False 0 | |
94 "Armor" False 0 | |
95 "Armor" False 0 | |
96 "Armor" False 0 | |
97 "Armor" False 0 | |
98 "Armor" False 0 | |
99 "Armor" False 0 | |
100 "Armor" False 0 | |
0 "Conjured pie" True 10 | |
1 "Conjured pie" True 8 | |
2 "Conjured pie" True 6 | |
3 "Conjured pie" True 4 | |
4 "Conjured pie" True 6 | |
5 "Conjured pie" False 2 | |
6 "Conjured pie" False 0 | |
7 "Conjured pie" False 0 | |
8 "Conjured pie" False 0 | |
9 "Conjured pie" False 0 | |
10 "Conjured pie" False 0 | |
11 "Conjured pie" False 0 | |
12 "Conjured pie" False 0 | |
13 "Conjured pie" False 0 | |
14 "Conjured pie" False 0 | |
15 "Conjured pie" False 0 | |
16 "Conjured pie" False 0 | |
17 "Conjured pie" False 0 | |
18 "Conjured pie" False 0 | |
19 "Conjured pie" False 0 | |
20 "Conjured pie" False 0 | |
21 "Conjured pie" False 0 | |
22 "Conjured pie" False 0 | |
23 "Conjured pie" False 0 | |
24 "Conjured pie" False 0 | |
25 "Conjured pie" False 0 | |
26 "Conjured pie" False 0 | |
27 "Conjured pie" False 0 | |
28 "Conjured pie" False 0 | |
29 "Conjured pie" False 0 | |
30 "Conjured pie" False 0 | |
31 "Conjured pie" False 0 | |
32 "Conjured pie" False 0 | |
33 "Conjured pie" False 0 | |
34 "Conjured pie" False 0 | |
35 "Conjured pie" False 0 | |
36 "Conjured pie" False 0 | |
37 "Conjured pie" False 0 | |
38 "Conjured pie" False 0 | |
39 "Conjured pie" False 0 | |
40 "Conjured pie" False 0 | |
41 "Conjured pie" False 0 | |
42 "Conjured pie" False 0 | |
43 "Conjured pie" False 0 | |
44 "Conjured pie" False 0 | |
45 "Conjured pie" False 0 | |
46 "Conjured pie" False 0 | |
47 "Conjured pie" False 0 | |
48 "Conjured pie" False 0 | |
49 "Conjured pie" False 0 | |
50 "Conjured pie" False 0 | |
51 "Conjured pie" False 0 | |
52 "Conjured pie" False 0 | |
53 "Conjured pie" False 0 | |
54 "Conjured pie" False 0 | |
55 "Conjured pie" False 0 | |
56 "Conjured pie" False 0 | |
57 "Conjured pie" False 0 | |
58 "Conjured pie" False 0 | |
59 "Conjured pie" False 0 | |
60 "Conjured pie" False 0 | |
61 "Conjured pie" False 0 | |
62 "Conjured pie" False 0 | |
63 "Conjured pie" False 0 | |
64 "Conjured pie" False 0 | |
65 "Conjured pie" False 0 | |
66 "Conjured pie" False 0 | |
67 "Conjured pie" False 0 | |
68 "Conjured pie" False 0 | |
69 "Conjured pie" False 0 | |
70 "Conjured pie" False 0 | |
71 "Conjured pie" False 0 | |
72 "Conjured pie" False 0 | |
73 "Conjured pie" False 0 | |
74 "Conjured pie" False 0 | |
75 "Conjured pie" False 0 | |
76 "Conjured pie" False 0 | |
77 "Conjured pie" False 0 | |
78 "Conjured pie" False 0 | |
79 "Conjured pie" False 0 | |
80 "Conjured pie" False 0 | |
81 "Conjured pie" False 0 | |
82 "Conjured pie" False 0 | |
83 "Conjured pie" False 0 | |
84 "Conjured pie" False 0 | |
85 "Conjured pie" False 0 | |
86 "Conjured pie" False 0 | |
87 "Conjured pie" False 0 | |
88 "Conjured pie" False 0 | |
89 "Conjured pie" False 0 | |
90 "Conjured pie" False 0 | |
91 "Conjured pie" False 0 | |
92 "Conjured pie" False 0 | |
93 "Conjured pie" False 0 | |
94 "Conjured pie" False 0 | |
95 "Conjured pie" False 0 | |
96 "Conjured pie" False 0 | |
97 "Conjured pie" False 0 | |
98 "Conjured pie" False 0 | |
99 "Conjured pie" False 0 | |
100 "Conjured pie" False 0 | |
-} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment