Skip to content

Commit

Permalink
spreadable plant growth (#1817)
Browse files Browse the repository at this point in the history
Closes #1533

# Demo
```
scripts/test/run-tests.sh --test-options '--pattern "sow"'
```
or
```
scripts/play.sh -i data/scenarios/Testing/1533-sow-command.yaml --autoplay
```
![Screenshot from 2024-05-03 19-12-08](https://github.com/swarm-game/swarm/assets/261693/52df7de4-c158-4973-b109-5337e38c35f1)

## Other changes

* Introduced the `ChildInheritance` type to specify how the `Display` attribute is inherited by built child robots.
* Introduce the `mature` property of `growth`.  For example, it doesn't make much sense to plant an `acorn` and call the resulting, fully-grown plant also an `acorn`.  Instead, an `acorn` matures into an `oak`.
  • Loading branch information
kostmo authored May 26, 2024
1 parent d9b639a commit 7a80355
Show file tree
Hide file tree
Showing 17 changed files with 549 additions and 45 deletions.
4 changes: 3 additions & 1 deletion data/scenarios/Testing/00-ORDER.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,6 @@ Achievements
1777-capability-cost.yaml
1775-custom-terrain.yaml
1642-biomes.yaml
1780-structure-merge-expansion
1780-structure-merge-expansion
1533-sow-command.yaml
1533-sow-seed-maturation.yaml
195 changes: 195 additions & 0 deletions data/scenarios/Testing/1533-sow-command.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
version: 1
name: Sow command and spread
seed: 0
description: |
Demonstrate `sow` command and spreading growth with biome restrictions.
Illustrates different rates of spread for different crops.
creative: false
attrs:
- name: clay
fg: "#444444"
bg: "#c2b280"
- name: wheat
fg: "#444444"
bg: "#F5DEB3"
- name: barley
fg: "#444444"
bg: "#F6E9B1"
- name: maize
fg: "#444444"
bg: "#FBEC5D"
- name: mint
bg: "#3EB489"
terrains:
- name: clay
attr: clay
description: |
Sandy soil
objectives:
- goal:
- |
Observe `kudzu`{=entity} spread
condition: |
r <- robotnamed "kudzubot";
as r {
kCount <- resonate "kudzu" ((0, 0), (10, 4));
return $ kCount >= 45;
}
solution: |
def doN = \n. \f. if (n > 0) {f; doN (n - 1) f} {}; end;
doN 6 move;
harvest;
doN 13 move;
turn right;
harvest;
doN 6 move;
sow "mint";
turn right;
doN 13 move;
sow "barley";
turn left;
doN 7 move;
sow "barley";
turn left;
doN 13 move;
sow "kudzu";
doN 6 move;
robots:
- name: base
dir: east
devices:
- branch predictor
- calculator
- comparator
- dictionary
- harvester
- logger
- seed spreader
- treads
inventory:
- [2, barley]
- [1, kudzu]
- [1, mint]
- name: kudzubot
dir: east
system: true
entities:
- name: wheat
display:
char: 'w'
attr: wheat
description:
- Grain
properties: [known, pickable, growable]
growth:
duration: [20, 30]
spread:
radius: 2
density: 0.3
biomes: [dirt, clay]
- name: barley
display:
char: 'b'
attr: barley
description:
- Grain
properties: [known, pickable, growable]
growth:
duration: [30, 50]
spread:
radius: 2
density: 0.3
biomes: [dirt, clay]
- name: corn
display:
char: 'c'
attr: maize
description:
- Animal feed
properties: [known, pickable, growable]
growth:
duration: [30, 60]
spread:
radius: 3
density: 0.1
biomes: [dirt, clay]
- name: kudzu
display:
char: 'k'
attr: plant
description:
- Dense, impassable plant.
properties: [known, unwalkable, growable]
growth:
duration: [30, 50]
spread:
radius: 1
density: 3
biomes: [dirt, clay]
- name: mint
display:
char: 'm'
attr: mint
description:
- Invasive
properties: [known, pickable, growable]
growth:
duration: [10, 50]
spread:
radius: 2
density: 0.6
biomes: [dirt, clay]
- name: seed spreader
display:
char: 's'
description:
- A handheld pouch with a manual crank to broadcast seeds evenly within a small radius
properties: [known]
capabilities: [sow]
known: [flower]
world:
default: [blank]
palette:
'.': [grass]
'B': [grass, null, base]
'd': [dirt]
'c': [clay]
'K': [clay, null, kudzubot]
'C': [dirt, corn]
'W': [clay, wheat]
upperleft: [-1, 1]
map: |
..........................
.ddddddddddd..ccccccccccc.
.ddddddddddd..ccccccccccc.
BdddddCddddd..cccccWccccc.
.ddddddddddd..ccccccccccc.
.ddddddddddd..ccccccccccc.
..........................
.ccccccccccc..ddddddddddd.
.ccccccccccc..ddddddddddd.
.ccccccccccc..ddddddddddd.
.ccccccccccc..ddddddddddd.
.ccccccccccc..ddddddddddd.
..........................
..........................
.ddddddddddd..ccccccccccc.
.ddddddddddd..ccccccccccc.
.ddddddddddd..ccccccccccc.
.ddddddddddd..ccccccccccc.
.ddddddddddd..Kcccccccccc.
..........................
..........................
..........................
.ccccccccccc..ddddddddddd.
.ccccccccccc..ddddddddddd.
.ccccccccccc..ddddddddddd.
.ccccccccccc..ddddddddddd.
.ccccccccccc..ddddddddddd.
..........................
101 changes: 101 additions & 0 deletions data/scenarios/Testing/1533-sow-seed-maturation.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
version: 1
name: Seed maturation
description: |
A seed grows into a different entity, which again
yields the original seed when harvested.
The 'mature' sub-property of the 'growth' property
facilitates the distinction between seeds and the
entities those seeds produce. For example, it doesn't make much sense
to plant an `acorn`{=entity} and call the resulting,
fully-grown plant also an `acorn`{=entity}.
In combination with 'yields', it
effectively precludes the grown entity (as it exists in the world)
from entering into the player's inventory.
creative: false
objectives:
- id: plant_acorn
goal:
- |
Plant an `acorn`{=entity}
condition: |
as base {
x <- has "acorn";
return $ not x;
}
- goal:
- |
Go to the `oak`{=entity}
condition: |
as base {
ishere "oak";
}
- goal:
- |
Pick another `acorn`{=entity}
prerequisite: plant_acorn
condition: |
as base {
has "acorn";
}
solution: |
sow "acorn";
move;
watch back;
turn back;
wait 1000;
move;
harvest;
robots:
- name: base
dir: east
devices:
- branch predictor
- calculator
- comparator
- dictionary
- harvester
- logger
- rolex
- scanner
- seed spreader
- treads
inventory:
- [1, acorn]
entities:
- name: acorn
display:
char: 'a'
description:
- Seed of an `oak`{=entity}
properties: [known, pickable, growable]
growth:
duration: [200, 300]
mature: oak
- name: oak
display:
char: 'k'
description:
- Grows from an `acorn`{=entity}
properties: [known, pickable, growable]
growth:
duration: [200, 300]
yields: acorn
- name: seed spreader
display:
char: 's'
description:
- A handheld pouch with a manual crank to broadcast seeds evenly within a small radius
properties: [known]
capabilities: [sow]
world:
default: [blank]
palette:
'.': [grass]
'B': [grass, null, base]
upperleft: [-2, 2]
map: |
.....
..B..
.....
5 changes: 5 additions & 0 deletions data/schema/display.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@
"default": false,
"type": "boolean",
"description": "Whether the entity or robot should be invisible. Invisible entities and robots are not drawn, but can still be interacted with in otherwise normal ways. System robots are by default invisible."
},
"inheritable": {
"default": true,
"type": "boolean",
"description": "Whether robot children inherit this display."
}
}
}
42 changes: 34 additions & 8 deletions data/schema/entity.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,44 @@
},
"growth": {
"default": null,
"type": "array",
"items": [

"oneOf": [
{
"name": "minimum",
"type": "number"
"$ref": "range.json",
"description": "For growable entities, a 2-tuple of integers specifying the minimum and maximum amount of time taken for one growth stage. The actual time for one growth stage will be chosen uniformly at random from this range; it takes two growth stages for an entity to be fully grown."
},
{
"name": "maximum",
"type": "number"
"type": "object",
"additionalProperties": false,
"properties": {
"mature": {
"default": null,
"type": "string",
"description": "The entity that will grow from the entity planted with the `sow` command."
},
"spread": {
"default": null,
"type": "object",
"additionalProperties": false,
"properties": {
"radius": {
"default": 1,
"type": "number",
"description": "Manhattan distance within which the entity may spread"
},
"density": {
"default": 0,
"type": "number",
"description": "Density within the range to seed"
}
}
},
"duration": {
"$ref": "range.json"
}
}
}
],
"description": "For growable entities, a 2-tuple of integers specifying the minimum and maximum amount of time taken for one growth stage. The actual time for one growth stage will be chosen uniformly at random from this range; it takes two growth stages for an entity to be fully grown."
]
},
"combustion": {
"type": "object",
Expand Down
1 change: 1 addition & 0 deletions editors/emacs/swarm-mode.el
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"turn"
"grab"
"harvest"
"sow"
"ignite"
"place"
"ping"
Expand Down
2 changes: 1 addition & 1 deletion editors/vim/swarm.vim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
syn keyword Keyword def end let in require
syn keyword Builtins self parent base if inl inr case fst snd force undefined fail not format chars split charat tochar key
syn keyword Command noop wait selfdestruct move backup volume path push stride turn grab harvest ignite place ping give equip unequip make has equipped count drill use build salvage reprogram say listen log view appear create halt time scout whereami waypoint structure floorplan hastag tagmembers detect resonate density sniff chirp watch surveil heading blocked scan upload ishere isempty meet meetall whoami setname random run return try swap atomic instant installkeyhandler teleport as robotnamed robotnumbered knows
syn keyword Command noop wait selfdestruct move backup volume path push stride turn grab harvest sow ignite place ping give equip unequip make has equipped count drill use build salvage reprogram say listen log view appear create halt time scout whereami waypoint structure floorplan hastag tagmembers detect resonate density sniff chirp watch surveil heading blocked scan upload ishere isempty meet meetall whoami setname random run return try swap atomic instant installkeyhandler teleport as robotnamed robotnumbered knows
syn keyword Direction east north west south down forward left back right
syn keyword Type int text dir bool cmd void unit actor

Expand Down
2 changes: 1 addition & 1 deletion editors/vscode/syntaxes/swarm.tmLanguage.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
},
{
"name": "keyword.other",
"match": "\\b(?i)(self|parent|base|if|inl|inr|case|fst|snd|force|undefined|fail|not|format|chars|split|charat|tochar|key|noop|wait|selfdestruct|move|backup|volume|path|push|stride|turn|grab|harvest|ignite|place|ping|give|equip|unequip|make|has|equipped|count|drill|use|build|salvage|reprogram|say|listen|log|view|appear|create|halt|time|scout|whereami|waypoint|structure|floorplan|hastag|tagmembers|detect|resonate|density|sniff|chirp|watch|surveil|heading|blocked|scan|upload|ishere|isempty|meet|meetall|whoami|setname|random|run|return|try|swap|atomic|instant|installkeyhandler|teleport|as|robotnamed|robotnumbered|knows)\\b"
"match": "\\b(?i)(self|parent|base|if|inl|inr|case|fst|snd|force|undefined|fail|not|format|chars|split|charat|tochar|key|noop|wait|selfdestruct|move|backup|volume|path|push|stride|turn|grab|harvest|sow|ignite|place|ping|give|equip|unequip|make|has|equipped|count|drill|use|build|salvage|reprogram|say|listen|log|view|appear|create|halt|time|scout|whereami|waypoint|structure|floorplan|hastag|tagmembers|detect|resonate|density|sniff|chirp|watch|surveil|heading|blocked|scan|upload|ishere|isempty|meet|meetall|whoami|setname|random|run|return|try|swap|atomic|instant|installkeyhandler|teleport|as|robotnamed|robotnumbered|knows)\\b"
}
]
},
Expand Down
Loading

0 comments on commit 7a80355

Please sign in to comment.