# Space Engine modding language abstraction
Using python, define complete systems in SpaceEngine.

For motivations, see [my blog entry about this repository](lucas.bourneuf.net/blog/se-lang.html).


## 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:

```asp
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](https://github.com/potassco/clingo/releases) in you $PATH.



## CLI Example
First, lookup some example of input data in [data/](data/), for instance the reproduction in JSON
of [the full 4 Kalgash systems](data/kalgash.json) 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:

```python
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:

```python
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](lucas.bourneuf.net/blog/uess.html).

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:

```asp
% 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/](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:
```json
{
    "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/](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](lucas.bourneuf.net/blog/se-lang.html).



## dev
- [x] ASP input: short and simple.
- [x] JSON input: not programmable, but useful for simple work.
- [x] Python input: good enough
- [ ] lisp input.
- [x] read input from file
- [x] reproduce Kalgash systems from [planetplanet.net](https://planetplanet.net/2018/03/21/asimov-kalgash-take2/): [see blog entry](https://lucas.bourneuf.net/blog/se-lang.html)
- [x] reproduce [UESS](https://lucas.bourneuf.net/blog/uess.html)
- [x] find a way to simplify UESS encoding: python do the job.
- [x] user-made spacing for rings
- [x] specific treatment for elements of rings
- [x] allow use of standard name for objects: `sun`, `earth`,…
- [x] allow use of non-standard name for objects: `planet` and `star` functions.
- [ ] injection of arbitrary SpaceEngine script code.
- [x] 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](https://github.com/Aluriak/se-pioneers), for asynchonous multiplayer.
