{-# LANGUAGE GADTs #-}

-- |
-- SPDX-License-Identifier: BSD-3-Clause
--
-- Utilities for working with procedurally generated worlds.
module Swarm.Game.World.Gen where

import Data.Semigroup (Last (..))
import Data.Set qualified as S
import Swarm.Game.Entity
import Swarm.Game.World.Syntax (CellVal (..))
import Swarm.Game.World.Typecheck (Const (CCell), TTerm (..))
import Swarm.Util.Erasable

type Seed = Int

-- | Extract a list of all entities mentioned in a given world DSL term.
extractEntities :: TTerm g a -> S.Set Entity
extractEntities :: forall (g :: [*]) a. TTerm g a -> Set Entity
extractEntities (TLam TTerm (ty1 : g) ty2
t) = TTerm (ty1 : g) ty2 -> Set Entity
forall (g :: [*]) a. TTerm g a -> Set Entity
extractEntities TTerm (ty1 : g) ty2
t
extractEntities (TApp TTerm g (a1 -> a)
t1 TTerm g a1
t2) = TTerm g (a1 -> a) -> Set Entity
forall (g :: [*]) a. TTerm g a -> Set Entity
extractEntities TTerm g (a1 -> a)
t1 Set Entity -> Set Entity -> Set Entity
forall a. Semigroup a => a -> a -> a
<> TTerm g a1 -> Set Entity
forall (g :: [*]) a. TTerm g a -> Set Entity
extractEntities TTerm g a1
t2
extractEntities (TConst (CCell (CellVal TerrainType
_ Erasable (Last Entity)
ee [TRobot]
_))) = Erasable (Last Entity) -> Set Entity
forall {a}. Erasable (Last a) -> Set a
getEntity Erasable (Last Entity)
ee
 where
  getEntity :: Erasable (Last a) -> Set a
getEntity (EJust (Last a
e)) = a -> Set a
forall a. a -> Set a
S.singleton a
e
  getEntity Erasable (Last a)
_ = Set a
forall a. Set a
S.empty
extractEntities TTerm g a
_ = Set Entity
forall a. Set a
S.empty