Skip to content

Commit cec2ab1

Browse files
author
cameron.jp
committed
Starting work on Galcon engine.
1 parent 94712de commit cec2ab1

File tree

9 files changed

+417
-32
lines changed

9 files changed

+417
-32
lines changed

Diff for: galcon/Makefile

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Copyright 2010 owners of the AI Challenge project
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4+
# use this file except in compliance with the License. You may obtain a copy
5+
# of the License at http:#www.apache.org/licenses/LICENSE-2.0 . Unless
6+
# required by applicable law or agreed to in writing, software distributed
7+
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8+
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
9+
# specific language governing permissions and limitations under the License.
10+
#
11+
# Author: Jeff Cameron ([email protected])
12+
#
13+
# Makefile for the entire AI contest project.
14+
15+
CC=g++
16+
CPPFLAGS += -Wall -I.. -I../third_party/googletest/include
17+
VPATH = third_party/googletest/make:cpp_util:sandbox
18+
SUBDIRS = engine
19+
20+
all: subdirs
21+
22+
clean:
23+
for dir in $(SUBDIRS); \
24+
do \
25+
$(MAKE) -C $$dir clean; \
26+
done
27+
28+
.PHONY: subdirs $(SUBDIRS)
29+
subdirs: $(SUBDIRS)
30+
31+
$(SUBDIRS):
32+
$(MAKE) -C $@

Diff for: galcon/engine/Makefile

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Copyright 2010 owners of the AI Challenge project
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4+
# use this file except in compliance with the License. You may obtain a copy
5+
# of the License at http:#www.apache.org/licenses/LICENSE-2.0 . Unless
6+
# required by applicable law or agreed to in writing, software distributed
7+
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8+
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
9+
# specific language governing permissions and limitations under the License.
10+
#
11+
# Author: Jeff Cameron ([email protected])
12+
#
13+
# Makefile for the Tic-Tac-Toe contest engine.
14+
15+
CC=g++
16+
CPPFLAGS += -Wall -I../.. -I../../third_party/googletest/include
17+
VPATH = ../../third_party/googletest/make:../../cpp_util:../../sandbox
18+
TARGETS = engine random_bot unit_tests
19+
20+
all: $(TARGETS)
21+
22+
clean:
23+
rm -f *.o $(TARGETS) *_test
24+
25+
engine: engine.o grid.o sandbox.a cpp_util.a
26+
27+
random_bot: random_bot.o cpp_util.a
28+
29+
unit_tests: grid.o grid_test.o gtest_main.a
30+
$(CC) $(CPPFLAGS) -o $@ $^ -lpthread

Diff for: galcon/engine/engine.cc

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2010 owners of the AI Challenge project
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4+
// use this file except in compliance with the License. You may obtain a copy
5+
// of the License at http://www.apache.org/licenses/LICENSE-2.0 . Unless
6+
// required by applicable law or agreed to in writing, software distributed
7+
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8+
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
9+
// specific language governing permissions and limitations under the License.
10+
//
11+
// Author: Jeff Cameron ([email protected])
12+
//
13+
// Runs a game of Tic-Tac-Toe between two computer programs.
14+
15+
#include <iostream>
16+
#include <stdlib.h>
17+
#include "cpp_util/string_util.h"
18+
#include "sandbox/sandbox.h"
19+
#include "tic_tac_toe/engine/grid.h"
20+
21+
int main(int argc, char *argv[]) {
22+
Sandbox player_one("./random_bot");
23+
Sandbox player_two("./random_bot");
24+
player_one.Init();
25+
player_two.Init();
26+
int blame = 0;
27+
Grid grid(3, 3, 3);
28+
while (!grid.GameOver()) {
29+
std::cout << "grid.GameOver(): " << grid.GameOver() << std::endl;
30+
Sandbox& player = grid.WhoseTurn() == 1 ? player_one : player_two;
31+
player.Write(grid.ToString());
32+
std::cout << grid.ToString();
33+
std::string line;
34+
int result = player.ReadLine(line, 1000);
35+
if (result <= 0) {
36+
blame = grid.WhoseTurn();
37+
std::cout << "Didn't receive a response from player " << blame
38+
<< std::endl;
39+
break;
40+
}
41+
std::cout << "Received from player " << grid.WhoseTurn() << " ("
42+
<< result << "): " << line << std::endl;
43+
std::vector<std::string> tokens = StringUtil::Tokenize(line);
44+
if (tokens.size() != 2) {
45+
blame = grid.WhoseTurn();
46+
break;
47+
}
48+
int x = atoi(tokens[0].c_str());
49+
int y = atoi(tokens[1].c_str());
50+
grid.MakeMove(x, y);
51+
}
52+
if (blame != 0) {
53+
std::cout << "Player " << blame << " did something bad." << std::endl;
54+
return 0;
55+
}
56+
std::cout << grid.ToString();
57+
if (grid.Winner() == 0) {
58+
std::cout << "Draw!" << std::endl;
59+
} else {
60+
std::cout << "Player " << grid.Winner() << " Wins!" << std::endl;
61+
}
62+
return 0;
63+
}

