Skip to content

Instantly share code, notes, and snippets.

@sharkdp
Created July 26, 2015 09:39
Show Gist options
  • Save sharkdp/624113f1218693f84739 to your computer and use it in GitHub Desktop.
Save sharkdp/624113f1218693f84739 to your computer and use it in GitHub Desktop.
Simulation of the game Panic Lab
module Main where
import Prelude
import Control.Monad (when)
import Control.Monad.Eff
import Control.Monad.Eff.Console
import Data.Int
import Data.Int.Bits
import Data.List
import Data.List.Random (shuffle)
import Data.Maybe
type Personality = Int
type BitMask = Int
data Card = Amoeba Personality | Mutation BitMask
instance eqCard :: Eq Card where
eq (Amoeba a) (Amoeba b) = a == b
eq (Mutation a) (Mutation b) = a == b
eq _ _ = false
cards :: List Card
cards = amoebae ++ amoebae ++ mutations
where amoebae = map Amoeba (range 0 7)
mutations = map Mutation (1 : 2 : 4 : Nil)
-- Simulate the escape of a single amoeba for a given queue of cards.
-- Returns the number of steps or `Nothing` if the amoeba dies.
run :: List Card -> Personality -> Maybe Int
run all pers = go 1 0 all pers
-- n: number of steps, m: number of mutations
where go :: Int -> Int -> List Card -> Personality -> Maybe Int
go n m Nil p = go n m all p -- end of queue, start from beginning
go _ 4 _ _ = Nothing -- four mutations, amoeba dies
-- bitwise XOR to toggle (mutate) the appropriate bit:
go n m (Cons (Mutation prop) cs) a = go (n + 1) (m + 1) cs (a .^. prop)
go n m (Cons (Amoeba b) cs) a | a == b = Just n
| otherwise = go (n + 1) m cs a
main = do
let runs = 8000
res <- replicateM runs $ do
queue <- shuffle cards
return (run queue 0)
let deaths = length $ filter isNothing res
print $ (toNumber deaths) / (toNumber runs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment