Source

python-ai / src / othello / Board.hpp

Full commit
#ifndef AI_OTHELLO_BOARD_H
#define AI_OTHELLO_BOARD_H

#include <list>
#include <string>
#include <boost/cstdint.hpp>
#include <boost/tuple/tuple.hpp>

using std::list;
using std::string;
using boost::tuple;

typedef int8_t BoardPlayerNum;
const BoardPlayerNum UNPICKED = 0;
const BoardPlayerNum FST_PLAYER = 1;
const BoardPlayerNum SND_PLAYER = 2;
const BoardPlayerNum INVALID = 3;

typedef int8_t BoardIdx;
typedef uint8_t BoardElem;
typedef int8_t BoardScore;
typedef tuple<BoardIdx, BoardIdx> BoardLoc;
typedef list<BoardLoc> BoardLocs;
typedef double Feature;

class Board {
public:
    Board();
    Board(const Board * const oldBoard) {
        for(int32_t i = 0; i < 16; i++) {
            positions[i] = oldBoard->positions[i];
        }
    }
    BoardElem get(const BoardIdx row, const BoardIdx col) const;
    BoardElem get(const BoardLoc loc) const
        { return get(loc.get<0>(), loc.get<1>()); }
    Board extend(const BoardIdx row, const BoardIdx col,
                 const BoardPlayerNum player) const;
    Board extend(const BoardLoc loc, const BoardPlayerNum player) const
        { return extend(loc.get<0>(), loc.get<1>(), player); }
    Board makeMove(const BoardIdx row, const BoardIdx col,
                   const BoardPlayerNum player) const;
    Board makeMove(const BoardLoc loc, const BoardPlayerNum player) const
        { return makeMove(loc.get<0>(), loc.get<1>(), player); }
    BoardLocs validMoves(const BoardPlayerNum player) const;
    bool validMove(const BoardIdx row, const BoardIdx col,
                   const BoardPlayerNum player) const;
    bool validMove(const BoardLoc loc, const BoardPlayerNum player) const
        { return validMove(loc.get<0>(), loc.get<1>(), player); }
    BoardScore score(const BoardPlayerNum player) const;
    bool complete() const;
    BoardPlayerNum winner() const;
    string toString() const;
    
    static BoardPlayerNum otherPlayer(const BoardPlayerNum player) {
        if (player == FST_PLAYER) return SND_PLAYER;
        if (player == SND_PLAYER) return FST_PLAYER;
        return UNPICKED;
    }
    static bool moveValid(const BoardIdx row, const BoardIdx col,
                          const BoardLocs validMoves);
    static bool moveValid(const BoardLoc loc, const BoardLocs validMoves)
        { return moveValid(loc.get<0>(), loc.get<1>(), validMoves); }
    static string boardLocToString(const BoardLoc loc);
    static string boardLocsToString(const BoardLocs locs);
    
    Feature featureCorners(const BoardPlayerNum player) const;
    Feature featureEdges(const BoardPlayerNum player) const;
    Feature featureScore(const BoardPlayerNum player) const
        { return ((double)score(player)) / 64.0; }
    Feature featureUnpicked() const
        { return featureScore(UNPICKED); }
    Feature featureMoves(const BoardPlayerNum player) const
        { return ((double)validMoves(player).size()) / 32.0; }
private:
    BoardElem positions[16];
    static bool valid(const BoardIdx row, const BoardIdx col) {
        return (row >= 0) && (row <= 7) && (col >= 0) && (col <= 7);
    }
    bool sandwich(const BoardIdx row, const BoardIdx col, const BoardPlayerNum player,
                  const int8_t rowDir, const int8_t colDir) const;
    BoardLocs getSandwich(const BoardIdx row, const BoardIdx col, const BoardPlayerNum player,
                          const int8_t rowDir, const int8_t colDir) const;
};

#endif