aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortslil clingman <>2020-01-27 00:23:53 -0800
committertslil clingman <>2020-01-27 00:23:53 -0800
commit87c2d3319effd4d6be83875bdb455be9077c0c1c (patch)
tree65aa7f1915991028b9dd2eb9a52812acff2bd929 /src
parent3a1c20ebba57632392443a050fc10d44e3048843 (diff)
Option parsing, some turn order confusion. Still bugs with moves
Diffstat (limited to 'src')
-rw-r--r--src/game.rs34
-rw-r--r--src/main.rs167
2 files changed, 153 insertions, 48 deletions
diff --git a/src/game.rs b/src/game.rs
index be9d23d..a6c79a4 100644
--- a/src/game.rs
+++ b/src/game.rs
@@ -661,8 +661,8 @@ impl GameState {
}
enum TurnOrder {
- BlackPlacesWhite,
WhitePlacesBlack,
+ BlackPlacesWhite,
Normal,
}
@@ -692,8 +692,8 @@ impl Game {
black_player_name: black_player_name.to_string(),
states: vec![GameState::new(size)],
actions: Vec::new(),
- current_player: Player::Black,
- turn_order: TurnOrder::BlackPlacesWhite,
+ current_player: Player::White,
+ turn_order: TurnOrder::WhitePlacesBlack,
},
warning,
)
@@ -719,8 +719,8 @@ impl Game {
pub fn query_stone_owner(&self) -> Player {
match self.turn_order {
- TurnOrder::BlackPlacesWhite => Player::White,
TurnOrder::WhitePlacesBlack => Player::Black,
+ TurnOrder::BlackPlacesWhite => Player::White,
TurnOrder::Normal => self.current_player,
}
}
@@ -734,11 +734,11 @@ impl Game {
let mut newline = true;
let num_actions = self.actions.len();
if num_actions > 0 {
- result += "0. ";
+ result += "1. ";
for i in 0..num_actions {
if i > 1 && newline {
// TODO: Is placing the opponent's first stone the zeroeth action?
- result += &format!("{}. ", i);
+ result += &format!("{}. ", i / 2 + 1);
}
result += &format!("{} ", self.actions[i]);
if i > 0 && !newline {
@@ -761,27 +761,27 @@ impl Game {
let state = maybe_state.unwrap();
let new_state_either = match &act {
Action::Place(player, pos, stone) => match self.turn_order {
- TurnOrder::BlackPlacesWhite => {
- if (self.current_player == Player::Black)
- && (*player == Player::White)
+ TurnOrder::WhitePlacesBlack => {
+ if (self.current_player == Player::White)
+ && (*player == Player::Black)
&& (*stone == Stone::Flat)
{
state.place_stone(*player, pos, *stone)
} else {
Err(String::from(
- "At the start of the game, B must place a W flat.",
+ "At the start of the game, W must place a B flat.",
))
}
}
- TurnOrder::WhitePlacesBlack => {
- if (self.current_player == Player::White)
- && (*player == Player::Black)
+ TurnOrder::BlackPlacesWhite => {
+ if (self.current_player == Player::Black)
+ && (*player == Player::White)
&& (*stone == Stone::Flat)
{
state.place_stone(*player, pos, *stone)
} else {
Err(String::from(
- "At the start of the game, W must place a B flat.",
+ "At the start of the game, B must place a W flat.",
))
}
}
@@ -810,8 +810,8 @@ impl Game {
self.states.push(new_state);
self.actions.push(act);
self.current_player = match self.turn_order {
+ TurnOrder::WhitePlacesBlack => Player::Black,
TurnOrder::BlackPlacesWhite => Player::White,
- TurnOrder::WhitePlacesBlack => Player::White,
TurnOrder::Normal => match self.current_player {
Player::Black => Player::White,
Player::White => Player::Black,
@@ -819,8 +819,8 @@ impl Game {
};
self.turn_order = match self.turn_order {
- TurnOrder::BlackPlacesWhite => TurnOrder::WhitePlacesBlack,
- TurnOrder::WhitePlacesBlack => TurnOrder::Normal,
+ TurnOrder::WhitePlacesBlack => TurnOrder::BlackPlacesWhite,
+ TurnOrder::BlackPlacesWhite => TurnOrder::Normal,
TurnOrder::Normal => TurnOrder::Normal,
};
return Ok((pos_vec, self.last_state().check_win()));
diff --git a/src/main.rs b/src/main.rs
index be24a77..8335422 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,5 @@
+extern crate argparse;
+
mod consulter;
mod game;
mod gui;
@@ -7,23 +9,22 @@ use crate::consulter::*;
use crate::game::*;
use crate::gui::*;
use crate::parser::*;
+
+use argparse::*;
use std::io::Error;
+use std::time::SystemTime;
-fn human_action(
- action_entry: &ActionEntry,
- message_log: &MessageLog,
- game: &Game,
-) -> Result<Action, Error> {
- loop {
- let inp = action_entry.read_action();
- match parse_action(&game, &inp) {
- Err(err) => message_log.log_error(format!("Input \"{}\": {}", inp, err)),
- Ok(action) => return Ok(action),
- }
- }
+struct GUI {
+ screen: Window,
+ width: i32,
+ height: i32,
+ game_log: GameLog,
+ message_log: MessageLog,
+ action_entry: ActionEntry,
+ board_gui: BoardGUI,
}
-fn main() {
+fn init_gui(size: u8) -> GUI {
let screen = initscr();
cbreak();
noecho();
@@ -45,7 +46,6 @@ fn main() {
screen.refresh();
- let size = 5;
let cell_height = 4;
let cell_width = 8;
let hoff = 3;
@@ -53,7 +53,7 @@ fn main() {
let board_bottom = (size * cell_height + 3) as i32;
let board_right = (size * cell_width + hoff + 3) as i32;
- let mut board_gui = BoardGUI::new(
+ let board_gui = BoardGUI::new(
0,
0,
size,
@@ -87,27 +87,127 @@ fn main() {
red_colour,
);
- let (mut game, warning) = Game::new(5, "tslil", "taktician");
- message_log.log_error(warning);
- game_log.update(&game);
+ GUI {
+ screen,
+ width,
+ height,
+ game_log,
+ message_log,
+ action_entry,
+ board_gui,
+ }
+}
+
+fn human_action(gui: &GUI, game: &Game) -> Result<Action, Error> {
+ loop {
+ let inp = gui.action_entry.read_action();
+ match parse_action(&game, &inp) {
+ Err(err) => gui
+ .message_log
+ .log_error(format!("Input \"{}\": {}", inp, err)),
+ Ok(action) => {
+ gui.action_entry.clear_entry_area();
+ return Ok(action);
+ }
+ }
+ }
+}
+
+fn main() {
+ let mut p1_name = String::from("Player1");
+ let mut p2_name = String::from("Player2");
+ let mut computer_opponent = String::new();
+ let mut size: u8 = 5;
+
+ {
+ let mut ap = ArgumentParser::new();
+ ap.set_description("Test description.");
+
+ ap.refer(&mut p1_name).add_option(
+ &["--player1"],
+ Store,
+ "Name of first player, Black/White assignment is still random.",
+ );
+
+ ap.refer(&mut p2_name).add_option(
+ &["--player2"],
+ Store,
+ "Name of second player, ignored if playing against a
+ computer opponent.",
+ );
+
+ ap.refer(&mut computer_opponent).add_option(
+ &["-e", "--engine"],
+ Store,
+ "Name of process which will be used as a computer opponent.
+ The process must accept a single argument point to a PTN file
+ of the current game state, and must generate a single PTN action
+ on STDOUT.",
+ );
+
+ ap.refer(&mut size).add_option(
+ &["-s", "--size"],
+ Store,
+ "Size of board (one dimension), default is 5.",
+ );
+
+ ap.add_option(
+ &["-V", "--version"],
+ Print(env!("CARGO_PKG_VERSION").to_string()),
+ "Show version",
+ );
+ ap.parse_args_or_exit();
+ }
+
+ let human_first;
+ let call_proc;
+ if !computer_opponent.is_empty() {
+ p2_name = computer_opponent.clone();
+ call_proc = true;
+ // Perhaps there's a better way.
+ human_first = match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
+ Ok(n) => n.as_secs() % 2 == 0,
+ Err(_) => false,
+ };
+ } else {
+ human_first = false;
+ call_proc = false;
+ }
+
+ let gui = init_gui(size);
+
+ let (mut game, warning) = Game::new(size, &p1_name, &p2_name);
+ gui.message_log.log_error(warning);
+ gui.game_log.update(&game);
- const CONSULT_PROC: &str = "/home/tslil/bin/wrap_taktician";
loop {
let inp = match game.query_current_player() {
- Player::Black => consult_next_action(&game, CONSULT_PROC),
- Player::White => human_action(&action_entry, &message_log, &game),
+ Player::Black => {
+ if call_proc && human_first {
+ consult_next_action(&game, &computer_opponent)
+ } else {
+ human_action(&gui, &game)
+ }
+ }
+ Player::White => {
+ if call_proc && (!human_first) {
+ consult_next_action(&game, &computer_opponent)
+ } else {
+ human_action(&gui, &game)
+ }
+ }
};
match inp {
Err(err) => {
- message_log.log_error(format!("{}", err));
+ gui.message_log.log_error(format!("{}", err));
break;
}
Ok(act) => {
let stone_owner = game.query_stone_owner();
let player = game.query_current_player();
- message_log.log_message(format!(
+ gui.message_log.log_message(format!(
"{} performs {}{}",
player,
act,
@@ -119,28 +219,33 @@ fn main() {
));
match game.perform_action(act) {
Err(e) => {
- message_log.log_error(e);
- if game.query_current_player() == Player::Black {
- // external and internal gamestates diverged
+ gui.message_log.log_error(e);
+ let current = game.query_current_player();
+ if call_proc
+ && ((human_first && current == Player::Black)
+ || ((!human_first) && current == Player::White))
+ {
+ gui.message_log.log_error(String::from(
+ "Error: external and internal game states disagree.",
+ ));
break;
}
}
Ok((pos_vec, win)) => {
- board_gui.update(&game, pos_vec);
- game_log.update(&game);
+ gui.board_gui.update(&game, pos_vec);
+ gui.game_log.update(&game);
if let Some(w) = win {
- message_log.log_message(format!("{}", w));
+ gui.message_log.log_message(format!("{}", w));
break;
}
}
}
}
}
- action_entry.clear_entry_area();
}
- screen.getch();
+ gui.screen.getch();
// board_gui.read_action();
endwin();
}