Skip to content

Commit

Permalink
Utility function for distance to stones and GTP command to show distance
Browse files Browse the repository at this point in the history
git-svn-id: svn://svn.code.sf.net/p/fuego/code/trunk@2003 2e953b5c-c64d-0410-be54-f773e93e544c
  • Loading branch information
mmueller65 committed Aug 16, 2015
1 parent 2535474 commit a16d52f
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 26 deletions.
13 changes: 13 additions & 0 deletions go/GoGtpEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "GoBoardRestorer.h"
#include "GoEyeUtil.h"
#include "GoGtpCommandUtil.h"
#include "GoInfluence.h"
#include "GoModBoard.h"
#include "GoNodeUtil.h"
#include "GoPlayer.h"
Expand Down Expand Up @@ -111,6 +112,7 @@ GoGtpEngine::GoGtpEngine(int fixedBoardSize, const char* programPath,
Register("get_komi", &GoGtpEngine::CmdGetKomi, this);
Register("gg-undo", &GoGtpEngine::CmdGGUndo, this);
Register("go_board", &GoGtpEngine::CmdBoard, this);
Register("go_distance", &GoGtpEngine::CmdDistance, this);
Register("go_param", &GoGtpEngine::CmdParam, this);
Register("go_param_rules", &GoGtpEngine::CmdParamRules, this);
Register("go_player_board", &GoGtpEngine::CmdPlayerBoard, this);
Expand Down Expand Up @@ -336,6 +338,7 @@ void GoGtpEngine::CmdAnalyzeCommands(GtpCommand& cmd)
"sboard/Go Point Numbers/go_point_numbers\n"
"none/Go Rules/go_rules %s\n"
"plist/All Legal/all_legal %c\n"
"sboard/Go Distance/go_distance %c\n"
"string/ShowBoard/showboard\n"
"string/CpuTime/cputime\n"
"string/Get Komi/get_komi\n"
Expand Down Expand Up @@ -403,6 +406,16 @@ void GoGtpEngine::CmdClock(GtpCommand& cmd)
cmd << '\n' << m_game.Time();
}

void GoGtpEngine::CmdDistance(GtpCommand& cmd)
{
cmd.CheckNuArg(1);
SgBlackWhite color = GoGtpCommandUtil::BlackWhiteArg(cmd, 0);
SgPointArray<int> distance;
GoInfluence::FindDistanceToStones(Board(), color, distance);
cmd << '\n' << SgWritePointArray<int>(distance, Board().Size());
}


/** Compute final score.
Computes score only if GoRules::CaptureDead() == true.
Otherwise it returns an error. Override this function for players that
Expand Down
1 change: 1 addition & 0 deletions go/GoGtpEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class GoGtpEngine
virtual void CmdBoardSize(GtpCommand&);
virtual void CmdClearBoard(GtpCommand&);
virtual void CmdClock(GtpCommand&);
virtual void CmdDistance(GtpCommand& cmd);
virtual void CmdFinalScore(GtpCommand&);
virtual void CmdFixedHandicap(GtpCommand&);
virtual void CmdGameOver(GtpCommand&);
Expand Down
86 changes: 60 additions & 26 deletions go/GoInfluence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#include "SgSystem.h"
#include "GoInfluence.h"

#include <vector>
#include "SgNbIterator.h"
#include "SgPointset.h"

//----------------------------------------------------------------------------
namespace {
Expand All @@ -31,11 +33,65 @@ void Spread(const GoBoard& bd, SgPoint p, const SgPointSet& stopPts,
} // namespace
//----------------------------------------------------------------------------

void GoInfluence::ComputeInfluence(const GoBoard& bd,
const SgBWSet& stopPts,
SgBWArray<SgPointArray<int> >* influence)
{
const int MAX_INFLUENCE = 64;
for (SgBWIterator cit; cit; ++cit)
{
SgBlackWhite color = *cit;
((*influence)[color]).Fill(0);
for (GoBoard::Iterator it(bd); it; ++it)
{
SgPoint p(*it);
if (bd.IsColor(p, color))
Spread(bd, p, stopPts[color], MAX_INFLUENCE,
(*influence)[color]);
}
}
}

void GoInfluence::FindDistanceToStones(const GoBoard& bd,
SgBlackWhite color,
SgPointArray<int>& distance)
{
for (GoBoard::Iterator it(bd); it; ++it)
distance[*it] = DISTANCE_INFINITE;

std::vector<SgPoint> queue;
SgMarker marker;
for (SgSetIterator it(bd.All(color)); it; ++it)
{
queue.push_back(*it);
marker.Include(*it);
}

int d = 0;
while (! queue.empty())
{
std::vector<SgPoint> next;
for(std::vector<int>::const_iterator it = queue.begin(); it != queue.end(); ++it)
{
const SgPoint p = *it;
distance[p] = d;
for (GoNbIterator it2(bd, p); it2; ++it2)
{
const SgPoint nb = *it2;
if (marker.NewMark(nb) && bd.IsEmpty(nb))
next.push_back(nb);
}
}
++d;
queue.swap(next);
}
}

void GoInfluence::FindInfluence(const GoBoard& board,
int nuExpand,
int nuShrink,
SgBWSet* influence)
{
int nuExpand,
int nuShrink,
SgBWSet* influence)
{
SgBWSet result = SgBWSet(board.All(SG_BLACK), board.All(SG_WHITE));
SgBWSet next;
const int size = board.Size();
Expand Down Expand Up @@ -68,25 +124,3 @@ int GoInfluence::Influence(const GoBoard& board,
FindInfluence(board, nuExpand, nuShrink, &result);
return result[color].Size();
}


void GoInfluence::ComputeInfluence(const GoBoard& bd,
const SgBWSet& stopPts,
SgBWArray<SgPointArray<int> >* influence)
{
const int MAX_INFLUENCE = 64;
for (SgBWIterator cit; cit; ++cit)
{
SgBlackWhite color = *cit;
((*influence)[color]).Fill(0);
for (GoBoard::Iterator it(bd); it; ++it)
{
SgPoint p(*it);
if (bd.IsColor(p, color))
Spread(bd, p, stopPts[color], MAX_INFLUENCE,
(*influence)[color]);
}
}
}


8 changes: 8 additions & 0 deletions go/GoInfluence.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@

namespace GoInfluence {

const int DISTANCE_INFINITE = 99;

/** Find Manhattan distance to nearest stone of color. Does not
go through opponent stones. Set distance to DISTANCE_INFINITE if no stone
is reachable. */
void FindDistanceToStones(const GoBoard& board, SgBlackWhite color,
SgPointArray<int>& distance);

