///////////////////////////////////////////////////////////////////////////////
// OthelloCore.cpp Ver. 1.6
// Programmer: PARK Youngho
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include <cstdlib>
#include <cassert>
#include <ctime>
#include "OthelloCore.h"
OthelloCore::OthelloCore (const char firstPlayer)
{
m_pMemento = new OthelloMemento(this);
assert(m_pMemento);
for (char i = 0; i < OTHELLO_WIDTH; i++)
C[i] = i+1;
#ifdef OTHELLO_RANDOM_SEED
srand(clock());
#endif
Initialize(firstPlayer);
}
OthelloCore::OthelloCore (int diag, const char firstPlayer)
{
m_pMemento = new OthelloMemento(this);
assert(m_pMemento);
for (char i = 0; i < OTHELLO_WIDTH; i++)
C[i] = i+1;
#ifdef OTHELLO_RANDOM_SEED
srand(clock());
#endif
Initialize(diag, firstPlayer);
}
OthelloCore::OthelloCore (OthelloCore* that)
{
assert(that);
memcpy((void*) m_Board, (void*) that->m_Board, sizeof m_Board);
memcpy(C, that->C, sizeof C);
m_Cur = that->m_Cur;
m_bOrder = that->m_bOrder;
m_First = that->m_First;
m_Diag = that->m_Diag;
m_pMemento = that->m_pMemento->Clone(this);
}
OthelloCore::~OthelloCore (void)
{
if (m_pMemento)
delete m_pMemento;
}
void OthelloCore::Initialize (int diag, const char firstPlayer)
{
m_First = firstPlayer;
m_Cur = 0;
InitBoard(diag);
InitPriority();
SwapIndex();
}
void OthelloCore::InitBoard (int diag)
{
memset((void*) m_Board, BLANK, sizeof m_Board);
m_bOrder = (m_First == PLAYER1);
m_Diag = (char) (diag % 8);
switch (m_Diag)
{
case 0:
case 6:
m_Board[OTHELLO_WIDTH / 2][OTHELLO_WIDTH / 2] = PLAYER2;
m_Board[OTHELLO_WIDTH / 2][OTHELLO_MARGIN / 2] = PLAYER1;
m_Board[OTHELLO_MARGIN / 2][OTHELLO_WIDTH / 2] = PLAYER1;
m_Board[OTHELLO_MARGIN / 2][OTHELLO_MARGIN / 2] = PLAYER2;
m_pMemento->Initialize(OTHELLO_WIDTH / 2, OTHELLO_MARGIN / 2,
OTHELLO_MARGIN / 2, OTHELLO_WIDTH / 2, PLAYER1);
m_pMemento->Initialize(OTHELLO_WIDTH / 2, OTHELLO_WIDTH / 2,
OTHELLO_MARGIN / 2, OTHELLO_MARGIN / 2, PLAYER2);
break;
case 1:
case 7:
m_Board[OTHELLO_WIDTH / 2][OTHELLO_WIDTH / 2] = PLAYER1;
m_Board[OTHELLO_WIDTH / 2][OTHELLO_MARGIN / 2] = PLAYER2;
m_Board[OTHELLO_MARGIN / 2][OTHELLO_WIDTH / 2] = PLAYER2;
m_Board[OTHELLO_MARGIN / 2][OTHELLO_MARGIN / 2] = PLAYER1;
m_pMemento->Initialize(OTHELLO_WIDTH / 2, OTHELLO_WIDTH / 2,
OTHELLO_MARGIN / 2, OTHELLO_MARGIN / 2, PLAYER1);
m_pMemento->Initialize(OTHELLO_WIDTH / 2, OTHELLO_MARGIN / 2,
OTHELLO_MARGIN / 2, OTHELLO_WIDTH / 2, PLAYER2);
break;
case 2:
m_Board[OTHELLO_WIDTH / 2][OTHELLO_WIDTH / 2] = PLAYER1;
m_Board[OTHELLO_WIDTH / 2][OTHELLO_MARGIN / 2] = PLAYER1;
m_Board[OTHELLO_MARGIN / 2][OTHELLO_WIDTH / 2] = PLAYER2;
m_Board[OTHELLO_MARGIN / 2][OTHELLO_MARGIN / 2] = PLAYER2;
m_pMemento->Initialize(OTHELLO_WIDTH / 2, OTHELLO_WIDTH / 2,
OTHELLO_WIDTH / 2, OTHELLO_MARGIN / 2, PLAYER1);
m_pMemento->Initialize(OTHELLO_MARGIN / 2, OTHELLO_WIDTH / 2,
OTHELLO_MARGIN / 2, OTHELLO_MARGIN / 2, PLAYER2);
break;
case 3:
m_Board[OTHELLO_WIDTH / 2][OTHELLO_WIDTH / 2] = PLAYER2;
m_Board[OTHELLO_WIDTH / 2][OTHELLO_MARGIN / 2] = PLAYER2;
m_Board[OTHELLO_MARGIN / 2][OTHELLO_WIDTH / 2] = PLAYER1;
m_Board[OTHELLO_MARGIN / 2][OTHELLO_MARGIN / 2] = PLAYER1;
m_pMemento->Initialize(OTHELLO_MARGIN / 2, OTHELLO_WIDTH / 2,
OTHELLO_MARGIN / 2, OTHELLO_MARGIN / 2, PLAYER1);
m_pMemento->Initialize(OTHELLO_WIDTH / 2, OTHELLO_WIDTH / 2,
OTHELLO_WIDTH / 2, OTHELLO_MARGIN / 2, PLAYER2);
break;
case 4:
m_Board[OTHELLO_WIDTH / 2][OTHELLO_WIDTH / 2] = PLAYER1;
m_Board[OTHELLO_WIDTH / 2][OTHELLO_MARGIN / 2] = PLAYER2;
m_Board[OTHELLO_MARGIN / 2][OTHELLO_WIDTH / 2] = PLAYER1;
m_Board[OTHELLO_MARGIN / 2][OTHELLO_MARGIN / 2] = PLAYER2;
m_pMemento->Initialize(OTHELLO_WIDTH / 2, OTHELLO_WIDTH / 2,
OTHELLO_MARGIN / 2, OTHELLO_WIDTH / 2, PLAYER1);
m_pMemento->Initialize(OTHELLO_WIDTH / 2, OTHELLO_MARGIN / 2,
OTHELLO_MARGIN / 2, OTHELLO_MARGIN / 2, PLAYER2);
break;
case 5:
m_Board[OTHELLO_WIDTH / 2][OTHELLO_WIDTH / 2] = PLAYER2;
m_Board[OTHELLO_WIDTH / 2][OTHELLO_MARGIN / 2] = PLAYER1;
m_Board[OTHELLO_MARGIN / 2][OTHELLO_WIDTH / 2] = PLAYER2;
m_Board[OTHELLO_MARGIN / 2][OTHELLO_MARGIN / 2] = PLAYER1;
m_pMemento->Initialize(OTHELLO_WIDTH / 2, OTHELLO_MARGIN / 2,
OTHELLO_MARGIN / 2, OTHELLO_MARGIN / 2, PLAYER1);
m_pMemento->Initialize(OTHELLO_WIDTH / 2, OTHELLO_WIDTH / 2,
OTHELLO_MARGIN / 2, OTHELLO_WIDTH / 2, PLAYER2);
break;
}
}
void OthelloCore::SwapIndex (void)
{
int v1, v2;
char temp;
for (int i = 0; i < OTHELLO_WIDTH + (OTHELLO_WIDTH / 2); i++)
{
v1 = rand() % OTHELLO_WIDTH;
v2 = rand() % OTHELLO_WIDTH;
temp = C[v1];
C[v1] = C[v2];
C[v2] = temp;
}
}
void OthelloCore::InitPriority (void)
{
}
int OthelloCore::Evaluate (int x, int y, const int player)
{
if ( (x < 1) || (x > OTHELLO_WIDTH)
|| (y < 1) || (y > OTHELLO_WIDTH)
|| (BLANK != m_Board[x][y]) )
return 0;
int ret = 0;
int opponent = (PLAYER1 == player) ? PLAYER2 : PLAYER1;
for (int dirx = -1; dirx <= 1; dirx++)
{
for (int diry = -1; diry <= 1; diry++)
{
int xx, yy, cnt;
for (xx = x + dirx, yy = y + diry, cnt = 0;
m_Board[xx][yy] == opponent;
cnt++, xx += dirx, yy += diry);
if ( cnt && (player == m_Board[xx][yy]) )
ret += cnt;
}
}
return ret;
}
bool OthelloCore::PutStone (int x, int y, const int player, bool bWithdraw)
{
if ( (x < 1) || (x > OTHELLO_WIDTH)
|| (y < 1) || (y > OTHELLO_WIDTH)
|| (BLANK != m_Board[x][y]) )
return false;
bool bPut = false;
int opponent = (PLAYER1 == player) ? PLAYER2 : PLAYER1;
for (int dirx = -1; dirx <= 1; dirx++)
{
for (int diry = -1; diry <= 1; diry++)
{
int xx, yy, cnt;
for (xx = x + dirx, yy = y + diry, cnt = 0;
m_Board[xx][yy] == opponent;
cnt++, xx += dirx, yy += diry);
if ( cnt && (player == m_Board[xx][yy]) )
{
bPut = true;
for (xx -= dirx, yy -= diry; cnt; cnt--, xx -= dirx, yy -= diry)
m_Board[xx][yy] = (char) player;
}
}
}
if (bPut)
{
m_Board[x][y] = (char) player;
m_bOrder = !m_bOrder;
Reorder(x, y);
if (!bWithdraw)
m_pMemento->Push(x, y, player);
m_Cur++;
}
return bPut;
}
bool OthelloCore::PutFirst (void)
{
if (WhoFirst() != PLAYER1)
return false;
int x, y;
if (SeekBestPoint (&x, &y, PLAYER1))
PutStone(x, y, PLAYER1);
return true;
}
bool OthelloCore::Withdraw (void)
{
if (1 >= m_Cur)
return false;
int cur = m_Cur - 2;
Initialize(m_Diag, m_First);
for (int i = 0; i < cur; i++)
{
int x, y, player;
m_pMemento->GetXY(i, &x, &y, &player);
PutStone(x, y, player, true);
}
return true;
}
bool OthelloCore::Restore (void)
{
if (m_pMemento->GetMax() <= m_Cur)
return false;
for (int i = 0; i < 2; i++)
{
int x, y, player;
m_pMemento->GetXY(m_Cur, &x, &y, &player);
PutStone(x, y, player, true);
}
return true;
}
char OthelloCore::GetBoard (int x, int y)
{
if ( (x > 0) && (x <= OTHELLO_WIDTH) && (y > 0) && (y <= OTHELLO_WIDTH) )
return m_Board[x][y];
return OUTOFBOARD;
}
int OthelloCore::WhoWin (int* pPlayer1, int* pPlayer2)
{
int cnt1 = 0, cnt2 = 0;
for (int x = 1; x <= OTHELLO_WIDTH; x++)
{
for (int y = 1; y <= OTHELLO_WIDTH; y++)
{
if (PLAYER1 == m_Board[x][y])
cnt1++;
else if (PLAYER2 == m_Board[x][y])
cnt2++;
}
}
if (pPlayer1)
*pPlayer1 = cnt1;
if (pPlayer2)
*pPlayer2 = cnt2;
if (cnt1 > cnt2)
return PLAYER1;
else if (cnt1 < cnt2)
return PLAYER2;
else // if (cnt1 == cnt2)
return BLANK;
}
bool OthelloCore::IsEnded (void)
{
if (60 <= m_Cur)
return true;
int player1, player2;
WhoWin(&player1, &player2);
return !(player1 && player2);
}
bool OthelloCore::Trace (int *px, int *py, int step)
{
return m_pMemento->GetXY(m_Cur + step - 1, px, py);
}
#ifdef OTHELLO_IQ_TEST
int OthelloCore::Compete (OthelloCore* pOthello1, OthelloCore* pOthello2,
int* pPlayer1, int* pPlayer2)
{
assert(pOthello1 && pOthello2);
if ( (pOthello1->m_Diag != pOthello2->m_Diag)
|| (PLAYER1 != pOthello1->m_First)
|| (PLAYER1 != pOthello2->m_First) )
return OUTOFBOARD;
int x, y;
do
{
if (pOthello1->SeekBestPoint(&x, &y, PLAYER1))
{
pOthello1->PutStone(x, y, PLAYER1);
pOthello2->PutStone(x, y, PLAYER1);
}
else if (m_pOthello1->IsEnded())
{
break;
}
else
{
m_pOthello1->Pass();
m_pOthello2->Pass();
}
if (pOthello2->SeekBestPoint(&x, &y, PLAYER2))
{
pOthello1->PutStone(x, y, PLAYER2);
pOthello2->PutStone(x, y, PLAYER2);
}
else if (m_pOthello2->IsEnded())
{
break;
}
else
{
m_pOthello1->Pass();
m_pOthello2->Pass();
}
} while (true);
return pOthello1->WhoWin(pPlayer1, pPlayer2);
}
void OthelloCore::Simulate (int step)
{
if (step < 0)
step = 60;
for (int i = 1; i <= step; i++)
{
int stone = WhoseTurn();
int x, y;
if (SeekBestPoint(&x, &y, stone))
PutStone(x, y, stone);
else if (IsEnded())
break;
else
Pass();
}
}
int OthelloCore::WhoAdvantageous (int* pPlayer1, int* pPlayer2)
{
return WhoWin(pPlayer1, pPlayer2);
}
#endif