a geicko-2 based round robin ranking system designed to test c++ battleship submissions
battleship.dunkirk.sh
1// Tournament battle runner - runs matches between two AI implementations
2// Outputs results in parseable format
3
4#include "battleship.h"
5#include "memory.h"
6#include <iostream>
7#include <cstdlib>
8#include <ctime>
9
10using namespace std;
11
12// Function pointers for the two AIs
13void (*initMemory1)(ComputerMemory&) = nullptr;
14string (*smartMove1)(const ComputerMemory&) = nullptr;
15void (*updateMemory1)(int, int, int, ComputerMemory&) = nullptr;
16
17void (*initMemory2)(ComputerMemory&) = nullptr;
18string (*smartMove2)(const ComputerMemory&) = nullptr;
19void (*updateMemory2)(int, int, int, ComputerMemory&) = nullptr;
20
21struct MatchResult {
22 int player1Wins = 0;
23 int player2Wins = 0;
24 int ties = 0;
25 int totalMoves = 0;
26};
27
28MatchResult runMatch(int numGames) {
29 MatchResult result;
30 srand(time(NULL));
31
32 for (int game = 0; game < numGames; game++) {
33 Board board1, board2;
34 ComputerMemory memory1, memory2;
35
36 initializeBoard(board1);
37 initializeBoard(board2);
38 initMemory1(memory1);
39 initMemory2(memory2);
40
41 int shipsSunk1 = 0;
42 int shipsSunk2 = 0;
43 int moveCount = 0;
44
45 while (true) {
46 moveCount++;
47
48 // Player 1 move
49 string move1 = smartMove1(memory1);
50 int row1, col1;
51 int check1 = checkMove(move1, board2, row1, col1);
52 while (check1 != VALID_MOVE) {
53 move1 = randomMove();
54 check1 = checkMove(move1, board2, row1, col1);
55 }
56
57 // Player 2 move
58 string move2 = smartMove2(memory2);
59 int row2, col2;
60 int check2 = checkMove(move2, board1, row2, col2);
61 while (check2 != VALID_MOVE) {
62 move2 = randomMove();
63 check2 = checkMove(move2, board1, row2, col2);
64 }
65
66 // Execute moves
67 int result1 = playMove(row1, col1, board2);
68 int result2 = playMove(row2, col2, board1);
69
70 updateMemory1(row1, col1, result1, memory1);
71 updateMemory2(row2, col2, result2, memory2);
72
73 if (isASunk(result1)) shipsSunk1++;
74 if (isASunk(result2)) shipsSunk2++;
75
76 if (shipsSunk1 == 5 || shipsSunk2 == 5) {
77 break;
78 }
79 }
80
81 result.totalMoves += moveCount;
82
83 if (shipsSunk1 == 5 && shipsSunk2 == 5) {
84 result.ties++;
85 } else if (shipsSunk1 == 5) {
86 result.player1Wins++;
87 } else {
88 result.player2Wins++;
89 }
90 }
91
92 return result;
93}
94
95int main(int argc, char* argv[]) {
96 if (argc < 2) {
97 cerr << "Usage: " << argv[0] << " <num_games>" << endl;
98 return 1;
99 }
100
101 int numGames = atoi(argv[1]);
102 if (numGames <= 0) numGames = 10;
103
104 setDebugMode(false);
105
106 MatchResult result = runMatch(numGames);
107
108 // Output in parseable format
109 cout << "PLAYER1_WINS=" << result.player1Wins << endl;
110 cout << "PLAYER2_WINS=" << result.player2Wins << endl;
111 cout << "TIES=" << result.ties << endl;
112 cout << "TOTAL_MOVES=" << result.totalMoves << endl;
113 cout << "AVG_MOVES=" << (result.totalMoves / numGames) << endl;
114
115 return 0;
116}