Compare commits
No commits in common. "archive" and "main" have entirely different histories.
129
src/Decoder.elm
129
src/Decoder.elm
|
|
@ -1,129 +0,0 @@
|
|||
module Decoder exposing (..)
|
||||
|
||||
import Dict
|
||||
import FastDict
|
||||
import Json.Decode as D
|
||||
import Json.Encode as E
|
||||
|
||||
|
||||
type Information a
|
||||
= Information
|
||||
{ decoder : D.Decoder a
|
||||
, encoder : a -> E.Value
|
||||
, keys : List String
|
||||
, default : a
|
||||
}
|
||||
|
||||
|
||||
bool : List String -> Bool -> Information Bool
|
||||
bool keys default =
|
||||
Information
|
||||
{ decoder = D.bool
|
||||
, encoder = E.bool
|
||||
, keys = keys
|
||||
, default = default
|
||||
}
|
||||
|
||||
|
||||
dict : List String -> Dict.Dict comparable value -> (comparable -> String) -> (String -> comparable) -> (value -> E.Value) -> D.Decoder value -> Information (Dict.Dict comparable value)
|
||||
dict keys default fromKey toKey fromValue valueDecoder =
|
||||
Information
|
||||
{ decoder =
|
||||
D.keyValuePairs valueDecoder
|
||||
|> D.map (List.map (Tuple.mapFirst toKey))
|
||||
|> D.map Dict.fromList
|
||||
, encoder = E.dict fromKey fromValue
|
||||
, keys = keys
|
||||
, default = default
|
||||
}
|
||||
|
||||
|
||||
fastdict : List String -> FastDict.Dict comparable value -> (comparable -> String) -> (String -> comparable) -> (value -> E.Value) -> D.Decoder value -> Information (FastDict.Dict comparable value)
|
||||
fastdict keys default fromKey toKey fromValue valueDecoder =
|
||||
Information
|
||||
{ decoder =
|
||||
D.keyValuePairs valueDecoder
|
||||
|> D.map (List.map (Tuple.mapFirst toKey))
|
||||
|> D.map FastDict.fromList
|
||||
, encoder =
|
||||
FastDict.toList
|
||||
>> List.map (Tuple.mapBoth fromKey fromValue)
|
||||
>> E.object
|
||||
, keys = keys
|
||||
, default = default
|
||||
}
|
||||
|
||||
|
||||
int : List String -> Int -> Information Int
|
||||
int keys default =
|
||||
Information
|
||||
{ decoder = D.int
|
||||
, encoder = E.int
|
||||
, keys = keys
|
||||
, default = default
|
||||
}
|
||||
|
||||
|
||||
list : List String -> List a -> (a -> E.Value) -> D.Decoder a -> Information (List a)
|
||||
list keys default fromValue valueDecoder =
|
||||
Information
|
||||
{ decoder = D.list valueDecoder
|
||||
, encoder = E.list fromValue
|
||||
, keys = keys
|
||||
, default = default
|
||||
}
|
||||
|
||||
|
||||
{-| The website allows users to overwrite the pre-generated values.
|
||||
Hence, if a value already exists, it is returned. If it does not, it will be
|
||||
generated.
|
||||
-}
|
||||
lookUp : E.Value -> Information a -> a
|
||||
lookUp value (Information { decoder, keys, default }) =
|
||||
case D.decodeValue (D.at keys decoder) value of
|
||||
Ok v ->
|
||||
v
|
||||
|
||||
Err _ ->
|
||||
default
|
||||
|
||||
|
||||
overwrite : a -> Information a -> E.Value -> E.Value
|
||||
overwrite newValue (Information info) obj =
|
||||
case info.keys of
|
||||
[] ->
|
||||
info.encoder newValue
|
||||
|
||||
head :: tail ->
|
||||
case D.decodeValue (D.keyValuePairs D.value) obj of
|
||||
Ok o ->
|
||||
o
|
||||
|> FastDict.fromList
|
||||
|> FastDict.update head
|
||||
(\mv ->
|
||||
overwrite newValue
|
||||
(Information
|
||||
{ encoder = info.encoder
|
||||
, decoder = info.decoder
|
||||
, keys = tail
|
||||
, default = info.default
|
||||
}
|
||||
)
|
||||
(mv |> Maybe.withDefault (E.dict identity identity Dict.empty))
|
||||
|> Just
|
||||
)
|
||||
|> FastDict.toCoreDict
|
||||
|> E.dict identity identity
|
||||
|
||||
Err _ ->
|
||||
obj
|
||||
|
||||
|
||||
string : List String -> String -> Information String
|
||||
string keys default =
|
||||
Information
|
||||
{ encoder = E.string
|
||||
, decoder = D.string
|
||||
, keys = keys
|
||||
, default = default
|
||||
}
|
||||
341
src/Defaults.elm
341
src/Defaults.elm
|
|
@ -1,341 +0,0 @@
|
|||
module Defaults exposing (..)
|
||||
|
||||
{-| The Defaults module exposes config values. These values can be overwritten
|
||||
but they are usually set by default.
|
||||
-}
|
||||
|
||||
import FastDict as Dict
|
||||
|
||||
|
||||
commonerOccupations : Dict.Dict String Int
|
||||
commonerOccupations =
|
||||
Dict.fromList
|
||||
[ ( "Baker", 25 )
|
||||
, ( "Shoemaker", 37 )
|
||||
, ( "Furrier", 62 )
|
||||
, ( "Household helper", 62 )
|
||||
, ( "Tailor", 62 )
|
||||
, ( "Barber", 87 )
|
||||
, ( "Unlicensed Doctor", 87 )
|
||||
, ( "Jeweler", 100 )
|
||||
, ( "Old cloth seller", 100 )
|
||||
, ( "Pastry baker", 125 )
|
||||
, ( "Mason", 125 )
|
||||
, ( "Carpenter", 137 )
|
||||
, ( "Ostler", 150 )
|
||||
, ( "Porter", 150 )
|
||||
, ( "Weaver", 150 )
|
||||
, ( "Chandler", 175 )
|
||||
, ( "Mercer", 175 )
|
||||
, ( "Cooper", 175 )
|
||||
, ( "Cobbler", 180 )
|
||||
, ( "Watercarrier", 212 )
|
||||
, ( "Scabbardmaker", 212 )
|
||||
, ( "Wine-seller", 225 )
|
||||
, ( "Hatmaker", 237 )
|
||||
, ( "Saddler", 250 )
|
||||
, ( "Chicken butcher", 250 )
|
||||
, ( "Pursemaker", 275 )
|
||||
, ( "Soapmaker", 275 )
|
||||
, ( "Goldsmith", 300 )
|
||||
, ( "Butcher", 300 )
|
||||
, ( "Farrier", 300 )
|
||||
, ( "Fishmonger", 300 )
|
||||
, ( "Beer seller", 350 )
|
||||
, ( "Buckle Maker", 350 )
|
||||
, ( "Plasterer", 350 )
|
||||
, ( "Spice Merchant", 350 )
|
||||
, ( "Hedge-Mage", 350 )
|
||||
, ( "Painter", 375 )
|
||||
, ( "Hunter", 400 )
|
||||
, ( "Licensed doctor", 425 )
|
||||
, ( "Roofer", 450 )
|
||||
, ( "Locksmith", 475 )
|
||||
, ( "Bather", 475 )
|
||||
, ( "Ropemaker", 475 )
|
||||
, ( "Inn", 500 )
|
||||
, ( "Tanner", 500 )
|
||||
, ( "Copyist", 500 )
|
||||
, ( "Sculptor", 500 )
|
||||
, ( "Rugmaker", 500 )
|
||||
, ( "Dyer", 500 )
|
||||
, ( "Harness-Maker", 500 )
|
||||
, ( "Bleacher", 525 )
|
||||
, ( "Hay Merchant", 575 )
|
||||
, ( "Cutler", 575 )
|
||||
, ( "Glovemaker", 600 )
|
||||
, ( "Woodcarver", 600 )
|
||||
, ( "Woodseller", 600 )
|
||||
, ( "Herald", 600 )
|
||||
, ( "Lorimer", 600 )
|
||||
, ( "Penmaker", 650 )
|
||||
, ( "Horse Trainer", 700 )
|
||||
, ( "Bookbinder", 750 )
|
||||
, ( "Stationer (Ink/Pen Maker)", 700 )
|
||||
, ( "Spurrer", 800 )
|
||||
, ( "Dung Carter", 800 )
|
||||
, ( "Costermonger", 800 )
|
||||
, ( "Fortune Teller", 900 )
|
||||
, ( "Chirurgeon", 900 )
|
||||
, ( "Silversmith", 920 )
|
||||
, ( "Illuminator", 975 )
|
||||
, ( "Coppersmith", 1100 )
|
||||
, ( "Master of Hounds", 1200 )
|
||||
, ( "Leech Collector", 1300 )
|
||||
, ( "Tinsmith", 1400 )
|
||||
, ( "Castellan", 1500 )
|
||||
, ( "Bookseller", 1575 )
|
||||
, ( "Composer", 1600 )
|
||||
, ( "Limeburner", 1600 )
|
||||
, ( "Ale-conner", 1700 )
|
||||
, ( "Amanuensis", 1800 )
|
||||
, ( "Gong Farmer", 1800 )
|
||||
, ( "Coiner", 1900 )
|
||||
, ( "Philosopher", 2000 )
|
||||
, ( "Noble", 3000 )
|
||||
]
|
||||
|
||||
|
||||
type alias RaceData =
|
||||
{ density : Int
|
||||
, maturesAt : Int
|
||||
, livesUntil : Int
|
||||
, becomesParentUntil : Int
|
||||
}
|
||||
|
||||
|
||||
races : Dict.Dict String RaceData
|
||||
races =
|
||||
Dict.fromList
|
||||
[ ( "Human"
|
||||
, { density = 800000
|
||||
, maturesAt = 20
|
||||
, livesUntil = 90
|
||||
, becomesParentUntil = 40
|
||||
}
|
||||
)
|
||||
, ( "Half-elf"
|
||||
, { density = 100000
|
||||
, maturesAt = 20
|
||||
, livesUntil = 200
|
||||
, becomesParentUntil = 160
|
||||
}
|
||||
)
|
||||
, ( "Dwarf"
|
||||
, { density = 60000
|
||||
, maturesAt = 50
|
||||
, livesUntil = 350
|
||||
, becomesParentUntil = 150
|
||||
}
|
||||
)
|
||||
, ( "Elf"
|
||||
, { density = 35000
|
||||
, maturesAt = 100
|
||||
, livesUntil = 750
|
||||
, becomesParentUntil = 500
|
||||
}
|
||||
)
|
||||
, ( "Half-orc"
|
||||
, { density = 25000
|
||||
, maturesAt = 14
|
||||
, livesUntil = 75
|
||||
, becomesParentUntil = 30
|
||||
}
|
||||
)
|
||||
, ( "Halfling"
|
||||
, { density = 20000
|
||||
, maturesAt = 20
|
||||
, livesUntil = 65
|
||||
, becomesParentUntil = 40
|
||||
}
|
||||
)
|
||||
, ( "Dragonborn"
|
||||
, { density = 10000
|
||||
, maturesAt = 15
|
||||
, livesUntil = 80
|
||||
, becomesParentUntil = 40
|
||||
}
|
||||
)
|
||||
, ( "Tiefling"
|
||||
, { density = 10000
|
||||
, maturesAt = 20
|
||||
, livesUntil = 110
|
||||
, becomesParentUntil = 45
|
||||
}
|
||||
)
|
||||
, ( "Gnome"
|
||||
, { density = 10000
|
||||
, maturesAt = 40
|
||||
, livesUntil = 500
|
||||
, becomesParentUntil = 200
|
||||
}
|
||||
)
|
||||
, ( "Aasimar"
|
||||
, { density = 9000
|
||||
, maturesAt = 20
|
||||
, livesUntil = 160
|
||||
, becomesParentUntil = 60
|
||||
}
|
||||
)
|
||||
, ( "Orc"
|
||||
, { density = 8000
|
||||
, maturesAt = 12
|
||||
, livesUntil = 50
|
||||
, becomesParentUntil = 30
|
||||
}
|
||||
)
|
||||
, ( "Goliath"
|
||||
, { density = 7500
|
||||
, maturesAt = 20
|
||||
, livesUntil = 90
|
||||
, becomesParentUntil = 40
|
||||
}
|
||||
)
|
||||
, ( "Tabaxi"
|
||||
, { density = 5000
|
||||
, maturesAt = 20
|
||||
, livesUntil = 90
|
||||
, becomesParentUntil = 40
|
||||
}
|
||||
)
|
||||
, ( "Hobgoblin"
|
||||
, { density = 2500
|
||||
, maturesAt = 20
|
||||
, livesUntil = 90
|
||||
, becomesParentUntil = 40
|
||||
}
|
||||
)
|
||||
, ( "Lizardfolk"
|
||||
, { density = 1500
|
||||
, maturesAt = 14
|
||||
, livesUntil = 60
|
||||
, becomesParentUntil = 30
|
||||
}
|
||||
)
|
||||
, ( "Goblin"
|
||||
, { density = 1000
|
||||
, maturesAt = 8
|
||||
, livesUntil = 60
|
||||
, becomesParentUntil = 30
|
||||
}
|
||||
)
|
||||
, ( "Yuan-Ti Pureblood"
|
||||
, { density = 1000
|
||||
, maturesAt = 20
|
||||
, livesUntil = 90
|
||||
, becomesParentUntil = 40
|
||||
}
|
||||
)
|
||||
, ( "Bugbear"
|
||||
, { density = 1000
|
||||
, maturesAt = 16
|
||||
, livesUntil = 80
|
||||
, becomesParentUntil = 35
|
||||
}
|
||||
)
|
||||
, ( "Tortle"
|
||||
, { density = 1000
|
||||
, maturesAt = 15
|
||||
, livesUntil = 50
|
||||
, becomesParentUntil = 30
|
||||
}
|
||||
)
|
||||
, ( "Warforged"
|
||||
, { density = 1000
|
||||
, maturesAt = 0
|
||||
, livesUntil = 5000
|
||||
, becomesParentUntil = 5000
|
||||
}
|
||||
)
|
||||
, ( "Kobold"
|
||||
, { density = 800
|
||||
, maturesAt = 6
|
||||
, livesUntil = 120
|
||||
, becomesParentUntil = 25
|
||||
}
|
||||
)
|
||||
, ( "Shifter"
|
||||
, { density = 750
|
||||
, maturesAt = 10
|
||||
, livesUntil = 70
|
||||
, becomesParentUntil = 30
|
||||
}
|
||||
)
|
||||
, ( "Triton"
|
||||
, { density = 400
|
||||
, maturesAt = 15
|
||||
, livesUntil = 200
|
||||
, becomesParentUntil = 110
|
||||
}
|
||||
)
|
||||
, ( "Firbolg"
|
||||
, { density = 300
|
||||
, maturesAt = 30
|
||||
, livesUntil = 500
|
||||
, becomesParentUntil = 300
|
||||
}
|
||||
)
|
||||
, ( "Kalashtar"
|
||||
, { density = 250
|
||||
, maturesAt = 20
|
||||
, livesUntil = 90
|
||||
, becomesParentUntil = 40
|
||||
}
|
||||
)
|
||||
, ( "Aarakocra"
|
||||
, { density = 250
|
||||
, maturesAt = 3
|
||||
, livesUntil = 30
|
||||
, becomesParentUntil = 20
|
||||
}
|
||||
)
|
||||
, ( "Kenku"
|
||||
, { density = 200
|
||||
, maturesAt = 12
|
||||
, livesUntil = 60
|
||||
, becomesParentUntil = 36
|
||||
}
|
||||
)
|
||||
, ( "Changeling"
|
||||
, { density = 50
|
||||
, maturesAt = 20
|
||||
, livesUntil = 90
|
||||
, becomesParentUntil = 40
|
||||
}
|
||||
)
|
||||
, ( "Gith"
|
||||
, { density = 75
|
||||
, maturesAt = 20
|
||||
, livesUntil = 90
|
||||
, becomesParentUntil = 40
|
||||
}
|
||||
)
|
||||
, ( "Air Genasi"
|
||||
, { density = 10
|
||||
, maturesAt = 20
|
||||
, livesUntil = 120
|
||||
, becomesParentUntil = 50
|
||||
}
|
||||
)
|
||||
, ( "Earth Genasi"
|
||||
, { density = 10
|
||||
, maturesAt = 20
|
||||
, livesUntil = 120
|
||||
, becomesParentUntil = 50
|
||||
}
|
||||
)
|
||||
, ( "Fire Genasi"
|
||||
, { density = 10
|
||||
, maturesAt = 20
|
||||
, livesUntil = 120
|
||||
, becomesParentUntil = 50
|
||||
}
|
||||
)
|
||||
, ( "Water Genasi"
|
||||
, { density = 10
|
||||
, maturesAt = 20
|
||||
, livesUntil = 120
|
||||
, becomesParentUntil = 50
|
||||
}
|
||||
)
|
||||
]
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
module Generatable exposing (Generatable, content, fromGenerator, generateAndReturnFromSeed, generateFromSeed, generate, map, regenerate, setContent, removeContent, updateGenerator)
|
||||
module Generatable exposing (..)
|
||||
{-| The Generatable type contains information that can be stored, modified,
|
||||
generated or regenerated.
|
||||
-}
|
||||
|
|
@ -26,25 +26,6 @@ fromGenerator : Random.Generator a -> Generatable a
|
|||
fromGenerator gr =
|
||||
ToBeGenerated gr
|
||||
|
||||
{-| Get the generator with which new values can be generated.
|
||||
-}
|
||||
generator : Generatable a -> Random.Generator a
|
||||
generator gen =
|
||||
case gen of
|
||||
ToBeGenerated gr ->
|
||||
gr
|
||||
|
||||
Generated _ gr ->
|
||||
gr
|
||||
|
||||
{-| Create a new Generatable from a given seed, and return the value.
|
||||
-}
|
||||
generateAndReturnFromSeed : Random.Seed -> Generatable a -> ( Generatable a, a )
|
||||
generateAndReturnFromSeed seed gen =
|
||||
case Random.step (generator gen) seed of
|
||||
( new, _ ) ->
|
||||
( Generated new (generator gen), new )
|
||||
|
||||
{-| Create a new generatable from a given seed.
|
||||
-}
|
||||
generateFromSeed : Random.Seed -> Generatable a -> Generatable a
|
||||
|
|
@ -84,13 +65,23 @@ already generated.
|
|||
-}
|
||||
regenerate : (a -> msg) -> Generatable a -> Cmd msg
|
||||
regenerate toMsg gen =
|
||||
Random.generate toMsg (generator gen)
|
||||
case gen of
|
||||
ToBeGenerated gr ->
|
||||
Random.generate toMsg gr
|
||||
|
||||
Generated _ gr ->
|
||||
Random.generate toMsg gr
|
||||
|
||||
{-| Override the content with freshly generated content.
|
||||
-}
|
||||
setContent : a -> Generatable a -> Generatable a
|
||||
setContent x gen =
|
||||
Generated x (generator gen)
|
||||
case gen of
|
||||
ToBeGenerated gr ->
|
||||
Generated x gr
|
||||
|
||||
Generated _ gr ->
|
||||
Generated x gr
|
||||
|
||||
{-| Remove any previously generated content from the generatable.
|
||||
-}
|
||||
|
|
|
|||
|
|
@ -1,121 +0,0 @@
|
|||
module Generator exposing (..)
|
||||
|
||||
{-| The Generator module helps generate values based on a given hash.
|
||||
-}
|
||||
|
||||
import Pick exposing (Generator)
|
||||
|
||||
|
||||
commonerOccupation : Generator (Maybe String)
|
||||
commonerOccupation =
|
||||
Pick.inverseWeighted
|
||||
[ ( "Baker", 25 )
|
||||
, ( "Shoemaker", 37 )
|
||||
, ( "Furrier", 62 )
|
||||
, ( "Household helper", 62 )
|
||||
, ( "Tailor", 62 )
|
||||
, ( "Barber", 87 )
|
||||
, ( "Unlicensed Doctor", 87 )
|
||||
, ( "Jeweler", 100 )
|
||||
, ( "Old cloth seller", 100 )
|
||||
, ( "Pastry baker", 125 )
|
||||
, ( "Mason", 125 )
|
||||
, ( "Carpenter", 137 )
|
||||
, ( "Ostler", 150 )
|
||||
, ( "Porter", 150 )
|
||||
, ( "Weaver", 150 )
|
||||
, ( "Chandler", 175 )
|
||||
, ( "Mercer", 175 )
|
||||
, ( "Cooper", 175 )
|
||||
, ( "Cobbler", 180 )
|
||||
, ( "Watercarrier", 212 )
|
||||
, ( "Scabbardmaker", 212 )
|
||||
, ( "Wine-seller", 225 )
|
||||
, ( "Hatmaker", 237 )
|
||||
, ( "Saddler", 250 )
|
||||
, ( "Chicken butcher", 250 )
|
||||
, ( "Pursemaker", 275 )
|
||||
, ( "Soapmaker", 275 )
|
||||
, ( "Goldsmith", 300 )
|
||||
, ( "Butcher", 300 )
|
||||
, ( "Farrier", 300 )
|
||||
, ( "Fishmonger", 300 )
|
||||
, ( "Beer seller", 350 )
|
||||
, ( "Buckle Maker", 350 )
|
||||
, ( "Plasterer", 350 )
|
||||
, ( "Spice Merchant", 350 )
|
||||
, ( "Hedge-Mage", 350 )
|
||||
, ( "Painter", 375 )
|
||||
, ( "Hunter", 400 )
|
||||
, ( "Licensed doctor", 425 )
|
||||
, ( "Roofer", 450 )
|
||||
, ( "Locksmith", 475 )
|
||||
, ( "Bather", 475 )
|
||||
, ( "Ropemaker", 475 )
|
||||
, ( "Inn", 500 )
|
||||
, ( "Tanner", 500 )
|
||||
, ( "Copyist", 500 )
|
||||
, ( "Sculptor", 500 )
|
||||
, ( "Rugmaker", 500 )
|
||||
, ( "Dyer", 500 )
|
||||
, ( "Harness-Maker", 500 )
|
||||
, ( "Bleacher", 525 )
|
||||
, ( "Hay Merchant", 575 )
|
||||
, ( "Cutler", 575 )
|
||||
, ( "Glovemaker", 600 )
|
||||
, ( "Woodcarver", 600 )
|
||||
, ( "Woodseller", 600 )
|
||||
, ( "Herald", 600 )
|
||||
, ( "Lorimer", 600 )
|
||||
, ( "Penmaker", 650 )
|
||||
, ( "Horse Trainer", 700 )
|
||||
, ( "Bookbinder", 750 )
|
||||
, ( "Stationer (Ink/Pen Maker)", 700 )
|
||||
, ( "Spurrer", 800 )
|
||||
, ( "Dung Carter", 800 )
|
||||
, ( "Costermonger", 800 )
|
||||
, ( "Fortune Teller", 900 )
|
||||
, ( "Chirurgeon", 900 )
|
||||
, ( "Silversmith", 920 )
|
||||
, ( "Illuminator", 975 )
|
||||
, ( "Coppersmith", 1100 )
|
||||
, ( "Master of Hounds", 1200 )
|
||||
, ( "Leech Collector", 1300 )
|
||||
, ( "Tinsmith", 1400 )
|
||||
, ( "Castellan", 1500 )
|
||||
, ( "Bookseller", 1575 )
|
||||
, ( "Composer", 1600 )
|
||||
, ( "Limeburner", 1600 )
|
||||
, ( "Ale-conner", 1700 )
|
||||
, ( "Amanuensis", 1800 )
|
||||
, ( "Gong Farmer", 1800 )
|
||||
, ( "Coiner", 1900 )
|
||||
, ( "Philosopher", 2000 )
|
||||
, ( "Noble", 3000 )
|
||||
]
|
||||
|
||||
|
||||
townName : Generator String
|
||||
townName =
|
||||
Pick.map2 (++)
|
||||
(Pick.fromList
|
||||
"Auden"
|
||||
[ "Caia"
|
||||
, "Ex Caia"
|
||||
, "Gold"
|
||||
, "Hirey"
|
||||
, "Ideato"
|
||||
, "Jairo"
|
||||
, "Kalares"
|
||||
, "Oosterdorp"
|
||||
]
|
||||
)
|
||||
(Pick.fromList
|
||||
""
|
||||
[ ""
|
||||
, ""
|
||||
, " City"
|
||||
, " Town"
|
||||
, "'s Creek"
|
||||
]
|
||||
)
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
module Objects exposing (..)
|
||||
|
||||
{-| This module exposes all types that can be generated.
|
||||
-}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
module Objects.District exposing (..)
|
||||
{-| Districts are sections of a town. These are mostly segregated to keep the
|
||||
design of the procedurally generated town simple.
|
||||
-}
|
||||
|
||||
{-| A district is a part of town. Usually, it is a neighbourhood.
|
||||
-}
|
||||
type District
|
||||
= District {}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
module Objects.NPC exposing (..)
|
||||
|
||||
{-| The NPC is the character that is most ordinary.
|
||||
-}
|
||||
|
||||
import Hash exposing (Hash)
|
||||
import Objects.TownName as Town
|
||||
|
||||
|
||||
type NPC
|
||||
= NPC { town : Town.TownName, id : Int }
|
||||
|
||||
|
||||
fromTown : { town : Town.TownName, id : Int } -> NPC
|
||||
fromTown =
|
||||
NPC
|
||||
|
||||
|
||||
toTown : NPC -> Town.TownName
|
||||
toTown (NPC { town }) =
|
||||
town
|
||||
|
||||
|
||||
toId : NPC -> Int
|
||||
toId (NPC { id }) =
|
||||
id
|
||||
|
||||
|
||||
toHash : NPC -> Hash
|
||||
toHash (NPC { town, id }) =
|
||||
Hash.fromString "NPC"
|
||||
|> Hash.dependent (Town.toHash town)
|
||||
|> Hash.dependent (Hash.fromInt id)
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
module Objects.Town exposing (..)
|
||||
|
||||
import Array exposing (Array)
|
||||
import Hash
|
||||
import Random
|
||||
import Generatable exposing (Generatable)
|
||||
import Objects.District as District exposing (District)
|
||||
|
||||
{-| The Msg is the update telling what adjustments are made to the model.
|
||||
-}
|
||||
type Msg
|
||||
= GenerateSize
|
||||
|
||||
{-| The Town is the comprehensive model that contains all the information about
|
||||
a town.
|
||||
-}
|
||||
type Town
|
||||
= Town
|
||||
{ districts : Generatable (Array (Generatable District))
|
||||
, name : String
|
||||
, size : TownSize
|
||||
}
|
||||
|
||||
type TownSize
|
||||
= Tiny
|
||||
| Small
|
||||
| Medium
|
||||
| Average
|
||||
| Big
|
||||
| Huge
|
||||
-- | Humongous
|
||||
-- | Massive
|
||||
-- | Colossal
|
||||
|
||||
{-| Determine the number of districts in the town based on its size.
|
||||
-}
|
||||
districtNumberGenerator : TownSize -> Random.Generator Int
|
||||
districtNumberGenerator ts =
|
||||
case ts of
|
||||
Tiny ->
|
||||
Random.int 1 2
|
||||
|
||||
Small ->
|
||||
Random.int 5 8
|
||||
|
||||
Medium ->
|
||||
Random.int 15 20
|
||||
|
||||
Average ->
|
||||
Random.int 35 45
|
||||
|
||||
Big ->
|
||||
Random.int 90 140
|
||||
|
||||
Huge ->
|
||||
Random.int 250 470
|
||||
|
||||
{-| Init a new town.
|
||||
-}
|
||||
init : { name : String, size : TownSize } -> Town
|
||||
init data =
|
||||
Town
|
||||
{ districts =
|
||||
data.size
|
||||
|> districtNumberGenerator
|
||||
|> Random.map (always never)
|
||||
|> Generatable.fromGenerator
|
||||
, name = data.name
|
||||
, size = data.size
|
||||
}
|
||||
|
||||
{-| Get a town's name.
|
||||
-}
|
||||
name : Town -> String
|
||||
name (Town town) = town.name
|
||||
|
||||
{-| Get a town's size.
|
||||
-}
|
||||
size : Town -> Maybe Int
|
||||
size (Town town) =
|
||||
Generatable.content town.size
|
||||
|
||||
{-| Get a town's size. If it isn't generated yet, generate it.
|
||||
-}
|
||||
sizeGenerate : Town -> ( Town, Int )
|
||||
sizeGenerate ((Town t) as town) =
|
||||
case Generatable.content t.size of
|
||||
Just s ->
|
||||
( town, s )
|
||||
|
||||
Nothing ->
|
||||
case Generatable.generateAndReturnFromSeed (sizeSeed town) t.size of
|
||||
( newSize, s ) ->
|
||||
( Town { t | size = newSize }, s )
|
||||
|
||||
{-| Generate a seed for the town's size.
|
||||
-}
|
||||
sizeSeed : Town -> Random.Seed
|
||||
sizeSeed (Town town) =
|
||||
Hash.fromString town.name
|
||||
|> Hash.dependent (Hash.fromString "size")
|
||||
|> Hash.toString
|
||||
|> String.toInt
|
||||
|> Maybe.withDefault 0
|
||||
|> Random.initialSeed
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
module Objects.TownName exposing (TownName, fromString, toHash, toString)
|
||||
|
||||
import Hash exposing (Hash)
|
||||
|
||||
|
||||
type TownName
|
||||
= TownName String
|
||||
|
||||
|
||||
{-| Decode a town name from a string.
|
||||
-}
|
||||
fromString : String -> TownName
|
||||
fromString =
|
||||
TownName
|
||||
|
||||
|
||||
{-| Encode a town name into a string.
|
||||
-}
|
||||
toString : TownName -> String
|
||||
toString (TownName name) =
|
||||
name
|
||||
|
||||
|
||||
{-| Hash a town name.
|
||||
-}
|
||||
toHash : TownName -> Hash
|
||||
toHash (TownName name) =
|
||||
Hash.dependent (Hash.fromString "town-name") (Hash.fromString name)
|
||||
68
src/Pick.elm
68
src/Pick.elm
|
|
@ -1,68 +0,0 @@
|
|||
module Pick exposing (..)
|
||||
|
||||
{-| The pick module helps pick random values based on a given hash.
|
||||
-}
|
||||
|
||||
import Hash exposing (Hash)
|
||||
import Random
|
||||
|
||||
|
||||
type alias Generator a =
|
||||
Random.Generator a
|
||||
|
||||
|
||||
generate : Hash -> Generator a -> a
|
||||
generate hash picker =
|
||||
let
|
||||
seed : Random.Seed
|
||||
seed =
|
||||
hash
|
||||
|> Hash.toString
|
||||
|> String.toInt
|
||||
|> Maybe.withDefault 0
|
||||
|> Random.initialSeed
|
||||
in
|
||||
Random.step
|
||||
|
||||
|
||||
fromList : a -> List a -> Generator a
|
||||
fromList head tail =
|
||||
Random.uniform head tail
|
||||
|
||||
|
||||
inverseWeighted : List ( a, Int ) -> Generator (Maybe a)
|
||||
inverseWeighted items =
|
||||
let
|
||||
chanceSum : Float
|
||||
chanceSum =
|
||||
items
|
||||
|> List.map Tuple.second
|
||||
|> List.map toFloat
|
||||
|> List.map ((/) 1)
|
||||
|> List.sum
|
||||
in
|
||||
items
|
||||
|> List.map (Tuple.mapSecond (\i -> 1 / toFloat i))
|
||||
|> List.map (\( a, b ) -> ( b, a ))
|
||||
|> List.map (Tuple.mapSecond Just)
|
||||
|> weighted ( max 0 (1 - chanceSum), Nothing )
|
||||
|
||||
|
||||
map : (a -> b) -> Generator a -> Generator b
|
||||
map =
|
||||
Random.map
|
||||
|
||||
|
||||
map2 : (a -> b -> c) -> Generator a -> Generator b -> Generator c
|
||||
map2 =
|
||||
Random.map2
|
||||
|
||||
|
||||
value : a -> Generator a
|
||||
value =
|
||||
Random.constant
|
||||
|
||||
|
||||
weighted : ( Float, a ) -> List ( Float, a ) -> Generator a
|
||||
weighted =
|
||||
Random.weighted
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
module Seed.Town exposing (TownSeed, fromName, toHash, toSeed)
|
||||
{-| The Town Seed helps generate different towns.
|
||||
-}
|
||||
|
||||
import Hash
|
||||
import Random
|
||||
|
||||
type TownSeed = TownSeed String
|
||||
|
||||
fromName : String -> TownSeed
|
||||
fromName name = TownSeed name
|
||||
|
||||
toHash : TownSeed -> Hash.Hash
|
||||
toHash (TownSeed name) =
|
||||
Hash.fromString name
|
||||
|
||||
toSeed : TownSeed -> Random.Seed
|
||||
toSeed seed =
|
||||
seed
|
||||
|> toHash
|
||||
|> Hash.toString
|
||||
|> String.toInt
|
||||
|> Maybe.withDefault 0
|
||||
|> Random.initialSeed
|
||||
Loading…
Reference in New Issue