Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

multiple heroes: a few tweaks around the type of heroes on a level

We should probably use the same type for monsters, to have a number
with which to indicate a targeted monster. Monsters probably don't need
to carry their numbers in them, unlike heroes, because they don't get
moved to and from any "current monster" state field.
  • Loading branch information...
commit f4732309616caa7cbc678a4721868c4495174d8a 1 parent c4fcdc8
@Mikolaj Mikolaj authored
View
6 src/Actions.hs
@@ -570,9 +570,8 @@ actorAttackActor source target =
generateMonster :: Action ()
generateMonster =
do
- lvl <- gets slevel
- player <- gets splayer
- nlvl <- liftIO $ rndToIO $ addMonster lvl player
+ state <- get
+ nlvl <- liftIO $ rndToIO $ addMonster state
modify (updateLevel (const nlvl))
-- | Advance the move time for the given actor.
@@ -590,4 +589,3 @@ regenerate actor =
-- TODO: remove hardcoded time interval, regeneration should be an attribute of the monster
when (time `mod` 1500 == 0) $
updateActor actor (\ m -> m { mhp = min (mhpmax m) (mhp m + 1) })
-
View
15 src/Dungeon.hs
@@ -91,7 +91,7 @@ emptyroom addWallsRnd cfg@(LevelConfig { levelSize = (sy,sx) }) nm =
do
let lmap = digRoom Light ((1,1),(sy-1,sx-1)) (emptyLMap (sy,sx))
let smap = M.fromList [ ((y,x),-100) | y <- [0..sy], x <- [0..sx] ]
- let lvl = Level nm M.empty (sy,sx) [] smap lmap ""
+ let lvl = Level nm lmEmpty (sy,sx) [] smap lmap ""
-- locations of the stairs
su <- findLoc lvl (const floor)
sd <- findLoc lvl (\ l t -> floor t
@@ -106,7 +106,7 @@ emptyroom addWallsRnd cfg@(LevelConfig { levelSize = (sy,sx) }) nm =
maybe id (\ l -> M.insert sd (newTile (Stairs Light Down l))) ld $
(\lmap -> foldl' addItem lmap is) $
lmap
- level lu ld = Level nm M.empty (sy,sx) [] smap (flmap lu ld) "bigroom"
+ level lu ld = Level nm lmEmpty (sy,sx) [] smap (flmap lu ld) "bigroom"
return (level, su, sd)
-- | For a bigroom level: Create a level consisting of only one, empty room.
@@ -222,7 +222,7 @@ level cfg nm =
let lmap :: LMap
lmap = foldr digCorridor (foldr (\ (r, dl) m -> digRoom dl r m)
(emptyLMap (levelSize cfg)) dlrooms) cs
- let lvl = Level nm M.empty (levelSize cfg) [] smap lmap ""
+ let lvl = Level nm lmEmpty (levelSize cfg) [] smap lmap ""
-- convert openings into doors
dlmap <- fmap M.fromList . mapM
(\ o@((y,x),(t,r)) ->
@@ -259,7 +259,7 @@ level cfg nm =
maybe id (\ l -> M.update (\ (t,r) -> Just $ newTile (Stairs (toDL $ light t) Down l)) sd) ld $
foldr (\ (l,it) f -> M.update (\ (t,r) -> Just (t { titems = it : titems t }, r)) l . f) id is
dlmap
- in Level nm M.empty (levelSize cfg) [] smap flmap meta, su, sd)
+ in Level nm lmEmpty (levelSize cfg) [] smap flmap meta, su, sd)
rollItems :: LevelConfig -> Level -> Loc -> Rnd [(Loc, Item)]
rollItems cfg lvl ploc =
@@ -303,14 +303,15 @@ digRoom dl ((y0,x0),(y1,x1)) l
in M.unionWith const rm l
-- | Create a new monster in the level, at a random position.
-addMonster :: Level -> Player -> Rnd Level
-addMonster lvl@(Level { lplayers = pls, lmonsters = ms, lmap = lmap }) player =
+addMonster :: State -> Rnd Level
+addMonster state@(State { slevel = lvl@(Level { lmonsters = ms,
+ lmap = lmap }) }) =
do
rc <- monsterGenChance (lname lvl) ms
if rc
then
do
- let ps = player : M.elems pls
+ let ps = levelPlayerList state
-- TODO: new monsters should always be generated in a place that isn't
-- visible by the player (if possible -- not possible for bigrooms)
-- levels with few rooms are dangerous, because monsters may spawn
View
22 src/Level.hs
@@ -7,6 +7,7 @@ import Data.Binary
import Data.Binary.Put
import Data.Binary.Get
import Data.Map as M
+import qualified Data.IntMap as IM
import Data.Set as S
import Data.List as L
import Data.Ratio
@@ -70,14 +71,16 @@ instance Binary Dungeon where
-- that level.
type DungeonLoc = (LevelName, Loc)
+type LMonsters = IM.IntMap Monster
+
data Level = Level
- { lname :: LevelName,
- lplayers :: M.Map Int Player,
- lsize :: (Y,X),
- lmonsters :: [Monster],
- lsmell :: SMap,
- lmap :: LMap,
- lmeta :: String }
+ { lname :: LevelName,
+ lplayers :: LMonsters, -- ^ all but the current heroes on the level
+ lsize :: (Y,X),
+ lmonsters :: [Monster],
+ lsmell :: SMap,
+ lmap :: LMap,
+ lmeta :: String }
deriving Show
updateLMap :: (LMap -> LMap) -> Level -> Level
@@ -89,9 +92,12 @@ updateSMap f lvl = lvl { lsmell = f (lsmell lvl) }
updateMonsters :: ([Monster] -> [Monster]) -> Level -> Level
updateMonsters f lvl = lvl { lmonsters = f (lmonsters lvl) }
-updatePlayers :: (M.Map Int Player -> M.Map Int Player) -> Level -> Level
+updatePlayers :: (LMonsters -> LMonsters) -> Level -> Level
updatePlayers f lvl = lvl { lplayers = f (lplayers lvl) }
+lmEmpty :: LMonsters
+lmEmpty = IM.empty
+
instance Binary Level where
put (Level nm pls sz@(sy,sx) ms lsmell lmap lmeta) =
do
View
10 src/Perception.hs
@@ -2,7 +2,6 @@ module Perception where
import Data.Set as S
import Data.List as L
-import Data.Map as M
import Data.Maybe
import Geometry
@@ -16,10 +15,9 @@ data Perception =
Perception { preachable :: Set Loc, pvisible :: Set Loc }
perception_ :: State -> Perception
-perception_ (State { splayer = player,
- slevel = Level { lmap = lmap, lplayers = pls },
- sconfig = config,
- ssensory = sensory }) =
+perception_ state@(State { slevel = Level { lmap = lmap },
+ sconfig = config,
+ ssensory = sensory }) =
let mode = Config.getOption config "engine" "fov_mode"
radius = fromMaybe 40 $ Config.getOption config "engine" "fov_radius"
fovMode =
@@ -34,7 +32,7 @@ perception_ (State { splayer = player,
Just "permissive" -> Permissive radius
Just "digital" -> Digital radius
_ -> Shadow
- ps = player : M.elems pls
+ ps = levelPlayerList state
pers = L.map (\ pl -> perception fovMode (mloc pl) lmap) ps
reachable = S.unions (L.map preachable pers)
visible = S.unions (L.map pvisible pers)
View
31 src/State.hs
@@ -1,6 +1,7 @@
module State where
import qualified Data.Map as M
+import qualified Data.IntMap as IM
import qualified Data.Set as S
import Control.Monad
import Data.Binary
@@ -16,18 +17,19 @@ import Message
-- In practice, we maintain extra state, but that state is state
-- accumulated during a turn or relevant only to the current session.
data State = State
- { splayer :: Player,
- slook :: Maybe (Loc, Target, LevelName), -- ^ cursor, new target, return level, if in look mode
- shistory :: [Message],
- ssensory :: SensoryMode,
- sdisplay :: DisplayMode,
- stime :: Time,
- sassocs :: Assocs, -- ^ how does every item appear
- sdiscoveries :: Discoveries, -- ^ items (types) have been discovered
- sdungeon :: Dungeon, -- ^ all but current dungeon level
- slevel :: Level,
- sconfig :: Config.CP
- }
+ { splayer :: Player, -- ^ the selected hero
+ slook :: Maybe (Loc, Target, LevelName),
+ -- ^ cursor, new target, initial level
+ shistory :: [Message],
+ ssensory :: SensoryMode,
+ sdisplay :: DisplayMode,
+ stime :: Time,
+ sassocs :: Assocs, -- ^ how every item appears
+ sdiscoveries :: Discoveries, -- ^ items (types) that have been discovered
+ sdungeon :: Dungeon, -- ^ all but the current dungeon level
+ slevel :: Level,
+ sconfig :: Config.CP
+ }
deriving Show
defaultState :: Loc -> Dungeon -> Level -> State
@@ -47,6 +49,11 @@ defaultState ploc dng lvl =
updatePlayer :: (Monster -> Monster) -> State -> State
updatePlayer f s = s { splayer = f (splayer s) }
+levelPlayerList :: State -> [Player]
+levelPlayerList (State { splayer = player,
+ slevel = Level { lplayers = pls } }) =
+ player : IM.elems pls
+
updateHistory :: ([String] -> [String]) -> State -> State
updateHistory f s = s { shistory = f (shistory s) }
Please sign in to comment.
Something went wrong with that request. Please try again.