From 82a42d08240c138703fa6f5b03f31d249a19f1da Mon Sep 17 00:00:00 2001 From: sheagrief <3a.mad1earth4@gmail.com> Date: Tue, 5 Nov 2024 21:43:53 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=90=9B=20Fix:=20error=20caused=20by?= =?UTF-8?q?=20registered=20names=20of=20different=20lengths.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/werewolf_cli/main.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/examples/werewolf_cli/main.rs b/examples/werewolf_cli/main.rs index 4a22736..94afde3 100644 --- a/examples/werewolf_cli/main.rs +++ b/examples/werewolf_cli/main.rs @@ -98,6 +98,9 @@ fn register_players() -> Vec { if name.is_empty() { println!("Player name is empty."); continue; + } else if name.len() >= 20 { + println!("Player name must be less than 20 characters."); + continue; } else { break; } @@ -108,7 +111,12 @@ fn register_players() -> Vec { name ); - Net::broadcast(&name) + let mut bytes = vec![0u8; 20]; + bytes[..name.len()].copy_from_slice(name.as_bytes()); + Net::broadcast(&bytes) + .into_iter() + .map(|b| String::from_utf8_lossy(&b[..]).to_string()) + .collect() } fn night_phase(game: &mut Game) { From f8ccefb42cfd03fcd60c852eb1a86f05163fa59a Mon Sep 17 00:00:00 2001 From: sheagrief <3a.mad1earth4@gmail.com> Date: Wed, 6 Nov 2024 23:14:05 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=93=9D=20Update:=20translate=20Japane?= =?UTF-8?q?se=20text=20into=20English=20associated=20with=20werewolf?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/werewolf_cli/game.rs | 33 +++++++++++++++------------- examples/werewolf_cli/game/role.rs | 4 ++-- examples/werewolf_cli/main.rs | 35 ++++++++++++++---------------- src/werewolf/types.rs | 6 ++--- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/examples/werewolf_cli/game.rs b/examples/werewolf_cli/game.rs index dc2205f..50001f7 100644 --- a/examples/werewolf_cli/game.rs +++ b/examples/werewolf_cli/game.rs @@ -245,9 +245,9 @@ impl Game { } if werewolf_count == 0 { - Some("村人".to_string()) + Some("Villagers side".to_string()) } else if werewolf_count >= villager_count { - Some("人狼".to_string()) + Some("Werewolves side".to_string()) } else { None } @@ -376,11 +376,14 @@ impl Game { { target.mark_for_death(); if am_werewolf { - events.push(format!("人狼が{}を襲撃対象に選びました。", target.name)); + events.push(format!( + "The werewolf has chosen {} as their target.", + target.name + )); } } else { if am_werewolf { - events.push("無効な襲撃対象が選択されました。".to_string()); + events.push("Invalid target was selected.".to_string()); } } @@ -407,19 +410,19 @@ impl Game { Fr::from(p.id as i32) == target_id.reveal() && p.is_alive && p.id != seer.id }) { let role_name = if target.is_werewolf() { - "人狼" + "Werewolf" } else { - "人狼ではない" + "Not Werewolf" }; if am_fortune_teller { events.push(format!( - "占い師が{}を占いました。結果:{}", + "The fortune teller divined {}. Result: {}", target.name, role_name )); } } else { if am_fortune_teller { - events.push("無効な占い対象が選択されました。".to_string()); + events.push("Invalid divination target was selected.".to_string()); } } } @@ -432,20 +435,20 @@ impl Game { for player in &mut self.state.players { if player.marked_for_death.reveal().is_one() && player.is_alive { player.kill(self.state.day); - events.push(format!("{}が無残な姿で発見されました。", player.name)); + events.push(format!("{} was found dead.", player.name)); player.marked_for_death = MpcBooleanField::pub_false(); } } if events.is_empty() { - events.push("昨夜は誰も襲撃されませんでした。".to_string()); + events.push("No one was attacked last night.".to_string()); } events } pub fn discussion_phase(&self) -> Vec { - vec!["討論フェーズが始まりました。".to_string()] + vec!["The discussion phase has begun.".to_string()] } pub fn voting_phase(&mut self, votes: Vec, is_prove: bool) -> Vec { @@ -456,14 +459,14 @@ impl Game { if voter.is_alive { vote_count[target] += 1; events.push(format!( - "{}が{}に投票しました。", + "{} voted for {}.", voter.name, self.state.players[target].name )); } } let max_votes = *vote_count.iter().max().unwrap(); - // 最大票数を持つプレイヤーを見つける。投票が同数の場合は + // Find the player with the maximum number of votes. let max_voted_indexes = self .state .players @@ -481,14 +484,14 @@ impl Game { let executed_index = if max_voted_indexes.len() == 1 { max_voted_indexes[0] } else { - // 投票が同数の場合は、ランダムに一人処刑される + // If there are multiple players with the same number of votes, one player is executed randomly. let random_index = rand::thread_rng().gen_range(0..max_voted_indexes.len()); max_voted_indexes[random_index] }; let player = &mut self.state.players[executed_index]; player.kill(self.state.day); - events.push(format!("{}が処刑されました。", player.name)); + events.push(format!("{} was executed.", player.name)); if is_prove { let votes = votes diff --git a/examples/werewolf_cli/game/role.rs b/examples/werewolf_cli/game/role.rs index 9157aea..71f37ea 100644 --- a/examples/werewolf_cli/game/role.rs +++ b/examples/werewolf_cli/game/role.rs @@ -14,7 +14,7 @@ pub fn assign_roles(player_count: usize, rules: &GameRules) -> Vec { let werewolf_count = (player_count as f32 * rules.werewolf_ratio).round() as usize; let seer_count = rules.seer_count; - // 役割を割り当てる + // assign roles for role in roles.iter_mut().take(werewolf_count) { *role = Role::Werewolf; } @@ -23,7 +23,7 @@ pub fn assign_roles(player_count: usize, rules: &GameRules) -> Vec { *role = Role::FortuneTeller; } - // ランダムに並び替える + // Shuffle randomly roles.shuffle(&mut rng); roles diff --git a/examples/werewolf_cli/main.rs b/examples/werewolf_cli/main.rs index 94afde3..3d54c65 100644 --- a/examples/werewolf_cli/main.rs +++ b/examples/werewolf_cli/main.rs @@ -24,9 +24,6 @@ struct Opt { } fn main() -> Result<(), Box> { - // let stream = TcpStream::connect("127.0.0.1:8080").await?; - // println!("サーバーに接続しました。"); - let opt = Opt::from_args(); // init @@ -120,7 +117,7 @@ fn register_players() -> Vec { } fn night_phase(game: &mut Game) { - println!("\n--- 夜のフェーズ ---"); + println!("\n--- Night Phase ---"); let players = game.state.players.clone(); let player = players.iter().find(|p| p.id == Net::party_id()).unwrap(); @@ -156,7 +153,7 @@ fn night_phase(game: &mut Game) { } fn wait_for_enter() { - println!("Enterキーを押して次に進んでください。"); + println!("Press Enter to continue."); let mut input = String::new(); io::stdin().read_line(&mut input).unwrap(); } @@ -176,7 +173,7 @@ fn get_werewolf_target(game: &Game, player: &Player) -> MFr { if player.role.unwrap().is_werewolf() { println!( - "{}さん、あなたは人狼です。襲撃する対象を選んでください:", + "{}, you are a werewolf. Choose your target to attack:", player.name ); game.state @@ -186,7 +183,7 @@ fn get_werewolf_target(game: &Game, player: &Player) -> MFr { .for_each(|p| println!("{}: {}", p.id, p.name)); loop { - print!("対象のIDを入力してください: "); + print!("Enter the ID of your target: "); io::stdout().flush().unwrap(); let mut input = String::new(); @@ -201,7 +198,7 @@ fn get_werewolf_target(game: &Game, player: &Player) -> MFr { { break; } else { - println!("無効な選択です。もう一度選んでください。"); + println!("Invalid selection. Please choose again."); } } } else { @@ -216,7 +213,7 @@ fn get_seer_target(game: &Game, player: &Player) -> MFr { if player.role.unwrap() == Role::FortuneTeller { println!( - "{}さん、あなたは占い師です。占う対象を選んでください:", + "{}, you are a fortune teller. Choose a target to divine:", player.name ); game.state @@ -226,7 +223,7 @@ fn get_seer_target(game: &Game, player: &Player) -> MFr { .for_each(|p| println!("{}: {}", p.id, p.name)); loop { - print!("対象のIDを入力してください: "); + print!("Enter the ID of your target: "); io::stdout().flush().unwrap(); let mut input = String::new(); @@ -241,7 +238,7 @@ fn get_seer_target(game: &Game, player: &Player) -> MFr { { break; } else { - println!("無効な選択です。もう一度選んでください。"); + println!("Invalid selection. Please choose again."); } } } else { @@ -259,26 +256,26 @@ fn morning_phase(game: &mut Game) { } fn discussion_phase(game: &Game) { - println!("\n--- 討論フェーズ ---"); + println!("\n--- Discussion Phase ---"); let events = game.discussion_phase(); for event in events { println!("{}", event); } - println!("生存しているプレイヤー:"); + println!("Players still alive:"); game.state .players .iter() .filter(|p| p.is_alive) .for_each(|p| println!("{}: {}", p.id, p.name)); - println!("討論を行ってください。準備ができたらEnterキーを押してください。"); + println!("Please discuss. Press Enter when you are ready."); let mut input = String::new(); io::stdin().read_line(&mut input).unwrap(); } fn voting_phase(game: &mut Game) { - println!("\n--- 投票フェーズ ---"); + println!("\n--- Voting Phase ---"); let vote; let players = game.state.players.clone(); @@ -286,7 +283,7 @@ fn voting_phase(game: &mut Game) { let player = players.iter().find(|p| p.id == Net::party_id()).unwrap(); if player.is_alive { - println!("{}さん、投票する対象を選んでください:", player.name); + println!("{} please choose who to vote for:", player.name); game.state .players .iter() @@ -294,7 +291,7 @@ fn voting_phase(game: &mut Game) { .for_each(|p| println!("{}: {}", p.id, p.name)); loop { - print!("対象のIDを入力してください: "); + print!("Please enter the ID of the player you want to vote for: "); io::stdout().flush().unwrap(); let mut input = String::new(); @@ -310,11 +307,11 @@ fn voting_phase(game: &mut Game) { vote = target_id; break; } else { - println!("無効な選択です。もう一度選んでください。"); + println!("Invalid selection. Please choose again."); } } } else { - vote = usize::MAX; // 死亡したプレイヤーの投票は無効 + vote = usize::MAX; // The vote of a dead player is invalid. } clear_screen(); diff --git a/src/werewolf/types.rs b/src/werewolf/types.rs index 281443a..4cdc6b0 100644 --- a/src/werewolf/types.rs +++ b/src/werewolf/types.rs @@ -13,9 +13,9 @@ pub enum Role { impl Role { pub fn description(&self) -> &'static str { match self { - Role::Villager => "村人:特別な能力はありませんが、議論と投票に参加します。", - Role::Werewolf => "人狼:夜に村人を襲撃します。昼は村人のふりをします。", - Role::FortuneTeller => "占い師:夜に一人のプレイヤーの役割を知ることができます。", + Role::Villager => "Villager: They have no special abilities, but they participate in discussions and voting.", + Role::Werewolf => "Werewolf: They attack villagers at night. They pretend to be villagers during the day.", + Role::FortuneTeller => "Fortune Teller: They can know whether a player is a werewolf or not at night.", } } From 0dbee2c10bcad8e9a937f65138ec4197ae133028 Mon Sep 17 00:00:00 2001 From: sheagrief <3a.mad1earth4@gmail.com> Date: Fri, 8 Nov 2024 20:56:12 +0900 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=93=9D=20Add:=20werewolf-cli=20usage?= =?UTF-8?q?=20in=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 1fce590..b0ecdd1 100644 --- a/README.md +++ b/README.md @@ -248,6 +248,20 @@ The command is written in Default zsh file, that player allocated `fortune telle ./run_werewolf.zsh night ``` +## Example - Werewolf CLI + +When playing with n players, in the i-th (0-indexed) terminal, enter the following command: + +``` +cargo run --example werewolf-cli --release i ./data/n +``` + +For example, for a 4-players game, in the first terminal, you would enter: + +``` +cargo run --example werewolf-cli --release 0 ./data/4 +``` + ## Technical Details ### SHE (Somewhat Homomorphic Encryption) protocol