Using std::tuple

Hi,

I`m trying to use tuple with my Search function. http://www.cplusplus.com/reference/tuple/tuple/

I`m not very good reading compiler error messages, and there must be some errors.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
std::tuple<int, bool> Search(int depth, bool bestMove, board b)
{
  board combined() =b;
  int w = 0;
  w = evaluateNegamax(b);
  int score;
  int move;
  int bestScore = std::numeric_limits<int>::min(); 
  bool bestMove = false;
  if(depth == 0) return w;
  int x=0, int y=0;
  for (int x = 0; x < 9; ++x) {
  for (int y = 0; y < 9; ++y) {
    while (!occupied(x,y));
    make_move(move);              
    score = -Search(depth-1,b,false);       // recursion 
    unMake(b);
    if(score > bestScore) {         
      bestScore = score;
      bestMove = move;
    }
   }
  }

   // return the best move
   return std::make_tuple(bestScore, bestMove);
}


For starters, can I assign bool to int?
and there must be some errors

Its hard to guess the error messages of your compiler. Please help us and do report them to the forum.
Here are some:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90

main.cpp: In function 'std::tuple<int, bool> Search(int, bool, board)':

main.cpp:226:18: warning: declaration of 'board combined()' has 'extern' and is initialized

   board combined() =b;

                  ^

main.cpp:226:22: error: invalid pure specifier (only '= 0' is allowed) before ';' token

   board combined() =b;

                      ^

main.cpp:226:22: error: function 'board combined()' is initialized like a variable

main.cpp:232:8: error: declaration of 'bool bestMove' shadows a parameter

   bool bestMove = false;

        ^

main.cpp:233:25: error: could not convert 'w' from 'int' to 'std::tuple<int, bool>'

   if(depth == 0) return w;

                         ^

main.cpp:234:12: error: expected unqualified-id before 'int'

   int x=0, int y=0;

            ^

main.cpp:238:19: error: no matching function for call to 'make_move(int&)'

     make_move(move);              

                   ^

main.cpp:238:19: note: candidates are:

main.cpp:70:6: note: void make_move(size_t, size_t, board&)

 void make_move( size_t row, size_t col, board & b )

      ^

main.cpp:70:6: note:   candidate expects 3 arguments, 1 provided

main.cpp:95:1: note: void make_move(size_t, size_t)

 make_move(size_t row, size_t col)

 ^

main.cpp:95:1: note:   candidate expects 2 arguments, 1 provided

main.cpp:239:36: error: no matching function for call to 'Search(int, board&, bool)'

     score = -Search(depth-1,b,false);       // recursion 

                                    ^

main.cpp:239:36: note: candidates are:

main.cpp:31:5: note: int Search(int, board)

 int Search(int depth, board b);

     ^

main.cpp:31:5: note:   candidate expects 2 arguments, 3 provided

main.cpp:224:23: note: std::tuple<int, bool> Search(int, bool, board)

 std::tuple<int, bool> Search(int depth, bool bestMove, board b)

                       ^

main.cpp:224:23: note:   no known conversion for argument 2 from 'board {aka std::bitset<9ul>}' to 'bool'

main.cpp:234:7: warning: unused variable 'x' [-Wunused-variable]

   int x=0, int y=0;

       ^

Last edited on
Line 3: The compiler takes this as a function declaration. Remove '()'.

Line 10: Your function does return int here, where std::tuple<int, bool> was expected. Have a look at line 26 to fix the bug.

Line 11: Use ';' as statement seperator. ',' is a list seperator. If you want to declare a list of variables of the same type, then use the type name as the first token of the statement.

Line 15: The compiler misses a function named make_move and expecting an int as argument. It knows about two other functions named make_move but with different argument count and type.

Line 16: Analog to line 15. There's no function named Search with the expected argument count, type and return value.
" Line 10: Your function does return int here, where std::tuple<int, bool> was expected. Have a look at line 26 to fix the bug. "

std::tuple<int, bool> is used to return a best score and a best co-ordinate. It has nothing

to do with evaluateNegamax(b);

Can I write

if(depth == 0) return evaluateNegamax(b); ?
Last edited on
No, because in line 1 you've declared the compiler that your function will return a std::tuple<int, bool>. So it has to do so in any case.

If
return std::make_tuple(evaluateNegamax(b), true);
or
return std::make_tuple(evaluateNegamax(b), false);
or something like this don't fit, then you may think about another design.
Hm, maybe something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34


int Search(int depth, bool bestMove, board b)
{
  board combined =b;
  int w = 0;
  w = evaluateNegamax(b);
  int score;
  int move;
  int bestScore = std::numeric_limits<int>::min(); 
  bool bestMove = false;
  if(depth == 0) return w;
  int x=0; int y=0;
  for (int x = 0; x < 9; ++x) {
  for (int y = 0; y < 9; ++y) {
    while (!occupied(x,y));
    make_move(move);              
    score = -Search(depth-1,b,false);       // recursion 
    unMake(b);
    if(score > bestScore) {         
      bestScore = score;
      bestMove = move;
    }
   }
  }

   // return the best move
   if (bestMove)
   return bestMove;
   
   else
   return bestScore;
}
I don't know the logic of your program, but if it fits your idea then I see only
one syntax error the compiler should have reported:

