Skip to content

Commit

Permalink
add combustion delay parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
byorgey committed Dec 30, 2024
1 parent c0075cf commit 42f0f24
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 21 deletions.
28 changes: 21 additions & 7 deletions data/scenarios/Testing/1355-combustion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ solution: |
ignite forward;
turn right;
move; move; move;
ignite left;
turn right;
move;
ignite left;
Expand Down Expand Up @@ -75,6 +76,18 @@ entities:
duration: [8, 8]
product: null
properties: [known, pickable, combustible]
- name: slowfuse
display:
attr: silver
char: '~'
description:
- Reliably combustible, but burns more slowly
combustion:
ignition: 20
duration: [64, 64]
delay: 63
product: null
properties: [known, pickable, combustible]
- name: dynamite
display:
attr: red
Expand Down Expand Up @@ -103,6 +116,7 @@ world:
'b': [grass, board]
'i': [grass, cotton]
'F': [grass, fuse]
'f': [grass, slowfuse]
'd': [grass, dynamite, judge]
'.': [grass]
upperleft: [0, 0]
Expand All @@ -123,11 +137,11 @@ world:
......iiiiiiii........F...F...F...F..
iiiiiiiiiiiiiii..Ω.FFFF...FFFFF...d..
......iiiiiiii.......................
iiiiiiiiiiiii.....qqqqqqqqqqqqqqqq...
......iiiiii......qqqqqqqqqqqqqqqq...
iiiiiiiiiii.......qqqqqqqqqqqqqqqq...
..................qqqqqqqqqqqqqqqq...
..................qqqqqqqqqqqqqqqq...
..................qqqqqqqqqqqqqqqq...
..................qqqqqqqqqqqqqqqq...
iiiiiiiiiiiii..f..qqqqqqqqqqqqqqqq...
......iiiiii...f..qqqqqqqqqqqqqqqq...
iiiiiiiiiii....f..qqqqqqqqqqqqqqqq...
...............f..qqqqqqqqqqqqqqqq...
..ffff...ffff..f..qqqqqqqqqqqqqqqq...
..f..f...f..f..f..qqqqqqqqqqqqqqqq...
..f..fffff..ffff..qqqqqqqqqqqqqqqq...
..................qqqqqqqqqqqqqqqq...
9 changes: 7 additions & 2 deletions data/schema/combustion.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,23 @@
"ignition": {
"default": 0.5,
"type": "number",
"description": "Rate of ignition by a neighbor, per tick."
"description": "Rate of ignition by a neighbor. This is the rate parameter of a Poisson distribution, i.e. the expected number of times per tick that a combusting neighbor would tend to ignite this entity. Typically a number between 0 and 1, but it can be any nonnegative real number (default: 0.5)."
},
"duration": {
"type": "array",
"default": [100, 200],
"$ref": "range.json",
"description": "For combustible entities, a 2-tuple of integers specifying the minimum and maximum amount of time that the combustion shall persist."
},
"delay": {
"type": "number",
"default": 0.0,
"description": "Warmup delay, i.e. the number of ticks combustion must persist until this entity will potentially start igniting its neighbors (default: 0)."
},
"product": {
"default": "ash",
"type": ["string", "null"],
"description": "What entity, if any, is left over after combustion"
"description": "What entity, if any, is left over after combustion."
}
}
}
32 changes: 22 additions & 10 deletions src/swarm-engine/Swarm/Game/Step/Combustion.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ igniteCommand c d = do
let selfCombustibility = (e ^. entityCombustion) ? defaultCombustibility
createdAt <- getNow
combustionDurationRand <- addCombustionBot e selfCombustibility createdAt loc
forM_ (getNeighborLocs loc) $ igniteNeighbor createdAt combustionDurationRand
let warmup = delay selfCombustibility
let neighborAffectDuration = max 0 (combustionDurationRand - warmup)
when (neighborAffectDuration > 0) $
forM_ (getNeighborLocs loc) $
igniteNeighbor createdAt warmup neighborAffectDuration
where
verb = "ignite"
verbed = "ignited"
Expand Down Expand Up @@ -117,7 +121,7 @@ addCombustionBot inputEntity combustibility ts loc = do
ts
return combustionDurationRand
where
Combustibility _ durationRange maybeCombustionProduct = combustibility
Combustibility _ durationRange _ maybeCombustionProduct = combustibility

