Rev 1805 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1805 | Rev 5123 | ||
---|---|---|---|
1 | #ifndef _HEADER_BOARD_H |
1 | #ifndef _HEADER_BOARD_H |
2 | #define _HEADER_BOARD_H |
2 | #define _HEADER_BOARD_H |
3 | - | ||
4 | #ifndef __MENUET__ |
3 | |
5 | #include |
4 | #include |
6 | #include |
5 | #include |
7 | #include |
6 | #include |
8 | #include |
7 | #include |
9 | #include |
8 | #include |
10 | #include |
9 | #include |
11 | #endif |
- | |
12 | #include "position.h" |
10 | #include "position.h" |
13 | #include "history.h" |
11 | #include "history.h" |
14 | #include "gr-draw.h" |
12 | #include "gr-draw.h" |
15 | 13 | ||
16 | int ssf = 0; |
14 | int ssf = 0; |
17 | 15 | ||
18 | struct TIntPoint |
16 | struct TIntPoint |
19 | { |
17 | { |
20 | TIntPoint() {} |
18 | TIntPoint() {} |
21 | TIntPoint(int x, int y) : x(x), y(y) {} |
19 | TIntPoint(int x, int y) : x(x), y(y) {} |
22 | TIntPoint(const TIntPoint &p) : x(p.x), y(p.y) {} |
20 | TIntPoint(const TIntPoint &p) : x(p.x), y(p.y) {} |
23 | 21 | ||
24 | TIntPoint &operator=(const TIntPoint &p) {x = p.x; y = p.y; return *this;} |
22 | TIntPoint &operator=(const TIntPoint &p) {x = p.x; y = p.y; return *this;} |
25 | 23 | ||
26 | int x, y; |
24 | int x, y; |
27 | }; |
25 | }; |
28 | 26 | ||
29 | struct TRealPoint |
27 | struct TRealPoint |
30 | { |
28 | { |
31 | TRealPoint() {} |
29 | TRealPoint() {} |
32 | TRealPoint(double x, double y) : x(x), y(y) {} |
30 | TRealPoint(double x, double y) : x(x), y(y) {} |
33 | TRealPoint(const TRealPoint &p) : x(p.x), y(p.y) {} |
31 | TRealPoint(const TRealPoint &p) : x(p.x), y(p.y) {} |
34 | TRealPoint(const TIntPoint &p) : x(p.x), y(p.y) {} |
32 | TRealPoint(const TIntPoint &p) : x(p.x), y(p.y) {} |
35 | 33 | ||
36 | TRealPoint &operator=(const TRealPoint &p) {x = p.x; y = p.y; return *this;} |
34 | TRealPoint &operator=(const TRealPoint &p) {x = p.x; y = p.y; return *this;} |
37 | TRealPoint &operator=(const TIntPoint &p) {x = p.x; y = p.y; return *this;} |
35 | TRealPoint &operator=(const TIntPoint &p) {x = p.x; y = p.y; return *this;} |
38 | 36 | ||
39 | TIntPoint Round() {return TIntPoint((int)floor(x+0.5), (int)floor(y+0.5));} |
37 | TIntPoint Round() {return TIntPoint((int)floor(x+0.5), (int)floor(y+0.5));} |
40 | 38 | ||
41 | double x, y; |
39 | double x, y; |
42 | }; |
40 | }; |
43 | 41 | ||
44 | struct TProjectivePoint |
42 | struct TProjectivePoint |
45 | { |
43 | { |
46 | TProjectivePoint() {} |
44 | TProjectivePoint() {} |
47 | TProjectivePoint(const TProjectivePoint &p) : x(p.x), y(p.y), z(p.z) {} |
45 | TProjectivePoint(const TProjectivePoint &p) : x(p.x), y(p.y), z(p.z) {} |
48 | TProjectivePoint(double x, double y, double z = 1) : x(x), y(y), z(z) {} |
46 | TProjectivePoint(double x, double y, double z = 1) : x(x), y(y), z(z) {} |
49 | TProjectivePoint(const TIntPoint &p, double z = 1) : x(p.x), y(p.y), z(z) {} |
47 | TProjectivePoint(const TIntPoint &p, double z = 1) : x(p.x), y(p.y), z(z) {} |
50 | TProjectivePoint(const TRealPoint &p, double z = 1) : x(p.x), y(p.y), z(z) {} |
48 | TProjectivePoint(const TRealPoint &p, double z = 1) : x(p.x), y(p.y), z(z) {} |
51 | 49 | ||
52 | int IsCorrect() const {return fabs(x) > Eps || fabs(y) > Eps || fabs(z) > Eps;} |
50 | int IsCorrect() const {return fabs(x) > Eps || fabs(y) > Eps || fabs(z) > Eps;} |
53 | int IsFinite() const; |
51 | int IsFinite() const; |
54 | TRealPoint rpnt() const; |
52 | TRealPoint rpnt() const; |
55 | int rpnt(TRealPoint &p) const; |
53 | int rpnt(TRealPoint &p) const; |
56 | TIntPoint pnt() const; |
54 | TIntPoint pnt() const; |
57 | int pnt(TIntPoint &p) const; |
55 | int pnt(TIntPoint &p) const; |
58 | 56 | ||
59 | TProjectivePoint &operator=(const TProjectivePoint &p); |
57 | TProjectivePoint &operator=(const TProjectivePoint &p); |
60 | TProjectivePoint &operator=(const TIntPoint &p) {x = p.x; y = p.y; z = 1; return *this;} |
58 | TProjectivePoint &operator=(const TIntPoint &p) {x = p.x; y = p.y; z = 1; return *this;} |
61 | TProjectivePoint &operator=(const TRealPoint &p) {x = p.x; y = p.y; z = 1; return *this;} |
59 | TProjectivePoint &operator=(const TRealPoint &p) {x = p.x; y = p.y; z = 1; return *this;} |
62 | TProjectivePoint &operator*=(int n) {x *= n; y *= n; z *= n; return *this;} |
60 | TProjectivePoint &operator*=(int n) {x *= n; y *= n; z *= n; return *this;} |
63 | friend TProjectivePoint operator*(const TProjectivePoint &p, int n) |
61 | friend TProjectivePoint operator*(const TProjectivePoint &p, int n) |
64 | {return TProjectivePoint(p.x * n, p.y * n, p.z * n);} |
62 | {return TProjectivePoint(p.x * n, p.y * n, p.z * n);} |
65 | friend TProjectivePoint operator*(int n, const TProjectivePoint &p) |
63 | friend TProjectivePoint operator*(int n, const TProjectivePoint &p) |
66 | {return TProjectivePoint(n * p.x, n * p.y, n * p.z);} |
64 | {return TProjectivePoint(n * p.x, n * p.y, n * p.z);} |
67 | TProjectivePoint &operator*=(double n) {x *= n; y *= n; z *= n; return *this;} |
65 | TProjectivePoint &operator*=(double n) {x *= n; y *= n; z *= n; return *this;} |
68 | friend TProjectivePoint operator*(const TProjectivePoint &p, double n) |
66 | friend TProjectivePoint operator*(const TProjectivePoint &p, double n) |
69 | {return TProjectivePoint(p.x * n, p.y * n, p.z * n);} |
67 | {return TProjectivePoint(p.x * n, p.y * n, p.z * n);} |
70 | friend TProjectivePoint operator*(double n, const TProjectivePoint &p) |
68 | friend TProjectivePoint operator*(double n, const TProjectivePoint &p) |
71 | {return TProjectivePoint(n * p.x, n * p.y, n * p.z);} |
69 | {return TProjectivePoint(n * p.x, n * p.y, n * p.z);} |
72 | 70 | ||
73 | double px() const {return x/z;} |
71 | double px() const {return x/z;} |
74 | double py() const {return y/z;} |
72 | double py() const {return y/z;} |
75 | 73 | ||
76 | double x, y, z; |
74 | double x, y, z; |
77 | 75 | ||
78 | static const double Eps, FR; |
76 | static const double Eps, FR; |
79 | }; |
77 | }; |
80 | 78 | ||
81 | const double TProjectivePoint::Eps = 1e-12; |
79 | const double TProjectivePoint::Eps = 1e-12; |
82 | const double TProjectivePoint::FR = 1e+4; |
80 | const double TProjectivePoint::FR = 1e+4; |
83 | 81 | ||
84 | inline int TProjectivePoint::IsFinite() const |
82 | inline int TProjectivePoint::IsFinite() const |
85 | { |
83 | { |
86 | double fz = fabs(z); |
84 | double fz = fabs(z); |
87 | return fz > Eps && fabs(x) < fz * FR && fabs(y) < fz * FR; |
85 | return fz > Eps && fabs(x) < fz * FR && fabs(y) < fz * FR; |
88 | } |
86 | } |
89 | 87 | ||
90 | TRealPoint TProjectivePoint::rpnt() const |
88 | TRealPoint TProjectivePoint::rpnt() const |
91 | { |
89 | { |
92 | if (!IsFinite()) return TRealPoint(0, 0); |
90 | if (!IsFinite()) return TRealPoint(0, 0); |
93 | else return TRealPoint(x/z, y/z); |
91 | else return TRealPoint(x/z, y/z); |
94 | } |
92 | } |
95 | 93 | ||
96 | inline int TProjectivePoint::rpnt(TRealPoint &p) const |
94 | inline int TProjectivePoint::rpnt(TRealPoint &p) const |
97 | { |
95 | { |
98 | if (!IsFinite()) {p.x = 0; p.y = 0; return 0;} |
96 | if (!IsFinite()) {p.x = 0; p.y = 0; return 0;} |
99 | else {p.x = x/z; p.y = y/z; return 1;} |
97 | else {p.x = x/z; p.y = y/z; return 1;} |
100 | } |
98 | } |
101 | 99 | ||
102 | inline TIntPoint TProjectivePoint::pnt() const |
100 | inline TIntPoint TProjectivePoint::pnt() const |
103 | { |
101 | { |
104 | if (!IsFinite()) return TIntPoint(INT_MIN, INT_MIN); |
102 | if (!IsFinite()) return TIntPoint(INT_MIN, INT_MIN); |
105 | else return TIntPoint((int)floor(x/z + 0.5), (int)floor(y/z + 0.5)); |
103 | else return TIntPoint((int)floor(x/z + 0.5), (int)floor(y/z + 0.5)); |
106 | } |
104 | } |
107 | 105 | ||
108 | inline int TProjectivePoint::pnt(TIntPoint &p) const |
106 | inline int TProjectivePoint::pnt(TIntPoint &p) const |
109 | { |
107 | { |
110 | if (!IsFinite()) {p.x = INT_MIN; p.y = INT_MIN; return 0;} |
108 | if (!IsFinite()) {p.x = INT_MIN; p.y = INT_MIN; return 0;} |
111 | else |
109 | else |
112 | { |
110 | { |
113 | p.x = (int)floor(x/z + 0.5); |
111 | p.x = (int)floor(x/z + 0.5); |
114 | p.y = (int)floor(y/z + 0.5); |
112 | p.y = (int)floor(y/z + 0.5); |
115 | return 1; |
113 | return 1; |
116 | } |
114 | } |
117 | } |
115 | } |
118 | 116 | ||
119 | TProjectivePoint &TProjectivePoint::operator=(const TProjectivePoint &p) |
117 | TProjectivePoint &TProjectivePoint::operator=(const TProjectivePoint &p) |
120 | { |
118 | { |
121 | x = p.x; y = p.y; z = p.z; |
119 | x = p.x; y = p.y; z = p.z; |
122 | return *this; |
120 | return *this; |
123 | } |
121 | } |
124 | 122 | ||
125 | 123 | ||
126 | class TProjectiveMap |
124 | class TProjectiveMap |
127 | { |
125 | { |
128 | public: |
126 | public: |
129 | TProjectiveMap() {} |
127 | TProjectiveMap() {} |
130 | TProjectiveMap(int n) {p[0].x = p[1].y = p[2].z = n; |
128 | TProjectiveMap(int n) {p[0].x = p[1].y = p[2].z = n; |
131 | p[0].y = p[0].z = p[1].x = p[1].z = p[2].x = p[2].y = 0;} |
129 | p[0].y = p[0].z = p[1].x = p[1].z = p[2].x = p[2].y = 0;} |
132 | TProjectiveMap(const TProjectiveMap &map) |
130 | TProjectiveMap(const TProjectiveMap &map) |
133 | {p[0] = map.p[0]; p[1] = map.p[1]; p[2] = map.p[2];} |
131 | {p[0] = map.p[0]; p[1] = map.p[1]; p[2] = map.p[2];} |
134 | TProjectiveMap(const TProjectivePoint pnt[]) |
132 | TProjectiveMap(const TProjectivePoint pnt[]) |
135 | {p[0] = pnt[0]; p[1] = pnt[1]; p[2] = pnt[2];} |
133 | {p[0] = pnt[0]; p[1] = pnt[1]; p[2] = pnt[2];} |
136 | TProjectiveMap(const TProjectivePoint &p0, const TProjectivePoint &p1, |
134 | TProjectiveMap(const TProjectivePoint &p0, const TProjectivePoint &p1, |
137 | const TProjectivePoint &p2) {p[0] = p0; p[1] = p1; p[2] = p2;} |
135 | const TProjectivePoint &p2) {p[0] = p0; p[1] = p1; p[2] = p2;} |
138 | 136 | ||
139 | TProjectiveMap &operator=(const TProjectiveMap &map) |
137 | TProjectiveMap &operator=(const TProjectiveMap &map) |
140 | {p[0] = map.p[0]; p[1] = map.p[1]; p[2] = map.p[2]; return *this;} |
138 | {p[0] = map.p[0]; p[1] = map.p[1]; p[2] = map.p[2]; return *this;} |
141 | TProjectiveMap &operator=(const TProjectivePoint pnt[]) |
139 | TProjectiveMap &operator=(const TProjectivePoint pnt[]) |
142 | {p[0] = pnt[0]; p[1] = pnt[1]; p[2] = pnt[2]; return *this;} |
140 | {p[0] = pnt[0]; p[1] = pnt[1]; p[2] = pnt[2]; return *this;} |
143 | TProjectiveMap &operator=(int n) {p[0].x = p[1].y = p[2].z = n; |
141 | TProjectiveMap &operator=(int n) {p[0].x = p[1].y = p[2].z = n; |
144 | p[0].y = p[0].z = p[1].x = p[1].z = p[2].x = p[2].y = 0; return *this;} |
142 | p[0].y = p[0].z = p[1].x = p[1].z = p[2].x = p[2].y = 0; return *this;} |
145 | 143 | ||
146 | TProjectivePoint operator()(const TProjectivePoint &point) const; |
144 | TProjectivePoint operator()(const TProjectivePoint &point) const; |
147 | friend TProjectiveMap operator*(const TProjectiveMap &a, const TProjectiveMap &b); |
145 | friend TProjectiveMap operator*(const TProjectiveMap &a, const TProjectiveMap &b); |
148 | TProjectiveMap &operator*=(const TProjectiveMap &b); |
146 | TProjectiveMap &operator*=(const TProjectiveMap &b); |
149 | TProjectiveMap &operator*=(int n) {p[0] *= n; p[1] *= n; p[2] *= n; return *this;} |
147 | TProjectiveMap &operator*=(int n) {p[0] *= n; p[1] *= n; p[2] *= n; return *this;} |
150 | friend TProjectiveMap operator*(const TProjectiveMap &a, int n) |
148 | friend TProjectiveMap operator*(const TProjectiveMap &a, int n) |
151 | {return TProjectiveMap(a.p[0] * n, a.p[1] * n, a.p[2] * n);} |
149 | {return TProjectiveMap(a.p[0] * n, a.p[1] * n, a.p[2] * n);} |
152 | friend TProjectiveMap operator*(int n, const TProjectiveMap &b) |
150 | friend TProjectiveMap operator*(int n, const TProjectiveMap &b) |
153 | {return TProjectiveMap(n * b.p[0], n * b.p[1], n * b.p[2]);} |
151 | {return TProjectiveMap(n * b.p[0], n * b.p[1], n * b.p[2]);} |
154 | TProjectiveMap Reversed() const; |
152 | TProjectiveMap Reversed() const; |
155 | TProjectiveMap &Reverse() {return (*this) = Reversed();} |
153 | TProjectiveMap &Reverse() {return (*this) = Reversed();} |
156 | friend TProjectiveMap operator/(const TProjectiveMap &a, const TProjectiveMap &b) |
154 | friend TProjectiveMap operator/(const TProjectiveMap &a, const TProjectiveMap &b) |
157 | {return a * b.Reversed();} |
155 | {return a * b.Reversed();} |
158 | TProjectiveMap &operator/=(const TProjectiveMap &b) {return (*this) *= b.Reversed();} |
156 | TProjectiveMap &operator/=(const TProjectiveMap &b) {return (*this) *= b.Reversed();} |
159 | TProjectiveMap &operator/=(int n) {if (!n) (*this) = 0; return *this;} |
157 | TProjectiveMap &operator/=(int n) {if (!n) (*this) = 0; return *this;} |
160 | TProjectivePoint Reversed(const TProjectivePoint &point) const; |
158 | TProjectivePoint Reversed(const TProjectivePoint &point) const; |
161 | 159 | ||
162 | TProjectivePoint operator()(double x, double y, double z = 1) const |
160 | TProjectivePoint operator()(double x, double y, double z = 1) const |
163 | {return (*this)(TProjectivePoint(x, y, z));} |
161 | {return (*this)(TProjectivePoint(x, y, z));} |
164 | TProjectivePoint Reversed(double x, double y, double z = 1) const |
162 | TProjectivePoint Reversed(double x, double y, double z = 1) const |
165 | {return Reversed(TProjectivePoint(x, y, z));} |
163 | {return Reversed(TProjectivePoint(x, y, z));} |
166 | 164 | ||
167 | TProjectiveMap &Set4(const TProjectivePoint &a0, const TProjectivePoint &a1, |
165 | TProjectiveMap &Set4(const TProjectivePoint &a0, const TProjectivePoint &a1, |
168 | const TProjectivePoint &a2, const TProjectivePoint &a3); |
166 | const TProjectivePoint &a2, const TProjectivePoint &a3); |
169 | TProjectiveMap &Set4(const TProjectivePoint a[]) {return Set4(a[0], a[1], a[2], a[3]);} |
167 | TProjectiveMap &Set4(const TProjectivePoint a[]) {return Set4(a[0], a[1], a[2], a[3]);} |
170 | TProjectiveMap &Set4to4(const TProjectivePoint a[], const TProjectivePoint b[]) |
168 | TProjectiveMap &Set4to4(const TProjectivePoint a[], const TProjectivePoint b[]) |
171 | {return Set4(b) /= TProjectiveMap().Set4(a);} |
169 | {return Set4(b) /= TProjectiveMap().Set4(a);} |
172 | TProjectiveMap &Set4to4(const TProjectivePoint &a0, const TProjectivePoint &a1, |
170 | TProjectiveMap &Set4to4(const TProjectivePoint &a0, const TProjectivePoint &a1, |
173 | const TProjectivePoint &a2, const TProjectivePoint &a3, |
171 | const TProjectivePoint &a2, const TProjectivePoint &a3, |
174 | const TProjectivePoint b[]) |
172 | const TProjectivePoint b[]) |
175 | {return Set4(b) /= TProjectiveMap().Set4(a0, a1, a2, a3);} |
173 | {return Set4(b) /= TProjectiveMap().Set4(a0, a1, a2, a3);} |
176 | TProjectiveMap &Set4to4(const TProjectivePoint a[], |
174 | TProjectiveMap &Set4to4(const TProjectivePoint a[], |
177 | const TProjectivePoint &b0, const TProjectivePoint &b1, |
175 | const TProjectivePoint &b0, const TProjectivePoint &b1, |
178 | const TProjectivePoint &b2, const TProjectivePoint &b3) |
176 | const TProjectivePoint &b2, const TProjectivePoint &b3) |
179 | {return Set4(b0, b1, b2, b2) /= TProjectiveMap().Set4(a);} |
177 | {return Set4(b0, b1, b2, b2) /= TProjectiveMap().Set4(a);} |
180 | TProjectiveMap &Set4to4(const TProjectivePoint &a0, const TProjectivePoint &a1, |
178 | TProjectiveMap &Set4to4(const TProjectivePoint &a0, const TProjectivePoint &a1, |
181 | const TProjectivePoint &a2, const TProjectivePoint &a3, |
179 | const TProjectivePoint &a2, const TProjectivePoint &a3, |
182 | const TProjectivePoint &b0, const TProjectivePoint &b1, |
180 | const TProjectivePoint &b0, const TProjectivePoint &b1, |
183 | const TProjectivePoint &b2, const TProjectivePoint &b3) |
181 | const TProjectivePoint &b2, const TProjectivePoint &b3) |
184 | {return Set4(b0, b1, b2, b2) /= TProjectiveMap().Set4(a0, a1, a2, a3);} |
182 | {return Set4(b0, b1, b2, b2) /= TProjectiveMap().Set4(a0, a1, a2, a3);} |
185 | 183 | ||
186 | public: |
184 | public: |
187 | TProjectivePoint p[3]; |
185 | TProjectivePoint p[3]; |
188 | }; |
186 | }; |
189 | 187 | ||
190 | TProjectivePoint TProjectiveMap::operator()(const TProjectivePoint &point) const |
188 | TProjectivePoint TProjectiveMap::operator()(const TProjectivePoint &point) const |
191 | { |
189 | { |
192 | return TProjectivePoint(p[0].x * point.x + p[1].x * point.y + p[2].x * point.z, |
190 | return TProjectivePoint(p[0].x * point.x + p[1].x * point.y + p[2].x * point.z, |
193 | p[0].y * point.x + p[1].y * point.y + p[2].y * point.z, |
191 | p[0].y * point.x + p[1].y * point.y + p[2].y * point.z, |
194 | p[0].z * point.x + p[1].z * point.y + p[2].z * point.z); |
192 | p[0].z * point.x + p[1].z * point.y + p[2].z * point.z); |
195 | } |
193 | } |
196 | 194 | ||
197 | TProjectiveMap operator*(const TProjectiveMap &a, const TProjectiveMap &b) |
195 | TProjectiveMap operator*(const TProjectiveMap &a, const TProjectiveMap &b) |
198 | { |
196 | { |
199 | return TProjectiveMap(a(b.p[0]), a(b.p[1]), a(b.p[2])); |
197 | return TProjectiveMap(a(b.p[0]), a(b.p[1]), a(b.p[2])); |
200 | } |
198 | } |
201 | 199 | ||
202 | TProjectiveMap &TProjectiveMap::operator*=(const TProjectiveMap &b) |
200 | TProjectiveMap &TProjectiveMap::operator*=(const TProjectiveMap &b) |
203 | { |
201 | { |
204 | TProjectivePoint p0 = (*this)(b.p[0]), p1 = (*this)(b.p[1]), p2 = (*this)(b.p[2]); |
202 | TProjectivePoint p0 = (*this)(b.p[0]), p1 = (*this)(b.p[1]), p2 = (*this)(b.p[2]); |
205 | p[0] = p0; p[1] = p1; p[2] = p2; |
203 | p[0] = p0; p[1] = p1; p[2] = p2; |
206 | return *this; |
204 | return *this; |
207 | } |
205 | } |
208 | 206 | ||
209 | TProjectiveMap TProjectiveMap::Reversed() const |
207 | TProjectiveMap TProjectiveMap::Reversed() const |
210 | { |
208 | { |
211 | return TProjectiveMap(TProjectivePoint(p[1].y * p[2].z - p[2].y * p[1].z, |
209 | return TProjectiveMap(TProjectivePoint(p[1].y * p[2].z - p[2].y * p[1].z, |
212 | p[2].y * p[0].z - p[0].y * p[2].z, p[0].y * p[1].z - p[1].y * p[0].z), |
210 | p[2].y * p[0].z - p[0].y * p[2].z, p[0].y * p[1].z - p[1].y * p[0].z), |
213 | TProjectivePoint(p[1].z * p[2].x - p[2].z * p[1].x, |
211 | TProjectivePoint(p[1].z * p[2].x - p[2].z * p[1].x, |
214 | p[2].z * p[0].x - p[0].z * p[2].x, p[0].z * p[1].x - p[1].z * p[0].x), |
212 | p[2].z * p[0].x - p[0].z * p[2].x, p[0].z * p[1].x - p[1].z * p[0].x), |
215 | TProjectivePoint(p[1].x * p[2].y - p[2].x * p[1].y, |
213 | TProjectivePoint(p[1].x * p[2].y - p[2].x * p[1].y, |
216 | p[2].x * p[0].y - p[0].x * p[2].y, p[0].x * p[1].y - p[1].x * p[0].y)); |
214 | p[2].x * p[0].y - p[0].x * p[2].y, p[0].x * p[1].y - p[1].x * p[0].y)); |
217 | } |
215 | } |
218 | 216 | ||
219 | TProjectivePoint TProjectiveMap::Reversed(const TProjectivePoint &point) const |
217 | TProjectivePoint TProjectiveMap::Reversed(const TProjectivePoint &point) const |
220 | { |
218 | { |
221 | return TProjectivePoint((p[1].y * p[2].z - p[2].y * p[1].z) * point.x + |
219 | return TProjectivePoint((p[1].y * p[2].z - p[2].y * p[1].z) * point.x + |
222 | (p[1].z * p[2].x - p[2].z * p[1].x) * point.y + |
220 | (p[1].z * p[2].x - p[2].z * p[1].x) * point.y + |
223 | (p[1].x * p[2].y - p[2].x * p[1].y) * point.z, |
221 | (p[1].x * p[2].y - p[2].x * p[1].y) * point.z, |
224 | (p[2].y * p[0].z - p[0].y * p[2].z) * point.x + |
222 | (p[2].y * p[0].z - p[0].y * p[2].z) * point.x + |
225 | (p[2].z * p[0].x - p[0].z * p[2].x) * point.y + |
223 | (p[2].z * p[0].x - p[0].z * p[2].x) * point.y + |
226 | (p[2].x * p[0].y - p[0].x * p[2].y) * point.z, |
224 | (p[2].x * p[0].y - p[0].x * p[2].y) * point.z, |
227 | (p[0].y * p[1].z - p[1].y * p[0].z) * point.x + |
225 | (p[0].y * p[1].z - p[1].y * p[0].z) * point.x + |
228 | (p[0].z * p[1].x - p[1].z * p[0].x) * point.y + |
226 | (p[0].z * p[1].x - p[1].z * p[0].x) * point.y + |
229 | (p[0].x * p[1].y - p[1].x * p[0].y) * point.z); |
227 | (p[0].x * p[1].y - p[1].x * p[0].y) * point.z); |
230 | } |
228 | } |
231 | 229 | ||
232 | TProjectiveMap &TProjectiveMap::Set4(const TProjectivePoint &a0, |
230 | TProjectiveMap &TProjectiveMap::Set4(const TProjectivePoint &a0, |
233 | const TProjectivePoint &a1, const TProjectivePoint &a2, const TProjectivePoint &a3) |
231 | const TProjectivePoint &a1, const TProjectivePoint &a2, const TProjectivePoint &a3) |
234 | { |
232 | { |
235 | p[0] = a0; p[1] = a1; p[2] = a2; |
233 | p[0] = a0; p[1] = a1; p[2] = a2; |
236 | TProjectivePoint K = Reversed(a3); |
234 | TProjectivePoint K = Reversed(a3); |
237 | p[0] *= K.x; p[1] *= K.y; p[2] *= K.z; |
235 | p[0] *= K.x; p[1] *= K.y; p[2] *= K.z; |
238 | return *this; |
236 | return *this; |
239 | } |
237 | } |
240 | 238 | ||
241 | 239 | ||
242 | TRealPoint r_circle_pnt[13]; |
240 | TRealPoint r_circle_pnt[13]; |
243 | TRealPoint r_star_pnt[13]; |
241 | TRealPoint r_star_pnt[13]; |
244 | const double r_star_large = 1.2, r_star_small = 0.8; |
242 | const double r_star_large = 1.2, r_star_small = 0.8; |
245 | const double r_ch_lines[] = {0.8, 0.7, 0.6, 0.5}; |
243 | const double r_ch_lines[] = {0.8, 0.7, 0.6, 0.5}; |
246 | 244 | ||
247 | void InitBoardData() |
245 | void InitBoardData() |
248 | { |
246 | { |
249 | int i, len; |
247 | int i, len; |
250 | double a, r; |
248 | double a, r; |
251 | len = NELEM(r_circle_pnt) - 1; |
249 | len = NELEM(r_circle_pnt) - 1; |
252 | for (i = 0; i < len; i++) |
250 | for (i = 0; i < len; i++) |
253 | { |
251 | { |
254 | a = 2 * i * M_PI / len; |
252 | a = 2 * i * M_PI / len; |
255 | r_circle_pnt[i].x = cos(a); |
253 | r_circle_pnt[i].x = cos(a); |
256 | r_circle_pnt[i].y = sin(a); |
254 | r_circle_pnt[i].y = sin(a); |
257 | } |
255 | } |
258 | r_circle_pnt[len] = r_circle_pnt[0]; |
256 | r_circle_pnt[len] = r_circle_pnt[0]; |
259 | len = sizeof(r_star_pnt) / sizeof(r_star_pnt[0]) - 1; |
257 | len = sizeof(r_star_pnt) / sizeof(r_star_pnt[0]) - 1; |
260 | for (i = 0; i < len; i++) |
258 | for (i = 0; i < len; i++) |
261 | { |
259 | { |
262 | a = 2 * i * M_PI / len; |
260 | a = 2 * i * M_PI / len; |
263 | r = (i % 2) ? r_star_small : r_star_large; |
261 | r = (i % 2) ? r_star_small : r_star_large; |
264 | r_star_pnt[i].x = cos(a) * r; |
262 | r_star_pnt[i].x = cos(a) * r; |
265 | r_star_pnt[i].y = sin(a) * r; |
263 | r_star_pnt[i].y = sin(a) * r; |
266 | } |
264 | } |
267 | r_star_pnt[len] = r_star_pnt[0]; |
265 | r_star_pnt[len] = r_star_pnt[0]; |
268 | } |
266 | } |
269 | 267 | ||
270 | class TChBoard; |
268 | class TChBoard; |
271 | 269 | ||
272 | class TSomeDraw |
270 | class TSomeDraw |
273 | { |
271 | { |
274 | public: |
272 | public: |
275 | TSomeDraw() {} |
273 | TSomeDraw() {} |
276 | 274 | ||
277 | virtual void Draw(TGraphDraw *drw, int w, int h) = 0; |
275 | virtual void Draw(TGraphDraw *drw, int w, int h) = 0; |
278 | virtual void DrawB(TGraphDraw *drw, TChBoard &brd); |
276 | virtual void DrawB(TGraphDraw *drw, TChBoard &brd); |
279 | virtual TIntPoint GetDSize(int w, int h) {return TIntPoint(INT_MIN, INT_MIN);} |
277 | virtual TIntPoint GetDSize(int w, int h) {return TIntPoint(INT_MIN, INT_MIN);} |
280 | }; |
278 | }; |
281 | 279 | ||
282 | class TChBoard |
280 | class TChBoard |
283 | { |
281 | { |
284 | public: |
282 | public: |
285 | TChBoard(int id = 0); |
283 | TChBoard(int id = 0); |
286 | 284 | ||
287 | TProjectiveMap Get4PMap() const; |
285 | TProjectiveMap Get4PMap() const; |
288 | int GetW() const {return width;} |
286 | int GetW() const {return width;} |
289 | int GetH() const {return height;} |
287 | int GetH() const {return height;} |
290 | void ClearWH() {width = -1; height = -1;} |
288 | void ClearWH() {width = -1; height = -1;} |
291 | void Resize(int w, int h); |
289 | void Resize(int w, int h); |
292 | void Resize(TIntPoint size) {Resize(size.x, size.y);} |
290 | void Resize(TIntPoint size) {Resize(size.x, size.y);} |
293 | 291 | ||
294 | TIntPoint PlToWin(double x, double y) const; |
292 | TIntPoint PlToWin(double x, double y) const; |
295 | TIntPoint PlToWin(TRealPoint rp) const {return PlToWin(rp.x, rp.y);} |
293 | TIntPoint PlToWin(TRealPoint rp) const {return PlToWin(rp.x, rp.y);} |
296 | TRealPoint WinToPl(int x, int y) const; |
294 | TRealPoint WinToPl(int x, int y) const; |
297 | TRealPoint WinToPl(TIntPoint p) const {return WinToPl(p.x, p.y);} |
295 | TRealPoint WinToPl(TIntPoint p) const {return WinToPl(p.x, p.y);} |
298 | 296 | ||
299 | void NewGame(); |
297 | void NewGame(); |
300 | int CanPlayerMove() const {return !IsPlayView && !game_end && !player[MainPos.wmove];} |
298 | int CanPlayerMove() const {return !IsPlayView && !game_end && !player[MainPos.wmove];} |
301 | 299 | ||
302 | void Draw(TGraphDraw *drw); |
300 | void Draw(TGraphDraw *drw); |
303 | int ResizeDraw(TGraphDraw *drw, int w, int h); |
301 | int ResizeDraw(TGraphDraw *drw, int w, int h); |
304 | int CheckResize(TGraphDraw *drw); |
302 | int CheckResize(TGraphDraw *drw); |
305 | int HaveCheckResize() const {return check_resize;} |
303 | int HaveCheckResize() const {return check_resize;} |
306 | void SetCheckResize(int cr) {check_resize = cr;} |
304 | void SetCheckResize(int cr) {check_resize = cr;} |
307 | int MouseClick(TGraphDraw *drw, int x, int y); |
305 | int MouseClick(TGraphDraw *drw, int x, int y); |
308 | void UnMove(TGraphDraw *drw); |
306 | void UnMove(TGraphDraw *drw); |
309 | 307 | ||
310 | int CMove(TGraphDraw *drw, int x, int y); |
308 | int CMove(TGraphDraw *drw, int x, int y); |
311 | int AutoMove(TGraphDraw *drw, int nmove = 0, int draw_check = 1); |
309 | int AutoMove(TGraphDraw *drw, int nmove = 0, int draw_check = 1); |
312 | 310 | ||
313 | enum PKey {PNull, PEnter, PLeft, PRight, PUp, PDown}; |
311 | enum PKey {PNull, PEnter, PLeft, PRight, PUp, PDown}; |
314 | PKey GetKeySide(PKey key); |
312 | PKey GetKeySide(PKey key); |
315 | int PKeyEvent(TGraphDraw *drw, PKey key = PEnter); |
313 | int PKeyEvent(TGraphDraw *drw, PKey key = PEnter); |
316 | protected: |
314 | protected: |
317 | enum TextLineType {TLT_Main, TLT_Move, TLT_Wait, TLT_GameEnd, TLT_WrongMove, |
315 | enum TextLineType {TLT_Main, TLT_Move, TLT_Wait, TLT_GameEnd, TLT_WrongMove, |
318 | TLT_PlDidntMove, TLT_PlWrongMove, TLT_WrongColor, |
316 | TLT_PlDidntMove, TLT_PlWrongMove, TLT_WrongColor, |
319 | TLT_WfCell, TLT_WnfCell, TLT_WMustEat, TLT_WMustEatMore, |
317 | TLT_WfCell, TLT_WnfCell, TLT_WMustEat, TLT_WMustEatMore, |
320 | TLT_WNoMove, TLT_WChBack, TLT_WNotDm, TLT_WOnlyDiag, |
318 | TLT_WNoMove, TLT_WChBack, TLT_WNotDm, TLT_WOnlyDiag, |
321 | TLT_WEatYour, TLT_WMoreOne, TLT_WNotDmE, TLT_WMustEatMoreD, |
319 | TLT_WEatYour, TLT_WMoreOne, TLT_WNotDmE, TLT_WMustEatMoreD, |
322 | TLT_WTurnBack}; |
320 | TLT_WTurnBack}; |
323 | void GetTextLine(char str[]) const; |
321 | void GetTextLine(char str[]) const; |
324 | void DrawTextLine(TGraphDraw *drw) const; |
322 | void DrawTextLine(TGraphDraw *drw) const; |
325 | void LineB(TGraphDraw *drw, double x1, double y1, double x2, double y2) const; |
323 | void LineB(TGraphDraw *drw, double x1, double y1, double x2, double y2) const; |
326 | void DrawCh(TGraphDraw *drw, double x0, double y0, const TRealPoint pnt[], int npnt, |
324 | void DrawCh(TGraphDraw *drw, double x0, double y0, const TRealPoint pnt[], int npnt, |
327 | int L = NELEM(r_ch_lines)) const; |
325 | int L = NELEM(r_ch_lines)) const; |
328 | void DrawIL(TGraphDraw *drw, double x0, double y0, int L) const; |
326 | void DrawIL(TGraphDraw *drw, double x0, double y0, int L) const; |
329 | void MoveErase(); |
327 | void MoveErase(); |
330 | void CurPointClear(TGraphDraw *drw) const; |
328 | void CurPointClear(TGraphDraw *drw) const; |
331 | void RenewMPos() {if (MainPlay.GetPos(MainPos, CurMoveN) < 0) MainPos.Init();} |
329 | void RenewMPos() {if (MainPlay.GetPos(MainPos, CurMoveN) < 0) MainPos.Init();} |
332 | void PrintLMove(); |
330 | void PrintLMove(); |
333 | void SetNoMove(TGraphDraw *drw = 0, int force = 1); |
331 | void SetNoMove(TGraphDraw *drw = 0, int force = 1); |
334 | TextLineType GetTLTfromA(int s) const; |
332 | TextLineType GetTLTfromA(int s) const; |
335 | void ChangeTLT(TGraphDraw *drw, TextLineType t); |
333 | void ChangeTLT(TGraphDraw *drw, TextLineType t); |
336 | TextLineType GetSimpleTLT() const; |
334 | TextLineType GetSimpleTLT() const; |
337 | public: |
335 | public: |
338 | void ResetTextLine(TGraphDraw *drw); |
336 | void ResetTextLine(TGraphDraw *drw); |
339 | TChPlayer *GetPlayer(int k) const {return player[k];} |
337 | TChPlayer *GetPlayer(int k) const {return player[k];} |
340 | void SetPlayer(int k, TChPlayer *pl) {player[k] = pl;} |
338 | void SetPlayer(int k, TChPlayer *pl) {player[k] = pl;} |
341 | int GetBottomColor() const {return BottomColor;} |
339 | int GetBottomColor() const {return BottomColor;} |
342 | void SetBottomColor(int c) {BottomColor = c & 1;} |
340 | void SetBottomColor(int c) {BottomColor = c & 1;} |
343 | public: |
341 | public: |
344 | enum {textlineh = 14, min_brd = 120, max_delt = 20, min_brdsize = 70}; |
342 | enum {textlineh = 14, min_brd = 120, max_delt = 20, min_brdsize = 70}; |
345 | int GetTextLineY() const; |
343 | int GetTextLineY() const; |
346 | TSomeDraw *GetSomeDraw() const {return some_draw;} |
344 | TSomeDraw *GetSomeDraw() const {return some_draw;} |
347 | void SetSomeDraw(TSomeDraw *drw) {some_draw = drw;} |
345 | void SetSomeDraw(TSomeDraw *drw) {some_draw = drw;} |
348 | TIntPoint GetMinWSize() const {return min_wsize;} |
346 | TIntPoint GetMinWSize() const {return min_wsize;} |
349 | void SetMinWSize(TIntPoint mws) {min_wsize = mws; Resize(width, height);} |
347 | void SetMinWSize(TIntPoint mws) {min_wsize = mws; Resize(width, height);} |
350 | void SetMinWSize(int w, int h) {SetMinWSize(TIntPoint(w, h));} |
348 | void SetMinWSize(int w, int h) {SetMinWSize(TIntPoint(w, h));} |
351 | void DrawTimer(TGraphDraw *drw, double t, int wh = 0) const; |
349 | void DrawTimer(TGraphDraw *drw, double t, int wh = 0) const; |
352 | int GetNumMove() const {return MainPlay.GetN() - 1;} |
350 | int GetNumMove() const {return MainPlay.GetN() - 1;} |
353 | int GetCurMoveN() const {return CurMoveN;} |
351 | int GetCurMoveN() const {return CurMoveN;} |
354 | int SetCurMoveN(int n, TGraphDraw *drw = 0); |
352 | int SetCurMoveN(int n, TGraphDraw *drw = 0); |
355 | int SetPlay(const PlayWrite &play); |
353 | int SetPlay(const PlayWrite &play); |
356 | PlayWrite GetPlay() const {return MainPlay;} |
354 | PlayWrite GetPlay() const {return MainPlay;} |
357 | int GetPViewStatus() const {return IsPlayView;} |
355 | int GetPViewStatus() const {return IsPlayView;} |
358 | void SetPViewStatus(int pv) {IsPlayView = pv;} |
356 | void SetPViewStatus(int pv) {IsPlayView = pv;} |
359 | void GoToCurMove(); |
357 | void GoToCurMove(); |
360 | int GetGameEnd() const {return game_end;} |
358 | int GetGameEnd() const {return game_end;} |
361 | void EraseHistory() {hist_inited = 0;} |
359 | void EraseHistory() {hist_inited = 0;} |
362 | int ReinitHistory(); |
360 | int ReinitHistory(); |
363 | protected: |
361 | protected: |
364 | double dw_delt, dw_cell; |
362 | double dw_delt, dw_cell; |
365 | int width, height; |
363 | int width, height; |
366 | TProjectiveMap PoleMap; |
364 | TProjectiveMap PoleMap; |
367 | Position MainPos; |
365 | Position MainPos; |
368 | int BottomColor; |
366 | int BottomColor; |
369 | unsigned char TheMove[NUM_CELL]; |
367 | unsigned char TheMove[NUM_CELL]; |
370 | unsigned char Eaten[NUM_CELL]; |
368 | unsigned char Eaten[NUM_CELL]; |
371 | unsigned char BecameD; |
369 | unsigned char BecameD; |
372 | TIntPoint CurPoint; |
370 | TIntPoint CurPoint; |
373 | int game_end; |
371 | int game_end; |
374 | int check_resize; |
372 | int check_resize; |
375 | TIntPoint delta_size; |
373 | TIntPoint delta_size; |
376 | TextLineType text_line_type; |
374 | TextLineType text_line_type; |
377 | PlayWrite MainPlay; |
375 | PlayWrite MainPlay; |
378 | TChPlayer *player[2]; |
376 | TChPlayer *player[2]; |
379 | TSomeDraw *some_draw; |
377 | TSomeDraw *some_draw; |
380 | TIntPoint min_wsize; |
378 | TIntPoint min_wsize; |
381 | int CurMoveN, IsPlayView; |
379 | int CurMoveN, IsPlayView; |
382 | THistory history; |
380 | THistory history; |
383 | int hist_inited; |
381 | int hist_inited; |
384 | }; |
382 | }; |
385 | 383 | ||
386 | inline void TSomeDraw::DrawB(TGraphDraw *drw, TChBoard &brd) |
384 | inline void TSomeDraw::DrawB(TGraphDraw *drw, TChBoard &brd) |
387 | { |
385 | { |
388 | Draw(drw, brd.GetW(), brd.GetH()); |
386 | Draw(drw, brd.GetW(), brd.GetH()); |
389 | } |
387 | } |
390 | 388 | ||
391 | void TChBoard::MoveErase() |
389 | void TChBoard::MoveErase() |
392 | { |
390 | { |
393 | TheMove[0] = 0; |
391 | TheMove[0] = 0; |
394 | Eaten[0] = 0; |
392 | Eaten[0] = 0; |
395 | BecameD = 0; |
393 | BecameD = 0; |
396 | } |
394 | } |
397 | 395 | ||
398 | TChBoard::TChBoard(int id) : history(id) |
396 | TChBoard::TChBoard(int id) : history(id) |
399 | { |
397 | { |
400 | InitBoardData(); |
398 | InitBoardData(); |
401 | player[0] = player[1] = 0; |
399 | player[0] = player[1] = 0; |
402 | dw_delt = 0.3; |
400 | dw_delt = 0.3; |
403 | dw_cell = 1; |
401 | dw_cell = 1; |
404 | BottomColor = 0; |
402 | BottomColor = 0; |
405 | check_resize = 0; |
403 | check_resize = 0; |
406 | delta_size.x = 0; delta_size.y = 0; |
404 | delta_size.x = 0; delta_size.y = 0; |
407 | some_draw = 0; |
405 | some_draw = 0; |
408 | min_wsize.x = 80; min_wsize.y = 80; |
406 | min_wsize.x = 80; min_wsize.y = 80; |
409 | ClearWH(); |
407 | ClearWH(); |
410 | Resize(400, 400); |
408 | Resize(400, 400); |
411 | NewGame(); |
409 | NewGame(); |
412 | } |
410 | } |
413 | 411 | ||
414 | TProjectiveMap TChBoard::Get4PMap() const |
412 | TProjectiveMap TChBoard::Get4PMap() const |
415 | { |
413 | { |
416 | return TProjectiveMap().Set4(TRealPoint(-dw_delt, -dw_delt), |
414 | return TProjectiveMap().Set4(TRealPoint(-dw_delt, -dw_delt), |
417 | TRealPoint(NW_CELL*dw_cell + dw_delt, -dw_delt), |
415 | TRealPoint(NW_CELL*dw_cell + dw_delt, -dw_delt), |
418 | TRealPoint(NW_CELL*dw_cell + dw_delt, NW_CELL*dw_cell + dw_delt), |
416 | TRealPoint(NW_CELL*dw_cell + dw_delt, NW_CELL*dw_cell + dw_delt), |
419 | TRealPoint(-dw_delt, NW_CELL*dw_cell + dw_delt)); |
417 | TRealPoint(-dw_delt, NW_CELL*dw_cell + dw_delt)); |
420 | } |
418 | } |
421 | 419 | ||
422 | void TChBoard::Resize(int w, int h) |
420 | void TChBoard::Resize(int w, int h) |
423 | { |
421 | { |
424 | width = w; height = h; |
422 | width = w; height = h; |
425 | if (width < min_wsize.x) width = min_wsize.x; |
423 | if (width < min_wsize.x) width = min_wsize.x; |
426 | if (height < min_wsize.y) height = min_wsize.y; |
424 | if (height < min_wsize.y) height = min_wsize.y; |
427 | for (;;) |
425 | for (;;) |
428 | { |
426 | { |
429 | if (some_draw) |
427 | if (some_draw) |
430 | { |
428 | { |
431 | TIntPoint dsz = some_draw->GetDSize(width, height); |
429 | TIntPoint dsz = some_draw->GetDSize(width, height); |
432 | if (dsz.x >= 0 && dsz.y >= 0) delta_size = dsz; |
430 | if (dsz.x >= 0 && dsz.y >= 0) delta_size = dsz; |
433 | } |
431 | } |
434 | int change = 0; |
432 | int change = 0; |
435 | if (width < delta_size.x + min_brdsize) |
433 | if (width < delta_size.x + min_brdsize) |
436 | { |
434 | { |
437 | width = delta_size.x + min_brdsize; |
435 | width = delta_size.x + min_brdsize; |
438 | change++; |
436 | change++; |
439 | } |
437 | } |
440 | if (height < delta_size.y + min_brdsize + textlineh) |
438 | if (height < delta_size.y + min_brdsize + textlineh) |
441 | { |
439 | { |
442 | height = delta_size.y + min_brdsize + textlineh; |
440 | height = delta_size.y + min_brdsize + textlineh; |
443 | change++; |
441 | change++; |
444 | } |
442 | } |
445 | if (!some_draw || !change) break; |
443 | if (!some_draw || !change) break; |
446 | } |
444 | } |
447 | double sx = max_delt, dx = width - 2*sx - delta_size.x; |
445 | double sx = max_delt, dx = width - 2*sx - delta_size.x; |
448 | double sy = max_delt, dy = height - 2*sy - delta_size.y - textlineh; |
446 | double sy = max_delt, dy = height - 2*sy - delta_size.y - textlineh; |
449 | if (dy < min_brd) |
447 | if (dy < min_brd) |
450 | { |
448 | { |
451 | double d = (min_brd - dy) / 2; |
449 | double d = (min_brd - dy) / 2; |
452 | if (d > sy) d = sy; |
450 | if (d > sy) d = sy; |
453 | sy -= d; dy += 2*d; |
451 | sy -= d; dy += 2*d; |
454 | } |
452 | } |
455 | if (dx < min_brd) |
453 | if (dx < min_brd) |
456 | { |
454 | { |
457 | double d = (min_brd - dx) / 2; |
455 | double d = (min_brd - dx) / 2; |
458 | if (d > sx) d = sx; |
456 | if (d > sx) d = sx; |
459 | sx -= d; dx += 2*d; |
457 | sx -= d; dx += 2*d; |
460 | } |
458 | } |
461 | if (dy > dx) {sy += (dy - dx) / 2; dy = dx;} |
459 | if (dy > dx) {sy += (dy - dx) / 2; dy = dx;} |
462 | double tx = (dx - dy * dy / dx) / 3; |
460 | double tx = (dx - dy * dy / dx) / 3; |
463 | PoleMap.Set4(TRealPoint(sx, sy + dy - 70*ssf), TRealPoint(sx + dx, sy + dy), |
461 | PoleMap.Set4(TRealPoint(sx, sy + dy - 70*ssf), TRealPoint(sx + dx, sy + dy), |
464 | TRealPoint(sx + dx - tx, sy), TRealPoint(sx + tx, sy + 40*ssf)); |
462 | TRealPoint(sx + dx - tx, sy), TRealPoint(sx + tx, sy + 40*ssf)); |
465 | PoleMap /= Get4PMap(); |
463 | PoleMap /= Get4PMap(); |
466 | } |
464 | } |
467 | 465 | ||
468 | TIntPoint TChBoard::PlToWin(double x, double y) const |
466 | TIntPoint TChBoard::PlToWin(double x, double y) const |
469 | { |
467 | { |
470 | if (BottomColor == 1) y = NW_CELL*dw_cell - y; |
468 | if (BottomColor == 1) y = NW_CELL*dw_cell - y; |
471 | else x = NW_CELL*dw_cell - x; |
469 | else x = NW_CELL*dw_cell - x; |
472 | /**/if (ssf) y += 0.6 * sin(x);/**/ |
470 | /**/if (ssf) y += 0.6 * sin(x);/**/ |
473 | return PoleMap(x, y).pnt(); |
471 | return PoleMap(x, y).pnt(); |
474 | } |
472 | } |
475 | 473 | ||
476 | TRealPoint TChBoard::WinToPl(int x, int y) const |
474 | TRealPoint TChBoard::WinToPl(int x, int y) const |
477 | { |
475 | { |
478 | TRealPoint rpnt; |
476 | TRealPoint rpnt; |
479 | if (PoleMap.Reversed(x, y).rpnt(rpnt)) |
477 | if (PoleMap.Reversed(x, y).rpnt(rpnt)) |
480 | { |
478 | { |
481 | /**/if (ssf) rpnt.y -= 0.6 * sin(rpnt.x);/**/ |
479 | /**/if (ssf) rpnt.y -= 0.6 * sin(rpnt.x);/**/ |
482 | if (BottomColor == 1) rpnt.y = NW_CELL*dw_cell - rpnt.y; |
480 | if (BottomColor == 1) rpnt.y = NW_CELL*dw_cell - rpnt.y; |
483 | else rpnt.x = NW_CELL*dw_cell - rpnt.x; |
481 | else rpnt.x = NW_CELL*dw_cell - rpnt.x; |
484 | return rpnt; |
482 | return rpnt; |
485 | } |
483 | } |
486 | else return TRealPoint(-dw_cell - dw_delt, -dw_cell - dw_delt); |
484 | else return TRealPoint(-dw_cell - dw_delt, -dw_cell - dw_delt); |
487 | } |
485 | } |
488 | 486 | ||
489 | void TChBoard::NewGame() |
487 | void TChBoard::NewGame() |
490 | { |
488 | { |
491 | int k; |
489 | int k; |
492 | MoveErase(); |
490 | MoveErase(); |
493 | MainPos.Init(); |
491 | MainPos.Init(); |
494 | MainPlay.Clear(); |
492 | MainPlay.Clear(); |
495 | for (k = 0; k < NW_CELL * 3 / 2; k++) MainPos.SH[k] = 1; |
493 | for (k = 0; k < NW_CELL * 3 / 2; k++) MainPos.SH[k] = 1; |
496 | for (k = 0; k < NW_CELL * 3 / 2; k++) MainPos.SH[NUM_CELL - k - 1] = 2; |
494 | for (k = 0; k < NW_CELL * 3 / 2; k++) MainPos.SH[NUM_CELL - k - 1] = 2; |
497 | MainPlay.Add(0, MainPos); |
495 | MainPlay.Add(0, MainPos); |
498 | CurMoveN = 0; |
496 | CurMoveN = 0; |
499 | text_line_type = TLT_Main; |
497 | text_line_type = TLT_Main; |
500 | game_end = 0; |
498 | game_end = 0; |
501 | CurPoint.x = -1; CurPoint.y = -1; |
499 | CurPoint.x = -1; CurPoint.y = -1; |
502 | IsPlayView = 0; |
500 | IsPlayView = 0; |
503 | printf("\nCheckers: New game.\n"); |
501 | printf("\nCheckers: New game.\n"); |
504 | EraseHistory(); |
502 | EraseHistory(); |
505 | } |
503 | } |
506 | 504 | ||
507 | int TChBoard::GetTextLineY() const |
505 | int TChBoard::GetTextLineY() const |
508 | { |
506 | { |
509 | int y = height - (max_delt + textlineh + delta_size.y); |
507 | int y = height - (max_delt + textlineh + delta_size.y); |
510 | int i, j; |
508 | int i, j; |
511 | for (i = 0; i <= 1; i++) for (j = 0; j <= 1; j++) |
509 | for (i = 0; i <= 1; i++) for (j = 0; j <= 1; j++) |
512 | { |
510 | { |
513 | TRealPoint corner; |
511 | TRealPoint corner; |
514 | corner.x = (2*i - 1) * dw_delt + i * NW_CELL * dw_cell; |
512 | corner.x = (2*i - 1) * dw_delt + i * NW_CELL * dw_cell; |
515 | corner.y = (2*j - 1) * dw_delt + j * NW_CELL * dw_cell; |
513 | corner.y = (2*j - 1) * dw_delt + j * NW_CELL * dw_cell; |
516 | TIntPoint wcr = PlToWin(corner); |
514 | TIntPoint wcr = PlToWin(corner); |
517 | if (wcr.x != INT_MIN && wcr.y != INT_MIN) |
515 | if (wcr.x != INT_MIN && wcr.y != INT_MIN) |
518 | { |
516 | { |
519 | if (y < wcr.y) y = wcr.y; |
517 | if (y < wcr.y) y = wcr.y; |
520 | } |
518 | } |
521 | } |
519 | } |
522 | y -= textlineh; |
520 | y -= textlineh; |
523 | if (y > height - delta_size.y - 2*textlineh) |
521 | if (y > height - delta_size.y - 2*textlineh) |
524 | { |
522 | { |
525 | y = height - delta_size.y - 2*textlineh; |
523 | y = height - delta_size.y - 2*textlineh; |
526 | } |
524 | } |
527 | return (y + height - delta_size.y) / 2; |
525 | return (y + height - delta_size.y) / 2; |
528 | } |
526 | } |
529 | 527 | ||
530 | #ifdef BUILD_RUS |
528 | #ifdef LANG_RUS |
531 | #define aCheckersGame "£à ¢ è 誨." |
529 | #define aCheckersGame "£à ¢ è 誨." |
532 | #define aRedMoves "à áë¥ å®¤ïâ." |
530 | #define aRedMoves "à áë¥ å®¤ïâ." |
533 | #define aBlueMoves "¨¨¥ 室ïâ." |
531 | #define aBlueMoves "¨¨¥ 室ïâ." |
534 | #define aWait "®¤®¦¤¨â¥." |
532 | #define aWait "®¤®¦¤¨â¥." |
535 | #define aRedWins "à áë¥ ¢ë¨£à «¨." |
533 | #define aRedWins "à áë¥ ¢ë¨£à «¨." |
536 | #define aBlueWins "¨¨¥ ¢ë¨£à «¨." |
534 | #define aBlueWins "¨¨¥ ¢ë¨£à «¨." |
537 | #define aDraw "¨çìï." |
535 | #define aDraw "¨çìï." |
538 | #define aRed "à áë¥ " |
536 | #define aRed "à áë¥ " |
539 | #define aBlue "¨¨¥ " |
537 | #define aBlue "¨¨¥ " |
540 | #define aMadeWrongMove "ᤥ« «¨ ¥¯à ¢¨«ìë© å®¤." |
538 | #define aMadeWrongMove "ᤥ« «¨ ¥¯à ¢¨«ìë© å®¤." |
541 | #define aNoMove "¥ ᬮ£«¨ ᤥ« âì 室." |
539 | #define aNoMove "¥ ᬮ£«¨ ᤥ« âì 室." |
542 | #define aEndGame "®¥æ ¨£àë." |
540 | #define aEndGame "®¥æ ¨£àë." |
543 | #define aYouWin " (ë ¢ë¨£à «¨)" |
541 | #define aYouWin " (ë ¢ë¨£à «¨)" |
544 | #define aYouLose " (ë ¯à®¨£à «¨)" |
542 | #define aYouLose " (ë ¯à®¨£à «¨)" |
545 | #define aRedWin " (à áë¥ ¢ë¨£à «¨)" |
543 | #define aRedWin " (à áë¥ ¢ë¨£à «¨)" |
546 | #define aBlueWin " (¨¨¥ ¢ë¨£à «¨)" |
544 | #define aBlueWin " (¨¨¥ ¢ë¨£à «¨)" |
547 | #define aWrongMove "¥¢¥àë© å®¤." |
545 | #define aWrongMove "¥¢¥àë© å®¤." |
548 | #define aNotYourChecker "â® ¥ ¢ è è èª ." |
546 | #define aNotYourChecker "â® ¥ ¢ è è èª ." |
549 | #define aFreeCell "â ª«¥âª ¯ãáâ ï." |
547 | #define aFreeCell "â ª«¥âª ¯ãáâ ï." |
550 | #define aNotFreeCell " 誨 ¬®£ãâ 室¨âì ⮫쪮 ᢮¡®¤ë¥ ª«¥âª¨." |
548 | #define aNotFreeCell " 誨 ¬®£ãâ 室¨âì ⮫쪮 ᢮¡®¤ë¥ ª«¥âª¨." |
551 | #define aMustEat "ë ¤®«¦ë ¢§ïâì è èªã." |
549 | #define aMustEat "ë ¤®«¦ë ¢§ïâì è èªã." |
552 | #define aMustEatMore "ë ¤®«¦ë ¢§ïâì ¥éñ è èªã." |
550 | #define aMustEatMore "ë ¤®«¦ë ¢§ïâì ¥éñ è èªã." |
553 | #define aCheckerNoMove " í⮩ è 誨 ¥â 室®¢." |
551 | #define aCheckerNoMove " í⮩ è 誨 ¥â 室®¢." |
554 | #define aNoBack " 誨 ¥ 室ïâ § ¤." |
552 | #define aNoBack " 誨 ¥ 室ïâ § ¤." |
555 | #define aNotDamka "â® ¥ ¤ ¬ª ." |
553 | #define aNotDamka "â® ¥ ¤ ¬ª ." |
556 | #define aOnlyDiag " 誨 室ïâ ⮫쪮 ¯® ¤¨ £® «¨." |
554 | #define aOnlyDiag " 誨 室ïâ ⮫쪮 ¯® ¤¨ £® «¨." |
557 | #define aEatYour " 誨 ¥ ¬®£ãâ ¥áâì ᢮¨å." |
555 | #define aEatYour " 誨 ¥ ¬®£ãâ ¥áâì ᢮¨å." |
558 | #define aMoreOne "ë ¥ ¬®¦¥â¥ ¢§ïâì ¡®«¥¥ ®¤®© è 誨 § à §." |
556 | #define aMoreOne "ë ¥ ¬®¦¥â¥ ¢§ïâì ¡®«¥¥ ®¤®© è 誨 § à §." |
559 | #define aNoTurnBack " 誨 ¥ ¬®£ãâ à §¢®à 稢 âìáï § ¤ ¯à¨ ¢§ï⨨." |
557 | #define aNoTurnBack " 誨 ¥ ¬®£ãâ à §¢®à 稢 âìáï § ¤ ¯à¨ ¢§ï⨨." |
560 | #else |
558 | #else |
561 | #define aCheckersGame "The checkers game." |
559 | #define aCheckersGame "The checkers game." |
562 | #define aRedMoves "Red moves." |
560 | #define aRedMoves "Red moves." |
563 | #define aBlueMoves "Blue moves." |
561 | #define aBlueMoves "Blue moves." |
564 | #define aWait "Please wait." |
562 | #define aWait "Please wait." |
565 | #define aRedWins "Red wins." |
563 | #define aRedWins "Red wins." |
566 | #define aBlueWins "Blue wins." |
564 | #define aBlueWins "Blue wins." |
567 | #define aDraw "Draw." |
565 | #define aDraw "Draw." |
568 | #define aRed "Red " |
566 | #define aRed "Red " |
569 | #define aBlue "Blue " |
567 | #define aBlue "Blue " |
570 | #define aMadeWrongMove "make a wrong move." |
568 | #define aMadeWrongMove "make a wrong move." |
571 | #define aNoMove "could not make a move." |
569 | #define aNoMove "could not make a move." |
572 | #define aEndGame "End of the game." |
570 | #define aEndGame "End of the game." |
573 | #define aYouWin " (You win)" |
571 | #define aYouWin " (You win)" |
574 | #define aYouLose " (You lose)" |
572 | #define aYouLose " (You lose)" |
575 | #define aRedWin " (Red win)" |
573 | #define aRedWin " (Red win)" |
576 | #define aBlueWin " (Blue win)" |
574 | #define aBlueWin " (Blue win)" |
577 | #define aWrongMove "Wrong move." |
575 | #define aWrongMove "Wrong move." |
578 | #define aNotYourChecker "It isn't your checker." |
576 | #define aNotYourChecker "It isn't your checker." |
579 | #define aFreeCell "The cell is free." |
577 | #define aFreeCell "The cell is free." |
580 | #define aNotFreeCell "Checkers may be moved only on a free cell." |
578 | #define aNotFreeCell "Checkers may be moved only on a free cell." |
581 | #define aMustEat "You must eat a checker." |
579 | #define aMustEat "You must eat a checker." |
582 | #define aMustEatMore "You must eat more checkers." |
580 | #define aMustEatMore "You must eat more checkers." |
583 | #define aCheckerNoMove "The checker have no moves." |
581 | #define aCheckerNoMove "The checker have no moves." |
584 | #define aNoBack "Checkers may not be moved back." |
582 | #define aNoBack "Checkers may not be moved back." |
585 | #define aNotDamka "It is not a damka." |
583 | #define aNotDamka "It is not a damka." |
586 | #define aOnlyDiag "Checkers may be moved only along diagonal." |
584 | #define aOnlyDiag "Checkers may be moved only along diagonal." |
587 | #define aEatYour "You may not eat your checkers." |
585 | #define aEatYour "You may not eat your checkers." |
588 | #define aMoreOne "You may not eat more than one checker at a time." |
586 | #define aMoreOne "You may not eat more than one checker at a time." |
589 | #define aNoTurnBack "Checkers may not turn back when eating." |
587 | #define aNoTurnBack "Checkers may not turn back when eating." |
590 | #endif |
588 | #endif |
591 | 589 | ||
592 | void TChBoard::GetTextLine(char str[]) const |
590 | void TChBoard::GetTextLine(char str[]) const |
593 | { |
591 | { |
594 | str[0] = 0; |
592 | str[0] = 0; |
595 | int g = (game_end - 1) % 2, h = 0; |
593 | int g = (game_end - 1) % 2, h = 0; |
596 | switch(text_line_type) |
594 | switch(text_line_type) |
597 | { |
595 | { |
598 | case TLT_Main: |
596 | case TLT_Main: |
599 | strcpy(str, aCheckersGame); |
597 | strcpy(str, aCheckersGame); |
600 | break; |
598 | break; |
601 | case TLT_Move: |
599 | case TLT_Move: |
602 | if (MainPos.wmove == 0) |
600 | if (MainPos.wmove == 0) |
603 | { |
601 | { |
604 | strcpy(str, aRedMoves); |
602 | strcpy(str, aRedMoves); |
605 | } |
603 | } |
606 | else strcpy(str, aBlueMoves); |
604 | else strcpy(str, aBlueMoves); |
607 | break; |
605 | break; |
608 | case TLT_Wait: |
606 | case TLT_Wait: |
609 | strcpy(str, aWait); |
607 | strcpy(str, aWait); |
610 | break; |
608 | break; |
611 | case TLT_GameEnd: |
609 | case TLT_GameEnd: |
612 | case TLT_PlDidntMove: |
610 | case TLT_PlDidntMove: |
613 | case TLT_PlWrongMove: |
611 | case TLT_PlWrongMove: |
614 | if (!game_end) break; |
612 | if (!game_end) break; |
615 | if (text_line_type == TLT_GameEnd) |
613 | if (text_line_type == TLT_GameEnd) |
616 | { |
614 | { |
617 | if (game_end == 1) strcpy(str, aRedWins); |
615 | if (game_end == 1) strcpy(str, aRedWins); |
618 | else if (game_end == 2) strcpy(str, aBlueWins); |
616 | else if (game_end == 2) strcpy(str, aBlueWins); |
619 | else if (game_end == 5) strcpy(str, aDraw); |
617 | else if (game_end == 5) strcpy(str, aDraw); |
620 | } |
618 | } |
621 | if (!str[0]) |
619 | if (!str[0]) |
622 | { |
620 | { |
623 | if (game_end >= 1 && game_end <= 4) |
621 | if (game_end >= 1 && game_end <= 4) |
624 | { |
622 | { |
625 | if (g == 0) strcpy(str, aRed); |
623 | if (g == 0) strcpy(str, aRed); |
626 | else strcpy(str, aBlue); |
624 | else strcpy(str, aBlue); |
627 | if (text_line_type == TLT_PlWrongMove) |
625 | if (text_line_type == TLT_PlWrongMove) |
628 | { |
626 | { |
629 | strcat(str, aMadeWrongMove); |
627 | strcat(str, aMadeWrongMove); |
630 | } |
628 | } |
631 | else strcat(str, aNoMove); |
629 | else strcat(str, aNoMove); |
632 | h = 1; |
630 | h = 1; |
633 | } |
631 | } |
634 | else strcpy(str, aEndGame); |
632 | else strcpy(str, aEndGame); |
635 | } |
633 | } |
636 | if (game_end >= 1 && game_end <= 4) |
634 | if (game_end >= 1 && game_end <= 4) |
637 | { |
635 | { |
638 | if (!IsPlayView && player[1-g] && !player[g]) |
636 | if (!IsPlayView && player[1-g] && !player[g]) |
639 | { |
637 | { |
640 | strcat(str, aYouWin); |
638 | strcat(str, aYouWin); |
641 | } |
639 | } |
642 | else if (!IsPlayView && player[g] && !player[1-g]) |
640 | else if (!IsPlayView && player[g] && !player[1-g]) |
643 | { |
641 | { |
644 | strcat(str, aYouLose); |
642 | strcat(str, aYouLose); |
645 | } |
643 | } |
646 | else if (h && g == 0) strcat(str, aRedWin); |
644 | else if (h && g == 0) strcat(str, aRedWin); |
647 | else if (h && g == 1) strcat(str, aBlueWin); |
645 | else if (h && g == 1) strcat(str, aBlueWin); |
648 | } |
646 | } |
649 | break; |
647 | break; |
650 | case TLT_WrongMove: |
648 | case TLT_WrongMove: |
651 | strcpy(str, aWrongMove); |
649 | strcpy(str, aWrongMove); |
652 | break; |
650 | break; |
653 | case TLT_WrongColor: |
651 | case TLT_WrongColor: |
654 | strcpy(str, aNotYourChecker); |
652 | strcpy(str, aNotYourChecker); |
655 | break; |
653 | break; |
656 | case TLT_WfCell: |
654 | case TLT_WfCell: |
657 | strcpy(str, aFreeCell); |
655 | strcpy(str, aFreeCell); |
658 | break; |
656 | break; |
659 | case TLT_WnfCell: |
657 | case TLT_WnfCell: |
660 | strcpy(str, aNotFreeCell); |
658 | strcpy(str, aNotFreeCell); |
661 | break; |
659 | break; |
662 | case TLT_WMustEat: |
660 | case TLT_WMustEat: |
663 | strcpy(str, aMustEat); |
661 | strcpy(str, aMustEat); |
664 | break; |
662 | break; |
665 | case TLT_WMustEatMore: |
663 | case TLT_WMustEatMore: |
666 | case TLT_WMustEatMoreD: |
664 | case TLT_WMustEatMoreD: |
667 | strcpy(str, aMustEatMore); |
665 | strcpy(str, aMustEatMore); |
668 | break; |
666 | break; |
669 | case TLT_WNoMove: |
667 | case TLT_WNoMove: |
670 | strcpy(str, aCheckerNoMove); |
668 | strcpy(str, aCheckerNoMove); |
671 | break; |
669 | break; |
672 | case TLT_WChBack: |
670 | case TLT_WChBack: |
673 | strcpy(str, aNoBack); |
671 | strcpy(str, aNoBack); |
674 | break; |
672 | break; |
675 | case TLT_WNotDm: |
673 | case TLT_WNotDm: |
676 | case TLT_WNotDmE: |
674 | case TLT_WNotDmE: |
677 | strcpy(str, aNotDamka); |
675 | strcpy(str, aNotDamka); |
678 | break; |
676 | break; |
679 | case TLT_WOnlyDiag: |
677 | case TLT_WOnlyDiag: |
680 | strcpy(str, aOnlyDiag); |
678 | strcpy(str, aOnlyDiag); |
681 | break; |
679 | break; |
682 | case TLT_WEatYour: |
680 | case TLT_WEatYour: |
683 | strcpy(str, aEatYour); |
681 | strcpy(str, aEatYour); |
684 | break; |
682 | break; |
685 | case TLT_WMoreOne: |
683 | case TLT_WMoreOne: |
686 | strcpy(str, aMoreOne); |
684 | strcpy(str, aMoreOne); |
687 | break; |
685 | break; |
688 | case TLT_WTurnBack: |
686 | case TLT_WTurnBack: |
689 | strcpy(str, aNoTurnBack); |
687 | strcpy(str, aNoTurnBack); |
690 | break; |
688 | break; |
691 | } |
689 | } |
692 | } |
690 | } |
693 | 691 | ||
694 | void TChBoard::DrawTextLine(TGraphDraw *drw) const |
692 | void TChBoard::DrawTextLine(TGraphDraw *drw) const |
695 | { |
693 | { |
696 | if (!drw || !drw->IsDraw()) return; |
694 | if (!drw || !drw->IsDraw()) return; |
697 | char str[100]; |
695 | char str[100]; |
698 | GetTextLine(str); |
696 | GetTextLine(str); |
699 | if (str[0]) drw->DrawText(10, GetTextLineY(), str); |
697 | if (str[0]) drw->DrawText(10, GetTextLineY(), str); |
700 | } |
698 | } |
701 | 699 | ||
702 | void TChBoard::ResetTextLine(TGraphDraw *drw) |
700 | void TChBoard::ResetTextLine(TGraphDraw *drw) |
703 | { |
701 | { |
704 | if (!game_end && text_line_type != TLT_Move) ChangeTLT(drw, TLT_Move); |
702 | if (!game_end && text_line_type != TLT_Move) ChangeTLT(drw, TLT_Move); |
705 | } |
703 | } |
706 | 704 | ||
707 | void TChBoard::LineB(TGraphDraw *drw, double x1, double y1, double x2, double y2) const |
705 | void TChBoard::LineB(TGraphDraw *drw, double x1, double y1, double x2, double y2) const |
708 | { |
706 | { |
709 | if (!drw || !drw->IsDraw()) return; |
707 | if (!drw || !drw->IsDraw()) return; |
710 | TIntPoint p1 = PlToWin(x1, y1), p2 = PlToWin(x2, y2); |
708 | TIntPoint p1 = PlToWin(x1, y1), p2 = PlToWin(x2, y2); |
711 | if (p1.x != INT_MIN && p1.y != INT_MIN && p2.x != INT_MIN && p2.y != INT_MIN) |
709 | if (p1.x != INT_MIN && p1.y != INT_MIN && p2.x != INT_MIN && p2.y != INT_MIN) |
712 | { |
710 | { |
713 | drw->DrawLine(p1.x, p1.y, p2.x, p2.y); |
711 | drw->DrawLine(p1.x, p1.y, p2.x, p2.y); |
714 | } |
712 | } |
715 | } |
713 | } |
716 | 714 | ||
717 | void TChBoard::DrawCh(TGraphDraw *drw, double x0, double y0, const TRealPoint pnt[], int npnt, int L) const |
715 | void TChBoard::DrawCh(TGraphDraw *drw, double x0, double y0, const TRealPoint pnt[], int npnt, int L) const |
718 | { |
716 | { |
719 | if (!drw || !drw->IsDraw()) return; |
717 | if (!drw || !drw->IsDraw()) return; |
720 | int i, j; |
718 | int i, j; |
721 | for (j = 0; j < L; j++) |
719 | for (j = 0; j < L; j++) |
722 | { |
720 | { |
723 | for (i = 0; i < npnt - 1; i++) |
721 | for (i = 0; i < npnt - 1; i++) |
724 | { |
722 | { |
725 | LineB(drw, x0 + pnt[i].x * dw_cell * r_ch_lines[j] / 2, |
723 | LineB(drw, x0 + pnt[i].x * dw_cell * r_ch_lines[j] / 2, |
726 | y0 + pnt[i].y * dw_cell * r_ch_lines[j] / 2, |
724 | y0 + pnt[i].y * dw_cell * r_ch_lines[j] / 2, |
727 | x0 + pnt[i+1].x * dw_cell * r_ch_lines[j] / 2, |
725 | x0 + pnt[i+1].x * dw_cell * r_ch_lines[j] / 2, |
728 | y0 + pnt[i+1].y * dw_cell * r_ch_lines[j] / 2); |
726 | y0 + pnt[i+1].y * dw_cell * r_ch_lines[j] / 2); |
729 | } |
727 | } |
730 | } |
728 | } |
731 | } |
729 | } |
732 | 730 | ||
733 | void TChBoard::DrawIL(TGraphDraw *drw, double x0, double y0, int L) const |
731 | void TChBoard::DrawIL(TGraphDraw *drw, double x0, double y0, int L) const |
734 | { |
732 | { |
735 | if (!drw || !drw->IsDraw()) return; |
733 | if (!drw || !drw->IsDraw()) return; |
736 | int i, j; |
734 | int i, j; |
737 | if (L == 0 || L == 1) |
735 | if (L == 0 || L == 1) |
738 | { |
736 | { |
739 | const int numDST[2] = {2, 4}; |
737 | const int numDST[2] = {2, 4}; |
740 | const double DST[2][4] = {{0.96, 0.88}, {0.8, 0.76, 0.72, 0.68}}; |
738 | const double DST[2][4] = {{0.96, 0.88}, {0.8, 0.76, 0.72, 0.68}}; |
741 | const int MULT[4][4] = {{-1, -1, -1, 1}, {-1, 1, 1, 1}, |
739 | const int MULT[4][4] = {{-1, -1, -1, 1}, {-1, 1, 1, 1}, |
742 | {-1, -1, 1, -1}, {1, -1, 1, 1}}; |
740 | {-1, -1, 1, -1}, {1, -1, 1, 1}}; |
743 | for (i = 0; i < numDST[L]; i++) for (j = 0; j < 4; j++) |
741 | for (i = 0; i < numDST[L]; i++) for (j = 0; j < 4; j++) |
744 | { |
742 | { |
745 | LineB(drw, x0 + dw_cell * DST[L][i] * MULT[j][0] / 2, |
743 | LineB(drw, x0 + dw_cell * DST[L][i] * MULT[j][0] / 2, |
746 | y0 + dw_cell * DST[L][i] * MULT[j][1] / 2, |
744 | y0 + dw_cell * DST[L][i] * MULT[j][1] / 2, |
747 | x0 + dw_cell * DST[L][i] * MULT[j][2] / 2, |
745 | x0 + dw_cell * DST[L][i] * MULT[j][2] / 2, |
748 | y0 + dw_cell * DST[L][i] * MULT[j][3] / 2); |
746 | y0 + dw_cell * DST[L][i] * MULT[j][3] / 2); |
749 | } |
747 | } |
750 | } |
748 | } |
751 | else if (L == 2) |
749 | else if (L == 2) |
752 | { |
750 | { |
753 | const double DP[] = {0.85, 0.90, 0.95}; |
751 | const double DP[] = {0.85, 0.90, 0.95}; |
754 | const int numDP = NELEM(DP); |
752 | const int numDP = NELEM(DP); |
755 | for (i = 0; i < numDP; i++) for (j = -1; j <= 1; j += 2) |
753 | for (i = 0; i < numDP; i++) for (j = -1; j <= 1; j += 2) |
756 | { |
754 | { |
757 | LineB(drw, x0 - j * dw_cell * DP[i] / 2, |
755 | LineB(drw, x0 - j * dw_cell * DP[i] / 2, |
758 | y0 - dw_cell * DP[numDP - i - 1] / 2, |
756 | y0 - dw_cell * DP[numDP - i - 1] / 2, |
759 | x0 + j * dw_cell * DP[numDP - i - 1] / 2, |
757 | x0 + j * dw_cell * DP[numDP - i - 1] / 2, |
760 | y0 + dw_cell * DP[i] / 2); |
758 | y0 + dw_cell * DP[i] / 2); |
761 | } |
759 | } |
762 | } |
760 | } |
763 | } |
761 | } |
764 | 762 | ||
765 | void TChBoard::Draw(TGraphDraw *drw) |
763 | void TChBoard::Draw(TGraphDraw *drw) |
766 | { |
764 | { |
767 | if (!drw || !drw->IsDraw()) return; |
765 | if (!drw || !drw->IsDraw()) return; |
768 | if (CheckResize(drw)) drw->DrawClear(); |
766 | if (CheckResize(drw)) drw->DrawClear(); |
769 | int i, j, k, kn; |
767 | int i, j, k, kn; |
770 | unsigned long black = drw->GetBlackColor(); |
768 | unsigned long black = drw->GetBlackColor(); |
771 | unsigned long red = drw->CreateColor(65535u, 0, 0); |
769 | unsigned long red = drw->CreateColor(65535u, 0, 0); |
772 | unsigned long green = drw->CreateColor(0, 49151u, 0); |
770 | unsigned long green = drw->CreateColor(0, 49151u, 0); |
773 | unsigned long blue = drw->CreateColor(0, 0, 65535u); |
771 | unsigned long blue = drw->CreateColor(0, 0, 65535u); |
774 | drw->SetColor(black); |
772 | drw->SetColor(black); |
775 | for (i = -1; i <= NW_CELL + 1; i++) for (j = -1; j <= NW_CELL; j++) |
773 | for (i = -1; i <= NW_CELL + 1; i++) for (j = -1; j <= NW_CELL; j++) |
776 | { |
774 | { |
777 | if (i < 0 || i > NW_CELL || j >= 0 && j < NW_CELL) |
775 | if (i < 0 || i > NW_CELL || j >= 0 && j < NW_CELL) |
778 | { |
776 | { |
779 | double mval = dw_cell * NW_CELL + dw_delt; |
777 | double mval = dw_cell * NW_CELL + dw_delt; |
780 | double x, y0, y1; |
778 | double x, y0, y1; |
781 | if (i < 0) x = -dw_delt; |
779 | if (i < 0) x = -dw_delt; |
782 | else if (i > NW_CELL) x = mval; |
780 | else if (i > NW_CELL) x = mval; |
783 | else x = i * dw_cell; |
781 | else x = i * dw_cell; |
784 | if (j < 0) y0 = -dw_delt; |
782 | if (j < 0) y0 = -dw_delt; |
785 | else if (j > NW_CELL) y0 = mval; |
783 | else if (j > NW_CELL) y0 = mval; |
786 | else y0 = j * dw_cell; |
784 | else y0 = j * dw_cell; |
787 | if ((j+1) < 0) y1 = -dw_delt; |
785 | if ((j+1) < 0) y1 = -dw_delt; |
788 | else if ((j+1) > NW_CELL) y1 = mval; |
786 | else if ((j+1) > NW_CELL) y1 = mval; |
789 | else y1 = (j+1) * dw_cell; |
787 | else y1 = (j+1) * dw_cell; |
790 | LineB(drw, x, y0, x, y1); |
788 | LineB(drw, x, y0, x, y1); |
791 | } |
789 | } |
792 | } |
790 | } |
793 | for (i = -1; i <= NW_CELL; i++) for (j = -1; j <= NW_CELL + 1; j++) |
791 | for (i = -1; i <= NW_CELL; i++) for (j = -1; j <= NW_CELL + 1; j++) |
794 | { |
792 | { |
795 | if (j < 0 || j > NW_CELL || i >= 0 && i < NW_CELL) |
793 | if (j < 0 || j > NW_CELL || i >= 0 && i < NW_CELL) |
796 | { |
794 | { |
797 | double mval = dw_cell * NW_CELL + dw_delt; |
795 | double mval = dw_cell * NW_CELL + dw_delt; |
798 | double x0, x1, y; |
796 | double x0, x1, y; |
799 | if (i < 0) x0 = -dw_delt; |
797 | if (i < 0) x0 = -dw_delt; |
800 | else if (i > NW_CELL) x0 = mval; |
798 | else if (i > NW_CELL) x0 = mval; |
801 | else x0 = i * dw_cell; |
799 | else x0 = i * dw_cell; |
802 | if ((i+1) < 0) x1 = -dw_delt; |
800 | if ((i+1) < 0) x1 = -dw_delt; |
803 | else if ((i+1) > NW_CELL) x1 = mval; |
801 | else if ((i+1) > NW_CELL) x1 = mval; |
804 | else x1 = (i+1) * dw_cell; |
802 | else x1 = (i+1) * dw_cell; |
805 | if (j < 0) y = -dw_delt; |
803 | if (j < 0) y = -dw_delt; |
806 | else if (j > NW_CELL) y = mval; |
804 | else if (j > NW_CELL) y = mval; |
807 | else y = j * dw_cell; |
805 | else y = j * dw_cell; |
808 | LineB(drw, x0, y, x1, y); |
806 | LineB(drw, x0, y, x1, y); |
809 | } |
807 | } |
810 | } |
808 | } |
811 | for (i = -1; i <= 1; i += 2) |
809 | for (i = -1; i <= 1; i += 2) |
812 | { |
810 | { |
813 | drw->SetColor((i < 0) ? red : blue); |
811 | drw->SetColor((i < 0) ? red : blue); |
814 | for (j = -1; j <= 1; j += 2) |
812 | for (j = -1; j <= 1; j += 2) |
815 | { |
813 | { |
816 | double c = dw_cell * NW_CELL / 2; |
814 | double c = dw_cell * NW_CELL / 2; |
817 | double d = (dw_cell/2 > dw_delt) ? dw_delt : dw_cell/2; |
815 | double d = (dw_cell/2 > dw_delt) ? dw_delt : dw_cell/2; |
818 | LineB(drw, c + j * (c + 0.5*d), c + i * (c - 0.5*d), |
816 | LineB(drw, c + j * (c + 0.5*d), c + i * (c - 0.5*d), |
819 | c + j * (c + 0.5*d), c + i * (c - 3.5*d)); |
817 | c + j * (c + 0.5*d), c + i * (c - 3.5*d)); |
820 | LineB(drw, c + j * (c + 0.5*d), c + i * (c - 3.5*d), |
818 | LineB(drw, c + j * (c + 0.5*d), c + i * (c - 3.5*d), |
821 | c + j * (c + 0.2*d), c + i * (c - 2.5*d)); |
819 | c + j * (c + 0.2*d), c + i * (c - 2.5*d)); |
822 | LineB(drw, c + j * (c + 0.5*d), c + i * (c - 3.5*d), |
820 | LineB(drw, c + j * (c + 0.5*d), c + i * (c - 3.5*d), |
823 | c + j * (c + 0.8*d), c + i * (c - 2.5*d)); |
821 | c + j * (c + 0.8*d), c + i * (c - 2.5*d)); |
824 | LineB(drw, c + j * (c + 0.2*d), c + i * (c - 2.5*d), |
822 | LineB(drw, c + j * (c + 0.2*d), c + i * (c - 2.5*d), |
825 | c + j * (c + 0.8*d), c + i * (c - 2.5*d)); |
823 | c + j * (c + 0.8*d), c + i * (c - 2.5*d)); |
826 | } |
824 | } |
827 | } |
825 | } |
828 | for (i = 0; i < NW_CELL; i++) for (j = 0; j < NW_CELL; j++) |
826 | for (i = 0; i < NW_CELL; i++) for (j = 0; j < NW_CELL; j++) |
829 | { |
827 | { |
830 | if (!PoleCpos(i, j)) |
828 | if (!PoleCpos(i, j)) |
831 | { |
829 | { |
832 | drw->SetColor(black); |
830 | drw->SetColor(black); |
833 | LineB(drw, (i+0.33) * dw_cell, j * dw_cell, (i+0.33) * dw_cell, (j+1) * dw_cell); |
831 | LineB(drw, (i+0.33) * dw_cell, j * dw_cell, (i+0.33) * dw_cell, (j+1) * dw_cell); |
834 | LineB(drw, (i+0.67) * dw_cell, j * dw_cell, (i+0.67) * dw_cell, (j+1) * dw_cell); |
832 | LineB(drw, (i+0.67) * dw_cell, j * dw_cell, (i+0.67) * dw_cell, (j+1) * dw_cell); |
835 | LineB(drw, i * dw_cell, (j+0.33) * dw_cell, (i+1) * dw_cell, (j+0.33) * dw_cell); |
833 | LineB(drw, i * dw_cell, (j+0.33) * dw_cell, (i+1) * dw_cell, (j+0.33) * dw_cell); |
836 | LineB(drw, i * dw_cell, (j+0.67) * dw_cell, (i+1) * dw_cell, (j+0.67) * dw_cell); |
834 | LineB(drw, i * dw_cell, (j+0.67) * dw_cell, (i+1) * dw_cell, (j+0.67) * dw_cell); |
837 | LineB(drw, i * dw_cell, j * dw_cell, (i+1) * dw_cell, (j+1) * dw_cell); |
835 | LineB(drw, i * dw_cell, j * dw_cell, (i+1) * dw_cell, (j+1) * dw_cell); |
838 | LineB(drw, (i+1) * dw_cell, j * dw_cell, i * dw_cell, (j+1) * dw_cell); |
836 | LineB(drw, (i+1) * dw_cell, j * dw_cell, i * dw_cell, (j+1) * dw_cell); |
839 | } |
837 | } |
840 | else |
838 | else |
841 | { |
839 | { |
842 | k = PoleToNum(i, j); |
840 | k = PoleToNum(i, j); |
843 | kn = MainPos.SH[k]; |
841 | kn = MainPos.SH[k]; |
844 | if (TheMove[0] > 0 && k == TheMove[1]) |
842 | if (TheMove[0] > 0 && k == TheMove[1]) |
845 | { |
843 | { |
846 | if (kn == 1 || kn == 2) kn = 5; |
844 | if (kn == 1 || kn == 2) kn = 5; |
847 | else if (kn == 3 || kn == 4) kn = 6; |
845 | else if (kn == 3 || kn == 4) kn = 6; |
848 | } |
846 | } |
849 | if (TheMove[0] > 0 && k == TheMove[TheMove[0]]) |
847 | if (TheMove[0] > 0 && k == TheMove[TheMove[0]]) |
850 | { |
848 | { |
851 | kn = MainPos.SH[TheMove[1]]; |
849 | kn = MainPos.SH[TheMove[1]]; |
852 | if (kn <= 2 && BecameD) kn += 2; |
850 | if (kn <= 2 && BecameD) kn += 2; |
853 | } |
851 | } |
854 | if (kn == 1) |
852 | if (kn == 1) |
855 | { |
853 | { |
856 | drw->SetColor(red); |
854 | drw->SetColor(red); |
857 | DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, |
855 | DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, |
858 | r_circle_pnt, NELEM(r_circle_pnt)); |
856 | r_circle_pnt, NELEM(r_circle_pnt)); |
859 | } |
857 | } |
860 | else if (kn == 2) |
858 | else if (kn == 2) |
861 | { |
859 | { |
862 | drw->SetColor(blue); |
860 | drw->SetColor(blue); |
863 | DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, |
861 | DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, |
864 | r_circle_pnt, NELEM(r_circle_pnt)); |
862 | r_circle_pnt, NELEM(r_circle_pnt)); |
865 | } |
863 | } |
866 | else if (kn == 3) |
864 | else if (kn == 3) |
867 | { |
865 | { |
868 | drw->SetColor(red); |
866 | drw->SetColor(red); |
869 | DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, |
867 | DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, |
870 | r_star_pnt, NELEM(r_star_pnt)); |
868 | r_star_pnt, NELEM(r_star_pnt)); |
871 | } |
869 | } |
872 | else if (kn == 4) |
870 | else if (kn == 4) |
873 | { |
871 | { |
874 | drw->SetColor(blue); |
872 | drw->SetColor(blue); |
875 | DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, |
873 | DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, |
876 | r_star_pnt, NELEM(r_star_pnt)); |
874 | r_star_pnt, NELEM(r_star_pnt)); |
877 | } |
875 | } |
878 | else if (kn == 5) |
876 | else if (kn == 5) |
879 | { |
877 | { |
880 | drw->SetColor(green); |
878 | drw->SetColor(green); |
881 | DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, |
879 | DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, |
882 | r_circle_pnt, NELEM(r_circle_pnt), 2); |
880 | r_circle_pnt, NELEM(r_circle_pnt), 2); |
883 | } |
881 | } |
884 | else if (kn == 6) |
882 | else if (kn == 6) |
885 | { |
883 | { |
886 | drw->SetColor(green); |
884 | drw->SetColor(green); |
887 | DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, |
885 | DrawCh(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, |
888 | r_circle_pnt, NELEM(r_circle_pnt), 2); |
886 | r_circle_pnt, NELEM(r_circle_pnt), 2); |
889 | } |
887 | } |
890 | } |
888 | } |
891 | } |
889 | } |
892 | for (k = 1; k <= Eaten[0]; k++) |
890 | for (k = 1; k <= Eaten[0]; k++) |
893 | { |
891 | { |
894 | if (TheMove[0] <= 0 || Eaten[k] != TheMove[TheMove[0]]) |
892 | if (TheMove[0] <= 0 || Eaten[k] != TheMove[TheMove[0]]) |
895 | { |
893 | { |
896 | NumToPole(Eaten[k], i, j); |
894 | NumToPole(Eaten[k], i, j); |
897 | kn = MainPos.SH[Eaten[k]]; |
895 | kn = MainPos.SH[Eaten[k]]; |
898 | if (kn) |
896 | if (kn) |
899 | { |
897 | { |
900 | if (kn == 1 || kn == 3) drw->SetColor(blue); |
898 | if (kn == 1 || kn == 3) drw->SetColor(blue); |
901 | else if (kn == 2 || kn == 4) drw->SetColor(red); |
899 | else if (kn == 2 || kn == 4) drw->SetColor(red); |
902 | DrawIL(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, 2); |
900 | DrawIL(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, 2); |
903 | } |
901 | } |
904 | } |
902 | } |
905 | } |
903 | } |
906 | if (TheMove[0] > 0) |
904 | if (TheMove[0] > 0) |
907 | { |
905 | { |
908 | NumToPole(TheMove[TheMove[0]], i, j); |
906 | NumToPole(TheMove[TheMove[0]], i, j); |
909 | drw->SetColor(green); |
907 | drw->SetColor(green); |
910 | DrawIL(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, 1); |
908 | DrawIL(drw, (i+0.5)*dw_cell, (j+0.5)*dw_cell, 1); |
911 | } |
909 | } |
912 | if (CurPoint.x >= 0 && CurPoint.y >= 0) |
910 | if (CurPoint.x >= 0 && CurPoint.y >= 0) |
913 | { |
911 | { |
914 | drw->SetColor(green); |
912 | drw->SetColor(green); |
915 | DrawIL(drw, (CurPoint.x+0.5)*dw_cell, (CurPoint.y+0.5)*dw_cell, 0); |
913 | DrawIL(drw, (CurPoint.x+0.5)*dw_cell, (CurPoint.y+0.5)*dw_cell, 0); |
916 | } |
914 | } |
917 | drw->SetColor(black); |
915 | drw->SetColor(black); |
918 | DrawTextLine(drw); |
916 | DrawTextLine(drw); |
919 | if (some_draw) some_draw->DrawB(drw, *this); |
917 | if (some_draw) some_draw->DrawB(drw, *this); |
920 | drw->FreeColor(red); |
918 | drw->FreeColor(red); |
921 | drw->FreeColor(green); |
919 | drw->FreeColor(green); |
922 | drw->FreeColor(blue); |
920 | drw->FreeColor(blue); |
923 | } |
921 | } |
924 | 922 | ||
925 | int TChBoard::ResizeDraw(TGraphDraw *drw, int w, int h) |
923 | int TChBoard::ResizeDraw(TGraphDraw *drw, int w, int h) |
926 | { |
924 | { |
927 | int w0 = width, h0 = height; |
925 | int w0 = width, h0 = height; |
928 | Resize(w, h); |
926 | Resize(w, h); |
929 | if (drw && drw->IsDraw() && (width != w0 || height != h0)) |
927 | if (drw && drw->IsDraw() && (width != w0 || height != h0)) |
930 | { |
928 | { |
931 | drw->DrawClear(); |
929 | drw->DrawClear(); |
932 | Draw(drw); |
930 | Draw(drw); |
933 | return 1; |
931 | return 1; |
934 | } |
932 | } |
935 | else return 0; |
933 | else return 0; |
936 | } |
934 | } |
937 | 935 | ||
938 | int TChBoard::CheckResize(TGraphDraw *drw) |
936 | int TChBoard::CheckResize(TGraphDraw *drw) |
939 | { |
937 | { |
940 | if (!drw || !check_resize) return 0; |
938 | if (!drw || !check_resize) return 0; |
941 | int w, h; |
939 | int w, h; |
942 | drw->GetSize(w, h); |
940 | drw->GetSize(w, h); |
943 | if (w < 0 || h < 0) return 0; |
941 | if (w < 0 || h < 0) return 0; |
944 | int w0 = width, h0 = height; |
942 | int w0 = width, h0 = height; |
945 | Resize(w, h); |
943 | Resize(w, h); |
946 | return width != w0 || height != h0; |
944 | return width != w0 || height != h0; |
947 | } |
945 | } |
948 | 946 | ||
949 | void TChBoard::CurPointClear(TGraphDraw *drw) const |
947 | void TChBoard::CurPointClear(TGraphDraw *drw) const |
950 | { |
948 | { |
951 | if (!drw || !drw->IsDraw()) return; |
949 | if (!drw || !drw->IsDraw()) return; |
952 | drw->SetColor(drw->GetWhiteColor()); |
950 | drw->SetColor(drw->GetWhiteColor()); |
953 | DrawIL(drw, (CurPoint.x+0.5)*dw_cell, (CurPoint.y+0.5)*dw_cell, 0); |
951 | DrawIL(drw, (CurPoint.x+0.5)*dw_cell, (CurPoint.y+0.5)*dw_cell, 0); |
954 | } |
952 | } |
955 | 953 | ||
956 | int TChBoard::MouseClick(TGraphDraw *drw, int x, int y) |
954 | int TChBoard::MouseClick(TGraphDraw *drw, int x, int y) |
957 | { |
955 | { |
958 | TRealPoint rpnt = WinToPl(x, y); |
956 | TRealPoint rpnt = WinToPl(x, y); |
959 | if (rpnt.x < -dw_delt || rpnt.y < -dw_delt || |
957 | if (rpnt.x < -dw_delt || rpnt.y < -dw_delt || |
960 | rpnt.x > NW_CELL*dw_cell + dw_delt || |
958 | rpnt.x > NW_CELL*dw_cell + dw_delt || |
961 | rpnt.y > NW_CELL*dw_cell + dw_delt) return -1; |
959 | rpnt.y > NW_CELL*dw_cell + dw_delt) return -1; |
962 | if (CurPoint.x >= 0 && CurPoint.y >= 0) |
960 | if (CurPoint.x >= 0 && CurPoint.y >= 0) |
963 | { |
961 | { |
964 | CurPointClear(drw); |
962 | CurPointClear(drw); |
965 | CurPoint.x = -1; CurPoint.y = -1; |
963 | CurPoint.x = -1; CurPoint.y = -1; |
966 | Draw(drw); |
964 | Draw(drw); |
967 | } |
965 | } |
968 | ResetTextLine(drw); |
966 | ResetTextLine(drw); |
969 | if (AutoMove(drw)) return 3; |
967 | if (AutoMove(drw)) return 3; |
970 | if (!CanPlayerMove()) return 0; |
968 | if (!CanPlayerMove()) return 0; |
971 | int i = (int)floor(rpnt.x / dw_cell), j = (int)floor(rpnt.y / dw_cell); |
969 | int i = (int)floor(rpnt.x / dw_cell), j = (int)floor(rpnt.y / dw_cell); |
972 | if (i < 0 || j < 0 || i >= NW_CELL || j >= NW_CELL) return 0; |
970 | if (i < 0 || j < 0 || i >= NW_CELL || j >= NW_CELL) return 0; |
973 | if (!PoleCpos(i, j)) return 1; |
971 | if (!PoleCpos(i, j)) return 1; |
974 | return 2 + CMove(drw, i, j); |
972 | return 2 + CMove(drw, i, j); |
975 | } |
973 | } |
976 | 974 | ||
977 | TChBoard::PKey TChBoard::GetKeySide(PKey key) |
975 | TChBoard::PKey TChBoard::GetKeySide(PKey key) |
978 | { |
976 | { |
979 | if (key != PLeft && key != PRight && key != PUp && key != PDown) return key; |
977 | if (key != PLeft && key != PRight && key != PUp && key != PDown) return key; |
980 | TIntPoint a0 = PlToWin(4*dw_cell, 0); |
978 | TIntPoint a0 = PlToWin(4*dw_cell, 0); |
981 | TIntPoint a1 = PlToWin(4*dw_cell, 8*dw_cell); |
979 | TIntPoint a1 = PlToWin(4*dw_cell, 8*dw_cell); |
982 | TIntPoint b0 = PlToWin(0, 4*dw_cell); |
980 | TIntPoint b0 = PlToWin(0, 4*dw_cell); |
983 | TIntPoint b1 = PlToWin(8*dw_cell, 4*dw_cell); |
981 | TIntPoint b1 = PlToWin(8*dw_cell, 4*dw_cell); |
984 | double ax = a0.x - a1.x, ay = a0.y - a1.y; |
982 | double ax = a0.x - a1.x, ay = a0.y - a1.y; |
985 | double bx = b0.x - b1.x, by = b0.y - b1.y; |
983 | double bx = b0.x - b1.x, by = b0.y - b1.y; |
986 | double t; |
984 | double t; |
987 | if (a0.x == INT_MIN || a0.y == INT_MIN || a1.x == INT_MIN || |
985 | if (a0.x == INT_MIN || a0.y == INT_MIN || a1.x == INT_MIN || |
988 | a1.y == INT_MIN || fabs(ax) < 0.5 && fabs(ay) < 0.5) |
986 | a1.y == INT_MIN || fabs(ax) < 0.5 && fabs(ay) < 0.5) |
989 | { |
987 | { |
990 | ax = 0, ay = 1; |
988 | ax = 0, ay = 1; |
991 | } |
989 | } |
992 | if (b0.x == INT_MIN || b0.y == INT_MIN || b1.x == INT_MIN || |
990 | if (b0.x == INT_MIN || b0.y == INT_MIN || b1.x == INT_MIN || |
993 | b1.y == INT_MIN || fabs(bx) < 0.5 && fabs(by) < 0.5) |
991 | b1.y == INT_MIN || fabs(bx) < 0.5 && fabs(by) < 0.5) |
994 | { |
992 | { |
995 | bx = 1, by = 0; |
993 | bx = 1, by = 0; |
996 | } |
994 | } |
997 | t = fabs(ax) + fabs(ay); ax /= t; ay /= t; |
995 | t = fabs(ax) + fabs(ay); ax /= t; ay /= t; |
998 | t = fabs(bx) + fabs(by); bx /= t; by /= t; |
996 | t = fabs(bx) + fabs(by); bx /= t; by /= t; |
999 | if (fabs(ax) <= fabs(bx)) |
997 | if (fabs(ax) <= fabs(bx)) |
1000 | { |
998 | { |
1001 | if (key == PLeft) return (bx > 0) ? PRight : PLeft; |
999 | if (key == PLeft) return (bx > 0) ? PRight : PLeft; |
1002 | if (key == PRight) return (bx > 0) ? PLeft : PRight; |
1000 | if (key == PRight) return (bx > 0) ? PLeft : PRight; |
1003 | if (key == PUp) return (ay > 0) ? PDown : PUp; |
1001 | if (key == PUp) return (ay > 0) ? PDown : PUp; |
1004 | if (key == PDown) return (ay > 0) ? PUp : PDown; |
1002 | if (key == PDown) return (ay > 0) ? PUp : PDown; |
1005 | } |
1003 | } |
1006 | else |
1004 | else |
1007 | { |
1005 | { |
1008 | if (key == PLeft) return (ax > 0) ? PDown : PUp; |
1006 | if (key == PLeft) return (ax > 0) ? PDown : PUp; |
1009 | if (key == PRight) return (ax > 0) ? PUp : PDown; |
1007 | if (key == PRight) return (ax > 0) ? PUp : PDown; |
1010 | if (key == PUp) return (by > 0) ? PRight : PLeft; |
1008 | if (key == PUp) return (by > 0) ? PRight : PLeft; |
1011 | if (key == PDown) return (by > 0) ? PLeft : PRight; |
1009 | if (key == PDown) return (by > 0) ? PLeft : PRight; |
1012 | } |
1010 | } |
1013 | return PNull; |
1011 | return PNull; |
1014 | } |
1012 | } |
1015 | 1013 | ||
1016 | int TChBoard::PKeyEvent(TGraphDraw *drw, PKey key) |
1014 | int TChBoard::PKeyEvent(TGraphDraw *drw, PKey key) |
1017 | { |
1015 | { |
1018 | ResetTextLine(drw); |
1016 | ResetTextLine(drw); |
1019 | if (AutoMove(drw)) return 3; |
1017 | if (AutoMove(drw)) return 3; |
1020 | if (!CanPlayerMove()) return 0; |
1018 | if (!CanPlayerMove()) return 0; |
1021 | key = GetKeySide(key); |
1019 | key = GetKeySide(key); |
1022 | if (CurPoint.x < 0 || CurPoint.y < 0 || |
1020 | if (CurPoint.x < 0 || CurPoint.y < 0 || |
1023 | CurPoint.x >= NW_CELL || CurPoint.y >= NW_CELL) |
1021 | CurPoint.x >= NW_CELL || CurPoint.y >= NW_CELL) |
1024 | { |
1022 | { |
1025 | CurPoint.x = NW_CELL / 2; |
1023 | CurPoint.x = NW_CELL / 2; |
1026 | CurPoint.y = NW_CELL / 2; |
1024 | CurPoint.y = NW_CELL / 2; |
1027 | Draw(drw); |
1025 | Draw(drw); |
1028 | return 1; |
1026 | return 1; |
1029 | } |
1027 | } |
1030 | if (key == PEnter) return 2 + CMove(drw, CurPoint.x, CurPoint.y); |
1028 | if (key == PEnter) return 2 + CMove(drw, CurPoint.x, CurPoint.y); |
1031 | if (drw && drw->IsDraw() && CheckResize(drw)) |
1029 | if (drw && drw->IsDraw() && CheckResize(drw)) |
1032 | { |
1030 | { |
1033 | drw->DrawClear(); |
1031 | drw->DrawClear(); |
1034 | Draw(drw); |
1032 | Draw(drw); |
1035 | } |
1033 | } |
1036 | if (key == PLeft) |
1034 | if (key == PLeft) |
1037 | { |
1035 | { |
1038 | if (CurPoint.x == 0) return 0; |
1036 | if (CurPoint.x == 0) return 0; |
1039 | CurPointClear(drw); |
1037 | CurPointClear(drw); |
1040 | CurPoint.x--; |
1038 | CurPoint.x--; |
1041 | Draw(drw); |
1039 | Draw(drw); |
1042 | return 1; |
1040 | return 1; |
1043 | } |
1041 | } |
1044 | else if (key == PRight) |
1042 | else if (key == PRight) |
1045 | { |
1043 | { |
1046 | if (CurPoint.x == NW_CELL - 1) return 0; |
1044 | if (CurPoint.x == NW_CELL - 1) return 0; |
1047 | CurPointClear(drw); |
1045 | CurPointClear(drw); |
1048 | CurPoint.x++; |
1046 | CurPoint.x++; |
1049 | Draw(drw); |
1047 | Draw(drw); |
1050 | return 1; |
1048 | return 1; |
1051 | } |
1049 | } |
1052 | else if (key == PUp) |
1050 | else if (key == PUp) |
1053 | { |
1051 | { |
1054 | if (CurPoint.y == 0) return 0; |
1052 | if (CurPoint.y == 0) return 0; |
1055 | CurPointClear(drw); |
1053 | CurPointClear(drw); |
1056 | CurPoint.y--; |
1054 | CurPoint.y--; |
1057 | Draw(drw); |
1055 | Draw(drw); |
1058 | return 1; |
1056 | return 1; |
1059 | } |
1057 | } |
1060 | else if (key == PDown) |
1058 | else if (key == PDown) |
1061 | { |
1059 | { |
1062 | if (CurPoint.y == NW_CELL - 1) return 0; |
1060 | if (CurPoint.y == NW_CELL - 1) return 0; |
1063 | CurPointClear(drw); |
1061 | CurPointClear(drw); |
1064 | CurPoint.y++; |
1062 | CurPoint.y++; |
1065 | Draw(drw); |
1063 | Draw(drw); |
1066 | return 1; |
1064 | return 1; |
1067 | } |
1065 | } |
1068 | else return 0; |
1066 | else return 0; |
1069 | } |
1067 | } |
1070 | 1068 | ||
1071 | void TChBoard::UnMove(TGraphDraw *drw) |
1069 | void TChBoard::UnMove(TGraphDraw *drw) |
1072 | { |
1070 | { |
1073 | MoveErase(); |
1071 | MoveErase(); |
1074 | if (drw && drw->IsDraw()) |
1072 | if (drw && drw->IsDraw()) |
1075 | { |
1073 | { |
1076 | drw->DrawClear(); |
1074 | drw->DrawClear(); |
1077 | Draw(drw); |
1075 | Draw(drw); |
1078 | } |
1076 | } |
1079 | } |
1077 | } |
1080 | 1078 | ||
1081 | TChBoard::TextLineType TChBoard::GetTLTfromA(int s) const |
1079 | TChBoard::TextLineType TChBoard::GetTLTfromA(int s) const |
1082 | { |
1080 | { |
1083 | if (s >= 0) return TLT_Main; |
1081 | if (s >= 0) return TLT_Main; |
1084 | switch(s) |
1082 | switch(s) |
1085 | { |
1083 | { |
1086 | case Position::AWColor: return TLT_WrongColor; |
1084 | case Position::AWColor: return TLT_WrongColor; |
1087 | case Position::AfCell: return TLT_WfCell; |
1085 | case Position::AfCell: return TLT_WfCell; |
1088 | case Position::AnfCell: return TLT_WnfCell; |
1086 | case Position::AnfCell: return TLT_WnfCell; |
1089 | case Position::AMustEat: return TLT_WMustEat; |
1087 | case Position::AMustEat: return TLT_WMustEat; |
1090 | case Position::AMustEatMore: return TLT_WMustEatMore; |
1088 | case Position::AMustEatMore: return TLT_WMustEatMore; |
1091 | case Position::AMustEatMoreD: return TLT_WMustEatMoreD; |
1089 | case Position::AMustEatMoreD: return TLT_WMustEatMoreD; |
1092 | case Position::ANoMove: return TLT_WNoMove; |
1090 | case Position::ANoMove: return TLT_WNoMove; |
1093 | case Position::AChBack: return TLT_WChBack; |
1091 | case Position::AChBack: return TLT_WChBack; |
1094 | case Position::ANotDm: return TLT_WNotDm; |
1092 | case Position::ANotDm: return TLT_WNotDm; |
1095 | case Position::ANotDmE: return TLT_WNotDmE; |
1093 | case Position::ANotDmE: return TLT_WNotDmE; |
1096 | case Position::AOnlyDiag: return TLT_WOnlyDiag; |
1094 | case Position::AOnlyDiag: return TLT_WOnlyDiag; |
1097 | case Position::AEatYour: return TLT_WEatYour; |
1095 | case Position::AEatYour: return TLT_WEatYour; |
1098 | case Position::AMoreOne: return TLT_WMoreOne; |
1096 | case Position::AMoreOne: return TLT_WMoreOne; |
1099 | case Position::ATurnBack: return TLT_WTurnBack; |
1097 | case Position::ATurnBack: return TLT_WTurnBack; |
1100 | default: return TLT_WrongMove; |
1098 | default: return TLT_WrongMove; |
1101 | } |
1099 | } |
1102 | } |
1100 | } |
1103 | 1101 | ||
1104 | void TChBoard::ChangeTLT(TGraphDraw *drw, TextLineType t) |
1102 | void TChBoard::ChangeTLT(TGraphDraw *drw, TextLineType t) |
1105 | { |
1103 | { |
1106 | if (text_line_type == t) return; |
1104 | if (text_line_type == t) return; |
1107 | if (drw && drw->IsDraw()) |
1105 | if (drw && drw->IsDraw()) |
1108 | { |
1106 | { |
1109 | drw->SetColor(drw->GetWhiteColor()); |
1107 | drw->SetColor(drw->GetWhiteColor()); |
1110 | DrawTextLine(drw); |
1108 | DrawTextLine(drw); |
1111 | } |
1109 | } |
1112 | text_line_type = t; |
1110 | text_line_type = t; |
1113 | if (drw && drw->IsDraw()) |
1111 | if (drw && drw->IsDraw()) |
1114 | { |
1112 | { |
1115 | drw->SetColor(drw->GetBlackColor()); |
1113 | drw->SetColor(drw->GetBlackColor()); |
1116 | DrawTextLine(drw); |
1114 | DrawTextLine(drw); |
1117 | } |
1115 | } |
1118 | } |
1116 | } |
1119 | 1117 | ||
1120 | TChBoard::TextLineType TChBoard::GetSimpleTLT() const |
1118 | TChBoard::TextLineType TChBoard::GetSimpleTLT() const |
1121 | { |
1119 | { |
1122 | if (game_end && CurMoveN >= MainPlay.GetN() - 1) return TLT_GameEnd; |
1120 | if (game_end && CurMoveN >= MainPlay.GetN() - 1) return TLT_GameEnd; |
1123 | else return TLT_Move; |
1121 | else return TLT_Move; |
1124 | } |
1122 | } |
1125 | 1123 | ||
1126 | inline int TChBoard::ReinitHistory() |
1124 | inline int TChBoard::ReinitHistory() |
1127 | { |
1125 | { |
1128 | if (history.Play(MainPlay)) {hist_inited = 1; return 1;} |
1126 | if (history.Play(MainPlay)) {hist_inited = 1; return 1;} |
1129 | else {hist_inited = 0; return 0;} |
1127 | else {hist_inited = 0; return 0;} |
1130 | } |
1128 | } |
1131 | 1129 | ||
1132 | void TChBoard::PrintLMove() |
1130 | void TChBoard::PrintLMove() |
1133 | { |
1131 | { |
1134 | PlayWrite::PMv pmv; |
1132 | PlayWrite::PMv pmv; |
1135 | if (MainPlay.GetMoveL(pmv.mv) >= 0) |
1133 | if (MainPlay.GetMoveL(pmv.mv) >= 0) |
1136 | { |
1134 | { |
1137 | MainPlay.GetPosL(pmv.pos, 1); |
1135 | MainPlay.GetPosL(pmv.pos, 1); |
1138 | char *s = new char[pmv.pos.GetLenMvEx(pmv.mv, 11)]; |
1136 | char *s = new char[pmv.pos.GetLenMvEx(pmv.mv, 11)]; |
1139 | if (s) |
1137 | if (s) |
1140 | { |
1138 | { |
1141 | pmv.pos.WriteMvEx(pmv.mv, s, 11); |
1139 | pmv.pos.WriteMvEx(pmv.mv, s, 11); |
1142 | printf("Checkers: %s%s\n", (pmv.pos.wmove == 1) ? "..." : "", s); |
1140 | printf("Checkers: %s%s\n", (pmv.pos.wmove == 1) ? "..." : "", s); |
1143 | delete[] s; |
1141 | delete[] s; |
1144 | } |
1142 | } |
1145 | if (!hist_inited) ReinitHistory(); |
1143 | if (!hist_inited) ReinitHistory(); |
1146 | else history.Move(pmv.pos, pmv.mv, MainPlay.GetN() - 1); |
1144 | else history.Move(pmv.pos, pmv.mv, MainPlay.GetN() - 1); |
1147 | } |
1145 | } |
1148 | } |
1146 | } |
1149 | 1147 | ||
1150 | int TChBoard::CMove(TGraphDraw *drw, int x, int y) |
1148 | int TChBoard::CMove(TGraphDraw *drw, int x, int y) |
1151 | { |
1149 | { |
1152 | if (AutoMove(drw)) return 1; |
1150 | if (AutoMove(drw)) return 1; |
1153 | if (!CanPlayerMove()) return 0; |
1151 | if (!CanPlayerMove()) return 0; |
1154 | if (!game_end && text_line_type != TLT_Move) ChangeTLT(drw, TLT_Move); |
1152 | if (!game_end && text_line_type != TLT_Move) ChangeTLT(drw, TLT_Move); |
1155 | int k = PoleToNum(x, y), s; |
1153 | int k = PoleToNum(x, y), s; |
1156 | if (TheMove[0] > 0) |
1154 | if (TheMove[0] > 0) |
1157 | { |
1155 | { |
1158 | if (!PoleCpos(x, y) || k == TheMove[TheMove[0]]) {UnMove(drw); return 1;} |
1156 | if (!PoleCpos(x, y) || k == TheMove[TheMove[0]]) {UnMove(drw); return 1;} |
1159 | int e = 1; |
1157 | int e = 1; |
1160 | s = MainPos.AMove(TheMove, k, e); |
1158 | s = MainPos.AMove(TheMove, k, e); |
1161 | if (s < 0) |
1159 | if (s < 0) |
1162 | { |
1160 | { |
1163 | ChangeTLT(drw, GetTLTfromA(s)); |
1161 | ChangeTLT(drw, GetTLTfromA(s)); |
1164 | return 0; |
1162 | return 0; |
1165 | } |
1163 | } |
1166 | if (s < NUM_CELL) Eaten[++Eaten[0]] = (unsigned char)s; |
1164 | if (s < NUM_CELL) Eaten[++Eaten[0]] = (unsigned char)s; |
1167 | TheMove[++TheMove[0]] = (unsigned char)k; |
1165 | TheMove[++TheMove[0]] = (unsigned char)k; |
1168 | BecameD = BecameD || MainPos.BecameD(k, MainPos.SH[TheMove[1]]); |
1166 | BecameD = BecameD || MainPos.BecameD(k, MainPos.SH[TheMove[1]]); |
1169 | if (e == 0) |
1167 | if (e == 0) |
1170 | { |
1168 | { |
1171 | if (MainPlay.Add(TheMove) != 0) |
1169 | if (MainPlay.Add(TheMove) != 0) |
1172 | { |
1170 | { |
1173 | ChangeTLT(drw, TLT_WrongMove); |
1171 | ChangeTLT(drw, TLT_WrongMove); |
1174 | return 0; |
1172 | return 0; |
1175 | } |
1173 | } |
1176 | CurMoveN = MainPlay.GetN() - 1; |
1174 | CurMoveN = MainPlay.GetN() - 1; |
1177 | MoveErase(); |
1175 | MoveErase(); |
1178 | RenewMPos(); |
1176 | RenewMPos(); |
1179 | PrintLMove(); |
1177 | PrintLMove(); |
1180 | if (AutoMove(drw)) return 1; |
1178 | if (AutoMove(drw)) return 1; |
1181 | } |
1179 | } |
1182 | if (drw && drw->IsDraw()) |
1180 | if (drw && drw->IsDraw()) |
1183 | { |
1181 | { |
1184 | drw->DrawClear(); |
1182 | drw->DrawClear(); |
1185 | Draw(drw); |
1183 | Draw(drw); |
1186 | } |
1184 | } |
1187 | return 1; |
1185 | return 1; |
1188 | } |
1186 | } |
1189 | else |
1187 | else |
1190 | { |
1188 | { |
1191 | if (!PoleCpos(x, y)) return 0; |
1189 | if (!PoleCpos(x, y)) return 0; |
1192 | s = MainPos.AChCell(k); |
1190 | s = MainPos.AChCell(k); |
1193 | if (s != 1) |
1191 | if (s != 1) |
1194 | { |
1192 | { |
1195 | ChangeTLT(drw, GetTLTfromA(s)); |
1193 | ChangeTLT(drw, GetTLTfromA(s)); |
1196 | return 0; |
1194 | return 0; |
1197 | } |
1195 | } |
1198 | TheMove[0] = 1; |
1196 | TheMove[0] = 1; |
1199 | TheMove[1] = (unsigned char)k; |
1197 | TheMove[1] = (unsigned char)k; |
1200 | Draw(drw); |
1198 | Draw(drw); |
1201 | return 1; |
1199 | return 1; |
1202 | } |
1200 | } |
1203 | } |
1201 | } |
1204 | 1202 | ||
1205 | void TChBoard::SetNoMove(TGraphDraw *drw, int force) |
1203 | void TChBoard::SetNoMove(TGraphDraw *drw, int force) |
1206 | { |
1204 | { |
1207 | if (!force && CurPoint.x < 0 && CurPoint.y < 0 && TheMove[0] == 0 && Eaten[0] == 0) |
1205 | if (!force && CurPoint.x < 0 && CurPoint.y < 0 && TheMove[0] == 0 && Eaten[0] == 0) |
1208 | { |
1206 | { |
1209 | return; |
1207 | return; |
1210 | } |
1208 | } |
1211 | CurPoint.x = -1; CurPoint.y = -1; |
1209 | CurPoint.x = -1; CurPoint.y = -1; |
1212 | MoveErase(); |
1210 | MoveErase(); |
1213 | if (drw && drw->IsDraw()) |
1211 | if (drw && drw->IsDraw()) |
1214 | { |
1212 | { |
1215 | drw->DrawClear(); |
1213 | drw->DrawClear(); |
1216 | Draw(drw); |
1214 | Draw(drw); |
1217 | } |
1215 | } |
1218 | } |
1216 | } |
1219 | 1217 | ||
1220 | int TChBoard::AutoMove(TGraphDraw *drw, int nmove, int draw_check) |
1218 | int TChBoard::AutoMove(TGraphDraw *drw, int nmove, int draw_check) |
1221 | { |
1219 | { |
1222 | if (game_end || IsPlayView) {SetNoMove(drw, 0); return 0;} |
1220 | if (game_end || IsPlayView) {SetNoMove(drw, 0); return 0;} |
1223 | if (CurMoveN < MainPlay.GetN() - 1) |
1221 | if (CurMoveN < MainPlay.GetN() - 1) |
1224 | { |
1222 | { |
1225 | CurMoveN = MainPlay.GetN() - 1; |
1223 | CurMoveN = MainPlay.GetN() - 1; |
1226 | RenewMPos(); |
1224 | RenewMPos(); |
1227 | SetNoMove(drw); |
1225 | SetNoMove(drw); |
1228 | return 2; |
1226 | return 2; |
1229 | } |
1227 | } |
1230 | if (!MainPos.AllCanEat() && !MainPos.AllCanMove()) |
1228 | if (!MainPos.AllCanEat() && !MainPos.AllCanMove()) |
1231 | { |
1229 | { |
1232 | game_end = 2 - MainPos.wmove; |
1230 | game_end = 2 - MainPos.wmove; |
1233 | ChangeTLT(drw, TLT_GameEnd); |
1231 | ChangeTLT(drw, TLT_GameEnd); |
1234 | if (!player[game_end - 1]) printf("Checkers: You win.\n"); |
1232 | if (!player[game_end - 1]) printf("Checkers: You win.\n"); |
1235 | else printf("Checkers: You lose.\n"); |
1233 | else printf("Checkers: You lose.\n"); |
1236 | SetNoMove(drw); |
1234 | SetNoMove(drw); |
1237 | return 3; |
1235 | return 3; |
1238 | } |
1236 | } |
1239 | else if (draw_check > 0 && MainPlay.IsDraw()) |
1237 | else if (draw_check > 0 && MainPlay.IsDraw()) |
1240 | { |
1238 | { |
1241 | game_end = 5; |
1239 | game_end = 5; |
1242 | ChangeTLT(drw, TLT_GameEnd); |
1240 | ChangeTLT(drw, TLT_GameEnd); |
1243 | printf("Checkers: Draw.\n"); |
1241 | printf("Checkers: Draw.\n"); |
1244 | SetNoMove(drw); |
1242 | SetNoMove(drw); |
1245 | return 3; |
1243 | return 3; |
1246 | } |
1244 | } |
1247 | if (!player[MainPos.wmove]) return 0; |
1245 | if (!player[MainPos.wmove]) return 0; |
1248 | TIntPoint CurP0 = CurPoint; |
1246 | TIntPoint CurP0 = CurPoint; |
1249 | if (CurPoint.x >= 0 && CurPoint.y >= 0) |
1247 | if (CurPoint.x >= 0 && CurPoint.y >= 0) |
1250 | { |
1248 | { |
1251 | if (drw) CurPointClear(drw); |
1249 | if (drw) CurPointClear(drw); |
1252 | CurPoint.x = -1; CurPoint.y = -1; |
1250 | CurPoint.x = -1; CurPoint.y = -1; |
1253 | } |
1251 | } |
1254 | MoveErase(); |
1252 | MoveErase(); |
1255 | int k; |
1253 | int k; |
1256 | for (k = 0; player[MainPos.wmove] && (k < nmove || nmove == 0); k++) |
1254 | for (k = 0; player[MainPos.wmove] && (k < nmove || nmove == 0); k++) |
1257 | { |
1255 | { |
1258 | TChPlayer::PMv pmv; |
1256 | TChPlayer::PMv pmv; |
1259 | pmv.pos = MainPos; |
1257 | pmv.pos = MainPos; |
1260 | Position::SetNullMv(pmv.mv); |
1258 | Position::SetNullMv(pmv.mv); |
1261 | MainPlay.GetMoveL(pmv.mv); |
1259 | MainPlay.GetMoveL(pmv.mv); |
1262 | text_line_type = TLT_Move; |
1260 | text_line_type = TLT_Move; |
1263 | if (!player[MainPos.wmove]->Move(pmv)) |
1261 | if (!player[MainPos.wmove]->Move(pmv)) |
1264 | { |
1262 | { |
1265 | text_line_type = TLT_PlDidntMove; |
1263 | text_line_type = TLT_PlDidntMove; |
1266 | game_end = 4 - MainPos.wmove; |
1264 | game_end = 4 - MainPos.wmove; |
1267 | break; |
1265 | break; |
1268 | } |
1266 | } |
1269 | if (MainPlay.Add(pmv.mv) != 0) |
1267 | if (MainPlay.Add(pmv.mv) != 0) |
1270 | { |
1268 | { |
1271 | text_line_type = TLT_PlWrongMove; |
1269 | text_line_type = TLT_PlWrongMove; |
1272 | game_end = 4 - MainPos.wmove; |
1270 | game_end = 4 - MainPos.wmove; |
1273 | break; |
1271 | break; |
1274 | } |
1272 | } |
1275 | CurMoveN = MainPlay.GetN() - 1; |
1273 | CurMoveN = MainPlay.GetN() - 1; |
1276 | MoveErase(); |
1274 | MoveErase(); |
1277 | RenewMPos(); |
1275 | RenewMPos(); |
1278 | PrintLMove(); |
1276 | PrintLMove(); |
1279 | if (!MainPos.AllCanEat() && !MainPos.AllCanMove()) |
1277 | if (!MainPos.AllCanEat() && !MainPos.AllCanMove()) |
1280 | { |
1278 | { |
1281 | game_end = 2 - MainPos.wmove; |
1279 | game_end = 2 - MainPos.wmove; |
1282 | text_line_type = TLT_GameEnd; |
1280 | text_line_type = TLT_GameEnd; |
1283 | if (!player[game_end - 1]) printf("Checkers: You win.\n"); |
1281 | if (!player[game_end - 1]) printf("Checkers: You win.\n"); |
1284 | else printf("Checkers: You lose.\n"); |
1282 | else printf("Checkers: You lose.\n"); |
1285 | break; |
1283 | break; |
1286 | } |
1284 | } |
1287 | else if (draw_check >= 0 && MainPlay.IsDraw()) |
1285 | else if (draw_check >= 0 && MainPlay.IsDraw()) |
1288 | { |
1286 | { |
1289 | game_end = 5; |
1287 | game_end = 5; |
1290 | text_line_type = TLT_GameEnd; |
1288 | text_line_type = TLT_GameEnd; |
1291 | printf("Checkers: Draw.\n"); |
1289 | printf("Checkers: Draw.\n"); |
1292 | break; |
1290 | break; |
1293 | } |
1291 | } |
1294 | } |
1292 | } |
1295 | if (!game_end) |
1293 | if (!game_end) |
1296 | { |
1294 | { |
1297 | text_line_type = TLT_Move; |
1295 | text_line_type = TLT_Move; |
1298 | CurPoint = CurP0; |
1296 | CurPoint = CurP0; |
1299 | } |
1297 | } |
1300 | if (drw && drw->IsDraw()) |
1298 | if (drw && drw->IsDraw()) |
1301 | { |
1299 | { |
1302 | drw->DrawClear(); |
1300 | drw->DrawClear(); |
1303 | Draw(drw); |
1301 | Draw(drw); |
1304 | } |
1302 | } |
1305 | return 1; |
1303 | return 1; |
1306 | } |
1304 | } |
1307 | 1305 | ||
1308 | void TChBoard::DrawTimer(TGraphDraw *drw, double t, int wh) const |
1306 | void TChBoard::DrawTimer(TGraphDraw *drw, double t, int wh) const |
1309 | { |
1307 | { |
1310 | if (!drw || !drw->IsDraw()) return; |
1308 | if (!drw || !drw->IsDraw()) return; |
1311 | if (wh) drw->SetColor(drw->GetWhiteColor()); |
1309 | if (wh) drw->SetColor(drw->GetWhiteColor()); |
1312 | else drw->SetColor(drw->GetBlackColor()); |
1310 | else drw->SetColor(drw->GetBlackColor()); |
1313 | double r1 = dw_delt * 0.4, r2 = dw_delt * 0.45; |
1311 | double r1 = dw_delt * 0.4, r2 = dw_delt * 0.45; |
1314 | double x = t * dw_cell * NW_CELL, y = -dw_delt / 2; |
1312 | double x = t * dw_cell * NW_CELL, y = -dw_delt / 2; |
1315 | if (MainPos.wmove == 1) |
1313 | if (MainPos.wmove == 1) |
1316 | { |
1314 | { |
1317 | x = dw_cell * NW_CELL - x; |
1315 | x = dw_cell * NW_CELL - x; |
1318 | y = dw_cell * NW_CELL - y; |
1316 | y = dw_cell * NW_CELL - y; |
1319 | } |
1317 | } |
1320 | LineB(drw, x - r1, y - r2, x + r2, y + r1); |
1318 | LineB(drw, x - r1, y - r2, x + r2, y + r1); |
1321 | LineB(drw, x - r2, y - r1, x + r1, y + r2); |
1319 | LineB(drw, x - r2, y - r1, x + r1, y + r2); |
1322 | LineB(drw, x - r1, y + r2, x + r2, y - r1); |
1320 | LineB(drw, x - r1, y + r2, x + r2, y - r1); |
1323 | LineB(drw, x - r2, y + r1, x + r1, y - r2); |
1321 | LineB(drw, x - r2, y + r1, x + r1, y - r2); |
1324 | if (wh) |
1322 | if (wh) |
1325 | { |
1323 | { |
1326 | int i, j, jj; |
1324 | int i, j, jj; |
1327 | drw->SetColor(drw->GetBlackColor()); |
1325 | drw->SetColor(drw->GetBlackColor()); |
1328 | for (i = -1; i <= NW_CELL; i++) |
1326 | for (i = -1; i <= NW_CELL; i++) |
1329 | { |
1327 | { |
1330 | double mval = dw_cell * NW_CELL + dw_delt; |
1328 | double mval = dw_cell * NW_CELL + dw_delt; |
1331 | double x0, x1, y; |
1329 | double x0, x1, y; |
1332 | if (i < 0) x0 = -dw_delt; |
1330 | if (i < 0) x0 = -dw_delt; |
1333 | else if (i > NW_CELL) x0 = mval; |
1331 | else if (i > NW_CELL) x0 = mval; |
1334 | else x0 = i * dw_cell; |
1332 | else x0 = i * dw_cell; |
1335 | if ((i+1) < 0) x1 = -dw_delt; |
1333 | if ((i+1) < 0) x1 = -dw_delt; |
1336 | else if ((i+1) > NW_CELL) x1 = mval; |
1334 | else if ((i+1) > NW_CELL) x1 = mval; |
1337 | else x1 = (i+1) * dw_cell; |
1335 | else x1 = (i+1) * dw_cell; |
1338 | if (fabs(x0 - x) < dw_delt || fabs(x1 - x) < dw_delt) |
1336 | if (fabs(x0 - x) < dw_delt || fabs(x1 - x) < dw_delt) |
1339 | { |
1337 | { |
1340 | for (jj = 0; jj <= 1; jj++) |
1338 | for (jj = 0; jj <= 1; jj++) |
1341 | { |
1339 | { |
1342 | if (MainPos.wmove == 1) j = NW_CELL + jj; |
1340 | if (MainPos.wmove == 1) j = NW_CELL + jj; |
1343 | else j = -jj; |
1341 | else j = -jj; |
1344 | if (j < 0 || j > NW_CELL || i >= 0 && i < NW_CELL) |
1342 | if (j < 0 || j > NW_CELL || i >= 0 && i < NW_CELL) |
1345 | { |
1343 | { |
1346 | if (j < 0) y = -dw_delt; |
1344 | if (j < 0) y = -dw_delt; |
1347 | else if (j > NW_CELL) y = mval; |
1345 | else if (j > NW_CELL) y = mval; |
1348 | else y = j * dw_cell; |
1346 | else y = j * dw_cell; |
1349 | LineB(drw, x0, y, x1, y); |
1347 | LineB(drw, x0, y, x1, y); |
1350 | } |
1348 | } |
1351 | } |
1349 | } |
1352 | } |
1350 | } |
1353 | } |
1351 | } |
1354 | } |
1352 | } |
1355 | } |
1353 | } |
1356 | 1354 | ||
1357 | int TChBoard::SetCurMoveN(int n, TGraphDraw *drw) |
1355 | int TChBoard::SetCurMoveN(int n, TGraphDraw *drw) |
1358 | { |
1356 | { |
1359 | int nmove = MainPlay.GetN() - 1; |
1357 | int nmove = MainPlay.GetN() - 1; |
1360 | if (n > nmove) n = nmove; |
1358 | if (n > nmove) n = nmove; |
1361 | if (n < 0) n = 0; |
1359 | if (n < 0) n = 0; |
1362 | if (CurMoveN != n) |
1360 | if (CurMoveN != n) |
1363 | { |
1361 | { |
1364 | CurMoveN = n; |
1362 | CurMoveN = n; |
1365 | RenewMPos(); |
1363 | RenewMPos(); |
1366 | if (n < nmove) |
1364 | if (n < nmove) |
1367 | { |
1365 | { |
1368 | MoveErase(); |
1366 | MoveErase(); |
1369 | CurPoint.x = -1; CurPoint.y = -1; |
1367 | CurPoint.x = -1; CurPoint.y = -1; |
1370 | } |
1368 | } |
1371 | text_line_type = GetSimpleTLT(); |
1369 | text_line_type = GetSimpleTLT(); |
1372 | if (drw && drw->IsDraw()) |
1370 | if (drw && drw->IsDraw()) |
1373 | { |
1371 | { |
1374 | drw->DrawClear(); |
1372 | drw->DrawClear(); |
1375 | Draw(drw); |
1373 | Draw(drw); |
1376 | } |
1374 | } |
1377 | return 1; |
1375 | return 1; |
1378 | } |
1376 | } |
1379 | else return 0; |
1377 | else return 0; |
1380 | } |
1378 | } |
1381 | 1379 | ||
1382 | int TChBoard::SetPlay(const PlayWrite &play) |
1380 | int TChBoard::SetPlay(const PlayWrite &play) |
1383 | { |
1381 | { |
1384 | if (play.GetN() <= 0) return 0; |
1382 | if (play.GetN() <= 0) return 0; |
1385 | MainPlay = play; |
1383 | MainPlay = play; |
1386 | MoveErase(); |
1384 | MoveErase(); |
1387 | CurPoint.x = -1; CurPoint.y = -1; |
1385 | CurPoint.x = -1; CurPoint.y = -1; |
1388 | CurMoveN = INT_MIN; |
1386 | CurMoveN = INT_MIN; |
1389 | SetCurMoveN(play.GetN()); |
1387 | SetCurMoveN(play.GetN()); |
1390 | if (!MainPos.AllCanEat() && !MainPos.AllCanMove()) game_end = 2 - MainPos.wmove; |
1388 | if (!MainPos.AllCanEat() && !MainPos.AllCanMove()) game_end = 2 - MainPos.wmove; |
1391 | else if (MainPlay.IsDraw()) game_end = 5; |
1389 | else if (MainPlay.IsDraw()) game_end = 5; |
1392 | else game_end = 0; |
1390 | else game_end = 0; |
1393 | text_line_type = GetSimpleTLT(); |
1391 | text_line_type = GetSimpleTLT(); |
1394 | IsPlayView = 1; |
1392 | IsPlayView = 1; |
1395 | EraseHistory(); |
1393 | EraseHistory(); |
1396 | return 1; |
1394 | return 1; |
1397 | } |
1395 | } |
1398 | 1396 | ||
1399 | void TChBoard::GoToCurMove() |
1397 | void TChBoard::GoToCurMove() |
1400 | { |
1398 | { |
1401 | if (!MainPos.AllCanEat() && !MainPos.AllCanMove() || |
1399 | if (!MainPos.AllCanEat() && !MainPos.AllCanMove() || |
1402 | MainPlay.IsDraw(CurMoveN + 1)) return; |
1400 | MainPlay.IsDraw(CurMoveN + 1)) return; |
1403 | MainPlay.ClearFrom(CurMoveN + 1); |
1401 | MainPlay.ClearFrom(CurMoveN + 1); |
1404 | MoveErase(); |
1402 | MoveErase(); |
1405 | game_end = 0; |
1403 | game_end = 0; |
1406 | text_line_type = GetSimpleTLT(); |
1404 | text_line_type = GetSimpleTLT(); |
1407 | IsPlayView = 0; |
1405 | IsPlayView = 0; |
1408 | } |
1406 | } |
1409 | 1407 | ||
1410 | #endif //_HEADER_BOARD_H=>>>>>>=>>>>>=>>>>>>>>>=>>>>>>>>>>>=>=>=>>>=>>=>>>>>>=>=>>>>>>=>=>=>>>>>>=>=>>=>=>>>>>>>>>>>>>> |
1408 | #endif //_HEADER_BOARD_H=>>>>>>=>>>>>=>>>>>>>>>=>>>>>>>>>>>=>=>=>>>=>>=>>>>>>=>=>>>>>>=>=>=>>>>>>=>=>>=>=>>>>>>>>>>>>>> |