Cli player with some ability to play
This commit is contained in:
parent
a4efaff9a8
commit
1d6eeada83
130
src/cli.rs
Normal file
130
src/cli.rs
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
use coup::*;
|
||||||
|
use Action::*;
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct HumanAgent {
|
||||||
|
turn: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HumanAgent {
|
||||||
|
pub fn new(turn: usize) -> Self {
|
||||||
|
HumanAgent { turn }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inform(&self, game: &Game) {
|
||||||
|
let player = &game.players[self.turn];
|
||||||
|
println!("Player {}:", self.turn);
|
||||||
|
match player.cards.as_slice() {
|
||||||
|
&[card1, card2] => println!("Your identities are {} and {}", card1, card2),
|
||||||
|
&[card] => println!("Your identity is {}", card),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
println!("Remaining players are:");
|
||||||
|
for id in 0..game.players.len() {
|
||||||
|
if id == self.turn || !game.players[id].is_alive() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
println!(" Player {} with {} coins and {} influence",
|
||||||
|
id, game.players[id].coins, game.players[id].cards.len());
|
||||||
|
}
|
||||||
|
println!("Discard is showing:");
|
||||||
|
for card in &game.discard {
|
||||||
|
println!(" {}", card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Agent for HumanAgent {
|
||||||
|
fn choose_move(&self, game: &Game) -> Move {
|
||||||
|
self.inform(game);
|
||||||
|
println!("Choose an action");
|
||||||
|
let action = loop {
|
||||||
|
for i in 1..=7 {
|
||||||
|
println!(" {}) {}", i, get_action(i).unwrap());
|
||||||
|
}
|
||||||
|
let index = get_index();
|
||||||
|
if let Some(action) = get_action(index) {
|
||||||
|
break action;
|
||||||
|
} else {
|
||||||
|
println!("Bad choice");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let target = if action.is_targeted() { Some(get_index()) } else { None };
|
||||||
|
Move { action, target }
|
||||||
|
}
|
||||||
|
fn should_action_challenge(&self, game: &Game, move_: Move) -> bool {
|
||||||
|
self.inform(game);
|
||||||
|
loop {
|
||||||
|
if let Some(target) = move_.target {
|
||||||
|
if target == self.turn {
|
||||||
|
print!("Will you challenge {} targeting you?", move_.action);
|
||||||
|
} else {
|
||||||
|
print!("Will you challenge {} targeting Player {}?", move_.action, target);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print!("Will you challenge {}?", move_.action);
|
||||||
|
}
|
||||||
|
match yes_or_no() {
|
||||||
|
Some(b) => break b,
|
||||||
|
None => println!("Bad input"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn choose_block_card(&self, game: &Game, move_: Move) -> Option<Card> {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
fn should_block_challenge(&self, game: &Game, move_: Move, block: Block) -> bool {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
fn exchange(&self, game: &Game, cards: &[Card]) -> [Card; 2] {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
fn choose_lost_influence(&self, game: &Game) -> Card {
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_action(index: usize) -> Option<Action> {
|
||||||
|
match index {
|
||||||
|
1 => Some(Income),
|
||||||
|
2 => Some(ForeignAid),
|
||||||
|
3 => Some(Coup),
|
||||||
|
4 => Some(Tax),
|
||||||
|
5 => Some(Assassinate),
|
||||||
|
6 => Some(Exchange),
|
||||||
|
7 => Some(Steal),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_index() -> usize {
|
||||||
|
let mut string = String::new();
|
||||||
|
io::stdin()
|
||||||
|
.read_line(&mut string)
|
||||||
|
.unwrap();
|
||||||
|
string
|
||||||
|
.trim()
|
||||||
|
.parse()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn yes_or_no() -> Option<bool> {
|
||||||
|
print!(" [y/n]: ");
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
|
let mut string = String::new();
|
||||||
|
io::stdin()
|
||||||
|
.read_line(&mut string)
|
||||||
|
.unwrap();
|
||||||
|
let string = string.to_uppercase();
|
||||||
|
let string = string.trim();
|
||||||
|
if string.starts_with("Y") {
|
||||||
|
Some(true)
|
||||||
|
} else if string.starts_with("N") {
|
||||||
|
Some(false)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
@ -412,7 +412,6 @@ pub struct Block {
|
|||||||
/// some phases might be skipped.
|
/// some phases might be skipped.
|
||||||
#[derive(PartialEq, Debug)]
|
#[derive(PartialEq, Debug)]
|
||||||
pub enum Phase {
|
pub enum Phase {
|
||||||
Action(Move),
|
|
||||||
ActionChallenge(Move),
|
ActionChallenge(Move),
|
||||||
Block(Move),
|
Block(Move),
|
||||||
BlockChallenge(Move, Block),
|
BlockChallenge(Move, Block),
|
||||||
|
21
src/main.rs
21
src/main.rs
@ -1,5 +1,22 @@
|
|||||||
use coup::*;
|
use coup::*;
|
||||||
|
|
||||||
fn main() {
|
mod cli;
|
||||||
println!("Hello, world!");
|
use cli::HumanAgent;
|
||||||
|
|
||||||
|
fn main() -> CoupResult<()> {
|
||||||
|
let mut game = Game::new(2);
|
||||||
|
let agents: &[&dyn Agent] = &[&HumanAgent::new(0), &HumanAgent::new(1)];
|
||||||
|
while !game.is_game_over() {
|
||||||
|
let mut phase = game.action(agents)?;
|
||||||
|
while phase != Phase::Done {
|
||||||
|
phase = match phase {
|
||||||
|
Phase::ActionChallenge(move_) => game.action_challenge(move_, agents)?,
|
||||||
|
Phase::Block(move_) => game.block(move_, agents)?,
|
||||||
|
Phase::BlockChallenge(move_, block) => game.block_challenge(move_, block, agents)?,
|
||||||
|
Phase::Resolution(move_) => game.resolution(move_, agents)?,
|
||||||
|
Phase::Done => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user