Cli player with some ability to play

This commit is contained in:
Dane Johnson 2022-05-20 14:42:16 -05:00
parent a4efaff9a8
commit 1d6eeada83
3 changed files with 149 additions and 3 deletions

130
src/cli.rs Normal file
View 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
}
}

View File

@ -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),

View File

@ -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(())
} }