packages feed

apecs-roaring-1.0: README.md

# 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))
```