Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

unify strategy targetting for heroes and for traitor monsters

  • Loading branch information...
commit 4c364f8755ee353e42c46bd136e47641f01c5c2f 1 parent 6a595a9
@Mikolaj Mikolaj authored
View
2  src/Actions.hs
@@ -445,7 +445,7 @@ targetMonster = do
AHero _ -> ms
(lt, gt) = IM.split i dms
gtlt = IM.assocs gt ++ IM.assocs lt
- lf = L.filter (\ (_, m) -> actorSeesLoc pl (mloc m) per pl) gtlt
+ lf = L.filter (\ (_, m) -> actorSeesLoc pl (mloc m) per (Just pl)) gtlt
tgt = case lf of
[] -> target -- no monsters in sight, stick to last target
(ni, nm) : _ -> TEnemy (AMonster ni) (mloc nm) -- pick the next
View
2  src/ItemAction.hs
@@ -110,7 +110,7 @@ zapGroupItem groupName verb = do
Nothing -> abortWith "target invalid"
Just loc ->
-- TODO: draw digital line and see if obstacles prevent firing
- if actorReachesLoc pl loc per pl
+ if actorReachesLoc pl loc per (Just pl)
then case locToActor loc state of
Just ta -> do
b <- itemEffectAction consumed pl ta
View
10 src/Perception.hs
@@ -32,7 +32,7 @@ ptreachable = preachable . ptotal
ptvisible = pvisible . ptotal
actorPrLoc :: (Perception -> S.Set Loc) ->
- Actor -> Loc -> Perceptions -> Actor -> Bool
+ Actor -> Loc -> Perceptions -> Maybe Actor -> Bool
actorPrLoc projection actor loc per pl =
let tryHero = case actor of
AMonster _ -> Nothing
@@ -40,18 +40,20 @@ actorPrLoc projection actor loc per pl =
hper <- IM.lookup i (pheroes per)
return $ loc `S.member` (projection hper)
tryPl = do -- the case for a monster under player control
- guard $ actor == pl
+ guard $ Just actor == pl
pper <- pplayer per
return $ loc `S.member` projection pper
tryAny = tryHero `mplus` tryPl
in fromMaybe False tryAny -- assume not visible, if no perception found
-actorSeesLoc, actorReachesLoc :: Actor -> Loc -> Perceptions -> Actor -> Bool
+actorSeesLoc :: Actor -> Loc -> Perceptions -> Maybe Actor -> Bool
actorSeesLoc = actorPrLoc pvisible
+
+actorReachesLoc :: Actor -> Loc -> Perceptions -> Maybe Actor -> Bool
actorReachesLoc = actorPrLoc preachable
-- Not quite correct if FOV not symmetric (Shadow).
-actorReachesActor :: Actor -> Actor -> Loc -> Loc -> Perceptions -> Actor
+actorReachesActor :: Actor -> Actor -> Loc -> Loc -> Perceptions -> Maybe Actor
-> Bool
actorReachesActor actor1 actor2 loc1 loc2 per pl =
actorReachesLoc actor1 loc2 per pl ||
View
37 src/StrategyState.hs
@@ -33,46 +33,46 @@ strategy actor
per =
strategy
where
- -- TODO: set monster targets and then prefer targets to other heroes
Movable { mkind = mk, mloc = me, mdir = mdir, mtarget = tgt } =
getActor actor oldState
delState = deleteActor actor oldState
- -- If the player is a monster, monsters spot and attack him when adjacent.
- ploc = if isAHero pl || creturnLn cursor /= ln
- then Nothing
- else Just $ mloc $ getPlayerBody delState
- onlyTraitor = onlyMoves (maybe (const False) (==) ploc) me
+ enemyVisible a l =
+ -- We assume monster sight is infravision, so light has no significance.
+ actorReachesActor a actor l me per Nothing ||
+ -- Any enemy is visible if adjacent (e. g., a monster player).
+ memActor a delState && adjacent me l
-- If no heroes on the level, monsters go at each other. TODO: let them
-- earn XP by killing each other to make this dangerous to the player.
hs = L.map (\ (i, m) -> (AHero i, mloc m)) $
IM.assocs $ lheroes $ slevel delState
ms = L.map (\ (i, m) -> (AMonster i, mloc m)) $
IM.assocs $ lmonsters $ slevel delState
- -- Below, "foe" is the hero (or a monster, or loc), followed by the actor.
+ -- Below, "foe" is the hero (or a monster, or loc) chased by the actor.
(newTgt, floc) =
case tgt of
TEnemy a ll | focusedMonster ->
case findActorAnyLevel a delState of
Just (_, m) ->
let l = mloc m
- in -- We assume monster sight is infravision.
- if actorReachesActor a actor l me per pl
+ in if enemyVisible a l
then (TEnemy a l, Just l)
else if isJust (snd closest) || me == ll
- then closest -- prefer visible enemies
+ then closest -- prefer visible foes
else (tgt, Just ll) -- last known location of enemy
- Nothing -> closest -- enemy dead
+ Nothing -> closest -- enemy dead, monsters can feel it
TLoc loc -> if me == loc
then closest
else (tgt, Just loc) -- ignore everything and go to loc
_ -> closest
closest =
- let foes = if L.null hs then ms else hs
+ let hsAndTraitor = if isAMonster pl
+ then (pl, mloc $ getPlayerBody delState) : hs
+ else hs
+ foes = if L.null hsAndTraitor then ms else hsAndTraitor
-- We assume monster sight is infravision, so light has no effect.
foeVisible =
- L.filter (\ (a, l) -> actorReachesActor a actor l me per pl) foes
+ L.filter (\ (a, l) -> enemyVisible a l) foes
foeDist = L.map (\ (a, l) -> (distance (me, l), l, a)) foeVisible
- -- Below, "foe" is the hero (or a monster) at floc, attacked by the actor.
in case foeDist of
[] -> (TCursor, Nothing)
_ -> let (_, l, a) = L.minimum foeDist
@@ -101,15 +101,14 @@ strategy actor
L.sortBy (\ (_, s1) (_, s2) -> compare s2 s1) $
L.filter (\ (_, s) -> s > 0) $
L.map (\ x -> (x, nsmap ! (me `shift` x) - time `max` 0)) moves
- fromDir d = dirToAction actor newTgt `liftM` onlySensible d
+ fromDir d = dirToAction actor newTgt `liftM` d
strategy =
- fromDir (onlyTraitor moveFreely) -- traitor has priority
- .| fromDir (onlyFoe moveFreely)
+ fromDir (onlyFoe moveFreely)
.| (greedyMonster && lootHere me) .=> actionPickup
- .| fromDir moveTowards
+ .| fromDir (onlySensible moveTowards)
.| lootHere me .=> actionPickup
- .| fromDir moveAround
+ .| fromDir (onlySensible moveAround)
actionPickup = return $ actorPickupItem actor
moveTowards =
(if pushyMonster then id else onlyUnoccupied) $
Please sign in to comment.
Something went wrong with that request. Please try again.