File: liberty8Table.cc

package info (click to toggle)
libosl 0.6.0-3.1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 148,792 kB
  • ctags: 151,985
  • sloc: cpp: 131,133; ansic: 7,228; ruby: 1,290; makefile: 569; perl: 309; sh: 35
file content (186 lines) | stat: -rw-r--r-- 6,185 bytes parent folder | download | duplicates (2)
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: