selang

Python, ASP and JSON abstractions of the SpaceEngine modding language


Keywords
SpaceEngine, DSL, Answer, Set, Programming
License
GPL-2.0+
Install
pip install selang==0.1.1

Documentation

Space Engine modding language abstraction

Using python, define complete systems in SpaceEngine.

For motivations, see my blog entry about this repository.

Short example

Let's say you want to reproduce a simple solar system with a sun, an earth and a moon. You can write in mysimplesystem.lp the following lines:

root(sun,"MySimpleSystem").
orbit(sun,orbit(earth,moon,"0.005"),1).

You now run selang on it:

python -m selang mysimplesystem.lp -o ~/path/to/SpaceEngine/install/dir

You can now run SpaceEngine and press F3 to search and go to MySimpleSystem.

Install

pip install selang

On random error, add no-cache-dir. To get the ASP part working, install clingo 5 in you $PATH.

CLI Example

First, lookup some example of input data in data/, for instance the reproduction in JSON of the full 4 Kalgash systems from planetplanet.net.

Now, run the command:

python -m selang data/kalgash.json

8 files will be created : two for each of the four Kalgash systems defined in data/kalgash.json. The two files correspond to the SpaceEngine modding interface, that needs a star record (which should be named system record) and a planet record (which should be named object record). Note that the star record, ending in .star.sc, is quite trivial.

Also, if you have the path to your SpaceEngine installation directory, for instance ~/games/SpaceEngine/:

python -m selang data/kalgash.json -o ~/games/SpaceEngine

This way, selang will directly put the generated files into the expected directories, i.e. <SpaceEngine installation directory>/addons/catalogs/{star,planet}/.

There is some help about this CLI if you need it:

python -m selang --help

API Example

Let's say you want to reproduce a simple solar system with a sun, an earth and a moon.

Using python and se-lang, you would write:

from selang import ref, orbit, Model, model_to_se

model = Model(
    'My little system',
    {  # structure of the system
        'sun': (1, orbit(1, eccentricity=0.04)),
        1: ('moon', orbit(0.05)),
    },
    {  # non explicit objects
        1: ref('earth', earth_mass=1.2),  # super earth
    }
)

model_to_se(model, '~/games/space_engine/SpaceEngine/')

Alternative typing

The internal model used by se-lang is quite simple, and therefore may be used directly:

from selang import ref, orbit, Model, model_to_se

model = Model(
    'My little system',
    (
        ('sun', 1, orbit(1, eccentricity=0.04)),
        (1, 'moon', orbit(0.05))
    ),
    {
        1: ref('earth', earth_mass=1.2),  # super earth
    }
)

model_to_se(model, '~/games/space_engine/SpaceEngine/')

Interest of se-lang over the modding language

The modding language of SpaceEngine is very well documented and powerful. However, beyond the simple cases described in the doc, you end up writing python scripts to automatize some standard things, like rings.

Instead of rewriting new python scripts each time, here it is: an internal model to rule them all. An internal model to be created by any format. An internal model to use for any case.

Input formats

The internal model can be directly built by client code. However, to simplify the input, further work will focus on building the internal model using other languages.

ASP

ASP is (logical) programming language, like prolog. It allows the high-level expression of logical relations, which is quite interesting for DSLs.

It leads to very short programs, as show the following reproduction of all 4 Kalgash systems:

% Common to all
root(black_hole,"Kalgash").


% Kalgash 2 system
orbit(black_hole,ring(sun,8),20).
orbit(black_hole,orbit(red_dwarf,earth,"0.2"),10).


% Kalgash 3 system
orbit(black_hole,ring(sun,12,orbit(1,earth,1)),20).


% Kalgash 4 system
orbit(black_hole,ring(sun,8),1,retrograde).
orbit(black_hole,earth,"2.5").
orbit(black_hole,ring(sun,8),"4").


% Kalgash 5 system
orbit(black_hole,ring(sun,8),1,retrograde).
orbit(black_hole,earth,"2.5").
orbit(black_hole,ring(blue_giant,8),20).

See other examples in data/.

JSON

JSON is really close to Python basic types, and as such enables a quasi-obvious mapping to the python API.

As for ASP, previous implementation handled JSON-based input. It was verbose, but simple:

{
    "name": "Kalgash 3",
    "UID": "Kalgash",
    "type": "black hole",
    "childs": {
            "type": ["ring", 12, "sun"],
            "distance": 20,
            "childof": {
                "1": {
                    "type": "earth",
                    "distance": 1
                }
            }
        }
}

See other examples in data/.

ASP vs JSON

ASP is (logical) programming language, JSON is a text format, so they differ in so many ways, you can assume they are different things.

The ideal language to abstract modding of SpaceEngine is probably not one of these two, but i had fun making the corresponding interpreters, and using them for some use cases.

dev

  • ASP input: short and simple.
  • JSON input: not programmable, but useful for simple work.
  • Python input: good enough
  • lisp input.
  • read input from file
  • reproduce Kalgash systems from planetplanet.net: see blog entry
  • reproduce UESS
  • find a way to simplify UESS encoding: python do the job.
  • user-made spacing for rings
  • specific treatment for elements of rings
  • allow use of standard name for objects: sun, earth,…
  • allow use of non-standard name for objects: planet and star functions.
  • injection of arbitrary SpaceEngine script code.
  • full orbit definition
  • testing suite
  • handle star barycenter as object (bottom line: necessary to handle binary objects)

FAQ

Dinopython support ?

No.

Contributions ?

Yes.

Other things i did for SpaceEngine ?

se-pioneer, for asynchonous multiplayer.