summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs167
1 files changed, 136 insertions, 31 deletions
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();
}