Behind Coleus

大学生なのに特別大学で楽しいことが一 つもない。虐待と男子校病のせいにしてみる。→日本脱出しました 今ジャカルタにいます。→ジャカルタから帰ってきました。→6月19日から小笠原沖で、インドネシア人とメカジキ漁

戦い13→戦い14でした

昨日の続きやる。

 

choose being attackedがリスピンファイターも殴れるバグに気付いたが、ちょっと待って。

ふふふいわし - Behind Coleus
for &entity in &player2_fzone.cards {
            if let Ok*1 = query.get(entity) {
                available_cards.push(entity);
                if let SpinCondition::Spin = spincondition {
                    // スピンしている場合
                    if let Some(fighter) = fighter {
                        println!(
                            "{}: {} (Fゾーン)[パワー: {}]",
                            available_cards.len(),
                            card.name,
                            fighter.power
                        );
                    } else {
                        println!("{}: {} (Fゾーン)", available_cards.len(), card.name);
                    }
                }
            }
        }

これで、fzoneな時点でリストに追加しちゃってるから、条件分岐の中に入れればいいと思う。リスピンしてればいいから、

for &entity in &player2_fzone.cards {
            if let Ok*2 = query.get(entity) {
                if let SpinCondition::Spin = spincondition {
                    available_cards.push(entity);
                    // スピンしている場合
                    if let Some(fighter) = fighter {
                        println!(
                            "{}: {} (Fゾーン)[パワー: {}]",
                            available_cards.len(),
                            card.name,
                            fighter.power
                        );
                    } else {
                        println!("{}: {} (Fゾーン)", available_cards.len(), card.name);
                    }
                }
            }
        }

デバグ中にさらなるバグ、選択肢の数が決まってない系のやつで、0を触るとバグる問題を忘れてはいけないな。

なおっつぁーただ、

println!("Select a card by number (1-{}):", cards_in_fzone.len());

        let mut input = String::new();
        io::stdin()
            .read_line(&mut input)
            .expect("Failed to read line");

        if let Ok(selected_index) = input.trim().parse::<usize>() {
            if selected_index > 0 && selected_index <= cards_in_fzone.len() {
                let selected_entity = cards_in_fzone[selected_index - 1];

                if let Ok*3 = query.get(selected_entity) {
                    withdraw_event_writer.send(Withdraw {
                        id: selected_entity,
                    });
                    println!(" {} を撤退するファイターとして選択しました", card.name); // カード名を表示
                }
                println!("You selected card with Entity ID: {:?}", selected_entity);
            } else {
                println!("Invalid selection.");
            }
        } else {
            println!("Please enter a valid number.");
        }
println!("Select a card by number (1-{}):", cards_in_fzone.len());

            loop {
                let mut input = String::new();
                io::stdin()
                    .read_line(&mut input)
                    .expect("Failed to read line");

                // Trim whitespace and attempt to parse the input
                match input.trim().parse::<usize>() {
                    Ok(selected_index) => {
                        if selected_index > 0 && selected_index <= cards_in_fzone.len() {
                            let selected_entity = cards_in_fzone[selected_index - 1];

                            if let Ok*4 = query.get(selected_entity) {
                                withdraw_event_writer.send(Withdraw {
                                    id: selected_entity,
                                });
                                println!("{} を撤退するファイターとして選択しました", card.name); // カード名を表示
                            }
                            println!("You selected card with Entity ID: {:?}", selected_entity);
                            break; // 有効な選択が行われたらループを抜ける
                        } else {
                            println!(
                                "Invalid selection. Please enter a number between 1 and {}.",
                                cards_in_fzone.len()
                            );
                        }
                    }
                    Err(_) => {
                        println!("Please enter a valid number.");
                    }
                }
            }


デバグはループ構文にして、まともな値を入力するまで帰れないようにした。
また、0を押せば戻れるようにする。


pub fn pick_fighter_to_withdraw(
    query: Query<(Entity, &Card, &Location), With<Player1>>,
    mut withdraw_event_writer: EventWriter<Withdraw>,
    mut pick_fighter_to_withdraw_event_reader: EventReader<PickFighterToWithdraw>,
    mut withdraw_management_event_writer: EventWriter<WithdrawManagement>,
) {
    for event in pick_fighter_to_withdraw_event_reader.read() {
        let mut cards_in_fzone = Vec::new();
        println!("Fゾーンにあるあなたのカードは:");
        for (entity, card, location) in query.iter() {
            if let Location::FZone = location {
                cards_in_fzone.push(entity); // エンティティIDを保存
                println!("{}: {}[{}]", cards_in_fzone.len(), card.name, card.energy); // 番号を振って表示
            }

            if cards_in_fzone.is_empty() {
                println!("No cards in hand.");
                return;
            }

            println!("Select a card by number (1-{}):", cards_in_fzone.len());

            loop {
                let mut input = String::new();
                io::stdin()
                    .read_line(&mut input)
                    .expect("Failed to read line");

                // Trim whitespace and attempt to parse the input
                match input.trim().parse::<usize>() {
                    Ok(selected_index) => {
                        if selected_index == 0 {
                            // 0が選択された場合
                            withdraw_management_event_writer.send(WithdrawManagement);
                            println!("Withdraw management initiated.");
                            break; // ループを抜ける
                        }
                        if selected_index > 0 && selected_index <= cards_in_fzone.len() {
                            let selected_entity = cards_in_fzone[selected_index - 1];

                            if let Ok*5 = query.get(selected_entity) {
                                withdraw_event_writer.send(Withdraw {
                                    id: selected_entity,
                                });
                                println!("{} を撤退するファイターとして選択しました", card.name); // カード名を表示
                            }
                            println!("You selected card with Entity ID: {:?}", selected_entity);
                            break; // 有効な選択が行われたらループを抜ける
                        } else {
                            println!(
                                "Invalid selection. Please enter a number between 1 and {}.",
                                cards_in_fzone.len()
                            );
                        }
                    }
                    Err(_) => {
                        println!("Please enter a valid number.");
                    }
                }
            }
        }
    }
}

pub fn pick_fighter_to_withdraw_opponent(
    query: Query<(Entity, &Card, &Location), With<Player2>>,
    mut withdraw_event_writer: EventWriter<Withdraw>,
    mut pick_fighter_to_withdraw_event_reader: EventReader<PickFighterToWithdraw>,
    mut withdraw_management_event_writer: EventWriter<WithdrawManagement>,
) {
    for event in pick_fighter_to_withdraw_event_reader.read() {
        let mut cards_in_fzone = Vec::new();
        println!("Fゾーンにあるあなたのカードは:");
        for (entity, card, location) in query.iter() {
            if let Location::FZone = location {
                cards_in_fzone.push(entity); // エンティティIDを保存
                println!("{}: {}[{}]", cards_in_fzone.len(), card.name, card.energy); // 番号を振って表示
            }

            if cards_in_fzone.is_empty() {
                println!("No cards in hand.");
                return;
            }

            println!("Select a card by number (1-{}):", cards_in_fzone.len());

            loop {
                let mut input = String::new();
                io::stdin()
                    .read_line(&mut input)
                    .expect("Failed to read line");

                // Trim whitespace and attempt to parse the input
                match input.trim().parse::<usize>() {
                    Ok(selected_index) => {
                        if selected_index == 0 {
                            // 0が選択された場合
                            withdraw_management_event_writer.send(WithdrawManagement);
                            println!("Withdraw management initiated.");
                            break; // ループを抜ける
                        }
                        if selected_index > 0 && selected_index <= cards_in_fzone.len() {
                            let selected_entity = cards_in_fzone[selected_index - 1];

                            if let Ok*6 = query.get(selected_entity) {
                                withdraw_event_writer.send(Withdraw {
                                    id: selected_entity,
                                });
                                println!("{} を撤退するファイターとして選択しました", card.name); // カード名を表示
                            }
                            println!("You selected card with Entity ID: {:?}", selected_entity);
                            break; // 有効な選択が行われたらループを抜ける
                        } else {
                            println!(
                                "Invalid selection. Please enter a number between 1 and {}.",
                                cards_in_fzone.len()
                            );
                        }
                    }
                    Err(_) => {
                        println!("Please enter a valid number.");
                    }
                }
            }
        }
    }
}

このようにした。ただ、fzoneのチェックの{}が大きな範囲をつけすぎた。


