Adding holographic trail and temporal web behaviors. Temporal web is currently broken.

parent 5eff4170
......@@ -20,3 +20,22 @@ run:
check: clean
cabal-dev configure --ghc-options="-O0" --disable-library-profiling --disable-executable-profiling
cabal-dev build
depends:
cabal-dev install cipher-aes-0.1.8
cabal-dev install MaybeT
cabal-dev install MonadCatchIO-transformers
cabal-dev install aeson
cabal-dev install data-lens-template
cabal-dev install data-memocombinators
cabal-dev install hastache
cabal-dev install hslogger
cabal-dev install mwc-random
cabal-dev install snap-core
cabal-dev install snap-server
cabal-dev install snap
cabal-dev install streams
cabal-dev install system-uuid
cabal-dev install data-lens-template
cabal-dev install snap
cabal-dev install streams
This diff is collapsed.
......@@ -9,7 +9,7 @@ import Roguestar.Lib.Data.ToolData
import Roguestar.Lib.Core.Monster
import Roguestar.Lib.DB
import Control.Monad.Error
import Roguestar.Lib.Substances
import Roguestar.Lib.Data.Substances
-- | Outcome of activating a tool.
data ActivationOutcome =
......
......@@ -32,4 +32,5 @@ modifyFacingTerrain f face creature_ref = liftM (fromMaybe False) $ runMaybeT $
clearTerrain :: Terrain -> Terrain
clearTerrain RockFace = RockyGround
clearTerrain Forest = Grass
clearTerrain ForceField = RockyGround
clearTerrain x = x
{-# LANGUAGE Rank2Types #-}
module Roguestar.Lib.Behavior.Outcome
(Effect(..),
Outcome(..),
FailureMode(..),
OutcomeWithEffect(..),
HasDuration(..))
where
import Roguestar.Lib.DB
-- | An effect or consequence in the game world.
class Effect e where
applyEffect :: e -> DB ()
instance Effect (DB x) where
applyEffect effect = effect >> return ()
-- | A failure mode: Abort means that the attempt was so obviously never possible that we should pretend the user (or AI, if an AI bug) never attempted.
-- An example of an Abort would be picking up an object that isn't nearby, or trying to go downstairs when there are no stairs.
data FailureMode = Success | Failure | Abort
-- | A primary outcome of a character's action.
class Outcome e where
failureMode :: e -> FailureMode
instance (Effect e) => Effect [e] where
applyEffect es = mapM_ applyEffect es
instance (Effect a, Effect b) => Effect (a,b) where
applyEffect (a,b) = applyEffect a >> applyEffect b
instance (Effect a, Effect b, Effect c) => Effect (a,b,c) where
applyEffect (a,b,c) = applyEffect a >> applyEffect b >> applyEffect c
instance (Effect a) => Effect (Maybe a) where
applyEffect = maybe (return ()) applyEffect
instance (Outcome a) => Outcome (Maybe a) where
failureMode = maybe Abort failureMode
-- | An outcome (success or failure) with an effect (consequences of the outcome). If the outcome is also an effect (that is, it implements both classes),
-- then it must in both the outcome component and the effect component.
data OutcomeWithEffect o e = OutcomeWithEffect {
_owe_outcome :: o,
_owe_effect :: e,
owe_duration :: (DBReadable db) => db Rational }
instance (Effect e) => Effect (OutcomeWithEffect o e) where
applyEffect (OutcomeWithEffect _ e _) = applyEffect e
instance (Outcome o) => Outcome (OutcomeWithEffect o e) where
failureMode (OutcomeWithEffect o _ _) = failureMode o
class HasDuration a where
getDuration :: (DBReadable db) => a -> db Rational
instance HasDuration (OutcomeWithEffect o e) where
getDuration = owe_duration
......@@ -8,16 +8,19 @@ module Roguestar.Lib.Behavior.Travel
executeClimb,
TeleportJumpOutcome,
resolveTeleportJump,
executeTeleportJump)
executeTeleportJump,
resolveStepWithHolographicTrail,
resolveStepWithTemporalWeb)
where
import Control.Monad.Maybe
import Roguestar.Lib.Data.FacingData
import Roguestar.Lib.DB as DB
import Roguestar.Lib.Core.Plane
import Roguestar.Lib.Core.Plane as Plane
import Data.Maybe
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Error
import Data.Ord
import Roguestar.Lib.Position as Position
import Roguestar.Lib.Data.TerrainData
......@@ -28,34 +31,59 @@ import Roguestar.Lib.Logging
import Roguestar.Lib.Data.TravelData
import Roguestar.Lib.Utility.DetailedLocation
import Roguestar.Lib.Utility.DetailedTravel as DetailedTravel
import Roguestar.Lib.Behavior.Outcome
import Roguestar.Lib.Time
import Roguestar.Lib.PlaneVisibility
data MoveOutcome =
MoveGood { _move_monster :: MonsterRef, move_from :: Standing, _move_to :: Standing }
| MoveFailedBecauseTerrainImpassable { move_from :: Standing }
walkMonster :: (DBReadable db) => Facing ->
(Integer,Integer) ->
MonsterRef ->
db Standing
walkMonster face (x',y') creature_ref =
do l <- DetailedTravel.whereIs creature_ref
db MoveOutcome
walkMonster face (x',y') monster_ref =
do l <- DetailedTravel.whereIs monster_ref
let (Parent plane_ref) = detail l
Position (x,y) = detail l
standing = Standing { standing_plane = plane_ref,
standing_position = Position (x+x',y+y'),
standing_facing = face }
is_passable <- isTerrainPassable plane_ref
creature_ref
monster_ref
(standing_position standing)
case () of
() | not is_passable ->
do logDB gameplay_log INFO $ "Terrain not passable."
return $ detail l
return $ MoveFailedBecauseTerrainImpassable (detail l)
() | otherwise ->
return $ standing
return $ MoveGood monster_ref (detail l) standing
stepMonster :: (DBReadable db) => Facing -> MonsterRef -> db Standing
stepMonster :: (DBReadable db) => Facing -> MonsterRef -> db MoveOutcome
stepMonster face = walkMonster face (facingToRelative face)
turnMonster :: (DBReadable db) => Facing -> MonsterRef -> db Standing
turnMonster :: (DBReadable db) => Facing -> MonsterRef -> db MoveOutcome
turnMonster face = walkMonster face (0,0)
executeMoveMonster :: MoveOutcome -> DB ()
executeMoveMonster (MoveGood monster_ref _ to) =
do _ <- move monster_ref to
return ()
executeMoveMonster (MoveFailedBecauseTerrainImpassable {}) =
return ()
instance Effect MoveOutcome where
applyEffect = executeMoveMonster
instance Outcome MoveOutcome where
failureMode (MoveFailedBecauseTerrainImpassable {}) = Abort
failureMode _ = Success
instance HasDuration MoveOutcome where
getDuration (MoveFailedBecauseTerrainImpassable {}) = return 0.0
getDuration (MoveGood monster_ref from to) = moveActionTime 1.0 (standing_position from, standing_position to) monster_ref
--------------------------------------------------------------------------------
-- Travel between planes.
--------------------------------------------------------------------------------
......@@ -106,7 +134,8 @@ executeClimb (ClimbGood direction creature_ref standing_location) =
--------------------------------------------------------------------------------
-- |
-- Try to teleport the creature to the specified Position. The teleport attempt can be automatically retried a number of times, and the most accurate attempt will be used.
-- Find a random teleport landing position.
-- The teleport attempt can be automatically retried a number of times, and the most accurate attempt will be used.
-- If the retries are negative, the teleport will be made artificially innacurate.
--
randomTeleportLanding :: (DBReadable db) => Integer -> PlaneRef -> Position -> Position -> db Position
......@@ -144,3 +173,70 @@ executeTeleportJump (TeleportJumpGood creature_ref standing_location) =
dbPushSnapshot $ TeleportEvent creature_ref
return ()
--------------------------------------------------------------------------------
-- Setting Terrain
--------------------------------------------------------------------------------
data SetTerrainEffect = SetTerrainEffect {
set_terrain_position :: Position,
set_terrain_plane :: PlaneRef,
set_terrain_type :: Terrain }
executeSetTerrain :: SetTerrainEffect -> DB ()
executeSetTerrain outcome = setTerrainAt (set_terrain_plane outcome)
(set_terrain_position outcome)
(set_terrain_type outcome)
instance Effect SetTerrainEffect where
applyEffect o = executeSetTerrain o
--------------------------------------------------------------------------------
-- Slowing Monsters
--------------------------------------------------------------------------------
data SlowMonsterEffect = SlowMonsterEffect {
slow_monster_ref :: MonsterRef,
slow_monster_amount :: Rational }
executeSlowMonster :: SlowMonsterEffect -> DB ()
executeSlowMonster outcome = increaseTime (slow_monster_ref outcome) (slow_monster_amount outcome)
instance Effect SlowMonsterEffect where
applyEffect = executeSlowMonster
--------------------------------------------------------------------------------
-- HolographicTrail
--------------------------------------------------------------------------------
resolveStepWithHolographicTrail :: (DBReadable db) => Facing -> MonsterRef -> db (OutcomeWithEffect MoveOutcome (MoveOutcome, Maybe SetTerrainEffect))
resolveStepWithHolographicTrail facing monster_ref =
do when (not $ facing `elem` [North,South,East,West]) $
throwError $ DBError "resolveStepWithHolographicTrail: only allowed in the four NSEW directions"
move_outcome <- stepMonster facing monster_ref
let (plane_ref :: PlaneRef, position :: Position) = (standing_plane $ move_from move_outcome, standing_position $ move_from move_outcome)
old_terrain_type <- terrainAt plane_ref position
return $ OutcomeWithEffect
move_outcome
(move_outcome,
if old_terrain_type `elem` difficult_terrains then Nothing else Just $ SetTerrainEffect position plane_ref ForceField)
(getDuration move_outcome)
--------------------------------------------------------------------------------
-- TemporalWeb
--------------------------------------------------------------------------------
resolveStepWithTemporalWeb :: (DBReadable db) => Facing -> MonsterRef -> db (OutcomeWithEffect MoveOutcome (MoveOutcome,[SlowMonsterEffect]))
resolveStepWithTemporalWeb facing monster_ref =
do move_outcome <- stepMonster facing monster_ref
let (plane_ref :: PlaneRef, position :: Position) = (standing_plane $ move_from move_outcome, standing_position $ move_from move_outcome)
t <- getDuration move_outcome
faction <- getMonsterFaction monster_ref
(vobs :: [MonsterRef]) <- liftM (mapMaybe coerceReference) $ dbGetVisibleObjectsForFaction (const $ return True) faction plane_ref
slows <- forM vobs $ \vob ->
do (p :: Position) <- liftM detail $ getPlanarLocation monster_ref
return $ SlowMonsterEffect vob (t / fromInteger (Position.distanceBetweenSquared p position))
return $ OutcomeWithEffect
move_outcome
(move_outcome, slows)
(getDuration move_outcome)
{-# LANGUAGE PatternGuards, ScopedTypeVariables #-}
--Mechanics
module Roguestar.Lib.Turns
module Roguestar.Lib.Behavior.Turns
(performPlayerTurn)
where
......@@ -8,7 +8,6 @@ import Prelude hiding (getContents)
import Control.Monad.Maybe
import Control.Monad.Trans
import Roguestar.Lib.DB
import Roguestar.Lib.Reference
import Roguestar.Lib.Data.FactionData
import Roguestar.Lib.Data.SpeciesData
import Roguestar.Lib.Data.MonsterData (Monster)
......@@ -19,6 +18,7 @@ import Data.Ratio
import Roguestar.Lib.Data.FacingData
import Roguestar.Lib.Data.TerrainData
import Data.Maybe
import Roguestar.Lib.Data.BehaviorData
import Roguestar.Lib.Behavior
import qualified Roguestar.Lib.Perception as P
import Roguestar.Lib.Position
......@@ -83,7 +83,7 @@ dbPerform1PlanarAITurn plane_ref =
do (terrain_type,species) <- weightedPickM $ unweightedSet monster_spawns
_ <- spawnNPC terrain_type species plane_ref $ List.map detail $ player_locations
return ()
dbAdvanceTime plane_ref planar_turn_interval
increaseTime plane_ref planar_turn_interval
-- |
-- Spawn a non-player creature on the specified terrain type (or fail if not finding that terrain type)
......
......@@ -19,7 +19,7 @@ import Prelude hiding (getContents)
import Roguestar.Lib.Data.MonsterData
import Roguestar.Lib.DB
import Roguestar.Lib.Data.SpeciesData
import Roguestar.Lib.Species
import Roguestar.Lib.Data.SpeciesTraits
import Roguestar.Lib.Data.FactionData
import Control.Monad.Error
import Control.Monad.Random
......
......@@ -19,7 +19,6 @@ module Roguestar.Lib.Core.Plane
import Prelude hiding (getContents)
import Roguestar.Lib.Utility.Grids
import Roguestar.Lib.Reference
import Roguestar.Lib.DB
import Roguestar.Lib.Data.TerrainData
import Roguestar.Lib.Data.PlaneData
......
......@@ -41,8 +41,10 @@ module Roguestar.Lib.DB
ro, atomic,
logDB,
mapRO, filterRO, sortByRO,
dbGetTimeCoordinate,
dbAdvanceTime,
getTime,
setTime,
adjustTime,
increaseTime,
dbNextTurn,
dbPushSnapshot,
peepOldestSnapshot,
......@@ -56,7 +58,6 @@ module Roguestar.Lib.DB
import Prelude hiding (getContents)
import Roguestar.Lib.Data.ReferenceTypes
import Roguestar.Lib.Data.LocationData
import Roguestar.Lib.Reference
import Roguestar.Lib.Data.MonsterData
import Roguestar.Lib.Data.PlaneData
import Roguestar.Lib.Data.BuildingData
......@@ -70,7 +71,6 @@ import Control.Monad.State
import Control.Monad.Error
import Control.Monad.Reader
import Control.Applicative
import Roguestar.Lib.TimeCoordinate
import Data.Ord
import Control.Monad.Random as Random
import Roguestar.Lib.Random
......@@ -98,7 +98,7 @@ data DB_BaseType = DB_BaseType { db_player_state :: PlayerState,
db_tools :: Map ToolRef Tool,
db_buildings :: Map BuildingRef Building,
db_hierarchy :: HD.HierarchicalDatabase Location,
db_time_coordinates :: Map (Reference ()) TimeCoordinate,
db_time_coordinates :: Map (Reference ()) Rational,
db_error_flag :: String,
db_prior_snapshot :: Maybe DB_BaseType,
db_action_count :: Integer }
......@@ -217,6 +217,9 @@ sortByRO f xs =
return (x,y)) xs
-- | Run action synthesized from a read-only action (prepare-execute pattern).
-- I don't remember why I wrote this function, and suspect that it is not needed.
-- It might have had something to do with reverting the state of the database if
-- an error were thrown.
atomic :: (x -> DB ()) -> (forall m. DBReadable m => m x) -> DB x
atomic action ro_action =
do x <- ro ro_action
......@@ -241,7 +244,7 @@ initial_db = DB_BaseType {
db_buildings = Map.fromList [],
db_hierarchy = HD.fromList [],
db_error_flag = [],
db_time_coordinates = Map.fromList [(genericReference the_universe, zero_time)],
db_time_coordinates = Map.fromList [(genericReference the_universe, 0)],
db_prior_snapshot = Nothing,
db_action_count = 0 }
......@@ -280,7 +283,7 @@ dbAddObjectComposable constructReferenceAction updateObjectAction constructLocat
updateObjectAction ref thing
setLocation $ constructLocationAction ref loc
genericParent_ref <- liftM parentReference $ whereIs ref
dbSetTimeCoordinate (genericReference ref) =<< dbGetTimeCoordinate (genericReference genericParent_ref)
setTime (genericReference ref) =<< getTime (genericReference genericParent_ref)
return ref
-- |
......@@ -456,7 +459,7 @@ dbUnwieldMonster c = mapM_ (maybe (return ()) setLocation . returnToInventory) =
-- Moves an object, returning the location of the object before and after
-- the move.
--
move :: (LocationConstructor l, ReferenceTypeOf l ~ e) => Reference e -> l -> DB (Location,Location)
move :: (LocationConstructor l, ReferenceTypeOf l ~ e, ReferenceType e) => Reference e -> l -> DB (Location,Location)
move ref location_data =
do old <- whereIs ref
let new = constructLocation ref location_data (Just old)
......@@ -464,7 +467,7 @@ move ref location_data =
when (childReference old /= childReference new) $
throwError $ DBError "moveTo: Object changed identity during move!"
when (parentReference old == parentReference new) $
dbSetTimeCoordinate ref =<< dbGetTimeCoordinate (parentReference new)
setTime ref =<< getTime (parentReference new)
return (old,new)
moveAllWithin :: (LocationConstructor l, ReferenceTypeOf l ~ ()) =>
......@@ -504,21 +507,29 @@ getContents item = asks (HD.lookupChildren (toUID item) . db_hierarchy)
-- |
-- Gets the time of an object.
--
dbGetTimeCoordinate :: (DBReadable db,ReferenceType a) => Reference a -> db TimeCoordinate
dbGetTimeCoordinate ref = asks (fromMaybe (error "dbGetTimeCoordinate: missing time coordinate.") .
Map.lookup (genericReference ref) . db_time_coordinates)
-- The "time" of an object is when its next turn is scheduled.
--
getTime :: (DBReadable db,ReferenceType a) => Reference a -> db Rational
getTime ref = asks (fromMaybe (error "dbGetTimeCoordinate: missing time coordinate.") .
Map.lookup (genericReference ref) . db_time_coordinates)
-- |
-- Sets the time of an object.
--
dbSetTimeCoordinate :: Reference a -> TimeCoordinate -> DB ()
dbSetTimeCoordinate ref tc = modify (\db -> db { db_time_coordinates = Map.insert (genericReference ref) tc $ db_time_coordinates db })
setTime :: (ReferenceType a) => Reference a -> Rational -> DB ()
setTime ref tc = modify (\db -> db { db_time_coordinates = Map.insert (genericReference ref) tc $ db_time_coordinates db })
-- |
-- Adjust the time of an object by an arbitrary rule.
--
adjustTime :: (ReferenceType a) => Reference a -> (Rational -> Rational) -> DB ()
adjustTime ref f = setTime ref . f =<< getTime ref
-- |
-- Advances the time of an object.
-- Add to the time of an object.
--
dbAdvanceTime :: (ReferenceType a) => Reference a -> Rational -> DB ()
dbAdvanceTime ref t = dbSetTimeCoordinate ref =<< (return . (advanceTime t)) =<< dbGetTimeCoordinate ref
increaseTime :: (ReferenceType a) => Reference a -> Rational -> DB ()
increaseTime ref x = adjustTime ref (+ x)
-- |
-- Finds the object whose turn is next, among a restricted group of objects.
......
module Roguestar.Lib.Data.BehaviorData
(FacingBehavior(..),
Behavior(..))
where
import Roguestar.Lib.Data.FacingData
import Roguestar.Lib.Data.LocationData
import Roguestar.Lib.Data.MakeData
data FacingBehavior =
Step
| TurnInPlace
| Jump
| Fire
| Attack
| ClearTerrain
| ActivateBuilding
| TemporalWebStep
| HolographicTrailStep
deriving (Show)
--
-- Every possible behavior that a creature might take, AI or Human.
--
data Behavior =
FacingBehavior FacingBehavior Facing
| StepDown
| StepUp
| Pickup ToolRef
| Wield ToolRef
| Unwield
| Drop ToolRef
| Wait
| Vanish
| Activate
| Make PrepareMake
deriving (Show)
......@@ -3,6 +3,9 @@
module Roguestar.Lib.Data.LocationData
(Reference,
toUID,
(=:=),
(=/=),
ReferenceType(..),
genericReference,
MonsterRef,
PlaneRef,
......@@ -38,7 +41,6 @@ import Roguestar.Lib.Data.PlaneData
import Roguestar.Lib.Data.BuildingData
import Control.Monad
import Roguestar.Lib.Position
import Roguestar.Lib.Reference
--
-- Getting References generically.
......
......@@ -16,7 +16,7 @@ module Roguestar.Lib.Data.MakeData
import Roguestar.Lib.Data.LocationData
import Roguestar.Lib.Data.ToolData
import Roguestar.Lib.Substances
import Roguestar.Lib.Data.Substances
-- | Multi-step process for gathering the materials to make something.
data PrepareMake = PrepareMake {
......
......@@ -89,7 +89,7 @@ data MonsterSpecial =
Hover
| Teleportation
| TemporalWeb
| ComplexificationMesh
| HolographicTrail
deriving (Eq,Read,Show,Ord)
instance MonsterEndo MonsterSpecial where
......
{-# LANGUAGE ScopedTypeVariables #-}
module Roguestar.Lib.Data.ReferenceTypes
(Reference(..),
unsafeReference,
toUID,
ReferenceType(..),
(=:=),
(=/=),
Location(..),
Position(..),
Standing(..),
......@@ -32,9 +37,6 @@ import Roguestar.Lib.Position
-- to guarantee that such data structures are always consistent with the game logic,
-- e.g. a planet can not be wielded as a weapon.
--
-- DB and DBData import and re-export most of DBPrivate, but the un-exported portions
-- of this module are unsafe. Other modules should not import DBPrivate.
--
-- |
-- Type representing the entire universe.
......@@ -67,6 +69,53 @@ toUID :: Reference a -> Integer
toUID (UniverseRef) = 0
toUID a = uid a
--
-- Reference Equality
--
(=:=) :: Reference a -> Reference b -> Bool
a =:= b = toUID a == toUID b
(=/=) :: Reference a -> Reference b -> Bool
a =/= b = not $ a =:= b
class ReferenceType a where
coerceReference :: Reference x -> Maybe (Reference a)
instance ReferenceType () where
coerceReference = Just . unsafeReference
instance ReferenceType Plane where
coerceReference (PlaneRef ref) = Just $ PlaneRef ref
coerceReference _ = Nothing
instance ReferenceType Tool where
coerceReference (ToolRef ref) = Just $ ToolRef ref
coerceReference _ = Nothing
instance ReferenceType Monster where
coerceReference (MonsterRef ref) = Just $ MonsterRef ref
coerceReference _ = Nothing
instance ReferenceType Building where
coerceReference (BuildingRef ref) = Just $ BuildingRef ref
coerceReference _ = Nothing
instance ReferenceType TheUniverse where
coerceReference UniverseRef = Just UniverseRef
coerceReference _ = Nothing
instance (ReferenceType a, ReferenceType b) => ReferenceType (Either a b) where
coerceReference x =
let coerce_left :: Maybe (Reference a)
coerce_left = coerceReference x
coerce_right :: Maybe (Reference b)
coerce_right = coerceReference x
result = case (coerce_left,coerce_right) of
(Just l,_) -> Just $ unsafeReference l
(_,Just r) -> Just $ unsafeReference r
_ -> Nothing
in result
-- |
-- The location of a Monster standing on a Plane.
--
......
--Data
module Roguestar.Lib.Data.SpeciesData
(Species(..),
all_species)
where
--Data
data Species =
BlueRecreant
| RedRecreant
......
--Data
module Roguestar.Lib.Species
module Roguestar.Lib.Data.SpeciesTraits
(SpeciesData(..),
speciesInfo)
where
--Data
import Roguestar.Lib.Data.MonsterData
import Roguestar.Lib.Data.SpeciesData
......@@ -43,6 +41,6 @@ speciesInfo TabularMonstrosity = SpeciesData
(Perception, 1),
(Speed, 4)]
[Hover,
ComplexificationMesh]
HolographicTrail]
{-# LANGUAGE OverloadedStrings #-}
--Data
module Roguestar.Lib.Substances
module Roguestar.Lib.Data.Substances
(Gas(..),
Material(..),
Chromalite(..),
......
......@@ -47,6 +47,7 @@ data Terrain = RockFace
| Lava
| Glass -- solidified lava
| RecreantFactory
| ForceField
| Upstairs
| Downstairs
deriving (Read,Show,Eq,Ord,Enum,Bounded)
......@@ -70,7 +71,7 @@ data TerrainPlacement = TerrainPlacement {
placeTerrain :: TerrainPlacement -> TerrainGrid -> TerrainGrid
placeTerrain terrain_placement =
arbitraryReplaceGrid (List.map (second Terrain) $ placement_sources terrain_placement)
(Random.map Terrain $ placement_replacements terrain_placement)
(fmap Terrain $ placement_replacements terrain_placement)
(placement_seed terrain_placement)
(placement_blob terrain_placement)
......@@ -125,7 +126,7 @@ difficult_terrains = impassable_terrains ++ [Water,Lava]
-- A list of TerrainPatches that are considered "impassable" for traveling.
--
impassable_terrains :: [Terrain]
impassable_terrains = [RockFace,Forest]
impassable_terrains = [RockFace,Forest,ForceField]
terrainInterpFn :: (Biome,Biome) -> WeightedSet Terrain
terrainInterpFn biomes = case biomes of
......@@ -144,7 +145,7 @@ terrainInterpMap :: Map (MetaTerrain,MetaTerrain) (WeightedSet MetaTerrain)
terrainInterpMap =
let biome_patch_pairs :: [(Biome,Biome)]
biome_patch_pairs = [(a,b) | a <- [minBound..maxBound], b <- [minBound..maxBound]]
interps = List.map (Random.map Terrain . terrainInterpFn) biome_patch_pairs
interps = List.map (fmap Terrain . terrainInterpFn) biome_patch_pairs
in fromList (zip (List.map (first Biome . second Biome) biome_patch_pairs) interps)
type TerrainGrid = Grid MetaTerrain
......@@ -159,5 +160,5 @@ generateTerrain :: TerrainGenerationData -> [Integer] -> TerrainGrid
generateTerrain tg rands = flip (List.foldr placeTerrain) (tg_placements tg) $
interpolateGrid Nothing (head rands) $
interpolateGrid (Just terrainInterpMap) (head $ drop 1 rands) $
generateGrid (Random.map Biome $ tg_biome tg) Nothing (tg_smootheness tg) (drop 2 rands)
generateGrid (fmap Biome $ tg_biome tg) Nothing (tg_smootheness tg) (drop 2 rands)
......@@ -19,7 +19,7 @@ module Roguestar.Lib.Data.ToolData
kinetic_sabre)
where
import Roguestar.Lib.Substances
import Roguestar.Lib.Data.Substances
import qualified Data.Text as T
data Tool = DeviceTool DeviceFunction Device
......
......@@ -15,7 +15,7 @@ import Roguestar.Lib.Data.FacingData
--
terrainHideMultiplier :: Terrain -> Integer
terrainHideMultiplier RockFace = 3
terrainHideMultiplier RockyGround = 1
terrainHideMultiplier RockyGround = 0
terrainHideMultiplier Dirt = 0
terrainHideMultiplier Grass = 1
terrainHideMultiplier Sand = 1
......@@ -27,6 +27,7 @@ terrainHideMultiplier Glass = 0
terrainHideMultiplier RecreantFactory = 0
terrainHideMultiplier Downstairs = 2
terrainHideMultiplier Upstairs = 0
terrainHideMultiplier ForceField = 0 -- probably painful to be inside a force field, not good for stealth
-- |
-- We cast a ray between the spotter and the hider. This indicates to what extent each terrain type
......@@ -36,16 +37,17 @@ terrainOpacity :: Terrain -> Integer
terrainOpacity RockFace = 90
terrainOpacity RockyGround = 0
terrainOpacity Dirt = 0
terrainOpacity Grass = 5
terrainOpacity Grass = 5 -- sometimes there is tall grass
terrainOpacity Sand = 0
terrainOpacity Forest = 25