Line 18: Change the order of the last two arguments of your Search()-call.


Line 5: Your compiler should have warned that you're never using variable combined.


Some tips:

Even if C++ doesn't support ranges and other restricting types, try to be as restrictive as possible. I think depth should never become negative, so better declare it unsigned int. In more complex software developing environments you may come in trouble if declaring each and everything as int.

At line 22 you're assigning an int value to a boolean one. This is indeed possible in C/C++. (C/C++ hackers do call the implicit conversion feature, while from a computer science viewpoint this is insufficient type safety). Better use something like
bestMove = (move != 0);
to be type safe.

At line 11 you're defining variable bestMove of the same name as the second parameter to your function and thus suppressing the formal parameter. The compiler should have reported a warning about this fact. Its important to honour it because your second parameter will never be used now in your program! Does this fit your intention?

At line 13 you're defining variable x and y - and never use them! The compiler also should have warned. You're using two variables also named x and y in your for-loops. But these are two different ones than defined at line 13. They are defined at line 14 and 15 as for-loop variables.



EDIT: Fixed syntax error.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

int Search(unsigned int depth, board b)
{
  board combined =b;
  int w = 0;
  w = evaluateNegamax(b);
  int bestMove= -2;
  int bestScore = std::numeric_limits<int>::min(); 
  int score;
  int move;
  if(depth == 0) return w;
  for (int x = 0; x < 9; ++x) {
  for (int y = 0; y < 9; ++y) {
    while (!occupied(x,y));
    make_move(move);              
    score = -Search(depth-1,false,b);       // recursion 
    unMake(b);
    if(score > bestScore) {         
      bestScore = score;
      bestMove = move;
    }
   }
  }

 // return the best move
   if (bestMove)
   return bestMove;
   
   else
   return bestScore;
}
Last edited on
Ok, but won't compile. Sorry ;-(

Line 16: Bad argument count (unless you've defined another function named Search with formal parameter list like (unsigned int, bool, board)).


Tip:

Lines 7 and 26: You treat an integer variable as a boolean one. As I've written above, this is ok in C/C++ - but its like comparing apples with oranges.


A question to your semantic: How do you distinguish between move and score of Search() result? Ok, because both are of type int, its syntactically correct, but semantically I don't understand what you're doing. How do you know f.e. at line 16 getting a score result returned from Search() and not a move?
"How do you distinguish between move and score of Search() result?"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

int Search(unsigned int depth, board b)
{
  board combined =b;
  int w = 0;
  w = evaluateNegamax(b);
  int bestMove= std::numeric_limits<int>::min(); 
  int bestScore = std::numeric_limits<int>::min(); 
  int score;
  if(depth == 0) return w;
  for (int x = 0; x < 9; ++x) {
  for (int y = 0; y < 9; ++y) {
    while (!occupied(x,y));
    make_move(b);              
    score = -Search(depth-1,b);       // recursion 
    unMake(b);
    bestScore= max(bestMove,bestScore)
   }
  }

   return bestScore;
}


See line 15


and then have another function to call this function.
Last edited on
If I do understand the intention of your Search() function, you're implementing a MinMax search and so you'll be also interested on the best move as a result to be returned. C/C++ functions may also return values using reference parameter (see http://www.cplusplus.com/doc/tutorial/functions/ for details). Your example may be rewritten as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int Search(
    unsigned int depth,  // IN:    search level. 0: deepest level
    board b,             // IN:    current board to be examined
    int &bestMove        // INOUT: best move
)
{
    int w = evaluateNegamax(b);
    bestMove = -2;    // Really overwrite bestMove?
    int bestScore = std::numeric_limits<int>::min(); 
    int score;
    int move;
    if (depth == 0) return w;
    for (int x = 0; x < 9; ++x) {
        for (int y = 0; y < 9; ++y) {
            while (!occupied(x,y));
            make_move(b);              
            score = -Search(depth-1, b, bestMove);  // overwrites bestMove!
            unMake(b);
            if(score > bestScore) {         
                bestScore = score;
                bestMove = move;
            }
       }
    }

    return bestScore;    // bestMove now contains bestMove on return
}


If my assumption about your intention does fit, you may also want bestScore being an INOUT parameter.
There is a bug though.

1
2
3
4
5
6
7
8
9
10

void make_move( size_t row, size_t col, board & b )
{
if (free(row, col))
{
b[pos(row, col)] = true;
last_move_row = row ;
last_move_col = col ;
}
}



compare to make_move(b);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# define curr_move_noughts 1
# define crosses -1

int negamax( board b, unsigned int depth, side, int& bestMove)

{

if (depth==0)

{

   int score=eval(b);
  return side * score;

}

int bestScore = -1000       // worst game scenario
for (int x = 0; x < 9; ++x) {
 for (int y = 0; y < 9; ++y) {
while (!occupied(x,y));
make_move(b);              
int val = -negamax(b, depth -1, -side);
unMake(b);
bestScore = max(bestScore, val)
 
   }
}


return bestScore;

}



And look to wikipedia:

http://en.wikipedia.org/wiki/Negamax

Practical implementations will also retain the best move, along with bestValue.

Now my function does all that?
Topic archived. No new replies allowed.