about summary refs log tree commit diff
path: root/src/Xanthous/Random.hs
diff options
context:
space:
mode:
authorGriffin Smith <root@gws.fyi>2019-09-28T19·02-0400
committerGriffin Smith <root@gws.fyi>2019-09-28T19·03-0400
commitec39dc0a5bed58e0b0b48eeac98e0fd0ceaa65db (patch)
tree65a53bd79b15020572524db0a6e65ec549b5ab24 /src/Xanthous/Random.hs
parentabea2dcfac0e094bf4ce0d378763af7816b04501 (diff)
Tweak gormlak movement slightly
- Don't let gormlaks run into things like walls or each other
- Add a small element of randomness to gormlaks' motion
- Increase gormlaks' vision by a large amount
Diffstat (limited to 'src/Xanthous/Random.hs')
-rw-r--r--src/Xanthous/Random.hs47
1 files changed, 43 insertions, 4 deletions
diff --git a/src/Xanthous/Random.hs b/src/Xanthous/Random.hs
index 33ada54cf105..bbf176f71d6e 100644
--- a/src/Xanthous/Random.hs
+++ b/src/Xanthous/Random.hs
@@ -1,14 +1,34 @@
-{-# LANGUAGE TupleSections #-}
+--------------------------------------------------------------------------------
 {-# LANGUAGE UndecidableInstances #-}
-
+{-# OPTIONS_GHC -fno-warn-orphans #-}
+--------------------------------------------------------------------------------
 module Xanthous.Random
   ( Choose(..)
   , ChooseElement(..)
+  , Weighted(..)
+  , evenlyWeighted
+  , weightedBy
   ) where
-
+--------------------------------------------------------------------------------
 import Xanthous.Prelude
+--------------------------------------------------------------------------------
 import Data.List.NonEmpty (NonEmpty)
-import Control.Monad.Random.Class (MonadRandom(getRandomR))
+import Control.Monad.Random.Class (MonadRandom(getRandomR, getRandom))
+import Data.Random.Shuffle.Weighted
+import Data.Random.Distribution
+import Data.Random.Distribution.Uniform
+import Data.Random.Distribution.Uniform.Exclusive
+import Data.Random.Sample
+import qualified Data.Random.Source as DRS
+--------------------------------------------------------------------------------
+
+instance {-# INCOHERENT #-} (Monad m, MonadRandom m) => DRS.MonadRandom m where
+  getRandomWord8 = getRandom
+  getRandomWord16 = getRandom
+  getRandomWord32 = getRandom
+  getRandomWord64 = getRandom
+  getRandomDouble = getRandom
+  getRandomNByteInteger n = getRandomR (0, 256 ^ n)
 
 class Choose a where
   type RandomResult a
@@ -37,3 +57,22 @@ instance MonoFoldable a => Choose (NonNull a) where
 instance Choose (NonEmpty a) where
   type RandomResult (NonEmpty a) = a
   choose = choose . fromNonEmpty @[_]
+
+newtype Weighted w t a = Weighted (t (w, a))
+
+evenlyWeighted :: [a] -> Weighted Int [] a
+evenlyWeighted = Weighted . itoList
+
+weightedBy :: Functor t => (a -> w) -> t a -> Weighted w t a
+weightedBy weighting xs = Weighted $ (weighting &&& id) <$> xs
+
+instance (Num w, Ord w, Distribution Uniform w, Excludable w) => Choose (Weighted w [] a) where
+  type RandomResult (Weighted w [] a) = Maybe a
+  choose (Weighted ws) = sample $ headMay <$> weightedSample 1 ws
+
+instance (Num w, Ord w, Distribution Uniform w, Excludable w) => Choose (Weighted w NonEmpty a) where
+  type RandomResult (Weighted w NonEmpty a) = a
+  choose (Weighted ws) =
+    sample
+    $ fromMaybe (error "unreachable") . headMay
+    <$> weightedSample 1 (toList ws)