-- | A system program for a "combustion robot", to burn an entity
-- after it is ignited.
Expand All @@ -141,7 +145,7 @@ addCombustionBot inputEntity combustibility ts loc = do
-- cells. This would avoid polluting the logic of the currently burning cell
-- with logic to manage probabilities of combustion propagation.
combustionProgram :: Integer -> Combustibility -> TSyntax
combustionProgram combustionDuration (Combustibility _ _ maybeCombustionProduct) =
combustionProgram combustionDuration (Combustibility _ _ _ maybeCombustionProduct) =
[tmQ|
wait $int:combustionDuration;
if ($int:invQuantity > 0) {
Expand All @@ -156,18 +160,25 @@ combustionProgram combustionDuration (Combustibility _ _ maybeCombustionProduct)
Nothing -> (0, "")
Just p -> (1, p)

-- | We treat the 'ignition' field in the 'Combustibility' record
-- as a /rate/ in a Poisson distribution.
-- Ignition of neighbors depends on that particular neighbor entity's
-- combustion /rate/, but also on the duration
-- that the current entity will burn.
-- | Possibly ignite a neighbor of a source entity that is combusting.
-- @creationTime@ is the time the source entity began to combust.
-- @warmup@ is the number of ticks of delay that the source entity
-- needs to burn before it will start affecting its neighbors;
-- @sourceDuration@ is the number of ticks that it will potentially
-- affect its neighbors.
--
-- We treat the 'ignition' field in the 'Combustibility' record as a
-- /rate/ in a Poisson distribution. Ignition of neighbors depends
-- on that particular neighbor entity's combustion /rate/, but also
-- on the @sourceDuration@ time that the current entity will burn.
igniteNeighbor ::
Has (State GameState) sig m =>
TimeSpec ->
Integer ->
Integer ->
Cosmic Location ->
m ()
igniteNeighbor creationTime sourceDuration loc = do
igniteNeighbor creationTime warmup sourceDuration loc = do
maybeEnt <- entityAt loc
forM_ maybeEnt igniteEntity
where
Expand All @@ -177,7 +188,8 @@ igniteNeighbor creationTime sourceDuration loc = do
when (probabilityOfIgnition >= threshold) $ do
ignitionDelayRand <- uniform (0, 1)
let ignitionDelay =
floor
(warmup +)
. floor
. min (fromIntegral sourceDuration)
. negate
$ log ignitionDelayRand / rate
Expand Down
15 changes: 13 additions & 2 deletions src/swarm-scenario/Swarm/Game/Entity.hs
Original file line number Diff line number Diff line change
Expand Up @@ -243,19 +243,30 @@ data Combustibility = Combustibility
-- See <https://math.stackexchange.com/a/1243629>.
, duration :: (Integer, Integer)
-- ^ min and max tick counts for combustion to persist
, delay :: Integer
-- ^ Delay until this entity may start igniting its neighbors.
, product :: Maybe EntityName
-- ^ what entity, if any, is left over after combustion
}
deriving (Eq, Ord, Show, Read, Generic, Hashable, FromJSON, ToJSON)
deriving (Eq, Ord, Show, Read, Generic, Hashable, ToJSON)

instance FromJSON Combustibility where
parseJSON = withObject "Combustibility" $ \v -> do
ignition <- v .: "ignition"
duration <- v .: "duration"
delay <- v .:? "delay" .!= 0
product <- v .: "product"

Check warning on line 258 in src/swarm-scenario/Swarm/Game/Entity.hs

View workflow job for this annotation

GitHub Actions / Haskell-CI - windows-latest - ghc-9.8.2

This binding for ‘product’ shadows the existing binding
pure Combustibility {..}

-- | The default combustion specification for a combustible entity
-- with no combustion specification:
--
-- * ignition rate 0.5
-- * duration (100, 200)
-- * delay of 0
-- * product @ash@
defaultCombustibility :: Combustibility
defaultCombustibility = Combustibility 0.5 (100, 200) (Just "ash")
defaultCombustibility = Combustibility 0.5 (100, 200) 0 (Just "ash")

------------------------------------------------------------
-- Entity
Expand Down

0 comments on commit 42f0f24

Please sign in to comment.