{- | Contains base datatypes that cannot be seperated into different modules because they are interdependent; circular imports are probably not a good idea. -} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE DeriveGeneric #-} module Dodge.Data ( module Dodge.Data , module Dodge.Distortion.Data , module Dodge.Data.DamageType , module Dodge.Data.SoundOrigin , module Dodge.Creature.State.Data , module Dodge.Creature.Stance.Data , module Dodge.Creature.Perception.Data , module Dodge.Creature.Memory.Data , module Dodge.Item.Attachment.Data , module Dodge.Item.Data , module Dodge.Config.Data ) where import Dodge.Creature.State.Data import Dodge.Creature.Stance.Data import Dodge.Creature.Perception.Data import Dodge.Creature.Memory.Data import Dodge.Distortion.Data import Dodge.Data.SoundOrigin import Dodge.Data.DamageType import Dodge.Config.Data import Dodge.Config.KeyConfig import Dodge.Item.Attachment.Data import Dodge.Item.Data import Dodge.Bounds import Data.Preload import Picture.Data import ShapePicture import Geometry.Data import Sound.Data import Dodge.GameRoom import Color import Shape import GHC.Generics import Control.Lens import System.Random import Data.Graph.Inductive import qualified Data.Set as S import qualified Data.IntSet as IS import qualified Data.IntMap.Strict as IM import qualified Data.Map.Strict as M import SDL (Scancode, MouseButton) import Data.Monoid type CRUpdate = Creature -> World -> (Endo World, Maybe Creature) data World = World { _keys :: !(S.Set Scancode) , _mouseButtons :: !(S.Set MouseButton) , _cameraCenter :: !Point2 , _cameraRot :: !Float , _cameraZoom :: !Float , _cameraViewFrom :: !Point2 , _creatures :: IM.IntMap Creature , _creaturesZone :: Zone (IM.IntMap Creature) , _creatureGroups :: IM.IntMap CrGroupParams , _itemPositions :: IM.IntMap ItemPos , _clouds :: [Cloud] , _cloudsZone :: Zone [Cloud] , _props :: IM.IntMap Prop , _instantParticles :: [Particle] , _particles :: ![Particle] , _walls :: !(IM.IntMap Wall) , _doors :: IM.IntMap Door , _machines :: IM.IntMap Machine , _blocks :: IM.IntMap Block , _coordinates :: IM.IntMap Point2 , _triggers :: IM.IntMap (World -> Bool) , _wallsZone :: Zone (IM.IntMap Wall) , _floorItems :: IM.IntMap FloorItem , _floorTiles :: [(Point3,Point3)] , _randGen :: StdGen , _mousePos :: !Point2 , _testString :: World -> [String] , _modifications :: IM.IntMap Modification , _yourID :: !Int , _worldEvents :: World -> World , _pressPlates :: IM.IntMap PressPlate , _buttons :: IM.IntMap Button , _toPlaySounds :: M.Map SoundOrigin Sound , _playingSounds :: M.Map SoundOrigin Sound , _decorations :: IM.IntMap Picture , _foregroundShape :: Shape , _corpses :: Zone [Corpse] , _clickMousePos :: !Point2 , _pathGraph :: ~(Gr Point2 Float) , _pathGraphP :: ~[(Point2,Point2)] , _pathPoints :: ~(IM.IntMap (IM.IntMap [(Int,Point2)])) , _menuLayers :: [ScreenLayer] , _worldFlags :: S.Set WorldFlag , _carteDisplay :: !Bool , _carteCenter :: !Point2 , _carteZoom :: !Float , _carteRot :: !Float , _lightSources :: !(IM.IntMap LightSource) , _tempLightSources :: ![TempLightSource] , _closeActiveObjects :: [Either FloorItem Button] , _seenLocations :: IM.IntMap (World -> Point2,String) , _selLocation :: Int , _sideEffects :: World -> IO World , _inventoryMode :: InventoryMode , _lClickHammer :: HammerPosition , _distortions :: [Distortion] , _worldBounds :: Bounds , _gameRooms :: [GameRoom] , _keyConfig :: KeyConfigSDL , _config :: Configuration , _preloadData :: PreloadData , _savedWorlds :: M.Map SaveSlot World , _frameClock :: Int } data SaveSlot = QuicksaveSlot | LevelStartSlot deriving (Eq,Ord) data OptionScreenFlag = NormalOptions | GameOverOptions data ScreenLayer = OptionScreen { _scTitle :: World -> String , _scOptions :: [MenuOption] , _scDefaultEff :: World -> Maybe World , _scOptionFlag :: OptionScreenFlag } | ColumnsScreen String [(String,String)] | InputScreen String | TerminalScreen Int [(Int,String)] | WaitScreen { _scWaitMessage :: World -> String , _scWaitTime :: Int } | DisplayScreen { _scDisplay :: World -> Picture } data MenuOption = Toggle { _moKey :: Scancode , _moEff :: World -> Maybe World , _moString :: World -> String } | Toggle2 { _moKey1 :: Scancode , _moEff1 :: World -> Maybe World , _moKey2 :: Scancode , _moEff2 :: World -> Maybe World , _moString :: World -> String } | InvisibleToggle { _moKey :: Scancode , _moEff :: World -> Maybe World } data InventoryMode = TopInventory | TweakInventory | CombineInventory | InspectInventory | LockedInventory deriving (Eq, Ord, Show) data CrGroupParams = CrGroupParams { _crGroupParamID :: Int , _crGroupIDs :: IS.IntSet , _crGroupCenter :: Point2 , _crGroupUpdate :: World -> CrGroupParams -> Maybe CrGroupParams } data Corpse = Corpse { _cpPos :: Point2 , _cpPict :: Picture , _cpRes :: Creature } data Cloud = Cloud { _clPos :: Point3 , _clVel :: Point3 , _clPict :: Cloud -> Picture , _clRad :: Float , _clAlt :: Float , _clTimer :: Int , _clType :: CloudType , _clEffect :: Cloud -> World -> World } data CloudType = SmokeCloud | GasCloud data LightSource = LS { _lsID :: !Int , _lsPos :: !Point3 , _lsDir :: !Float , _lsRad :: !Float , _lsIntensity :: !Point3 , _lsPict :: LightSource -> Picture } data TempLightSource = TLS { _tlsPos :: !Point3 , _tlsRad :: !Float , _tlsIntensity :: !Point3 , _tlsUpdate :: World -> TempLightSource -> Maybe TempLightSource , _tlsTime :: !Int } data Creature = Creature { _crPos :: Point2 , _crOldPos :: Point2 , _crVel :: Point2 , _crDir :: Float , _crOldDir :: Float , _crMvDir :: Float , _crID :: Int , _crPict :: Creature -> World -> SPic , _crUpdate :: Creature -> World -> (Endo World, Maybe Creature) , _crRad :: Float , _crMass :: Float , _crHP :: Int , _crMaxHP :: Int , _crInv :: IM.IntMap Item , _crInvSel :: Int , _crLeftInvSel :: Maybe Int , _crState :: CreatureState , _crCorpse :: Picture , _crApplyDamage :: [DamageType] -> Creature -> (World -> World,Creature) , _crStance :: Stance , _crActionPlan :: ActionPlan , _crMeleeCooldown :: !Int , _crPerception :: PerceptionState , _crMemory :: MemoryState , _crVocalization :: Vocalization , _crFaction :: Faction , _crGroup :: CrGroup , _crIntention :: Intention , _crMvType :: CrMvType } data Vocalization = Mute | Vocalization {_vcSound :: SoundID ,_vcMaxCoolDown :: Int ,_vcCoolDown :: Int } data Intention = Intention { _targetCr :: Maybe Creature , _mvToPoint :: Maybe Point2 , _viewPoint :: Maybe Point2 } data CrMvType = NoMvType | MvWalking { _mvSpeed :: Float } | ChaseMvType { _mvSpeed :: Float , _mvTurnRad :: Float -> Float , _mvTurnJit :: Float } | AimMvType { _mvSpeed :: Float , _mvTurnRad :: Float -> Float , _mvTurnJit :: Float , _mvAimSpeed :: Float -> Float } data WorldFlag = ResetLevel Int | GameOver deriving (Eq,Ord) data Button = Button { _btPict :: Button -> SPic , _btPos :: Point2 , _btRot :: Float , _btEvent :: Button -> World -> World , _btID :: Int , _btText :: String , _btState :: ButtonState } data ButtonState = BtOn | BtOff | BtNoLabel deriving (Eq, Show) data PressPlate = PressPlate { _ppPict :: Picture , _ppPos :: Point2 , _ppRot :: Float , _ppEvent :: PressPlate -> World -> World , _ppID :: Int , _ppText :: String } data FloorItem = FlIt { _flIt :: Item , _flItPos :: Point2 , _flItRot :: Float, _flItID :: Int} data ItemPos = InInv { _itCrId :: Int , _itInvId :: Int } | OnFloor { _itFlID :: Int } data Item = Weapon { _itName :: String , _wpMaxAmmo :: Int , _wpLoadedAmmo :: Int , _wpAmmo :: Ammo , _wpReloadTime :: Int , _wpReloadState :: Int , _wpReloadType :: ReloadType , _wpMaxWarmUp :: Int , _wpCurWarmUp :: Int , _wpMaxCoolDown :: Int , _wpCurCoolDown :: Int , _itUseRate :: Int , _itUseTime :: Int , _itUse :: Item -> Creature -> World -> World , _itUseModifiers :: [(Item -> Creature -> World -> World) -> Item -> Creature -> World -> World] , _itLeftClickUse :: Maybe (Creature -> Int -> World -> World) , _wpSpread :: Float , _wpRange :: Float , _itHammer :: HammerPosition , _itFloorPict :: Item -> SPic , _itAimingSpeed :: Float , _itAimingRange :: Float , _itZoom :: ItZoom , _itAimZoom :: ItZoom , _itEquipPict :: Creature -> Int -> SPic , _itScroll :: Float -> Creature -> Item -> Item , _itIdentity :: ItemIdentity , _itAttachment :: ItAttachment , _itID :: Maybe Int , _itEffect :: ItEffect , _itInvDisplay :: Item -> String , _itInvColor :: Color , _itTargeting :: Maybe (World -> Maybe Point2, Int -> Item -> Creature -> World -> Picture) , _itWorldTrigger :: Maybe (Int -> World -> Bool) , _itAimStance :: AimStance , _wpNumBarrels :: Int , _itDimension :: ItemDimension , _itCurseStatus :: CurseStatus } | Consumable { _itName :: String , _itMaxStack :: Int , _itAmount :: Int , _cnEffect :: Int -> World -> Maybe World , _itFloorPict :: Item -> SPic , _itEquipPict :: Creature -> Int -> SPic , _itIdentity :: ItemIdentity , _itID :: Maybe Int , _itInvDisplay :: Item -> String , _itInvColor :: Color , _itEffect :: ItEffect , _itHammer :: HammerPosition , _itAimStance :: AimStance , _itCurseStatus :: CurseStatus } | Craftable { _itName :: String , _itMaxStack :: Int , _itAmount :: Int , _itFloorPict :: Item -> SPic , _itEquipPict :: Creature -> Int -> SPic , _itIdentity :: ItemIdentity , _itID :: Maybe Int , _itInvDisplay :: Item -> String , _itInvColor :: Color , _itAimStance :: AimStance , _itCurseStatus :: CurseStatus } | Equipment { _itName :: String , _itFloorPict :: Item -> SPic , _itEquipPict :: Creature -> Int -> SPic , _itIdentity :: ItemIdentity , _itEffect :: ItEffect , _itID :: Maybe Int , _itAimingSpeed :: Float , _itAimingRange :: Float , _itZoom :: ItZoom , _itAimZoom :: ItZoom , _itInvDisplay :: Item -> String , _itInvColor :: Color , _itHammer :: HammerPosition , _itAimStance :: AimStance , _itCurseStatus :: CurseStatus } | Throwable { _itName :: String , _itMaxStack :: Int , _itAmount :: Int , _itFloorPict :: Item -> SPic , _twMaxRange :: Float , _twAccuracy :: Float , _itUse :: Item -> Creature -> World -> World , _itUseRate :: Int , _itUseTime :: Int , _itUseModifiers :: [(Item -> Creature -> World -> World) -> Item -> Creature -> World -> World] , _itAimingSpeed :: Float , _itAimingRange :: Float , _itZoom :: ItZoom , _itAimZoom :: ItZoom , _itEquipPict :: Creature -> Int -> SPic , _itIdentity :: ItemIdentity , _itID :: Maybe Int , _itAttachment :: ItAttachment , _itInvDisplay :: Item -> String , _itInvColor :: Color , _itEffect :: ItEffect , _itHammer :: HammerPosition , _itScroll :: Float -> Creature -> Item -> Item , _itAimStance :: AimStance , _itCurseStatus :: CurseStatus } | NoItem data CurseStatus = Uncursed | UndroppableIdentified | UndroppableUnidentified data ItemDimension = ItemDimension { _itDim :: Point3 -- length width height , _itHandle :: Point3 , _itCenter :: Point3 , _muzzleLength :: Float } data ReloadType = ActiveReload | PassiveReload SoundID data ItEffect = NoItEffect | ItInvEffect {_itInvEffect :: ItEffect -> Creature -> Int -> World -> World -- the Int is the items inventory position ,_itEffectCounter :: Int } | ItEffect {_itInvEffect :: ItEffect -> Creature -> Int -> World -> World ,_itFloorEffect :: Int -> World -> World ,_itEffectCounter :: Int } | ItInvEffectID {_itInvEffect :: ItEffect -> Creature -> Int -> World -> World -- the Int is the items inventory position ,_itEffectID :: Maybe Int } data ItZoom = ItZoom { _itZoomMax :: Float , _itZoomMin :: Float , _itZoomFac :: Float } data IntID a = IntID Int a {- Objects without ids. Update themselves, perhaps with side effects. -} data Particle = Particle { _ptDraw :: Particle -> Picture , _ptUpdate :: World -> Particle -> (World, Maybe Particle) } | LinearParticle { _ptDraw :: Particle -> Picture , _ptUpdate :: World -> Particle -> (World, Maybe Particle) , _ptPoints :: [Point2] , _ptTimer :: Int , _ptColor :: Color } | BulletPt { _ptDraw :: Particle -> Picture , _ptUpdate :: World -> Particle -> (World, Maybe Particle) , _btVel' :: Point2 , _btColor' :: Color , _btTrail' :: [Point2] , _btPassThrough' :: Maybe Int , _btWidth' :: Float , _btTimer' :: Int , _btHitEffect' :: HitEffect } | PtZ { _ptDraw :: Particle -> Picture , _ptUpdate :: World -> Particle -> (World, Maybe Particle) , _btVel' :: Point2 , _btColor' :: Color , _btPos' :: Point2 , _btPassThrough' :: Maybe Int , _btWidth' :: Float , _btTimer' :: Int , _btHitEffect' :: HitEffect , _ptZ :: Float } | Shockwave' { _ptDraw :: Particle -> Picture , _ptUpdate :: World -> Particle -> (World, Maybe Particle) , _btColor' :: Color , _btPos' :: Point2 , _btRad' :: Float , _btDam' :: Int , _btPush' :: Float , _btMaxTime' :: Int , _btTimer' :: Int } type HitEffect = Particle -> [(Point2, Either Creature Wall)] -> World -> (World,Maybe Particle) data Ammo = ShellAmmo { _amPayload :: Point2 -> World -> World , _amString :: String , _amPjParams :: [PjParam] , _amPjDraw :: Prop -> SPic , _amParamSel :: Int } | BulletAmmo { _amString :: String , _amBulEff :: HitEffect , _amBulWth :: Float , _amBulVel :: Point2 } | GenericAmmo data PjParam = PjParam { _pjMoveParam :: Int -> Item -> Creature -> Prop -> World -> World , _pjIntParam :: Int , _pjMaxParam :: Int , _pjDisplayParam :: Int -> String } data Modification = ModIDTimerPoint3Bool { _mdID :: Int , _mdExternalID :: Int , _mdUpdate :: Modification -> World -> World , _mdTimer :: Int , _mdPoint3 :: Point3 , _mdBool :: Bool } data Prop = Projectile { _pjPos :: Point2 , _pjStartPos :: Point2 , _pjVel :: Point2 , _prDraw :: Prop -> SPic , _pjID :: Int , _pjUpdate :: Prop -> World -> World } | RecursiveProp { _pjPos :: Point2 , _pjID :: Int , _pjDraw :: Prop -> SPic , _pjUpdate :: Prop -> World -> World , _pjProp :: Prop } | ProjectileTimed { _pjPos :: Point2 , _pjStartPos :: Point2 , _pjVel :: Point2 , _prDraw :: Prop -> SPic , _pjID :: Int , _pjUpdate :: Prop -> World -> World , _pjTime :: Int } | ShapeProp { _pjPos :: Point2 , _pjID :: Int , _pjRot :: Float , _pjUpdate :: Prop -> World -> World , _prDraw :: Prop -> SPic , _prToggle :: Bool } | Shell { _pjPos :: Point2 , _pjStartPos :: Point2 , _pjVel :: Point2 , _pjAcc :: Point2 , _pjDir :: Float , _pjSpin :: Float , _prDraw :: Prop -> SPic , _pjID :: Int , _pjUpdate :: Prop -> World -> World , _pjPayload :: Point2 -> World -> World , _pjTimer :: Int , _pjZ :: Float } | Bomb { _pjPos :: Point2 , _pjVel :: Point2 , _pjZ :: Float , _pjVelZ :: Float , _prDraw :: Prop -> SPic , _pjID :: Int , _pjUpdate :: Prop -> World -> World , _pjPayload :: Point2 -> World -> World , _pjTimer :: Int } | LinearShockwave { _prDraw :: Prop -> SPic , _pjPos :: Point2 , _pjID :: Int , _pjUpdate :: Prop -> World -> World , _pjPoints :: [(Point2,Point2)] , _pjTimer :: Int } data Either3 a b c = E3x1 a | E3x2 b | E3x3 c data Block = Block { _blID :: Int , _blWallIDs :: IS.IntSet , _blHPs :: [Int] , _blShadows :: [Int] , _blMaterial :: BlockMaterial } data BlockMaterial = WoodBlock | DirtBlock | StoneBlock | GlassBlock | MetalBlock data Machine = Machine { _mcID :: Int , _mcWallIDs :: IS.IntSet , _mcUpdate :: Machine -> World -> World , _mcDraw :: Machine -> SPic , _mcPos :: Point2 , _mcDir :: Float , _mcHP :: Int , _mcSensor :: Int , _mcDamage :: [DamageType] , _mcLSs :: [Int] , _mcType :: MachineType } data MachineType = StaticMachine | Turret { _tuWeapon :: Item , _tuTurnSpeed :: Float , _tuFireTime :: Int } data Door = Door { _drID :: Int , _drWallIDs :: IS.IntSet , _drStatus :: DoorStatus , _drTrigger :: World -> Bool , _drMech :: Door -> World -> World } data DoorStatus = DoorOpen | DoorClosed | DoorHalfway | DoorInt Int deriving (Eq, Ord, Show) data Wall = Wall { _wlLine :: (Point2,Point2) , _wlID :: Int , _wlColor :: Color , _wlSeen :: Bool , _wlOpacity :: Opacity , _wlPathable :: Bool , _wlWalkable :: Bool , _wlFireThrough :: Bool , _wlReflect :: Bool , _wlDraw :: Bool , _wlRotateTo :: Bool , _wlStructure :: WallStructure } data Opacity = SeeThrough | SeeAbove | Opaque deriving (Eq,Ord,Show) data WallStructure = StandaloneWall | DoorPart { _wlStDoor :: Int } | MachinePart { _wlStMachine :: Int } | BlockPart { _wlStBlock :: Int } | CreaturePart { _wlStCreature :: Int , _wlStDamCreature :: DamageType -> Wall -> Int -> World -> World } -- | Strict maybe data Maybe' a = Just' a | Nothing' data ActionPlan = Inanimate | ActionPlan {_crImpulse :: [Impulse] ,_crAction :: [Action] ,_crStrategy :: Strategy ,_crGoal :: [Goal] } data Impulse = Move Point2 | MoveForward Float | Turn Float | RandomTurn Float | TurnToward Point2 Float | MvTurnToward Point2 | MvForward | TurnTo Point2 | UseItem | SwitchToItem Int | DropItem -- | PickupNearby Int -- | UseWorldObject Int | Bark SoundID -- placeholder for various communication types -- | UseIntrinsicAbility | Melee Int | ChangePosture Posture | MakeSound SoundID | ChangeStrategy Strategy | AddGoal Goal | ArbitraryImpulseFunction (World -> Creature -> Creature) | ArbitraryImpulse (Creature -> World -> Impulse) | ImpulseUseTargetCID {_impulseUseTargetCID :: Int -> Impulse } | ImpulseUseTarget {_impulseUseTarget :: Creature -> Impulse } | ImpulseUseAheadPos {_impulseUseAheadPos :: Point2 -> Impulse } -- deriving (Eq,Ord,Show) infixr 9 `WaitThen` infixr 9 `DoActionThen` infixr 9 `DoActionWhile` infixr 9 `DoReplicate` infixr 9 `DoImpulsesAlongside` data Action = AimAt {_targetID :: Int ,_targetSeenAt :: Point2 } | PathTo {_pathToPoint :: Point2 } | TurnToA {_turnToAPoint :: Point2 } -- | PickupItem -- {_pickupItemID :: Int -- } | ImpulsesList {_impulsesListList :: [[Impulse]] } | DoImpulses {_doImpulsesList :: [Impulse] } | WaitThen {_waitThenTimer :: Int ,_waitThenAction :: Action } | DoActionWhile {_doActionWhileCondition :: (World, Creature) -> Bool ,_doActionWhileAction :: Action } | DoActionWhilePartial {_doActionWhilePartial :: Action ,_doActionWhileCondition :: (World, Creature) -> Bool ,_doActionWhileAction :: Action } | DoActionIf {_doActionIfCondition :: (World, Creature) -> Bool ,_doActionIfAction :: Action } | DoActionIfElse {_doActionIfElseIfAction :: Action ,_doActionIfElseCondition :: (World, Creature) -> Bool ,_doActionIfElseElseAction :: Action } | DoActionWhileInterrupt {_doActionWhileThenDo :: Action ,_doActionWhileThenCondition :: (World, Creature) -> Bool ,_doActionWhileThenThen :: Action } | DoActions {_doActionsList :: [Action] } | DoActionThen {_doActionThenFirst :: Action ,_doActionThenSecond :: Action } -- | DoGuardActions -- {_doGuardActionsList :: [( (World, Creature) -> Bool, Action, Maybe Action)] -- } | DoReplicate {_doReplicateTimes :: Int ,_doReplicateAction :: Action } | DoReplicatePartial {_partialAction :: Action ,_doReplicateTimes :: Int ,_doReplicateAction :: Action } | LeadTarget {_leadTargetBy :: Point2 } | NoAction | StartSentinelPost | UseTarget {_useTarget :: Maybe Creature -> Action } | UseSelf {_useSelf :: Creature -> Action } | UseAheadPos {_useAheadPos :: Point2 -> Action } | UseMvTargetPos {_useMvTargetPos :: Maybe Point2 -> Action } | ArbitraryAction { _arbitraryAction :: Creature -> World -> Action } | DoImpulsesAlongside -- ^ Repeatedly perform impulses alongside a main action until the main action terminates {_sideImpulses :: [Impulse] ,_mainAction :: Action } deriving (Generic) -- deriving (Eq,Ord,Show) data Strategy = Flank Int | Ambush Int | Lure Int Point2 | Patrol [Point2] | ShootAt Int | FollowImpulses | WatchAndWait | StrategyActions Strategy [Action] | GetTo Point2 | Reload | Flee | MeleeStrike deriving (Generic) -- deriving (Eq,Ord,Show) data Goal = LiveLongAndProsper | Kill Int | SentinelAt Point2 Float newtype Zone a = Zone { _znObjects :: IM.IntMap (IM.IntMap a) } makeLenses ''World makeLenses ''Cloud makeLenses ''Creature makeLenses ''LightSource makeLenses ''TempLightSource makeLenses ''Item makeLenses ''ItemPos makeLenses ''ItEffect makeLenses ''ItZoom makeLenses ''FloorItem makeLenses ''Ammo makeLenses ''PjParam makeLenses ''Prop makeLenses ''Modification makeLenses ''Particle makeLenses ''Wall makeLenses ''WallStructure makeLenses ''PressPlate makeLenses ''Button makeLenses ''ActionPlan makeLenses ''Impulse makeLenses ''Action makeLenses ''CrGroupParams makeLenses ''CrMvType makeLenses ''Intention makeLenses ''Door makeLenses ''Block makeLenses ''Machine makeLenses ''MachineType makeLenses ''Zone makeLenses ''ItemDimension makeLenses ''Vocalization