直したので、ファイター選択をやり直していく。
攻撃ファイターの選択、攻撃先の選択、ガードの選択この3つで、選択肢の数が不定の入力が必要になる。
その際に、loopして必要な情報がえられるまでやるようにする。
ガードはやり直さない予定なので、そのままイベントを記述した。


pub fn select_attacker(
    player1_fzone: ResMut<Player1FZone>,
    query: Query<(Entity, &Card, &Fighter, &Location, &SpinCondition), With<Player1>>, // Fighterコンポーネントを追加
    mut commands: Commands,
    mut attack_event_writer: EventWriter<Attack>,
    mut select_attacker_event_reader: EventReader<SelectAttacker>,
    mut main_phase_management_event_writer: EventWriter<MainPhaseManagement>,
) {
    for _event in select_attacker_event_reader.read() {
        let mut available_fighters = Vec::new();

        println!("Fゾーンにある攻撃可能なあなたのファイターは:");

        for &entity in &player1_fzone.cards {
            if let Ok*7 = query.get(entity) {
                if !fighter.summoned_sick {
                    if let SpinCondition::ReSpin = spincondition {
                        available_fighters.push(entity);
                        println!(
                            "{}: {}[{}]",
                            available_fighters.len(),
                            card.name,
                            fighter.power
                        ); // 召喚酔いでない場合
                    }
                }
            }
        }

        if available_fighters.is_empty() {
            println!("召喚酔いしていないファイターがFゾーンにありません。");
            main_phase_management_event_writer.send(MainPhaseManagement);
        }

        println!(
            "ファイターを選択してください (1-{} または 0で戻る):",
            available_fighters.len()
        );

        loop {
            let mut input = String::new();
            io::stdin()
                .read_line(&mut input)
                .expect("Failed to read line");

            if let Ok(selected_index) = input.trim().parse::<usize>() {
                if selected_index == 0 {
                    // 0を選択した場合、管理フェーズに戻る
                    main_phase_management_event_writer.send(MainPhaseManagement);
                    break; // ループを抜ける
                } else if selected_index > 0 && selected_index <= available_fighters.len() {
                    let selected_entity = available_fighters[selected_index - 1];

                    if let Ok*8 = query.get(selected_entity) {
                        attack_event_writer.send(Attack {
                            attacker_id: selected_entity,
                        });
                        println!("{} を攻撃するファイターとして選択しました", card.name); // カード名を表示
                        commands.entity(selected_entity).insert(SpinCondition::Spin);
                    }
                    break; // 有効な選択が行われたらループを抜ける
                } else {
                    println!("無効な選択です。もう一度入力してください。");
                }
            } else {
                println!("有効な番号を入力してください。");
            }
        }
    }
}

pub fn choose_card_being_attacked(
    player2_szone: ResMut<Player2SZone>,
    player2_fzone: ResMut<Player2FZone>,
    query: Query<(Entity, &Card, Option<&Fighter>, &SpinCondition), With<Player2>>, // Fighterコンポーネントを追加
    mut commands: Commands,
    mut being_attacked_event_writer: EventWriter<BeingAttacked>,
    mut attack_event_reader: EventReader<Attack>,
    mut choose_guard_event_writer: EventWriter<ChooseGuard>,
    mut select_attacker_event_writer: EventWriter<SelectAttacker>,
) {
    for event in attack_event_reader.read() {
        let mut available_cards = Vec::new();

        // Sゾーンのカードをリストアップ
        for &entity in &player2_szone.cards {
            if let Ok*9 = query.get(entity) {
                available_cards.push(entity);
                if let Some(fighter) = fighter_option {
                    println!(
                        "{}: {} (Sゾーン)[パワー: {}]",
                        available_cards.len(),
                        card.name,
                        fighter.power
                    );
                } else {
                    println!("{}: {} (Sゾーン)", available_cards.len(), card.name);
                }
            }
        }

        // Fゾーンのスピン中のカードをリストアップ
        for &entity in &player2_fzone.cards {
            if let Ok*10 = query.get(entity) {
                if let SpinCondition::Spin = spincondition {
                    available_cards.push(entity);
                    // スピンしている場合
                    if let Some(fighter) = fighter {
                        println!(
                            "{}: {} (Fゾーン)[パワー: {}]",
                            available_cards.len(),
                            card.name,
                            fighter.power
                        );
                    } else {
                        println!("{}: {} (Fゾーン)", available_cards.len(), card.name);
                    }
                }
            }
        }

        if available_cards.is_empty() {
            println!("攻撃対象となるカードがありません。");
            return;
        }

        println!("攻撃対象を選択してください (1-{}):", available_cards.len());

        loop {

            let mut input = String::new();
            io::stdin()
                .read_line(&mut input)
                .expect("Failed to read line");

            if let Ok(selected_index) = input.trim().parse::<usize>() {
                if selected_index == 0 {
                    // 0が選択された場合、操作をキャンセル
                    println!("攻撃をキャンセルしました。攻撃ファイターをリスピンしました。");
                    commands.entity(event.attacker_id).insert(SpinCondition::ReSpin);
                    select_attacker_event_writer.send(SelectAttacker);
                   
                   

                    return; // メソッドを終了
                } else if selected_index > 0 && selected_index <= available_cards.len() {
                    let selected_entity = available_cards[selected_index - 1];

                    if let Ok*11 = query.get(selected_entity) {
                        choose_guard_event_writer.send(ChooseGuard {
                            attacked_card_id: selected_entity,
                            attacker_id: event.attacker_id,
                        });

                        println!("{} を攻撃対象として選択しました", card.name); // カード名を表示
                    }
                    break; // 有効な選択が行われたらループを抜ける
                } else {
                    println!("無効な選択です。もう一度入力してください。");
                }
            } else {
                println!("有効な番号を入力してください。");
            }
        }
    }
}

