-
Notifications
You must be signed in to change notification settings - Fork 1
/
Goon.hs
156 lines (141 loc) · 7.94 KB
/
Goon.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
module Goon (selectFromRanges, selectMetaType) where
import Cyberware (Cyberware(..), BodyPart(..), CyberLimbEnhancement(..))
import Hacking (Program)
import Stats (Stats, createStatsShort, BP(..), MetaType(..), getStatsThatAreMaxed, addToStats, subBP)
import Weapons (Weapon, getWeapon)
import Skills (Skill(..), createSkill, SkillLevel(..))
import Spells (Spell, getSpell)
import Armor (getArmor)
import Equipment (Equipment(..), getEquipment, FocusType(..))
import Qualities (getQualityCost)
import System.Random (mkStdGen)
import Prelude hiding (init, foldl)
import Data.Maybe (fromJust, isNothing)
import Utility (selectFromRanges)
import Data.Hashable (hash)
import Qualities (Quality(..), qualityDb)
import qualified Data.Map as M
import qualified Data.List as L
import Control.Applicative
import Data.Ord (comparing)
data Goon = Goon {
name :: String,
rating :: Int,
stats :: Stats,
skills :: [Skill],
weapons :: [Weapon],
equipment :: [Equipment],
cyberware :: Maybe [Cyberware],
programs :: Maybe [Program],
spells :: Maybe [Spell],
metatype :: MetaType} deriving (Show)
data GoonType = Hacker | Magician | Berzerker | Gunman | Face | Pilot deriving (Show)
generateGoon :: GoonType -> BP -> String -> Goon
generateGoon goonType bp goonName = undefined
where
-- generate metatype
seed = fromIntegral $ hash goonName
metaType = selectMetaType goonType seed
-- generate qualities
(bp', qualities) = getMaxQualitiesByMetaType goonType bp
-- assign BPs to attributes
-- assign BPs to skills
-- assign BPs to resources, gear etc.
selectMetaType :: GoonType -> Int -> MetaType
selectMetaType goonType seed = fromJust . fst $ selectFromRanges ranges (mkStdGen seed)
where
ranges = getRange $ case goonType of
Hacker -> [30, 10, 25, 25, 10]
Magician -> [20, 10, 20, 40, 10]
Berzerker -> [10, 20, 10, 10, 50]
Gunman -> [20, 20, 20, 20, 20]
Face -> [35, 10, 10, 35, 10]
Pilot -> [20, 15, 30, 20, 15]
getRange probabilities = zip [Human .. Troll] probabilities
getMetaTypeQualities :: GoonType -> [[Quality]]
getMetaTypeQualities goonType = case goonType of
Hacker -> [[CodeSlinger "Matrix Attack"], [ExceptionalAttribute "Logic"]]
Magician -> (toQualities [["Magician"], ["Focused Concentration 1", "Focused Concentration 2"]]) ++ [[ExceptionalAttribute "Magic"]]
Berzerker -> (toQualities [["High Pain Tolerance" ++ (show i) | i <- [1..3]]]) ++ [[ExceptionalAttribute "Strength"]]
Gunman -> [[ExceptionalAttribute "Agility"]]
Face -> (toQualities [["First Impression"], ["Blandness"]]) ++ [[ExceptionalAttribute "Charisma"]]
Pilot -> [[ExceptionalAttribute "Reaction"]]
where
toQuality x = fromJust $ M.lookup x qualityDb
toQualities lst = map (map toQuality) lst
getMaxQualitiesByMetaType :: GoonType -> BP -> (BP, [Quality])
getMaxQualitiesByMetaType goonType bp = L.foldl' ff (bp, []) qualities
where
ff (bp', qs) nqs
| isNothing mq = (bp', qs)
| otherwise = ((subBP bp' mqc), (fromJust mq:qs))
where
mq = maxCost nqs bp'
mqc = fromJust $ (\x -> getQualityCost x []) <$> mq
qualities = getMetaTypeQualities goonType
maxCost lst maxBp
| L.null filteredList = Just $ L.maximumBy (comparing (\x -> getQualityCost x [])) filteredList
| otherwise = Nothing
where
filteredList = filter underThreshold lst
underThreshold x = bpx <= maxBp
where
bpx = getQualityCost x []
addStats :: BP -> GoonType -> MetaType -> Stats -> Int -> Maybe (Stats, BP)
addStats bp goonType metaType goonStats seed = getStatsAndBpFromStatName maybeStatName
where
getStatsAndBpFromStatName (Just goonName) = addToStats bp goonName goonStats metaType
getStatsAndBpFromStatName (Nothing) = Nothing
(maybeStatName, _) = selectFromRanges filteredRanges $ mkStdGen seed
-- Get the stats that are maxed out, and filter those out
filteredRanges = filter (\(stat, _) -> not $ stat `M.member` statsThatAreMaxed) ranges
-- If one stat is maxed then we cannot max out any other stats, so remove any that are one below max as well
statsThatAreMaxed = getStatsThatAreMaxed goonStats metaType
ranges = zip statNames $ case goonType of
-- b a r s c i l w m r
Hacker -> [10, 20, 10, 10, 10, 10, 40, 10, 0, 30]
Magician -> [10, 10, 10, 10, 10, 10, 20, 10, 40, 0]
Berzerker -> [20, 10, 10, 40, 10, 10, 10, 10, 0, 0]
Gunman -> [10, 40, 10, 10, 10, 10, 10, 10, 0, 0]
Face -> [10, 10, 10, 10, 40, 10, 10, 10, 0, 0]
Pilot -> [10, 10, 40, 10, 10, 10, 10, 10, 0, 0]
statNames = ["body", "agility", "reaction", "strength", "charisma", "intuition", "logic", "willpower", "magic", "resonance"]
createGoonStats :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Stats
createGoonStats b a r s c i l w init = createStatsShort $ createBaseStats b a r s c i l w 1 init 1 10
createMagicGoonStats :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> Int -> Int -> Int -> Int -> Int -> Int -> Stats
createMagicGoonStats b a r s c i l w ess m init ip cm astralInit astralIp = createStatsShort $ statTuples ++ magicalStatTuples
where
magicalStatTuples = zip ["m", "astral init", "astral ip"] $ map fromIntegral [m, astralInit, astralIp]
statTuples = createBaseStats b a r s c i l w ess init ip cm
createGoon :: String -> Int -> Stats -> [(String, Int)] -> [String] -> [String] -> [String] -> Maybe [Cyberware] -> Maybe [Program] -> Maybe [Spell] -> Goon
createGoon goonName rank goonStats goonSkills goonWeapons armor goonEquipment goonCyberware goonPrograms goonSpells = Goon goonName rank goonStats skills' weapons' equipment' goonCyberware goonPrograms goonSpells Human
where
skills' = [createSkill x (SkillLevel y) | (x,y) <- goonSkills]
weapons' = [getWeapon x | x <- goonWeapons]
equipment' = [getArmor x | x <- armor] ++ [getEquipment x | x <- goonEquipment]
createSkillList :: [(String, Int)] -> [Skill]
createSkillList goonSkills = [createSkill x (SkillLevel y) | (x,y) <- goonSkills]
createBaseStats :: Int -> Int -> Int -> Int -> Int -> Int -> Int -> Int -> Double -> Int -> Int -> Int -> [(String,Double)]
createBaseStats b a r s c i l w ess init ip cm = statsTuples ++ [("ess", ess)]
where
statsTuples = zip ["b", "a", "r", "s", "c", "i", "l", "w", "e", "init", "ip", "cm"] statsList
statsList = map fromIntegral [b,a,r,s,c,i,l,w,1,init,ip,cm]
{--
rentacop :: Goon
rentacop = createGoon "Corporate Security Unit" 2 goonStats goonSkills goonWeapons armor goonEquipment Nothing Nothing Nothing
where
goonStats = createGoonStats 3 3 4 3 3 3 2 3 7
goonSkills = [("Athletics", 3), ("Automatics", 3), ("Dodge", 3), ("Pistols", 3), ("Close Combat", 3)]
goonWeapons = ["Fischetti Security 600 Light Pistol", "HK-227X", "Stun Baton"]
armor = ["Armor Vest"]
goonEquipment = ["CMT Clip"]
rentaCopLt :: Goon
rentaCopLt = Goon "CorpSec Lieutenant" 2 goonStats goonSkills goonWeapons goonEquipment (Just goonCyberware) Nothing (Just goonSpells) Human
where
goonStats = createMagicGoonStats 3 3 3 3 3 4 3 4 6.0 3 7 1 10 8 3
goonSkills = createSkillList [("Assensing", 3), ("Astral Combat", 4), ("Conjuring", 3), ("Leadership", 2), ("Pistols", 2), ("Sorcery", 4)]
goonWeapons = [getWeapon "Fischetti Security 600 Light Pistol"]
goonEquipment = [getArmor "Armor Vest", getEquipment "Renraku Sensei", Focus Spellcasting 2]
goonCyberware = [CyberLimb "Full Arm" Arm (Just $ Body 1) 1.0 15 []]
goonSpells = map getSpell ["Detect Life", "Light", "Physical Barrier", "Powerbolt", "Silence", "Stunball"]
--}