Diff for: galcon/engine/game.cc

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Copyright 2010 owners of the AI Challenge project
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4+
// use this file except in compliance with the License. You may obtain a copy
5+
// of the License at http://www.apache.org/licenses/LICENSE-2.0 . Unless
6+
// required by applicable law or agreed to in writing, software distributed
7+
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8+
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
9+
// specific language governing permissions and limitations under the License.
10+
//
11+
// Author: Jeff Cameron ([email protected])
12+
13+
#include "galcon/engine/game.h"
14+

Diff for: galcon/engine/game.h

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2010 owners of the AI Challenge project
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4+
// use this file except in compliance with the License. You may obtain a copy
5+
// of the License at http://www.apache.org/licenses/LICENSE-2.0 . Unless
6+
// required by applicable law or agreed to in writing, software distributed
7+
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8+
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
9+
// specific language governing permissions and limitations under the License.
10+
//
11+
// Author: Jeff Cameron ([email protected])
12+
//
13+
// Stores the game state.
14+
15+
#ifndef GALCON_ENGINE_GAME_H_
16+
#define GALCON_ENGINE_GAME_H_
17+
18+
#include <string>
19+
20+
class Game {
21+
public:
22+
// Initializes a game using a description of a map from a text file. See the
23+
// LoadMapFromFile function for a description of the map file format.
24+
Game(const std::string& map_filename);
25+
26+
// Returns the number of planets in the map.
27+
int NumPlanets() const;
28+
29+
// Returns the owner of the planet with the given number.
30+
int Owner(int planet_id) const;
31+
32+
// Returns the number of ships in the given planet.
33+
int NumShips(int planet_id) const;
34+
35+
// Returns the x- and y-coordinate of a given planet.
36+
int PlanetX(int planet_id) const;
37+
int PlanetY(int planet_id) const;
38+
39+
private:
40+
// Loads a map from a test file. The text file contains a description of the
41+
// starting state of a game. One planet is specified per line. Each line
42+
// contains the x- and y-coordinate of one planet, the player number that
43+
// starts off owning the planet, and the number of ships originally in the
44+
// planet. Any characters on a line beyond a '#' character should be
45+
// ignored. The coordinates are real numbers, and need not be integers.
46+
// The player number and number of ships must be integers. Fields are
47+
// separated by space characters. Lines that do not appear to match the
48+
// specified line format should be ignored. For example:
49+
//
50+
// # This is a sample map file, for the purpose of illustration.
51+
// 0 0 1 34 # Player one home planet
52+
// 7 7 2 34 # Player two home planet
53+
// 3.14 2.71 0 15 # Neutral planet with real-numbere coordinates.
54+
void LoadMapFromFile(const std::string& map_filename);
55+
};
56+
57+
#endif

Diff for: galcon/engine/game_test.cc

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Copyright 2010 owners of the AI Challenge project
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4+
// use this file except in compliance with the License. You may obtain a copy
5+
// of the License at http://www.apache.org/licenses/LICENSE-2.0 . Unless
6+
// required by applicable law or agreed to in writing, software distributed
7+
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8+
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
9+
// specific language governing permissions and limitations under the License.
10+
//
11+
// Author: Jeff Cameron ([email protected])
12+
//
13+
// Unit tests for the Sandbox class.
14+
15+
#include "tic_tac_toe/engine/grid.h"
16+
#include <sstream>
17+
#include "gtest/gtest.h"
18+
19+
// Tests the default constructor. It's supposed to make a standard 3x3 Tic Tac
20+
// Toe board.
21+
TEST(GridTest, DefaultConstructor) {
22+
Grid g;
23+
ASSERT_EQ(g.Width(), 3) << "Board width is suppsed to be 3.";
24+
ASSERT_EQ(g.Height(), 3) << "Board height is suppsed to be 3.";
25+
ASSERT_EQ(g.WinLength(), 3) << "Board win length is suppsed to be 3.";
26+
ASSERT_EQ(g.GameOver(), false) << "Game should not be over right after "
27+
<< "initialization.";
28+
}
29+
// Tests the custom constructor, which creates boards with arbitrary
30+
// dimensions.
31+
TEST(GridTest, CustomConstructor) {
32+
Grid g(2, 4, 3);
33+
ASSERT_EQ(g.Width(), 2) << "Wrong board width.";
34+
ASSERT_EQ(g.Height(), 4) << "Wrong board height.";
35+
ASSERT_EQ(g.WinLength(), 3) << "Wrong win length.";
36+
ASSERT_EQ(g.GameOver(), false) << "Game should not be over right after "
37+
<< "initialization.";
38+
}
39+
40+
// Runs a full game on a small, simple board, testing the state of the grid
41+
// after each move.
42+
TEST(GridTest, SmallGame) {
43+
Grid g(2, 2, 2);
44+
ASSERT_EQ(g.Width(), 2);
45+
ASSERT_EQ(g.Height(), 2);
46+
ASSERT_EQ(g.WinLength(), 2);
47+
ASSERT_EQ(g.GameOver(), false);
48+
ASSERT_EQ(g.WhoseTurn(), 1);
49+
std::stringstream grid_string;
50+
grid_string << "2 2 2" << std::endl
51+
<< "00" << std::endl
52+
<< "00" << std::endl;
53+
ASSERT_EQ(g.ToString(), grid_string.str());
54+
ASSERT_EQ(g.Winner(), 0);
55+
ASSERT_EQ(g.Loser(), 0);
56+
ASSERT_EQ(g.MakeMove(0, 0), 0);
57+
ASSERT_EQ(g.GameOver(), false);
58+
ASSERT_EQ(g.WhoseTurn(), 2);
59+
grid_string.str("");
60+
grid_string << "2 2 2" << std::endl
61+
<< "10" << std::endl
62+
<< "00" << std::endl;
63+
ASSERT_EQ(g.ToString(), grid_string.str());
64+
ASSERT_EQ(g.Winner(), 0);
65+
ASSERT_EQ(g.Loser(), 0);
66+
ASSERT_EQ(g.MakeMove(1, 0), 0);
67+
ASSERT_EQ(g.GameOver(), false);
68+
ASSERT_EQ(g.WhoseTurn(), 1);
69+
grid_string.str("");
70+
grid_string << "2 2 2" << std::endl
71+
<< "12" << std::endl
72+
<< "00" << std::endl;
73+
ASSERT_EQ(g.ToString(), grid_string.str());
74+
ASSERT_EQ(g.Winner(), 0);
75+
ASSERT_EQ(g.Loser(), 0);
76+
ASSERT_EQ(g.MakeMove(1, 1), 0);
77+
ASSERT_EQ(g.GameOver(), true);
78+
ASSERT_EQ(g.WhoseTurn(), 2);
79+
grid_string.str("");
80+
grid_string << "2 2 2" << std::endl
81+
<< "12" << std::endl
82+
<< "01" << std::endl;
83+
ASSERT_EQ(g.ToString(), grid_string.str());
84+
ASSERT_EQ(g.Winner(), 1);
85+
ASSERT_EQ(g.Loser(), 2);
86+
}
87+
88+
// Tries to move onto a square which has already been filled.
89+
TEST(GridTest, IllegalMove) {
90+
Grid g;
91+
ASSERT_EQ(g.WhoseTurn(), 1);
92+
ASSERT_EQ(g.MakeMove(1, 1), 0);
93+
ASSERT_EQ(g.WhoseTurn(), 2);
94+
ASSERT_EQ(g.MakeMove(1, 1), -1);
95+
ASSERT_EQ(g.WhoseTurn(), 2);
96+
}
97+
98+
// Tries to move onto a square which is out of bounds.
99+
TEST(GridTest, OutOfBounds) {
100+
Grid g;
101+
ASSERT_EQ(g.MakeMove(3, 2), -1);
102+
}
103+
104+
// Makes sure that draws are detected okay. Plays the following game:
105+
// 122
106+
// 211
107+
// 112
108+
// where the moves are made in the following order:
109+
// 984
110+
// 615
111+
// 372
112+
// then checks to make sure that the draw is detected.
113+
TEST(GridTest, DrawDetection) {
114+
Grid g;
115+
ASSERT_EQ(g.GameOver(), false);
116+
ASSERT_EQ(g.MakeMove(1, 1), 0);
117+
ASSERT_EQ(g.GameOver(), false);
118+
ASSERT_EQ(g.MakeMove(2, 2), 0);
119+
ASSERT_EQ(g.GameOver(), false);
120+
ASSERT_EQ(g.MakeMove(0, 2), 0);
121+
ASSERT_EQ(g.GameOver(), false);
122+
ASSERT_EQ(g.MakeMove(2, 0), 0);
123+
ASSERT_EQ(g.GameOver(), false);
124+
ASSERT_EQ(g.MakeMove(2, 1), 0);
125+
ASSERT_EQ(g.GameOver(), false);
126+
ASSERT_EQ(g.MakeMove(0, 1), 0);
127+
ASSERT_EQ(g.GameOver(), false);
128+
ASSERT_EQ(g.MakeMove(1, 2), 0);
129+
ASSERT_EQ(g.GameOver(), false);
130+
ASSERT_EQ(g.MakeMove(1, 0), 0);
131+
ASSERT_EQ(g.GameOver(), false);
132+
ASSERT_EQ(g.MakeMove(0, 0), 0);
133+
ASSERT_EQ(g.GameOver(), true);
134+
ASSERT_EQ(g.Winner(), 0);
135+
ASSERT_EQ(g.Loser(), 0);
136+
}

0 commit comments

Comments
 (0)