packages feed

roguestar-engine-0.4.0.0: src/Substances.hs

{-# LANGUAGE OverloadedStrings #-}
module Substances
    (Gas(..),
     Material(..),
     Chromalite(..),
     Solid(..),
     materialValue,
     MaterialValue(..),
     Substance(..),
     SubstanceType(toSubstance),
     coerceSubstance,
     isGas,
     isMaterial,
     isChromalite,
     substances,
     prettySubstance,
     printSubstances,
     gasValue,
     chromaliteAlignment,
     chromalitePotency)
    where

import Alignment
import Data.List
import Data.Ord
import Data.Maybe
import qualified Data.ByteString.Char8 as B

data Substance = 
    GasSubstance Gas
  | MaterialSubstance Material
  | ChromaliteSubstance Chromalite
             deriving (Read,Show,Eq,Ord)

substances :: [Substance]
substances = map GasSubstance [minBound..maxBound] ++
             map MaterialSubstance [minBound..maxBound] ++
	     map ChromaliteSubstance [minBound..maxBound]

prettySubstance :: Substance -> B.ByteString
prettySubstance (GasSubstance x) = B.pack $ show x
prettySubstance (MaterialSubstance x) = B.pack $ show x
prettySubstance (ChromaliteSubstance x) = B.pack $ show x

printSubstances :: IO ()
printSubstances = B.putStrLn $ B.unlines $ map (\(x,y) -> prettySubstance y `B.append` ":  " `B.append` B.pack (show x)) $ sortBy (comparing fst) $ map (\x -> (substanceValue x,x)) substances

data Solid = MaterialSolid Material
           | ChromaliteSolid Chromalite
           deriving (Read,Show,Eq,Ord)
             
data Gas = 
    Water
  | Hydrogen
  | Helium
  | Oxygen
  | Nitrogen
  | Flourine
  | Neon
  | Argon
  | Krypton
  | Xenon
  | Radon
  | Methane
  | Ammonia
  | Iodine
  | Chlorine deriving (Eq,Enum,Ord,Show,Read,Bounded)
	
data Material = 
    Aluminum
  | Titanium
  | Palladium
  | Molybdenum
  | Lead
  | Copper
  | Iron
  | Cobalt
  | Zirconium
  | Gold
  | Silver
  | Platinum
  | Zinc
  | Uranium
  | Plutonium
  | Thorium
  | Diamond
  | Carbon
  | Wood
  | Plastic
  | Silicon
  | Nickel
        deriving (Eq,Enum,Ord,Show,Read,Bounded)

--
-- Chromalite is an engineered, crystaline metamaterial capable of storing many times it's own rest mass energy.
-- Precisely how many times is indicated by the chromalitePotency function.
--
-- Because any accidental release of this energy would obviously be catastrophic, chromalite is itself intelligent
-- and capable of adapting to stressful situations to avoid any such accidental release.
--
data Chromalite = 
    Rutilium     -- red Chromalite
  | Crudnium     -- green Chromalite
  | Pteulanium   -- blue Chromalite
  | Caerulite    -- azure Chromalite
  | Ionidium     -- violet Chromalite
  | Aurite       -- yellow Chromalite
  | Argentate    -- silver Chromalite
  | Trabanate    -- brown Chromalite
  | Arumate      -- gold Chromalite
  | Candonium    -- white Chromalite
  | Canitium     -- gray Chromalite
  | Infuscanoid  -- black Chromalite
  | Endurium     -- blue/shadowy Chromalite
  | Malignite    -- yellow/shadowy Chromalite
  | Diabolite    -- radiant white Chromalite
  | Bectonite    -- radiant black Chromalite
     deriving (Eq,Enum,Ord,Show,Read,Bounded)

gasValue :: Gas -> Integer
gasValue Water = 2
gasValue Hydrogen = 4
gasValue Helium = 6
gasValue Nitrogen = 7
gasValue Oxygen = 10
gasValue Flourine = 12
gasValue Neon = 20
gasValue Ammonia = 21
gasValue Methane = 24
gasValue Chlorine = 30
gasValue Argon = 40
gasValue Krypton = 42
gasValue Xenon = 60
gasValue Radon = 70
gasValue Iodine = 100

data MaterialValue = MaterialValue {
    material_construction_value :: Integer, -- value of material for constructing buildings, pipes, casings for gadgets, etc
    material_critical_value :: Integer,     -- value of material for critical purposes, such as miniature electronic components
    material_scarcity :: Integer }          -- scarcity of material

materialValue :: Material -> MaterialValue
materialValue Aluminum =    MaterialValue  50  20   6
materialValue Titanium =    MaterialValue  70  15  15
materialValue Palladium =   MaterialValue  30  30  65
materialValue Molybdenum =  MaterialValue  18  55  40
materialValue Lead =        MaterialValue  15   7  31
materialValue Copper =      MaterialValue  40  40  18
materialValue Iron =        MaterialValue  25  15  10
materialValue Cobalt =      MaterialValue  30  35  30
materialValue Zirconium =   MaterialValue  12  50  23
materialValue Gold =        MaterialValue  20  35  83
materialValue Silver =      MaterialValue  10  20  80
materialValue Platinum =    MaterialValue  22  40  81
materialValue Zinc =        MaterialValue  35  25  26
materialValue Uranium =     MaterialValue   5  90  37
materialValue Plutonium =   MaterialValue   1 100 100
materialValue Thorium =     MaterialValue  20  80  33
materialValue Diamond =     MaterialValue 100 100  90
materialValue Carbon =      MaterialValue  60  20  20
materialValue Wood =        MaterialValue  25   1   3
materialValue Plastic =     MaterialValue  30  10   1
materialValue Silicon =     MaterialValue  25  50   5
materialValue Nickel =      MaterialValue  25  45  25

chromaliteAlignment :: Chromalite -> Alignment
chromaliteAlignment Rutilium = (Chaotic,Strategic)
chromaliteAlignment Crudnium = (Neutral,Strategic)
chromaliteAlignment Pteulanium = (Lawful,Strategic)
chromaliteAlignment Caerulite = (Lawful,Tactical)
chromaliteAlignment Ionidium = (Neutral,Tactical)
chromaliteAlignment Aurite = (Chaotic,Tactical)
chromaliteAlignment Argentate = (Lawful,Diplomatic)
chromaliteAlignment Trabanate = (Neutral,Diplomatic)
chromaliteAlignment Arumate = (Chaotic,Diplomatic)
chromaliteAlignment Candonium = (Lawful,Indifferent)
chromaliteAlignment Canitium = (Neutral,Indifferent)
chromaliteAlignment Infuscanoid = (Chaotic,Indifferent)
chromaliteAlignment Endurium = (Evil,Strategic)
chromaliteAlignment Malignite = (Evil,Tactical)
chromaliteAlignment Diabolite = (Evil,Diplomatic)
chromaliteAlignment Bectonite = (Evil,Indifferent)

class SubstanceType a where
    toSubstance :: a -> Substance
    fromSubstance :: Substance -> Maybe a

coerceSubstance :: (SubstanceType a,SubstanceType b) => a -> Maybe b
coerceSubstance = fromSubstance . toSubstance

isGas :: (SubstanceType a) => a -> Bool
isGas = isJust . (`asTypeOf` (undefined :: Maybe Gas)) . coerceSubstance

isMaterial :: (SubstanceType a) => a -> Bool
isMaterial = isJust . (`asTypeOf` (undefined :: Maybe Material)) . coerceSubstance

isChromalite :: (SubstanceType a) => a -> Bool
isChromalite = isJust . (`asTypeOf` (undefined :: Maybe Chromalite)) . coerceSubstance

substanceValue :: (SubstanceType a) => a -> Integer
substanceValue a = case toSubstance a of
    GasSubstance x -> gasValue x + 10
    MaterialSubstance x -> (nom + crit) * scarce
        where MaterialValue nom crit scarce = materialValue x
    ChromaliteSubstance x -> 1000 + 2 * chromalitePotency x ^ 2

instance SubstanceType Gas where
    toSubstance x = GasSubstance x
    fromSubstance (GasSubstance x) = Just x
    fromSubstance _ = Nothing
    
instance SubstanceType Material where
    toSubstance x = MaterialSubstance x
    fromSubstance (MaterialSubstance x) = Just x
    fromSubstance _ = Nothing

instance SubstanceType Chromalite where
    toSubstance x = ChromaliteSubstance x
    fromSubstance (ChromaliteSubstance x) = Just x
    fromSubstance _ = Nothing

instance SubstanceType Substance where
    toSubstance x = x
    fromSubstance = Just

instance SubstanceType Solid where
    toSubstance (MaterialSolid x) = toSubstance x
    toSubstance (ChromaliteSolid x) = toSubstance x
    fromSubstance (MaterialSubstance x) = Just $ MaterialSolid x
    fromSubstance (ChromaliteSubstance x) = Just $ ChromaliteSolid x
    fromSubstance _ = Nothing

chromalitePotency :: Chromalite -> Integer
chromalitePotency = alignmentPotency . chromaliteAlignment