# apecs-roaring
[apecs](https://github.com/jonascarpay/apecs) stores for flag-like components and bitmap joins, backed by [CRoaring](https://github.com/RoaringBitmap/CRoaring) 64-bit bitmaps.
See the [benchmark results](https://dpwiz.gitlab.io/apecs-roaring) for how they compare with `Map` and `Cache` (tldr: counting, filtering, saving space on large-ish collections).
## Usage
```haskell
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
import Apecs (Cache, Component (..), Map, cfold, makeWorld, newEntity_, runWith)
import Apecs.Stores.Flags (Flags)
import Apecs.Stores.Roaring (Roaring)
import GHC.Generics (Generic)
data Enemy = Enemy deriving (Generic)
instance Component Enemy where
type Storage Enemy = Flags Enemy
data Dead = Dead deriving (Generic)
instance Component Dead where
type Storage Dead = Flags Dead
newtype Health = Health Int
instance Component Health where
type Storage Health = Roaring (Cache 1024 (Map Health))
makeWorld "World" [''Enemy, ''Dead, ''Health]
main :: IO ()
main = do
world <- initWorld
totalHealth <- runWith world $ do
newEntity_ (Enemy, Health 30)
newEntity_ (Enemy, Health 10, Dead)
newEntity_ $ Health 50
cfold (\total (Health health) -> total + health) 0
print totalHealth
```
`Query.count` from `Apecs.Stores.Query` reads a store's size off its bitmap without visiting any entity:
```haskell
enemies <- Query.count @Enemy
```
`Every` from the same module joins a tuple by intersecting bitmaps, subtracting any `Not` terms, and `Query.count` sizes the join without listing it:
```haskell
cmap $ \(Every (Enemy, Health health, _ :: Not Dead)) -> Health $ health - 1
livingEnemies <- Query.count @(Every (Enemy, Not Dead))
```