pub fn choose_guard(
    query: Query<(Entity, &Card, &SpinCondition, &Fighter), (With<Player2>, With<Guard>)>,
    player2_fzone: ResMut<Player2FZone>,
    mut choose_guard_eventreader: EventReader<ChooseGuard>,
    mut attack_fzone_event_writer: EventWriter<AttackFZone>,
    mut being_attacked_event_writer: EventWriter<BeingAttacked>,
    mut commands: Commands,
) {
    for event in choose_guard_eventreader.read() {
        let mut has_respin = false;

        // player2_fzone に含まれるエンティティをループ
        let mut available_guards = Vec::new();

        for &entity in &player2_fzone.cards {
            if let Ok*12 = query.get(entity) {
                if let SpinCondition::ReSpin = spincondition {
                    available_guards.push(entity);
                    println!(
                        "{}: {}[{}]",
                        available_guards.len(),
                        card.name,
                        fighter.power
                    ); // 召喚酔いでない場合
                }
            }
        }

        if available_guards.is_empty() {
            println!("ガードはありません");
            being_attacked_event_writer.send(BeingAttacked {
                attacker_id: event.attacker_id,
                attacked_card_id: event.attacked_card_id,
            });
        } else {
            println!(
                "ガードファイターを選んでいます。 (1-{})[0]でガードをやめる",
                available_guards.len()
            );

            let mut input = String::new();
            io::stdin()
                .read_line(&mut input)
                .expect("Failed to read line");

            if let Ok(selected_index) = input.trim().parse::<usize>() {
                if selected_index == 0 {
                    // 攻撃をやめる場合
                    println!("ガードされませんでした");
                    being_attacked_event_writer.send(BeingAttacked {
                        attacked_card_id: event.attacked_card_id,
                        attacker_id: event.attacker_id,
                    });
                }
                if selected_index > 0 && selected_index <= available_guards.len() {
                    let selected_entity = available_guards[selected_index - 1];

                    if let Ok*13 = query.get(selected_entity) {
                        attack_fzone_event_writer.send(AttackFZone {
                            attacked_card_id: selected_entity,
                            attacker_id: event.attacker_id,
                        });
                        println!("{} にガードされました", card.name); // カード名を表示
                        commands.entity(selected_entity).insert(SpinCondition::Spin);
                        println!("{}はスピンしました", card.name);
                    }
                } else {
                    println!("ガードされませんでした");
                    being_attacked_event_writer.send(BeingAttacked {
                        attacked_card_id: event.attacked_card_id,
                        attacker_id: event.attacker_id,
                    });
                }
            } else {
                println!("有効な番号を入力してください。");
            }
        }
    }
}

これよく考えたら、攻撃対象選んでからスピンでよかったと思う。

