Permalink
Browse files

blind monsters don't see, but can smell; even under player domination

  • Loading branch information...
1 parent f9d3c84 commit f799aa1107d9e15ec22e7dc29b3cc95776369056 @Mikolaj Mikolaj committed Mar 29, 2011
Showing with 30 additions and 20 deletions.
  1. +4 −3 src/Actions.hs
  2. +1 −1 src/Display.hs
  3. +12 −10 src/EffectAction.hs
  4. +3 −1 src/FOV.hs
  5. +6 −3 src/Perception.hs
  6. +4 −2 src/Turn.hs
View
@@ -337,11 +337,12 @@ lvlChange vdir =
else do
-- Remove the player from the old level.
modify (deleteActor pl)
- -- At this place the invariant that player exists fails.
- -- Change to the new level (invariant not essential).
+ -- At this place the invariant that the player exists fails.
+ -- Change to the new level (invariant not needed).
assertTrue $ lvlSwitch nln
- -- Restore the invariant: add player to the new level.
+ -- Add the player to the new level.
modify (insertActor pl pbody)
+ -- At this place the invariant is restored again.
-- Land the player at the other end of the stairs.
updatePlayerBody (\ p -> p { mloc = nloc })
-- Change the level of the player recorded in cursor.
View
@@ -154,7 +154,7 @@ displayLevel
| n > 9 = '*'
| n < 0 = '-'
| otherwise = Char.intToDigit n
- rainbow loc = toEnum (1 + snd loc `mod` 14)
+ rainbow loc = toEnum ((fst loc + snd loc) `mod` 14 + 1)
(char, fg) =
case L.find (\ m -> loc == mloc m) (hs ++ ms) of
_ | sTer > 0 -> Terrain.viewTerrain sTer False (tterrain tile)
View
@@ -158,6 +158,11 @@ selectPlayer actor =
modify (updateCursor (\ c -> c { creturnLn = nln }))
-- Switch to the level.
lvlSwitch nln
+ -- Set smell display, depending on player capabilities.
+ -- This also reset FOV mode.
+ modify (\ s -> s { ssensory = if MovableKind.nsmell (mkind pbody)
+ then Smell
+ else Implicit })
-- Announce.
messageAdd $ subjectMovable (mkind pbody) ++ " selected."
return True
@@ -199,17 +204,14 @@ checkPartyDeath =
then gameOver go
else case L.filter (\ (actor, _) -> actor /= pl) ahs of
[] -> gameOver go
- (actor, nln) : _ -> do
- -- Important invariant: player always has to exist somewhere.
- -- Make the new actor the player-controlled actor.
- modify (\ s -> s { splayer = actor })
- -- Record the original level of the new player.
- modify (updateCursor (\ c -> c { creturnLn = nln }))
- -- Now the old player can be safely removed.
- modify (deleteActor pl)
- -- Now we can switch to the level of the new player.
- lvlSwitch nln
+ (actor, _nln) : _ -> do
message "The survivors carry on."
+ -- Remove the dead player.
+ modify (deleteActor pl)
+ -- At this place the invariant that the player exists fails.
+ -- Focus on the new hero (invariant not needed).
+ assertTrue $ selectPlayer actor
+ -- At this place the invariant is restored again.
-- | End game, showing the ending screens, if requested.
gameOver :: Bool -> Action ()
View
@@ -14,7 +14,7 @@ import FOV.Shadow
import Geometry
import Level
-data FovMode = Shadow | Permissive Int | Digital Int
+data FovMode = Shadow | Permissive Int | Digital Int | Blind
-- Three Field of View algorithms. Press 'V' to cycle among them in the game.
@@ -44,3 +44,5 @@ fullscan fovMode loc lmap =
(((B(0, 1), B(r, -r)), [B(0, 0)]),
((B(0, 0), B(r, r+1)), [B(0, 1)])))
[qtr0,qtr1,qtr2,qtr3]
+ Blind -> -- only feeling out adjacent tiles by touch
+ S.empty
View
@@ -11,6 +11,7 @@ import State
import Level
import Movable
import MovableState
+import qualified MovableKind
import FOV
import qualified Config
@@ -62,7 +63,7 @@ perception_ state@(State { splayer = pl,
ssensory = sensory }) =
let mode = Config.get config "engine" "fovMode"
radius = Config.get config "engine" "fovRadius"
- fovMode =
+ fovMode m = if not $ MovableKind.nsight (mkind m) then Blind else
-- terrible, temporary hack
case sensory of
Vision 3 -> Digital radius
@@ -78,9 +79,10 @@ perception_ state@(State { splayer = pl,
-- Perception for a player-controlled monster on the current level.
pper = if isAMonster pl && memActor pl state
- then Just $ perception fovMode (mloc (getPlayerBody state)) lmap
+ then let m = getPlayerBody state
+ in Just $ perception (fovMode m) (mloc m) lmap
else Nothing
- pers = IM.map (\ h -> perception fovMode (mloc h) lmap) hs
+ pers = IM.map (\ h -> perception (fovMode h) (mloc h) lmap) hs
lpers = maybeToList pper ++ IM.elems pers
reachable = S.unions (L.map preachable lpers)
visible = S.unions (L.map pvisible lpers)
@@ -134,4 +136,5 @@ perception fovMode ploc lmap =
in
case fovMode of
Shadow -> Perception reachable visible
+ Blind -> Perception reachable visible
_ -> Perception reachable simpleVisible
View
@@ -158,11 +158,13 @@ handlePlayer =
then withPerception handlePlayer -- no time taken, repeat
else do
state <- get
+ pl <- gets splayer
let time = stime state
ploc = mloc (getPlayerBody state)
- smellTimeout = Config.get (sconfig state) "monsters" "smellTimeout"
+ sTimeout = Config.get (sconfig state) "monsters" "smellTimeout"
-- update smell
- modify (updateLevel (updateSMap (M.insert ploc (time + smellTimeout))))
+ when (isAHero pl) $ -- only humans leave strong scent
+ modify (updateLevel (updateSMap (M.insert ploc (time + sTimeout))))
-- determine player perception and continue with monster moves
withPerception handleMonsters

0 comments on commit f799aa1

Please sign in to comment.