1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
#include "osl/effect/liberty8Table.h"
#include "osl/boardTable.h"
#include "osl/stl/vector.h"
#include <iostream>
#include <iomanip>
#include <algorithm>
namespace osl
{
namespace effect
{
/**
* 黒の攻め方の駒ptype から dx, dyの位置にdirectMoveがあるか?
*/
static bool hasShortMove(Ptype ptype,int dx, int dy,int dx0, int dy0){
if (dx<-8 || 8<dx || dy<-8 || 8<dy) return false;
// 1マス離れたところにも利きを持ちうるか?
const Offset32 long_offset = Offset32(dx,dy);
const EffectContent effect
=Ptype_Table.getEffect(newPtypeO(BLACK,ptype),
long_offset);
const Offset offset=Board_Table.getShortOffset(long_offset);
if (effect.hasUnblockableEffect()) {
assert(! offset.zero());
int dx1=dx+offset.dx();
int dy1=dy+offset.dy();
// shortにして良い
if (abs(dx0-dx1)>1 || abs(dy0-dy1)>1) return true;
//
if (dx1<-8 || 8<dx1 || dy1<-8 || 8<dy1) return true;
const EffectContent effect=Ptype_Table.getEffect(newPtypeO(BLACK,ptype),
Offset32(dx1,dy1));
return ! effect.hasBlockableEffect();
}
else if (effect.hasBlockableEffect())
{
assert(! offset.zero());
if (dx0==offset.dx() && dy0==offset.dy())
return true;
}
return false;
}
/**
* 黒の攻め方の駒ptype から dx, dyの位置にInDirectMoveがあるか?
* ただし,隣で伸ばした先が8近傍内に無い場合は shortMoveにする
* また,目的のちょうど対称の時もshortMoveにする
*/
static bool hasLongMove(Ptype ptype,int dx, int dy,int dx0,int dy0){
if (dx<-8 || 8<dx || dy<-8 || 8<dy) return false;
if (hasShortMove(ptype,dx,dy,dx0,dy0)) return false;
EffectContent effect=Ptype_Table.getEffect(newPtypeO(BLACK,ptype),
Offset32(dx,dy));
return effect.hasEffect();
}
/**
* 黒の攻め方の駒ptype から dx, dyの位置にいる白玉の
* 近隣 Dir(白玉に白の目から見てDirの動き到達可能なマス) に
* 利きを持つ場合は dirToMask(Dir)が0, そうでない場合は1
*/
static unsigned char shortMaskOf(Ptype ptype,int dx,int dy){
unsigned int mask=0xff;
/**
* 自分が動いて元のマスに利きをつける手は生成しない
*/
if (dx==0 && dy==0)
return mask;
for (int i=0;i<8;i++){
Direction dir=static_cast<Direction>(i);
if (hasShortMove(ptype,dx+Board_Table.getDxForBlack(dir),
dy+Board_Table.getDyForBlack(dir),
dx,dy))
mask&= ~(1<<i);
}
return mask;
}
/**
* -dx, -dyの動きが黒に取って, dir であるときに
* 1<<dirを返す
* dx, dyは 8近傍の動きのみ許す
*/
static unsigned int directionOf(int dx, int dy){
Direction dir=Board_Table.getLongDirection<BLACK>(Offset32(-dx,-dy));
assert(isLong(dir));
return 1<<(longToShort(dir));
}
/**
* 黒の攻め方の駒ptype から dx, dyの位置にいる白玉の
* 近隣 Dir(白玉に白の目から見てDirの動き到達可能なマス) に
* 利きを持つ場合は dirToMask(Dir)が0, そうでない場合は1
*/
LongEffect8 Liberty8Table::longEffectOf(Ptype ptype,int dx,int dy){
assert(Ptype_Table.hasLongMove(ptype));
LongEffect8 ret;
/**
* 自分が動いて元のマスに利きをつける手は生成しない
*/
if (dx==0 && dy==0)
return ret;
if ((ptype==PROOK || ptype==ROOK) && abs(dx)==1 && abs(dy)==1){
LongEffect8 ret1;
ret1.setOffset(Offset::ZERO());
ret1.setMask(0,directionOf(0,dy));
ret1.setMask(1,directionOf(-dx,dy));
Offset32 offset32=Offset32(dx,dy);
int index=offset32.index();
longEffect2[index]=ret1;
ret.setOffset(Offset(-dx,0));
ret.setMask(0,directionOf(dx,0));
ret.setMask(1,directionOf(dx,-dy));
return ret;
}
typedef std::pair<Offset,unsigned char> OffsetMask;
typedef std::pair<int,OffsetMask> LenOffsetMask;
typedef vector<LenOffsetMask> LenOffsetMasks;
LenOffsetMasks lenOffsetMasks;
for (size_t i=0;i<8;i++){
Direction dir=static_cast<Direction>(i);
int dx1=Board_Table.getDxForBlack(dir);
int dy1=Board_Table.getDyForBlack(dir);
int dx2=dx+dx1;
int dy2=dy+dy1;
if (hasLongMove(ptype,dx2,dy2,dx,dy)){
// マンハッタン距離
int len=abs(dx2)+abs(dy2);
Offset offset=Offset(dx1,dy1);
unsigned char mask=(1<<i);
lenOffsetMasks.push_back(LenOffsetMask(len,OffsetMask(offset,mask)));
}
}
if (lenOffsetMasks.size()>0){
std::sort(lenOffsetMasks.begin(),lenOffsetMasks.end());
ret.setOffset(lenOffsetMasks[0].second.first);
for (size_t i=0;i<lenOffsetMasks.size();i++){
ret.setMask(i,lenOffsetMasks[i].second.second);
}
}
return ret;
}
Liberty8Table::Liberty8Table(){
{
#ifndef NDEBUG
const Offset32 long_offset = Offset32(-1,8);
EffectContent const_effect=Ptype_Table.getEffect(newPtypeO(BLACK,ROOK),long_offset);
assert(! const_effect.hasEffect());
#endif
assert(Ptype_Table.getEffect(newPtypeO(BLACK,PPAWN),
Offset32(Square(7,1), Square(8,1)))
== EffectContent::DIRECT());
}
for (int i=PTYPE_MAX;i>=PTYPE_PIECE_MIN;i--){
Ptype ptype=static_cast<Ptype>(i);
/**
* まずはクリア()
*/
shortMask[i].fill();
for (int dx= -8;dx<=8;dx++){
for (int dy= -8;dy<=8;dy++){
Offset32 offset32=Offset32(dx,dy);
int index=offset32.index();
shortMask[i][index]=shortMaskOf(ptype,dx,dy);
if (Ptype_Table.hasLongMove(ptype)){
longEffect[i][index]=longEffectOf(ptype,dx,dy);
}
}
}
}
}
#ifndef MINIMAL
std::ostream& operator<<(std::ostream& os,LongEffect8 const& longEffect){
os << "LongEffect(" << longEffect.getOffset() << ",[";
for (int i=0;i<3;i++){
if (longEffect.getMask(i)==0)break;
os << std::setbase(16) << "0x" << longEffect.getMask(i) << std::setbase(10) << ",";
}
return os << "])";
}
#endif
} // namespace effect
} // namespace osl
// ;;; Local Variables:
// ;;; mode:c++
// ;;; c-basic-offset:2
// ;;; End:
|