usiagent 0.7.0

USIAgent is a framework for Shogi AI development that supports the usi protocol.
Documentation
use std::time::{Instant,Duration};
use std::convert::TryFrom;

use usiagent::shogi::*;
use usiagent::event::*;
use usiagent::error::*;

#[allow(unused)]
use usiagent::shogi::KomaKind::{
	SFu,
	SKyou,
	SKei,
	SGin,
	SKin,
	SKaku,
	SHisha,
	SOu,
	SFuN,
	SKyouN,
	SKeiN,
	SGinN,
	SKakuN,
	SHishaN,
	GFu,
	GKyou,
	GKei,
	GGin,
	GKin,
	GKaku,
	GHisha,
	GOu,
	GFuN,
	GKyouN,
	GKeiN,
	GGinN,
	GKakuN,
	GHishaN,
	Blank
};
#[test]
fn test_movekind_display() {
	let input_and_expected:Vec<(MovedKind,&'static str)> = vec![
		(MovedKind::Fu,""),
		(MovedKind::Kyou,""),
		(MovedKind::Kei,""),
		(MovedKind::Gin,""),
		(MovedKind::Kin,""),
		(MovedKind::Kaku,""),
		(MovedKind::Hisha,""),
		(MovedKind::SOu,""),
		(MovedKind::GOu,""),
		(MovedKind::FuN,"成歩"),
		(MovedKind::KyouN,"成香"),
		(MovedKind::KeiN,"成桂"),
		(MovedKind::GinN,"成銀"),
		(MovedKind::KakuN,""),
		(MovedKind::HishaN,""),
		(MovedKind::Blank,"駒無し"),
	];

	for (i,r) in input_and_expected.into_iter() {
		assert_eq!(format!("{}",i).as_str(),r);
	}
}
#[test]
fn test_moved_try_from() {
	let input_and_expected:Vec<(KomaKind,Result<Moved, TypeConvertError<String>>)> = vec![
		(SFu,Ok(Moved::To(MovedKind::Fu,(9,1),(8,2),false))),
		(SKyou,Ok(Moved::To(MovedKind::Kyou,(9,1),(8,2),false))),
		(SKei,Ok(Moved::To(MovedKind::Kei,(9,1),(8,2),false))),
		(SGin,Ok(Moved::To(MovedKind::Gin,(9,1),(8,2),false))),
		(SKin,Ok(Moved::To(MovedKind::Kin,(9,1),(8,2),false))),
		(SKaku,Ok(Moved::To(MovedKind::Kaku,(9,1),(8,2),false))),
		(SHisha,Ok(Moved::To(MovedKind::Hisha,(9,1),(8,2),false))),
		(SOu,Ok(Moved::To(MovedKind::SOu,(9,1),(8,2),false))),
		(SFuN,Ok(Moved::To(MovedKind::FuN,(9,1),(8,2),false))),
		(SKyouN,Ok(Moved::To(MovedKind::KyouN,(9,1),(8,2),false))),
		(SKeiN,Ok(Moved::To(MovedKind::KeiN,(9,1),(8,2),false))),
		(SGinN,Ok(Moved::To(MovedKind::GinN,(9,1),(8,2),false))),
		(SKakuN,Ok(Moved::To(MovedKind::KakuN,(9,1),(8,2),false))),
		(SHishaN,Ok(Moved::To(MovedKind::HishaN,(9,1),(8,2),false))),
		(GFu,Ok(Moved::To(MovedKind::Fu,(9,1),(8,2),false))),
		(GKyou,Ok(Moved::To(MovedKind::Kyou,(9,1),(8,2),false))),
		(GKei,Ok(Moved::To(MovedKind::Kei,(9,1),(8,2),false))),
		(GGin,Ok(Moved::To(MovedKind::Gin,(9,1),(8,2),false))),
		(GKin,Ok(Moved::To(MovedKind::Kin,(9,1),(8,2),false))),
		(GKaku,Ok(Moved::To(MovedKind::Kaku,(9,1),(8,2),false))),
		(GHisha,Ok(Moved::To(MovedKind::Hisha,(9,1),(8,2),false))),
		(GOu,Ok(Moved::To(MovedKind::GOu,(9,1),(8,2),false))),
		(GFuN,Ok(Moved::To(MovedKind::FuN,(9,1),(8,2),false))),
		(GKyouN,Ok(Moved::To(MovedKind::KyouN,(9,1),(8,2),false))),
		(GKeiN,Ok(Moved::To(MovedKind::KeiN,(9,1),(8,2),false))),
		(GGinN,Ok(Moved::To(MovedKind::GinN,(9,1),(8,2),false))),
		(GKakuN,Ok(Moved::To(MovedKind::KakuN,(9,1),(8,2),false))),
		(GHishaN,Ok(Moved::To(MovedKind::HishaN,(9,1),(8,2),false))),
		(Blank,Ok(Moved::To(MovedKind::Blank,(9,1),(8,2),false))),
	];

	for (k,r) in input_and_expected.into_iter() {
		let mut banmen = Banmen([[Blank; 9]; 9]);
		banmen.0[0][0] = k;

		assert_eq!(Moved::try_from((&banmen,&Move::To(KomaSrcPosition(9,1),KomaDstToPosition(8,2,false)))),r);
	}

	let input_and_expected:Vec<(KomaKind,Result<Moved, TypeConvertError<String>>)> = vec![
		(SFu,Ok(Moved::To(MovedKind::Fu,(9,1),(8,2),true))),
		(SKyou,Ok(Moved::To(MovedKind::Kyou,(9,1),(8,2),true))),
		(SKei,Ok(Moved::To(MovedKind::Kei,(9,1),(8,2),true))),
		(SGin,Ok(Moved::To(MovedKind::Gin,(9,1),(8,2),true))),
		(SKin,Ok(Moved::To(MovedKind::Kin,(9,1),(8,2),true))),
		(SKaku,Ok(Moved::To(MovedKind::Kaku,(9,1),(8,2),true))),
		(SHisha,Ok(Moved::To(MovedKind::Hisha,(9,1),(8,2),true))),
		(SOu,Ok(Moved::To(MovedKind::SOu,(9,1),(8,2),true))),
		(SFuN,Ok(Moved::To(MovedKind::FuN,(9,1),(8,2),true))),
		(SKyouN,Ok(Moved::To(MovedKind::KyouN,(9,1),(8,2),true))),
		(SKeiN,Ok(Moved::To(MovedKind::KeiN,(9,1),(8,2),true))),
		(SGinN,Ok(Moved::To(MovedKind::GinN,(9,1),(8,2),true))),
		(SKakuN,Ok(Moved::To(MovedKind::KakuN,(9,1),(8,2),true))),
		(SHishaN,Ok(Moved::To(MovedKind::HishaN,(9,1),(8,2),true))),
		(GFu,Ok(Moved::To(MovedKind::Fu,(9,1),(8,2),true))),
		(GKyou,Ok(Moved::To(MovedKind::Kyou,(9,1),(8,2),true))),
		(GKei,Ok(Moved::To(MovedKind::Kei,(9,1),(8,2),true))),
		(GGin,Ok(Moved::To(MovedKind::Gin,(9,1),(8,2),true))),
		(GKin,Ok(Moved::To(MovedKind::Kin,(9,1),(8,2),true))),
		(GKaku,Ok(Moved::To(MovedKind::Kaku,(9,1),(8,2),true))),
		(GHisha,Ok(Moved::To(MovedKind::Hisha,(9,1),(8,2),true))),
		(GOu,Ok(Moved::To(MovedKind::GOu,(9,1),(8,2),true))),
		(GFuN,Ok(Moved::To(MovedKind::FuN,(9,1),(8,2),true))),
		(GKyouN,Ok(Moved::To(MovedKind::KyouN,(9,1),(8,2),true))),
		(GKeiN,Ok(Moved::To(MovedKind::KeiN,(9,1),(8,2),true))),
		(GGinN,Ok(Moved::To(MovedKind::GinN,(9,1),(8,2),true))),
		(GKakuN,Ok(Moved::To(MovedKind::KakuN,(9,1),(8,2),true))),
		(GHishaN,Ok(Moved::To(MovedKind::HishaN,(9,1),(8,2),true))),
		(Blank,Ok(Moved::To(MovedKind::Blank,(9,1),(8,2),true))),
	];

	for (k,r) in input_and_expected.into_iter() {
		let mut banmen = Banmen([[Blank; 9]; 9]);
		banmen.0[0][0] = k;

		assert_eq!(Moved::try_from((&banmen,&Move::To(KomaSrcPosition(9,1),KomaDstToPosition(8,2,true)))),r);
	}

	let input_and_expected:Vec<(MochigomaKind,Result<Moved, TypeConvertError<String>>)> = vec![
		(MochigomaKind::Fu,Ok(Moved::Put(MochigomaKind::Fu,(9,1)))),
		(MochigomaKind::Kyou,Ok(Moved::Put(MochigomaKind::Kyou,(9,1)))),
		(MochigomaKind::Kei,Ok(Moved::Put(MochigomaKind::Kei,(9,1)))),
		(MochigomaKind::Gin,Ok(Moved::Put(MochigomaKind::Gin,(9,1)))),
		(MochigomaKind::Kin,Ok(Moved::Put(MochigomaKind::Kin,(9,1)))),
		(MochigomaKind::Hisha,Ok(Moved::Put(MochigomaKind::Hisha,(9,1)))),
		(MochigomaKind::Kaku,Ok(Moved::Put(MochigomaKind::Kaku,(9,1))))
	];


	for (k,r) in input_and_expected.into_iter() {
		let banmen = Banmen([[Blank; 9]; 9]);

		assert_eq!(Moved::try_from((&banmen,&Move::Put(k,KomaDstPutPosition(9,1)))),r);
	}
}
#[test]
fn test_moved_display() {
	let input_and_expected:Vec<(Moved,&'static str)> = vec![
		(Moved::To(MovedKind::SOu,(9,0),(9,1),false),"9零王 -> 9一 (不正な手です)"),
		(Moved::To(MovedKind::Gin,(9,0),(8,1),true),"9零銀 -> 8一成 (不正な手です)"),
		(Moved::To(MovedKind::SOu,(9,1),(9,0),false),"9一王 -> 9零 (不正な手です)"),
		(Moved::To(MovedKind::Gin,(9,1),(8,0),true),"9一銀 -> 8零成 (不正な手です)"),
		(Moved::To(MovedKind::SOu,(0,1),(1,2),false),"0一王 -> 1二 (不正な手です)"),
		(Moved::To(MovedKind::Kaku,(0,1),(1,2),true),"0一角 -> 1二成 (不正な手です)"),
		(Moved::To(MovedKind::SOu,(9,10),(8,9),false),"9,10王 -> 8,9 (不正な手です)"),
		(Moved::To(MovedKind::Kaku,(9,10),(8,9),true),"9,10角 -> 8,9成 (不正な手です)"),
		(Moved::To(MovedKind::SOu,(1,9),(2,10),false),"1,9王 -> 2,10 (不正な手です)"),
		(Moved::To(MovedKind::Kaku,(1,9),(2,10),true),"1,9角 -> 2,10成 (不正な手です)"),
		(Moved::Put(MochigomaKind::Fu,(10,1)),"10一歩 (不正な手です)"),
		(Moved::Put(MochigomaKind::Kyou,(10,1)),"10一香 (不正な手です)"),
		(Moved::Put(MochigomaKind::Kei,(10,1)),"10一桂 (不正な手です)"),
		(Moved::Put(MochigomaKind::Gin,(10,1)),"10一銀 (不正な手です)"),
		(Moved::Put(MochigomaKind::Kin,(10,1)),"10一金 (不正な手です)"),
		(Moved::Put(MochigomaKind::Kaku,(10,1)),"10一角 (不正な手です)"),
		(Moved::Put(MochigomaKind::Hisha,(10,1)),"10一飛 (不正な手です)"),
		(Moved::Put(MochigomaKind::Fu,(9,0)),"9零歩 (不正な手です)"),
		(Moved::Put(MochigomaKind::Kyou,(9,0)),"9零香 (不正な手です)"),
		(Moved::Put(MochigomaKind::Kei,(9,0)),"9零桂 (不正な手です)"),
		(Moved::Put(MochigomaKind::Gin,(9,0)),"9零銀 (不正な手です)"),
		(Moved::Put(MochigomaKind::Kin,(9,0)),"9零金 (不正な手です)"),
		(Moved::Put(MochigomaKind::Kaku,(9,0)),"9零角 (不正な手です)"),
		(Moved::Put(MochigomaKind::Hisha,(9,0)),"9零飛 (不正な手です)"),
		(Moved::Put(MochigomaKind::Fu,(9,10)),"9,10歩 (不正な手です)"),
		(Moved::Put(MochigomaKind::Kyou,(9,10)),"9,10香 (不正な手です)"),
		(Moved::Put(MochigomaKind::Kei,(9,10)),"9,10桂 (不正な手です)"),
		(Moved::Put(MochigomaKind::Gin,(9,10)),"9,10銀 (不正な手です)"),
		(Moved::Put(MochigomaKind::Kin,(9,10)),"9,10金 (不正な手です)"),
		(Moved::Put(MochigomaKind::Kaku,(9,10)),"9,10角 (不正な手です)"),
		(Moved::Put(MochigomaKind::Hisha,(9,10)),"9,10飛 (不正な手です)"),

		(Moved::To(MovedKind::Fu,(9,1),(8,2),true),"9一歩 -> 8二成"),
		(Moved::To(MovedKind::Kyou,(9,1),(8,2),true),"9一香 -> 8二成"),
		(Moved::To(MovedKind::Kei,(9,1),(8,2),true),"9一桂 -> 8二成"),
		(Moved::To(MovedKind::Gin,(9,1),(8,2),true),"9一銀 -> 8二成"),
		(Moved::To(MovedKind::Kin,(9,1),(8,2),true),"9一金 -> 8二成 (不正な手です)"),
		(Moved::To(MovedKind::Kaku,(9,1),(8,2),true),"9一角 -> 8二成"),
		(Moved::To(MovedKind::Hisha,(9,1),(8,2),true),"9一飛 -> 8二成"),
		(Moved::To(MovedKind::SOu,(9,1),(8,2),true),"9一王 -> 8二成 (不正な手です)"),
		(Moved::To(MovedKind::GOu,(9,1),(8,2),true),"9一玉 -> 8二成 (不正な手です)"),
		(Moved::To(MovedKind::FuN,(9,1),(8,2),false),"9一成歩 -> 8二"),
		(Moved::To(MovedKind::FuN,(9,1),(8,2),true),"9一成歩 -> 8二成 (不正な手です)"),
		(Moved::To(MovedKind::KyouN,(9,1),(8,2),false),"9一成香 -> 8二"),
		(Moved::To(MovedKind::KyouN,(9,1),(8,2),true),"9一成香 -> 8二成 (不正な手です)"),
		(Moved::To(MovedKind::KeiN,(9,1),(8,2),false),"9一成桂 -> 8二"),
		(Moved::To(MovedKind::KeiN,(9,1),(8,2),true),"9一成桂 -> 8二成 (不正な手です)"),
		(Moved::To(MovedKind::GinN,(9,1),(8,2),false),"9一成銀 -> 8二"),
		(Moved::To(MovedKind::GinN,(9,1),(8,2),true),"9一成銀 -> 8二成 (不正な手です)"),
		(Moved::To(MovedKind::KakuN,(9,1),(8,2),false),"9一馬 -> 8二"),
		(Moved::To(MovedKind::KakuN,(9,1),(8,2),true),"9一馬 -> 8二成 (不正な手です)"),
		(Moved::To(MovedKind::HishaN,(9,1),(8,2),false),"9一龍 -> 8二"),
		(Moved::To(MovedKind::HishaN,(9,1),(8,2),true),"9一龍 -> 8二成 (不正な手です)"),
		(Moved::To(MovedKind::Fu,(9,1),(8,2),false),"9一歩 -> 8二"),
		(Moved::To(MovedKind::Kyou,(9,1),(8,2),false),"9一香 -> 8二"),
		(Moved::To(MovedKind::Kei,(9,1),(8,2),false),"9一桂 -> 8二"),
		(Moved::To(MovedKind::Gin,(9,1),(8,2),false),"9一銀 -> 8二"),
		(Moved::To(MovedKind::Kin,(9,1),(8,2),false),"9一金 -> 8二"),
		(Moved::To(MovedKind::Kaku,(9,1),(8,2),false),"9一角 -> 8二"),
		(Moved::To(MovedKind::Hisha,(9,1),(8,2),false),"9一飛 -> 8二"),
		(Moved::To(MovedKind::SOu,(9,1),(8,2),false),"9一王 -> 8二"),
		(Moved::To(MovedKind::GOu,(9,1),(8,2),false),"9一玉 -> 8二"),
		(Moved::To(MovedKind::Blank,(9,1),(8,2),false),"9一駒無し -> 8二 (不正な手です)"),
		(Moved::To(MovedKind::Blank,(9,1),(8,2),true),"9一駒無し -> 8二成 (不正な手です)"),
		(Moved::Put(MochigomaKind::Fu,(9,1)),"9一歩"),
		(Moved::Put(MochigomaKind::Kyou,(9,1)),"9一香"),
		(Moved::Put(MochigomaKind::Kei,(9,1)),"9一桂"),
		(Moved::Put(MochigomaKind::Gin,(9,1)),"9一銀"),
		(Moved::Put(MochigomaKind::Kin,(9,1)),"9一金"),
		(Moved::Put(MochigomaKind::Kaku,(9,1)),"9一角"),
		(Moved::Put(MochigomaKind::Hisha,(9,1)),"9一飛"),
	];

	for (i,r) in input_and_expected.into_iter() {
		assert_eq!(format!("{}",i).as_str(),r);
	}
}
#[test]
fn test_usi_go_time_limit_to_insant() {
	let now = Instant::now();

	let input_and_expected:Vec<((UsiGoTimeLimit,Teban),Option<Instant>)> = vec![
		((UsiGoTimeLimit::None,Teban::Sente),None),
		((UsiGoTimeLimit::None,Teban::Gote),None),
		((UsiGoTimeLimit::Infinite,Teban::Sente),None),
		((UsiGoTimeLimit::Infinite,Teban::Gote),None),
		((UsiGoTimeLimit::Limit(Some((10,100)),None),Teban::Sente),Some(now + Duration::from_millis(10 as u64))),
		((UsiGoTimeLimit::Limit(Some((10,100)),None),Teban::Gote),Some(now + Duration::from_millis(100 as u64))),
		((UsiGoTimeLimit::Limit(Some((1000,10000)),Some(UsiGoByoyomiOrInc::Byoyomi(100))),Teban::Sente),Some(now + Duration::from_millis(1100 as u64))),
		((UsiGoTimeLimit::Limit(Some((1000,10000)),Some(UsiGoByoyomiOrInc::Byoyomi(100))),Teban::Gote),Some(now + Duration::from_millis(10100 as u64))),
		((UsiGoTimeLimit::Limit(Some((1000,10000)),Some(UsiGoByoyomiOrInc::Inc(10,100))),Teban::Sente),Some(now + Duration::from_millis(1010 as u64))),
		((UsiGoTimeLimit::Limit(Some((1000,10000)),Some(UsiGoByoyomiOrInc::Inc(10,100))),Teban::Gote),Some(now + Duration::from_millis(10100 as u64))),
		((UsiGoTimeLimit::Limit(None,Some(UsiGoByoyomiOrInc::Byoyomi(100))),Teban::Sente),Some(now + Duration::from_millis(100 as u64))),
		((UsiGoTimeLimit::Limit(None,Some(UsiGoByoyomiOrInc::Byoyomi(100))),Teban::Gote),Some(now + Duration::from_millis(100 as u64))),
		((UsiGoTimeLimit::Limit(None,Some(UsiGoByoyomiOrInc::Inc(10,100))),Teban::Sente),Some(now + Duration::from_millis(10 as u64))),
		((UsiGoTimeLimit::Limit(None,Some(UsiGoByoyomiOrInc::Inc(10,100))),Teban::Gote),Some(now + Duration::from_millis(100 as u64))),
		((UsiGoTimeLimit::Limit(None,None),Teban::Sente),Some(now)),
		((UsiGoTimeLimit::Limit(None,None),Teban::Gote),Some(now)),
	];

	for ((l,t),r) in input_and_expected.into_iter() {
		assert_eq!(l.to_instant(t,now),r);
	}
}
#[test]
fn test_usi_go_mate_time_limit_to_insant() {
	let now = Instant::now();

	let input_and_expected:Vec<(UsiGoMateTimeLimit,Option<Instant>)> = vec![
		(UsiGoMateTimeLimit::None,None),
		(UsiGoMateTimeLimit::Infinite,None),
		(UsiGoMateTimeLimit::Limit(100),Some(now + Duration::from_millis(100 as u64))),
	];

	for (l,r) in input_and_expected.into_iter() {
		assert_eq!(l.to_instant(now),r);
	}
}
#[test]
fn test_usi_go_time_limit_calc_next_limit() {
	let think_start_time = Instant::now();
	let now = think_start_time + Duration::from_millis(10);

	let input_and_expected:Vec<((UsiGoTimeLimit,Teban),Option<u64>)> = vec![
		((UsiGoTimeLimit::None,Teban::Sente),None),
		((UsiGoTimeLimit::None,Teban::Gote),None),
		((UsiGoTimeLimit::Infinite,Teban::Sente),None),
		((UsiGoTimeLimit::Infinite,Teban::Gote),None),
		((UsiGoTimeLimit::Limit(Some((100,1000)),None),Teban::Sente),Some(100)),
		((UsiGoTimeLimit::Limit(Some((100,1000)),None),Teban::Gote),Some(1000)),
		((UsiGoTimeLimit::Limit(Some((1000,10000)),Some(UsiGoByoyomiOrInc::Byoyomi(100))),Teban::Sente),Some(1000)),
		((UsiGoTimeLimit::Limit(Some((1000,10000)),Some(UsiGoByoyomiOrInc::Byoyomi(100))),Teban::Gote),Some(10000)),
		((UsiGoTimeLimit::Limit(Some((1000,10000)),Some(UsiGoByoyomiOrInc::Inc(10,100))),Teban::Sente),Some(2000)),
		((UsiGoTimeLimit::Limit(Some((1000,10000)),Some(UsiGoByoyomiOrInc::Inc(10,100))),Teban::Gote),Some(20090)),
		((UsiGoTimeLimit::Limit(None,Some(UsiGoByoyomiOrInc::Byoyomi(100))),Teban::Sente),Some(0)),
		((UsiGoTimeLimit::Limit(None,Some(UsiGoByoyomiOrInc::Byoyomi(100))),Teban::Gote),Some(0)),
		((UsiGoTimeLimit::Limit(None,Some(UsiGoByoyomiOrInc::Inc(20,100))),Teban::Sente),Some(10)),
		((UsiGoTimeLimit::Limit(None,Some(UsiGoByoyomiOrInc::Inc(20,100))),Teban::Gote),Some(90)),
		((UsiGoTimeLimit::Limit(None,None),Teban::Sente),Some(0)),
		((UsiGoTimeLimit::Limit(None,None),Teban::Gote),Some(0)),
	];

	for ((l,t),r) in input_and_expected.into_iter() {
		assert_eq!(l.calc_next_limit(t,think_start_time,now),r);
	}
}