Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

World function DSL #1320

Closed
xsebek opened this issue Jun 9, 2023 · 9 comments
Closed

World function DSL #1320

xsebek opened this issue Jun 9, 2023 · 9 comments
Assignees
Labels
C-Moderate Effort Should take a moderate amount of time to address. G-Game State An issue having to do with the game state record. G-Scenarios An issue having to do with scenario design, the way scenarios are described and loaded, etc. G-World An issue having to do with world design, world generation, etc. L-World DSL World description language S-Moderate The fix or feature would substantially improve user experience. T-Challenges Involves the challenge scenarios - shorter games with objectives. T-Map editor Tooling for editing scenario maps Z-Developer Experience This issue seeks to make life easier for developers writing Scenarios or other Swarm code. Z-Feature A new feature to be added to the game.

Comments

@xsebek
Copy link
Member

xsebek commented Jun 9, 2023

Is your feature request related to a problem? Please describe.

The world function is currently static except for seed. Being able to parametrise it would be helpful in several places:

  1. in custom scenarios
  2. in scenario launch options (Scenario-configurable World Function parameters #1290)
  3. in save files (Saving/loading games #50)
  4. in world editor? (world editor prototype #873)

Another related problem is that we currently have competing ways to specify the world.
Namely specifying the seed, default entity and a part of map.
When the default entity is specified, it will disregard the seed and default world function.

Describe the solution you'd like
We should create a simple configuration scheme, that we can play with, modify and extend.

In YAML the current world function could look like this:

world:
  parameters:
    noise: # WorldGen.hs: Perlin noises p0, p1, p2, cl0
      smallBig: [0, 6, 0.05, 0.6]  # seed, number of octaves, scale, and persistance.
      softHard: [1, 6, 0.05, 0.6]  # we could specify those as object parameters or tuple
      naturalArtificial: [2, 6, 0.05, 0.6]  # here I am using tuple to be brief, but object is likely better
      choice: [0, 4, 0.08, 0.5]
    biomes:
      big:
        hard:
          natural:  # WorldGen.hs: genBiome Big Hard Natural
            # use object for conditions
            - [{sample: 0.5}, "stone", "mountain"]
            # interpret top-down
            - [{murmur: {mod: 30, equal: 0}}, "stone", "boulder"]
            # combine conditions
            - [{sample: 0.5; murmur: {mod: 30, equal: 0}}, "stone", "LaTeX"]
            - [{sample: 0.5}, "stone", "tree"] 
            # use otherwise string like in Haskell and null for no entity
            - [otherwise, "grass", null]
          artificial:
             # ...
      small:
        # ...

The Haskell datatype WorldParameters would follow this structure and get interpreted like testWorld2.

Describe alternatives you've considered

In general (ignoring the specific syntax proposed here) the only alternative is passing parameters ad-hoc in code.
That is fine for current seed and default entity, but will need more structured approach later.

Additional context

  • We should consider how changes to the scheme will impact saves.
    Adding a new field should not brick all player save files... at least once we have a stable release. 😄
  • We should measure the performance impact.
    A new benchmark would be needed.
@xsebek xsebek added Z-Feature A new feature to be added to the game. C-Moderate Effort Should take a moderate amount of time to address. S-Moderate The fix or feature would substantially improve user experience. G-World An issue having to do with world design, world generation, etc. G-Game State An issue having to do with the game state record. G-Scenarios An issue having to do with scenario design, the way scenarios are described and loaded, etc. T-Challenges Involves the challenge scenarios - shorter games with objectives. Z-Developer Experience This issue seeks to make life easier for developers writing Scenarios or other Swarm code. T-Map editor Tooling for editing scenario maps labels Jun 9, 2023
@xsebek xsebek self-assigned this Jun 9, 2023
@xsebek
Copy link
Member Author

xsebek commented Jun 9, 2023

@kostmo @byorgey what do you think about this proposal?

The proposed format could subsume current world function, but might be more generic then what was imagined in #1290.

I think we could still manage to squeeze it in UI though. If we assume that sample has priority over murmur, then we can show always both and allow user to enable either or both. Maybe at first we would not allow the player to add new list entries in UI. 😅

@byorgey
Copy link
Member

byorgey commented Jun 9, 2023

I think this is headed in the right direction, though I think I would design the DSL rather differently. I will give it some thought and come back with some concrete proposals for comparison.

I really don't think we should worry about the UI at this point --- the idea is just to be able to have a more flexible way to design worlds in scenario descriptions.

@byorgey
Copy link
Member

byorgey commented Jun 13, 2023

Edited 6/15 to include feedback/ideas.

Here are my current thoughts towards DSL for world functions. I think it ought to be a real programming language (though not a general-purpose or Turing complete one), not just a configuration language: that is, there should be a sense of building/computing the world function we want out of compositional pieces rather than specifying a bunch of configuration data.

I think all the below will be straightforward to implement (though probably still a lot of work).

@xsebek , @kostmo would love to hear your thoughts/feedback!

Design considerations

The language ought to be able to handle things like:

  • Specifying, transforming, and combining finite "patches" or "structures", including transparency/overlay, as in Structure templates in YAML #1138 .
  • Specifying the current testWorld2, and other similar infinite, procedurally-generated worlds.
  • Providing a good target format for saving the current state of the world, as in Saving/loading games #50 .

Types

  • To be able to handle things like noise functions, thresholding, etc. as well as specifying cells in the world I think we need (at least) four base types: boolean, integer, float, and cell.
  • Any integer can also be used as a float.
  • A cell can be a one-, two-, or three-tuple as currently (i.e. terrain or terrain+entity or terrain+entity+robot).
    • Actually, this probably wants a bit of rethinking: for example, might we want to be able to overlay a pattern of robots onto a separately specified terrain, so it would be annoying if we must specify a terrain along with a robot. I will come back to this later.
    • In any case there should be some kind of monoid to combine cell values.
  • There are also two "complex" types:
    • World b, where b is one of the four base types, represents a (finite or infinite) "world function" which specifies a value of type b at every coordinate in its domain. For example, the ultimate goal will be to describe a World cell; a noise function would have type World float; a value of type World boolean would represent some kind of "mask", and so on.
    • Palette b, where b is one of the four base types, represents a finite mapping from characters to values of type b. The current "palettes" we use have type Palette cell, but it could also be useful to have something like a Palette boolean so you can specify the two characters you will use to draw a mask.
    • I considered whether or not to make Palette its own type, but it seems like it could be useful to give a name to a palette via let, in which case it needs to be its own separate thing.
  • Any base type b is a subtype of World b; that is, a value of type b may be used anywhere a World b is expected, or, put another way, any b may be automatically "promoted" to a World b. Semantically, a single value of a base type may be promoted to an infinite, constant world function which returns that single value at every coordinate.
  • In general, any function of type b1 -> ... -> bn where the bi are all base types may be "lifted" to have type World b1 -> ... -> World bn, which means the function will act "coordinatewise", i.e. like a giant 2D zipWith.
    • For example, the < operator has a type like integer -> integer -> bool but that means it could also have type World integer -> World integer -> World bool.
  • I recommend explicitly not allowing function definitions since that would make the typechecking more difficult. But we could potentially add functions later.

Frames

Each value of type World b will have an associated frame consisting of two ranges, an x range and a y range. A range consists of a lower bound (inclusive) and an upper bound (exclusive), both of which can also be infinite. In other words, a frame is a rectangular region, but the region can also be infinite in one or more directions.

  • Frames form a semigroup, with the combination of two frames being the smallest frame which contains both.
  • A world function created by promoting a constant has a frame infinite in all directions, whereas one created via a struct has a finite frame.
  • In practice there may or may not end up being ways to create e.g. a frame which is infinite in only one direction.

Syntax

I will be deliberately vague about concrete syntax; I imagine that it might be nice to support both compact, "applicative" syntax like overlay [x, rot90 y, flip z] and also a YAML-like syntax, e.g.

overlay:
- x
- rot90: y
- flip: z

Perhaps one could even use a mix of the two, using YAML syntax for big structures and using the compact syntax for expressions that would be tedious to write out in a tree form.

In what follows I will use compact syntax but the concrete syntax is not really the important thing.

I did consider the possibility of using an embedded DSL, so that world descriptions would actually consist of Haskell code. This would definitely save some work implementing a type checker and interpreter, however, (1) it would require some complex code to interpret Haskell within Haskell, which I'd rather not have to do given the recent unreliability of the hint package and the difficulty of using the GHC API directly; (2) it is not a great fit for Haskell due to the pervasive use of subtyping. We would need to introduce and use a bunch of explicit conversion functions, e.g. constant :: b -> World b.

Another crazy idea would be to piggyback off of our existing machinery and use swarm-lang syntax and/or types. However, we definitely don't want to use CESK machines to run these since they need to be as fast as possible.

Expressions

For each kind of expression I will give an example and explain the type and semantics. This should not be taken as an exhaustive list, there might be other things we want that I have missed and we can certainly explore alternatives, add more things later, etc.

  • The special empty constant has any base type, and represents an empty/undefined value. This is so we can specify transparent/undefined areas of world functions. e.g. we might want to specify a world function which yields 3 inside a certain rectangle but is empty everywhere else. Overlaying this on top of something else will only have an effect inside the given rectangle.
  • Literals
    • e.g. 3 : integer, true : bool, etc.
    • Each literal can either be used as a single value, or, e.g. since any integer can also be treated as a World integer, 3 could also represent an infinite, constant world function which returns 3 at every coordinate.
  • Unary operators: not, -
    • not : bool -> bool, and - : integer -> integer or - : float -> float.
    • As always, these can also be lifted to act over Worlds.
    • For example, not can either have type bool -> bool as usual, OR it can have type World bool -> World bool, in which case it simply negates the boolean value at every coordinate.
  • Binary operators: arithmetic operators like +, -, *, /, %, comparison operators like <, ==, etc. and logical operators &&, ||
    • Each binary operator operates appropriately on certain base types, or can be lifted to combine two World values coordinatewise.
    • For example, + can have type integer -> integer -> integer, or float -> float -> float, or World integer -> World integer -> World integer (or float). In the World case, it adds the corresponding values at every coordinate, i.e. it's like a giant 2D zipWith (+).
    • All the other operators work in a similar way, i.e. they act just like what you would usually expect but can be lifted to work coordinatewise over Worlds.
  • It may be convenient to have a built-in mask : World boolean -> World b -> World b such that mask p w = if p w empty.
  • seed : integer is a special built-in constant which represents the value of the world seed.
  • x : World integer represents the x-coordinate at every location. Similarly, y : World integer represents the y-coordinate.
  • perlin : integer -> integer -> float -> float -> World float constructs a noise function from the usual parameters (seed, octaves, scale, persistence).
  • hash : World integer represents the murmur3 hash of the coordinates.
  • if : bool -> b -> b for any base type b. It can also be lifted: if : World bool -> World b -> World b.
  • let x1 = e1, x2 = e2, ..., xn = en in e defines the variables x1 through xn in the expression e2.
  • There are rotation operators rot90, rot180, rot270 (or maybe we can come up with better names for them) which all have type World b -> World b for any base type b. They rotate a world function about the origin.
  • There is a translation/offset operator offset : integer -> integer -> World b -> World b which translates the given world function.
  • There are horizontal and vertical reflection operators e.g. reflectV : World b -> World b which reflect across lines through the origin.
  • The struct operator takes a Palette b and a literal rectangle of characters and returns a World b. The resulting world function is empty everywhere outside the rectangle and takes on values as specified by the palette inside.
    • Note that the rectangle will always have its upper left corner at (0,0). The offset transformation can be used if a different offset is desired.
    • The default frame will be exactly surrounding the given specified rectangle.
  • The overlay operator takes a list of World b and returns a single World b.
    • At each coordinate, we get the monoidal accumulation of all the values at the given coordinate, with empty serving as the identity element, and otherwise combining according to the semigroup on the underlying base type.
    • integer, float, and boolean just use the simple Last semigroup, i.e. x <> y = y.
    • cell may use something more complex so that e.g. overlaying a terrain value and a robot will combine them.
    • The frame of the resulting world function will be the combination of all the individual frames, i.e. the smallest frame that contains all.
  • vcat and hcat take a list of World b and return a single World b, using their frames to place them next to each other vertically or horizontally.
  • hrepeat and vrepeat take a single World b and repeat it infinitely in either the horizontal or vertical direction.
  • frame : integer -> integer -> integer -> integer -> World b -> World b explicitly sets the frame to the given coordinates. This can be used either to make the frame larger than it would otherwise be (e.g. to add some "padding"), or to cut out a specific piece of a larger map, etc.. (If you want to make a frame infinite, just overlay with empty.)

Parameters

If we wanted to allow user-configurable parameters other than the seed (as in #1290) we could allow a parameters section at the beginning that specifies the names of parameters, their types, and their default values. They could then be used like any other variables within the world specification.

Examples

  • if (perlin seed 6 0.05 0.6 > 0) [ice] [stone] defines an infinite world of ice and stone blobs defined by where the given noise function is positive or negative, respectively. Notice how perlin seed 6 0.05 0.6 necessarily has type World float; hence the > comparison is lifted to compare two World floats and return a World bool; the literal 0 is automatically promoted to represent a World float which is constantly 0; and so on.

  • The current testWorld2 (https://github.com/swarm-game/swarm/blob/main/src/Swarm/Game/WorldGen.hs) could be encoded something like this:

    let pn0 = perlin seed 6 0.05 0.6,
        pn1 = perlin (seed + 1) 6 0.05 0.6,
        pn2 = perlin (seed + 2) 6 0.05 0.6,
        cl  = perlin seed 4 0.08 0.5,
        big = pn0 > 0,
        hard = pn1 > 0,
        artificial = pn2 > 0,
        small = not big,
        soft = not hard,
        natural = not artificial
    in
    overlay
    [ mask (big && hard && artificial)
        (if (cl > 0.85) [stone, copper ore] [stone])
    , mask (big && hard && natural)
      ( overlay
        [ [grass]
        , mask (cl > 0) (if (hash % 30 == 1) [dirt, LaTeX] [dirt, tree])
        , mask (hash % 30 == 0) [stone, boulder]
        , mask (cl > 0.5) [stone, mountain]
        ]
      )
    , ...
    ]
    
  • The example in Testing/1138-structures/flip-and-rotate.yaml might be encoded something like this, using YAML-like syntax this time. I'm not 100% sure of the best way to encode ASTs in YAML, very open to suggestions here. Note: the repeating pattern of flowers could probably be encoded more compactly by making use of things like hrepeat and vrepeat. Also, the tetrominoes could probably be placed via hcat and vcat.

    let:
      tetromino:
        struct:
          palette:
            '0': [stone, bit (0)]
            '1': [stone, bit (1)]
            '.': empty
          map: |
            10..
            10..
            10..
            10..
            1000
            1111
    overlay:
      - struct:
          palette:
            '.': [grass]
            '*': [stone, flower]
            '┌': [stone, upper left corner]
            '┐': [stone, upper right corner]
            '└': [stone, lower left corner]
            '┘': [stone, lower right corner]
            '─': [stone, horizontal wall]
            '│': [stone, vertical wall]
          map: |
            ┌──────────────────────────────┐
            │*..*..*..*..*..*..*..*..*..*..│
            │.*..*..*..*..*..*..*..*..*..*.│
            │..*..*..*..*..*..*..*..*..*..*│
            │*..*..*..*..*..*..*..*..*..*..│
            │.*..*..*..*..*..*..*..*..*..*.│
            │..*..*..*..*..*..*..*..*..*..*│
            │*..*..*..*..*..*..*..*..*..*..│
            │.*..*..*..*..*..*..*..*..*..*.│
            │..*..*..*..*..*..*..*..*..*..*│
            │*..*..*..*..*..*..*..*..*..*..│
            │.*..*..*..*..*..*..*..*..*..*.│
            │..*..*..*..*..*..*..*..*..*..*│
            │*..*..*..*..*..*..*..*..*..*..│
            │.*..*..*..*..*..*..*..*..*..*.│
            │..*..*..*..*..*..*..*..*..*..*│
            └──────────────────────────────┘
      - offset:
          - [3, -2]
          - tetromino
      - offset:
          - [9, -2]
          - rot90: tetromino
      - offset:
          - [17, -2]
          - rot180: tetromino
      - ... etc.
    

@kostmo
Copy link
Member

kostmo commented Jun 14, 2023

  • we could also imagine adding some functions like vcat, hcat, etc. in order to lay out structures/tiles/map sections next to each other without having to know the precise offsets needed.

I dare say this would be an essential feature for ergonomic world design. Manually calculating the offset for each tile in #1334 was tedious and not scalable, and is essentially now read-only.

There are some concepts from Diagrams that would greatly facilitate world design. In addition to the "relative positioning" described above, also being able to define an "envelope" that may be larger "map" rectangle (see the giant, uniform rectangle here as a motivating example). It would be a riot to make diagrams a package dependency of swarm and use V2 Int :D.

I would also like to be able to independently specify repeat-x and repeat-y as with CSS to re-use map tiles.

This world description language is shaping up to be a hybrid of a fragment shader and box model. Very interesting...

@byorgey
Copy link
Member

byorgey commented Jun 15, 2023

  • we could also imagine adding some functions like vcat, hcat, etc. in order to lay out structures/tiles/map sections next to each other without having to know the precise offsets needed.

I dare say this would be an essential feature for ergonomic world design. Manually calculating the offset for each tile in #1334 was tedious and not scalable, and is essentially now read-only.

Noted. I wasn't 100% sure when I wrote that, but now that I've thought through it a bit more I'm confident they should be straightforward to implement.

There are some concepts from Diagrams that would greatly facilitate world design. In addition to the "relative positioning" described above, also being able to define an "envelope" that may be larger "map" rectangle (see the giant, uniform rectangle here as a motivating example).

Yes, makes sense. I think all we need is something like frame : (int,int) -> (int,int) -> World b -> World b which could be used both to take a finite map and make it bigger (exposing default empty cells around it), or to cut out a finite part of some bigger map. Essentially frame is used to manually set the "envelope". But let's call it the "frame" instead of "envelope" since we don't need all the complication of diagrams envelopes; the frame will just be either infinite or some finite rectangular region.

I would also like to be able to independently specify repeat-x and repeat-y as with CSS to re-use map tiles.

Ah, makes sense. That also sounds easy to add.

This world description language is shaping up to be a hybrid of a fragment shader and box model. Very interesting...

Ha, yes, that's a nice way to think of it. Somehow I seem to keep designing DSLs in this space. See also https://hackage.haskell.org/package/boxes and https://github.com/diagrams/active/ and https://hendrix-cs.github.io/csci360/projects/quilt/Quilt.html ...

mergify bot pushed a commit that referenced this issue Aug 17, 2023
DSL for programming worlds, towards #1320 and #29 (and, indirectly, toward #50, since the world DSL should make a nice target for world saves) .  Eventually this should be able to recreate all the world description/building features we have, though there is still a long way to go.  But currently we can at least recreate the "classic" procedurally-generated world.  I think this is a solid foundation we can merge as a first step, and then work on adding more features in subsequent PRs.  Below are some notes that should help in reviewing.  Note that the large number of files changed is due in large part to the elimination of the `default` field in scenario descriptions; see the "changed files" section below for an overview of the important/interesting changes.

Issues split off from this one: #1394 #1395 #1396 #1397 

Major changes
============

- New `data/worlds` subdirectory
    - All `.world` files are parsed at load time and saved in a `WorldMap` which gets threaded through, similar to `EntityMap` (perhaps we should think about passing around a single record instead)
- Standard "classic" world
    - Used to be `testWorld2`, defined in Haskell code; now it is defined via the DSL in `worlds/classic.world`.  This should make it much easier to experiment with variations.
    - We can now automatically extract entities mentioned in a world DSL term with `extractEntities`.  There used to be an explicit list in `testWorld2Entities`, used to check pedagogy, generate documentation, etc., but it turns out it had (predictably) gotten out of date!  This can't happen anymore.
    - It is now referenced in several tutorials (backstory, farming, world101, speedruns, etc.)
- The `default` field of world descriptions is no more: one can use `dsl` to just specify a constant
    - Note in `Swarm.Game.State`, `dslWF` and `arrayWF` are combined using the `Monoid` instance to create `wf`.
- `Erasable`
    - It used to be the case that if some kind of default terrain + entity was specified (e.g. stone + water), any `map` would completely override the default.  However, we want to move towards combining everything with a `Monoid` instance.  But by default this means the default entity would show through anywhere the `map` did not specify an entity.  So we need a way to explicitly "erase" an entity from a lower layer.
    - If `e` is a `Semigroup`, then `Maybe e` is a `Monoid` where `Nothing` acts as an identity element.  Likewise, `Erasable e` is a `Monoid` but adds two new elements: `ENothing` to be an identity, and `EErase` to be an *annihilator*.  i.e. combining with `EErase` is like multiplying by zero.
    - We can now specify `erase` as an entity to override entity underneath.
    - There are several Haskell files with only changes related to `Erasable`, relating to e.g. the world editor, `PCells`, etc.; I'm not 100% sure I've always done the right thing here.

DSL overview
===========

- Integer, float, and Boolean literals.  Note that `3` is *always* an `int`, and `3.0` is a `float`.  It makes things much easier to not have to deal with `3` possibly being either `int` or `float`, though it does make things slightly more annoying for programmers.
- Standard boolean, arithmetic, and comparison operators
- `if ... then ... else ...`
- `<>` operator for combining via `Semigroup` instance
- Cell literals are enclosed in curly braces.  Unlike the previous awkward world description syntax with one, two, or three-element lists denoting terrain, terrain + entity, or terrain + entity + robot, there can now be any number of elements in any order.
    - `{foo}` will be resolved as either terrain, an entity, or a robot, whichever is successful.  So if the names are unambiguous one can just write `{tree}` or `{stone}`.
    - It is possible to explicitly indicate the type of cell value with syntax like `{entity: tree}` or `{terrain: stone}`.
    - Multiple items separated by commas is syntax sugar for combining with `<>`.  e.g. `{tree, entity: boulder, stone} = {tree} <> {entity: boulder} <> {stone}`.
- Ability to refer to the `seed`
- Refer to the current `x` or `y` coordinates or the `hash` of the current coordinates
- `let`-expressions for multiple variables: `let x1 = e1, x2 = e2, ... in ...`
- `overlay [e1, e2, ...]` layers `e1` on the bottom, `e2` on top of that, etc., using the `Semigroup` instance for world functions
- `"foo"` imports the DSL term in `worlds/foo.world`
- `perlin` function to generate perlin noise
- `mask` function to mask with a condition

Changed files
===========

- `Swarm.Util`: moved the `acquire` function here and gave it a more descriptive name.
- `Swarm.Doc.Gen`: can now extract mentioned entities directly.
- `Swarm.Game.Failure`: added new failure modes
- `Swarm.Game.Scenario.Topography.WorldDescription`: get rid of `defaultTerrain` field, add `worldProg` for DSL.
- `Swarm.Game.State`: see comment.
- `Swarm.Game.World`: a bit of reorganization.  Added a bunch of modules under this.
    - `Swarm.Game.World.Coords`: moved some code here from `Swarm.Game.World`.
    - `Swarm.Game.World.Gen`: moved some things here from `Swarm.Game.WorldGen` (also deleted a bunch of irrelevant code), and also added the `extractEntities` function to get all entities mentioned by a DSL term.
    - `Swarm.Game.World.Syntax`: raw, untyped syntax for world DSL terms.
    - `Swarm.Game.World.Parse`: parser for world DSL terms. Fairly standard.
    - `Swarm.Game.World.Typecheck`: takes raw, untyped terms produced by the parser and both typechecks and elaborates them into a simpler core language.  An interesting feature is that the core language is *type-indexed*, so that the Haskell type system is actually ensuring that our typechecker is correct; every typechecked world DSL term value has a type which is indexed by a Haskell type corresponding to the type of the underlying DSL term.  For example, `{entity: tree}` would have a type like `TTerm [] (World CellVall)` etc.  Once terms make it through the typechecker, there cannot possibly be any bugs in the rest of the pipeline which would result in a crash, because the Haskell type system.  (There could of course be *semantic* bugs.)  Understanding exactly how the typechecker works is not too important.  Of interest may be the `resolveCell` function, which determines how we decide what `Cell` is represented by a cell expression in curly braces.
    - `Swarm.Game.World.Abstract`: compile elaborated, typechecked world DSL terms down into an extremely simple core language with only constants and function application.  This gives us very fast evaluation of world DSL terms.  Understanding this module is not really necessary but there is a link to a blog post for those who are interested in how it works.
    - `Swarm.Game.World.Compile`: a further processing/compilation step after `Swarm.Game.World.Abstract`.  Currently we don't actually use this, since it doesn't seem like it makes a big efficiency difference.
    - `Swarm.Game.World.Interpret`: interpreter for abstracted world DSL terms.
    - `Swarm.Game.World.Eval`: just puts together the pieces of the pipeline to evaluate a typechecked world DSL term.
    - `Swarm.Game.World.Load`: just loading world DSL terms from disk.
@xsebek
Copy link
Member Author

xsebek commented Oct 7, 2023

@byorgey shall we close this? 🙂

There are already some followup Issues, so I would rather create a new Meta Issue to track progress, rather than keeping this around.

@byorgey
Copy link
Member

byorgey commented Oct 7, 2023

@xsebek Why not just turn this issue into the meta issue? This issue still has a lot of description, specifications, ideas, etc. that are not captured in any of the followup issues, so I'd rather not close it.

@xsebek
Copy link
Member Author

xsebek commented Oct 8, 2023

Because reading discussion in threads with edited messages and updated initial description is confusing. 😅

I think citing the relevant messages in new Issues will be clearer.

Also I am pretty sure GitHub does not send notifications for edits.

@byorgey
Copy link
Member

byorgey commented Oct 8, 2023

OK, that's fair. 😄 Let me split out some more issues from this one first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-Moderate Effort Should take a moderate amount of time to address. G-Game State An issue having to do with the game state record. G-Scenarios An issue having to do with scenario design, the way scenarios are described and loaded, etc. G-World An issue having to do with world design, world generation, etc. L-World DSL World description language S-Moderate The fix or feature would substantially improve user experience. T-Challenges Involves the challenge scenarios - shorter games with objectives. T-Map editor Tooling for editing scenario maps Z-Developer Experience This issue seeks to make life easier for developers writing Scenarios or other Swarm code. Z-Feature A new feature to be added to the game.
Projects
None yet
Development

No branches or pull requests

3 participants