3

I'm taking a class in AI Methods along with a friend of mine, and we've partenered for the final project, which is coding Othello & an AI for it using C++ and OpenGL.

So far we have the board and the Othello Engine (I'm using an MVC type approach). But the one thing thats proving difficult to grasp is the AI.

We're supposed to write an AI that uses Alpha-Beta pruning on a tree to quickly calculate the next move it should make.

The concepts of Alpha-Beta pruning, as well as the algorithm for detecting which squares are worth more than others, as far as the game is concerned.

However, my partner nor I have yet to take the data structures class, and as such we don't know how to properly create a tree in C++ or even where to get started.

So my question to you, Stack Overflow is: Where do I get started to quickly (and effectively) write and traverse a Tree for Alpha-Beta Pruning in C++ without using STL. (Our assignment states that we're not allowed to use STL).

Any and all help is appreciated, thank you!

Navarr
  • 3,703
  • 7
  • 33
  • 57
  • 3
    Two things: (1) all of the info about AI isn't necessary, it seems all you want to do is find out how to implement a tree in C++, and (2) there are PLENTY of resources out there on this topic. Google is your friend. If you have any *specific* difficulties implementing the tree, ask then. – Chris Eberle Aug 01 '11 at 05:52
  • @Martinho: neat. I learn something new every day. The fact that the teacher explicitly forbade STL makes me think that it must be a pretty common data structure. I could of course be wrong, maybe the teacher nixed it because it's a false start. Your thoughts, OP? – Chris Eberle Aug 01 '11 at 06:09
  • 1
    Ooops, I should get some sleep. Shouldn't have deleted that comment :( Basically, it said this is not really about implementing a tree data structure, but about searching on the game tree, which is not to be stored in memory, because that would defeat the algorithm's efficiency gains. Othello has a game-tree complexity of 10^58, which is why you need this kind of algorithms. I do think that the question is too broad. I recommend you start by reading/googling on Alpha-Beta pruning and minimax, and then come back when you have more specific questions about the implementation. – R. Martinho Fernandes Aug 01 '11 at 06:15
  • 5
    “Our assignment states that we're not allowed to use STL” – **Your assignment sucks.** That is all. – Konrad Rudolph Aug 01 '11 at 07:33
  • @Konrad there are many cases when STL is inapplicable. Games shun it, especially on consoles. – Don Reba Aug 01 '11 at 08:36
  • 1
    @Don Nonsense. If necessary, games write their own implementation (EASTL). But they don’t *shun* an algorithmic standard library. On the contrary. – Konrad Rudolph Aug 01 '11 at 08:39
  • @Konrad They shun the standard one in favour of their own non-standard libraries. Also, AI often uses specialized structures. Not using STL is a totally reasonable requirement for an AI assignment. – Don Reba Aug 01 '11 at 08:47
  • 1
    @Don I don’t buy it and I respectfully suggest that your information is wrong. The whole point of the STL is that it’s general purpose. Most C++ code that doesn’t use it employs some very questionable programming techniques (= is just bad code), and there is nothing specifically in AI that makes the STL inapplicable. In particular, computational optimisation (where alpha-beta pruning is applied) is just a general programming technique and there is no reason whatsoever to not use the STL when employing it. – Konrad Rudolph Aug 01 '11 at 12:06
  • I think the teacher generally doesn't allow STL in any of his courses where programming is required. (He's more of a C guy...) And this is the same professor that made us learn OpenGL for an AI course (and is requiring we print and electronically turn in the assignment) – Navarr Aug 01 '11 at 14:32
  • 2
    @Don: Stop saying "they" as if the game industry is a single nebulous entity. I'm a game programmer, and I use the standard library. Only the morons suffering from not-invented-here syndrome go "hur hur you use standard library? Slow! I can waste my time doing worse." Only after profiling proper code should you ever even consider doing something manually. The games industry is literally the largest producer of terrible programming practices I've ever seen, and it's usually coupled with blinding ignorance and immovable arrogance. Anyone who looks to games for coding practices has already lost. – GManNickG Aug 03 '11 at 00:38

1 Answers1

2

The tree for alpha-beta pruning is usually implicit. It is a way of preventing your AI search algorithm from wasting time on bad solutions. Here is the pseudocode from Wikipedia:

function alphabeta(node, depth, α, β, Player)         
    if  depth = 0 or node is a terminal node
        return the heuristic value of node
    if  Player = MaxPlayer
        for each child of node
            α := max(α, alphabeta(child, depth-1, α, β, not(Player) ))     
            if β ≤ α
                break                             (* Beta cut-off *)
        return α
    else
        for each child of node
            β := min(β, alphabeta(child, depth-1, α, β, not(Player) ))     
            if β ≤ α
                break                             (* Alpha cut-off *)
        return β 
(* Initial call *)
alphabeta(origin, depth, -infinity, +infinity, MaxPlayer)

The function recursively evaluates board positions. The "node" is the current position, and where it says "for each child of node" is where you generate new board positions resulting from each possible move at the current one. The depth parameter controls how far ahead you want to evaluate the tree, for analyzing moves to an unlimited depth might be impractical.


Still, if you have to build a tree of some given depth before pruning it for educational purposes, the structure for a tree with nodes that can have variable numbers of children is very simple and could look something like this:

struct Node
{
    Node ** children;
    int     childCount;
    double  value;
};

Node * tree;

Here children is a Node array with childCount members. Leaf nodes would have childCount=0. To construct the tree, you would search the availabile board positions like this:

Node * CreateTree(Board board, int depth)
{
    Node * node = new Node();
    node.childCount = board.GeAvailableMoveCount();
    node.value      = board.GetValue;
    if (depth > 0 && node.childCount > 0)
    {
        node.children = new Node * [node.childCount];
        for (int i = 0; i != node.childCount; ++i)
            node.children[i] = CreateTree(board.Move(i), depth - 1);
    }
    else
    {
        node.children = NULL;
    }
    return node;
}

void DeleteTree(Node * tree)
{
    for (int i = 0; i != tree.childCount; ++i)
        DeleteTree(tree.children[i]);
    delete [] tree.children; // deleting NULL is OK
    delete tree;
}
Don Reba
  • 13,814
  • 3
  • 48
  • 61
  • But how do you *build* the tree? – Navarr Aug 02 '11 at 00:33
  • You usually *do* store the tree, because the algorithms are almost always coupled with iterative deepening. – GManNickG Aug 03 '11 at 00:39
  • @GMan do you store the whole tree for iterative deepining, or just list the leaf nodes? – Don Reba Aug 03 '11 at 00:46
  • @Don: When I did it, I just stored the tree. It's cheap enough (memory-wise) that you're going to be limited on time more than memory, so you won't get to exhaust the memory. (Make no mistake, though, that it does use lots.) Forward pruning helps significantly, especially for a game with a high branching factor, such as the game I was doing, The Game of the Amazons. – GManNickG Aug 03 '11 at 01:00