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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
//! 玩家端。

use inquire::Text;
pub mod comm;
use comm::Client;
use indicatif::{ProgressBar, ProgressStyle};
use crossterm::terminal::{Clear, ClearType};
use std::io::{self, stdout, Read};
pub mod villager;
use villager::Villager;
pub mod werewolf;
use werewolf::Werewolf;
pub mod hunter;
use hunter::Hunter;
use comm::Message;


pub struct Player {
    cli: Client,
    id: u64,
    username: String,
    role: Box<dyn Role>,
}

trait Role {
    fn born(&self, _id: u64, _username: String) {}

    fn night(&self, cli: &mut Client)  {
        let _night_over = cli.end();
        pause();
    }

    fn day(&self, cli: &mut Client) {
        cli.begin();
        loop {
            let msg = cli.receive();
            match msg {
                Message::Begin => {
                    let inq = Text::new("发言:").prompt().unwrap();
                    cli.transimit(Message::Text(inq));
                }
                Message::Text(s) => println!("{s:}"),
                Message::End => break,
                _ => panic!("error rece type"),
            }
        }
        loop {
            let msg = cli.receive();
            match msg {
                Message::Begin => comm::vote(cli),
                Message::Text(s) => println!("{s:}"),
                Message::End => break,
                _ => panic!("error rece type"),
            }
        }
    }

    fn dead(&self, cli: &mut Client) {
        let msg = cli.receive().unwrap();
        let inq = Text::new(&msg).prompt().unwrap();
        cli.transimit(Message::Text(inq));
        watch(cli);
    }
}

fn watch(cli: &mut Client) {
    println!("[观战模式]");
    loop {
        let msg = cli.receive();
        if let Message::Text(s) = msg {
            println!("{s:}");
            if s == "好人胜利" || s == "狼人胜利" {
                break;
            }
        }
    }
    pause();
    std::process::exit(0);
}

/// 没有分配角色前的角色。
struct RawRole { }

impl Role for RawRole { }

fn pause() {
    let mut stdin = io::stdin();
    println!("按回车继续。");
    // Read a single byte and discard
    let _ = stdin.read(&mut [0u8]).unwrap();
}

impl Player {
    pub fn new() -> Self {
        let addr ;
        #[cfg(not(debug_assertions))] 
        {
            addr = Text::new("服务器地址").prompt().unwrap();
        }
        #[cfg(debug_assertions)]
        {
            addr = "127.0.0.1:8080".to_string();
        }
        let username = Text::new("昵称").prompt().unwrap();
        let mut cli = Client::new(addr);
        let id = cli.rec_number();
        let role = Box::new(RawRole {});
        Player { cli, id, username, role }
    }

    fn wait_connect(&mut self) {
        let mut cur_player_cnt = self.id;
        let player_num = self.cli.rec_number();
        println!("等待其它玩家连接");
        let style = ProgressStyle::with_template("{bar:20} {pos:}/{len:}").unwrap();
        let pb = ProgressBar::new(player_num).with_style(style);
        pb.set_position(cur_player_cnt);
        while cur_player_cnt != player_num {
            self.cli.rec();
            pb.inc(1);
            cur_player_cnt += 1;
        }
        pb.finish();
    }

    fn reply_username(&mut self) {
        self.cli.transimit(Message::Text(self.username.clone()));
    }

    fn map_role(s: String) -> Box<dyn Role> {
        match s.as_str() {
            "平民" => Box::new(Villager::new()),
            "狼人" => Box::new(Werewolf::new()),
            "猎人" => Box::new(Hunter::new()),
            _ => panic!("error communicate"),
        }
    }

    fn get_role(&mut self) {
        let role_name = self.cli.receive().unwrap();
        self.role = Self::map_role(role_name);
        self.role.born(self.id, self.username.clone());
    }

    pub fn init(mut self) {
        self.wait_connect();
        self.reply_username();
        self.get_role();
        self.play();
    }

    /// 检查游戏是否结束。
    fn is_over(cli: &mut Client) {
        let status = cli.receive();
        match status {
            Message::End => return,
            _ => {
                println!("{}", status.unwrap());
                pause();
                std::process::exit(0);
            }
        }
    }

    /// 检查死亡。为了处理多个死亡的情形已经方便死亡提示,当收到开始信号后再进行死亡动作,其它消息直接输出。
    fn check_death(role: &mut Box<dyn Role>, cli: &mut Client) {
        loop {
            let msg = cli.receive();
            match msg {
                Message::Begin => role.dead(cli),
                Message::Text(s) => println!("{s:}"),
                Message::End => break,
                _ => panic!("error rece type"),
            }
        }
    }

    /// 清空屏幕。
    fn clear() {
        crossterm::execute!(stdout(), Clear(ClearType::All)).unwrap();
    }

    fn play(&mut self) {
        pause();
        Self::clear();
        println!("天黑请闭眼。");
        loop {
            self.role.night(&mut self.cli);
            Self::clear();
            println!("天亮了。");
            Self::check_death(&mut self.role, &mut self.cli);
            Self::is_over(&mut self.cli);
            self.role.day(&mut self.cli);
            Self::check_death(&mut self.role, &mut self.cli);
            Self::is_over(&mut self.cli);
            Self::clear();
            pause();
            println!("天黑请闭眼。");
        }
    }
}