OKそうあとで、run_ifつけないと、ゲームオーバーしても、処理が続行されちゃうのがあるね。
忘れる前にじゃんけん


fn get_user_input() -> String {
    let mut input = String::new();
    print!("> ");
    io::stdout().flush().unwrap(); // 出力をフラッシュしてプロンプトを表示
    io::stdin()
        .read_line(&mut input)
        .expect("Failed to read line");
    input.trim().to_string()
}

fn determine_winner(player1_choice: &str, player2_choice: &str) -> u32 {
    let player1_hand = match player1_choice {
        "1" => "グー",
        "2" => "チョキ",
        "3" => "パー",
        _ => {
            println!("無効な選択です。Player 1の選択を無効とします。");
            return 0; // 無効な場合はゼロを返す
        }
    };

    let player2_hand = match player2_choice {
        "1" => "グー",
        "2" => "チョキ",
        "3" => "パー",
        _ => {
            println!("無効な選択です。Player 2の選択を無効とします。");
            return 0; // 無効な場合はゼロを返す
        }
    };

    let outcomes: HashMap<&str, &str> = [("グー", "チョキ"), ("チョキ", "パー"), ("パー", "グー")]
        .iter()
        .cloned()
        .collect();

    if player1_hand == player2_hand {
        println!("あいこです。もう一度選んでください。");

        // あいこの場合、再度入力を受け付ける
        let new_player1_choice = get_user_input();
        let new_player2_choice = get_user_input();
        return determine_winner(&new_player1_choice, &new_player2_choice); // 再帰的に呼び出し
    } else if outcomes.get(player1_hand).unwrap() == &player2_hand {
        println!("Player 1の勝ちです!");
        return 1; // Player 1 の勝ち
    } else {
        println!("Player 2の勝ちです!");
        return 2; // Player 2 の勝ち
    }
}

fn decide_turn(winner: u32) -> (u32, u32) {
    let winner_choice = if winner == 1 {
        println!("Player 1: 先行または後攻を選んでください。(1: 先行, 2: 後攻)");
        get_user_input()
    } else {
        println!("Player 2: 先行または後攻を選んでください。(1: 先行, 2: 後攻)");
        get_user_input()
    };

    match winner_choice.as_str() {
        "1" => {
            println!("勝者は先行を選びました。");
            (winner, 3 - winner) // 1が勝者ならturn_playerはwinner、non_turn_playerは対戦相手
        }
        "2" => {
            println!("勝者は後攻を選びました。");
            (3 - winner, winner) // 2が勝者ならnon_turn_playerはwinner
        }
        _ => {
            println!("無効な選択肢です。");
            (0, 0) // 無効な場合はゼロを返す
        }
    }
}

fn janken() -> (u32, u32) {
    println!(
        "じゃんけんをします。Player 1: 1: グー、2: チョキ、3: パー のいずれかを選択してください。"
    );
    let player1_choice = get_user_input();

    println!("Player 2: 1: グー、2: チョキ、3: パー のいずれかを選択してください。");
    let player2_choice = get_user_input();

    let winner = determine_winner(&player1_choice, &player2_choice);

    // ターンプレイヤーと非ターンプレイヤーを決定
    let (turn_player, non_turn_player) = decide_turn(winner);

    (turn_player, non_turn_player) // ターンプレイヤーと非ターンプレイヤーを返す
}

これも、123以外を入力するとやり直すようにする。


fn get_user_input(prompt: &str) -> String {
    let mut input = String::new();
    loop {
        print!("{}", prompt);
        io::stdout().flush().unwrap(); // 出力をフラッシュしてプロンプトを表示
        io::stdin()
            .read_line(&mut input)
            .expect("Failed to read line");
        let trimmed_input = input.trim().to_string();

        // 入力が1, 2, 3のいずれかであることを確認
        if trimmed_input == "1" || trimmed_input == "2" || trimmed_input == "3" {
            return trimmed_input; // 有効な入力を返す
        } else {
            println!("無効な選択です。1, 2, または 3 を選んでください。");
            input.clear(); // 入力をクリアして再度プロンプトを表示
        }
    }
}

