diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ find_package(ECM ${KF5_MIN_VERSION} REQUIRED CONFIG) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) -find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE COMPONENTS Widgets Svg) +find_package(Qt5 ${QT_MIN_VERSION} REQUIRED NO_MODULE COMPONENTS Widgets Svg Test) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Completion Config @@ -37,15 +37,16 @@ add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libkcardgame/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/libkcardgame/include ${FC_SOLVE_INCLUDE_DIRS}) add_subdirectory(icons) add_subdirectory(libkcardgame) add_subdirectory(mimetypes) add_subdirectory(previews) add_subdirectory(sounds) add_subdirectory(themes) add_subdirectory(doc) +add_subdirectory(autotests) set(kpat_SRCS ${libfcs_SRCS} main.cpp diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/autotests/CMakeLists.txt @@ -0,0 +1,8 @@ +include(ECMAddTests) +include_directories(AFTER "${CMAKE_CURRENT_SOURCE_DIR}/..") +ecm_add_test( + shuffle_test.cpp + TEST_NAME ShuffleTest + LINK_LIBRARIES Qt5::Test + NAME_PREFIX "kpat-" +) diff --git a/autotests/shuffle_test.cpp b/autotests/shuffle_test.cpp new file mode 100644 --- /dev/null +++ b/autotests/shuffle_test.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2018 Shlomi Fish + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include "shuffle.h" + +class TestCardsShuffle: public QObject +{ + Q_OBJECT +private slots: + void shuffle_seed1(); + void shuffle_seed24(); +}; + +typedef const char * Card; +typedef QList CardList; + + +const CardList input({"AC", "AD", "AH", "AS", "2C", "2D", "2H", "2S", "3C", "3D", "3H", "3S", "4C", "4D", "4H", "4S", "5C", "5D", "5H", "5S", "6C", "6D", "6H", "6S", "7C", "7D", "7H", "7S", "8C", "8D", "8H", "8S", "9C", "9D", "9H", "9S", "TC", "TD", "TH", "TS", "JC", "JD", "JH", "JS", "QC", "QD", "QH", "QS", "KC", "KD", "KH", "KS"} + ); + +void TestCardsShuffle::shuffle_seed1() +{ + CardList have = KpatShuffle::shuffled(input, 1); + CardList want( + {"6H", "2H", "9C", "6S", "TC", "8C", "3D", "6C", "QS", "8D", "8S", "6D", "7D", "JH", "2C", "8H", "TH", "4S", "TD", "3S", "7S", "4D", "AC", "4H", "QH", "TS", "5C", "4C", "3C", "AH", "AS", "JS", "QD", "9D", "KS", "2S", "3H", "KH", "QC", "AD", "5S", "9S", "KC", "KD", "5H", "7C", "7H", "5D", "JC", "9H", "2D", "JD"} + ); + QCOMPARE(have, want); +} + +void TestCardsShuffle::shuffle_seed24() +{ + CardList have = KpatShuffle::shuffled(input, 24); + CardList want( + {"AS", "3D", "QD", "2H", "9D", "JD", "7C", "8D", "6D", "KS", "4H", "4S", "8S", "8H", "KC", "TD", "JH", "3S", "3H", "QS", "4D", "AD", "TS", "TC", "5C", "9H", "AC", "8C", "7D", "6S", "KH", "TH", "JC", "6H", "3C", "9C", "6C", "5S", "JS", "KD", "2S", "9S", "QH", "2C", "7S", "AH", "7H", "2D", "5D", "QC", "5H", "4C"} + ); + QCOMPARE(have, want); +} + +QTEST_MAIN(TestCardsShuffle) +#include "shuffle_test.moc" diff --git a/dealer.cpp b/dealer.cpp --- a/dealer.cpp +++ b/dealer.cpp @@ -39,6 +39,7 @@ #include "dealerinfo.h" #include "messagebox.h" #include "renderer.h" +#include "shuffle.h" #include "speeds.h" #include "patsolve/solverinterface.h" #include "version.h" @@ -66,24 +67,6 @@ { const qreal wonBoxToSceneSizeRatio = 0.7; - QList shuffled( const QList & cards, unsigned int seed ) - { - QList result = cards; - for ( int i = result.size(); i > 1; --i ) - { - // We use the same pseudorandom number generation algorithm as Windows - // Freecell, so that game numbers are the same between the two applications. - // For more inforation, see - // http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q28150 - seed = 214013 * seed + 2531011; - int rand = ( seed >> 16 ) & 0x7fff; - - result.swap( i - 1, rand % i ); - } - - return result; - } - QString solverStatusMessage( int status, bool everWinnable ) { switch ( status ) @@ -843,7 +826,7 @@ p->clear(); m_dealInProgress = true; - restart( shuffled( deck()->cards(), m_dealNumber ) ); + restart( KpatShuffle::shuffled( deck()->cards(), m_dealNumber ) ); m_dealInProgress = false; takeState(); diff --git a/freecell.cpp b/freecell.cpp --- a/freecell.cpp +++ b/freecell.cpp @@ -177,7 +177,8 @@ if (c->isAnimated()) return false; - if (allowedToRemove(c->pile(), c)) + if (allowedToRemove(c->pile(), c) + && c == c->pile()->topCard()) { for (int i = 0; i < 4; i++) { diff --git a/main.cpp b/main.cpp --- a/main.cpp +++ b/main.cpp @@ -166,6 +166,9 @@ aboutData.addAuthor( i18n("Parker Coates"), i18n("Cleanup and polish"), QStringLiteral("coates@kde.org") ); + aboutData.addAuthor( i18n("Shlomi Fish"), + i18n("Integration with Freecell Solver and further work"), + QStringLiteral("shlomif@cpan.org") ); // Create a KLocale earlier than normal so that we can use i18n to translate // the names of the game types in the help text. diff --git a/shuffle.h b/shuffle.h new file mode 100644 --- /dev/null +++ b/shuffle.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 1995 Paul Olav Tvete + * Copyright (C) 2000-2009 Stephan Kulow + * Copyright (C) 2009-2010 Parker Coates + * + * License of original code: + * ------------------------------------------------------------------------- + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose and without fee is hereby granted, + * provided that the above copyright notice appear in all copies and that + * both that copyright notice and this permission notice appear in + * supporting documentation. + * + * This file is provided AS IS with no warranties of any kind. The author + * shall have no liability with respect to the infringement of copyrights, + * trade secrets or any patents by this file or any part thereof. In no + * event will the author be liable for any lost revenue or profits or + * other special, indirect and consequential damages. + * ------------------------------------------------------------------------- + * + * License of modifications/additions made after 2009-01-01: + * ------------------------------------------------------------------------- + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * ------------------------------------------------------------------------- + */ + +#include +#include + +#ifndef SHUFFLE_H +#define SHUFFLE_H +namespace KpatShuffle +{ + template + QList shuffled( const QList & cards, unsigned int seed ) + { + QList result = cards; + for ( int i = result.size(); i > 1; --i ) + { + // We use the same pseudorandom number generation algorithm as Windows + // Freecell, so that game numbers are the same between the two applications. + // For more inforation, see + // http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q28150 + seed = 214013 * seed + 2531011; + int rand = ( seed >> 16 ) & 0x7fff; + + result.swap( i - 1, rand % i ); + } + + return result; + } +}; + +#endif