Skip to main content

usiagent/
selfmatch.rs

1//! 自己対局機能
2use chrono::prelude::*;
3
4use std::fmt;
5use std::{thread};
6use std::sync::Mutex;
7use std::sync::Arc;
8use std::sync::atomic::AtomicBool;
9use std::sync::atomic::Ordering;
10use std::thread::JoinHandle;
11use std::marker::Send;
12use std::marker::PhantomData;
13use std::time::{Instant,Duration};
14use std::io::Write;
15use std::io::BufWriter;
16use std::fs;
17use std::fs::OpenOptions;
18use std::convert::TryFrom;
19
20use crossbeam_channel::unbounded;
21use crossbeam_channel::Sender;
22use crossbeam_channel::Receiver;
23use crossbeam_channel::SendError;
24use crossbeam_channel::after;
25use crossbeam_channel::never;
26
27use command::*;
28use event::*;
29use error::*;
30use input::*;
31use output::*;
32use player::*;
33use shogi::*;
34use hash::*;
35use Logger;
36use logger::FileLogger;
37use OnErrorHandler;
38use SandBox;
39use rule::*;
40use protocol::*;
41
42/// 棋譜を記録する
43pub trait SelfMatchKifuWriter {
44	/// 棋譜の書き込みを行う
45	///
46	/// # Arguments
47	/// * `initial_sfen` - 開始時の局面のsfen文字列表現
48	/// * `m` - 開始局面からの指し手のリスト
49	fn write(&mut self,initial_sfen:&String,m:&Vec<Move>) -> Result<(),KifuWriteError>;
50	/// 開始時の局面のsfen文字列と`Vec<Move>`から棋譜のsfen文字列を生成するメソッドのデフォルト実装
51	///
52	/// # Arguments
53	/// * `initial_sfen` - 開始時の局面のsfen文字列表現
54	/// * `m` - 開始局面からの指し手のリスト
55	fn to_sfen(&self,initial_sfen:&String,m:&Vec<Move>)
56		-> Result<String, SfenStringConvertError> {
57
58		let sfen = initial_sfen.split(" ").collect::<Vec<&str>>();
59
60		if sfen.len() >= 5 {
61			match (sfen[0],sfen[1],sfen[2],sfen[3],sfen[4]) {
62				("sfen",p1,p2,p3,p4) if m.len() > 0 => {
63					Ok(format!("sfen {} {} {} {} moves {}",p1,p2,p3,p4,m.to_sfen()?))
64				},
65				("sfen",p1,p2,p3,p4) => {
66					Ok(format!("sfen {} {} {} {}",p1,p2,p3,p4))
67				},
68				("startpos",_,_,_,_) if m.len() > 0 => {
69					Ok(format!("startpos moves {}",m.to_sfen()?))
70				},
71				("startpos",_,_,_,_)=> {
72					Ok(format!("startpos"))
73				},
74				_ => {
75					Err(SfenStringConvertError::InvalidFormat(initial_sfen.clone()))
76				}
77			}
78		} else if sfen.len() >= 1 && sfen[0] == "startpos" {
79			if m.len() > 0 {
80				Ok(format!("startpos moves {}",m.to_sfen()?))
81			} else {
82				Ok(format!("startpos"))
83			}
84		} else {
85			Err(SfenStringConvertError::InvalidFormat(initial_sfen.clone()))
86		}
87	}
88}
89/// ファイルに記録する`SelfMatchKifuWriter`の実装
90#[derive(Debug)]
91pub struct FileSfenKifuWriter {
92	writer:BufWriter<fs::File>,
93}
94impl FileSfenKifuWriter {
95	/// FileSfenKifuWriterの生成
96	///
97	/// # Arguments
98	/// * `file` - 書き込み先ファイル
99	pub fn new(file:String) -> Result<FileSfenKifuWriter,KifuWriteError> {
100		Ok(FileSfenKifuWriter {
101			writer:BufWriter::new(OpenOptions::new().append(true).create(true).open(file)?),
102		})
103	}
104}
105impl SelfMatchKifuWriter for FileSfenKifuWriter {
106	/// ファイルに棋譜を書き込む
107	///
108	/// # Arguments
109	/// * `initial_sfen` - 開始時の局面のsfen文字列表現
110	/// * `m` - 開始局面からの指し手のリスト
111	fn write(&mut self,initial_sfen:&String,m:&Vec<Move>) -> Result<(),KifuWriteError> {
112		let sfen = self.to_sfen(initial_sfen,m)?;
113
114		let _ = self.writer.write(format!("{}\n",sfen).as_bytes())?;
115		Ok(())
116	}
117}
118/// タイムアウトの種別
119#[derive(Debug)]
120enum TimeoutKind {
121	/// タイムアウト無し
122	Never,
123	/// 現在のターンのタイムアウト
124	Turn,
125	/// 自己対局機能の起動時に指定した終了時刻に達した
126	Uptime,
127}
128/// 自己対局機能の実装内でやり取りするメッセージオブジェクト
129#[derive(Debug)]
130pub enum SelfMatchMessage {
131	/// 準備完了
132	Ready,
133	/// ゲーム開始
134	GameStart,
135	/// プレイヤーの思考を開始する
136	StartThink(Teban,Banmen,MochigomaCollections,u32,Vec<AppliedMove>,Instant),
137	/// プレイヤーの思考を開始する(go ponder)
138	StartPonderThink(Teban,Banmen,MochigomaCollections,u32,Vec<AppliedMove>),
139	/// プレイヤーから指し手を返す
140	NotifyMove(BestMove),
141	/// ponderで予測した指し手と一致した
142	PonderHit,
143	/// ponderで予測した指し手と一致しない
144	PonderNG,
145	/// 対局終了
146	GameEnd(GameEndState),
147	/// 中断
148	Abort,
149	/// 自己対局終了
150	Quit,
151	/// エラー発生を通知
152	Error(usize),
153}
154/// 自己対局の結果
155#[derive(Debug)]
156pub struct SelfMatchResult {
157	/// 実施した対局回数
158	pub game_count:u32,
159	/// 自己対局開始からの経過時間
160	pub elapsed:Duration,
161	/// 自己対局の開始時間
162	pub start_dt:DateTime<Local>,
163	/// 自己対局の終了時間
164	pub end_dt:DateTime<Local>,
165}
166/// 自己対局エンジン
167#[derive(Debug)]
168pub struct SelfMatchEngine<E>
169	where 	E: PlayerError {
170	player_error_type:PhantomData<E>,
171	/// システムイベントキュー
172	pub system_event_queue:Arc<Mutex<SystemEventQueue>>,
173}
174impl<E> SelfMatchEngine<E>
175	where E: PlayerError {
176	/// `SelfMatchEngine`の生成
177	pub fn new() -> SelfMatchEngine<E> where E: PlayerError {
178		SelfMatchEngine {
179			player_error_type:PhantomData::<E>,
180			system_event_queue:Arc::new(Mutex::new(EventQueue::new())),
181		}
182	}
183
184	/// デフォルト設定で開始(ログファイルのパスlogs/log.txt,ログをファイルに記録)
185	///
186	/// # Arguments
187	/// * `on_init_event_dispatcher` - 自己対局時に通知されるSelfMatchEventのイベントディスパッチャーを初期化
188	/// * `flip_players` - 対局時の初期局面時のplayer1とplayer2の手番の割り当てを逆にする。(通常はplayer1が先手)
189	/// * `initial_position_creator` - 対局毎の初期局面を生成して返す関数
190	/// * `kifu_writer` - 対局終了時に棋譜を書き込むためのコールバック関数
191	/// * `input_handler` - 標準入力から読みこんだ行が渡されるコールバック関数。システムイベントの発行などに使う('quit'で終了など)
192	/// * `player1` - USIPlayerを実装したプレイヤーオブジェクト
193	/// * `player2` - USIPlayerを実装したプレイヤーオブジェクト
194	/// * `player1_options` - player1に渡されるオプション
195	/// * `player2_options` - player2に渡されるオプション
196	/// * `info_sender` - infoコマンドを送信するための機能を持つオブジェクト
197	/// * `pinfo_sender` - あらかじめスケジュールされた一定の間隔でinfoコマンドを送信するための機能を持つオブジェクト
198	/// * `game_time_limit` - 対局毎の制限時間
199	/// * `uptime` - 自己対局機能全体の実行時間制限。この時間に達すると自己対局は終了する(現在の対局だけではない)
200	/// * `number_of_games` - 自己対局機能で行われる対局の回数。この回数を終えると自己対局は終了する
201	/// * `on_error` - エラー発生時に呼ばれるコールバック関数。エラーオブジェクトへの参照とロガーが渡される。
202	pub fn start_default<T,S,P,I,F,RH,EH>(&mut self, on_init_event_dispatcher:I,
203						flip_players:F,
204						initial_position_creator:Option<Box<dyn FnMut() -> String + Send + 'static>>,
205						kifu_writer:Option<Box<dyn FnMut(&String,&Vec<Move>) -> Result<(),KifuWriteError>  +Send + 'static>>,
206						input_handler:RH,
207						player1:T,
208						player2:T,
209						player1_options:Vec<(String,SysEventOption)>,
210						player2_options:Vec<(String,SysEventOption)>,
211						info_sender:S,
212						pinfo_sender:P,
213						game_time_limit:UsiGoTimeLimit,
214						uptime:Option<Duration>,
215						number_of_games:Option<u32>,
216						on_error:EH) -> Result<SelfMatchResult,SelfMatchRunningError<E>>
217		where T: USIPlayer<E> + fmt::Debug + Send + 'static,
218				F: FnMut() -> bool + Send + 'static,
219				RH: FnMut(String) -> Result<bool,SelfMatchRunningError<E>> + Send + 'static,
220				I: FnMut(&mut SelfMatchEventDispatcher<E,FileLogger>),
221				S: InfoSender,
222				P: PeriodicallyInfo + Clone + Send + 'static,
223				Arc<Mutex<FileLogger>>: Send + 'static,
224				EH: FnMut(Option<Arc<Mutex<OnErrorHandler<FileLogger>>>>,
225					&SelfMatchRunningError<E>) {
226		self.start_with_log_path(String::from("logs/log.txt"),
227								on_init_event_dispatcher,
228								flip_players,
229								initial_position_creator,
230								kifu_writer, input_handler,
231								player1,player2,
232								player1_options, player2_options,
233								info_sender,
234								pinfo_sender,
235								game_time_limit,
236								uptime,
237								number_of_games,
238								on_error)
239	}
240
241	/// ログファイルのパスを指定して開始
242	///
243	/// # Arguments
244	/// * `path` - ログファイルのパス
245	/// * `on_init_event_dispatcher` - 自己対局時に通知されるSelfMatchEventのイベントディスパッチャーを初期化
246	/// * `flip_players` - 対局時の初期局面時のplayer1とplayer2の手番の割り当てを逆にする。(通常はplayer1が先手)
247	/// * `initial_position_creator` - 対局毎の初期局面を生成して返す関数
248	/// * `kifu_writer` - 対局終了時に棋譜を書き込むためのコールバック関数
249	/// * `input_handler` - 標準入力から読みこんだ行が渡されるコールバック関数。システムイベントの発行などに使う('quit'で終了など)
250	/// * `player1` - USIPlayerを実装したプレイヤーオブジェクト
251	/// * `player2` - USIPlayerを実装したプレイヤーオブジェクト
252	/// * `player1_options` - player1に渡されるオプション
253	/// * `player2_options` - player2に渡されるオプション
254	/// * `info_sender` - infoコマンドを送信するための機能を持つオブジェクト
255	/// * `pinfo_sender` - あらかじめスケジュールされた一定の間隔でinfoコマンドを送信するための機能を持つオブジェクト
256	/// * `game_time_limit` - 対局毎の制限時間
257	/// * `uptime` - 自己対局機能全体の実行時間制限。この時間に達すると自己対局は終了する(現在の対局だけではない)
258	/// * `number_of_games` - 自己対局機能で行われる対局の回数。この回数を終えると自己対局は終了する
259	/// * `on_error` - エラー発生時に呼ばれるコールバック関数。エラーオブジェクトへの参照とロガーが渡される。
260	pub fn start_with_log_path<T,S,P,I,F,RH,EH>(&mut self,path:String,
261						on_init_event_dispatcher:I,
262						flip_players:F,
263						initial_position_creator:Option<Box<dyn FnMut() -> String + Send + 'static>>,
264						kifu_writer:Option<Box<dyn FnMut(&String,&Vec<Move>) -> Result<(),KifuWriteError>  +Send + 'static>>,
265						input_handler:RH,
266						player1:T,
267						player2:T,
268						player1_options:Vec<(String,SysEventOption)>,
269						player2_options:Vec<(String,SysEventOption)>,
270						info_sender:S,
271						pinfo_sender:P,
272						game_time_limit:UsiGoTimeLimit,
273						uptime:Option<Duration>,
274						number_of_games:Option<u32>,
275						mut on_error:EH) -> Result<SelfMatchResult,SelfMatchRunningError<E>>
276		where T: USIPlayer<E> + fmt::Debug + Send + 'static,
277				F: FnMut() -> bool + Send + 'static,
278				RH: FnMut(String) -> Result<bool,SelfMatchRunningError<E>> + Send + 'static,
279				I: FnMut(&mut SelfMatchEventDispatcher<E,FileLogger>),
280				S: InfoSender,
281				P: PeriodicallyInfo + Clone + Send + 'static,
282				Arc<Mutex<FileLogger>>: Send + 'static,
283				EH: FnMut(Option<Arc<Mutex<OnErrorHandler<FileLogger>>>>,
284					&SelfMatchRunningError<E>) {
285		let logger = match FileLogger::new(path) {
286			Err(e) => {
287				let e = SelfMatchRunningError::IOError(e);
288				on_error(None,&e);
289				return Err(e);
290			},
291			Ok(logger) => logger,
292		};
293
294		let input_reader = USIStdInputReader::new();
295
296		self.start(on_init_event_dispatcher,
297					flip_players,
298					initial_position_creator,
299					kifu_writer, input_reader, input_handler,
300					player1,player2,
301					player1_options, player2_options,
302					info_sender,
303					pinfo_sender,
304					game_time_limit,
305					uptime,
306					number_of_games,
307					logger, on_error)
308	}
309
310	/// `Logger`,`USIInputReader`を指定して開始
311	///
312	/// # Arguments
313	/// * `on_init_event_dispatcher` - 自己対局時に通知されるSelfMatchEventのイベントディスパッチャーを初期化
314	/// * `flip_players` - 対局時の初期局面時のplayer1とplayer2の手番の割り当てを逆にする。(通常はplayer1が先手)
315	/// * `initial_position_creator` - 対局毎の初期局面を生成して返す関数
316	/// * `kifu_writer` - 対局終了時に棋譜を書き込むためのコールバック関数
317	/// * `input_reader` - 入力を読み取るためのオブジェクト。実装によって標準入力以外から読み取るものを指定することも可能。
318	/// * `input_handler` - 標準入力から読みこんだ行が渡されるコールバック関数。システムイベントの発行などに使う('quit'で終了など)
319	/// * `player1` - USIPlayerを実装したプレイヤーオブジェクト
320	/// * `player2` - USIPlayerを実装したプレイヤーオブジェクト
321	/// * `player1_options` - player1に渡されるオプション
322	/// * `player2_options` - player2に渡されるオプション
323	/// * `info_sender` - infoコマンドを送信するための機能を持つオブジェクト
324	/// * `pinfo_sender` - あらかじめスケジュールされた一定の間隔でinfoコマンドを送信するための機能を持つオブジェクト
325	/// * `game_time_limit` - 対局毎の制限時間
326	/// * `uptime` - 自己対局機能全体の実行時間制限。この時間に達すると自己対局は終了する(現在の対局だけではない)
327	/// * `number_of_games` - 自己対局機能で行われる対局の回数。この回数を終えると自己対局は終了する
328	/// * `logger` - ログを書き込むためのオブジェクト。実装によってファイル以外に書き込むものを指定することも可能。
329	/// * `on_error` - エラー発生時に呼ばれるコールバック関数。エラーオブジェクトへの参照とロガーが渡される。
330	pub fn start<T,S,P,I,F,R,RH,L,EH>(&mut self, on_init_event_dispatcher:I,
331						flip_players:F,
332						initial_position_creator:Option<Box<dyn FnMut() -> String + Send + 'static>>,
333						kifu_writer:Option<Box<dyn FnMut(&String,&Vec<Move>) -> Result<(),KifuWriteError>  +Send + 'static>>,
334						input_reader:R,
335						input_handler:RH,
336						player1:T,
337						player2:T,
338						player1_options:Vec<(String,SysEventOption)>,
339						player2_options:Vec<(String,SysEventOption)>,
340						info_sender:S,
341						pinfo_sender:P,
342						game_time_limit:UsiGoTimeLimit,
343						uptime:Option<Duration>,
344						number_of_games:Option<u32>,
345						logger:L, mut on_error:EH) -> Result<SelfMatchResult,SelfMatchRunningError<E>>
346		where T: USIPlayer<E> + fmt::Debug + Send + 'static,
347				F: FnMut() -> bool + Send + 'static,
348				R: USIInputReader + Send + 'static,
349				RH: FnMut(String) -> Result<bool,SelfMatchRunningError<E>> + Send + 'static,
350				I: FnMut(&mut SelfMatchEventDispatcher<E,L>),
351				S: InfoSender,
352				P: PeriodicallyInfo + Clone + Send + 'static,
353				L: Logger + fmt::Debug + Send + 'static,
354				Arc<Mutex<L>>: Send + 'static,
355				EH: FnMut(Option<Arc<Mutex<OnErrorHandler<L>>>>,
356					&SelfMatchRunningError<E>) {
357		let logger_arc = Arc::new(Mutex::new(logger));
358		let on_error_handler_arc = Arc::new(Mutex::new(OnErrorHandler::new(logger_arc.clone())));
359		let on_error_handler = on_error_handler_arc.clone();
360
361		let r = self.run(on_init_event_dispatcher,
362							flip_players,
363							initial_position_creator,
364							kifu_writer, input_reader, input_handler,
365							player1,player2,
366							player1_options, player2_options,
367							info_sender,
368							pinfo_sender,
369							game_time_limit,
370							uptime,
371							number_of_games,
372							logger_arc, on_error_handler_arc);
373
374		if let Err(ref e) = r {
375			on_error(Some(on_error_handler),e);
376		}
377
378		r
379	}
380
381	fn run<T,S,P,I,F,R,RH,L>(&mut self, mut on_init_event_dispatcher:I,
382						mut flip_players:F,
383						initial_position_creator:Option<Box<dyn FnMut() -> String + Send + 'static>>,
384						kifu_writer:Option<Box<dyn FnMut(&String,&Vec<Move>) -> Result<(),KifuWriteError> + Send + 'static>>,
385						mut input_reader:R,
386						mut input_handler:RH,
387						mut player1:T,
388						mut player2:T,
389						player1_options:Vec<(String,SysEventOption)>,
390						player2_options:Vec<(String,SysEventOption)>,
391						info_sender:S,
392						pinfo_sender:P,
393						game_time_limit:UsiGoTimeLimit,
394						uptime:Option<Duration>,
395						number_of_games:Option<u32>,
396						logger_arc:Arc<Mutex<L>>,
397						on_error_handler_arc:Arc<Mutex<OnErrorHandler<L>>>) -> Result<SelfMatchResult,SelfMatchRunningError<E>>
398		where T: USIPlayer<E> + fmt::Debug + Send + 'static,
399				F: FnMut() -> bool + Send + 'static,
400				R: USIInputReader + Send + 'static,
401				RH: FnMut(String) -> Result<bool,SelfMatchRunningError<E>> + Send + 'static,
402				I: FnMut(&mut SelfMatchEventDispatcher<E,L>),
403				S: InfoSender,
404				P: PeriodicallyInfo + Clone + Send + 'static,
405				L: Logger + fmt::Debug + Send + 'static,
406				Arc<Mutex<L>>: Send + 'static {
407		let start_time = Instant::now();
408		let start_dt = Local::now();
409
410		let mut self_match_event_dispatcher:SelfMatchEventDispatcher<E,L> = USIEventDispatcher::new(&on_error_handler_arc);
411
412		on_init_event_dispatcher(&mut self_match_event_dispatcher);
413
414		let mut system_event_dispatcher:SystemEventDispatcher<SelfMatchEngine<E>,E,L> = USIEventDispatcher::new(&on_error_handler_arc);
415
416		let user_event_queue_arc:[Arc<Mutex<UserEventQueue>>; 2] = [Arc::new(Mutex::new(EventQueue::new())),Arc::new(Mutex::new(EventQueue::new()))];
417
418		let user_event_queue = [user_event_queue_arc[0].clone(),user_event_queue_arc[1].clone()];
419
420		let mut initial_position_creator:Box<dyn FnMut() -> String + Send + 'static> =
421			initial_position_creator.map_or(Box::new(|| String::from("startpos")), |f| {
422				f
423			});
424
425		let on_error_handler = on_error_handler_arc.clone();
426
427		let mut kifu_writer = kifu_writer;
428		let mut kifu_writer = move |sfen:&String,m:&Vec<Move>| {
429			let _ = kifu_writer.as_mut().map(|w| {
430				let _= w(sfen,m).map_err(|e| on_error_handler.lock().map(|h| h.call(&e)));
431			});
432		};
433
434		let quit_ready_arc = Arc::new(AtomicBool::new(false));
435		let on_error_handler = on_error_handler_arc.clone();
436
437		let self_match_event_queue:SelfMatchEventQueue = EventQueue::new();
438		let self_match_event_queue_arc = Arc::new(Mutex::new(self_match_event_queue));
439
440		let (ss,sr) = unbounded();
441		let (cs1,cr1) = unbounded();
442		let (cs2,cr2) = unbounded();
443		let mut cr = vec![cr1,cr2];
444
445		{
446			let ss = ss.clone();
447			let quit_ready = quit_ready_arc.clone();
448
449			let on_error_handler = on_error_handler_arc.clone();
450
451			system_event_dispatcher.add_handler(SystemEventKind::Quit, move |_,e| {
452				match e {
453					&SystemEvent::Quit => {
454						for i in 0..2 {
455							match user_event_queue[i].lock() {
456								Ok(mut user_event_queue) => {
457									user_event_queue.push(UserEvent::Quit);
458								},
459								Err(ref e) => {
460									let _ = on_error_handler.lock().map(|h| h.call(e));
461								}
462							};
463						};
464
465						if !quit_ready.load(Ordering::Acquire) {
466							if let Err(ref e) = ss.send(SelfMatchMessage::Quit) {
467								let _ = on_error_handler.lock().map(|h| h.call(e));
468							}
469						}
470
471						Ok(())
472					},
473					e => Err(EventHandlerError::InvalidState(e.event_kind())),
474				}
475			});
476		}
477
478		for (k,v) in player1_options {
479			match player1.set_option(k,v) {
480				Ok(()) => (),
481				Err(ref e) => {
482					let _ = on_error_handler.lock().map(|h| h.call(e));
483					return Err(SelfMatchRunningError::Fail(String::from(
484						"An error occurred while executing a self match. Please see the log for details ..."
485					)));
486				}
487			}
488		}
489
490		for (k,v) in player2_options {
491			match player2.set_option(k,v) {
492				Ok(()) => (),
493				Err(ref e) => {
494					let _ = on_error_handler.lock().map(|h| h.call(e));
495					return Err(SelfMatchRunningError::Fail(String::from(
496						"An error occurred while executing a self match. Please see the log for details ..."
497					)));
498				}
499			}
500		}
501
502		let position_parser = PositionParser::new();
503
504		let self_match_event_queue = self_match_event_queue_arc.clone();
505		let quit_ready = quit_ready_arc.clone();
506
507		let on_error_handler = on_error_handler_arc.clone();
508
509		let user_event_queue = user_event_queue_arc.clone();
510
511		let bridge_h = thread::spawn(move || SandBox::immediate(|| {
512			let cs = [cs1.clone(),cs2.clone()];
513			let mut prev_move:Option<AppliedMove> = None;
514			let mut ponders:[Option<AppliedMove>; 2] = [None,None];
515
516			let quit_ready_inner = quit_ready.clone();
517
518			let quit_notification =  move || {
519				quit_ready_inner.store(true,Ordering::Release);
520			};
521
522			let self_match_event_queue_inner = self_match_event_queue.clone();
523			let on_error_handler_inner = on_error_handler.clone();
524
525			let quit_ready_inner = quit_ready.clone();
526
527			let on_gameend = move |win_cs:Sender<SelfMatchMessage>,
528									lose_cs:Sender<SelfMatchMessage>,
529									_:[Sender<SelfMatchMessage>; 2],
530									sr:&Receiver<SelfMatchMessage>,
531									s:SelfMatchGameEndState| {
532				let mut message_state = GameEndState::Win;
533
534				let quit_notification = || {
535					quit_ready_inner.store(true,Ordering::Release);
536				};
537
538				match self_match_event_queue_inner.lock() {
539					Ok(mut self_match_event_queue) => {
540						self_match_event_queue.push(SelfMatchEvent::GameEnd(s));
541					},
542					Err(ref e) => {
543						let _ = on_error_handler_inner.lock().map(|h| h.call(e));
544						return Err(SelfMatchRunningError::InvalidState(String::from(
545							"Exclusive lock on self_match_event_queue failed."
546						)));
547					}
548				}
549
550				for current_cs in &[win_cs.clone(),lose_cs.clone()] {
551					current_cs.send(SelfMatchMessage::GameEnd(message_state))?;
552					match sr.recv()? {
553						SelfMatchMessage::Ready => (),
554						SelfMatchMessage::Error(n) => {
555							return Err(SelfMatchRunningError::PlayerThreadError(n));
556						},
557						SelfMatchMessage::Quit => {
558							quit_notification();
559
560							return Ok(());
561						},
562						_ => {
563							return Err(SelfMatchRunningError::InvalidState(String::from(
564								"An invalid message was sent to the self-match management thread."
565							)));
566						}
567					}
568					message_state = GameEndState::Lose;
569				}
570				Ok(())
571			};
572
573			let mut game_count = 0;
574
575			'gameloop: while !quit_ready.load(Ordering::Acquire) &&
576				number_of_games.map_or(true, |n| game_count < n) &&
577				uptime.map_or(true, |t| Instant::now() - start_time < t) {
578
579				cs[0].send(SelfMatchMessage::GameStart)?;
580				cs[1].send(SelfMatchMessage::GameStart)?;
581
582				game_count += 1;
583
584				let mut cs_index = if flip_players() {
585					1
586				} else {
587					0
588				};
589
590				let sfen = initial_position_creator();
591				let (teban, banmen, mc, n, mvs) = match position_parser.parse(&sfen.split(" ").collect::<Vec<&str>>()) {
592					Ok(position) => {
593						position.extract()
594					},
595					Err(ref e) => {
596						let _ = on_error_handler.lock().map(|h| h.call(e));
597						return Err(SelfMatchRunningError::InvalidState(String::from(
598							"An error occurred parsing the sfen string."
599						)));
600					}
601				};
602
603				if teban == Teban::Gote {
604					cs_index = (cs_index + 1) % 2;
605				}
606
607				let banmen_at_start = banmen.clone();
608				let mc_at_start = mc.clone();
609				let teban_at_start = teban.clone();
610
611				let mut current_game_time_limit = [game_time_limit,game_time_limit];
612				let mut current_time_limit = current_game_time_limit[cs_index].to_instant(teban,Instant::now());
613
614				let kyokumen_map:KyokumenMap<u64,u32> = KyokumenMap::new();
615				let oute_kyokumen_map:KyokumenMap<u64,u32> = KyokumenMap::new();
616
617				let hasher = KyokumenHash::new();
618
619				let (ms,mg) = match mc {
620					MochigomaCollections::Pair(ref ms, ref mg) => {
621						match teban {
622							Teban::Sente => (ms.clone(),mg.clone()),
623							Teban::Gote => (mg.clone(),ms.clone()),
624						}
625					},
626					MochigomaCollections::Empty => {
627						(Mochigoma::new(),Mochigoma::new())
628					},
629				};
630
631				let (mhash, shash) = hasher.calc_initial_hash(&banmen,&ms,&mg);
632
633				let mut mvs = mvs.into_iter().map(|m| m.to_applied_move()).collect::<Vec<AppliedMove>>();
634
635				let (mut teban,
636					 mut state,
637					 mut mc,
638					 mut mhash,
639					 mut shash,
640					 mut kyokumen_map,
641					 mut oute_kyokumen_map) = Rule::apply_moves(State::new(banmen),
642															 	teban,mc,&mvs,
643															 	mhash,shash,
644															 	kyokumen_map,
645															 	oute_kyokumen_map,&hasher);
646
647				if teban != teban_at_start {
648					cs_index = (cs_index + 1) % 2;
649				}
650
651				match self_match_event_queue.lock() {
652					Ok(mut self_match_event_queue) => {
653						self_match_event_queue.push(
654							SelfMatchEvent::GameStart(if cs_index == 1 {
655								2
656							} else {
657								1
658							}, teban, sfen.clone()));
659					},
660					Err(ref e) => {
661						let _ = on_error_handler.lock().map(|h| h.call(e));
662						return Err(SelfMatchRunningError::InvalidState(String::from(
663							"Exclusive lock on self_match_event_queue failed."
664						)));
665					}
666				}
667
668				while uptime.map_or(true, |t| Instant::now() - start_time < t) {
669					match user_event_queue[cs_index].lock() {
670						Ok(mut user_event_queue) => {
671							user_event_queue.clear();
672						},
673						Err(ref e) => {
674							let _ = on_error_handler.lock().map(|h| h.call(e));
675						}
676					}
677
678					match ponders[cs_index] {
679						None => {
680							let _ = cs[cs_index].send(SelfMatchMessage::StartThink(
681								teban_at_start.clone(),banmen_at_start.clone(),mc_at_start.clone(),n,mvs.clone(),Instant::now()));
682						},
683						pm @ Some(_) if pm == prev_move => {
684							match user_event_queue[cs_index].lock() {
685								Ok(mut user_event_queue) => {
686									user_event_queue.push(UserEvent::PonderHit(Instant::now()));
687								},
688								Err(ref e) => {
689									let _ = on_error_handler.lock().map(|h| h.call(e));
690								}
691							}
692							let _ = cs[cs_index].send(SelfMatchMessage::PonderHit);
693						},
694						_ => {
695							match user_event_queue[cs_index].lock() {
696								Ok(mut user_event_queue) => {
697									user_event_queue.push(UserEvent::Stop);
698								},
699								Err(ref e) => {
700									let _ = on_error_handler.lock().map(|h| h.call(e));
701								}
702							}
703							let _ = cs[cs_index].send(SelfMatchMessage::PonderNG);
704							let _ = cs[cs_index].send(SelfMatchMessage::StartThink(
705								teban_at_start.clone(),banmen_at_start.clone(),mc_at_start.clone(),n,mvs.clone(),Instant::now()));
706						}
707					}
708
709					let think_start_time = Instant::now();
710
711					let timeout = current_time_limit.map(|cl| uptime.map(|u| {
712						if start_time + u < cl {
713							start_time + u - Instant::now()
714						} else {
715							cl - Instant::now()
716						}
717					}).unwrap_or(cl - Instant::now()))
718						.map(|d| after(d))
719						.unwrap_or_else(|| uptime.map(|u| after(start_time + u - Instant::now()))
720						.unwrap_or(never()));
721
722					let timeout_kind = current_time_limit.map(|cl| uptime.map(|u| {
723						if start_time + u < cl {
724							TimeoutKind::Uptime
725						} else {
726							TimeoutKind::Turn
727						}
728					}).unwrap_or(TimeoutKind::Turn))
729						.unwrap_or_else(|| uptime.map(|_| TimeoutKind::Uptime).unwrap_or(TimeoutKind::Never));
730
731					select! {
732						recv(sr) -> message => {
733							match message? {
734								SelfMatchMessage::NotifyMove(BestMove::Move(m,pm)) => {
735									match self_match_event_queue.lock() {
736										Ok(mut self_match_event_queue) => {
737											self_match_event_queue.push(SelfMatchEvent::Moved(teban,Moved::try_from((state.get_banmen(),&m))?));
738										},
739										Err(ref e) => {
740											let _ = on_error_handler.lock().map(|h| h.call(e));
741											return Err(SelfMatchRunningError::InvalidState(String::from(
742												"Exclusive lock on self_match_event_queue failed."
743											)));
744										}
745									}
746
747									current_game_time_limit[cs_index] = Rule::update_time_limit(
748										&current_game_time_limit[cs_index],
749										teban,think_start_time.elapsed()
750									);
751									current_time_limit = current_game_time_limit[cs_index].to_instant(teban,Instant::now());
752
753									let m = m.to_applied_move();
754
755									match Rule::apply_valid_move(&state,teban,&mc,m) {
756										Ok((next,nmc,o)) => {
757
758											let is_win = Rule::is_win(&state,teban,m);
759
760											if is_win {
761												mvs.push(m);
762
763												kifu_writer(&sfen,&mvs.into_iter()
764																		.map(|m| m.to_move())
765																		.collect::<Vec<Move>>());
766												on_gameend(
767													cs[cs_index].clone(),
768													cs[(cs_index+1) % 2].clone(),
769													[cs[0].clone(),cs[1].clone()],
770													&sr,
771													SelfMatchGameEndState::Win(teban)
772												)?;
773												break;
774											}
775
776											if Rule::in_check(teban.opposite(),&state) {
777												if Rule::in_check(teban.opposite(),&next) {
778													mvs.push(m);
779													kifu_writer(&sfen,&mvs.into_iter()
780																			.map(|m| m.to_move())
781																			.collect::<Vec<Move>>());
782													on_gameend(
783														cs[(cs_index+1) % 2].clone(),
784														cs[cs_index].clone(),
785														[cs[0].clone(),cs[1].clone()],
786														&sr,
787														SelfMatchGameEndState::Foul(teban,FoulKind::NotRespondedOute)
788													)?;
789													break;
790												}
791											} else {
792												if Rule::in_check(teban.opposite(),&next) {
793													mvs.push(m);
794													kifu_writer(&sfen,&mvs.into_iter()
795																			.map(|m| m.to_move())
796																			.collect::<Vec<Move>>());
797													on_gameend(
798														cs[(cs_index+1) % 2].clone(),
799														cs[cs_index].clone(),
800														[cs[0].clone(),cs[1].clone()],
801														&sr,
802														SelfMatchGameEndState::Foul(teban,FoulKind::Suicide)
803													)?;
804													break;
805												}
806											}
807
808											mvs.push(m);
809
810											mhash = hasher.calc_main_hash(mhash,teban,&state.get_banmen(),&mc,m,&o);
811											shash = hasher.calc_sub_hash(shash,teban,&state.get_banmen(),&mc,m,&o);
812
813											mc = nmc;
814											state = next;
815
816											if Rule::is_put_fu_and_mate(&state,teban,&mc,m) {
817												kifu_writer(&sfen,&mvs.into_iter()
818																				.map(|m| m.to_move())
819																				.collect::<Vec<Move>>());
820												on_gameend(
821													cs[(cs_index+1) % 2].clone(),
822													cs[cs_index].clone(),
823													[cs[0].clone(),cs[1].clone()],
824													&sr,
825													SelfMatchGameEndState::Foul(teban,FoulKind::PutFuAndMate)
826												)?;
827												break;
828											}
829
830											if Rule::is_sennichite_by_oute(
831												&state,
832												teban,mhash,shash,
833												&oute_kyokumen_map
834											) {
835												kifu_writer(&sfen,&mvs.into_iter()
836																		.map(|m| m.to_move())
837																		.collect::<Vec<Move>>());
838												on_gameend(
839													cs[(cs_index+1) % 2].clone(),
840													cs[cs_index].clone(),
841													[cs[0].clone(),cs[1].clone()],
842													&sr,
843													SelfMatchGameEndState::Foul(teban,FoulKind::SennichiteOu)
844												)?;
845												break;
846											}
847
848											Rule::update_sennichite_by_oute_map(
849												&state,
850												teban,mhash,shash,
851												&mut oute_kyokumen_map
852											);
853
854											if Rule::is_sennichite(
855												&state,teban,mhash,shash,&kyokumen_map
856											) {
857												kifu_writer(&sfen,&mvs.into_iter()
858																		.map(|m| m.to_move())
859																		.collect::<Vec<Move>>());
860												on_gameend(
861													cs[(cs_index+1) % 2].clone(),
862													cs[cs_index].clone(),
863													[cs[0].clone(),cs[1].clone()],
864													&sr,
865													SelfMatchGameEndState::Foul(teban,FoulKind::Sennichite)
866												)?;
867												break;
868											}
869
870											Rule::update_sennichite_map(
871												&state,teban,mhash,shash,&mut kyokumen_map
872											);
873
874											teban = teban.opposite();
875
876											ponders[cs_index] = pm.map(|pm| pm.to_applied_move());
877
878											match pm {
879												Some(pm) => {
880													match mvs.clone() {
881														mut mvs => {
882															mvs.push(pm.to_applied_move());
883															cs[cs_index].send(
884																SelfMatchMessage::StartPonderThink(
885																	teban_at_start.clone(),banmen_at_start.clone(),
886																	mc_at_start.clone(),n,mvs))?;
887														}
888													}
889												},
890												None => (),
891											}
892
893											cs_index = (cs_index + 1) % 2;
894										},
895										Err(_) => {
896											mvs.push(m);
897											kifu_writer(&sfen,&mvs.into_iter()
898																	.map(|m| m.to_move())
899																	.collect::<Vec<Move>>());
900											on_gameend(
901												cs[(cs_index+1) % 2].clone(),
902												cs[cs_index].clone(),
903												[cs[0].clone(),cs[1].clone()],
904												&sr,
905												SelfMatchGameEndState::Foul(teban,FoulKind::InvalidMove)
906											)?;
907											break;
908										}
909									}
910									prev_move = Some(m)
911								},
912								SelfMatchMessage::NotifyMove(BestMove::Resign) => {
913									kifu_writer(&sfen,&mvs.into_iter()
914															.map(|m| m.to_move())
915															.collect::<Vec<Move>>());
916									on_gameend(
917										cs[(cs_index+1) % 2].clone(),
918										cs[cs_index].clone(),
919										[cs[0].clone(),cs[1].clone()],
920										&sr,
921										SelfMatchGameEndState::Resign(teban)
922									)?;
923									break;
924								},
925								SelfMatchMessage::NotifyMove(BestMove::Abort) => {
926									match self_match_event_queue.lock() {
927										Ok(mut self_match_event_queue) => {
928											self_match_event_queue.push(SelfMatchEvent::Abort);
929											cs[0].send(SelfMatchMessage::Abort)?;
930											cs[1].send(SelfMatchMessage::Abort)?;
931										},
932										Err(ref e) => {
933											let _ = on_error_handler.lock().map(|h| h.call(e));
934											return Err(SelfMatchRunningError::InvalidState(String::from(
935												"Exclusive lock on self_match_event_queue failed."
936											)));
937										}
938									}
939									break;
940								},
941								SelfMatchMessage::NotifyMove(BestMove::Win) if Rule::is_nyugyoku_win(&state,teban,&mc,&current_time_limit)=> {
942									kifu_writer(&sfen,&mvs.into_iter()
943															.map(|m| m.to_move())
944															.collect::<Vec<Move>>());
945									on_gameend(
946										cs[cs_index].clone(),
947										cs[(cs_index+1) % 2].clone(),
948										[cs[0].clone(),cs[1].clone()],
949										&sr,
950										SelfMatchGameEndState::NyuGyokuWin(teban)
951									)?;
952									break;
953								},
954								SelfMatchMessage::NotifyMove(BestMove::Win) => {
955									kifu_writer(&sfen,&mvs.into_iter()
956															.map(|m| m.to_move())
957															.collect::<Vec<Move>>());
958									on_gameend(
959										cs[(cs_index+1) % 2].clone(),
960										cs[cs_index].clone(),
961										[cs[0].clone(),cs[1].clone()],
962										&sr,
963										SelfMatchGameEndState::NyuGyokuLose(teban)
964									)?;
965									break;
966								},
967								SelfMatchMessage::Error(n) => {
968									return Err(SelfMatchRunningError::PlayerThreadError(n));
969								},
970								SelfMatchMessage::Quit => {
971									quit_notification();
972
973									cs[0].send(SelfMatchMessage::Quit)?;
974									cs[1].send(SelfMatchMessage::Quit)?;
975
976									return Ok(SelfMatchResult {
977										game_count: game_count,
978										elapsed: start_time.elapsed(),
979										start_dt:start_dt,
980										end_dt:Local::now(),
981									});
982								},
983								_ => {
984									return Err(SelfMatchRunningError::InvalidState(String::from(
985										"An invalid message was sent to the self-match management thread."
986									)));
987								}
988							}
989						},
990						recv(timeout) -> message => {
991							match message? {
992								_ => {
993									match user_event_queue[cs_index].lock() {
994										Ok(mut user_event_queue) => {
995											user_event_queue.push(UserEvent::Stop);
996										},
997										Err(ref e) => {
998											let _ = on_error_handler.lock().map(|h| h.call(e));
999										}
1000									}
1001
1002									match timeout_kind {
1003										TimeoutKind::Turn => {
1004											kifu_writer(&sfen,&mvs.into_iter().map(|m| m.to_move()).collect::<Vec<Move>>());
1005											match sr.recv()? {
1006												SelfMatchMessage::NotifyMove(_) => {
1007													on_gameend(
1008													cs[(cs_index+1) % 2].clone(),
1009													cs[cs_index].clone(),
1010													[cs[0].clone(),cs[1].clone()],
1011													&sr,
1012													SelfMatchGameEndState::Timeover(teban))?;
1013
1014												},
1015												_ => {
1016													return Err(SelfMatchRunningError::InvalidState(String::from(
1017														"An invalid message was sent to the self-match management thread."
1018													)));
1019												}
1020											}
1021
1022											break;
1023										},
1024										TimeoutKind::Uptime => {
1025											match sr.recv()? {
1026												SelfMatchMessage::NotifyMove(_) => {
1027													break 'gameloop;
1028												},
1029												_ => {
1030													return Err(SelfMatchRunningError::InvalidState(String::from(
1031														"An invalid message was sent to the self-match management thread."
1032													)));
1033												}
1034											}
1035										},
1036										_ => {
1037											return Err(SelfMatchRunningError::InvalidState(String::from(
1038												"Timeout kind is invalid."
1039											)));
1040										}
1041									}
1042								}
1043							}
1044						}
1045					}
1046				}
1047			}
1048			quit_notification();
1049
1050			cs[0].send(SelfMatchMessage::Quit)?;
1051			cs[1].send(SelfMatchMessage::Quit)?;
1052
1053			Ok(SelfMatchResult {
1054				game_count: game_count,
1055				elapsed: start_time.elapsed(),
1056				start_dt:start_dt,
1057				end_dt:Local::now()
1058			})
1059		}, on_error_handler.clone()).map_err(|e| {
1060			match e {
1061				SelfMatchRunningError::SendError(SendError(SelfMatchMessage::Error(n))) => {
1062					let r = if n == 0 {
1063						cs2.send(SelfMatchMessage::Error(0))
1064					} else {
1065						cs1.send(SelfMatchMessage::Error(1))
1066					};
1067					if let Err(ref e) = r {
1068						let _ = on_error_handler.lock().map(|h| h.call(e));
1069					}
1070				},
1071				SelfMatchRunningError::PlayerThreadError(0) => {
1072					if let Err(ref e) = cs2.send(SelfMatchMessage::Error(0)) {
1073						let _ = on_error_handler.lock().map(|h| h.call(e));
1074					}
1075				},
1076				SelfMatchRunningError::PlayerThreadError(1) => {
1077					if let Err(ref e) = cs1.send(SelfMatchMessage::Error(1)) {
1078						let _ = on_error_handler.lock().map(|h| h.call(e));
1079					}
1080				},
1081				_ => {
1082					if let Err(ref e) = cs1.send(SelfMatchMessage::Error(0)) {
1083						let _ = on_error_handler.lock().map(|h| h.call(e));
1084					}
1085					if let Err(ref e) = cs2.send(SelfMatchMessage::Error(1)) {
1086						let _ = on_error_handler.lock().map(|h| h.call(e));
1087					}
1088				}
1089			}
1090			quit_ready.store(true,Ordering::Release);
1091			e
1092		}));
1093
1094		let mut players = vec![player1,player2];
1095		let mut handlers:Vec<JoinHandle<Result<(),SelfMatchRunningError<E>>>> = Vec::with_capacity(2);
1096
1097		for i in 0..2 {
1098			let cr = cr.remove(0);
1099			let mut player = players.remove(0);
1100			let on_error_handler = on_error_handler_arc.clone();
1101			let logger = logger_arc.clone();
1102			let user_event_queue = [user_event_queue_arc[0].clone(),user_event_queue_arc[1].clone()];
1103			let quit_ready = quit_ready_arc.clone();
1104			let info_sender = info_sender.clone();
1105			let pinfo_sender = pinfo_sender.clone();
1106			let limit = game_time_limit;
1107
1108			let ss = ss.clone();
1109
1110			let player_i = i;
1111
1112			handlers.push(thread::spawn(move || SandBox::immediate(|| {
1113				loop {
1114					match cr.recv()? {
1115						SelfMatchMessage::GameStart => {
1116							let writer = Arc::new(Mutex::new(VoidOutPutWriter));
1117
1118							player.take_ready(OnKeepAlive::new(writer,on_error_handler.clone()))?;
1119							player.newgame()?;
1120
1121							loop {
1122								match cr.recv()? {
1123									SelfMatchMessage::StartThink(t,b,mc,n,m,s) => {
1124										let (ms, mg) = match mc {
1125											MochigomaCollections::Pair(ref ms, ref mg) => {
1126												(ms.clone(),mg.clone())
1127											},
1128											MochigomaCollections::Empty => {
1129												(Mochigoma::new(),Mochigoma::new())
1130											}
1131										};
1132
1133										player.set_position(t, b, ms, mg, n, m.into_iter().map(|m| {
1134											m.to_move()
1135										}).collect::<Vec<Move>>())?;
1136
1137										let m = player.think(s,&limit,
1138															user_event_queue[player_i].clone(),
1139															info_sender.clone(),
1140															 pinfo_sender.clone(),
1141															 on_error_handler.clone())?;
1142
1143										if !quit_ready.load(Ordering::Acquire) {
1144											ss.send(SelfMatchMessage::NotifyMove(m))?;
1145										}
1146									},
1147									SelfMatchMessage::StartPonderThink(t,b,mc,n,m) => {
1148										let (ms, mg) = match mc {
1149											MochigomaCollections::Pair(ref ms, ref mg) => {
1150												(ms.clone(),mg.clone())
1151											},
1152											MochigomaCollections::Empty => {
1153												(Mochigoma::new(),Mochigoma::new())
1154											}
1155										};
1156
1157										player.set_position(t, b, ms, mg, n, m.into_iter().map(|m| {
1158											m.to_move()
1159										}).collect::<Vec<Move>>())?;
1160
1161										let m = player.think_ponder(&limit,
1162																user_event_queue[player_i].clone(),
1163																info_sender.clone(),
1164																	pinfo_sender.clone(),
1165																	on_error_handler.clone())?;
1166
1167										match cr.recv()? {
1168											SelfMatchMessage::PonderHit => {
1169												if !quit_ready.load(Ordering::Acquire) {
1170													ss.send(SelfMatchMessage::NotifyMove(m))?;
1171												}
1172											},
1173											SelfMatchMessage::PonderNG => (),
1174											SelfMatchMessage::Quit => {
1175												player.quit()?;
1176
1177												return Ok(());
1178											},
1179											SelfMatchMessage::Abort => {
1180												break;
1181											},
1182											SelfMatchMessage::Error(_) => {
1183												return Ok(());
1184											}
1185											_ => {
1186												let _ = logger.lock().map(|mut logger| {
1187													logger.logging(&format!("Invalid message."))
1188												}).map_err(|_| {
1189													USIStdErrorWriter::write("Logger's exclusive lock could not be secured").unwrap();
1190													false
1191												});
1192
1193												if !quit_ready.load(Ordering::Acquire) {
1194													if !quit_ready.load(Ordering::Acquire) {
1195														ss.send(SelfMatchMessage::Error(player_i))?;
1196													}
1197												}
1198												break;
1199											}
1200										}
1201									},
1202									SelfMatchMessage::GameEnd(s) => {
1203										player.gameover(&s,user_event_queue[player_i].clone(),
1204																		on_error_handler.clone())?;
1205
1206										if !quit_ready.load(Ordering::Acquire) {
1207											ss.send(SelfMatchMessage::Ready)?;
1208										}
1209
1210										break;
1211									},
1212									SelfMatchMessage::Abort => {
1213										break;
1214									},
1215									SelfMatchMessage::Quit => {
1216										player.quit()?;
1217
1218										return Ok(());
1219									},
1220									SelfMatchMessage::Error(_) => {
1221										return Ok(());
1222									},
1223									_ => {
1224										let _ = logger.lock().map(|mut logger| {
1225											logger.logging(&format!("Invalid message."))
1226										}).map_err(|_| {
1227											USIStdErrorWriter::write("Logger's exclusive lock could not be secured").unwrap();
1228											false
1229										});
1230
1231										if !quit_ready.load(Ordering::Acquire) {
1232											ss.send(SelfMatchMessage::Error(player_i))?;
1233										}
1234
1235										break;
1236									}
1237								}
1238							}
1239						},
1240						SelfMatchMessage::Quit => {
1241							player.quit()?;
1242
1243							return Ok(());
1244						},
1245						SelfMatchMessage::Error(_) => {
1246							return Ok(());
1247						},
1248						_ => {
1249							let _ = logger.lock().map(|mut logger| {
1250								logger.logging(&format!("Invalid message."))
1251							}).map_err(|_| {
1252								USIStdErrorWriter::write("Logger's exclusive lock could not be secured").unwrap();
1253								false
1254							});
1255
1256							if !quit_ready.load(Ordering::Acquire) {
1257								ss.send(SelfMatchMessage::Error(player_i))?;
1258							}
1259						}
1260					}
1261				}
1262			}, on_error_handler.clone()).map_err(|e| {
1263				match e {
1264					SelfMatchRunningError::SendError(SendError(_)) |
1265						SelfMatchRunningError::RecvError(_) => (),
1266					_ if !quit_ready.load(Ordering::Acquire) => {
1267						if let Err(ref e) = ss.send(SelfMatchMessage::Error(player_i)) {
1268							let _ = on_error_handler.lock().map(|h| h.call(e));
1269						}
1270					},
1271					_ => (),
1272				}
1273				e
1274			})));
1275		}
1276
1277		let delay = Duration::from_millis(50);
1278		let on_error_handler = on_error_handler_arc.clone();
1279		let self_match_event_queue = self_match_event_queue_arc.clone();
1280		let logger = logger_arc.clone();
1281		let quit_ready = quit_ready_arc.clone();
1282
1283		thread::spawn(move || {
1284			while !quit_ready.load(Ordering::Acquire) {
1285				match input_reader.read() {
1286					Ok(Some(line)) => {
1287						match input_handler(line) {
1288							Ok(false) => {
1289								return;
1290							},
1291							Err(ref e) => {
1292								let _ = on_error_handler.lock().map(|h| h.call(e));
1293								return;
1294							},
1295							_ => (),
1296						}
1297					},
1298					Err(ref e) if !quit_ready.load(Ordering::Acquire) => {
1299						let _ = on_error_handler.lock().map(|h| h.call(e));
1300						return;
1301					},
1302					_ => (),
1303				}
1304			}
1305		});
1306
1307		let on_error_handler = on_error_handler_arc.clone();
1308
1309		let quit_ready = quit_ready_arc.clone();
1310
1311		while !quit_ready.load(Ordering::Acquire) || (match self.system_event_queue.lock() {
1312			Ok(system_event_queue) => system_event_queue.has_event(),
1313			Err(ref e) => {
1314				let _ = on_error_handler.lock().map(|h| h.call(e));
1315				false
1316			}
1317		}) || (match self_match_event_queue.lock() {
1318			Ok(self_match_event_queue) => self_match_event_queue.has_event(),
1319			Err(ref e) => {
1320				let _ = on_error_handler.lock().map(|h| h.call(e));
1321				false
1322			}
1323		}) {
1324			match system_event_dispatcher.dispatch_events(self, &*self.system_event_queue) {
1325				Ok(_) => true,
1326				Err(ref e) => {
1327					on_error_handler.lock().map(|h| h.call(e)).is_err()
1328				}
1329			};
1330			match self_match_event_dispatcher.dispatch_events(self, &*self_match_event_queue) {
1331				Ok(_) => true,
1332				Err(ref e) => {
1333					on_error_handler.lock().map(|h| h.call(e)).is_err()
1334				}
1335			};
1336			thread::sleep(delay);
1337		}
1338
1339		let mut has_error = false;
1340
1341		let result = bridge_h.join().map_err(|_| {
1342			has_error = true;
1343			let _ = logger.lock().map(|mut logger| {
1344				logger.logging(&format!("Main thread join failed."))
1345			}).map_err(|_| {
1346				USIStdErrorWriter::write("Logger's exclusive lock could not be secured").unwrap();
1347				false
1348			});
1349		}).unwrap_or(Err(SelfMatchRunningError::ThreadJoinFailed(String::from(
1350			"Main thread join failed."
1351		)))).map_err(|e| {
1352			has_error = true;
1353			e
1354		});
1355
1356		for h in handlers {
1357			let _ = h.join().map_err(|_| {
1358				has_error = true;
1359				let _ = logger.lock().map(|mut logger| {
1360					logger.logging(&format!("Sub thread join failed."))
1361				}).map_err(|_| {
1362					USIStdErrorWriter::write("Logger's exclusive lock could not be secured").unwrap();
1363					false
1364				});
1365			}).map(|r| {
1366				r.map_err(|e| {
1367					has_error = true;
1368					e
1369				}).is_err()
1370			});
1371		}
1372
1373		if has_error {
1374			Err(SelfMatchRunningError::Fail(String::from(
1375				"An error occurred while executing a self match. Please see the log for details ..."
1376			)))
1377		} else {
1378			result
1379		}
1380	}
1381}