72 lines
2.7 KiB
Markdown
72 lines
2.7 KiB
Markdown
# AI TCP API
|
|
|
|
The AI handler listens on `127.0.0.1:8765` by default. Set `AI_HOST`,
|
|
`AI_PORT`, or `AI_MAX_WORKERS` to change the server configuration. Messages
|
|
are UTF-8 JSON objects separated by newlines. The connection stays open for
|
|
multiple requests.
|
|
|
|
## Ping
|
|
|
|
Request: `{"type":"ping"}`
|
|
|
|
Response: `{"ok":true,"type":"pong"}`
|
|
|
|
## Start a simulation
|
|
|
|
The server chooses the map. For the first training simulation it selects the
|
|
map closest to difficulty 0. After a simulation finishes, the server computes
|
|
each model's score from coins, progress toward the finish, and whether it won.
|
|
The best score becomes the next training difficulty. Validation requests ignore
|
|
the training score and randomly select a map with difficulty at least 70, or
|
|
any map when no such map exists.
|
|
|
|
The score is from 0 to 100:
|
|
|
|
`40 * coin_progress + 40 * distance_progress + 20 * won`
|
|
|
|
where `coin_progress` is collected coins divided by the map's total coins,
|
|
`distance_progress` is progress from the spawn point to the finish, and `won`
|
|
is 1 when the finish was reached and 0 when the model stopped elsewhere,
|
|
including on spikes.
|
|
|
|
Send one model entry per model. The model entries contain only an ID; moves
|
|
are requested separately on every turn.
|
|
|
|
```json
|
|
{"type":"simulate","validation":false,"models":[{"id":"model-a"},{"id":"model-b"}]}
|
|
```
|
|
|
|
Every model gets a separate `Game` instance and can run in parallel. Valid
|
|
requests. Valid moves are `left_down`, `left`, `left_up`, `up`, `right_up`,
|
|
`right`, and `right_down`. Send `null` for a model when it has no more moves;
|
|
that model is stopped for the current generation.
|
|
|
|
The response identifies the selected map and returns the initial state:
|
|
|
|
```json
|
|
{
|
|
"ok":true,
|
|
"type":"move_request",
|
|
"map":{"name":"default","difficulty":30.0,"layout":[["stone", "stone"]]},
|
|
"results":{"model-a":{"won":false,"coins":0,"moves":0,"position":[1,4],"finished":false},"model-b":{"won":false,"coins":0,"moves":0,"position":[1,4],"finished":false}}
|
|
}
|
|
```
|
|
|
|
## Advance one turn
|
|
|
|
The client must send exactly one move for every model on each turn. The server
|
|
advances all model simulations in parallel and replies before the client must
|
|
predict the next moves.
|
|
|
|
```json
|
|
{"type":"step","moves":{"model-a":"right","model-b":null}}
|
|
```
|
|
|
|
The response is `move_request` with the selected map and updated per-model states, asking the
|
|
client for the next move of every model. When every model has finished, the
|
|
response type becomes `simulation_result` and includes the best model's
|
|
server-computed `score`, which is used to choose the next training map.
|
|
|
|
The result score is `1000` for a win, plus `10` per coin, minus the number of
|
|
moves. Malformed requests receive `{"ok":false,"error":"..."}`.
|