/** Compute influence by nuExpand expansions followed by nuShrink
contractions.
Starts from the player's stones.
Expand Down
63 changes: 63 additions & 0 deletions go/test/GoInfluenceTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//----------------------------------------------------------------------------
/** @file GoInfluenceTest.cpp
Unit tests for GoInfluence. */
//----------------------------------------------------------------------------

#include "SgSystem.h"

#include <boost/test/auto_unit_test.hpp>
#include "GoInfluence.h"

#include "GoSetupUtil.h"

using SgPointUtil::Pt;

//----------------------------------------------------------------------------

namespace {

//----------------------------------------------------------------------------

BOOST_AUTO_TEST_CASE(GoInfluenceTest_Distance_Black)
{
std::string s(". . . .\n"
". . . .\n"
". . X .\n"
". . . .\n");
int boardSize;
GoSetup setup = GoSetupUtil::CreateSetupFromString(s, boardSize);
GoBoard bd(boardSize, setup);
SgPointArray<int> distance;
GoInfluence::FindDistanceToStones(bd, SG_BLACK, distance);
BOOST_CHECK_EQUAL(distance[Pt(3, 2)], 0);
BOOST_CHECK_EQUAL(distance[Pt(2, 2)], 1);
BOOST_CHECK_EQUAL(distance[Pt(3, 1)], 1);
BOOST_CHECK_EQUAL(distance[Pt(3, 3)], 1);
BOOST_CHECK_EQUAL(distance[Pt(1, 3)], 3);
BOOST_CHECK_EQUAL(distance[Pt(1, 4)], 4);
BOOST_CHECK_EQUAL(distance[Pt(4, 3)], 2);
}

BOOST_AUTO_TEST_CASE(GoInfluenceTest_Distance_White)
{
std::string s(". . . .\n"
". . . .\n"
". . . .\n"
". . . O\n");
int boardSize;
GoSetup setup = GoSetupUtil::CreateSetupFromString(s, boardSize);
GoBoard bd(boardSize, setup);
SgPointArray<int> distance;
GoInfluence::FindDistanceToStones(bd, SG_WHITE, distance);
BOOST_CHECK_EQUAL(distance[Pt(4, 1)], 0);
BOOST_CHECK_EQUAL(distance[Pt(4, 2)], 1);
BOOST_CHECK_EQUAL(distance[Pt(3, 1)], 1);
BOOST_CHECK_EQUAL(distance[Pt(3, 2)], 2);
BOOST_CHECK_EQUAL(distance[Pt(1, 3)], 5);
BOOST_CHECK_EQUAL(distance[Pt(1, 4)], 6);
BOOST_CHECK_EQUAL(distance[Pt(4, 3)], 2);
}

//----------------------------------------------------------------------------

} // namespace

0 comments on commit a16d52f

Please sign in to comment.