File indexing completed on 2024-11-24 03:43:17

0001 /*******************************************************************
0002  *
0003  * Copyright 2002,2007 Aron Boström <aron.bostrom@gmail.com>
0004  *
0005  * This file is part of the KDE project "Bovo"
0006  *
0007  * Bovo is free software; you can redistribute it and/or modify
0008  * it under the terms of the GNU General Public License as published by
0009  * the Free Software Foundation; either version 2, or (at your option)
0010  * any later version.
0011  *
0012  * Bovo is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015  * GNU General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU General Public License
0018  * along with Bovo; see the file COPYING.  If not, write to
0019  * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
0020  * Boston, MA 02110-1301, USA.
0021  *
0022  ********************************************************************/
0023 
0024 #include <cstdlib>
0025 #include <ctime>
0026 #include <iostream>
0027 
0028 #include "board.h"
0029 #include "dim.h"
0030 
0031 using namespace luffarschack;
0032 using namespace std;
0033 
0034 struct error {
0035 };
0036 
0037 int tests = 0;
0038 char ESC = 27;
0039 
0040 void ok(const string &s)
0041 {
0042     cout << "   " << s << "... ";
0043     cout.setf(ios::right);
0044     cout << ESC << "[32m"
0045          << " [OK] " << ESC << "[0m" << endl;
0046     cout.setf(ios::left);
0047     ++tests;
0048 }
0049 
0050 void fail(const string &s)
0051 {
0052     cout << "   " << s << "... ";
0053     cout.setf(ios::right);
0054     cout << ESC << "[31m"
0055          << " FAILED! " << ESC << "[0m" << endl;
0056     cout.setf(ios::left);
0057 }
0058 
0059 void ass(const bool b, const string &s) throw(error)
0060 {
0061     if (b) {
0062         ok(s);
0063         return;
0064     } else {
0065         fail(s);
0066         throw error();
0067     }
0068 }
0069 
0070 void status(const string &s)
0071 {
0072     cout << endl << ESC << "[33m" << s << ':' << ESC << "[0m" << endl;
0073 }
0074 
0075 void testWidthHeight() throw(error)
0076 {
0077     status("Testing width and height");
0078     short int WIDTH = 7;
0079     short int HEIGHT = 9;
0080     board b(WIDTH, HEIGHT);
0081     ass(b.width() == WIDTH, "width() for board(int, int)");
0082     ass(b.height() == HEIGHT, "height() for board(int, int)");
0083     ass(b.width() != HEIGHT, "width != height for board(int, int)");
0084     WIDTH = 13;
0085     board b2(dim(WIDTH, HEIGHT));
0086     ass(b2.width() == WIDTH, "width() for board(dim)");
0087     ass(b2.height() == HEIGHT, "height() for board(dim)");
0088     ass(b2.height() != WIDTH, "height != width for board(dim)");
0089 }
0090 
0091 void testOutsideBoundaries() throw(error)
0092 {
0093     status("Testing boundaries");
0094     short int WIDTH = 3;
0095     short int HEIGHT = 4;
0096     board b(WIDTH, HEIGHT);
0097     board b2(dim(WIDTH, HEIGHT));
0098     bool test = false;
0099     try {
0100         for (short int i = 0; i < WIDTH; ++i)
0101             for (short int j = 0; j < HEIGHT; ++j) {
0102                 coord c(i, j);
0103                 b.empty(c);
0104                 b2.empty(c);
0105                 b.player(c);
0106                 b2.player(c);
0107             }
0108         test = true;
0109     } catch (outOfBounds) {
0110         test = false;
0111     }
0112     ass(test, "inside boundaries");
0113     test = false;
0114     try {
0115         coord c(-1, 0);
0116         b.empty(c);
0117         test = false;
0118     } catch (outOfBounds) {
0119         test = true;
0120     }
0121     ass(test, "empty() lesser than width");
0122     test = false;
0123     try {
0124         coord c(0, -1);
0125         b.empty(c);
0126         test = false;
0127     } catch (outOfBounds) {
0128         test = true;
0129     }
0130     ass(test, "empty() lesser than height");
0131     test = false;
0132     try {
0133         coord c(WIDTH, 0);
0134         b.empty(c);
0135         test = false;
0136     } catch (outOfBounds) {
0137         test = true;
0138     }
0139     ass(test, "empty() too wide");
0140     test = false;
0141     try {
0142         coord c(0, HEIGHT);
0143         b.empty(c);
0144         test = false;
0145     } catch (outOfBounds) {
0146         test = true;
0147     }
0148     ass(test, "empty() too high");
0149     test = false;
0150     try {
0151         coord c(-1, 0);
0152         b.player(c);
0153         test = false;
0154     } catch (outOfBounds) {
0155         test = true;
0156     }
0157     ass(test, "player() lesser than width");
0158     test = false;
0159     try {
0160         coord c(0, -1);
0161         b.player(c);
0162         test = false;
0163     } catch (outOfBounds) {
0164         test = true;
0165     }
0166     ass(test, "player() lesser than height");
0167     test = false;
0168     try {
0169         coord c(WIDTH, 0);
0170         b.player(c);
0171         test = false;
0172     } catch (outOfBounds) {
0173         test = true;
0174     }
0175     ass(test, "player() too wide");
0176     test = false;
0177     try {
0178         coord c(0, HEIGHT);
0179         b.player(c);
0180         test = false;
0181     } catch (outOfBounds) {
0182         test = true;
0183     }
0184     ass(test, "player() too high");
0185     test = false;
0186     try {
0187         coord c(-1, 0);
0188         b.setPlayer(c, 1);
0189         test = false;
0190     } catch (outOfBounds) {
0191         test = true;
0192     }
0193     ass(test, "setPlayer() lesser than width");
0194     test = false;
0195     try {
0196         coord c(0, -1);
0197         b.setPlayer(c, 1);
0198         test = false;
0199     } catch (outOfBounds) {
0200         test = true;
0201     }
0202     ass(test, "setPlayer() lesser than height");
0203     test = false;
0204     try {
0205         coord c(WIDTH, 0);
0206         b.setPlayer(c, 1);
0207         test = false;
0208     } catch (outOfBounds) {
0209         test = true;
0210     }
0211     ass(test, "setPlayer() too wide");
0212     test = false;
0213     try {
0214         coord c(0, HEIGHT);
0215         b.setPlayer(c, 1);
0216         test = false;
0217     } catch (outOfBounds) {
0218         test = true;
0219     }
0220     ass(test, "setPlayer() too high");
0221 }
0222 
0223 void testSetPlayerAndEmpty() throw(error)
0224 {
0225     status("Testing setPlayer(coord, unsigned short int) and checking with empty(coord) and player(coord)");
0226     unsigned short int WIDTH = 3;
0227     unsigned short int HEIGHT = 4;
0228     board b(WIDTH, HEIGHT);
0229     bool test = false;
0230     try {
0231         for (unsigned short int i = 0; i < WIDTH; ++i)
0232             for (unsigned short int j = 0; j < HEIGHT; ++j) {
0233                 coord c(i, j);
0234                 if (!b.empty(c) || b.player(c) != 0)
0235                     throw error();
0236             }
0237         test = true;
0238     } catch (error) {
0239         test = false;
0240     }
0241     ass(test, "board is empty and player is 0");
0242     test = false;
0243     try {
0244         coord c(1, 1);
0245         b.setPlayer(c, 1);
0246         for (unsigned short int i = 0; i < WIDTH; ++i)
0247             for (unsigned short int j = 0; j < HEIGHT; ++j) {
0248                 if (i == 1 && j == 1)
0249                     continue;
0250                 coord c2(i, j);
0251                 if (!b.empty(c2) || b.player(c2) != 0)
0252                     throw busy();
0253             }
0254         ass(b.player(c) == 1, "setPlayer(coord, 1) -> player(coord) == 1");
0255         test = true;
0256     } catch (busy) {
0257         test = false;
0258     }
0259     ass(test, "board should still be empty");
0260     test = false;
0261     try {
0262         coord c(1, 1);
0263         b.setPlayer(c, 1);
0264         test = false;
0265     } catch (busy) {
0266         test = true;
0267     }
0268     ass(test, "setPlayer(coord, 1) again should fail");
0269     test = false;
0270     try {
0271         coord c(1, 1);
0272         b.setPlayer(c, 2);
0273         test = false;
0274     } catch (busy) {
0275         test = true;
0276     }
0277     ass(test, "setPlayer(coord, 2) should also fail");
0278     ass(b.player(coord(1, 1)) == 1, "player(coord) should still be 1");
0279     test = false;
0280     try {
0281         for (unsigned short int i = 0; i < WIDTH; ++i)
0282             for (unsigned short int j = 0; j < HEIGHT; ++j) {
0283                 if (i == 1 && j == 1)
0284                     continue;
0285                 coord c2(i, j);
0286                 b.setPlayer(c2, 2);
0287             }
0288         ass(b.player(coord(0, 0)) == 2, "setPlayer(coord, 2) -> player(coord) == 2");
0289         test = true;
0290     } catch (busy) {
0291         test = false;
0292     }
0293     ass(test, "board should be setable");
0294 }
0295 
0296 void testGameOver()
0297 {
0298     status("Testing game over");
0299     unsigned short int WIDTH = 29;
0300     unsigned short int HEIGHT = 29;
0301     board b(dim(WIDTH, HEIGHT));
0302     ass(!b.setPlayer(coord(1, 1), 1), "not five in row shouldn't win");
0303     ass(!b.setPlayer(coord(2, 1), 1), "not five in row shouldn't win");
0304     ass(!b.setPlayer(coord(4, 1), 1), "not five in row shouldn't win");
0305     ass(!b.setPlayer(coord(5, 1), 1), "not five in row shouldn't win");
0306     ass(!b.setPlayer(coord(6, 1), 1), "not five in row shouldn't win");
0307     ass(!b.setPlayer(coord(7, 1), 1), "not five in row shouldn't win");
0308     ass(!b.setPlayer(coord(3, 1), 2), "not five in row shouldn't win");
0309     ass(!b.setPlayer(coord(8, 1), 2), "not five in row shouldn't win");
0310     ass(!b.setPlayer(coord(9, 1), 1), "not five in row shouldn't win");
0311     ass(!b.setPlayer(coord(10, 1), 1), "not five in row shouldn't win");
0312     ass(!b.setPlayer(coord(11, 1), 1), "not five in row shouldn't win");
0313     ass(!b.setPlayer(coord(13, 1), 1), "not five in row shouldn't win");
0314     ass(!b.setPlayer(coord(14, 1), 1), "not five in row shouldn't win");
0315     ass(!b.setPlayer(coord(15, 1), 1), "not five in row shouldn't win");
0316     ass(b.setPlayer(coord(12, 1), 1), "five in row should win");
0317     try {
0318         b.setPlayer(coord(16, 1), 1);
0319         ass(false, "Nothing should be done when game is over");
0320     } catch (gameover) {
0321         ass(b.empty(coord(16, 1)), "Nothing should be done when game is over");
0322     }
0323     board b5(dim(WIDTH, HEIGHT));
0324     b5.setPlayer(coord(3, 2), 2);
0325     b5.setPlayer(coord(4, 2), 2);
0326     b5.setPlayer(coord(5, 2), 2);
0327     ass(!b5.setPlayer(coord(6, 2), 2), "not five in row shouldn't win");
0328     ass(b5.setPlayer(coord(7, 2), 2), "five in row SHOULD win");
0329     board b4(dim(WIDTH, HEIGHT));
0330     b4.setPlayer(coord(0, 0), 2);
0331     b4.setPlayer(coord(1, 1), 2);
0332     b4.setPlayer(coord(2, 2), 2);
0333     ass(!b4.setPlayer(coord(3, 3), 2), "not five in diag shouldn't win");
0334     ass(b4.setPlayer(coord(4, 4), 2), "five in diag SHOULD win");
0335     board b2(dim(WIDTH, HEIGHT));
0336     b2.setPlayer(coord(4, 0), 2);
0337     b2.setPlayer(coord(3, 1), 2);
0338     b2.setPlayer(coord(2, 2), 2);
0339     ass(!b2.setPlayer(coord(1, 3), 2), "not five in other diag shouldn't win");
0340     ass(b2.setPlayer(coord(0, 4), 2), "five in other diag SHOULD win");
0341     board b3(dim(WIDTH, HEIGHT));
0342     b3.setPlayer(coord(4, 0), 2);
0343     b3.setPlayer(coord(4, 1), 2);
0344     b3.setPlayer(coord(4, 2), 2);
0345     ass(!b3.setPlayer(coord(4, 3), 2), "not five in col shouldn't win");
0346     ass(b3.setPlayer(coord(4, 4), 2), "five in col SHOULD win");
0347 }
0348 
0349 void testSetNonvalidPlayer()
0350 {
0351     status("Testing setting a non-valid player");
0352     board b = board(dim(1, 1));
0353     bool test = false;
0354     try {
0355         b.setPlayer(coord(0, 0), 0);
0356         test = false;
0357     } catch (notValidPlayer) {
0358         test = true;
0359     }
0360     ass(test, "player 0 (empty) should not work");
0361     test = false;
0362     try {
0363         b.setPlayer(coord(0, 0), 3);
0364         test = false;
0365     } catch (notValidPlayer) {
0366         test = true;
0367     }
0368     ass(test, "player 3 should not work either");
0369 }
0370 
0371 void testEcho()
0372 {
0373     board b = board(dim(20, 20));
0374     unsigned short int player = 1;
0375     qsrand((unsigned)time(0));
0376     try {
0377         while (true) {
0378             coord c(0, 0);
0379             while (true) {
0380                 c = coord(qrand() % 20, qrand() % 20);
0381                 if (b.empty(c))
0382                     break;
0383             }
0384             b.setPlayer(c, player);
0385             player = player % 2 + 1;
0386         }
0387     } catch (busy) {
0388     } catch (gameover) {
0389         cout << endl << "Player " << player % 2 + 1 << " won" << endl;
0390     }
0391     b.echo();
0392 }
0393 
0394 int main()
0395 {
0396     try {
0397         testWidthHeight();
0398         testOutsideBoundaries();
0399         testSetPlayerAndEmpty();
0400         testSetNonvalidPlayer();
0401         testGameOver();
0402         testEcho();
0403         cout << endl << ESC << "[32m" << tests << " tests passed!" << ESC << "[0m" << endl;
0404     } catch (error) {
0405         cerr << endl
0406              << ESC << "[31m"
0407              << "FEL FEL FEL!!!" << ESC << "[0m" << endl;
0408     }
0409 }