1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
-
+
+
+
-
+
-
+
+
+
+
+
+
+
-
+
+
+
+
+
+
-
+
-
-
+
-
-
+
-
+
+
+
+
+
+
+
-
+
-
-
+
-
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
+
+
+
+
-
+
+
-
+
-
+
+
+
+
-
+
-
-
-
+
+
+
-
+
+
+
+
-
+
-
-
-
-
+
+
+
+
|
## Pravda: social games for a social network.
This crate is a functional bot that you can use to connect to a mastodon server (or one providing a similar API) in order to run social games. For now it can be used to play *Rock, Paper, Scissors*, or roll dice. The code is written modularly so that it is relatively easy to add new games.
Pravda is a Mastodon bot that runs social deduction and party games. It
connects to any Mastodon-compatible instance, listens for mentions, and routes
commands to a catalogue of games implemented as pluggable state machines.
The Game trait defines the behaviour for a game, involving an associated method *new* for setup, and a method *next* which receives user toots and is responsible to advance the state of the game. Every game receives every message and must be able to discard anything that is irrelevant to it.
Out of the box the bot supports:
There are some constants to shut down the bot remotely with a toot. *ADMIN* contains the administrative account, *QUIT* contains the quit message which must be sent as a mention to the bot, and *INSTANCE* contains the URL of the instance to connect to. At the moment, it uses my own fedi account by default, and the message *!QUIT!* but you should customise this if you deploy. The default instance is botsin.space, an appropriate instance for bots, but you should change this if you want to run it somewhere else.
- **Rock, Paper, Scissors** – quick duels with private moves and public results.
- **Spoof** – hidden-coin guessing with timed reminders.
- **Dice** – flexible NdM style dice rolling (`dice`, `dice 3`, `dice 2d12`).
- **Unique Lowest Bid** – sealed-bid auction where the lowest unique bid wins.
- **Two Thirds Average** – players try to guess two-thirds of the group average.
- **Soviet Mafia** – a fully themed social deduction game with roles such as
workers, saboteurs, commissars, spies, and more.
Bear in mind you must have a valid account on the instance before you attempt to authorise the bot.
All games implement the shared `Game` trait (`src/game.rs`), receiving every
incoming command and returning a `Reply` that includes text plus visibility
(a.k.a. public vs. DM). The runtime fans out commands to each game, and the
game decides whether to react or ignore the input. This makes it easy to add
new games without touching the bot core; just register them in
`src/catalog.rs` so they are constructed at startup.
### First run.
### Getting Started
Decide where you want to execute the game, and make sure you have write permissions. The game will connect to an instance and attempt to establish an OAuth flow, asking you to visit a link and authorise the application with your mastodon/fedi account.
1. Install Rust and clone this repository.
Once this is done, the information is written into a toml file, which *should* remain private, as it contains a token that allows for almost full control of the account it's authorised under.
2. Run `cargo run --bin game_cli` to exercise the games locally via stdin.
On subsequent runs, if this file is encountered, the information will be read from it and the connection will be realised without human intervention.
The CLI harness accepts input in the form `acct@example.com: command` and
prints bot responses, which is helpful for development.
3. To connect to Mastodon, ensure you have an account on your target instance
and execute `cargo run --bin pravda`. The first run walks you through the
OAuth flow and stores credentials in `mastodon-data.toml` (keep it private).
4. Update `ADMIN`, `QUIT`, and `INSTANCE` in `src/main.rs` to match your desired
deployment values before going live.
### Limitations.
### Development Workflow
It is not possible to connect this client to GoTosocial for now. mastodon-async does not use the websocket endpoint to stream from the fedi, but the SSE endpoint instead. GoToSocial only implements the websocket endpoint for streaming operations.
- Run `cargo fmt` and `cargo clippy --all-targets` to keep formatting and
Naturally, it supports both HTTP and HTTPS, through the use of rustls-tls by default. You can change to OpenSSL by modifying the features in Cargo.toml.
lints tidy.
- Execute `cargo test` before committing. Unit tests sit next to the modules
they exercise.
- Use `cargo run --bin game_cli` for fast manual testing; most command flows can
be simulated locally without touching the network.
### Future ambitions.
### Security & Operational Notes
I'm interested in implementing any sort of social game, by which I understand games which involve social interaction, deception, prediction, or the like. In particular, I am interested in implementing the following games:
- Outbound statuses are normalised and truncated before posting; nevertheless,
run the bot from a dedicated account with scoped tokens (read:notifications,
write:statuses, follow).
- The bot ignores mentions originating from itself to avoid event loops.
- When adding new games, sanitise any user-controlled text before including it
in replies.
### Extending Pravda
* [Spoof](https://en.wikipedia.org/wiki/Spoof_(game\)) (in progress on the spoof branch).
* [Prisoner's dilemma](https://en.wikipedia.org/wiki/Prisoner%27s_dilemma).
* [Centipede game](https://en.wikipedia.org/wiki/Centipede_game).
* [Public goods game](https://en.wikipedia.org/wiki/Public_goods_game).
* [Traveller's dilemma](https://en.wikipedia.org/wiki/Traveler%27s_dilemma).
* [Ultimatum game](https://en.wikipedia.org/wiki/Ultimatum_game).
* [Dictator game](https://en.wikipedia.org/wiki/Dictator_game)
* [Mafia](https://en.wikipedia.org/wiki/Mafia_(party_game\)).
* Unique lowest bid.
To create a new game:
1. Add a module under `src/` that implements `Game`.
2. Register it in `src/catalog.rs::default_games` so both the bot and CLI know
about it.
* Guess 2/3 the average.
* Predict the judgement.
3. Emit appropriate replies via the provided `Reply` type. If you need timers,
schedule your own tasks and cancel them when the game ends (see
`src/soviet.rs` for an example).
4. Document the commands in this README so players know how to interact.
Some of these games need more interesting names.
Unit tests live alongside their games. Existing tests illustrate how to drive
command sequences without Mastodon.
It would be nice to run a nomic on the fedi, but that is a lot more than a bot can do by itself.
### Planned Work
## Bug reports, feature requests, code contributions and other feedback.
- Balance tuning for the Soviet Mafia roles and better test coverage for
probabilistic flows.
- Additional social experiments such as Prisoner's Dilemma, Centipede, and
Nomic-style rule systems.
If you want to tell me something about the crate, the best ways are:
### Support & Feedback
* My fedi account, [@modulux@node.isonomia.net](https://node.isonomia.net/@modulux).
* The [fossil repository](https://modulus.isonomia.net/pravda.cgi) for the project.
* If you must, email me at modulus at isonomia dot net.
- Mastodon: [@modulux@node.isonomia.net](https://node.isonomia.net/@modulux)
- Fossil repo: <https://modulus.isonomia.net/pravda.cgi>
- Email: modulus at isonomia dot net
## Change log.
### Changelog
* Unreleased
* Added Unique Lowest Bid, Two Thirds Average, and Soviet Mafia games.
* Hardened outbound post handling and added a shared game manager.
* V 0.2.0: Spoof is implemented.
* V0.2.0 – Spoof
* V 0.1.3: dice can be rolled with the dice command, accepting an ndm optional parameter.
* V 0.1.2: exponential backoff system for cases where the streaming API fails. Assorted typographical corrections.
* V 0.1.1: set a loop around the toot streaming in case it errors out.
* V 0.1.0: initial release.
* V0.1.3 – Dice roll command (`dice`, `dice NdM`)
* V0.1.2 – Streaming backoff and assorted fixes
* V0.1.1 – Wrapped streaming in retry loop
* V0.1.0 – Initial release
|