// subscript (operator[]) void test_cluster_subscript(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Cluster - Subscript ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("cluster with one point"); { Cluster c; Point p(10); p[5] = 3.14; c.add(p); Point p1 = c[0]; pass = p1[5] == 3.14; ec.result(pass); } ec.DESC("cluster with several point"); { Cluster c; for (int i = 0; i < 10; i ++) { Point p(10); p[5] = 3.14; c.add(p); } pass = true; for (int i = 0; i < 10; i ++) { Point p1 = c[i]; pass = pass && (p1[5] == 3.14); } ec.result(pass); } } }
// operator= void test_point_assignment(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Point - Assign ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("simple assignment"); { Point p1(50); for (int i = 0; i < 50; i++) p1[i] = 44.56 * i * i + 23.45 * i + 12.34; Point p2 = p1; pass = true; for (int i = 0; i < 50; i++) pass = pass && (p1[i] == p2[i]); ec.result(pass); } ec.DESC("chained assignment"); { Point p1(50); for (int i = 0; i < 50; i++) p1[i] = 44.56 * i * i + 23.45 * i + 12.34; Point p2(50), p3(50), p4(50), p5(50); p2 = p3 = p4 = p5 = p1; pass = true; for (int i = 0; i < 50; i++) pass = pass && (p1[i] == p2[i]); ec.result(pass); } } }
// Containment void test_cluster_contain(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Cluster - Containment ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("cluster with one point"); { Point p(10); p[0] = p[2] = p[4] = p[8] = 6.705; Cluster c; c.add(p); pass = c.contains(p); ec.result(pass); } ec.DESC("cluster with several points"); { Point p(10); p[0] = p[2] = p[4] = p[8] = 6.705; Cluster c; for (int i = 0; i < 10; i ++) { Point pp(10); for (int j = 0; j < 10; j ++) { pp[i] = 3.4 + i * 2.1 + i * i; } c.add(pp); } c.add(p); pass = c.contains(p); ec.result(pass); } } }
// Copy constructor void test_point_copying(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Point - Copy ---"); for (int run = 0; run < numRuns; run ++) { ec.DESC("simple copy"); { Point p1(50); for (int i = 0; i < 50; i ++) p1[i] = 44.56 * i * i + 23.45 * i + 12.34; Point p2(p1); pass = true; for (int i = 0; i < 50; i ++) pass = pass && (p1[i] == p2[i]); ec.result(pass); } ec.DESC("pass and return by value"); { Point p1(50); for (int i = 0; i < 50; i ++) p1[i] = 44.56 * i * i + 23.45 * i + 12.34; Point p2 = point_in_and_out(p1); pass = true; for (int i = 0; i < 50; i ++) pass = pass && (p1[i] == p2[i]); ec.result(pass); } } }
void test_piece_print(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Piece - Id-s, names, printing ---"); for (int run = 0; run < numRuns; run ++) { ec.DESC("piece id-s, names, and printing"); { Game g; // note: Game smoke test is needed first Position p0(0, 0); Simple s(g, p0, 10); Position p1(1, 0); Strategic t(g, p1, 20); Position p2(2, 2); Food f(g, p2, 5); Position p3(0, 2); Advantage a(g, p3, 3); std::stringstream ss; ss << s << ' ' << t << ' ' << f << ' ' << a; int id = 0; std::regex re("S[[:d:]]{1,}[ ]"); // ECMAScript, by default std::smatch m; std::string search_str(ss.str()); // convert string to lvalue // std::regex_search(ss.str(), m, re); std::regex_search(search_str, m, re); if (m.size() != 1) { // parse problem pass = false; } else { std::string matchStr(m[0]); std::regex r("[[:d:]]{1,}"); std::regex_search(matchStr, m, r); id = stoi(m[0]); pass = true; } std::stringstream compare; compare << 'S' << id << " T" << (id+1) << " F" << (id+2) << " D" << (id+3); pass = pass && (ss.str() == compare.str()); ec.result(pass); } } }
// Copy constructor void test_cluster_copying(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Cluster - Copy ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("simple copy"); { Point p1(10), p2(10), p3(10); Cluster c1; c1.add(p1); c1.add(p2); c1.add(p3); Cluster c2(c1); pass = (c1 == c2); ec.result(pass); } ec.DESC("chained copy"); { Point p1(10), p2(10), p3(10); Cluster c1; c1.add(p1); c1.add(p2); c1.add(p3); Cluster c2(c1), c3(c2), c4(c3); pass = (c1 == c4); ec.result(pass); } } }
// Smoketest: constructor, copy constructor, destructor void test_cluster_smoketest(ErrorContext &ec) { bool pass; ec.DESC("--- Test - Cluster - Smoketest ---"); ec.DESC("constructor, destructor"); pass = true; for (int i = 0; i < 10; i ++) { Cluster c; } ec.result(pass); ec.DESC("size getter - implement if you haven't"); pass = true; for (int i = 0; i < 10; i ++) { // Construct a Point // At the end of the block, destructor will be called Cluster c; pass = (c.getSize() == 0); if (!pass) break; } ec.result(pass); ec.DESC("copy constructor"); pass = true; for (int i = 0; i < 10; i ++) { Cluster c1, c2(c1); pass = (c1 == c2); if (!pass) break; } ec.result(pass); }
// id void test_point_id(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Point - Point ID ---"); for (int run = 0; run < numRuns; run ++) { ec.DESC("get a point's id"); { Point p(15); pass = (p.getId() >= 0); ec.result(pass); } ec.DESC("sequential id-s"); { Point **points = new Point*[100]; for (int i=0; i<100; i++) points[i] = new Point(15); pass = true; int firstId = points[0]->getId(); for (int i=0; i<100; i++) pass = pass && (points[i]->getId() == (firstId + i)); for (int i=0; i<100; i++) delete points[i]; delete [] points; ec.result(pass); } } }
// Smoketest: constructor, copy constructor, destructor, number of pieces void test_game_smoketest(ErrorContext &ec) { bool pass; ec.DESC("--- Test - Game - Smoketest ---"); ec.DESC("constructor, empty game, default grid size, destructor"); pass = true; for (int i = 0; i < 10; i ++) { Game g; pass = (g.getWidth() == 3 && g.getHeight() == 3 && g.getNumPieces() == 0); } ec.result(pass); ec.DESC("constructor with dimensions"); pass = true; for (int i = 0; i < 10; i ++) { Game g(4, 5); pass = (g.getWidth() == 4 && g.getHeight() == 5 && g.getNumPieces() == 0); } ec.result(pass); ec.DESC("insufficient dimensions (exception generated)"); pass = true; for (int i = 0; i < 10; i ++) { try { Game g(Game::MIN_WIDTH-1, 5); pass = false; } catch (InsufficientDimensionsEx &ex) { std::cerr << "Exception generated: " << ex << std::endl; pass = (ex.getName() == "InsufficientDimensionsEx"); } } ec.result(pass); }
// operator==, operator!= void test_cluster_equality(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Cluster - Equal ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("check operator== is not a dummy"); { // The requirements don't provide for many other methods that // can be used for testing, so operator== is checked first Cluster c1, c2; c1.add(Point(100)); pass = !(c1 == c2); ec.result(pass); } ec.DESC("check inequality"); { // The requirements don't provide for many other methods that // can be used for testing, so operator== is checked first Cluster c1, c2; c1.add(Point(100)); pass = (c1 != c2); ec.result(pass); } } }
// operator>>, operator<< void test_cluster_IO(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Cluster - Stream IO ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("read from a file"); { std::ifstream csv("points.csv"); Cluster c; if (csv.is_open()) { csv >> c; csv.close(); } pass = (c.getSize() == 4); ec.result(pass); } ec.DESC("read, write, and read again"); { std::ifstream csv("points.csv"); Cluster c; if (csv.is_open()) { csv >> c; csv.close(); } pass = (c.getSize() == 4); // add a point c.add(Point(5)); std::ofstream csv1("points1.csv", std::ofstream::out); csv1 << c; csv1.close(); std::ifstream csv2("points1.csv"); Cluster c2; if (csv2.is_open()) { csv2 >> c2; csv2.close(); }
void empty(ErrorContext &ec) { ec.DESC("--- Empty matrices (0 by 0) ---"); // If this test fails, it means that getrows returned a non-zero value // when called on an "empty" (0x0) matrix created with the default // constructor. ec.DESC("default constructor and getrows"); // Construct an empty matrix using the default constructor. const Matrix a; // Make sure 'getrows' method returns zero for this matrix. ec.result(a.getrows() == 0); // Same as above, for getcols instead of getrows. ec.DESC("default constructor and getcols"); ec.result(a.getcols() == 0); // If this test fails, it means that getrows returned a non-zero value // when called on an "empty" (0x0) matrix created with the 2-argument // constructor. ec.DESC("two-argument constructor and getrows"); // Construct an empty matrix using the two-argument constructor. const Matrix b(0, 0); // Make sure 'getrows' method returns zero for this matrix. ec.result(b.getrows() == 0); // Same as above, for getcols instead of getrows. ec.DESC("two-argument constructor and getcols"); ec.result(b.getcols() == 0); }
// Smoketest: constructor, copy constructor, destructor, resources void test_piece_smoketest(ErrorContext &ec) { bool pass; ec.DESC("--- Test - Unit - Smoketest ---"); ec.DESC("constructor, destructor for leaf classes from Piece hierarchy"); pass = true; for (int i = 0; i < 10; i++) { Game g; // note: Game smoke test is needed first Position p0(0, 0); Simple s(g, p0, 10); Position p1(1, 0); Strategic t(g, p1, 20); Position p2(2, 2); Food f(g, p2, 5); Position p3(0, 2); Advantage a(g, p3, 3); } ec.result(pass); }
// operator<, operator<=, operator>, operator>= // (pseudo-lexicographic comparison) void test_point_comparison(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Point - Compare ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("compare pseudo-lexicographic order"); { Point p1(50), p2(50), p3(50); for (int i = 0; i < 50; i ++) { p1[i] = i; p2[i] = i + 1.0; p3[i] = i + 2.0; } pass = (p1 < p2) && (p2 < p3) && (p1 < p3); ec.result(pass); } ec.DESC("less than, one different value, leading"); { Point p1(50), p2(50), p3(50); for (int i = 0; i < 50; i ++) { p1[i] = p2[i] = p3[i] = i; } p2[1] = p1[1] + std::numeric_limits<double>::epsilon(); p3[1] = p2[1] + std::numeric_limits<double>::epsilon(); pass = (p1 < p2) && (p2 < p3) && (p1 < p3); ec.result(pass); } ec.DESC("less than, one different value, middle"); { Point p1(50), p2(50), p3(50); for (int i = 0; i < 50; i ++) { p1[i] = p2[i] = p3[i] = i; } p2[30] = p1[30] + 0.00000001; p3[30] = p2[30] + 0.00000001; pass = (p1 < p2) && (p2 < p3) && (p1 < p3); ec.result(pass); } ec.DESC("less than, one different value, trailing"); { Point p1(50), p2(50), p3(50); for (int i = 0; i < 50; i ++) { p1[i] = p2[i] = p3[i] = i; } p2[49] = p1[49] + 0.00000001; p3[49] = p2[49] + 0.00000001; pass = (p1 < p2) && (p2 < p3) && (p1 < p3); ec.result(pass); } ec.DESC("less than or equal, equal values"); { Point p1(50), p2(50), p3(50); for (int i = 0; i < 50; i ++) { p1[i] = p2[i] = p3[i] = i; } pass = (p1 <= p2) && (p2 <= p3) && (p1 <= p3); ec.result(pass); } ec.DESC("less than or equal, one different value, trailing"); { Point p1(50), p2(50), p3(50); for (int i = 0; i < 50; i ++) { p1[i] = p2[i] = p3[i] = i; } p2[49] = p1[49] + 0.00000001; p3[49] = p2[49] + 0.00000001; pass = (p1 <= p2) && (p2 <= p3) && (p1 <= p3); ec.result(pass); } ec.DESC("more than or equal, equal values"); { Point p1(50), p2(50), p3(50); for (int i = 0; i < 50; i ++) { p1[i] = p2[i] = p3[i] = i; } pass = (p1 >= p2) && (p2 >= p3) && (p1 >= p3); ec.result(pass); } ec.DESC("more than or equal, one different value, middle"); { Point p1(50), p2(50), p3(50); for (int i = 0; i < 50; i ++) { p1[i] = p2[i] = p3[i] = i; } p2[30] = p3[30] + 0.00000001; p1[30] = p2[30] + 0.00000001; pass = (p1 >= p2) && (p2 >= p3) && (p1 >= p3); ec.result(pass); } ec.DESC("more than, one different value, middle"); { Point p1(50), p2(50), p3(50); for (int i = 0; i < 50; i ++) { p1[i] = p2[i] = p3[i] = i; } p2[30] = p3[30] + 0.00000001; p1[30] = p2[30] + 0.00000001; pass = (p1 > p2) && (p2 > p3) && (p1 > p3); ec.result(pass); } } }
// Randomization of motion void test_game_randomization(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Game - Randomization ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("position randomizer"); { std::vector<int> positions; for (int i = 0; i < 4; i++) positions.push_back(i); for (int i = 5; i < 9; i++) positions.push_back(i); Position pos; unsigned counts[9]; for (auto &c : counts) c = 0; for (int i = 0; i < 1000; i++) { pos = Game::randomPosition(positions); ++ counts[pos.x * 3 + pos.y]; } pass = counts[0] > 100 && counts[1] > 100 && counts[2] > 100 && counts[3] > 100 && counts[4] == 0 && counts[5] > 100 && counts[6] > 100 && counts[7] > 100 && counts[8] > 100; if (! pass) for (auto c : counts) std::cout << c << ' '; ec.result(pass); } ec.DESC("position randomizer, empty vector (exception generated)"); { std::vector<int> positions; try { Position pos = Game::randomPosition(positions); pass = false; } catch (PosVectorEmptyEx &ex) { std::cerr << "Exception generated: " << ex << std::endl; pass = (ex.getName() == "PosVectorEmptyEx"); } ec.result(pass); } ec.DESC("random walk of a Simple agent"); { Game g(101, 101); Position pos(50, 50); g.addSimple(Position(pos), 1000 * Game::STARTING_AGENT_ENERGY); const Piece *piece = g.getPiece(pos.x, pos.y); unsigned actionCounts[ActionType::STAY + 1]; for (auto &a : actionCounts) a = 0; Position oldPos = pos; for (int i = 0; i < 1000; i ++) { g.round(); pos = piece->getPosition(); assert(pos.x != oldPos.x || pos.y != oldPos.y); assert(piece->isViable()); ActionType actionType = g.reachSurroundings(oldPos, pos); ++ actionCounts[actionType]; oldPos = pos; } pass = actionCounts[ActionType::NE] > 100 && actionCounts[ActionType::NW] > 100 && actionCounts[ActionType::N] > 100 && actionCounts[ActionType::W] > 100 && actionCounts[ActionType::E] > 100 && actionCounts[ActionType::SW] > 100 && actionCounts[ActionType::SE] > 100 && actionCounts[ActionType::S] > 100 && actionCounts[ActionType::STAY] == 0; if (! pass) { std::cout << std::endl; for (auto c : actionCounts) std::cout << c << ' '; } ec.result(pass); } } }
// Playing and termination of a game void test_game_play(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Game - Play ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("3x3 grid, manual, game w/o resources terminates immediately"); { Game g; // manual = true, by default g.play(); // verbose = false, by default pass = (g.getNumResources() == 0); ec.result(pass); } ec.DESC("3x3 grid, manual, 1 simple, 1 resource"); { Game g; // manual = true, by default g.addSimple(1, 1); g.addFood(2, 2); g.play(false); // verbose = false, by default pass = (g.getNumResources() == 0) && (g.getNumAgents() == 1); ec.result(pass); } ec.DESC("3x3 grid, manual, 1 simple, 2 resources"); { Game g; // manual = true, by default g.addSimple(1, 1); g.addFood(2, 2); g.addAdvantage(1, 0); g.play(false); // verbose = false, by default pass = (g.getNumResources() == 0) && (g.getNumAgents() == 1); ec.result(pass); } ec.DESC("3x3 grid, manual, 1 simple, 3 resources"); { Game g; // manual = true, by default g.addSimple(0, 0); g.addFood(0, 2); g.addFood(2, 2); g.addAdvantage(1, 0); g.play(false); // verbose = false, by default pass = (g.getNumResources() == 0) && (g.getNumAgents() == 1); ec.result(pass); } ec.DESC("3x3 grid, manual, 2 simple, 3 resources"); { Game g; // manual = true, by default g.addSimple(0, 0); g.addSimple(0, 1); g.addFood(0, 2); g.addFood(2, 2); g.addAdvantage(1, 0); g.play(false); pass = (g.getNumResources() == 0) && (g.getNumAgents() == 2); ec.result(pass); } ec.DESC("3x3 grid, manual, 3 simple, 3 resources"); { Game g; // manual = true, by default g.addSimple(0, 0); g.addSimple(0, 1); g.addSimple(1, 1); g.addFood(0, 2); g.addFood(2, 2); g.addAdvantage(1, 0); g.play(false); // verbose = false, by default pass = (g.getNumResources() == 0) && (g.getNumAgents() == 3); ec.result(pass); } ec.DESC("3x3 grid, manual, 1 default strategic, 1 simple, 3 resources"); { Game g; // manual = true, by default g.addSimple(0, 0); g.addStrategic(0, 1); g.addFood(0, 2); g.addFood(2, 2); g.addAdvantage(1, 0); g.play(false); // verbose = false, by default pass = (g.getNumResources() == 0) && (g.getNumStrategic() == 1) && (g.getNumSimple() == 1); ec.result(pass); } ec.DESC("3x3 grid, manual, 1 aggressive strategic, 3 resources"); { Game g; // manual = true, by default g.addStrategic(0, 1, new AggressiveAgentStrategy(Game::STARTING_AGENT_ENERGY)); g.addFood(0, 2); g.addFood(2, 2); g.addAdvantage(1, 0); g.play(false); // verbose = false, by default pass = (g.getNumResources() == 0) && (g.getNumStrategic() == 1); ec.result(pass); } ec.DESC("3x3 grid, manual, 1 aggressive strategic, 1 far simple, 3 res"); { Game g; // manual = true, by default // In this configuration, the Simple and Strategic are far from each other // and they might or might not get close to each other before the // Resources run out g.addStrategic(0, 1, new AggressiveAgentStrategy(Game::STARTING_AGENT_ENERGY)); g.addSimple(2, 1); g.addFood(0, 2); g.addFood(2, 2); g.addAdvantage(1, 0); g.play(false); // verbose = false, by default pass = (g.getNumResources() == 0) && (g.getNumStrategic() == 1 ) && (g.getNumSimple() <= 1); // randomized game play ec.result(pass); } ec.DESC("3x3 grid, manual, 1 aggressive strategic, 1 near simple, 3 res"); { Game g; // manual = true, by default // In this configuration, the Simple gets an Advantage and when the // aggressive Strategic challenges it, the Strategic loses and disappears g.addSimple(0, 0); g.addStrategic(0, 1, new AggressiveAgentStrategy(Game::STARTING_AGENT_ENERGY)); g.addFood(0, 2); g.addFood(2, 2); g.addAdvantage(1, 0); g.play(false); // verbose = false, by default pass = (g.getNumResources() == 0) && (g.getNumSimple() == 1) && (g.getNumStrategic() == 0); ec.result(pass); } ec.DESC("3x3 grid, manual, 1 def, 1 aggr, 1 simple, 2 resources"); { Game g; // manual = true, by default // In this situation, the default flees, the aggressive attacks either // the default or the Simple, and the dies with it, leaving the other // one to win g.addStrategic(0, 0); g.addSimple(1, 0); g.addStrategic(0, 1, new AggressiveAgentStrategy(Game::STARTING_AGENT_ENERGY)); g.addFood(0, 2); g.addFood(2, 2); g.play(false); // verbose = false, by default pass = (g.getNumResources() == 0) && ((g.getNumStrategic() == 1 && g.getNumSimple() == 0) || (g.getNumStrategic() == 0 && g.getNumSimple() == 1)); ec.result(pass); } } }
// Surroundings (vector of enums of type PieceType) smoke test void test_surroundings_smoketest(ErrorContext &ec) { bool pass; ec.DESC("--- Test - Surroundings - Smoketest ---"); ec.DESC("printing PieceTypes"); pass = true; for (int i = 0; i < 10; i ++) { std::stringstream ss; ss << PieceType::SIMPLE << ' ' << PieceType::STRATEGIC << ' ' << PieceType::FOOD << ' ' << PieceType::ADVANTAGE << ' ' << PieceType::INACCESSIBLE << ' ' << PieceType::SELF << ' ' << PieceType::EMPTY; pass = (ss.str() == "0 1 2 3 4 5 6"); // if (! pass) std::cout << ss.str() << std::endl; } ec.result(pass); ec.DESC("3x3 grid, manual, surroundings of agents"); pass = true; for (int i = 0; i < 10; i ++) { Game g; // note: Game smoke test required first Position p0(0, 0); g.addSimple(p0); Position p1(1, 0); g.addStrategic(p1); Position p2(2, 2); g.addFood(p2); Position p3(0, 2); g.addAdvantage(p3); // The surroundings of the simple agent Surroundings surr = g.getSurroundings(p0); std::stringstream ss0; for (int i = 0; i < 9; i++) ss0 << surr.array[i] << ' '; pass = (ss0.str() == "4 4 4 4 5 6 4 1 6 "); if (! pass) std::cout << ss0.str() << std::endl; // The surroundings of the strategic agent surr = g.getSurroundings(p1); std::stringstream ss1; for (int i = 0; i < 9; i++) ss1 << surr.array[i] << ' '; pass = pass && (ss1.str() == "4 0 6 4 5 6 4 6 6 "); if (! pass) std::cout << ss1.str() << std::endl; } ec.result(pass); ec.DESC("4x5 grid, manual, surroundings of agents"); pass = true; for (int i = 0; i < 10; i ++) { Game g(4, 5); // note: Game smoke test required first // std::cout << g << std::endl; g.addSimple(0, 1); Position p0(0, 1); g.addAdvantage(1, 0); g.addAdvantage(1, 1); g.addFood(1, 3); g.addStrategic(2, 2); Position p1(2, 2); g.addFood(3, 1); g.addSimple(3, 2); Position p2(3, 2); g.addStrategic(4, 3); Position p3(4, 3); // The surroundings of the simple agent at p0 Surroundings surr = g.getSurroundings(p0); std::stringstream ss0; for (int i = 0; i < 9; i++) ss0 << surr.array[i] << ' '; pass = (ss0.str() == "4 4 4 6 5 6 3 3 6 "); if (! pass) std::cout << ss0.str() << std::endl; // The surroundings of the strategic agent at p1 surr = g.getSurroundings(p1); std::stringstream ss1; for (int i = 0; i < 9; i++) ss1 << surr.array[i] << ' '; pass = pass && (ss1.str() == "3 6 2 6 5 6 2 0 6 "); if (! pass) std::cout << ss1.str() << std::endl; // The surroundings of the simple agent at p2 surr = g.getSurroundings(p2); std::stringstream ss2; for (int i = 0; i < 9; i++) ss2 << surr.array[i] << ' '; pass = pass && (ss2.str() == "6 1 6 2 5 6 6 6 1 "); if (! pass) std::cout << ss2.str() << std::endl; // The surroundings of the strategic agent at p3 surr = g.getSurroundings(p3); std::stringstream ss3; for (int i = 0; i < 9; i++) ss3 << surr.array[i] << ' '; pass = pass && (ss3.str() == "0 6 4 6 5 4 4 4 4 "); if (! pass) std::cout << ss3.str() << std::endl; } ec.result(pass); }
// distanceTo void test_point_distance(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Point - Distance ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("same point"); { Point p1(50); for (int i = 0; i < 50; i++) p1[i] = 2.4 * i * i + 1.3 * i + 6.7; Point p2(p1); pass = (p1.distanceTo(p2) == 0); ec.result(pass); } ec.DESC("5 units away"); { Point p1(50); for (int i = 0; i < 50; i++) p1[i] = i; Point p2(p1); p2[1] += 5; pass = (p1.distanceTo(p2) == 5); if (!pass) std::cout << p1.distanceTo(p2) << " "; ec.result(pass); } // Integer sequence A180442 ec.DESC("distance 1612 from origin"); { Point p1(169); // 198 - 29 unsigned int start = 30; for (int i = 0; i < 169; i++) { p1[i] = start; start++; } Point origin(169); // relies on initialization to zeros pass = (p1.distanceTo(origin) == 1612); if (!pass) std::cout << p1.distanceTo(origin) << " "; ec.result(pass); } } }
// Taking turns void test_piece_turntaking(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Piece - Taking turns ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("3x3, manual, simple agent going for a resource"); { Game g(3, 3); // populate the game environment g.addFood(0, 0); g.addAdvantage(2, 1); // create a Simple, passing it the game and a position Simple s(g, Position(1, 1), Game::STARTING_AGENT_ENERGY); // create an upcast pointer to the agent for polymorphic turn taking Piece *piece = &s; // get the Surroundings for the agent's position from the Game Surroundings surr = g.getSurroundings(Position(1, 1)); // call takeTurn on the Piece pointer to the agent ActionType action = piece->takeTurn(surr); // if there is a resource, it should ask to there // and so on... pass = (action == ActionType::NW) || (action == ActionType::S); if (! pass) std::cout << action << std::endl; ec.result(pass); } ec.DESC("3x3, manual, simple agent moving to an empty position"); { Game g(3, 3); // populate the game environment g.addStrategic(0, 1); g.addSimple(1, 1); // create a Simple, passing it the game and a position Simple s(g, Position(0, 2), Game::STARTING_AGENT_ENERGY); // create an upcast pointer to the agent for polymorphic turn taking Piece *piece = &s; // get the Surroundings for the agent's position from the Game Surroundings surr = g.getSurroundings(Position(0, 2)); // call takeTurn on the Piece pointer to the agent ActionType action = piece->takeTurn(surr); // if there is a resource, it should ask to there // and so on... pass = (action == ActionType::S); if (! pass) std::cout << action << std::endl; ec.result(pass); } ec.DESC("3x3, manual, simple agent staying in place, not attacking"); { Game g(3, 3); // populate the game environment g.addStrategic(0, 1); g.addSimple(1, 1); g.addSimple(1, 2); // create a Simple, passing it the game and a position Simple s(g, Position(0, 2), Game::STARTING_AGENT_ENERGY); // create an upcast pointer to the agent for polymorphic turn taking Piece *piece = &s; // get the Surroundings for the agent's position from the Game Surroundings surr = g.getSurroundings(Position(0, 2)); // call takeTurn on the Piece pointer to the agent ActionType action = piece->takeTurn(surr); // if there is a resource, it should ask to there // and so on... pass = (action == ActionType::STAY); if (! pass) std::cout << action << std::endl; ec.result(pass); } ec.DESC("3x3, manual, resources don't move"); { Game g(3, 3); Food f(g, Position(0, 0), Game::STARTING_RESOURCE_CAPACITY); Advantage a(g, Position(2, 1), Game::STARTING_RESOURCE_CAPACITY); // create an upcast pointer to the agent for polymorphic turn taking Piece *piece[2] = { &f, &a }; // get the Surroundings for a Piece's position Surroundings surr[2] = { g.getSurroundings(Position(0, 0)), g.getSurroundings(Position(2, 1)) }; // call takeTurn on the Piece pointer ActionType actions[2] = { piece[0]->takeTurn(surr[0]), piece[1]->takeTurn(surr[1]) }; pass = (actions[0] == ActionType::STAY) && (actions[1] == ActionType::STAY); ec.result(pass); } ec.DESC("3x3, manual, default strategic agent choosing an advantage"); { Game g(3, 3); // populate the game environment g.addFood(0, 0); g.addAdvantage(2, 1); // create a default Strategic, passing it the game and a position Strategic s(g, Position(1, 1), Game::STARTING_AGENT_ENERGY); // create an upcast pointer to the agent for polymorphic turn taking Piece *piece = &s; // get the Surroundings for the agent's position from the Game Surroundings surr = g.getSurroundings(Position(1, 1)); // call takeTurn on the Piece pointer to the agent ActionType action = piece->takeTurn(surr); // if there is a resource, it should ask to there // and so on... pass = (action == ActionType::S); if (! pass) std::cout << action << std::endl; ec.result(pass); } ec.DESC("3x3, manual, hemmed in default strategic challenging a simple"); { Game g(3, 3); // populate the game environment g.addSimple(0, 0); g.addSimple(0, 1); g.addSimple(0, 2); g.addStrategic(1, 0); g.addStrategic(1, 2); g.addSimple(2, 0); g.addSimple(2, 1); g.addSimple(2, 2); // create a default Strategic, passing it the game and a position Strategic s(g, Position(1, 1), Game::STARTING_AGENT_ENERGY); // create an upcast pointer to the agent for polymorphic turn taking Piece *piece = &s; // get the Surroundings for the agent's position from the Game Surroundings surr = g.getSurroundings(Position(1, 1)); // call takeTurn on the Piece pointer to the agent ActionType action = piece->takeTurn(surr); // if there is a resource, it should ask to there // and so on... pass = (action == ActionType::NW) || (action == ActionType::N) || (action == ActionType::NE) || (action == ActionType::SW) || (action == ActionType::S) || (action == ActionType::SE); if (! pass) std::cout << action << std::endl; ec.result(pass); } ec.DESC("3x3, manual, hemmed in default strategic staying put"); { Game g(3, 3); // populate the game environment g.addStrategic(0, 0); g.addStrategic(0, 1); g.addStrategic(0, 2); g.addStrategic(1, 0); g.addStrategic(1, 2); g.addStrategic(2, 0); g.addStrategic(2, 1); g.addStrategic(2, 2); // create a default Strategic, passing it the game and a position Strategic s(g, Position(1, 1), Game::STARTING_AGENT_ENERGY); // create an upcast pointer to the agent for polymorphic turn taking Piece *piece = &s; // get the Surroundings for the agent's position from the Game Surroundings surr = g.getSurroundings(Position(1, 1)); // call takeTurn on the Piece pointer to the agent ActionType action = piece->takeTurn(surr); // if there is a resource, it should ask to there // and so on... pass = (action == ActionType::STAY); if (! pass) std::cout << action << std::endl; ec.result(pass); } ec.DESC("3x3, manual, hemmed in default strategic fleeing"); { Game g(3, 3); // populate the game environment g.addStrategic(0, 0); g.addStrategic(0, 1); g.addStrategic(0, 2); g.addStrategic(1, 0); g.addStrategic(2, 0); g.addStrategic(2, 1); g.addStrategic(2, 2); // create a default Strategic, passing it the game and a position Strategic s(g, Position(1, 1), Game::STARTING_AGENT_ENERGY); // create an upcast pointer to the agent for polymorphic turn taking Piece *piece = &s; // get the Surroundings for the agent's position from the Game Surroundings surr = g.getSurroundings(Position(1, 1)); // call takeTurn on the Piece pointer to the agent ActionType action = piece->takeTurn(surr); // if there is a resource, it should ask to there // and so on... pass = (action == ActionType::E); if (! pass) std::cout << action << std::endl; ec.result(pass); } ec.DESC("3x3, manual, hemmed in aggressive strategic attacking"); { Game g(3, 3); // populate the game environment g.addStrategic(0, 0); g.addStrategic(0, 1); g.addStrategic(0, 2); g.addStrategic(1, 0); g.addStrategic(2, 0); g.addStrategic(2, 1); g.addStrategic(2, 2); // create an aggressive Strategic, passing it the game and a position Strategic s(g, Position(1, 1), Game::STARTING_AGENT_ENERGY, new AggressiveAgentStrategy(Game::STARTING_AGENT_ENERGY)); // create an upcast pointer to the agent for polymorphic turn taking Piece *piece = &s; // get the Surroundings for the agent's position from the Game Surroundings surr = g.getSurroundings(Position(1, 1)); // call takeTurn on the Piece pointer to the agent ActionType action = piece->takeTurn(surr); // if there is a resource, it should ask to there // and so on... pass = (action != ActionType::E); if (! pass) std::cout << action << std::endl; ec.result(pass); } ec.DESC("3x3, manual, strong aggressive strategic prefers to attack"); { Game g(3, 3); // populate the game environment g.addFood(0, 0); g.addAdvantage(0, 2); g.addStrategic(1, 0); g.addFood(2, 1); g.addSimple(2, 2); // create an aggressive Strategic, passing it the game and a position Strategic s(g, Position(1, 1), Game::STARTING_AGENT_ENERGY, new AggressiveAgentStrategy(Game::STARTING_AGENT_ENERGY)); // create an upcast pointer to the agent for polymorphic turn taking Piece *piece = &s; // get the Surroundings for the agent's position from the Game Surroundings surr = g.getSurroundings(Position(1, 1)); // call takeTurn on the Piece pointer to the agent ActionType action = piece->takeTurn(surr); // if there is a resource, it should ask to there // and so on... pass = (action == ActionType::W) || (action == ActionType::SE); if (! pass) std::cout << action << std::endl; ec.result(pass); } ec.DESC("3x3, manual, weak aggressive strategic goes for an advantage"); { Game g(3, 3); // populate the game environment g.addFood(0, 0); g.addAdvantage(0, 2); g.addStrategic(1, 0); g.addFood(2, 1); g.addSimple(2, 2); // create an aggressive Strategic, passing it the game and a position double energy = Game::STARTING_AGENT_ENERGY / 2; // weaken the agent Strategic s(g, Position(1, 1), energy, new AggressiveAgentStrategy(energy)); // create an upcast pointer to the agent for polymorphic turn taking Piece *piece = &s; // get the Surroundings for the agent's position from the Game Surroundings surr = g.getSurroundings(Position(1, 1)); // call takeTurn on the Piece pointer to the agent ActionType action = piece->takeTurn(surr); // if there is a resource, it should ask to there // and so on... pass = (action == ActionType::NE); if (! pass) std::cout << action << std::endl; ec.result(pass); } } }
// populate the game grid void test_game_populate(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Game - Populate ---"); // note: piece smoke test needed first for (int run = 0; run < numRuns; run ++) { ec.DESC("3x3 grid, manual population"); { Game g; g.addSimple(0, 0); g.addStrategic(1, 1); g.addFood(0, 2); g.addFood(2, 1); g.addAdvantage(2, 2); pass = (g.getNumPieces() == 5) && (g.getNumAgents() == 2) && (g.getNumResources() == 3); ec.result(pass); } ec.DESC("4x5 grid, manual population"); { Game g(4, 5); g.addSimple(0, 0); g.addStrategic(1, 1); g.addFood(0, 2); g.addFood(2, 1); g.addAdvantage(2, 2); g.addSimple(4, 3); g.addAdvantage(2, 3); try { g.addFood(4, 3); pass = false; } catch (PositionNonemptyEx &ex) { std::cerr << "Exception generated: " << ex << std::endl; pass = (ex.getName() == "PositionNonemptyEx"); } try { g.addStrategic(0, 2); pass = false; } catch (PositionNonemptyEx &ex) { std::cerr << "Exception generated: " << ex << std::endl; pass = (ex.getName() == "PositionNonemptyEx"); } pass = pass && (g.getNumPieces() == 7) && (g.getNumAgents() == 3) && (g.getNumResources() == 4); ec.result(pass); } ec.DESC("4x5 grid, manual, out of bounds (exception generated)"); { Game g(4, 5); g.addSimple(0, 0); g.addStrategic(1, 1); g.addFood(0, 2); try { g.addAdvantage(4, 5); pass = false; } catch (OutOfBoundsEx &ex) { std::cerr << "Exception generated: " << ex << std::endl; pass = pass && (ex.getName() == "OutOfBoundsEx"); } try { Position pos(6, 10); g.addStrategic(pos); pass = false; } catch (OutOfBoundsEx &ex) { std::cerr << "Exception generated: " << ex << std::endl; pass = pass && (ex.getName() == "OutOfBoundsEx"); } ec.result(pass); } ec.DESC("3x3 grid, auto population"); { Game g(3, 3, false); pass = (g.getNumAgents() == 2) && (g.getNumResources() == 4); ec.result(pass); } ec.DESC("4x5 grid, auto population"); { Game g(4, 5, false); pass = (g.getNumAgents() == 5) && (g.getNumResources() == 10); ec.result(pass); } ec.DESC("9x9 grid, auto population"); { Game g(9, 9, false); pass = (g.getNumAgents() == 20) && (g.getNumResources() == 40); if (! pass) std::cout << g.getNumAgents() << ' ' << g.getNumResources() << ' ' << std::endl << g << ' '; ec.result(pass); } } }
// Action smoke test void test_action_smoketest(ErrorContext &ec) { bool pass; ec.DESC("--- Test - Action - Smoketest ---"); ec.DESC("printing ActionType"); pass = true; for (int i = 0; i < 10; i ++) { std::stringstream ss; ss << ActionType::N << ' ' << ActionType::NE << ' ' << ActionType::NW << ' ' << ActionType::E << ' ' << ActionType::W << ' ' << ActionType::SE << ' ' << ActionType::SW << ' ' << ActionType::S << ' ' << ActionType::STAY; pass = (ss.str() == "0 1 2 3 4 5 6 7 8"); // if (! pass) std::cout << ss.str() << std::endl; } ec.result(pass); ec.DESC("3x3, manual, agent in the middle"); pass = true; for (int i = 0; i < 10; i ++) { Game g; // not actually necessary for the test g.addSimple(1, 1); Position pos(1, 1); pass = g.isLegal(ActionType::N, pos) && g.isLegal(ActionType::NE, pos) && g.isLegal(ActionType::NW, pos) && g.isLegal(ActionType::E, pos) && g.isLegal(ActionType::W, pos) && g.isLegal(ActionType::SE, pos) && g.isLegal(ActionType::SW, pos) && g.isLegal(ActionType::S, pos) && g.isLegal(ActionType::STAY, pos); } ec.result(pass); ec.DESC("7x6, manual, agent in the SW corner"); pass = true; for (int i = 0; i < 10; i ++) { Game g(7, 6); // not actually necessary for the test g.addSimple(5, 6); Position pos(5, 6); pass = g.isLegal(ActionType::N, pos) && (! g.isLegal(ActionType::NE, pos)) && g.isLegal(ActionType::NW, pos) && (! g.isLegal(ActionType::E, pos)) && g.isLegal(ActionType::W, pos) && (! g.isLegal(ActionType::SE, pos)) && (! g.isLegal(ActionType::SW, pos)) && (! g.isLegal(ActionType::S, pos)) && g.isLegal(ActionType::STAY, pos); } ec.result(pass); ec.DESC("7x6, movement from position to position"); pass = true; for (int i = 0; i < 10; i ++) { Game g(13, 9); // width - y, height - x g.addSimple(0, 12); Position ne(0, 12); Position p0 = (g.isLegal(ActionType::NE, ne)) ? g.move(ne, ActionType::NE) : ne; pass = (p0.x == ne.x) && (p0.y == ne.y); p0 = (g.isLegal(ActionType::S, ne)) ? g.move(ne, ActionType::S) : ne; pass = pass && (p0.x == ne.x+1) && (p0.y == ne.y); p0 = (g.isLegal(ActionType::W, ne)) ? g.move(ne, ActionType::W) : ne; pass = pass && (p0.x == ne.x) && (p0.y == ne.y-1); p0 = (g.isLegal(ActionType::SE, ne)) ? g.move(ne, ActionType::SE) : ne; pass = pass && (p0.x == ne.x) && (p0.y == ne.y); } ec.result(pass); ec.DESC("7x6, action needed to reach one position from another"); pass = true; for (int i = 0; i < 10; i ++) { Game g(5, 5); g.addSimple(1, 1); Position simpos(1, 1); g.addFood(1, 2); Position foodpos(1, 2); pass = (Game::reachSurroundings(simpos, foodpos) == ActionType::E); g.addAdvantage(0, 1); Position adpos(0, 1); pass = pass && (Game::reachSurroundings(simpos, adpos) == ActionType::N); Position newpos(2, 0); pass = pass && (Game::reachSurroundings(simpos, newpos) == ActionType::SW); } ec.result(pass); }
//operator+=, operator-=, operator*=, operator/= void test_point_CAO(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Point - Compound arithmetic ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("plus equals (two points)"); { Point p1(50), p2(50); for (int i = 0; i < 50; i++) { p1[i] = i; p2[i] = i + 1; } Point p3(50); p3 += p1 += p2; pass = true; for (int i = 0; i < 50; i++) { pass = pass && (p3[i] == 2 * i + 1); } ec.result(pass); } ec.DESC("minus equals (two points)"); { Point p1(50), p2(50), p3(50); for (int i = 0; i < 50; i++) { p1[i] = i; p2[i] = i + 1; p3[i] = 3 * i + 1; } p3 -= p2 -= p1; pass = true; for (int i = 0; i < 50; i++) { pass = pass && (p3[i] == 3 * i); } ec.result(pass); } ec.DESC("times equals (point and double)"); { Point p1(50); for (int i = 0; i < 50; i++) { p1[i] = i; } p1 *= 3.14; pass = true; for (int i = 0; i < 50; i++) { pass = pass && (p1[i] == 3.14 * i); } ec.result(pass); } ec.DESC("divide equals (point and double)"); { Point p1(50); for (int i = 0; i < 50; i++) { p1[i] = 100.0 * i; } p1 /= 3.14; pass = true; for (int i = 0; i < 50; i++) { pass = pass && (p1[i] == 100.0 * i / 3.14); } ec.result(pass); } } }
//operator+, operator-, operator*, operator/ void test_point_SAO(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Point - Simple arithmetic ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("plus (two points)"); { Point p1(50), p2(50); for (int i = 0; i < 50; i++) { p1[i] = i; p2[i] = i + 1; } Point p3 = p1 + p2; pass = true; for (int i = 0; i < 50; i++) { pass = pass && (p3[i] == 2 * i + 1); } ec.result(pass); } ec.DESC("minus (two points)"); { Point p1(50), p2(50); for (int i = 0; i < 50; i++) { p1[i] = i + 1; p2[i] = 2 * i - 1; } Point p3 = p2 - p1; pass = true; for (int i = 0; i < 50; i++) { pass = pass && (p3[i] == i - 2); } ec.result(pass); } ec.DESC("times (point and double)"); { Point p1(50); for (int i = 0; i < 50; i++) { p1[i] = i; } Point p2 = p1 * 3.14; pass = true; for (int i = 0; i < 50; i++) { pass = pass && (p2[i] == 3.14 * i); } ec.result(pass); } ec.DESC("divide (point and double)"); { Point p1(50); for (int i = 0; i < 50; i++) { p1[i] = 100.0 * i; } Point p2 = p1 / 3.14; pass = true; for (int i = 0; i < 50; i++) { pass = pass && (p2[i] == 100.0 * i / 3.14); } ec.result(pass); } } }
// setValue, getValue, operator[] void test_point_getsetelem(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Point - Get/set element ---"); for (int run = 0; run < numRuns; run ++) { ec.DESC("values default to zero"); { Point p(50); // Check zeros pass = true; for (int i = 0; i < 50; i ++) { pass = pass && (p.getValue(i) == 0.0) && (p[i] == 0.0); } ec.result(pass); } ec.DESC("setValue, getValue (0-indexed)"); { Point p(20); // Set values for (int i = 0; i < 20; i ++) p.setValue(i, 13.43 * i * i + 4.567 * i + 1.234567); // Check values pass = true; for (int i = 0; i < 20; i ++) pass = pass && (p.getValue(i) == (13.43 * i * i + 4.567 * i + 1.234567)) && (p[i] == (13.43 * i * i + 4.567 * i + 1.234567)); ec.result(pass); } ec.DESC("operator[] (0-indexed)"); { Point p(5); // Set values for (int i = 0; i < 5; i ++) p[i] = 1000000.43 * i * i + 400000.567 * i + 10000.234567; // Check values pass = true; for (int i = 0; i < 5; i ++) pass = pass && (p.getValue(i) == (1000000.43 * i * i + 400000.567 * i + 10000.234567)) && (p[i] == (1000000.43 * i * i + 400000.567 * i + 10000.234567)); ec.result(pass); } } }
// add, remove void test_cluster_addremove(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Cluster - Add/remove points ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("add and check with size getter"); { Cluster c1; c1.add(Point(50)); c1.add(Point(50)); c1.add(Point(50)); pass = (c1.getSize() == 3); ec.result(pass); } // by default, points will get released here ec.DESC("add, remove, and check with size getter"); { Point p1(10), p2(10), p3(10); Cluster c1; c1.add(p1); c1.add(p2); c1.add(p3); c1.remove(p1); c1.remove(p2); c1.remove(p3); pass = (c1.getSize() == 0); if (!pass) { std::cout << std::endl; std::cout << c1 << std::endl; std::cout << std::endl; } ec.result(pass); } // by default, points will get released here ec.DESC("add, check with cluster equality, remove"); { Point p1(10), p2(10), p3(10); Cluster c1, c2; c1.add(p1); c1.add(p2); c1.add(p3); c2.add(p1); c2.add(p2); c2.add(p3); pass = (c1 == c2); // don't forget to remove the points from one // of the clusters to avoid the "double delete" c2.remove(p1); c2.remove(p2); c2.remove(p3); ec.result(pass); } ec.DESC("check point after add and remove"); { Point p1(10); for (int i = 0; i < 10; i++) p1[i] = 5.4 * i * i + 3.4 * i + 1.6; Cluster c1; c1.add(p1); Point p2 = c1.remove(p1); pass = (p1 == p2); ec.result(pass); } } }
// operator+, operator-, different rhs void test_cluster_SAO(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Cluster - Simple arithmetic ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("plus (Cluster and Point)"); { Cluster c1, c2; Point p1(50), p2(50), p3(50), p4(50); c1.add(p1); c1.add(p2); c1.add(p3); c2 = c1; c2.add(p4); Cluster c3 = c1 + p4; pass = (c3 == c2); ec.result(pass); } ec.DESC("minus (Cluster and Point)"); { Cluster c1, c2; Point p1(50), p2(50), p3(50), p4(50); c1.add(p1); c1.add(p2); c1.add(p3); c1.add(p4); c2 = c1; c2.remove(p4); Cluster c3 = c1 - p4; pass = (c3 == c2); ec.result(pass); } ec.DESC("plus (Cluster union)"); { Cluster c1, c2; Point p1(50), p2(50), p3(50), p4(50), p5(50); c1.add(p1); c1.add(p2); c1.add(p3); c2.add(p4); c2.add(p5); Cluster c3; c3.add(p1); c3.add(p2); c3.add(p3); c3.add(p4); c3.add(p5); Cluster c4 = c1 + c2; pass = (c4 == c3); ec.result(pass); } ec.DESC("minus (Cluster difference)"); { Cluster c1, c2; Point p1(50), p2(50), p3(50), p4(50), p5(50); c1.add(p1); c1.add(p2); c1.add(p3); c2.add(p3); c2.add(p4); c2.add(p5); Cluster c3; c3.add(p1); c3.add(p2); Cluster c4 = c1 - c2; pass = (c4 == c3); ec.result(pass); } } }
// ascending pseudo-lexicographic order void test_cluster_order(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Cluster - Order ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("points in a cluster are sorted"); { Point p1(5), p2(5), p3(5), p4(5), p5(5); p1[0] = 1; p2[1] = 1; p3[2] = 1; p4[3] = 1; p5[4] = 1; Cluster c; c.add(p1); c.add(p2); c.add(p4); c.add(p3); c.add(p5); pass = (c[0] == p5) && (c[1] == p4) && (c[2] == p3) && (c[3] == p2) && (c[4] == p1); if (!pass) { std::cout << std::endl; std::cout << c << std::endl; std::cout << std::endl; } ec.result(pass); } ec.DESC("ascending pseudo-lexicographic order"); { Point p1(5), p2(5), p3(5), p4(5), p5(5); p1[0] = 1; p2[1] = 1; p3[2] = -1; p4[3] = 1; p5[4] = -1; Cluster c; c.add(p1); c.add(p2); c.add(p4); c.add(p3); c.add(p5); pass = (c[0] == p3) && (c[1] == p5) && (c[2] == p4) && (c[3] == p2) && (c[4] == p1); if (!pass) { std::cout << std::endl; std::cout << c << std::endl; std::cout << std::endl; } ec.result(pass); } } }
// Piece interaction operator* void test_piece_interaction(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Piece - Interaction ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("3x3, manual, two agents with equal energy"); { Game g; Simple s0(g, Position(2, 0), Game::STARTING_AGENT_ENERGY); Strategic s1(g, Position(1, 1), Game::STARTING_AGENT_ENERGY); Piece *pieces[2] = { &s0, &s1 }; Piece &p0 = *pieces[0], &p1 = *pieces[1]; p1 * p0; pass = (! p0.isViable()) && (! p1.isViable()); ec.result(pass); } ec.DESC("3x3, manual, two agents with inequal energy"); { Game g; Simple s0(g, Position(2, 0), Game::STARTING_AGENT_ENERGY); Strategic s1(g, Position(1, 1), Game::STARTING_AGENT_ENERGY * 1.1); Piece *pieces[2] = { &s0, &s1 }; Piece &p0 = *pieces[0], &p1 = *pieces[1]; p1 * p0; pass = (! p0.isViable()) && p1.isViable(); ec.result(pass); } ec.DESC("3x3, manual, a simple agent and a resource"); { Game g; Food s0(g, Position(2, 0), Game::STARTING_RESOURCE_CAPACITY); Strategic s1(g, Position(1, 1), Game::STARTING_AGENT_ENERGY * 1.1); Piece *pieces[2] = { &s0, &s1 }; Piece &p0 = *pieces[0], &p1 = *pieces[1]; p1 * p0; pass = (! p0.isViable()) && p1.isViable(); ec.result(pass); } ec.DESC("3x3, manual, no interaction between resources"); { Game g; Food s0(g, Position(2, 0), Game::STARTING_RESOURCE_CAPACITY); Food s1(g, Position(1, 1), Game::STARTING_RESOURCE_CAPACITY); Piece *pieces[2] = { &s0, &s1 }; Piece &p0 = *pieces[0], &p1 = *pieces[1]; p1 * p0; pass = p0.isViable() && p1.isViable(); ec.result(pass); } } }
//// operator= void test_cluster_assignment(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Cluster - Assign ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("simple assignment"); { Point p1(10), p2(10), p3(10); Cluster c1; c1.add(p1); c1.add(p2); c1.add(p3); Cluster c2 = c1; pass = (c1 == c2); ec.result(pass); } ec.DESC("assignment causing deletion"); { Point p1(10), p2(10), p3(10); Cluster c1; c1.add(p1); c1.add(p2); c1.add(p3); Cluster c2; // add some other points c2.add(Point(10)); c2.add(Point(10)); c2.add(Point(10)); c2 = c1; pass = (c1 == c2); ec.result(pass); } ec.DESC("chained assignment"); { Point p1(10), p2(10), p3(10); Cluster c1; c1.add(p1); c1.add(p2); c1.add(p3); Cluster c2 = c1; Cluster c3 = c2; Cluster c4 = c3; pass = (c1 == c4); ec.result(pass); } } }
// operator+=, operator-=, different rhs void test_cluster_CAO(ErrorContext &ec, unsigned int numRuns) { bool pass; // Run at least once!! assert(numRuns > 0); ec.DESC("--- Test - Cluster - Compound arithmetic ---"); for (int run = 0; run < numRuns; run++) { ec.DESC("plus equals (Cluster and Point) check with non-equality"); { Cluster c1, c2; Point p1(50); for (int i = 0; i < 50; i++) p1[i] = 6.75 * i * i + 5.45 * i + 1.15; c1 += p1; pass = !(c1 == c2); ec.result(pass); } ec.DESC("plus equals (Cluster and Point) check with size getter"); { Cluster c1; Point p1(50); for (int i = 0; i < 50; i++) p1[i] = 6.75 * i * i + 5.45 * i + 1.15; c1 += p1; pass = (c1.getSize() == 1); ec.result(pass); } ec.DESC("minus equals (Cluster and Point) check with non-equality"); { Cluster c1, c2; Point p1(50); for (int i = 0; i < 50; i++) p1[i] = 6.75 * i * i + 5.45 * i + 1.15; c1 += p1; pass = !(c1 == c2); c1 -= p1; pass = (c1 == c2); ec.result(pass); } ec.DESC("minus equals (Cluster and Point) check with size getter"); { Cluster c1; Point p1(50); for (int i = 0; i < 50; i++) p1[i] = 6.75 * i * i + 5.45 * i + 1.15; c1 += p1; pass = (c1.getSize() == 1); c1 -= p1; pass = (c1.getSize() == 0); ec.result(pass); } ec.DESC("plus equals (Cluster union) no common points"); { Cluster c1, c2, c3; Point p1(50), p2(50), p3(50), p4(50), p5(50); c1.add(p1); c1.add(p2); c1.add(p3); c2.add(p4); c2.add(p5); // create a union to compare to c3.add(p1); c3.add(p2); c3.add(p3); c3.add(p4); c3.add(p5); c1 += c2; pass = (c1 == c3); ec.result(pass); } ec.DESC("plus equals (Cluster union) one common point"); { Cluster c1, c2, c3; Point p1(50), p2(50), p3(50), p4(50), p5(50); c1.add(p1); c1.add(p2); c1.add(p3); c2.add(p3); c2.add(p4); c2.add(p5); // create a union to compare to c3.add(p1); c3.add(p2); c3.add(p3); c3.add(p4); c3.add(p5); c1 += c2; pass = (c1 == c3); ec.result(pass); } ec.DESC("plus equals (Cluster union) two equal clusters"); { Cluster c1, c2; Point p1(50), p2(50), p3(50), p4(50), p5(50); c1.add(p1); c1.add(p2); c1.add(p3); c1.add(p4); c1.add(p5); c2.add(p1); c2.add(p2); c2.add(p3); c2.add(p4); c2.add(p5); c1 += c2; pass = (c1 == c2); ec.result(pass); } ec.DESC("minus equals (asymmetric Cluster difference) no common points"); { Cluster c1, c2, c3; Point p1(50), p2(50), p3(50), p4(50), p5(50); c1.add(p1); c1.add(p2); c1.add(p3); c2.add(p4); c2.add(p5); c3 = c1; c1 -= c2; pass = (c1 == c3); ec.result(pass); } ec.DESC("minus equals (asymmetric Cluster difference) one common point"); { Cluster c1, c2, c3; Point p1(50), p2(50), p3(50), p4(50), p5(50); c1.add(p1); c1.add(p2); c1.add(p3); c2.add(p3); c2.add(p4); c2.add(p5); // Prepare a difference to compare to c3.add(p1); c3.add(p2); c1 -= c2; pass = (c1 == c3); ec.result(pass); } ec.DESC("minus equals (asymmetric Cluster difference) two equal clusters"); { Cluster c1, c2, c3; Point p1(50), p2(50), p3(50), p4(50), p5(50); c1.add(p1); c1.add(p2); c1.add(p3); c1.add(p4); c1.add(p5); c2.add(p1); c2.add(p2); c2.add(p3); c2.add(p4); c2.add(p5); c1 -= c2; pass = (c1 == c3); // c1 should be empty ec.result(pass); } } }