fn determine_winner(player1_choice: &str, player2_choice: &str) -> u32 {
    let player1_hand = match player1_choice {
        "1" => "グー",
        "2" => "チョキ",
        "3" => "パー",
        _ => {
            println!("無効な選択です。Player 1の選択を無効とします。");
            return 0; // 無効な場合はゼロを返す
        }
    };

    let player2_hand = match player2_choice {
        "1" => "グー",
        "2" => "チョキ",
        "3" => "パー",
        _ => {
            println!("無効な選択です。Player 2の選択を無効とします。");
            return 0; // 無効な場合はゼロを返す
        }
    };

    let outcomes: HashMap<&str, &str> = [("グー", "チョキ"), ("チョキ", "パー"), ("パー", "グー")]
        .iter()
        .cloned()
        .collect();

    if player1_hand == player2_hand {
        println!("あいこです。もう一度選んでください。");

        // あいこの場合、再度入力を受け付ける
        let new_player1_choice = get_user_input("Player 1の選択> ");
        let new_player2_choice = get_user_input("Player 2の選択> ");
        return determine_winner(&new_player1_choice, &new_player2_choice); // 再帰的に呼び出し
    } else if outcomes.get(player1_hand).unwrap() == &player2_hand {
        println!("Player 1の勝ちです!");
        return 1; // Player 1 の勝ち
    } else {
        println!("Player 2の勝ちです!");
        return 2; // Player 2 の勝ち
    }
}

fn decide_turn(winner: u32) -> (u32, u32) {
    let winner_choice = if winner == 1 {
        println!("Player 1: 先行または後攻を選んでください。(1: 先行, 2: 後攻)");
        get_user_input("")
    } else {
        println!("Player 2: 先行または後攻を選んでください。(1: 先行, 2: 後攻)");
        get_user_input("")
    };

    match winner_choice.as_str() {
        "1" => {
            println!("勝者は先行を選びました。");
            (winner, 3 - winner) // 1が勝者ならturn_playerはwinner、non_turn_playerは対戦相手
        }
        "2" => {
            println!("勝者は後攻を選びました。");
            (3 - winner, winner) // 2が勝者ならnon_turn_playerはwinner
        }
        _ => {
            println!("無効な選択肢です。");
            (0, 0) // 無効な場合はゼロを返す
        }
    }
}

fn janken() -> (u32, u32) {
    println!(
        "じゃんけんをします。Player 1: 1: グー、2: チョキ、3: パー のいずれかを選択してください。"
    );
    let player1_choice = get_user_input("Player 1の選択> ");

    println!("Player 2: 1: グー、2: チョキ、3: パー のいずれかを選択してください。");
    let player2_choice = get_user_input("Player 2の選択> ");

    let winner = determine_winner(&player1_choice, &player2_choice);

    // ターンプレイヤーと非ターンプレイヤーを決定
    let (turn_player, non_turn_player) = decide_turn(winner);

    (turn_player, non_turn_player) // ターンプレイヤーと非ターンプレイヤーを返す
}

こういう風に直した。

そしたら、こんなエラーが出た。
先行後攻は、入力すべき数字が違うから分けないとだめだわ。


fn get_turn_choice(prompt: &str) -> String {
    let mut input = String::new();
    loop {
        print!("{}", prompt);
        io::stdout().flush().unwrap(); // 出力をフラッシュしてプロンプトを表示
        io::stdin()
            .read_line(&mut input)
            .expect("Failed to read line");
        let trimmed_input = input.trim().to_string();

        // 入力が1または2であることを確認
        if trimmed_input == "1" || trimmed_input == "2" {
            return trimmed_input; // 有効な入力を返す
        } else {
            println!("無効な選択です。1または2を選んでください。");
            input.clear(); // 入力をクリアして再度プロンプトを表示
        }
    }
}

同様だけど、1と2だけ受け付ける入力関数を作った。

OKだね。
いくらルールブックを読んでも上手くかけない参考文献は、もうChaatGPTに書いていただきました。

chatgpt.com



*1:_, card, fighter, spincondition

*2:_, card, fighter, spincondition

*3:_, card, _

*4:_, card, _

*5:_, card, _

*6:_, card, _

*7:_, card, fighter, _, spincondition

*8:_, card, _, _, _

*9:_, card, fighter_option, _

*10:_, card, fighter, spincondition

*11:_, card, _, _

*12:_, card, spincondition, fighter

*13:_, card, _, _