multiple_participants/
multiple_participants.rs

1use par::{
2    exchange::{Recv, Send},
3    runtimes::tokio::fork,
4    Dual,
5};
6use std::time::Duration;
7
8#[derive(Debug)]
9enum Move {
10    Up,
11    Down,
12}
13
14enum Outcome {
15    Win,
16    Loss,
17    Draw(Round),
18}
19
20type Round = Send<Move, Recv<Outcome>>;
21type Player = Dual<Round>; // Recv<Move, Send<Outcome>>
22
23#[derive(Debug)]
24enum Winner {
25    First,
26    Second,
27    Third,
28}
29
30type Game = Send<(Player, Player, Player), Recv<Winner>>;
31
32fn start_playing() -> Game {
33    use {Move::*, Outcome::*, Winner::*};
34
35    fork(|game: Dual<Game>| async {
36        let ((mut player1, mut player2, mut player3), winner) = game.recv().await;
37
38        loop {
39            let (move1, outcome1) = player1.recv().await;
40            let (move2, outcome2) = player2.recv().await;
41            let (move3, outcome3) = player3.recv().await;
42
43            tokio::time::sleep(Duration::from_secs(1)).await;
44            println!("{:?} {:?} {:?}", move1, move2, move3);
45            tokio::time::sleep(Duration::from_secs(1)).await;
46
47            match (move1, move2, move3) {
48                (Up, Down, Down) | (Down, Up, Up) => {
49                    outcome1.send1(Win);
50                    outcome2.send1(Loss);
51                    outcome3.send1(Loss);
52                    break winner.send1(First);
53                }
54                (Down, Up, Down) | (Up, Down, Up) => {
55                    outcome1.send1(Loss);
56                    outcome2.send1(Win);
57                    outcome3.send1(Loss);
58                    break winner.send1(Second);
59                }
60                (Down, Down, Up) | (Up, Up, Down) => {
61                    outcome1.send1(Loss);
62                    outcome2.send1(Loss);
63                    outcome3.send1(Win);
64                    break winner.send1(Third);
65                }
66                (Up, Up, Up) | (Down, Down, Down) => {
67                    player1 = outcome1.choose(Draw);
68                    player2 = outcome2.choose(Draw);
69                    player3 = outcome3.choose(Draw);
70                    println!("Draw...");
71                }
72            }
73        }
74    })
75}
76
77fn random_player() -> Player {
78    fork(|mut round: Round| async move {
79        while let Outcome::Draw(next_round) = round.send(random_move()).recv1().await {
80            round = next_round;
81        }
82    })
83}
84
85fn random_move() -> Move {
86    if fastrand::bool() {
87        Move::Up
88    } else {
89        Move::Down
90    }
91}
92
93#[tokio::main]
94async fn main() {
95    for _ in 0..10 {
96        let winner = start_playing()
97            .send((random_player(), random_player(), random_player()))
98            .recv1()
99            .await;
100        println!("{:?}!\n", winner);
101    }
102}