駒打ちルーチン
たぶん、指し手がそこそこ速いのは姑息な展開が利いているのだと思います。こんな感じ。
桂香歩打ちはあまりいじってないです。
class Te { public: uint64 T; inline bool IsNull() { return (T&0x0ffff)==0; } inline Te() {}; inline Te(unsigned char f,unsigned char t,KomaInf k,KomaInf c,int p=0,int K=0 ,short v=0) : T ((uint64)t | (f<<8) | (k<<16) | (c<<24) | ((p==0)?0:(1ULL<<31)) | ((uint64)v)<<32) { (void)K; } (中略) // 駒打ち特化ルーチン // template <int hands,int player>inline void hGenDropHands(int &teNum, Te *teBuf, int n, unsigned char *empty) { for(int pos=0;pos<n;pos++) { if(hands&(1<<3)) teBuf[teNum++]=Te(0,empty[pos],player|GI,0,0); if(hands&(1<<4)) teBuf[teNum++]=Te(0,empty[pos],player|KI,0,0); if(hands&(1<<5)) teBuf[teNum++]=Te(0,empty[pos],player|KA,0,0); if(hands&(1<<6)) teBuf[teNum++]=Te(0,empty[pos],player|HI,0,0); } } // // 打つ手を生成する // template <int player>inline void hGenDrop(Kyokumen &k,int &teNum, Te *teBuf, int n, unsigned char *empty) { const int hands=(player==SELF)? ((k.Hand[SGI]>0?(1<<3):0) |(k.Hand[SKI]>0?(1<<4):0) |(k.Hand[SKA]>0?(1<<5):0) |(k.Hand[SHI]>0?(1<<6):0)): ((k.Hand[EGI]>0?(1<<3):0) |(k.Hand[EKI]>0?(1<<4):0) |(k.Hand[EKA]>0?(1<<5):0) |(k.Hand[EHI]>0?(1<<6):0)); switch (hands){ case 0x00: break; case 0x08: return hGenDropHands<0x08,player>(teNum,teBuf,n,empty); case 0x10: return hGenDropHands<0x10,player>(teNum,teBuf,n,empty); case 0x18: return hGenDropHands<0x18,player>(teNum,teBuf,n,empty); case 0x20: return hGenDropHands<0x20,player>(teNum,teBuf,n,empty); case 0x28: return hGenDropHands<0x28,player>(teNum,teBuf,n,empty); case 0x30: return hGenDropHands<0x30,player>(teNum,teBuf,n,empty); case 0x38: return hGenDropHands<0x38,player>(teNum,teBuf,n,empty); case 0x40: return hGenDropHands<0x40,player>(teNum,teBuf,n,empty); case 0x48: return hGenDropHands<0x48,player>(teNum,teBuf,n,empty); case 0x50: return hGenDropHands<0x50,player>(teNum,teBuf,n,empty); case 0x58: return hGenDropHands<0x58,player>(teNum,teBuf,n,empty); case 0x60: return hGenDropHands<0x60,player>(teNum,teBuf,n,empty); case 0x68: return hGenDropHands<0x68,player>(teNum,teBuf,n,empty); case 0x70: return hGenDropHands<0x70,player>(teNum,teBuf,n,empty); case 0x78: return hGenDropHands<0x78,player>(teNum,teBuf,n,empty); } // 有効そうな手を生成する // pinには必ず有効なpin情報がある前提 template <int SorE>int Kyokumen::hMakeEffectiveMoves(Te *teBuf,char *pin) { int teNum=0; int suji,dan; int nEmpty=0; unsigned char Empty[83]; Empty[nEmpty++]=0; // 盤上の駒を動かす for(dan=1;dan<=9;dan++) { for(suji=0x10;suji<=0x90;suji+=0x10) { if (ban[suji+dan]==EMPTY) { Empty[nEmpty++]=suji+dan; }else if (ban[suji+dan]&SorE) { AddMovesPromote(SorE,teNum,teBuf,ban[suji+dan],suji+dan,pin[suji+dan]); } } } Empty[nEmpty]=0x9a; if(SorE==SELF){ hGenDrop<SELF>(*this,teNum,teBuf,nEmpty-1,&Empty[1]); }else{ hGenDrop<ENEMY>(*this,teNum,teBuf,nEmpty-1,&Empty[1]); } (以下略) }
今気がついた。voidな関数の戻り値をreturnで返してやがる(>_<)。直そう…
持ち駒をbitで持ってればもうちょっと速くなるんだけど、改造箇所が増えまくるからなあ。