diff options
author | Griffin Smith <root@gws.fyi> | 2019-11-30T03·59-0500 |
---|---|---|
committer | Griffin Smith <root@gws.fyi> | 2019-11-30T03·59-0500 |
commit | 8a1235c3dcf7fe69b2e2ea3eea326858d26d38b9 (patch) | |
tree | 398c6dce549602c9890fbded64e3bdf2646b2a1f /src/Xanthous/Game | |
parent | 7d8ce026a2acc5a4d208110750be188f0ce5591c (diff) |
Use menus for combat and picking up items
Refactor a bunch of stuff around to allow for polymorphically surfacing an EntityChar for all entities, and use this to write a generic `entityMenu` function, which generates a menu from the chars of a list of entities - and use that to fully implement (removing `undefined`) menus for both attacking and picking things up when there are multiple entities on the relevant tile.
Diffstat (limited to 'src/Xanthous/Game')
-rw-r--r-- | src/Xanthous/Game/Arbitrary.hs | 4 | ||||
-rw-r--r-- | src/Xanthous/Game/Draw.hs | 2 | ||||
-rw-r--r-- | src/Xanthous/Game/Lenses.hs | 8 | ||||
-rw-r--r-- | src/Xanthous/Game/Prompt.hs | 9 | ||||
-rw-r--r-- | src/Xanthous/Game/State.hs | 85 |
5 files changed, 98 insertions, 10 deletions
diff --git a/src/Xanthous/Game/Arbitrary.hs b/src/Xanthous/Game/Arbitrary.hs index e8f9ae22c461..090eba634d4b 100644 --- a/src/Xanthous/Game/Arbitrary.hs +++ b/src/Xanthous/Game/Arbitrary.hs @@ -18,11 +18,11 @@ import qualified Xanthous.Data.EntityMap as EntityMap instance Arbitrary GameState where arbitrary = do - char <- arbitrary @Character + chr <- arbitrary @Character charPos <- arbitrary _messageHistory <- arbitrary (_characterEntityID, _entities) <- arbitrary <&> - EntityMap.insertAtReturningID charPos (SomeEntity char) + EntityMap.insertAtReturningID charPos (SomeEntity chr) _revealedPositions <- fmap setFromList . sublistOf $ EntityMap.positions _entities _randomGen <- mkStdGen <$> arbitrary let _promptState = NoPrompt -- TODO diff --git a/src/Xanthous/Game/Draw.hs b/src/Xanthous/Game/Draw.hs index 2f7ccf29f795..ab0e31f8a04a 100644 --- a/src/Xanthous/Game/Draw.hs +++ b/src/Xanthous/Game/Draw.hs @@ -12,7 +12,7 @@ import Brick.Widgets.Edit import Xanthous.Data import Xanthous.Data.EntityMap (EntityMap, atPosition) import qualified Xanthous.Data.EntityMap as EntityMap -import Xanthous.Entities +import Xanthous.Game.State import Xanthous.Entities.Character import Xanthous.Game ( GameState(..) diff --git a/src/Xanthous/Game/Lenses.hs b/src/Xanthous/Game/Lenses.hs index cd7148442ace..7dbd60290144 100644 --- a/src/Xanthous/Game/Lenses.hs +++ b/src/Xanthous/Game/Lenses.hs @@ -37,11 +37,11 @@ getInitialState = initialStateFromSeed <$> getRandom initialStateFromSeed :: Int -> GameState initialStateFromSeed seed = let _randomGen = mkStdGen seed - char = mkCharacter + chr = mkCharacter (_characterEntityID, _entities) = EntityMap.insertAtReturningID (Position 0 0) - (SomeEntity char) + (SomeEntity chr) mempty _messageHistory = mempty _revealedPositions = mempty @@ -56,10 +56,10 @@ positionedCharacter :: Lens' GameState (Positioned Character) positionedCharacter = lens getPositionedCharacter setPositionedCharacter where setPositionedCharacter :: GameState -> Positioned Character -> GameState - setPositionedCharacter game char + setPositionedCharacter game chr = game & entities . at (game ^. characterEntityID) - ?~ fmap SomeEntity char + ?~ fmap SomeEntity chr getPositionedCharacter :: GameState -> Positioned Character getPositionedCharacter game diff --git a/src/Xanthous/Game/Prompt.hs b/src/Xanthous/Game/Prompt.hs index 6c3629f31055..8e9ec04ccb33 100644 --- a/src/Xanthous/Game/Prompt.hs +++ b/src/Xanthous/Game/Prompt.hs @@ -1,6 +1,8 @@ +{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE GADTs #-} +{-# LANGUAGE DeriveFunctor #-} -------------------------------------------------------------------------------- module Xanthous.Game.Prompt ( PromptType(..) @@ -25,6 +27,7 @@ import Xanthous.Prelude import Brick.Widgets.Edit (Editor, editorText, getEditContents) import Test.QuickCheck import Test.QuickCheck.Arbitrary.Generic +import Control.Comonad -------------------------------------------------------------------------------- import Xanthous.Util (smallestNotIn) import Xanthous.Data (Direction, Position) @@ -159,9 +162,13 @@ instance CoArbitrary (PromptState ('Menu a)) where deriving stock instance Show (PromptState pt) data MenuOption a = MenuOption Text a - deriving stock (Eq, Generic) + deriving stock (Eq, Generic, Functor) deriving anyclass (NFData, CoArbitrary, Function) +instance Comonad MenuOption where + extract (MenuOption _ x) = x + extend cok mo@(MenuOption text _) = MenuOption text (cok mo) + mkMenuItems :: (MonoFoldable f, Element f ~ (Char, MenuOption a)) => f -> Map Char (MenuOption a) diff --git a/src/Xanthous/Game/State.hs b/src/Xanthous/Game/State.hs index 92c68a3f65c0..16d93c61bae6 100644 --- a/src/Xanthous/Game/State.hs +++ b/src/Xanthous/Game/State.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE GADTs #-} @@ -36,6 +37,13 @@ module Xanthous.Game.State , downcastEntity , _SomeEntity , entityIs + , DrawRawChar(..) + , DrawRawCharPriority(..) + , DrawCharacter(..) + , DrawStyledCharacter(..) + -- ** Field classes + , HasChar(..) + , HasStyle(..) -- * Debug State , DebugState(..) @@ -55,13 +63,18 @@ import Test.QuickCheck.Arbitrary.Generic import Control.Monad.State.Class import Control.Monad.State import Control.Monad.Random.Class -import Brick (EventM, Widget) +import Brick (EventM, Widget, raw, str) import Data.Aeson (ToJSON(..), FromJSON(..), Value(Null)) import qualified Data.Aeson as JSON import Data.Aeson.Generic.DerivingVia +import Data.Generics.Product.Fields +import qualified Graphics.Vty.Attributes as Vty +import qualified Graphics.Vty.Image as Vty +import Control.Comonad -------------------------------------------------------------------------------- -import Xanthous.Data.EntityMap (EntityMap, EntityID) import Xanthous.Data +import Xanthous.Data.EntityMap (EntityMap, EntityID) +import Xanthous.Data.EntityChar import Xanthous.Orphans () import Xanthous.Game.Prompt import Xanthous.Resource @@ -181,6 +194,73 @@ instance Draw a => Draw (Positioned a) where drawWithNeighbors ns (Positioned _ a) = drawWithNeighbors ns a draw (Positioned _ a) = draw a +newtype DrawCharacter (char :: Symbol) (a :: Type) where + DrawCharacter :: a -> DrawCharacter char a + +instance KnownSymbol char => Draw (DrawCharacter char a) where + draw _ = str $ symbolVal @char Proxy + +data Color = Black | Red | Green | Yellow | Blue | Magenta | Cyan | White + +class KnownColor (color :: Color) where + colorVal :: forall proxy. proxy color -> Vty.Color + +instance KnownColor 'Black where colorVal _ = Vty.black +instance KnownColor 'Red where colorVal _ = Vty.red +instance KnownColor 'Green where colorVal _ = Vty.green +instance KnownColor 'Yellow where colorVal _ = Vty.yellow +instance KnownColor 'Blue where colorVal _ = Vty.blue +instance KnownColor 'Magenta where colorVal _ = Vty.magenta +instance KnownColor 'Cyan where colorVal _ = Vty.cyan +instance KnownColor 'White where colorVal _ = Vty.white + +newtype DrawStyledCharacter (fg :: Color) (bg :: Color) (char :: Symbol) (a :: Type) where + DrawStyledCharacter :: a -> DrawStyledCharacter fg bg char a + +instance + ( KnownColor fg + , KnownColor bg + , KnownSymbol char + ) + => Draw (DrawStyledCharacter fg bg char a) where + draw _ = raw $ Vty.string attr $ symbolVal @char Proxy + where attr = Vty.Attr + { Vty.attrStyle = Vty.Default + , Vty.attrForeColor = Vty.SetTo $ colorVal @fg Proxy + , Vty.attrBackColor = Vty.SetTo $ colorVal @bg Proxy + , Vty.attrURL = Vty.Default + } + +instance Draw EntityChar where + draw EntityChar{..} = raw $ Vty.string _style [_char] + +-------------------------------------------------------------------------------- + +newtype DrawRawChar (rawField :: Symbol) (a :: Type) = DrawRawChar a + +instance + forall rawField a raw. + ( HasField rawField a a raw raw + , HasChar raw EntityChar + ) => Draw (DrawRawChar rawField a) where + draw (DrawRawChar e) = draw $ e ^. field @rawField . char + +newtype DrawRawCharPriority + (rawField :: Symbol) + (priority :: Nat) + (a :: Type) + = DrawRawCharPriority a + +instance + forall rawField priority a raw. + ( HasField rawField a a raw raw + , KnownNat priority + , HasChar raw EntityChar + ) => Draw (DrawRawCharPriority rawField priority a) where + draw (DrawRawCharPriority e) = draw $ e ^. field @rawField . char + drawPriority = const . fromIntegral $ natVal @priority Proxy + + -------------------------------------------------------------------------------- class Brain a where @@ -208,6 +288,7 @@ class ( Show a, Eq a, NFData a ) => Entity a where blocksVision :: a -> Bool description :: a -> Text + entityChar :: a -> EntityChar data SomeEntity where SomeEntity :: forall a. (Entity a, Typeable a) => a -> SomeEntity |