Skip to content

Component tags and sums#147

Open
dpwiz wants to merge 10 commits intojonascarpay:masterfrom
dpwiz:component-tags
Open

Component tags and sums#147
dpwiz wants to merge 10 commits intojonascarpay:masterfrom
dpwiz:component-tags

Conversation

@dpwiz
Copy link
Collaborator

@dpwiz dpwiz commented Mar 10, 2026

This allows types like Map Entity (Map WorldTag WorldSum) and IntMap (IntMap a) for #146

The story so far (an excerpt from my patched shmup used to

type WorldComps = [''Position, ''Velocity, ''Player, ''Target, ''Bullet, ''Score, ''Time, ''Particle, ''Camera]

-- vanilla makeWorld
makeWorld "World" WorldComps

-- new tagged stuff generators
makeTaggedComponents "World" WorldComps -- same component list (requires it to be defined elsewhere, or a fused generator)

{- generated:

data WorldTag = TPosition | TVelocity | ...
  deriving (Eq, Ord, Show, Enum, Bounded)

data WorldSum
  = SPosition Position
  | SVelocity Velocity
  | ...
  deriving (Show)

tagWorldSum :: WorldSum -> WorldTag -- don't like the name

type instance WTag World = WorldTag

instance Monad m => HasTags World m where
  entityTags = getWorldTags
-}

-- all live entities (already in main)
worldEntityIds :: System World IS.IntSet
worldEntityIds = do
  s :: Storage WorldEnumerable <- getStore
  explMemberSet s

-- count your archetypes
census :: System World (M.Map (S.Set WorldTag) Int)
census = do
  live <- worldEntityIds -- using raw intset
  countCombinations live -- new helper that 

-- alternatives:
-- [WorldSum] -- the wrapper is its own tag (a forgetting map is available)
-- Maybify WorldEnumerable -- type fun to quickly hack (A, B, ...) into (Maybe A, Maybe B, ...)
-- making a record of maybe fields (HKD much?)
type Dump = M.Map WorldTag WorldSum

dump :: Entity -> System World Dump
dump e = do
  tags <- entityTags e -- check explExists
  fmap M.fromList . forM tags $ \t -> (t,) <$> getWorldTag e t -- unsafe get over every found tag

type Megadump = M.Map Entity Dump

-- dump literally every thing in the world
megadump :: System World Megadump
megadump = do
  live <- map Entity . IS.toList <$> worldEntityIds
  fmap M.fromList . forM live $ \e -> fmap (e,) $ dump e

-- dump only some specific entities
dumpPlayer :: System World Megadump
dumpPlayer = do
  players <- collect (\(Player, ety) -> Just ety)
  fmap M.fromList . forM players $ \e -> fmap (e,) $ dump e

step dT = do
  ...
  triggerEvery dT 3 0 $ census >>= liftIO . print
  triggerEvery dT 5 0 $ dumpPlayer >>= liftIO . print
  triggerEvery dT 7 0 $ megadump >>= liftIO . print

google-labs-jules bot and others added 10 commits March 10, 2026 11:30
Added `makeComponentTags` in `Apecs.TH` to fold component types into an enum of tags as requested.
It takes a string for the enum name and a list of component types, and generates a data declaration where the constructors are the component names prefixed with `T`.
Also added the generation test to the `WorldEnumerable` scenario in `apecs/test/Main.hs`.

Co-authored-by: dpwiz <486682+dpwiz@users.noreply.github.com>
Co-authored-by: dpwiz <486682+dpwiz@users.noreply.github.com>
Also clean up some of the tag/sum mess.

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Extra utilities to collect and introspect "everything".

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
…#11)

Co-authored-by: dpwiz <486682+dpwiz@users.noreply.github.com>
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
…Components`

Generates a function that counts how many entities have each enumerable
component type, returning `[(tag, Int)]`. Filters by `ExplMembers` so
Global/ReadOnly stores are excluded.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…etypes

A plain utility function (not TH-generated) that takes a member set and
a tag-getter function, groups entities by their tag combination using
IntSet as a compact intermediate, and returns Map (Set tag) Int.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Follows the same pattern as `Has w m c` — the world type `w` dispatches
to the tag system generated by `makeTaggedComponents`. This enables
generic utilities that work in `SystemT w m` without naming world-specific
types like `getWorldTags`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract `WTag` as a standalone type family and add `m` parameter to
`HasTags w m`, mirroring the existing `Has w m c` pattern. This allows
`HasTags` to work with apecs-stm (STM) or pure test monads instead of
being hardcoded to IO.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
@dpwiz dpwiz marked this pull request as ready for review March 16, 2026 19:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant