kolibrios-fun/programs/games/checkers/trunk/position.h
CleverMouse fbdccce9a4 * gcc flags: add -march=pentium-mmx -fno-rtti
* menuetlibc: fix printf, sprintf
* menuetlibc: alias clock() to sysfn 26.9.
  Not exactly what is required by POSIX, but better than zero
* autobuild games/checkers

git-svn-id: svn://kolibrios.org@5123 a494cfbc-eb01-0410-851d-a64ba20cac60
2014-09-15 09:42:01 +00:00

881 lines
20 KiB
C++

#ifndef _HEADER_POSITION_H
#define _HEADER_POSITION_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define NELEM(a) (sizeof(a) / sizeof((a)[0]))
const int NW_CELL = 8;
const int NUM_CELL = NW_CELL * NW_CELL / 2;
const int LEN_WPOS = (NUM_CELL + 2) / 3;
inline int PoleCpos(int i, int j)
{
return (i + j) % 2 != 0;
}
inline int PoleToNum(int i, int j)
{
return j * (NW_CELL / 2) + i/2;
}
inline void NumToPole(int k, int &i, int &j)
{
j = k / (NW_CELL / 2);
i = k % (NW_CELL / 2);
i *= 2;
if (j % 2 == 0) i++;
}
class Position
{
public:
char SH[NUM_CELL];
char wmove;
Position() {Init();}
Position(const Position &p);
Position& operator=(const Position &p);
void Init();
int IsNull() const;
void Add(int np, char sh) {SH[np] = sh;}
void Del(int np) {SH[np] = 0;}
void Move(int np0, int np1) {if (np0 != np1) {SH[np1] = SH[np0]; SH[np0] = 0;}}
static int BecameD(int np, char ch);
enum {AWrong = -1, AWColor = -2, AfCell = -3, AnfCell = -4,
AMustEatMore = -5, AMustEat = -6, ANoMove = -7, AChBack = -8,
ANotDm = -9, AOnlyDiag = -10, AEatYour = -11, AMoreOne = -12,
ANotDmE = -13, AMustEatMoreD = -14, ATurnBack = -15};
int ScanSide(int x, int y, int sx, int sy, int sh_k = -1) const;
int CanEat(int k, int psx = 0, int psy = 0, int sh_k = -1) const;
int CanMove(int k) const;
int AChCell(int k);
int AMove(const unsigned char MV[], int k = -1, int &mkmove = *(int*)0);
int AllCanEat(int w = -1) const;
int AllCanMove(int w = -1) const;
char *Write(char WP[], int how = 0) const;
Position &Read(const char WP[], int how = 0);
static char *WriteMv(const unsigned char mv[], char WP[], int how = 0);
int WriteMvEx(const unsigned char mv[], char WP[], int how = 0) const;
static unsigned char *ReadMv(unsigned char mv[], const char WP[], int how = 0);
static int GetLenMv(const unsigned char mv[], int how = 0);
int GetLenMvEx(const unsigned char mv[], int how = 0) const;
static int GetLenMwr(const char WP[], int how = 0);
static void SetNullMv(unsigned char mv[]) {mv[0] = 0;}
void Reverse();
};
Position::Position(const Position &p) : wmove(p.wmove)
{
for(int i = 0; i < NUM_CELL; i++) SH[i] = p.SH[i];
}
Position& Position::operator=(const Position &p)
{
wmove = p.wmove;
for(int i = 0; i < NUM_CELL; i++) SH[i] = p.SH[i];
return *this;
}
void Position::Init()
{
wmove = 0;
for (int i = 0; i < NUM_CELL; i++) SH[i] = 0;
}
int Position::IsNull() const
{
for (int i = 0; i < NUM_CELL; i++) if (SH[i] != 0) return 0;
return 1;
}
inline int Position::BecameD(int np, char ch)
{
int x, y;
NumToPole(np, x, y);
return ch == 1 && y == NW_CELL - 1 || ch == 2 && y == 0;
}
char *Position::Write(char WP[], int how) const
{
if (how == 0)
{
int i = 0, j;
for (j = 0; i < NUM_CELL; j++)
{
WP[j] = SH[i++];
if (i < NUM_CELL) {WP[j] *= (char)5; WP[j] += SH[i++];}
if (i < NUM_CELL) {WP[j] *= (char)5; WP[j] += SH[i++];}
if (i >= NUM_CELL) {WP[j] *= (char)2; WP[j] += wmove;}
WP[j]++;
}
}
else if (how == 1)
{
int i;
for (i = NUM_CELL - 1; i >= 0; i--)
{
if (SH[i] < 0 || SH[i] >= 5) return 0;
}
for (i = 0; i < NUM_CELL; i++)
{
const char SYMBOL[5] = {'0', 'R', 'B', 'X', 'Z'};
WP[i] = SYMBOL[SH[NUM_CELL - 1 - i]];
}
WP[NUM_CELL] = ':';
WP[NUM_CELL + 1] = (wmove == 0) ? 'r' : 'b';
WP[NUM_CELL + 2] = 0;
}
return WP;
}
Position &Position::Read(const char WP[], int how)
{
if (how == 0)
{
int i = 0, j, ii;
for (j = 0; i < NUM_CELL; j++)
{
unsigned int cwp = WP[j] - 1;
if (i >= NUM_CELL - 3)
{
wmove = char(cwp % 2);
cwp /= 2;
ii = NUM_CELL - 1;
}
else ii = i + 2;
while(ii >= i) {SH[ii--] = char(cwp % 5); cwp /= 5;}
i += 3;
}
}
else if (how == 1)
{
int i;
wmove = 0;
for (i = 0; i < NUM_CELL; i++)
{
switch(WP[i])
{
case '0':
case '-': case '.':
case 'F': case 'f':
SH[NUM_CELL - 1 - i] = 0;
break;
case '1':
case 'A': case 'a':
case 'R': case 'r':
SH[NUM_CELL - 1 - i] = 1;
break;
case '2':
case 'B': case 'b':
case 'S': case 's':
SH[NUM_CELL - 1 - i] = 2;
break;
case '3':
case 'W': case 'w':
case 'X': case 'x':
SH[NUM_CELL - 1 - i] = 3;
break;
case '4':
case 'Y': case 'y':
case 'Z': case 'z':
SH[NUM_CELL - 1 - i] = 4;
break;
default:
Init();
return *this;
}
}
if (WP[NUM_CELL] == ':')
{
char c = WP[NUM_CELL + 1];
if (c == 'B' || c == 'b' || c == 'S' || c == 's' ||
c == 'Y' || c == 'y' || c == 'Z' || c == 'z')
{
wmove = 1;
}
}
}
return *this;
}
char *Position::WriteMv(const unsigned char mv[], char WP[], int how)
{
int i, nmv = 0;
if (mv) nmv = mv[0];
if (how == 0)
{
WP[0] = char(nmv + 1);
for (i = 1; i <= nmv; i++) WP[i] = char(mv[i] + 1);
}
else if (how == 1)
{
int j = 0;
for (i = 1; i <= nmv; i++)
{
int x, y;
NumToPole(mv[i], x, y);
WP[j++] = char('a' + NW_CELL - 1 - x);
int r = itoa(WP + j, 1 + y);
if (r > 0) j += r;
if (i != nmv) WP[j++] = '-';
}
WP[j] = 0;
}
return WP;
}
unsigned char *Position::ReadMv(unsigned char mv[], const char WP[], int how)
{
int i;
if (how == 0)
{
mv[0] = char(WP[0] - 1);
for (i = 1; i <= mv[0]; i++) mv[i] = char(WP[i] - 1);
}
else if (how == 1)
{
int j = 0, x = -1, y = -1;
mv[0] = 0;
for (;;)
{
if (isdigit(WP[j]))
{
y = atoi(WP + j) - 1;
while (isdigit(WP[j])) j++;
}
else if (islower(WP[j])) x = NW_CELL - 1 - (WP[j++] - 'a');
else
{
if (x >= 0 && y >= 0 && x < NW_CELL && y < NW_CELL)
{
mv[++mv[0]] = (char)PoleToNum(x, y);
}
else if (y >= 0 && y < NUM_CELL) mv[++mv[0]] = (char)(NUM_CELL - 1 - y);
x = -1; y = -1;
if (WP[j] == '-' || WP[j] == '*' || WP[j] == ':') j++;
else break;
}
if (x >= 0 && y >= 0 && x < NW_CELL && y < NW_CELL)
{
mv[++mv[0]] = (char)PoleToNum(x, y);
x = -1; y = -1;
}
}
}
return mv;
}
int Position::GetLenMv(const unsigned char mv[], int how)
{
if (how == 0) return mv ? (1 + mv[0]) : 1;
else if (how == 1)
{
int i, j = 0;
if (!mv) return 1;
for (i = 1; i <= mv[0]; i++)
{
int x, y;
NumToPole(mv[i], x, y);
j++; y++;
while(y > 0) {j++; y /= 10;}
if (i != mv[0]) j++;
}
return ++j;
}
else return 0;
}
int Position::GetLenMwr(const char WP[], int how)
{
if (how == 0) return (unsigned char)WP[0];
else if (how == 1)
{
int j;
for (j = 0; WP[j] == '-' || WP[j] == '*' ||
WP[j] == ':' || isdigit(j) || islower(j); j++);
return j + 1;
}
else return 0;
}
inline int Position::GetLenMvEx(const unsigned char mv[], int how) const
{
return WriteMvEx(mv, 0, how);
}
int Position::WriteMvEx(const unsigned char mv[], char WP[], int how) const
{
if (how == 11)
{
Position pos = *this;
int p, L = 0, was_d = 0;
for (p = 1; p <= mv[0]; p++)
{
if (!was_d && pos.SH[mv[p]] > 2)
{
if (WP) WP[L] = '*';
L++;
was_d = 1;
}
int x0, y0, x1, y1;
NumToPole(mv[p], x0, y0);
if (WP)
{
WP[L++] = char('a' + NW_CELL - 1 - x0);
int r = itoa(WP + L, 1 + y0);
if (r > 0) L += r;
}
else
{
L++;
int g = y0 + 1;
while(g > 0) {L++; g /= 10;}
}
if (p >= mv[0]) break;
NumToPole(mv[p+1], x1, y1);
int mi = abs(x1 - x0), i, eat = -1;
if (mi > 0 && mi == abs(y1 - y0))
{
int sx = (x1 > x0) ? 1 : -1;
int sy = (y1 > y0) ? 1 : -1;
for (i = 1; i < mi; i++)
{
int r = PoleToNum(x0 + i * sx, y0 + i * sy);
if (pos.SH[r] != 0)
{
eat = r;
pos.Del(r);
}
}
}
if (WP) WP[L] = (eat >= 0) ? ':' : '-';
L++;
if (pos.SH[mv[p]] == 1 && y1 == NW_CELL - 1) pos.SH[mv[p]] = 3;
else if (pos.SH[mv[p]] == 2 && y1 == 0) pos.SH[mv[p]] = 4;
pos.Move(mv[p], mv[p+1]);
}
if (WP) WP[L] = 0;
L++;
return L;
}
else
{
if (WP) WriteMv(mv, WP, how);
return GetLenMv(mv, how);
}
}
int Position::ScanSide(int x, int y, int sx, int sy, int sh_k) const
{
if (sh_k < 0) sh_k = SH[PoleToNum(x, y)];
if (sh_k < 1 || sh_k > 4) return -2;
if (sh_k >= 2) sh_k -= 2;
int i, i0, i1, f = 0, g = 0;
if (sx < 0) i0 = x;
else i0 = NW_CELL - x - 1;
if (sy < 0) i1 = y;
else i1 = NW_CELL - y - 1;
if (i0 > i1) i0 = i1;
for (i = 1; i <= i0; i++)
{
char nk = SH[PoleToNum(x + i*sx, y + i*sy)];
if (nk)
{
if (f || (nk != 3 - sh_k && nk != 5 - sh_k)) return g;
else f = 1;
}
else if (f) return (i == 2) ? 4 : (2 + g);
else if (i == 1) g = 1;
}
return g;
}
int Position::CanEat(int k, int psx, int psy, int sh_k) const
{
int x, y, sx, sy;
if (sh_k < 0) sh_k = SH[k];
if (sh_k < 1 || sh_k > 6) return 0;
NumToPole(k, x, y);
if (sh_k > 4)
{
int i, i0, i1, f = 0;
if (-psx < 0) i0 = x;
else i0 = NW_CELL - x - 1;
if (-psy < 0) i1 = y;
else i1 = NW_CELL - y - 1;
if (i0 > i1) i0 = i1;
for (i = 1; i <= i0; i++)
{
int nk = SH[PoleToNum(x - i*psx, y - i*psy)];
if (nk)
{
if (f || (nk != 7 - sh_k && nk != 9 - sh_k)) break;
else f = 1;
}
else
{
if (f) return 1;
if (ScanSide(x - i*psx, y - i*psy, psy, -psx, sh_k-2) >= 2) return 1;
if (ScanSide(x - i*psx, y - i*psy, -psy, psx, sh_k-2) >= 2) return 1;
}
}
}
else for (sx = -1; sx <= 1; sx += 2) if (x + 2*sx >= 0 && x + 2*sx < NW_CELL)
{
for (sy = -1; sy <= 1; sy += 2)
{
if ((sx != psx || sy != psy) && y + 2*sy >= 0 && y + 2*sy < NW_CELL)
{
if (sh_k <= 2)
{
if (SH[PoleToNum(x + 2*sx, y + 2*sy)] == 0)
{
int nk = SH[PoleToNum(x + sx, y + sy)];
if (nk == 3 - sh_k || nk == 5 - sh_k) return 1;
}
}
else if (ScanSide(x, y, sx, sy, sh_k) >= 2) return 1;
}
}
}
return 0;
}
int Position::CanMove(int k) const
{
int x, y, xx, yy, y1, y2;
NumToPole(k, x, y);
if (SH[k] == 1) y1 = y2 = y + 1;
else if (SH[k] == 2) y1 = y2 = y - 1;
else if (SH[k] != 3 && SH[k] != 4) return 0;
else {y1 = y - 1; y2 = y + 1;}
for (yy = y1; yy <= y2; yy += 2) if (yy >= 0 && yy < NW_CELL)
{
for (xx = x - 1; xx <= x + 1; xx += 2) if (xx >= 0 && xx < NW_CELL)
{
if (SH[PoleToNum(xx, yy)] == 0) return 1;
}
}
return 0;
}
int Position::AChCell(int k)
{
if (k < 0 || k >= NUM_CELL) return AWrong;
if (SH[k] == 0) return AfCell;
if (SH[k] != 1 + wmove && SH[k] != 3 + wmove) return AWColor;
if (CanEat(k)) return 1;
if (AllCanEat()) return AMustEat;
if (CanMove(k)) return 1;
return ANoMove;
}
int Position::AMove(const unsigned char MV[], int k, int &mkmove)
{
if (k >= NUM_CELL) return AWrong;
if (MV[0] <= 0)
{
if (k < 0) return NUM_CELL;
int s = AChCell(k);
if (s < 0) return s;
else return NUM_CELL;
}
if (MV[0] == 1 && k < 0)
{
int s = AChCell(MV[1]);
if (s < 0) return s;
else return NUM_CELL;
}
if (SH[MV[1]] == 0) return AfCell;
if (SH[MV[1]] != 1 + wmove && SH[MV[1]] != 3 + wmove) return AWColor;
int i, mi, p, MV_L, MV_N = MV[0], eat = -1, r;
int psx = 0, psy = 0;
if (k >= 0) MV_N++;
Position pos = *this;
for (p = 1; p < MV_N; p++)
{
int x0, y0, x1, y1, i_eat;
if (p < MV[0]) MV_L = MV[p+1];
else if (k < 0) break;
else MV_L = k;
if (pos.SH[MV_L] != 0) return AnfCell;
NumToPole(MV[p], x0, y0);
NumToPole(MV_L, x1, y1);
mi = abs(x1 - x0);
if (mi <= 0 || mi != abs(y1 - y0)) return AOnlyDiag;
int sx = (x1 > x0) ? 1 : -1;
int sy = (y1 > y0) ? 1 : -1;
if (sx == psx && sy == psy) return ATurnBack;
psx = -sx; psy = -sy;
eat = -1; i_eat = -1;
for (i = 1; i < mi; i++)
{
r = PoleToNum(x0 + i * sx, y0 + i * sy);
if (pos.SH[r] != 0)
{
if (eat >= 0) return AMoreOne;
if (pos.SH[r] != 2 - wmove && pos.SH[r] != 4 - wmove) return AEatYour;
eat = r; i_eat = i;
pos.Del(r);
}
}
if (eat >= 0)
{
if (pos.SH[MV[p]] <= 2 && mi != 2) return ANotDmE;
}
else
{
if (MV_N > 2) return AMustEatMore;
if (pos.SH[MV[p]] <= 2)
{
if (mi != 1) return ANotDm;
if (wmove == 0 && y1 < y0 || wmove == 1 && y1 > y0) return AChBack;
}
if (AllCanEat()) return AMustEat;
}
if (i_eat >= 0 && pos.SH[MV[p]] > 2)
{
if (!pos.CanEat(MV_L, psx, psy, pos.SH[MV[p]]))
{
if (pos.CanEat(PoleToNum(x0 + i_eat*sx, y0 + i_eat*sy),
psx, psy, pos.SH[MV[p]] + 2))
{
return AMustEatMoreD;
}
}
}
if (wmove == 0 && y1 == NW_CELL - 1) pos.SH[MV[p]] = 3;
else if (wmove == 1 && y1 == 0) pos.SH[MV[p]] = 4;
pos.Move(MV[p], MV_L);
}
if (&mkmove)
{
int end = MV_N > 1 && (eat < 0 || !pos.CanEat(MV_L, psx, psy));
if (mkmove == 1 && end)
{
*this = pos;
wmove = !wmove;
}
if (end) mkmove = 0;
else
{
if (MV_N > 1 && eat >= 0) mkmove = AMustEatMore;
else mkmove = AWrong;
}
}
if (k < 0 || eat < 0) eat = NUM_CELL;
return eat;
}
int Position::AllCanEat(int w) const
{
int k;
if (w < 0) w = wmove;
for (k = 0; k < NUM_CELL; k++)
{
if ((SH[k] == w+1 || SH[k] == w+3) && CanEat(k)) return 1;
}
return 0;
}
int Position::AllCanMove(int w) const
{
int k;
if (w < 0) w = wmove;
for (k = 0; k < NUM_CELL; k++)
{
if ((SH[k] == w+1 || SH[k] == w+3) && CanMove(k)) return 1;
}
return 0;
}
void Position::Reverse()
{
int i;
for (i = 0; i <= (NUM_CELL-1) / 2; i++)
{
int sh1 = SH[i], sh2 = SH[NUM_CELL - 1 - i];
if (sh1 == 1) sh1 = 2;
else if (sh1 == 2) sh1 = 1;
else if (sh1 == 3) sh1 = 4;
else if (sh1 == 4) sh1 = 3;
if (sh2 == 1) sh2 = 2;
else if (sh2 == 2) sh2 = 1;
else if (sh2 == 3) sh2 = 4;
else if (sh2 == 4) sh2 = 3;
SH[i] = (char)sh2; SH[NUM_CELL - 1 - i] = (char)sh1;
}
wmove = !wmove;
}
class PlayWrite
{
public:
PlayWrite() : play(0), mplay(0), nplay(0), start(0), mstart(0), nstart(0) {}
PlayWrite(const PlayWrite &pl) : play(0), mplay(0), nplay(0),
start(0), mstart(0), nstart(0) {(*this) = pl;}
~PlayWrite() {Clear();}
void Clear();
PlayWrite &operator=(const PlayWrite &pl);
int GetN() const {return nstart - 1;}
int GetLen() const {return nplay - sizeof(int);}
struct PMv
{
Position pos;
unsigned char mv[NUM_CELL];
};
void Add(const unsigned char move[], const Position &pos);
void Add(const PMv &pmv) {Add(pmv.mv, pmv.pos);}
int Add(const unsigned char move[]);
int GetMove(unsigned char move[], int k) const;
int GetPos(Position &pos, int k) const;
int GetPMv(PMv &pmv, int k) const;
int GetMoveL(unsigned char move[], int k = 0) const
{return GetMove(move, nstart - 2 - k);}
int GetPosL(Position &pos, int k = 0) const {return GetPos(pos, nstart - 2 - k);}
int GetPMvL(PMv &pmv, int k = 0) const {return GetPMv(pmv, nstart - 2 - k);}
int ClearFrom(int k = 0);
int IsDraw(int nmove = -1);
protected:
void IncPlay(int k);
void IncStart(int k);
void IncStart() {IncStart(nstart + 1);}
void AddStart() {IncStart(); start[nstart++] = nplay;}
void Split();
void SplitClear();
protected:
char *play;
int *start;
int mplay, nplay, mstart, nstart;
};
void PlayWrite::Clear()
{
if (play)
{
if ((*(int*)play) > 0) (*(int*)play)--;
else delete[] play;
}
play = 0; mplay = 0; nplay = 0;
if (start)
{
if (start[0] > 0) start[0]--;
else delete[] start;
}
start = 0; mstart = 0; nstart = 0;
}
void PlayWrite::Split()
{
if (play && (*(int*)play) > 0)
{
(*(int*)play)--;
char *play0 = play;
mplay = nplay;
play = new char[mplay];
memcpy(play, play0, nplay * sizeof(play[0]));
(*(int*)play) = 0;
}
if (start && start[0] > 0)
{
start[0]--;
int *start0 = start;
mstart = nstart;
start = new int[mstart];
memcpy(start, start0, nstart * sizeof(start[0]));
start[0] = 0;
}
}
void PlayWrite::SplitClear()
{
if (play && (*(int*)play) > 0)
{
(*(int*)play)--;
play = 0;
nplay = 0; mplay = 0;
}
if (start && start[0] > 0)
{
start[0]--;
start = 0;
nstart = 0; mstart = 0;
}
}
PlayWrite &PlayWrite::operator=(const PlayWrite &pl)
{
if (&pl != this)
{
play = pl.play;
(*(int*)play)++;
nplay = pl.nplay; mplay = pl.mplay;
start = pl.start;
start[0]++;
nstart = pl.nstart; mstart = pl.mstart;
}
return *this;
}
void PlayWrite::IncPlay(int k)
{
if (mplay < k)
{
int m0 = mplay;
char *play0 = play;
mplay = 2*k + 10;
play = new char[mplay];
memcpy(play, play0, m0 * sizeof(play[0]));
(*(int*)play) = 0;
if (play0)
{
if ((*(int*)play0) > 0) (*(int*)play0)--;
else delete[] play0;
}
}
}
void PlayWrite::IncStart(int k)
{
if (mstart < k)
{
int m0 = mstart;
int *start0 = start;
mstart = 2*k + 10;
start = new int[mstart];
memcpy(start, start0, m0 * sizeof(start[0]));
start[0] = 0;
if (start0)
{
if (start0[0] > 0) start0[0]--;
else delete[] start0;
}
}
}
void PlayWrite::Add(const unsigned char move[], const Position &pos)
{
Split();
int k = Position::GetLenMv(move);
if (nstart < 1) nstart = 1;
if (nplay < sizeof(int)) nplay = sizeof(int);
AddStart();
IncPlay(nplay + k + LEN_WPOS);
Position::WriteMv(move, play + nplay, 0);
nplay += k;
pos.Write(play + nplay, 0);
nplay += LEN_WPOS;
}
int PlayWrite::Add(const unsigned char move[])
{
if (nstart <= 1) return 1;
Position pos;
GetPosL(pos);
int mkmove = 1;
int res = pos.AMove(move, -1, mkmove);
if (res < 0) return res;
else if (mkmove != 0) return mkmove;
Add(move, pos);
return 0;
}
int PlayWrite::GetMove(unsigned char move[], int k) const
{
if (!play || !start) return -1;
k++;
if (k <= 0 || k >= nstart) return -1;
Position::ReadMv(move, play + start[k], 0);
return Position::GetLenMv(move);
}
int PlayWrite::GetPos(Position &pos, int k) const
{
if (!play || !start) return -1;
k++;
if (k <= 0 || k >= nstart) return -1;
int mlen = Position::GetLenMwr(play + start[k], 0);
pos.Read(play + start[k] + mlen, 0);
return LEN_WPOS;
}
int PlayWrite::GetPMv(PMv &pmv, int k) const
{
if (!play || !start) return -1;
k++;
if (k <= 0 || k >= nstart) return -1;
Position::ReadMv(pmv.mv, play + start[k], 0);
int mlen = Position::GetLenMv(pmv.mv);
pmv.pos.Read(play + start[k] + mlen, 0);
return mlen + LEN_WPOS;
}
int PlayWrite::ClearFrom(int k)
{
if (!play || !start) return 0;
k++;
if (k >= nstart) return 0;
if (k <= 1) {Clear(); return 2;}
nplay = start[k];
nstart = k;
return 1;
}
int PlayWrite::IsDraw(int nmove)
{
nmove++;
if (nmove <= 0 || nmove > nstart) nmove = nstart;
if (!start || nmove <= 3) return 0;
int i, j, k, draw = 0;
for (i = 1; i < nmove; i++)
{
k = 1;
char *p1 = play + start[i] + Position::GetLenMwr(play + start[i], 0);
for (j = 1; j < i; j++)
{
char *p2 = play + start[j] + Position::GetLenMwr(play + start[j], 0);
if (memcmp(p1, p2, LEN_WPOS) == 0) k++;
}
if (k >= 3) {draw = 1; break;}
}
return draw;
}
class TChPlayer
{
public:
TChPlayer() {}
typedef struct PlayWrite::PMv PMv;
virtual int PlayerID() {return 0;}
virtual int Move(PMv &pmv) = 0;
int Move(Position &pos, char mv[]);
};
int TChPlayer::Move(Position &pos, char mv[])
{
PMv pmv;
pmv.pos = pos; memcpy(pmv.mv, mv, sizeof(pmv.mv));
int res = Move(pmv);
pos = pmv.pos; memcpy(mv, pmv.mv, sizeof(pmv.mv));
return res;
}
#endif //_HEADER_POSITION_H