Commit Graph

1175 Commits

Author SHA1 Message Date
Karl Ostmo
e8ea33927b
Implement 'backup' command (#1400)
Closes #1399.

## Demo

    scripts/play.sh --scenario data/scenarios/Testing/1399-backup-command.yaml --autoplay
2023-08-01 19:43:46 +00:00
Brent Yorgey
2d67a229d7
Continue parsing the rest of the scenarios in a directory when one fails (#1391)
The problem was that we loaded an entire directory with `mapM loadScenarioItem` which caused the entire directory to fail if any single scenario did.  Now we run each individual `loadScenarioItem` call with `runExceptT` and appropriately collect up the individual failures together with any warnings from the successfully loaded scenarios.  

Fixes #1380.
2023-07-24 22:29:17 +00:00
Karl Ostmo
b7cdff076f
Automatic re-orientation via portal (#1390)
Closes #1379

Related: #950

Also moves "directions" types/logic into its own module.

## Demo

    scripts/play.sh --scenario data/scenarios/Testing/1379-single-world-portal-reorientation.yaml --autoplay
2023-07-24 20:28:00 +00:00
Karl Ostmo
f9c22635b5
subworlds (#1353)
Closes #144.

This builds upon portals support (#1356)

# Demo

    scripts/play.sh --scenario data/scenarios/Testing/144-subworlds/subworld-mapped-robots.yaml --autoplay --speed 2

[![asciicast](https://asciinema.org/a/vC13dW8M1S8t2b1J4XkW80U1q.svg)](https://asciinema.org/a/vC13dW8M1S8t2b1J4XkW80U1q)

# Future work
* Augment portal definitions with an optional "relative orientation" attribute, that can turn the player around when passing through the portal (#1379)
* Specify whether portal performs instant transportation or whether `move down` is required (#1368)
2023-07-22 20:29:22 +00:00
Brent Yorgey
d1a8242e5a
Highlight ticks per frame in red when it reaches the cap (#1386)
Closes #1348.
2023-07-20 18:14:06 +00:00
Noah Yorgey
6c5ca42114
Update about to 2023 (#1384) 2023-07-20 13:04:56 +00:00
Brent Yorgey
720387501f
Load persistent state from disk only once and reuse for all integration tests (#1383)
This seems to make a big difference --- the integration test suite now takes only about 35% as long as it used to. Fixes #1279.
2023-07-20 00:17:17 +00:00
Noah Yorgey
56b0935691
Change binding on Hide REPL to M-, (#1375)
Fixes #1325.
2023-07-19 15:52:38 +00:00
Karl Ostmo
4491f10764
Use robotMap directly instead of addRobot (#1378)
Closes #1372
2023-07-18 16:57:57 +00:00
Karl Ostmo
485e6ace1f
Fourmolu fixup (#1326)
Switch to `fourmolu-0.13` and reformat all source code.
2023-07-12 18:00:23 +00:00
Karl Ostmo
8548e4f296
merge fixup (#1367)
See https://github.com/swarm-game/swarm/pull/1356#issuecomment-1631768381
2023-07-12 14:48:50 +00:00
Karl Ostmo
cfb1e92666
waypoints and portals (#1356) 2023-07-11 18:58:32 -07:00
Brent Yorgey
7f53d9061d
Update to support GHC 9.6, mtl-2.3, and bump upper bounds (#1363)
Support GHC 9.6 / `base-4.18`, `mtl-2.3`, `megaparsec-9.4`, `servant-0.20`, `servant-docs-0.13`, `servant-server-0.20`, `template-haskell-2.20`, `optparse-applicative-0.18`, fix a bunch of new warnings, and update CI to test on GHC 9.6. 

---------

Co-authored-by: restyled-io[bot] <32688539+restyled-io[bot]@users.noreply.github.com>
Co-authored-by: Restyled.io <commits@restyled.io>
2023-07-11 19:05:14 -05:00
Karl Ostmo
7daa64b9c3
better JSON direction representation (#1359) 2023-07-11 14:55:46 +00:00
Karl Ostmo
a30b6ed0c9
planar direction sum type (#1358)
Simplifies some existing and planned code.
2023-07-10 15:15:34 +00:00
Brent Yorgey
6a7063bec0
Update to LTS-21, GHC 9.4.5, brick-1.9 (#1351)
[Stackage LTS 21](https://www.stackage.org/blog/2023/06/announce-lts-21-nightly-ghc9.6) was just released, which is great news for us because it includes GHC 9.4.5 (GHC 9.4.4 was no longer supported by HLS) and we no longer have to rely on a specific "nightly" version.  This PR updates a few things to build with LTS-21.

The biggest thing I *didn't* update was our `lsp` dependency: LTS-21 comes with `lsp-2.0` and `lsp-types-2.0`, but those apparently introduce some breaking changes and it wasn't immediately apparent to me what would need to change.  I filed https://github.com/swarm-game/swarm/issues/1350 to track that issue.
2023-06-26 17:51:52 +00:00
Karl Ostmo
f1b0b09f14
powerset scenario (#1342)
![image](https://github.com/swarm-game/swarm/assets/261693/cb8c7b90-7af3-47bb-8bfc-06197a997c38)

    scripts/play.sh --scenario data/scenarios/Challenges/Ranching/powerset.yaml --autoplay
2023-06-25 21:21:52 +00:00
Karl Ostmo
e8a77d6017
goal dialog suppression with --autoplay (#1344)
Closes #1340.

Compare:

    scripts/play.sh --scenario data/scenarios/Challenges/blender.yaml --run data/scenarios/Challenges/_blender/solution.sw

vs.

    scripts/play.sh --scenario data/scenarios/Challenges/blender.yaml --autoplay
2023-06-25 21:05:05 +00:00
Karl Ostmo
31c4844d6e
rename inventory to compendium (#1346)
![Screenshot from 2023-06-25 00-12-37](https://github.com/swarm-game/swarm/assets/261693/2e03a7b9-aa43-4a3b-bec0-16eb35c30fc8)

Closes #1139
2023-06-25 16:54:20 +00:00
Karl Ostmo
8c318c2a8e
Separate entities for each text operation (#1339)
Closes #1239

The `string` device maintains all four of the split capabilities for backwards compatibility.
2023-06-24 17:53:37 +00:00
Karl Ostmo
8bc105b13d
arbitrage scenario (#1192)
![image](https://github.com/swarm-game/swarm/assets/261693/cc6d555f-8c84-474b-a8b4-47632f78f7da)

    scripts/play.sh --scenario data/scenarios/Challenges/arbitrage.yaml --autoplay
2023-06-24 04:41:44 +00:00
Karl Ostmo
3bbbd88261
scenario with enemies (#971)
Uses the `meet` command to simulate a "hitbox" for enemy encounters.

Closes #1146

![image](https://github.com/swarm-game/swarm/assets/261693/200b5f33-c848-4fa5-b6aa-ef5a5d0616aa)
2023-06-22 04:22:43 +00:00
Karl Ostmo
c43dca066a
canonical device for 'scout' command (#1337)
Supplements #1207
2023-06-20 22:17:07 +00:00
Karl Ostmo
30e6bd67ad
sliding puzzle (#1237)
Note: I put some effort toward a completely general, automated solution, but eventually just reduced the board size to 3x3 and solved it manually, and used the API to obtain the manual commands to paste into the solution:

    curl http://localhost:5357/repl/history/full | jq .[].in -r

The board generator is generalized to any square dimension, but some scaffolding must be built to re-use the code across multiple scenarios.  The new `Sliding Puzzles` directory is intended to contain a 3x3, 4x4, and 5x5 puzzle, but currently only contains 3x3.

### 3x3 board
![image](https://github.com/swarm-game/swarm/assets/261693/babf3dbb-2d89-4c1e-a452-be8f61077180)

### 4x4 demo
![board](https://user-images.githubusercontent.com/261693/235421110-db0de5ce-8a25-482f-8a61-f42f5b469761.png)

## Demo

    scripts/play.sh --scenario "data/scenarios/Challenges/Sliding Puzzles/3x3.yaml" --autoplay
2023-06-17 23:58:46 +00:00
Karl Ostmo
8b46979abc
active trapdoor demo (#976)
Towards #1088
![image](https://github.com/swarm-game/swarm/assets/261693/c48bd24b-23b8-4165-8670-c105301f04c4)
2023-06-17 23:11:08 +00:00
Karl Ostmo
adcb2c75fc
traffic vignette (#1334)
A simulation of traffic on intersecting roads.  This is a "dynamic vignette"---an animated, looping scene that a player might come upon in their exploration of the `swarm` world.  Such scenes would presumably be "paused" until within range of the player.

Makes use of structure templates (#1332) and records (#1148).

    scripts/play.sh --scenario data/scenarios/Vignettes/roadway.yaml

![image](https://github.com/swarm-game/swarm/assets/261693/8e52e206-be90-4d40-932f-446f87c80ef7)
2023-06-13 04:43:56 +00:00
Karl Ostmo
06db9e8677
structure templates (#1332)
Closes #1138.

Supports all of:
* Nesting
* Transparency
* Flip
* Rotate

![image](https://github.com/swarm-game/swarm/assets/261693/4b175ea5-9081-496c-9161-58876849faa2)

![image](https://github.com/swarm-game/swarm/assets/261693/1f7358eb-c75d-492b-8e54-7492685cebdb)

![image](https://github.com/swarm-game/swarm/assets/261693/4481597f-c531-428c-a310-633e711e84d4)


## Demo

    scripts/play.sh --scenario scenarios/Testing/1138-structures/nested-structure.yaml
    scripts/play.sh --scenario scenarios/Testing/1138-structures/flip-and-rotate.yaml
    scripts/play.sh --scenario data/scenarios/Testing/1138-structures/sibling-precedence.yaml
2023-06-12 18:11:35 +00:00
Brent Yorgey
a85318e32d
Better type error messages when there are unification variables involved (#1318)
Say things like "expecting `xyz` to be a function" instead of "expecting `xyz` to have type `u3 -> u4`".  Closes #1313.
2023-06-11 02:59:47 +00:00
Karl Ostmo
94588efc8d
wrap TickNumber in newtype (#1330)
newtypes > aliases
2023-06-10 18:45:58 +00:00
Brent Yorgey
001ac195ae
More typechecking error message improvements (#1308)
Towards #1297 .  In this PR:

- Moves some functions out of `Pipeline` and into more appropriate modules
- Adds a new type `Join` to represent two types or other things, one "expected" and one "actual", at the point where they join + we check whether they are equal; a bunch of refactoring to use this new type.  This way we don't have to remember which argument is which when calling a function that takes one "expected" thing and one "actual" thing.
- Refactors all the `decomposeXXX` functions to take a `Syntax` node to use in error messages, and to take a `Sourced UType` (*i.e.* a `UType` along with whether it is "expected" or "actual") instead of just a `UType` so we can generate accurate error messages
- Introduce a basic typechecking stack that keeps track of "what we are currently in the middle of checking", so that when we encounter an error we can say things like "while checking the definition of `foo`".  Currently this is just a basic proof of concept.
- A few other miscellaneous error message improvements.
2023-06-10 01:22:50 +00:00
Brent Yorgey
a83aa99eb4
Don't step robots that are waiting, even during instant (#1322)
This fixes #1267 in the best possible way (option 3): if a `wait` command is executed inside `instant`, then it goes into effect immediately, and any subsequent commands will be executed `instant`ly once the robot wakes up. For example, `instant (move; move; wait 1; move; move)` moves twice in one tick and then twice in the next tick.  Even calls to `wait` nested inside recursive function calls inside a call to `instant` work fine.
2023-06-10 00:18:47 +00:00
Karl Ostmo
987ddd6c04
world editor prototype (#873)
Towards #558
I was motivated to build this after finding that editing scenario maps directly in the YAML file is rather constraining.

## What I've implemented so far
* A small, collapsible panel to the left of the REPL containing World Editing status/operations.  Enter world-editing mode with CTRL+e to show the panel.
    * This works only in `--cheat` mode
* Terrain selection
    * A "picker"/"eye dropper" middle-click mechanism to select a terrain style to draw.
    * A pop-up selector to choose between the 5 different types of terrain.
* Drawing terrain with the left mouse button
* Saving a rectangular section of the world map (terrain only) to a file with CTRL+s
* Code organization
    * The complete state of the World Editor, including "painted overlays" of terrain, is contained within the `uiWorldEditor` field of `UIState` record.
    * The bulk of the World Editor functionality shall be in new modules
    * Some refactoring of `Controller.hs` and `View.hs` to extract functions utilized by the World Editor (towards #707)

## Vision

* The audience for this tooling is strictly envisioned to be Scenario authors.
    * Though, if we eventually allow swarm-lang to program the UI, there may be some common code to extract.
* The World Editor is intended to be compatible with a workflow of editing maps in text form within YAML scenario files.

# Demos
## Round-trip with random world

    stack run -- --scenario creative --seed 0 --cheat

Then Ctrl+e, tab down to the Save button, hit Enter to save the map
In another tab run:

    stack run -- --scenario mymap.yaml

Toggle between tabs to compare, observe the derived map is an identical 41x21 subset.
2023-06-09 18:14:41 +00:00
Brent Yorgey
6691300f5f
Make launch options message take up a whole line, even when blank (#1315)
This way the new game menu doesn't wiggle up and down depending on whether the launch options message is displayed.
2023-06-09 17:20:44 +00:00
Karl Ostmo
b382494f7b
Scenario launch options selection (#1010)
Closes #358 and closes #866.

Allows specification of a seed value and/or the path of a script to run.  Specifying a script to run in advance allows eligibility for code size scoring.

Some effort was invested into integrating the Brick `FileBrowser` widget and discovering its idiosyncrasies.  This paves the way for more applications of `FileBrowser` within Swarm.

## Usage

From the scenario selection menu, press the `o` key to pop up a dialog for launch options.

![Screenshot from 2023-06-06 01-38-25](https://github.com/swarm-game/swarm/assets/261693/e306f2ce-db30-4906-9b02-db8e44bc5e99)

Any manually-selected initial-script or seed are persisted to disk and will pre-populate the launch configuration dialog upon the next play.  If a certain scenario is subsequently launched the normal way (i.e. by pressing `Enter` instead of `o`), then this clears the saved script path/seed, and the next pop-up of the launch configuration dialog will not see its fields pre-populated.

## Warning: Save format changed

This PR changes the `ScenarioStatus` datatype, and therefore game status/progress saved previously to this PR will not be recognized.  See https://github.com/swarm-game/swarm/pull/974#discussion_r1111335102 for discussion about this situation.
2023-06-09 06:38:51 +00:00
Karl Ostmo
873ee19cf4
peg fourmolu version (#1311)
This is so that our PR's don't suddenly start failing when the restyled.io service bumps is `fourmolu` version.

## TODO

I wasn't actually able to install version `0.10.1.0`; both of these attempts failed:

    stack install fourmolu-0.10.1.0

and

    cabal install fourmolu-0.10.1.0
2023-06-09 06:18:38 +00:00
Karl Ostmo
f39bd1bc37
ensure progress gets saved (#1305)
I believe that since #1277 the progress has not been saved when exiting a scenario back to the menu.

It is because `getNormalizedCurrentScenarioPath`, which is utilized by `saveScenarioInfoOnQuit`, was returning `Nothing`, in turn because `currentScenarioPath` was `Nothing`.  This is because `scenarioToAppState` was clearing it immediately after being set inside `startGameWithSeed`.

Foreshadowed by this comment: https://github.com/swarm-game/swarm/pull/1243#pullrequestreview-1411539743 .
2023-06-05 01:18:42 +00:00
Karl Ostmo
bdea72f6aa
Cleanup 'use' command code (#1299)
From review feedback in #1287
2023-06-04 16:12:24 +00:00
Brent Yorgey
abe0ae88a6
Better type error messages (#1298)
Improvements to type inference and type error messages.  Includes:
- More informative error when record literal fields don't match the expected set of fields
- More informative type mismatch error which includes the term where the mismatch occurred.
- Reinstates a case for lambdas with explicit type annotations in inference mode (which was removed in #1283), which helps preserve better error messages in some cases.
2023-06-03 12:22:06 +00:00
Brent Yorgey
4509a3b378
Refactor to factor out type error SrcLoc (#1294)
Some refactoring related to type errors:

- Change the type of `addLocToTypeErr` to something more sensible, and get rid of some redundant calls
- Instead of storing a `SrcLoc` in every single `TypeErr` constructor, factor it out into a new type `ContextualTypeErr`.  This also paves the way for additional contextual information which will help generate better type error messages.

This is 100% refactoring; there should be no behavioral changes.
2023-06-01 19:59:51 +00:00
Karl Ostmo
67871a59d2
Density command (#1296)
Closes #1295
2023-06-01 16:28:10 +00:00
Karl Ostmo
4bcf1b9317
'use' command (#1287)
Towards #1007

The `use` command adopts the same return type as `drill`:

    use : text -> dir -> cmd (unit + text) 

## Demo

    scripts/play.sh --scenario data/scenarios/Testing/1007-use-command.yaml --autoplay
2023-05-30 17:47:14 +00:00
Karl Ostmo
c1a1a67480
Extract drilling logic (#1288)
Just a simple code relocation with no functional changes.

Towards #1007.
2023-05-29 16:02:02 +00:00
Brent Yorgey
b2747a6fce
Rework type checker using "propagate types inward" trick (#1283)
The basic idea is that we try as hard as possible to stay in "checking mode", where we have an "expected type" from the context and "push it down" through a term.  We also try hard to avoid generating fresh unification type variables unless absolutely necessary.  That way, when we come to something that doesn't match the expected type, we can immediately flag a specific error about that part of the code, rather than later having a generic unification error.

This is mostly just refactoring, but it already improves the type error messages somewhat:

* Instead of saying something like "can't unify int and text", it might say something like "expected type int, but got text" with a reference to a specific source code location.
*  It's probably possible to still get it to sometimes fail with a "can't unify" type error, but with only this technique I don't think we can ever 100% get rid of that.
* Type errors now report a specific line and column number, not just a line number like they used to. 

There is still a lot more I want to do to improve the type error messages but this is a start.

Closes #99.
2023-05-28 02:28:15 +00:00
Brent Yorgey
a2cd731c83
Recreate GameState from scratch when starting a scenario (#1277)
All info that needs to be persistent (*e.g.* the set of standard/default entities and recipes) is now stored in the `RuntimeState`.  The `GameState` record is now recreated completely from scratch every time upon starting a new scenario, so custom entities and recipes from the previous scenario do not persist into the next.

Fixes #516.  Fixes #689.

Also a bunch of related refactoring/simplification relating to how we were initializing state for tests and benchmarks.

I also want to refactor the tests so we only load data from disk once, but I have split that out into a separate issue (#1279).
2023-05-25 11:24:05 +00:00
Karl Ostmo
2633403a97
lights out (#1273)
See https://en.wikipedia.org/wiki/Lights_Out_(game)

![image](https://github.com/swarm-game/swarm/assets/261693/e61cf515-f3c6-4d06-ab4f-01b79261a64a)

The seed is not fixed; random valid games are generated and can be solved automatically via the provided solution.

One can use the solution strategy described [here](https://en.wikipedia.org/wiki/Lights_Out_(game)#Light_chasing).
2023-05-22 17:54:50 +00:00
Karl Ostmo
07340ad10f
use isPrivilegedBot more (#1275) 2023-05-21 00:08:09 +00:00
Karl Ostmo
60441451cc
Allow zero-tick recipes to apply immediately (#1272)
# Summary

This PR allows a recipe's effects to be applied within the same tick if `time: 0` is specified for the recipe.

The previous behavior was that if the `time` of the recipe was zero, it would nonetheless behave the same as `time: 1`, and the entity updates would not be applied until the next tick.

This new behavior is useful when "abusing" the `drill` command to emulate various other games via help from a system robot.

# Motivation
For the "Lights Out" game (#1273) I have implemented a system robot that `instant`-ly toggles the four adjacent lights and the center light when a center light is `drill`-ed by the player.  The light entities are named `"off"` and `"on"`.

I did some experiments to see if the system robot would react "fast enough" if the player drilled quickly in succession.

# Experiments

The 5x5 light grid is initially `"off"`.  I moved the player robot to the center of the grid, facing `east`. From this position, I tried three command sequence variations both *before* and *after* this PR.  The recipes for toggling lights specify `time: 0`.

## Before this PR

### 1. Drilling twice in succession

    drill down; drill left;

This resulted in an error:
![no-instant-error-message](https://github.com/swarm-game/swarm/assets/261693/f22a0a28-5df7-4fe8-ac18-97504d64e3c8)

so only the first `drill` got applied:

![no-instant](https://github.com/swarm-game/swarm/assets/261693/2d9e4ba7-c138-4dcb-94a6-3c7bb14ddd68)

This is because I believe the sequence of events was:

| Tick / Robot | Action |
| --- | --- |
| **Tick 1:** Player | Execute the first `drill` command, queue entity modification |
| **Tick 1:** System | No changes observed |
| **Tick 2:** Player | Entity modification from first `drill` is applied.  Execute second `drill` command, queue second entity modifications |
| **Tick 2:** System | Observe modified entity, toggle the adjacent lights |
| **Tick 3:** Player | Try to apply entity modification from second `drill` command. Throw an error because the system robot has toggled the drill's target entity to `on` whereas the `drill` was initially executed when it was still `off`. |

### 2. Instant for both drills

    instant $ (drill down; drill left)

In this case, both of the player's `drill` commands were executed, but the system robot then failed to doubly-invert one of the cells:

![instant-both-drills](https://github.com/swarm-game/swarm/assets/261693/65642fd6-3cea-4834-96fd-404da7628c66)

This is due to some kind of race condition in the system robot's logic.  However, it is irrelevant because the `instant` command shall not be available to the player.

### 3. Instant for first drill only, then second drill

    instant (drill down); drill left;

This accomplished what approach number 1 was supposed to; both drill commands were applied and the two overlapping cells got properly inverted:

![instant-first-drill](https://github.com/swarm-game/swarm/assets/261693/64aab681-140d-457a-9273-943ae5b4d58d)

**Explanation:** In this case, the entire drilling operation (including applying all effects to entities on the ground) was completed within the player's first tick, so the system robot updated the lights appropriately on its turn.  Then, in the next tick the player robot applied another drill command, and again the system robot appropriately did another inversion on the two overlapping middle cells.

## After this PR

### 1. Drilling twice in succession

    drill down; drill left;

Now works as expected:

![after-no-instant](https://github.com/swarm-game/swarm/assets/261693/538767d3-9832-4e5c-996e-12a9b7a2015c)

### 2. and 3.

Behaved identically to before the PR.
2023-05-20 20:02:29 +00:00
Karl Ostmo
39ae4ae40d
sokoban levels (#1269)
Three simple (demonstration) levels plus one serious challenge, `foresight.yaml`.

![image](https://github.com/swarm-game/swarm/assets/261693/f1f298e1-13ee-4f8d-b153-8c50f5d53ba8)
2023-05-19 19:28:17 +00:00
Brent Yorgey
2487737d1d
halt command (#1256)
Closes #392 .  Adds a command `halt : actor -> cmd unit` which halts the given robot if it is within a distance of 1 (no distance limit for system robots or in creative mode).  `halt self` works too.  Privileged robots (i.e. system robots, or when in creative mode) can halt any other robot.  Unprivileged robots cannot halt system robots.
2023-05-19 13:06:20 +00:00
Brent Yorgey
8ada24de48
Abstract out common lens generation code (#1266)
Just some simple housekeeping, abstracting out some common lens generation code to reduce the amount of repeated boilerplate.
2023-05-17 18:57:55 +00:00