Giter Site home page Giter Site logo

swarm-game / swarm Goto Github PK

View Code? Open in Web Editor NEW
775.0 775.0 47.0 9.39 MB

Resource gathering + programming game

License: Other

Haskell 94.76% Emacs Lisp 0.32% TypeScript 0.08% Shell 0.67% Sway 3.50% Lua 0.01% Vim Script 0.09% HTML 0.15% JavaScript 0.30% CSS 0.09%

swarm's People

Contributors

0xcefaedfe avatar 7h3w1zz avatar alexander-block avatar bwignall avatar byorgey avatar ccasin avatar chhackett avatar danidiaz avatar elderephemera avatar fryguybob avatar gaganchandan avatar huwcampbell avatar juhp avatar kostmo avatar lsmor avatar noahyor avatar p3rsik avatar polux avatar samtay avatar tristancacqueray avatar twitu avatar ussgarci avatar valyagolev avatar xsebek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swarm's Issues

Starting base with a large but finite supply of basic robot parts

Right now, the base can build infinitely many robots with basic devices: a detonator, grabber, solar panel, and treads. However, it is a bit unrealistic that we can make infinitely many of these. Well, not that the game is realistic, but you know what I mean. It might be worth considering instead:

  • Do not any longer install those devices on robots by default; they must be available in the inventory just like any other device.
  • Start the base out with a large number (100? 500? 1000? maybe the number depends on the difficulty level? maybe different numbers of different devices, e.g. fewer detonators than treads?) of these devices, so that at the start of the game the user can construct a bunch of basic robots "for free", but will eventually have to think about producing more of these devices.
  • In order to make this work, we also have to come up with recipes for these devices, and think carefully about how to balance the depth and difficulty.

error with stack run

when i do stack run i get the error

