1use std::{thread,time};
3use std::time::Instant;
4use std::sync::{atomic, mpsc, Mutex};
5use std::sync::Arc;
6use std::sync::atomic::AtomicBool;
7use std::collections::BTreeMap;
8use std::fmt;
9use std::error::Error;
10use std::convert::TryFrom;
11
12use std::sync::mpsc::{Receiver, Sender};
13
14use command::*;
15use error::*;
16use event::*;
17use shogi::*;
18use protocol::*;
19use rule::*;
20use output::*;
21use Logger;
22use OnErrorHandler;
23use crossbeam_channel::{unbounded, after};
24
25pub trait USIPlayer<E>: fmt::Debug where E: PlayerError {
27 const ID: &'static str;
29 const AUTHOR: &'static str;
31 fn get_option_kinds(&mut self) -> Result<BTreeMap<String,SysEventOptionKind>,E>;
33 fn get_options(&mut self) -> Result<BTreeMap<String,UsiOptType>,E>;
35 fn take_ready<W,L>(&mut self, on_keep_alive:OnKeepAlive<W,L>)
39 -> Result<(),E> where W: USIOutputWriter + Send + 'static, L: Logger + Send + 'static;
40 fn set_option(&mut self,name:String,value:SysEventOption) -> Result<(),E>;
45 fn newgame(&mut self) -> Result<(),E>;
47 fn set_position(&mut self,teban:Teban,ban:Banmen,ms:Mochigoma,mg:Mochigoma,n:u32,m:Vec<Move>)
56 -> Result<(),E>;
57 fn think<L,S,P>(&mut self,think_start_time:Instant,limit:&UsiGoTimeLimit,event_queue:Arc<Mutex<UserEventQueue>>,
66 info_sender:S,periodically_info:P,on_error_handler:Arc<Mutex<OnErrorHandler<L>>>)
67 -> Result<BestMove,E> where L: Logger + Send + 'static,
68 S: InfoSender,
69 P: PeriodicallyInfo,;
70 fn think_ponder<L,S,P>(&mut self,limit:&UsiGoTimeLimit,event_queue:Arc<Mutex<UserEventQueue>>,
78 info_sender:S,periodically_info:P,on_error_handler:Arc<Mutex<OnErrorHandler<L>>>)
79 -> Result<BestMove,E> where L: Logger + Send + 'static,
80 S: InfoSender + Send + 'static,
81 P: PeriodicallyInfo;
82 fn think_mate<L,S,P>(&mut self,limit:&UsiGoMateTimeLimit,event_queue:Arc<Mutex<UserEventQueue>>,
90 info_sender:S,periodically_info:P,on_error_handler:Arc<Mutex<OnErrorHandler<L>>>)
91 -> Result<CheckMate,E> where L: Logger + Send + 'static,
92 S: InfoSender,
93 P: PeriodicallyInfo;
94 fn on_stop(&mut self,e:&UserEvent) -> Result<(), E> where E: PlayerError;
96 fn on_ponderhit(&mut self,e:&UserEvent) -> Result<(), E> where E: PlayerError;
98 fn gameover<L>(&mut self,s:&GameEndState,
104 event_queue:Arc<Mutex<UserEventQueue>>,
105 on_error_handler:Arc<Mutex<OnErrorHandler<L>>>) -> Result<(),E> where L: Logger, Arc<Mutex<OnErrorHandler<L>>>: Send + 'static;
106 fn on_quit(&mut self,e:&UserEvent) -> Result<(), E> where E: PlayerError;
108 fn quit(&mut self) -> Result<(),E>;
110 fn handle_events<'a,L>(&mut self,event_queue:&'a Mutex<UserEventQueue>,
115 on_error_handler:&Mutex<OnErrorHandler<L>>) -> Result<bool,E>
116 where L: Logger, E: Error + fmt::Debug,
117 Arc<Mutex<OnErrorHandler<L>>>: Send + 'static,
118 EventHandlerError<UserEventKind,E>: From<E> {
119 Ok(match self.dispatch_events(event_queue,&on_error_handler) {
120 Ok(_)=> true,
121 Err(ref e) => {
122 let _ = on_error_handler.lock().map(|h| h.call(e));
123 false
124 }
125 })
126 }
127
128 fn dispatch_events<'a,L>(&mut self, event_queue:&'a Mutex<UserEventQueue>,
133 on_error_handler:&Mutex<OnErrorHandler<L>>) ->
134 Result<(), EventDispatchError<'a,UserEventQueue,UserEvent,E>>
135 where L: Logger, E: Error + fmt::Debug,
136 Arc<Mutex<OnErrorHandler<L>>>: Send + 'static,
137 EventHandlerError<UserEventKind,E>: From<E> {
138 let events = {
139 event_queue.lock()?.drain_events()
140 };
141
142 let mut has_error = false;
143
144 for e in &events {
145 match e {
146 &UserEvent::Stop => {
147 match self.on_stop(e) {
148 Ok(_) => (),
149 Err(ref e) => {
150 let _ = on_error_handler.lock().map(|h| h.call(e));
151 has_error = true;
152 }
153 };
154 },
155 &UserEvent::PonderHit(_) => {
156 match self.on_ponderhit(e) {
157 Ok(_) => (),
158 Err(ref e) => {
159 let _ = on_error_handler.lock().map(|h| h.call(e));
160 has_error = true;
161 }
162 };
163 },
164 &UserEvent::Quit => {
165 match self.on_quit(e) {
166 Ok(_) => (),
167 Err(ref e) => {
168 let _ = on_error_handler.lock().map(|h| h.call(e));
169 has_error = true;
170 }
171 };
172 }
173 };
174 }
175
176 match has_error {
177 true => Err(EventDispatchError::ContainError),
178 false => Ok(()),
179 }
180 }
181
182 fn apply_moves<T,F>(&self,mut state:State,
191 mut teban:Teban,
192 mut mc:MochigomaCollections,
193 m:&Vec<AppliedMove>,mut r:T,mut f:F)
194 -> (Teban,State,MochigomaCollections,T)
195 where F: FnMut(&Self,Teban,&Banmen,
196 &MochigomaCollections,&Option<AppliedMove>,
197 &Option<MochigomaKind>,T) -> T {
198
199 for m in m {
200 match Rule::apply_move_none_check(&state,teban,&mc,*m) {
201 (next,nmc,o) => {
202 r = f(self,teban,&state.get_banmen(),&mc,&Some(*m),&o,r);
203 state = next;
204 mc = nmc;
205 teban = teban.opposite();
206 }
207 }
208 }
209 r = f(self,teban,&state.get_banmen(),&mc,&None,&None,r);
210
211 (teban,state,mc,r)
212 }
213}
214#[derive(Clone, Debug)]
216pub enum UsiInfoMessage {
217 Commands(Vec<UsiInfoSubCommand>),
219 Flush,
221 Quit,
223}
224pub trait InfoSender: Clone + Send + 'static {
226 fn send(&mut self,commands:Vec<UsiInfoSubCommand>) -> Result<(), InfoSendError>;
231 fn send_immediate(&mut self,commands:Vec<UsiInfoSubCommand>) -> Result<(), InfoSendError>;
236 fn flush(&mut self) -> Result<(), InfoSendError> {
237 Ok(())
238 }
239}
240pub struct USIInfoSender<W> where W: USIOutputWriter + Send + 'static {
242 worker:InfoSendWorker<W>
243}
244impl<W> USIInfoSender<W> where W: USIOutputWriter + Send + 'static {
245 pub fn new(worker:InfoSendWorker<W>) -> USIInfoSender<W> {
250 USIInfoSender {
251 worker:worker
252 }
253 }
254}
255impl<W> InfoSender for USIInfoSender<W> where W: USIOutputWriter + Send + 'static {
256 fn send(&mut self,commands:Vec<UsiInfoSubCommand>) -> Result<(), InfoSendError> {
257 if let Err(_) = self.worker.sender.send(UsiInfoMessage::Commands(commands)) {
258 Err(InfoSendError::Fail(String::from(
259 "info command send failed.")))
260 } else {
261 Ok(())
262 }
263 }
264
265 fn send_immediate(&mut self, commands: Vec<UsiInfoSubCommand>) -> Result<(), InfoSendError> {
266 self.send(commands)?;
267 Ok(self.flush()?)
268 }
269
270 fn flush(&mut self) -> Result<(), InfoSendError> {
271 if let Err(_) = self.worker.sender.send(UsiInfoMessage::Flush) {
272 Err(InfoSendError::Fail(String::from(
273 "info sender buffer flush failed.")))
274 } else {
275 Ok(())
276 }
277 }
278}
279impl<W> Clone for USIInfoSender<W> where W: USIOutputWriter + Send + 'static {
280 fn clone(&self) -> USIInfoSender<W> {
281 USIInfoSender::new(self.worker.clone())
282 }
283}
284pub struct InfoSendWorker<W> where W: USIOutputWriter {
286 sender:Sender<UsiInfoMessage>,
287 writer:Arc<Mutex<W>>,
288 quited:Arc<AtomicBool>
289}
290const INFO_SEND_BUFFER_SIZE:usize = 100;
291
292impl<W> InfoSendWorker<W> where W: USIOutputWriter {
293 pub fn new<L>(writer:Arc<Mutex<W>>,
300 notifier:Sender<()>,
301 on_error_handler:Arc<Mutex<OnErrorHandler<L>>>)
302 -> InfoSendWorker<W> where L: Logger,
303 Arc<Mutex<W>>: Send + 'static,
304 Arc<Mutex<OnErrorHandler<L>>>: Send + 'static {
305 let mut buffer = Vec::with_capacity(INFO_SEND_BUFFER_SIZE);
306
307 let (sender,receiver) = mpsc::channel();
308 {
309 let writer = writer.clone();
310
311 thread::spawn(move || {
312 loop {
313 match receiver.recv() {
314 Ok(UsiInfoMessage::Commands(commands)) => {
315 let command = match UsiInfoCommand(commands).to_usi_command() {
316 Ok(command) => command,
317 Err(ref e) => {
318 let _ = on_error_handler.lock().map(|h| h.call(e));
319 break;
320 }
321 };
322
323 buffer.push(command);
324
325 if buffer.len() >= INFO_SEND_BUFFER_SIZE {
326 match writer.lock() {
327 Err(ref e) => {
328 let _ = on_error_handler.lock().map(|h| h.call(e));
329 break;
330 },
331 Ok(ref writer) => {
332 if let Err(ref e) = writer.write(&buffer) {
333 let _ = on_error_handler.lock().map(|h| h.call(e));
334 break;
335 }
336 buffer.clear();
337 }
338 }
339 }
340 },
341 Ok(UsiInfoMessage::Flush) => {
342 if buffer.len() > 0 {
343 match writer.lock() {
344 Err(ref e) => {
345 let _ = on_error_handler.lock().map(|h| h.call(e));
346 },
347 Ok(ref writer) => {
348 if let Err(ref e) = writer.write(&buffer) {
349 let _ = on_error_handler.lock().map(|h| h.call(e));
350 }
351 }
352 }
353 }
354 },
355 Ok(UsiInfoMessage::Quit) => {
356 if buffer.len() > 0 {
357 match writer.lock() {
358 Err(ref e) => {
359 let _ = on_error_handler.lock().map(|h| h.call(e));
360 },
361 Ok(ref writer) => {
362 if let Err(ref e) = writer.write(&buffer) {
363 let _ = on_error_handler.lock().map(|h| h.call(e));
364 }
365 }
366 }
367 }
368
369 break;
370 },
371 Err(ref e) => {
372 let _ = on_error_handler.lock().map(|h| h.call(e));
373 break;
374 }
375 }
376 }
377
378 if let Err(ref e) = notifier.send(()) {
379 let _ = on_error_handler.lock().map(|h| h.call(e));
380 }
381 });
382 }
383
384 InfoSendWorker {
385 sender:sender,
386 writer:writer,
387 quited:Arc::new(AtomicBool::new(false))
388 }
389 }
390
391 pub fn quit(&self,receiver:Receiver<()>) -> Result<(), InfoSendWorkerError> {
393 if !self.quited.swap(true,atomic::Ordering::Release) {
394 self.sender.send(UsiInfoMessage::Quit)?;
395 receiver.recv()?;
396 }
397 Ok(())
398 }
399}
400impl<W> Clone for InfoSendWorker<W> where W: USIOutputWriter {
401 fn clone(&self) -> Self {
402 InfoSendWorker {
403 sender:self.sender.clone(),
404 writer:self.writer.clone(),
405 quited:self.quited.clone()
406 }
407 }
408}
409pub struct ConsoleInfoSender {
411 writer:USIStdOutputWriter,
412 silent:bool,
413}
414impl ConsoleInfoSender {
415 pub fn new(silent:bool) -> ConsoleInfoSender {
420 ConsoleInfoSender {
421 writer:USIStdOutputWriter::new(),
422 silent:silent
423 }
424 }
425}
426impl InfoSender for ConsoleInfoSender {
427 fn send(&mut self,commands:Vec<UsiInfoSubCommand>) -> Result<(), InfoSendError> {
428 if !self.silent {
429 let lines = vec![commands.to_usi_command()?];
430
431 if let Err(_) = self.writer.write(&lines) {
432 return Err(InfoSendError::Fail(String::from(
433 "info command send failed.")))
434 }
435 }
436 Ok(())
437 }
438
439 fn send_immediate(&mut self, commands: Vec<UsiInfoSubCommand>) -> Result<(), InfoSendError> {
440 self.send(commands)
441 }
442}
443impl Clone for ConsoleInfoSender {
444 fn clone(&self) -> ConsoleInfoSender {
445 ConsoleInfoSender::new(self.silent)
446 }
447}
448pub trait KeepAliveSender {
450 fn send(&self);
452 #[must_use]
453 fn auto(&self,sec:u64) -> AutoKeepAlive;
463}
464pub struct OnKeepAlive<W,L> where W: USIOutputWriter + Send + 'static, L: Logger + Send + 'static {
466 writer:Arc<Mutex<W>>,
468 on_error_handler:Arc<Mutex<OnErrorHandler<L>>>
470}
471impl<W,L> OnKeepAlive<W,L> where W: USIOutputWriter + Send + 'static, L: Logger + Send + 'static {
472 pub fn new(writer:Arc<Mutex<W>>,on_error_handler:Arc<Mutex<OnErrorHandler<L>>>) -> OnKeepAlive<W,L> {
478 OnKeepAlive {
479 writer:writer,
480 on_error_handler:on_error_handler
481 }
482 }
483}
484impl<W,L> KeepAliveSender for OnKeepAlive<W,L> where W: USIOutputWriter + Send + 'static, L: Logger + Send + 'static {
485 fn send(&self) {
486 match self.writer.lock() {
487 Err(ref e) => {
488 let _ = self.on_error_handler.lock().map(|h| h.call(e));
489 },
490 Ok(ref writer) => {
491 if let Err(ref e) = writer.write(&vec![String::from("")]) {
492 let _ = self.on_error_handler.lock().map(|h| h.call(e));
493 }
494 }
495 };
496 }
497
498 #[must_use]
499 fn auto(&self,sec:u64) -> AutoKeepAlive {
500 AutoKeepAlive::new(sec,self.clone())
501 }
502}
503impl<W,L> Clone for OnKeepAlive<W,L> where W: USIOutputWriter + Send + 'static, L: Logger + Send + 'static {
504 fn clone(&self) -> OnKeepAlive<W,L> {
505 OnKeepAlive {
506 writer:self.writer.clone(),
507 on_error_handler:self.on_error_handler.clone()
508 }
509 }
510}
511pub struct AutoKeepAlive {
518 stop_sender:crossbeam_channel::Sender<()>
520}
521impl AutoKeepAlive {
522 fn new<W,L>(sec:u64,on_keep_alive: OnKeepAlive<W,L>)
528 -> AutoKeepAlive where W: USIOutputWriter + Send + 'static, L: Logger + Send + 'static {
529 let(s,r) = unbounded();
530
531 std::thread::spawn(move || {
532 let mut timeout = after(time::Duration::from_secs(sec));
533
534 loop {
535 select! {
536 recv(r) -> _ => {
537 return;
538 },
539 recv(timeout) -> _ => {
540 on_keep_alive.send();
541 timeout = after(time::Duration::from_secs(sec));
542 }
543 }
544 }
545 });
546
547 AutoKeepAlive {
548 stop_sender:s
549 }
550 }
551}
552impl Drop for AutoKeepAlive {
553 fn drop(&mut self) {
554 let _ = self.stop_sender.send(());
555 }
556}
557pub struct PeriodicallyInfoSender {
566 stop_sender:crossbeam_channel::Sender<()>,
568}
569impl PeriodicallyInfoSender {
570 pub fn new(stop_sender:crossbeam_channel::Sender<()>) -> PeriodicallyInfoSender {
572 PeriodicallyInfoSender {
573 stop_sender:stop_sender
574 }
575 }
576}
577impl Drop for PeriodicallyInfoSender {
578 fn drop(&mut self) {
579 let _ = self.stop_sender.send(());
580 }
581}
582pub trait PeriodicallyInfo: Send + 'static {
584 #[must_use]
585 fn start<F,L>(self,interval:u64,info_generator:F,on_error_handler:&Arc<Mutex<OnErrorHandler<L>>>)
597 -> PeriodicallyInfoSender where F: FnMut() -> Vec<UsiInfoSubCommand> + Sized + Send + 'static,
598 L: Logger + Send + 'static;
599}
600pub struct USIPeriodicallyInfo<W> where W: USIOutputWriter + Send + 'static {
601 writer:Arc<Mutex<W>>,
603 silent:bool
605}
606impl<W> USIPeriodicallyInfo<W>
607 where W: USIOutputWriter + Send + 'static {
608 pub fn new(writer:Arc<Mutex<W>>,silent:bool) -> USIPeriodicallyInfo<W> {
614 USIPeriodicallyInfo {
615 writer:writer,
616 silent:silent
617 }
618 }
619}
620impl<W> PeriodicallyInfo for USIPeriodicallyInfo<W>
621 where W: USIOutputWriter + Send + 'static {
622
623 #[must_use]
624 fn start<F,L>(self,interval:u64,info_generator:F,on_error_handler:&Arc<Mutex<OnErrorHandler<L>>>)
625 -> PeriodicallyInfoSender where F: FnMut() -> Vec<UsiInfoSubCommand> + Send + 'static,
626 L: Logger + Send + 'static {
627 let (s,r) = unbounded();
628
629 let writer = self.writer.clone();
630 let mut info_generator = info_generator;
631 let silent = self.silent;
632 let on_error_handler = on_error_handler.clone();
633
634 std::thread::spawn(move || {
635 let mut timeout = after(time::Duration::from_millis(interval));
636
637 loop {
638 select! {
639 recv(r) -> _ => {
640 return;
641 },
642 recv(timeout) -> _ => {
643 match UsiOutput::try_from(&UsiCommand::UsiInfo(info_generator())) {
644 Ok(UsiOutput::Command(ref s)) => {
645 match writer.lock() {
646 Err(ref e) => {
647 let _ = on_error_handler.lock().map(|h| h.call(e));
648 break;
649 },
650 Ok(ref writer) => {
651 if !silent {
652 let _ = writer.write(s).map_err(|e| on_error_handler.lock().map(|h| h.call(&e)));
653 }
654 }
655 };
656 },
657 Err(ref e) => {
658 let _ = on_error_handler.lock().map(|h| h.call(e));
659 break;
660 }
661 }
662 timeout = after(time::Duration::from_millis(interval));
663 }
664 }
665 }
666 });
667
668 PeriodicallyInfoSender::new(s)
669 }
670}
671impl<W> Clone for USIPeriodicallyInfo<W> where W: USIOutputWriter + Send + 'static {
672 fn clone(&self) -> USIPeriodicallyInfo<W> {
673 USIPeriodicallyInfo {
674 writer:self.writer.clone(),
675 silent:self.silent
676 }
677 }
678}
679pub struct ConsolePeriodicallyInfo {
680 inner:USIPeriodicallyInfo<USIStdOutputWriter>
681}
682impl ConsolePeriodicallyInfo {
683 pub fn new(silent:bool) -> ConsolePeriodicallyInfo {
688 ConsolePeriodicallyInfo {
689 inner:USIPeriodicallyInfo::new(
690 Arc::new(Mutex::new(USIStdOutputWriter::new())),
691 silent
692 )
693 }
694 }
695}
696impl PeriodicallyInfo for ConsolePeriodicallyInfo {
697 #[must_use]
698 fn start<F,L>(self,interval:u64,info_generator:F,on_error_handler:&Arc<Mutex<OnErrorHandler<L>>>)
699 -> PeriodicallyInfoSender where F: FnMut() -> Vec<UsiInfoSubCommand> + Send + 'static,
700 L: Logger + Send + 'static {
701 self.inner.start(interval,info_generator,on_error_handler)
702 }
703}
704impl Clone for ConsolePeriodicallyInfo {
705 fn clone(&self) -> ConsolePeriodicallyInfo {
706 ConsolePeriodicallyInfo {
707 inner:self.inner.clone()
708 }
709 }
710}