sakurapyon’s blog

sakurapyon’s blog

駒打ちルーチン

たぶん、指し手がそこそこ速いのは姑息な展開が利いているのだと思います。こんな感じ。
桂香歩打ちはあまりいじってないです。

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で持ってればもうちょっと速くなるんだけど、改造箇所が増えまくるからなあ。