Executable named git not found on path: [".","C:\Program Files\Common Files\Oracle\Java\javapath","C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common","C:\Windows\system32","C:\Windows","C:\Windows\System32\Wbem","C:\Windows\System32\WindowsPowerShell\v1.0\","C:\Windows\System32\OpenSSH\","C:\Program Files\dotnet\","C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\","C:\Users\user\AppData\Roaming\local\bin","C:\Users\user\AppData\Local\Microsoft\WindowsApps","F:\vs\Microsoft VS Code\bin","C:\Users\user\.dotnet\tools"]

Improve display of tick/frame info

Right now the ticks per second and ticks per frame are displayed centered at the top of the world view, and the ticks per frame value is updated every frame. I have in mind several ways this could be improved:

  • Only update the ticks/frame value every second or so.
    • Add a counter to the UIState to count frames (we already have one to count ticks).
    • Get rid of the frameTickHist list, the frameTickHistSize, and the rememberFrameTicks function.
    • Also store the TimeSpec corresponding to the last time we updated the info in the UI.
    • In the updateUI function, check if the last time we updated the info in the UI was at least one second ago. If so, reset the time, compute ticks per frame and frames per second, and reset both counters to zero.
  • Display ticks per frame AND frames per second, perhaps using compact abbreviations like TPF and FPS, or t/f and f/s, or something like that.
  • We should always show the ticks per second; but we could add a key (probably f?) to let the user toggle the display of TPF + FPS on and off.
  • Once #37 is implemented, we could move the display of these things to e.g. the bottom right of the world border instead of centered at the top. (done in aef3d4e)

Add spawning robots to output of `WorldFun`

[Note, I no longer think this original issue description is a good idea, but leaving it here for context. Read all the way through the comments below to see how my thinking has changed.]

Right now a World is specified by a WorldFun, defined as

type WorldFun t e = Coords -> (t, Maybe e)

This is just a function that specifies a terrain value and possible entity for every cell. However, this has several limitations. For one thing, it is difficult to specify things that should be coherent across multiple cells (i.e. structures). For another, if we want the world to contain creatures that move around (implemented as system robots), there is no good way to specify when they should spawn.

The implementation of Worlds already uses a notion of tiles for efficiency, and we can build on this to solve the limitations above. Instead of specifying a world cell by cell, we specify it tile by tile. That is, a WorldFun will now be something like

type WorldFun t e = TileCoords -> (TerrainTile t, EntityTile e, [Robot])

which says that the world function takes as input the coordinates of a tile and generates an entire tile's worth of terrain and entities all at once, in addition to some robots which should spawn when this tile is loaded. When calling the function, it will build tiles first by filling in initial values based on a Coords -> (t, Maybe e) function as before, but then has the opportunity to further modify them, e.g. by deciding where to draw in certain structures.

Active robot queue

This is an idea to make the interpreter a bit more efficient, especially if there are lots of "dead" robots lying around.

  • In addition to the robotMap, add activeRobots :: [Text] to the GameState, representing the names of robots which are actively running code.
  • The addRobot function should add a robot to both the robotMap and the activeRobots list.
  • Each tick, we iterate over every robot in activeRobots (instead of over every robot in the robotMap), filter out any which are inactive, tick the rest, and rebuild the list.

This way we only spend time iterating over the robots which will actually do some computation.

`grab` command should return the name of the thing grabbed

The grab command should have type cmd string and return the name of the thing that was grabbed. That way instead of e.g.

grab; ... ; give "base" "tree" -- give this thing that I already have to know is called a "tree"

you could write

thing <- grab; ... ; give "base" thing   -- give whatever the heck it is I just grabbed

This makes things more discoverable. Note that we should also edit the tutorial to explain this.

Better indentation & layout for pretty-printing

I kind of threw the pretty-printer together without much regard for how the layout and indentation works. The prettyprinter library has lots of nice tools for specifying this kind of thing; someone just needs to sit down and figure out how they work and how to apply them to the Swarm language to get good results.

This is very related to #7 , which will depend on this to get nice-looking save files that users can actually edit without tearing their hair out. Another semi-related issue is #644 .

At the moment, we use pretty-printing quite a bit for types, but we only pretty-print terms in certain error messages (e.g. when a command throws an exception).

Add shortcuts to jump directly to specific panels

I can already tell I am going to be annoyed having to push Tab an unknown number of times when I want to type something at the REPL. It would be nice to offer some shortcuts for jumping directly to a specific panel. For example, Ctrl-I for info panel, Ctrl-R for REPL, and Ctrl-W for world.

Handle bracketed paste events in the REPL

Right now, if you paste something into the REPL, it gets sent one keypress event at a time, which in particular means the parser and typechecker get re-run between every single key event. It's not too slow, but the lag is noticeable.

According to the brick user manual, however, the vty library supports a "bracketed paste mode"---if the terminal does---which sends the entire paste as a ByteString in a single paste event. We should definitely look into enabling this. I'm not yet sure whether we would need to update the REPL event handler; it passes most events on to the input form event handler (provided by brick), so it depends on whether the input form event handler knows how to handle paste events. If it does, this might be as simple as just turning on vty bracketed paste support.

Mechanisms for world exploration & discovery

It's easy to move the map around, but I couldn't tell what features were interesting or how to interact with them. The tutorial explains trees, which is fine, and I guessed the yellowish C was copper, but to do anything with copper I need a furnace, which needs stone. Where does that come from? I can't point at a tile on the map and ask "is this stone?", and there are multiple grey glyphs which plausibly could be.

Switch entity tiles to use *mutable* arrays

Right now we store the world as a triple: a collection of immutable terrain tiles, a collection of immutable entity tiles, and a map specifying which cells have been updated from their original entity values. However, there is no good reason that we can't just use mutable arrays for entity tiles. Running the game already takes place in a monad; we just have to make sure that it supports the mutable array operations. This should hopefully make the implementation simpler and speed up the game as well.

Get impossible operations to return a random result

A few pure operations (comparison on certain types, e.g. function types; division by zero; exponentiation by a negative number) typecheck but have undefined semantics. Making them not typecheck would require adding too much complexity to the type system; and we don't want them to throw exceptions since right now only commands can throw exceptions (giving pure expressions the ability to throw exceptions would make a lot of things more complicated too).

Instead, right now, these operations return a certain magic constant (False in the case of comparison; 42 in the case of division and exponentiation). However, it would be more fun if they returned a random result of the appropriate type. This would entail figuring out how to thread the capability to generate randomness through the interpreter (right now it is done using IO for the random command but I'd like to get rid of that if we can).

Add type ascription syntax to the language

It would be nice to be able to annotate arbitrary expressions with type annotations, as in (3 : int) + 5. It's not clear how necessary this is at the moment --- type inference, plus giving type annotations to top-level definitions, usually seems to be able to do the job. But as we add more polymorphic things it may become increasingly helpful. And in any event it can be helpful as a form of documentation.

Adding this would require

  • adding an AST node to represent a type annotation
  • adding a case for annotations to the parser
  • adding a case to the pretty-printer
  • adding a case for type inference: hitting a type annotation simply makes it call the check function.

Advertise Ctrl-C to cancel base computation

While the base is actively running a computation, the [Enter] execute hint in the key menu should be replaced by [^c] cancel. This feature already exists but it is not advertised anywhere.

Tutorial via challenge mode

Once we implement #15 , I think it would be nice to have a simple tutorial that advances through a series of simple challenges, guiding the user through doing a few of the kinds of things they will need to do at the start of the game (build some robots, make some definitions, craft some devices, etc.)

Deterministic `random` values

Values generated by the random command should actually be deterministically based on the world seed. We could have some kind of PRNG that gets stored in the GameState. Right now the random values are just generated in the IO monad.

Avoid "spiral of death" by capping maximum number of ticks per frame

At the moment, Swarm is susceptible to the "spiral of death" described at https://gafferongames.com/post/fix_your_timestep/ : when the amount of computation we have to do for a frame takes longer than the amount of time allotted for the frame, it starts getting further and further behind. This could in theory be triggered either by a lot of robots doing a lot of computation, or by the user pushing the ticks/second rate too high. If this happens, each frame will take longer than the previous frame and the game will essentially grind to a halt as it tries futilely to catch up but only gets further and further behind.

There is a simple way to avoid this, which is simply to cap the maximum number of ticks per frame (based on my own experience so far, a cap of around 25 seems reasonable). When it hits the cap, the game will slow down: it will essentially be running at a slower ticks/second rate than requested. Perhaps we could signal this by e.g. drawing the ticks per second rate in red, or something like that.

swarm runs at 100% CPU

Describe the bug
swarm runs at 100% CPU

To Reproduce
Run swarm. In another terminal, run top:

PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
388509 f         20   0 1024.3g  32808  14516 R 100.0   1.1   0:06.59 swarm

(alternative: listen to your PC’s fan)

Expected behavior
Use less CPU cycles.

Screenshots
N/A

Additional context
N/A

Parametrized growth rates

Entities which have the growable property, when harvested via the grab command, spawn a system robot representing a "seed", which takes a while to grow through two phases and then replaces itself with another copy of the originally harvested entity. However, the length of time that it takes to grow is hard-coded into the program for the seed robot. This should be configurable, by specifying some data in entities.yaml.

There are a lot more details yet to work out here; just putting this issue here as a placeholder for now.

Design and implement more capabilities and devices

There are quite a few capabilities that are missing; see the comments in Swarm.Language.Capability. This will require some creative thinking and careful planning and testing.


Here is a list of commands and related issues (TODO):

  • View this should also require something. #17
  • Not, And, Or some kind of boolean logic cap? #562
  • Inl, Inr, Case should require a capability for sums #563
  • Fst, Snd should require a cap for pairs #563
  • Try definitely needs to require something #132
  • Wait could require time capability #402

Here is the list of capabilities that are missing devices:

  • senseloc (Whereami)
  • appear (Appear) #1027
  • setname (Setname) #1028
  • #1041
  • random (Random) #497
  • create (Create) make restricted instead in #408
  • compare (==,!=,<, <=,>,>=) added with comparator in #395
  • arith (+,-,*,/) added with calculator in #362

Here is a list of devices that provide a capability but are missing a recipe (see also #361):

In addition, the following commands require god capability and are currently only intended for scenario development and not available to players (except for creative mode):

  • RobotNamed, RobotNumbered
  • As
  • Create

Since #373 the exception users will see if there are no devices to provide required capability looks like this:

Missing the random capability for:
  'random'
 but no device yet provides it. See
 https://github.com/swarm-game/swarm/issues/26

Restricted commands give different message:

Thee shalt not utter such blasphemy:
  'as'
  If't be true thee wanteth to playeth god, then tryeth Creative game.

Persist entity descriptions in the UI when switching to other panels

Right now, a description of the highlighted inventory entity is shown in the bottom portion of the info panel whenever the info panel is focused. However, this disappears as soon as you switch away from the info panel. This feels annoying, though, because an item description might contain something you want to refer to while typing a command at the REPL: some examples of a language feature, for example, or a list of recipes.

The thing that replaces the entity description when not focused on the info panel is the global message log. Perhaps the answer is to make message logs per-robot, and to associate them with a logger device: see #39 . Then the bottom part of the info panel will always show info about the currently selected inventory item, and if you want to see the message log, you can just select that device in your inventory.

Generalize the `uiError` widget to support showing any kind of pop-up dialog

There is a widget which can be shown floating on top of the rest of the UI. Right now it is only ever used for showing language processing errors (e.g. parsing or type checking errors). However, there are probably other reasons we might want a pop-up dialog. At the very least we should change the name from uiError; probably there are other things that should be generalized as well, but I'm not sure off the top of my head.

`salvage` command

There ought to be a way to retrieve all the inventory and devices from a "dead" robot. I'm imagining something like salvage : string -> cmd (), where salvage x will try to salvage a robot named x. If successful, all of x's inventory and installed devices go into the inventory of the robot that executed salvage, and x itself disappears.

Some issues to work out:

  • What is the range of the salvage command? I'm thinking probably you have to be in the very same cell.
  • What if you don't know the name of the robot you want to salvage? There has to be some other way to discover the name(s) of nearby robot(s). That should be orthogonal to salvage, but it's still worth thinking about them together.
  • We'll need to add a new salvage capability. What device should confer this capability, and what should its recipe be? How difficult should it be to construct?

Add logger device

We should add a new kind of device (a logger, recipe: 1 log) which allows logging messages via a log command (i.e. there will be a log capability, provided by a logger, and required to execute the log command). This will also be the mechanism by which uncaught exceptions are reported; on any robot without a logger, such uncaught exceptions will just be silently discarded. See this comment in Swarm.Game.Step.

This will require adding a message queue field to the Robot record type. We should also get rid of the global message queue in the GameState.

We'll have to rethink what the say command does---perhaps it should broadcast a message that will be added to the log of nearby robots?

Challenge mode

Implement a Challenge mode where users try to complete preset challenges. A challenge consists of

  • Some kind of description of a finite world (it isn't yet clear to me what the best way is to specify the world)
  • An initial inventory for the base
  • An unrestricted global program (of type cmd bool) which runs to completion on every tick to see whether the challenge has been successfully completed.

It should be possible to describe challenges in a .yaml file of some to-be-determined format.

Allow generating worlds from different seeds

Right now, in Swarm.Game.WorldGen, some seed values are simply hardcoded. Instead, especially once we implement #4 , when the user starts a new game they should be able to specify a seed value or have one randomly generated. Then the seed value should in turn deterministically generate a unique world.

Add a way for users to find out the type of expressions

It should be possible for a user to learn the type of an expression without executing it. There are a couple ways I could imagine this working.

  1. We could just add a special :type command, so the user can enter something like :type foo at the prompt, hit Enter, and have it print out the type, like GHCi does. This is maybe the simplest to implement in some ways, although it does mean adding a special parser for things entered at the REPL to see whether they start with a colon command or are just an expression. This parser would be used not just when the user hits Enter but also every time the REPL updates to check it for validity.
  2. The fact that we check REPL input for validity every time the user hits a key actually affords a nice opportunity. Instead of making the user enter a special :type command, we could simply display the type in some way any time the current input is valid. The hardest part here would just be figuring out how to display this information. For example, it could be shown in grey with a colon just beyond the input, or it could be shown on the line below.

"Unbound variable" error for recursive definition

def forever = \c : cmd (). c ; forever c end produces the error Unbound variable forever. The problem really is that currently, definitions can only be recursive if they include a top-level type signature, like

def forever : cmd () -> cmd () = \c. c ; forever c end

We should either (1) explicitly check for this scenario and give a better error message suggesting how to fix it, or (2) modify type inference so that it can successfully infer the types of unannotated recursive definitions. (After all, Haskell can do it!)

Disable world scrolling in Classic mode

It seems to make the most sense within the logic of the game that your base has only a limited view of the surroundings, and the only way to see anything farther away is to send a robot there which can broadcast its view back to you.

As a start, we should simply disable the ability to scroll the world view at all when in Classic mode (and also remove the related hint in the key menu display below the world).

Quasiquoters for Swarm types and terms

We often have cause to write down Swarm types and terms in the Haskell source, but right now this is very tedious and hard to read, due to the need to encode them as ASTs. It would be really nice to create some quasiquoters so that we could write them in Swarm syntax but still have them checked at compile time.

Copper mines

Right now there is very limited and non-renewable copper available on the surface, but it's going to be an important ingredient in many recipes. The description for copper says you can get more by drilling, but that needs to be implemented. My ideas are:

  • Create a new kind of terrain, "copper seam", which looks the same as stone.
  • Add a drill command, with a corresponding capability provided by a drill entity. At first drill won't take any parameters, though perhaps later it will take a direction as an argument (to allow for drilling through boulders and mountains etc.)
  • Executing drill on a copper seam cell has a small percentage chance of adding copper to the robot's inventory.

World map

NOTE: this issue was originally about being able to zoom in and out, but perhaps that is too complicated and what we really want is just the ability to see some sort of zoomed-out world map, perhaps in a toggleable dialog or panel. See discussion below.

It would be cool to be able to zoom in and out on the world view. There are a lot of details to work out here, but I am imagining something like the following:

  • It is only possible to zoom by a factor of two.
  • There should be a limit on how many levels it is possible to zoom out.
  • It is not possible to zoom in further than 1:1.
  • The character shown for a given cell when zoomed out can just be the character that occurs most often among the cells covered by the zoomed-out cell. If there is no one majority cell then there could be some kind of deterministic rule for picking.
  • The world could store a different tile map for each zoom level. So for example when zooming out once we would load and fill 64x64 2:1 tiles each of which covers four 1:1 tiles. At two levels zoomed out, each tile would cover 16 1:1 tiles, and so on.
  • Note that the zoomed-out tiles will probably store only characters with attributes, not actual terrain or entity values.
  • Loading a tile at a given zoom level might have to ensure that all the tiles it covers at the previous zoom level are loaded first (and so on recursively).
  • It might be a bit tricky to figure out how to keep zoomed-out tiles appropriately updated when things in the world change. Perhaps there should be some way to mark tiles as "dirty" so we know when tiles above it in the zoom hierarchy need to be modified or rebuilt.

Line-wrap recipes

Tried the game out today, and I couldn't do anything with copper until I read the source, because recipes do not fit in the recipe pane, even if I make my terminal much wider than I usually would. Recipes like the one for copper wire are too long to fit into the pane, and are just clipped at the end, so I knew I could craft "co[something]", but had no way to find out more.

Give `view` a limited broadcast range

This issue used to be about adding an antenna entity to enable view, but see comments below for some reasons why I no longer think we should do that.

I'm thinking there can be an "Antenna" entity.

  • An antenna provides a broadcast capability, with a corresponding broadcast command.
  • Only robots (besides base) which have executed broadcast can be viewed with the view command.
  • The recipe for an antenna could involve, say, 5 copper wires, + maybe something else? Depends on how hard it should be to obtain early in the game. It would probably be pretty helpful for debugging etc. so probably shouldn't be too hard to get.
  • Perhaps later, an antenna can have a limited broadcast range, and there can be more difficult ways to craft more powerful antennas. But probably for a first crack we can just make antennas have an unlimited range.

Partial REPL input should be preserved after scrolling through the REPL history

Describe the bug
If you have typed some input at the REPL but not yet hit Enter, and then scroll through the REPL history, your input will be lost.

To Reproduce

  1. Make sure there is at least one thing in your REPL history (e.g. just type 1 and hit Enter).
  2. Type something at the REPL, but do not hit Enter.
  3. Hit the "up" arrow key, which will switch to the previous REPL entry.
  4. Now hit "down".

Expected behavior
The partially entered input should be restored when you scroll back to the end of the history. Instead, it is blank.

Add a way to visualize a robot's currently executing program

That is, a way to display the current state of the CEK machine for the focused robot. This would require first overhauling CEK machine pretty-printing. I am imagining showing the continuation stack as nested frames rather than a sequence of frames. For example given the program let x = 3 + 2 in x * 4, when we are currently focused on evaluating the 3, we could imagine something like

[let x = [[3] + 2] in x * 4]

or maybe even without all the brackets except the ones around the 3. This would probably require some creativity in certain cases but I think it could be done in a nice, compact way.

The second part of this would be devising ways both (1) for the user to possibly choose whether they want to see this, and (2) figuring out a good place for it in the UI.

Saving/loading games

It should be possible to save the current state of your game, and then later to load from a saved game. There is nothing theoretically difficult about this, but it will take a good deal of engineering. Off the top of my head, a save would need to include.

  • A version number, so that we can do something reasonable with saves created by a previous version of the game.
  • The current state of the world:
    • The seed used to generate the world
    • Which tiles have been loaded
    • The contents of those tiles (either the complete contents, or perhaps just a catalog of the cells whose entity contents have changed from their initial value)
  • All (active and inactive) robots, including their CEK machine state.
  • Note, when saving entities (either in the world map, or in an inventory, or a robot entity), if the hash matches the hash of a standard entity, we only have to save the hash. Otherwise we must serialize the entire entity.
    • Note that for this to work well on old save files, we need to keep old/outdated entities around (perhaps in a separate old_entities.yaml file) so that we can load them.
    • Alternatively (this might be simpler), every save file could just contain a complete description of every entity which needs to be referenced?
  • Probably various other fields of the GameState and/or UIState.

For loading entities and recipes, we use .yaml files, so that they can be easily human-editable. However, for saving the entire game state we definitely don't want to do that. Instead we should use some kind of binary serialization framework so save files will be as compact as possible. Since we can already load scenarios from .yaml files, it makes sense at this point to just double down on that and make save files use the same format.

Once we enable this feature, we'll have to be very careful about versioning things such as entities and recipes, world generation, etc., and keep around old versions of things (as much as is reasonable) so that we can correctly load save files produced by older versions of the game.

Note, a related issue is #7 .

Better handling of water

Right now, water is a terrain type, with an entity for waves so that water can have a checkerboard of waves. But robots can walk right across it, and there's no way for robots to obtain any water. This should be handled in a different way.

Here are my current ideas:

  • Make water an entity with properties [portable, drown, growable]. drown is a new property that means any robot walking on it will drown (i.e. instantly disappear).
  • Get rid of the water terrain type.
  • Change the world generation function to generate water entities on top of e.g. dirt terrain, instead of water terrain.
  • Make a boat device (constructible out of boards?) that conveys a float capability. Robots with the float capability do not die when walking on top of an entity with the drown property. The logic about drown and float will need to be added to the interpretation of the Move command in Swarm.Game.Step.
  • This should be done in conjunction with #23 , to give water a growth time of 0 (i.e. as soon as a robot picks it up, there is more water generated there).
  • Consider whether a robot needs to have some special device to collect water, or if a grabber device should be sufficient.
  • Make water able to have two "orientations" in its display map so we can have some water entities with waves and some without.
  • Modify hashing for entities so the current orientation is NOT taken into account when hashing. What direction an entity is facing should not affect its identity, and in this case it means we can have water entities which are identical when picked up but have two different appearances in the world.

Wrapping and scrolling for messages

Currently, when displaying the message queue, very simple logic is used to decide how to display the messages and how many to display. This often leads to messages being unreadable, especially in a smaller terminal. Also, we choose a static number of messages to display based on the height of the panel, but this is wrong if any of the messages are more than one line high; this leads to messages being cut off the bottom of the panel.

  • We ought to use something like txtWrap to display the actual messages, so they wrap to whatever width the info panel happens to be.
  • Instead of the current logic displaying the last n messages, we should render all the messages into a brick Viewport. As a bonus, we should provide some sort of mechanism to allow the user to scroll it. Note, this kind of scrolling ability will also be needed for entity descriptions, which can be cut off at the bottom if they are too long and/or the window is too small.

Make test suite(s)

Right now we don't have any tests at all, which is kind of embarrassing. I don't even know what a good test suite would look like. Probably we should have several. For example, on one level there are probably many individual functions we could test with QuickCheck and so on. We can also test things at the level of the simulation: e.g. fuzz testing to make sure the game never crashes, and so on. We could also construct some unit tests for each programming language constant or feature, to make sure that programs using those features do what is expected. This would be very valuable as a regression test suite, to make sure that future updates to the language don't break anything.

`program` command

program : string -> cmd () -> cmd () is like build, except it operates on an existing robot in the same cell instead of creating a new robot. The robot being programmed must (1) be idle and (2) have the necessary capabilities to execute the program.

What entity should provide this ability?

Ability to save definitions typed at the REPL to a `.sw` file

I think we ought to get rid of the run command and just make some kind of REPL commands for saving and loading the current set of definitions. For example,

> def x = 3 end
> x + 2
5
> def m2 = move; move end
> :save myDefs.sw

might create a file myDefs.sw which contains the code defining x and m2. Similarly :load myDefs.sw might load the definitions (replacing any currently in scope --- perhaps with some kind of warning and opportunity to cancel).

This seems rather critical to actual gameplay since people will develop various useful definitions and want to edit them, reuse them in later sessions, and so on.

I don't think this should be too hard once #8 (and any other pretty printing bugs) is addressed. To save, just get the robotEnv from the base robot, and pretty-print the definitions it contains (possibly adding some type annotations from the robotCtx). It may be necessary to add something to keep track of the order of the definitions (something the robotEnv does not care about) so that we can pretty-print them to a file in the same order the user entered them.

More principled pretty-printer for `Value`s

Right now the pretty-printer for Values is even more hacked together than the rest; it doesn't even use the same framework. It ought to be rewritten in a more principled way.

`wait` command and waiting robot queue

Right now, the only way for a robot to wait for a certain amount of time is to execute a program like repeat 500 wait, but this means the robot is doing a bunch of computation steps every tick (evaluating the recursive repeat command, subtracting one from a number, checking whether it is zero...). Instead, there should be a way for a robot to register its intent to sleep for a certain amount of time, and have the game engine wake it up later. This will save a lot of work --- for example, I have noticed that the game slows down noticeably when harvesting a large forest, generating a large number of system seed robots which are all busily waiting for a long time to grow.

The idea is as follows. Note that #19 needs to be implemented first.

  • Change the wait command to take an int argument, denoting the duration of waiting.
  • Right now the wait command requires no capabilities, but perhaps with this change it should. I propose adding a time capability, which can be provided by a new clock entity (recipe: some gears + some springs (in turn made from copper wire)?).
    • While we're at it, perhaps we can also add getTime : cmd int, also requiring the time capability.
  • Add a counter to the GameState which tracks the number of ticks since the game started.
  • Add a priority queue of waiting robots to the GameState, keyed by the tick at which the robot should wake up.
  • When a robot executes a wait command, remove it from the activeRobots queue and place it in the priority queue (after calculating the time at which it should be woken).
  • Each tick, before iterating through the active robots, check the priority queue and move any robots which should be woken on this time step into the active robot queue.

Menu screen

When the game initially starts there should be a menu screen giving you options to start a new game in Classic or Creative modes, and eventually offer other choices such as a tutorial, challenge moves, loading a saved game, etc.

Fix pretty-printing of infix operators

Infix operators do not print correctly at the moment; they print as if they were prefix operations, like + 2 3.

Fixing this will be critical to being able to round-trip pretty-printing and parsing, which in turn is needed to be able to support #7 .

Windows support

i am trying to use the command stack run but i get the error:

In the dependencies for brick-0.64:
    unix needed, but the stack configuration has no specified version  (latest matching version is 2.7.2.2)
needed due to swarm-0.1.0.0 -> brick-0.64

In the dependencies for vty-5.33:
    unix needed, but the stack configuration has no specified version  (latest matching version is 2.7.2.2)
needed due to swarm-0.1.0.0 -> vty-5.33

how can i fix this

Display the current game mode in the UI

The current game mode (Classic, Creative, etc.) probably ought to be displayed somewhere in the UI. Not sure where the best place would be... somewhere in the world border, perhaps? (Related: #37 ) Or on the far right of the strip showing available key commands?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.