Пример #1
0
//------------------------------------------------------------------------------
//-------------------------------MCTS Methods-----------------------------------
//------------------------------------------------------------------------------
void playRandomGame(Player p, Board &b) {
    int movesPlayed = 1;
    int i = 0;
    Move last = MOVE_PASS;

    // Regenerate the movelist up to 4 times
    while (movesPlayed > 0 && i < 4) {
        movesPlayed = 0;
        i++;
        MoveList legalMoves = b.getLegalMoves(p);
        int koCount = 0;

        // While we still have legal moves remaining
        while (legalMoves.size() > 0) {
            // Check if the last move put its own chain into atari
            // Do not do this twice in a row to prevent infinite ko recapture
            if (koCount == 0) {
                Move cap = b.getPotentialCapture(last);
                if (cap != MOVE_PASS) {
                    int ci = legalMoves.find(cap);
                    if (ci != -1)
                        legalMoves.removeFast(ci);
                    
                    b.doMove(p, cap);
                    last = cap;
                    p = otherPlayer(p);
                    movesPlayed++;
                    koCount++;
                    continue;
                }
            }

            // Otherwise, pick a move at random
            std::uniform_int_distribution<int> distribution(0, legalMoves.size()-1);
            int index = distribution(rng);
            Move m = legalMoves.get(index);

            // Only play moves that are not into own eyes and not suicides
            if (!b.isEye(p, m) && b.isMoveValid(p, m)) {
                b.doMove(p, m);
                last = m;
                p = otherPlayer(p);
                movesPlayed++;
                koCount = 0;
            }

            legalMoves.removeFast(index);
        }
    }
}
int UltimateTicTacToeMontecarloAI::expand(int leafIndex, Nodes& nodes, int const player) const
{
  Node& node = nodes[leafIndex];
  node.children.reserve(maxChildren);
  Moves options = movementOptions(node.board, node.previousMove);
  int turn = node.previousMove > 0 ? otherPlayer(node.board.grids.at(node.previousMove)) : player;

  int mostPromisingChildIndex = -1;
  int mostPromisingChildScore = 0;

  while(node.children.size() < maxChildren && !options.empty())
  {
    Move move = options.takeAt(qrand() % options.size());
    int childIndex = nodes.size();
    node.children.append(childIndex);
    Board newBoard(node.board);
    nodes.append( Node {0, 1, playMove(newBoard, move, turn), move, leafIndex, Node::Children()});
    int score = scoreBoard(nodes.last().board, player);
    if(score > mostPromisingChildScore || mostPromisingChildIndex < 0)
    {
      mostPromisingChildIndex = childIndex;
      mostPromisingChildScore = score;
    }
  }

  return mostPromisingChildIndex;
}
Пример #3
0
void nextMove(char player, char board[3][3]){
    int iboard[25];
    int i,j,move;
    pair best;
    initializeBoard(iboard, board);
    
    US = player;
    THEM = otherPlayer(US);

    timesCalled=0;
    //printboard(iboard); 
    best = chooseMoveAB(iboard,player,INT_MIN,INT_MAX);
    convert1dTo2d(best.move);
    printf("chooseMoveAB timesCalled: %d bestMove:%d\n", timesCalled,best.move);

    timesCalled=0;
    //printboard(iboard); 
    best = chooseMove(iboard,player);
    convert1dTo2d(best.move);
    printf("chooseMove timesCalled: %d bestMove:%d\n", timesCalled,best.move);

    timesCalled=0;
    //printboard(iboard); 
    best = chooseMoveEvaluate(iboard,player);
    convert1dTo2d(best.move);
    printf("chooseMoveEvaluate timesCalled: %d bestMove:%d\n", timesCalled,best.move);    

    timesCalled=0;
    //printboard(iboard); 
    best = chooseMoveABDepth(iboard,player,INT_MIN,INT_MAX);
    convert1dTo2d(best.move);
    printf("chooseMoveAB timesCalled: %d bestMove:%d\n", timesCalled,best.move);    

}
Пример #4
0
void PlayerJoinEvent::Execute(vector<PlayerThread*>& rvPlayers,PlayerPool* pPlayerPool) {
    if (rvPlayers.empty()) {
        return;
    }

    //Write join message to chat
    pPlayerPool->sendMessageToAll( _pSourcePlayer->getUsername() + " joined game" );
    EntityPlayer NewPlayer(_pSourcePlayer);

    for (int x=0; x<=rvPlayers.size()-1; x++) {
        if (!(rvPlayers[x]->isAssigned() && rvPlayers[x]->isSpawned())) {
            continue;   /* Not spawned */
        }
        if (rvPlayers[x] == _pSourcePlayer) {
            continue;   /* dont spawn yourself to yourself */
        }

        rvPlayers[x]->PlayerInfoList(true,_pSourcePlayer->getUsername()); /* spawn name to playerlist */

        if (MathHelper::distance2D(rvPlayers[x]->getCoordinates(),_pSourcePlayer->getCoordinates()) > 100.0) {
            continue;   /* You're too distant */
        }
        rvPlayers[x]->spawnEntity(&NewPlayer); /* Spawn entity */

        /* Spawn other players to new player */
        EntityPlayer otherPlayer(rvPlayers[x]);
        _pSourcePlayer->spawnEntity(&otherPlayer);
    }
}
Пример #5
0
bool Board::isMoveValid(Player p, Move m) {
    if (m == MOVE_PASS)
        return true;

    int x = getX(m);
    int y = getY(m);
    assert(pieces[index(x, y)] == EMPTY);

    // First check if the move makes a capture, since if so then
    // it cannot possibly be a suicide
    Player victim = otherPlayer(p);
    int eastID = (pieces[index(x+1, y)] == victim) * chainID[index(x+1, y)];
    int westID = (pieces[index(x-1, y)] == victim) * chainID[index(x-1, y)];
    int northID = (pieces[index(x, y+1)] == victim) * chainID[index(x, y+1)];
    int southID = (pieces[index(x, y-1)] == victim) * chainID[index(x, y-1)];

    if (eastID) {
        Chain *node = nullptr;
        searchChainsByID(node, eastID);
        if (node->liberties == 1)
            return true;
    }
    if (westID) {
        Chain *node = nullptr;
        searchChainsByID(node, westID);
        if (node->liberties == 1)
            return true;
    }
    if (northID) {
        Chain *node = nullptr;
        searchChainsByID(node, northID);
        if (node->liberties == 1)
            return true;
    }
    if (southID) {
        Chain *node = nullptr;
        searchChainsByID(node, southID);
        if (node->liberties == 1)
            return true;
    }

    if (isEye(victim, m))
        return false;

    pieces[index(x, y)] = p;

    // Suicides are illegal
    if (pieces[index(x+1, y)] && pieces[index(x-1, y)]
     && pieces[index(x, y+1)] && pieces[index(x, y-1)]) {
        if (doCaptures<false>(p, coordToMove(x, y))) {
            pieces[index(x, y)] = EMPTY;
            return false;
        }
    }

    pieces[index(x, y)] = EMPTY;
    return true;
}
Пример #6
0
void testApp::fire(int player) {
	Player& me = players[player];
	//cout << "players (0: " << players[0].life << "," << players[0].lastId << "," << players[0].position << ")" << endl;
	//cout << "players (1: " << players[1].life << "," << players[1].lastId << "," << players[1].position << ")" << endl;
	if(me.life > 0) {
		Player& you = players[otherPlayer(player)];
		ofVec2f position = me.position;
		ofVec2f velocity = you.position - me.position;
		projectiles.push_back(Projectile(player, position, velocity));
	}
}
int UltimateTicTacToeMontecarloAI::simulate(Board board, int const previousMove, int const player) const
{
  int turn = previousMove > 0 ? otherPlayer(board.grids.at(previousMove)) : player;
  GameState state = gameState(board, player);
  Move prev = previousMove;
  while(state == GameState::UNRESOLVED)
  {
    Moves options = movementOptions(board, prev);
    Move option = options.at(qrand() % options.size());
    playMove(board, option, turn);
    turn = otherPlayer(turn);
    state = gameState(board, player);
    prev = option;
  }

  switch(state)
  {
    case GameState::WIN: return 1;
    case GameState::LOSE: return -1;
    default: return 0;
  }
}
Пример #8
0
void scoreGame(Player p, Board &b, float &myScore, float &oppScore) {
    int whiteTerritory = 0, blackTerritory = 0;
    b.countTerritory(whiteTerritory, blackTerritory);

    myScore = b.getCapturedStones(p)
        + ((p == BLACK) ? blackTerritory : whiteTerritory);
    oppScore = b.getCapturedStones(otherPlayer(p))
        + ((p == BLACK) ? whiteTerritory : blackTerritory);

    if (p == WHITE)
        myScore += komi;
    else
        oppScore += komi;
}
Пример #9
0
int testApp::getId(int realid) {
	// converts realid to 0 or 1
	int id;
	bool exists = false;
	for(int i = 0; i < players.size(); i++) {
		if(players[i].lastId == realid) {
			id = i;
			exists = true;
		}
	}
	if(!exists) {
		id = curPlayer;
		players[id].lastId = realid;
		curPlayer = otherPlayer(curPlayer);
	}
	return id;
}
Пример #10
0
GameState& GameState::move(Direction direction)
{
	lastMoveCode_ = getMoveCode(direction);
	
	getField_(currentPosition_).setOccupied_(direction);
	currentPosition_ = currentPosition_.getNeighbor(direction);
	getField_(currentPosition_).setOccupied_(reverseDirection(direction));
	
	if(!canRebound() && !isBlocked())
	{
		currentPlayer_ = otherPlayer(currentPlayer_);
		
		if(currentPlayer_ == PLAYER_1)
			++turnNumber_;
	}
	
	++moveNumber_;
	
	return *this;
}
Пример #11
0
GameState& GameState::undo(Direction direction)
{
	lastMoveCode_ = -1;
	
	if(!canRebound() && !isBlocked())
	{
		if(currentPlayer_ == PLAYER_1)
			--turnNumber_;
		
		currentPlayer_ = otherPlayer(currentPlayer_);
	}
	
	direction = reverseDirection(direction);
	getField_(currentPosition_).setOccupied_(direction, false);
	currentPosition_ = currentPosition_.getNeighbor(direction);
	getField_(currentPosition_).setOccupied_(reverseDirection(direction), false);
	
	--moveNumber_;
	
	return *this;
}
UltimateTicTacToeMontecarloAI::GameState UltimateTicTacToeMontecarloAI::gameState(Board const& board, int player) const
{
  int winner = gridWinner(board.bigGrid);

  if(winner == player)
  {
    return GameState::WIN;
  }
  else if(winner == otherPlayer(player))
  {
    return GameState::LOSE;
  }
  else if(boardFull(board))
  {
    return GameState::TIE;
  }
  else
  {
    return GameState::UNRESOLVED;
  }
}
Пример #13
0
void PlayerMoveEvent::Execute(vector<PlayerThread*>& rvPlayers,PlayerPool* pPlayerPool) {
    if (rvPlayers.empty()) {
        return;
    }

    EntityPlayer Player(_pSourcePlayer);

    for (int x=0; x<=rvPlayers.size()-1; x++) {
        if (!(rvPlayers[x]->isAssigned() && rvPlayers[x]->isSpawned())) {
            continue;   /* not spawned */
        }
        if (rvPlayers[x] == _pSourcePlayer) {
            continue;   /* filter yourself */
        }

        if (MathHelper::distance2D(rvPlayers[x]->getCoordinates(),_newCoordinates) > FC_PLAYERSPAWNRADIUS) { /* Too distant from other player*/
            if (rvPlayers[x]->isEntitySpawned(_pSourcePlayer->getEntityID())) { /* despawn me*/
                rvPlayers[x]->despawnEntity(_pSourcePlayer->getEntityID());
            }
            continue;
        } else { /* Spawn other players into my view circle */
            if (!_pSourcePlayer->isEntitySpawned(rvPlayers[x]->getEntityID())) { /* other is not spawned to me */
                EntityPlayer otherPlayer(rvPlayers[x]);
                _pSourcePlayer->spawnEntity(&otherPlayer);
                continue;
            }
        }

        /* Update my position to other players  */
        if (!rvPlayers[x]->isEntitySpawned(_pSourcePlayer->getEntityID())) { /* if I'm not spawned -> spawn me */
            rvPlayers[x]->spawnEntity(&Player);
        } else { //Already spawned -> update position
            rvPlayers[x]->updateEntityPosition(&Player);
        }
    }
}
Пример #14
0
/*
 * Updates the board with a move. Assumes that the move is legal.
 */
