2024-05-04 19:15:35 +08:00
|
|
|
pub mod skills;
|
2024-05-12 10:40:10 +08:00
|
|
|
pub mod utils;
|
2024-05-04 19:15:35 +08:00
|
|
|
|
2024-05-04 20:28:27 +08:00
|
|
|
use std::fmt::Display;
|
|
|
|
|
2024-05-04 19:37:17 +08:00
|
|
|
use crate::rc4::RC4;
|
|
|
|
|
2024-05-04 19:15:35 +08:00
|
|
|
pub struct PlayerStatus {
|
2024-05-04 20:28:27 +08:00
|
|
|
/// 是否被冻结
|
2024-05-04 19:15:35 +08:00
|
|
|
frozen: bool,
|
2024-05-04 20:28:27 +08:00
|
|
|
/// 是否存活
|
|
|
|
alive: bool,
|
|
|
|
/// 血量
|
|
|
|
hp: u32,
|
|
|
|
/// 分数
|
|
|
|
point: u32,
|
2024-05-04 19:15:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for PlayerStatus {
|
|
|
|
fn default() -> Self {
|
2024-05-04 20:28:27 +08:00
|
|
|
PlayerStatus {
|
|
|
|
frozen: false,
|
|
|
|
alive: true,
|
|
|
|
hp: 0,
|
|
|
|
point: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for PlayerStatus {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
write!(
|
|
|
|
f,
|
|
|
|
"PlayerStatus{{{},{} hp: {}, point: {} }}",
|
|
|
|
// 冻结/正常
|
|
|
|
// 存活/死亡
|
|
|
|
if self.frozen { "冻结" } else { "正常" },
|
|
|
|
if self.alive { "存货" } else { "死亡" },
|
|
|
|
self.hp,
|
|
|
|
self.point
|
|
|
|
)
|
2024-05-04 19:15:35 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-04 17:28:19 +08:00
|
|
|
pub struct Player {
|
2024-05-04 20:28:27 +08:00
|
|
|
/// 队伍
|
2024-05-04 17:56:33 +08:00
|
|
|
team: String,
|
2024-05-04 20:28:27 +08:00
|
|
|
/// 玩家名
|
2024-05-04 17:56:33 +08:00
|
|
|
name: String,
|
2024-05-04 20:28:27 +08:00
|
|
|
/// 武器
|
|
|
|
weapon: Option<String>,
|
|
|
|
/// 玩家类型
|
2024-05-04 17:56:33 +08:00
|
|
|
player_type: PlayerType,
|
2024-05-04 19:15:35 +08:00
|
|
|
/// skl id
|
|
|
|
skil_id: Vec<u32>,
|
|
|
|
/// skl prop
|
|
|
|
skil_prop: Vec<u32>,
|
|
|
|
/// 玩家状态
|
2024-05-04 20:28:27 +08:00
|
|
|
///
|
2024-05-04 19:15:35 +08:00
|
|
|
/// 主要是我懒得加一大堆字段
|
|
|
|
status: PlayerStatus,
|
2024-05-04 17:28:19 +08:00
|
|
|
}
|
|
|
|
|
2024-05-04 17:56:33 +08:00
|
|
|
pub const BOSS_NAMES: [&str; 11] = [
|
|
|
|
"mario", "sonic", "mosquito", "yuri", "slime", "ikaruga", "conan", "aokiji", "lazy", "covid", "saitama",
|
|
|
|
];
|
|
|
|
|
2024-05-12 10:40:10 +08:00
|
|
|
// ["田一人", 18, "云剑狄卡敢", 25, "云剑穸跄祇", 35]
|
|
|
|
pub const BOOST_NAMES: [&str; 3] = ["云剑狄卡敢", "云剑穸跄祇", "田一人"];
|
|
|
|
|
|
|
|
#[derive(Default, PartialEq, Eq, Debug)]
|
2024-05-04 17:28:19 +08:00
|
|
|
pub enum PlayerType {
|
|
|
|
#[default]
|
|
|
|
Normal,
|
2024-05-04 17:41:59 +08:00
|
|
|
/// 种子玩家
|
2024-05-04 17:56:33 +08:00
|
|
|
///
|
2024-05-04 17:41:59 +08:00
|
|
|
/// # marker: `seed:`
|
|
|
|
Seed,
|
|
|
|
/// 被克隆的玩家
|
2024-05-04 17:56:33 +08:00
|
|
|
///
|
|
|
|
/// 似乎有个三种?
|
2024-05-04 17:41:59 +08:00
|
|
|
Clone,
|
|
|
|
/// Boss 玩家
|
|
|
|
/// 其实应该是一大堆
|
|
|
|
Boss,
|
|
|
|
/// 被特殊增强的玩家
|
2024-05-04 17:56:33 +08:00
|
|
|
///
|
2024-05-04 19:37:17 +08:00
|
|
|
/// 有一堆玩家都被增强了
|
2024-05-04 17:41:59 +08:00
|
|
|
Boost,
|
|
|
|
/// 标准测号用靶子
|
2024-05-04 17:56:33 +08:00
|
|
|
///
|
2024-05-04 17:41:59 +08:00
|
|
|
/// # marker: `\u0002`
|
|
|
|
Test1,
|
|
|
|
/// 没用到的测号用玩家
|
2024-05-04 17:56:33 +08:00
|
|
|
///
|
2024-05-04 17:41:59 +08:00
|
|
|
/// # marker: `\u0003`
|
|
|
|
Test2,
|
|
|
|
/// 比标准测号再强一点的测号用靶子
|
2024-05-04 17:56:33 +08:00
|
|
|
///
|
2024-05-04 17:41:59 +08:00
|
|
|
/// # marker: `!`
|
|
|
|
TestEx,
|
2024-05-04 17:28:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Player {
|
2024-05-04 20:28:27 +08:00
|
|
|
pub fn new(team: String, name: String, weapon: Option<String>) -> Self {
|
2024-05-04 17:56:33 +08:00
|
|
|
let player_type = {
|
2024-05-04 19:15:35 +08:00
|
|
|
match team.as_str() {
|
|
|
|
"!" => {
|
|
|
|
if BOSS_NAMES.contains(&name.as_str()) {
|
|
|
|
PlayerType::Boss
|
2024-05-12 10:40:10 +08:00
|
|
|
} else if BOOST_NAMES.contains(&name.as_str()) {
|
|
|
|
PlayerType::Boost
|
|
|
|
} else if name.starts_with("seed:") {
|
|
|
|
PlayerType::Seed
|
2024-05-04 19:15:35 +08:00
|
|
|
} else {
|
|
|
|
// 高强度测号用靶子
|
|
|
|
PlayerType::TestEx
|
|
|
|
}
|
|
|
|
}
|
|
|
|
"\u{0002}" => PlayerType::Test1,
|
|
|
|
"\u{0003}" => PlayerType::Test2,
|
|
|
|
_ => {
|
|
|
|
if name.starts_with("seed:") {
|
|
|
|
PlayerType::Seed
|
|
|
|
} else {
|
|
|
|
PlayerType::Normal
|
2024-05-04 17:56:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2024-05-04 17:28:19 +08:00
|
|
|
Player {
|
|
|
|
team,
|
|
|
|
name,
|
|
|
|
weapon,
|
2024-05-04 17:56:33 +08:00
|
|
|
player_type,
|
2024-05-04 19:15:35 +08:00
|
|
|
skil_id: vec![],
|
|
|
|
skil_prop: vec![],
|
|
|
|
status: PlayerStatus::default(),
|
2024-05-04 17:28:19 +08:00
|
|
|
}
|
|
|
|
}
|
2024-05-04 17:56:33 +08:00
|
|
|
|
2024-05-06 21:57:24 +08:00
|
|
|
/// 直接从一个名竞的原始输入创建一个 Player
|
|
|
|
///
|
|
|
|
/// # 要求
|
|
|
|
/// 不许有 \n
|
|
|
|
///
|
|
|
|
/// 可能的输入格式:
|
|
|
|
/// - <name>
|
|
|
|
/// - <name>@<team>
|
|
|
|
/// - <name>+<weapon>
|
|
|
|
/// - <name>+<weapon>+diy{xxxxx}
|
|
|
|
/// - <name>@<team>+<weapon>
|
|
|
|
/// - <name>@<team>+<weapon>+diy{xxxxx}
|
|
|
|
pub fn new_from_namerena_raw(raw_name: String) -> Self {
|
|
|
|
// 先判断是否有 + 和 @
|
|
|
|
if !raw_name.contains("@") && !raw_name.contains("+") {
|
|
|
|
return Player::new(raw_name.clone(), raw_name.clone(), None);
|
|
|
|
}
|
|
|
|
// 区分队伍名
|
|
|
|
let name: &str;
|
|
|
|
let mut team: &str;
|
|
|
|
let weapon: Option<&str>;
|
|
|
|
if raw_name.contains("@") {
|
|
|
|
(name, team) = raw_name.split_once("@").unwrap();
|
2024-05-08 00:08:10 +08:00
|
|
|
// 判定武器
|
|
|
|
if team.contains("+") {
|
2024-05-12 10:40:10 +08:00
|
|
|
let tmp;
|
|
|
|
(team, tmp) = team.split_once("+").unwrap();
|
|
|
|
weapon = Some(tmp);
|
2024-05-08 00:08:10 +08:00
|
|
|
} else {
|
|
|
|
weapon = None;
|
|
|
|
}
|
|
|
|
} else {
|
2024-05-12 10:40:10 +08:00
|
|
|
team = raw_name.as_str();
|
2024-05-08 00:08:10 +08:00
|
|
|
// 没有队伍名, 直接是武器
|
|
|
|
if team.contains("+") {
|
2024-05-12 10:40:10 +08:00
|
|
|
let tmp;
|
|
|
|
(name, tmp) = raw_name.split_once("+").unwrap();
|
|
|
|
weapon = Some(tmp);
|
2024-05-08 00:08:10 +08:00
|
|
|
team = name;
|
|
|
|
} else {
|
2024-05-12 10:40:10 +08:00
|
|
|
name = team;
|
2024-05-08 00:08:10 +08:00
|
|
|
weapon = None;
|
|
|
|
}
|
2024-05-06 21:57:24 +08:00
|
|
|
}
|
2024-05-12 10:40:10 +08:00
|
|
|
Player::new(team.to_string(), name.to_string(), weapon.map(|s| s.to_string()))
|
2024-05-06 21:57:24 +08:00
|
|
|
}
|
|
|
|
|
2024-05-04 17:56:33 +08:00
|
|
|
pub fn update_player(&mut self) {}
|
2024-05-04 19:37:17 +08:00
|
|
|
|
2024-05-04 20:28:27 +08:00
|
|
|
pub fn step(&mut self, randomer: &mut RC4) {}
|
2024-05-04 17:28:19 +08:00
|
|
|
}
|
2024-05-12 10:40:10 +08:00
|
|
|
|
|
|
|
impl Display for Player {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
write!(f, "Player{{{}@{}{}, status: {}}}",
|
|
|
|
self.name,
|
|
|
|
self.team,
|
|
|
|
if let Some(weapon) = &self.weapon {
|
|
|
|
format!("+{}", weapon)
|
|
|
|
} else {
|
|
|
|
"".to_string()
|
|
|
|
},
|
|
|
|
self.status
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
/// 测试根据原始输入创建 Player
|
|
|
|
fn player_raw_new() {
|
|
|
|
let player = Player::new_from_namerena_raw("mario".to_string());
|
|
|
|
assert_eq!(player.name, "mario");
|
|
|
|
assert_eq!(player.team, "mario");
|
|
|
|
assert_eq!(player.weapon, None);
|
|
|
|
assert_eq!(player.player_type, PlayerType::Normal);
|
|
|
|
|
|
|
|
let player = Player::new_from_namerena_raw("mario@red".to_string());
|
|
|
|
println!("{}", player);
|
|
|
|
assert_eq!(player.name, "mario");
|
|
|
|
assert_eq!(player.team, "red");
|
|
|
|
assert_eq!(player.weapon, None);
|
|
|
|
assert_eq!(player.player_type, PlayerType::Normal);
|
|
|
|
|
|
|
|
let player = Player::new_from_namerena_raw("mario+fire".to_string());
|
|
|
|
assert_eq!(player.name, "mario");
|
|
|
|
assert_eq!(player.team, "mario");
|
|
|
|
assert_eq!(player.weapon, Some("fire".to_string()));
|
|
|
|
assert_eq!(player.player_type, PlayerType::Normal);
|
|
|
|
|
|
|
|
let player = Player::new_from_namerena_raw("mario+fire+diy{xxxx}".to_string());
|
|
|
|
assert_eq!(player.name, "mario");
|
|
|
|
assert_eq!(player.team, "mario");
|
|
|
|
assert_eq!(player.weapon, Some("fire+diy{xxxx}".to_string()));
|
|
|
|
assert_eq!(player.player_type, PlayerType::Normal);
|
|
|
|
|
|
|
|
let player = Player::new_from_namerena_raw("mario@red+fire".to_string());
|
|
|
|
assert_eq!(player.name, "mario");
|
|
|
|
assert_eq!(player.team, "red");
|
|
|
|
assert_eq!(player.weapon, Some("fire".to_string()));
|
|
|
|
assert_eq!(player.player_type, PlayerType::Normal);
|
|
|
|
|
|
|
|
let player = Player::new_from_namerena_raw("mario@red+fire+diy{xxxx}".to_string());
|
|
|
|
assert_eq!(player.name, "mario");
|
|
|
|
assert_eq!(player.team, "red");
|
|
|
|
assert_eq!(player.weapon, Some("fire+diy{xxxx}".to_string()));
|
|
|
|
assert_eq!(player.player_type, PlayerType::Normal);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
pub fn player_raw_types() {
|
|
|
|
let player = Player::new_from_namerena_raw("normal@normal".to_string());
|
|
|
|
assert_eq!(player.player_type, PlayerType::Normal);
|
|
|
|
|
|
|
|
// seed
|
|
|
|
let player = Player::new_from_namerena_raw("seed:just seed@!".to_string());
|
|
|
|
assert_eq!(player.name, "seed:just seed");
|
|
|
|
assert_eq!(player.player_type, PlayerType::Seed);
|
|
|
|
|
|
|
|
// testEx
|
|
|
|
let player = Player::new_from_namerena_raw("testEx@!".to_string());
|
|
|
|
assert_eq!(player.player_type, PlayerType::TestEx);
|
|
|
|
|
|
|
|
// test1
|
|
|
|
let player = Player::new_from_namerena_raw("test1@\u{0002}".to_string());
|
|
|
|
assert_eq!(player.team, "\u{0002}".to_string());
|
|
|
|
assert_eq!(player.player_type, PlayerType::Test1);
|
|
|
|
|
|
|
|
// test2
|
|
|
|
let player = Player::new_from_namerena_raw("test2@\u{0003}".to_string());
|
|
|
|
assert_eq!(player.team, "\u{0003}".to_string());
|
|
|
|
assert_eq!(player.player_type, PlayerType::Test2);
|
|
|
|
|
|
|
|
// boss
|
|
|
|
let player = Player::new_from_namerena_raw("mario@!".to_string());
|
|
|
|
assert_eq!(player.player_type, PlayerType::Boss);
|
|
|
|
|
|
|
|
// boosted
|
|
|
|
let player = Player::new_from_namerena_raw("云剑狄卡敢@!".to_string());
|
|
|
|
assert_eq!(player.player_type, PlayerType::Boost);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|