void Board::doMove(Player p, Move m) {
    if (m == MOVE_PASS)
        return;

    int x = getX(m);
    int y = getY(m);

    assert(pieces[index(x, y)] == EMPTY);
    assert(chainID[index(x, y)] == 0);
    
    pieces[index(x, y)] = p;
    zobristKey ^= zobristTable[zobristIndex(p, x, y)];

    Player victim = otherPlayer(p);

    Stone east = pieces[index(x+1, y)];
    Stone west = pieces[index(x-1, y)];
    Stone north = pieces[index(x, y+1)];
    Stone south = pieces[index(x, y-1)];
    int connectionCount = (east == p) + (west == p) + (north == p) + (south == p);

    // If the stone placed is a new chain
    if (connectionCount == 0) {
        // Record which chain this square is a part of
        chainID[index(x, y)] = nextID;

        // Add this chain to the list of chains
        Chain *cargo = new Chain(p, nextID);
        cargo->add(m);
        cargo->liberties = 0;
        if (east == EMPTY)
            cargo->addLiberty(coordToMove(x+1, y));
        if (west == EMPTY)
            cargo->addLiberty(coordToMove(x-1, y));
        if (north == EMPTY)
            cargo->addLiberty(coordToMove(x, y+1));
        if (south == EMPTY)
            cargo->addLiberty(coordToMove(x, y-1));

        chainList.add(cargo);

        nextID++;
    }

    // If the stone placed is added to an existing chain
    else if (connectionCount == 1) {
        // Find the ID of the chain we are adding this stone to
        int thisID;
        if (east == p)
            thisID = chainID[index(x+1, y)];
        else if (west == p)
            thisID = chainID[index(x-1, y)];
        else if (north == p)
            thisID = chainID[index(x, y+1)];
        else
            thisID = chainID[index(x, y-1)];

        chainID[index(x, y)] = thisID;
        Chain *node = nullptr;
        searchChainsByID(node, thisID);
        node->add(m);

        // The new stone occupies a previous liberty, but adds on however many
        // liberties it itself has
        node->removeLiberty(node->findLiberty(m));
        updateLiberty(node, x, y);
    }

    // If the stone possibly connects two existing chains
    else {
        int eastID = (east == p) * chainID[index(x+1, y)];
        int westID = (west == p) * chainID[index(x-1, y)];
        int northID = (north == p) * chainID[index(x, y+1)];
        int southID = (south == p) * chainID[index(x, y-1)];
        Chain *node = nullptr;
        bool added = false;

        if (eastID) {
            chainID[index(x, y)] = eastID;
            searchChainsByID(node, eastID);

            node->add(m);
            node->removeLiberty(node->findLiberty(m));
            updateLiberty(node, x, y);
            added = true;
        }

        if (westID) {
            if (added) {
                // If two stones from the same chain are adjacent, do nothing
                // If they are from different chains, we need to combine...
                if (westID != eastID)
                    mergeChains(node, westID, m);
            }
            else {
                chainID[index(x, y)] = westID;
                searchChainsByID(node, westID);

                node->add(m);
                node->removeLiberty(node->findLiberty(m));
                updateLiberty(node, x, y);
                added = true;
            }
        }

        if (northID) {
            if (added) {
                if (northID != eastID && northID != westID)
                    mergeChains(node, northID, m);
            }
            else {
                chainID[index(x, y)] = northID;
                searchChainsByID(node, northID);

                node->add(m);
                node->removeLiberty(node->findLiberty(m));
                updateLiberty(node, x, y);
                added = true;
            }
        }

        if (southID) {
            if (added) {
                if (southID != eastID && southID != westID && southID != northID)
                    mergeChains(node, southID, m);
            }
            else {
                chainID[index(x, y)] = southID;
                searchChainsByID(node, southID);

                node->add(m);
                node->removeLiberty(node->findLiberty(m));
                updateLiberty(node, x, y);
                added = true;
            }
        }
    }


    // Update opponent liberties
    int eastID = (east == victim) * chainID[index(x+1, y)];
    int westID = (west == victim) * chainID[index(x-1, y)];
    int northID = (north == victim) * chainID[index(x, y+1)];
    int southID = (south == victim) * chainID[index(x, y-1)];

    if (eastID) {
        Chain *node = nullptr;
        int nodeIndex = searchChainsByID(node, eastID);
        node->removeLiberty(node->findLiberty(m));

        if (node->liberties == 0)
            captureChain(node, nodeIndex);
    }

    if (westID && westID != eastID) {
        Chain *node = nullptr;
        int nodeIndex = searchChainsByID(node, westID);
        node->removeLiberty(node->findLiberty(m));

        if (node->liberties == 0)
            captureChain(node, nodeIndex);
    }

    if (northID && northID != eastID && northID != westID) {
        Chain *node = nullptr;
        int nodeIndex = searchChainsByID(node, northID);
        node->removeLiberty(node->findLiberty(m));

        if (node->liberties == 0)
            captureChain(node, nodeIndex);
    }

    if (southID && southID != eastID && southID != westID && southID != northID) {
        Chain *node = nullptr;
        int nodeIndex = searchChainsByID(node, southID);
        node->removeLiberty(node->findLiberty(m));

        if (node->liberties == 0)
            captureChain(node, nodeIndex);
    }

    // Check for a suicide
    int selfID = chainID[index(x, y)];
    Chain *node = nullptr;
    int nodeIndex = searchChainsByID(node, selfID);

    if (node->liberties == 0)
        captureChain(node, nodeIndex);


    // A debugging check
    assert(!checkChains());

    // Check if p captured any of the other player's stones with move m
    /*
    doCaptures<true>(victim, coordToMove(x+1, y));
    doCaptures<true>(victim, coordToMove(x-1, y));
    doCaptures<true>(victim, coordToMove(x, y+1));
    doCaptures<true>(victim, coordToMove(x, y-1));

    // Check if p suicided with move m
    doCaptures<true>(p, coordToMove(x, y));
    */
}
Пример #15
0
Player GameState::whoWon() const
{
	return currentPosition_.y == height_ / 2 ? PLAYER_1 :
		   currentPosition_.y == -height_ / 2 ? PLAYER_2 :
		   isBlocked() ? otherPlayer(currentPlayer_) : NO_PLAYER;
}
Пример #16
0
pair chooseMoveEvaluate (int* iboard, int player) {
    ASSERT(player == XPL || player == OPL);
    
    pair myBest = {0,-1};
    pair reply;
    int i, move;
    int moveCount=0, moveList[9];

    //default score
    if(player == US){
        myBest.score = INT_MIN;
    } else {
        myBest.score = INT_MAX;
    }

    timesCalled++;
    pair temp;
    temp.score = 0;
    temp.move = -1;    
    if(didHeWin(iboard,US)) {
        //printf("%c WON\n",US);
        //printf("=====returning{1}====================\n");
        //printboard(iboard);
        //temp.score = 10+timesCalled;
        temp.score = evaluateBoard(iboard);
        return temp;
    } else if(didHeWin(iboard,THEM)) {
        //printf("%c WON\n",THEM);
        //printf("=====returning{-1}====================\n");
        //printboard(iboard);
        //temp.score = -10-timesCalled;
        temp.score = evaluateBoard(iboard);        
        return temp;
    } else if(isBoardFull(iboard)) {
        //printf("FULL\n");
        //printf("=====returning{0}====================\n");
        //temp.score = 0;
        return temp;
    }
    
    // get legal moves
    for(i = 0; i < 9; i++) {
        if( iboard[convert9To25[cellScoreOrdered[i]]] == EMPTY) {
            moveList[moveCount++] = convert9To25[cellScoreOrdered[i]];
        }
    }

    // for(i = 0; i < 9; i++) {
    //     if( iboard[convert9To25[i]] == EMPTY) {
    //         moveList[moveCount++] = convert9To25[i];
    //     }
    // }

    // any legal move
    //myBest.move = pickValuedMove(moveList,moveCount);
    //printf("Move by %c;*********************************************\n",player);
    //for(i=0; i < moveCount; i++) {
        //printf("%d ", moveList[i]);
    //}
    //printf("\n");
    for(i=0; i < moveCount; i++) {
        move = moveList[i];
        iboard[move] = player;
        //printf("%c(to move(%d/%d) %d);best:%d ;reply:%d \n", 
        //    player,i+1,moveCount,move,myBest.score,reply.score);
        //printboard(iboard);
        reply = chooseMove(iboard, otherPlayer(player));
        iboard[move] = EMPTY;
        //printf("RESET %c(to move(%d/%d) %d);best:%d ;reply:%d \n", 
        //    player,i+1,moveCount,move,myBest.score,reply.score);
        if( // maximizinf by selecting opponents less score
            (player == US && myBest.score < reply.score) ||
            // minimizing by letting them select high score
            (player == THEM && myBest.score > reply.score)){
        //    printf("%c SCORE CHANGED (score:%d, best move:%d)!!\n",
        //        player,reply.score,move);
            myBest.score = reply.score;
            myBest.move = move;
        }
    }
    return myBest;
}
Пример #17
0
GameResult RunAIGame::play(Depth depth, BoardWidth size, RulesType rules, bool contenderFirst)
{
	for (int i=0; i<=1; i++)
	{
		PenteGame *p = _players[i];
		p->restartGame();
		p->setColour(i+1);
		p->setNormalDepth(depth);
		p->setBoardSize(size);
		p->setRules(rules);
	}

	int toMove = P1;

	AlphaBeta ab_games[2] = {
		AlphaBeta(*_players[0]),
		AlphaBeta(*_players[1])
	};

	GameResult res = GameResult();
	res._depth = std::to_string((int)depth);
	res._size = std::to_string((int)size);
	res._rules = rules;
	res._contenderP = (contenderFirst ? "P1" : "P2");

	Colour winner = EMPTY;

	while (winner == EMPTY)
	{
		Timer tmr;
		Loc bestMove = ab_games[toMove-1].getBestMove();
		if (!_silent) {
			std::cout << bestMove << std::endl;
		}
		res._times[toMove-1] += tmr.elapsed();
		assert(_players[0]->isLegalMove(bestMove));

		_players[0]->makeMove(bestMove, toMove);
		_players[1]->makeMove(bestMove, toMove);

		toMove = otherPlayer(toMove);
		winner = _players[1]->getWonBy();
		if (!_silent) {
			// TODO: Use another flag for games
			_players[0]->print();

#if 0
			const PriorityLevel &p1Threes
				= _players[0]->_posStats.getPriorityLevel(P1, Line3);
			const PriorityLevel &p2Threes
				= _players[0]->_posStats.getPriorityLevel(P2, Line3);
			const PriorityLevel &p1Fours
				= _players[0]->_posStats.getPriorityLevel(P1, Line4);
			const PriorityLevel &p2Fours
				= _players[0]->_posStats.getPriorityLevel(P2, Line4);

			cout << "P1 3s: " << p1Threes.getNumCands()
				 << "; P2 3s: " << p2Threes.getNumCands()
				 << "; P1 4s: " << p1Fours.getNumCands()
				 << "; P2 4s: " << p2Fours.getNumCands() << endl;
#endif
		}
	}
	res._winnerWasContender = ((winner==P2) xor contenderFirst);

	return res;
}
Пример #18
0
Move generateMove(Player p, Move lastMove) {
    MoveList legalMoves = game.getLegalMoves(p);
    MoveList localMoves = game.getLocalMoves(lastMove);

    // Pass if every move is either into your own eye, a suicide, or places
    // a chain into atari
    bool playPass = true;
    for (unsigned int n = 0; n < legalMoves.size(); n++) {
        Board copy = Board(game);
        Move m = legalMoves.get(n);

        if (!copy.isMoveValid(otherPlayer(p), m) && copy.isEye(p, m))
            continue;

        if (!copy.isMoveValid(p, m))
            continue;

        copy.doMove(p, m);
        if (copy.isInAtari(m))
            continue;

        playPass = false;
        break;
    }

    if (playPass)
        return MOVE_PASS;


    MCTree searchTree;
    float komiAdjustment = 0.0;
    Move captureLastStone = game.getPotentialCapture(lastMove);
    Move potentialEscape = game.getPotentialEscape(p, lastMove);

    // Add all first-level moves
    for (unsigned int n = 0; n < legalMoves.size(); n++) {
        Board copy = Board(game);
        Player genPlayer = p;

        Move next = legalMoves.get(n);
        // Check legality of moves (suicide)
        if (!copy.isMoveValid(genPlayer, next))
            continue;

        copy.doMove(genPlayer, next);
        // Never place own chain in atari
        if (copy.isInAtari(next))
            continue;

        // Check for ko rule violation
        bool koViolation = false;
        if (next != MOVE_PASS) {
            uint64_t newKey = copy.getZobristKey();
            for (int i = keyStackSize-1; i >= 0; i--) {
                if (newKey == keyStack[i]) {
                    koViolation = true;
                    break;
                }
            }
        }
        if (koViolation)
            continue;

        // First level moves are added to the root
        MCNode *leaf = searchTree.root;
        MCNode *addition = new MCNode();
        addition->parent = leaf;
        addition->m = next;

        // Play out a random game. The final board state will be stored in copy.
        playRandomGame(otherPlayer(genPlayer), copy);

        // Score the game
        float myScore = 0.0, oppScore = 0.0;
        scoreGame(genPlayer, copy, myScore, oppScore);
        if (myScore > oppScore)
            addition->numerator++;
        addition->scoreDiff = ((int) myScore) - ((int) oppScore);
        komiAdjustment += myScore - oppScore;

        // Add the new node to the tree
        leaf->children[leaf->size] = addition;
        leaf->size++;

        // Backpropagate the results
        searchTree.backPropagate(addition);

        // Do priors, if any
        // Own eye and opening priors inspired by Pachi,
        // written by Petr Baudis and Jean-loup Gailly
        int basePrior = boardSize * boardSize / 8;
        // Discourage playing into own eyes
        if (game.isEye(genPlayer, next)) {
            addition->denominator += basePrior;
            // If this eye is not ko-related we almost certainly should not play
            // in it
            if (!game.isMoveValid(otherPlayer(genPlayer), next)) {
                addition->denominator += 10 * basePrior;
                addition->scoreDiff -= 10 * 360;
            }
        }

        // Discourage playing onto edges and encourage playing onto the 4th line
        // in 13x13 and 19x19 openings
        unsigned int openingMoves = boardSize * boardSize - boardSize;
        if ((boardSize == 13 || boardSize == 19) && legalMoves.size() > openingMoves) {
            int x = getX(next);
            int y = getY(next);
            if (x == 1 || x == 19 || y == 1 || y == 19) {
                addition->denominator += 2 * basePrior;
            }
            else {
                int taperedPrior = basePrior * (legalMoves.size() - openingMoves) / boardSize;
                if (x == 4 || x == boardSize-3) {
                    addition->numerator += 2 * taperedPrior;
                    addition->denominator += 2 * taperedPrior;
                }
                if (y == 4 || y == boardSize-3) {
                    addition->numerator += 2 * taperedPrior;
                    addition->denominator += 2 * taperedPrior;
                }
                if (x == 3 || x == boardSize-2 || y == 3 || y == boardSize-2) {
                    addition->numerator += taperedPrior;
                    addition->denominator += taperedPrior;
                }
            }
        }
        // And the same for 9x9
        else if (boardSize == 9 && legalMoves.size() > openingMoves) {
            int x = getX(next);
            int y = getY(next);
            if (x == 1 || x == boardSize || y == 1 || y == boardSize) {
                addition->denominator += 2 * basePrior;
            }
            else {
                int taperedPrior = basePrior * (legalMoves.size() - openingMoves) / boardSize;
                if (x == 3 || x == boardSize-2) {
                    addition->numerator += 2 * taperedPrior;
                    addition->denominator += 2 * taperedPrior;
                }
                if (y == 3 || y == boardSize-2) {
                    addition->numerator += 2 * taperedPrior;
                    addition->denominator += 2 * taperedPrior;
                }
            }
        }

        // Add a bonus for capturing a chain that the opponent placed
        // into atari on the previous move
        if (next == captureLastStone) {
            addition->numerator += 5 * basePrior;
            addition->denominator += 5 * basePrior;
        }

        // Add a bonus for escaping when the opponent's last move
        // placed our chain into atari
        if (next == potentialEscape) {
            addition->numerator += 5 * basePrior;
            addition->denominator += 5 * basePrior;
        }

        // Add a bonus to local moves
        if (legalMoves.size() < openingMoves) {
            int li = localMoves.find(next);
            if (li != -1) {
                localMoves.removeFast(li);
            }
            else {
                addition->numerator += basePrior;
                addition->denominator += 2 * basePrior;
            }
        }
    }

    // If we have no moves that are ko-legal, pass.
    if (searchTree.root->size == 0)
        return MOVE_PASS;

    // Calculate an estimate of a komi adjustment
    komiAdjustment /= legalMoves.size();


    // Expand the MC tree iteratively
    for (int n = 0; n < playouts; n++) {
        Board copy = Board(game);
        Player genPlayer = p;

        // Find a node in the tree to add a child to
        int depth = -1;
        MCNode *leaf = searchTree.findLeaf(genPlayer, copy, depth);

        MCNode *addition = new MCNode();
        addition->parent = leaf;
        MoveList candidates = copy.getLegalMoves(genPlayer);
        candidates.add(MOVE_PASS);

        // Set up a permutation matrix
        int *permutation = new int[candidates.size()];
        // Fisher-Yates shuffle
        for (unsigned int i = 0; i < candidates.size(); i++) {
            std::uniform_int_distribution<int> distribution(0, i);
            int j = distribution(rng);
            permutation[i] = permutation[j];
            permutation[j] = i;
        }

        // Find a random move that has not been explored yet
        Move next = 0;
        for (unsigned int i = 0; i < candidates.size(); i++) {
            next = candidates.get(permutation[i]);

            bool used = false;
            for (int j = 0; j < leaf->size; j++) {
                if (next == leaf->children[j]->m) {
                    used = true;
                    break;
                }
            }

            if (!used && copy.isMoveValid(genPlayer, next))
                break;
        }

        delete[] permutation;

        addition->m = next;
        copy.doMove(genPlayer, next);

        // Play out a random game. The final board state will be stored in copy.
        playRandomGame(otherPlayer(genPlayer), copy);

        // Score the game... somehow...
        float myScore = 0.0, oppScore = 0.0;
        scoreGame(genPlayer, copy, myScore, oppScore);
        myScore += (genPlayer == p) ? -komiAdjustment : komiAdjustment;

        if (myScore > oppScore) {
            addition->numerator++;
            // If the node is not a child of root
            if (depth)
                raveTable.inc(next, depth);
        }
        else {
            if (depth)
                raveTable.dec(next, depth);
        }
        addition->scoreDiff = ((int) myScore) - ((int) oppScore);

        // Add the new node to the tree
        leaf->children[leaf->size] = addition;
        leaf->size++;

        // Backpropagate the results
        searchTree.backPropagate(addition);
    }


    // Find the highest scoring move
    Move bestMove = searchTree.root->children[0]->m;
    double bestScore = 0.0;
    int64_t diff = -(1 << 30);
    int maxRAVE = raveTable.max();
    for (int i = 0; i < searchTree.root->size; i++) {
        double candidateScore = (double) searchTree.root->children[i]->numerator
                              / (double) searchTree.root->children[i]->denominator;
                            // +   (double) raveTable.score(searchTree.root->children[i]->m)
                            //   / ((double) maxRAVE)
                            //   / (16 + std::sqrt(searchTree.root->children[i]->denominator))
                            // +   (double) searchTree.root->children[i]->scoreDiff
                            //   / (double) (360 * 32);

        // if (candidateScore > bestScore) {
        //     bestScore = candidateScore;
        //     bestMove = searchTree.root->children[i]->m;
        // }

        if (debugOutput) {
            std::cerr << "(" << getX(searchTree.root->children[i]->m) << ", "
                      << getY(searchTree.root->children[i]->m) << "): "
                      << searchTree.root->children[i]->numerator << " / "
                      << searchTree.root->children[i]->denominator << std::endl;
        }

        if (candidateScore > bestScore
         || (candidateScore == bestScore && searchTree.root->children[i]->scoreDiff > diff)) {
            bestScore = candidateScore;
            bestMove = searchTree.root->children[i]->m;
            diff = searchTree.root->children[i]->scoreDiff;
        }
    }

    raveTable.age();

    return bestMove;
}
Пример #19
0
// Counts the territory each side owns
void Board::countTerritory(int &whiteTerritory, int &blackTerritory) {
    whiteTerritory = 0;
    blackTerritory = 0;
    Stone *visited = new Stone[arraySize*arraySize];
    Stone *territory = new Stone[arraySize*arraySize];
    Stone *region = new Stone[arraySize*arraySize]; 

    // Count territory for both sides
    for (Player p = BLACK; p <= WHITE; p++) {
        // Reset the visited array
        for (int i = 0; i < arraySize*arraySize; i++)
            visited[i] = 0;

        // Main loop
        for (int j = 1; j <= boardSize; j++) {
            for (int i = 1; i <= boardSize; i++) {
                // Don't recount territory
                if (visited[index(i, j)])
                    continue;
                // Only use empty squares as seeds
                if (pieces[index(i, j)])
                    continue;

                if (isEye(p, coordToMove(i, j))) {
                    visited[index(i, j)] = 1;
                    if (p == BLACK)
                        blackTerritory++;
                    else
                        whiteTerritory++;
                    continue;
                }
                
                for (int k = 0; k < arraySize*arraySize; k++)
                    territory[k] = 0;
                int territorySize = 0;
                int boundarySize = 0;

                getTerritory(p, i, j, visited, territory, territorySize, boundarySize);

                // Check if territory was actually sectioned off
                if (territorySize + boundarySize == boardSize*boardSize)
                    continue;

                // Detect life/death of internal stones
                // Initialize region to 0 if territory is 1, and vice versa
                // This acts as our "visited" array, so that we only explore areas
                // inside the territory
                // bool isContested = false;
                // for (int n = 1; n <= boardSize; n++) {
                //     for (int m = 1; m <= boardSize; m++) {
                //         if (!territory[index(m, n)])
                //             continue;
                //         if (pieces[index(m, n)] == otherPlayer(p)) {
                //             isContested = true;
                //             break;
                //         }
                //     }
                // }

                // if (!isContested) {
                //     if (p == BLACK)
                //         blackTerritory += territorySize;
                //     else
                //         whiteTerritory += territorySize;
                // }
                
                for (int k = 0; k < arraySize*arraySize; k++)
                    region[k] = territory[k] ^ 1;
                int internalRegions = 0;

                for (int n = 1; n <= boardSize; n++) {
                    for (int m = 1; m <= boardSize; m++) {
                        if (region[index(m, n)])
                            continue;
                        if (pieces[index(m, n)])
                            continue;

                        MoveList eye;
                        if (isSurrounded(EMPTY, p, m, n, region, eye))
                            internalRegions++;
                    }
                }

                int territoryCount = 0;
                if (internalRegions == 0) {
                    territoryCount += territorySize;
                    // Score dead stones
                    for (int k = 0; k < arraySize*arraySize; k++)
                        if (territory[k] && pieces[k] == otherPlayer(p))
                            territoryCount++;
                }

                if (p == BLACK)
                    blackTerritory += territoryCount;
                else
                    whiteTerritory += territoryCount;
            }
        }
    }

    delete[] visited;
    delete[] territory;
    delete[] region;
}
Пример #20
0
pair chooseMoveABDepth (int* iboard, int player, int alpha, int beta) {
    ASSERT(player == XPL || player == OPL);
    
    pair myBest = {0,-1};
    pair reply;
    int i,j, move;
    int moveCount=0, moveList[9];

    //default score
    if(player == US){
        myBest.score = alpha;
    } else {
        myBest.score = beta;
    }


    timesCalled++;
    pair temp;
    //temp.score = evaluateBoard(iboard);
    temp.move = -1;

    // if(level == 0){
    //     temp.score = evaluateBoard(iboard);
    //     return temp;
    // }

    if(didHeWin(iboard,US)) {
        //printf("%c WON\n",US);
        //printboard(iboard);        
        //temp.score = evaluateBoard(iboard);
        temp.score = evaluatePosition(iboard,US);
        return temp;
    } else if(didHeWin(iboard,THEM)) {
        //printf("%c WON\n",THEM);
        //printboard(iboard);          
        //temp.score = evaluateBoard(iboard);
        temp.score = evaluatePosition(iboard,US);
        return temp;
    } else if(isBoardFull(iboard)) {
        //printf("FULL\n");
        //printboard(iboard);          
        temp.score = evaluatePosition(iboard,US);
        return temp;
    }
    
    // get legal moves in25
    for(i = 0; i < 9; i++) {
        if( iboard[convert9To25[i]] == EMPTY) {
            moveList[moveCount++] = convert9To25[i];
        }
    }

    // for(i = 0; i < 9; i++) {
    //     if( iboard[convert9To25[cellScoreOrdered[i]]] == EMPTY) {
    //         moveList[moveCount++] = convert9To25[cellScoreOrdered[i]];
    //     }
    // }

    myBest.move = moveList[0];
    for(i=0; i < moveCount; i++) {
        move = moveList[i];
        iboard[move] = player;
        
        reply = chooseMoveAB(iboard, otherPlayer(player),alpha,beta);

        iboard[move] = EMPTY;
        // maximum lower bound of possible solutions
        if(player == US && myBest.score < reply.score){
            alpha = reply.score;
            myBest.score = evaluatePosition(iboard,US);
            myBest.move = move;            
        }
        // minimum upper bound of possible solutions 
        else if (player == THEM && myBest.score > reply.score){
            beta = reply.score;
            myBest.score = reply.score;
            myBest.move = move;            
        }

        if(alpha >= beta){
            return myBest;
        }
    }
    return myBest;
}