├── .clang-format
├── .gitignore
├── CMakeLists.txt
├── LICENSE
├── README.md
├── images
├── c_bb.svg
├── c_bk.svg
├── c_bn.svg
├── c_bp.svg
├── c_bq.svg
├── c_br.svg
├── c_wb.svg
├── c_wk.svg
├── c_wn.svg
├── c_wp.svg
├── c_wq.svg
├── c_wr.svg
└── point.svg
├── qml
├── Board.qml
├── ChessFigure.qml
├── GameFDialog.qml
├── History.qml
└── Window.qml
├── resouces.qrc
└── src
├── CMakeLists.txt
├── chess.cpp
├── chessmodel.cc
├── chessmodel.hpp
├── figurebishop.cc
├── figurebishop.hpp
├── figureintf.cc
├── figureintf.hpp
├── figureking.cc
├── figureking.hpp
├── figureknight.cc
├── figureknight.hpp
├── figurepawn.cc
├── figurepawn.hpp
├── figurequeen.cc
├── figurequeen.hpp
├── figurerook.cc
├── figurerook.hpp
├── gameengine.cc
├── gameengine.hpp
├── historymanager.cc
├── historymanager.hpp
├── historymodel.cc
├── historymodel.hpp
├── movepawn.cc
├── movepawn.hpp
├── movepoints.cc
├── movepoints.hpp
├── movevectors.cc
└── movevectors.hpp
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | AccessModifierOffset: -1
4 | AlignAfterOpenBracket: Align
5 | AlignConsecutiveAssignments: false
6 | AlignConsecutiveDeclarations: false
7 | AlignEscapedNewlinesLeft: true
8 | AlignOperands: true
9 | AlignTrailingComments: true
10 | AllowAllParametersOfDeclarationOnNextLine: true
11 | AllowShortBlocksOnASingleLine: false
12 | AllowShortCaseLabelsOnASingleLine: false
13 | AllowShortFunctionsOnASingleLine: Empty
14 | AllowShortIfStatementsOnASingleLine: true
15 | AllowShortLoopsOnASingleLine: true
16 | AlwaysBreakAfterDefinitionReturnType: None
17 | AlwaysBreakAfterReturnType: None
18 | AlwaysBreakBeforeMultilineStrings: true
19 | AlwaysBreakTemplateDeclarations: true
20 | BinPackArguments: true
21 | BinPackParameters: true
22 | BraceWrapping:
23 | AfterClass: false
24 | AfterControlStatement: false
25 | AfterEnum: false
26 | AfterFunction: false
27 | AfterNamespace: false
28 | AfterObjCDeclaration: false
29 | AfterStruct: false
30 | AfterUnion: false
31 | BeforeCatch: false
32 | BeforeElse: false
33 | IndentBraces: false
34 | BreakBeforeBinaryOperators: None
35 | BreakBeforeBraces: Attach
36 | BreakBeforeTernaryOperators: true
37 | BreakConstructorInitializersBeforeComma: false
38 | ColumnLimit: 80
39 | CommentPragmas: '^ IWYU pragma:'
40 | ConstructorInitializerAllOnOneLineOrOnePerLine: true
41 | ConstructorInitializerIndentWidth: 4
42 | ContinuationIndentWidth: 4
43 | Cpp11BracedListStyle: true
44 | DerivePointerAlignment: true
45 | DisableFormat: false
46 | ExperimentalAutoDetectBinPacking: false
47 | ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
48 | IncludeCategories:
49 | - Regex: '^<.*\.h>'
50 | Priority: 1
51 | - Regex: '^<.*'
52 | Priority: 2
53 | - Regex: '.*'
54 | Priority: 3
55 | IndentCaseLabels: true
56 | IndentWidth: 2
57 | IndentWrappedFunctionNames: false
58 | KeepEmptyLinesAtTheStartOfBlocks: false
59 | MacroBlockBegin: ''
60 | MacroBlockEnd: ''
61 | MaxEmptyLinesToKeep: 1
62 | NamespaceIndentation: None
63 | ObjCBlockIndentWidth: 2
64 | ObjCSpaceAfterProperty: false
65 | ObjCSpaceBeforeProtocolList: false
66 | PenaltyBreakBeforeFirstCallParameter: 1
67 | PenaltyBreakComment: 300
68 | PenaltyBreakFirstLessLess: 120
69 | PenaltyBreakString: 1000
70 | PenaltyExcessCharacter: 1000000
71 | PenaltyReturnTypeOnItsOwnLine: 200
72 | PointerAlignment: Left
73 | ReflowComments: true
74 | SortIncludes: true
75 | SpaceAfterCStyleCast: false
76 | SpaceBeforeAssignmentOperators: true
77 | SpaceBeforeParens: ControlStatements
78 | SpaceInEmptyParentheses: false
79 | SpacesBeforeTrailingComments: 2
80 | SpacesInAngles: false
81 | SpacesInContainerLiterals: true
82 | SpacesInCStyleCastParentheses: false
83 | SpacesInParentheses: false
84 | SpacesInSquareBrackets: false
85 | Standard: Auto
86 | TabWidth: 8
87 | UseTab: Never
88 | ...
89 |
90 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # C++ objects and libs
2 |
3 | *.slo
4 | *.lo
5 | *.o
6 | *.a
7 | *.la
8 | *.lai
9 | *.so
10 | *.dll
11 | *.dylib
12 |
13 | # Qt-es
14 |
15 | /.qmake.cache
16 | /.qmake.stash
17 | *.moc
18 | moc_*.cpp
19 | qrc_*.cpp
20 | ui_*.h
21 | Makefile*
22 | *-build-*
23 |
24 | # QtCreator
25 | *.autosave
26 | *.user
27 |
28 | # vim
29 | *.sw*
30 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.1)
2 | project(qt-chess LANGUAGES CXX)
3 |
4 | if(NOT CMAKE_BUILD_TYPE)
5 | set(CMAKE_BUILD_TYPE "Release")
6 | endif()
7 |
8 | set(CMAKE_CXX_STANDARD 11)
9 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
10 |
11 | set(CMAKE_AUTOMOC On)
12 | set(CMAKE_INCLUDE_CURRENT_DIR On)
13 |
14 | find_package(Qt5 5.5.0 CONFIG REQUIRED Widgets Svg Qml Quick)
15 |
16 | add_subdirectory(src)
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # qt-chess
2 | Chess game on qt5 framework
3 |
4 | ## Build Requirements
5 | * Qt5 >= 5.5
6 | * CMake >= 3.1
7 | * GCC >= 4.8
8 |
9 | ## Resources
10 | ### Images
11 | Chess pieces found on https://commons.wikimedia.org/wiki/Category:SVG_chess_pieces/Maurizio_Monge
12 | made by Maurizio Monge
13 |
14 | ## Why have you done this?
15 | Simple answer - for fun. I've decided to check what the hell qml is.
16 |
--------------------------------------------------------------------------------
/images/c_bb.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
213 |
--------------------------------------------------------------------------------
/images/c_bk.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
289 |
--------------------------------------------------------------------------------
/images/c_bn.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
211 |
--------------------------------------------------------------------------------
/images/c_bp.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
149 |
--------------------------------------------------------------------------------
/images/c_bq.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
332 |
--------------------------------------------------------------------------------
/images/c_br.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
217 |
--------------------------------------------------------------------------------
/images/c_wb.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
213 |
--------------------------------------------------------------------------------
/images/c_wk.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
256 |
--------------------------------------------------------------------------------
/images/c_wn.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
211 |
--------------------------------------------------------------------------------
/images/c_wp.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
149 |
--------------------------------------------------------------------------------
/images/c_wq.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
300 |
--------------------------------------------------------------------------------
/images/c_wr.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
217 |
--------------------------------------------------------------------------------
/images/point.svg:
--------------------------------------------------------------------------------
1 |
69 |
70 |
--------------------------------------------------------------------------------
/qml/Board.qml:
--------------------------------------------------------------------------------
1 | /**
2 | * Board.qml
3 | *
4 | * Chess board object
5 | *
6 | *
7 | * @author Petr Orlov
8 | * @date 22.08.2018
9 | */
10 | import QtQuick 2.4
11 | import QtQuick.Layouts 1.1
12 | import QtQuick.Dialogs 1.2
13 |
14 |
15 | Rectangle {
16 | id: gameField
17 |
18 | width: 100
19 | height: 100
20 | property var figures
21 |
22 | signal figureClicked(var x, var y)
23 |
24 | Grid {
25 | id: chessGrid
26 | rows: 8
27 | columns: 8
28 | spacing: 0
29 |
30 | anchors.fill: parent
31 |
32 | // ChessBoard
33 | Repeater {
34 | model: 8 * 8
35 |
36 | Rectangle {
37 | height: chessGrid.height / 8
38 | width: height
39 |
40 | color: {
41 | var row = Math.floor(index / 8);
42 | var column = index % 8
43 | if ((row + column) % 2 == 1)
44 | "#8B4513";
45 | else
46 | "#FFE4B5";
47 | }
48 | }
49 | }
50 |
51 | Repeater {
52 | model: gameField.figures
53 |
54 | delegate: Item {
55 |
56 | height: chessGrid.height / 8
57 | width: height
58 |
59 | x: (Y - 1) * width
60 |
61 | y: (X - 1) * height
62 |
63 | Image {
64 | width: parent.width
65 | height: parent.height
66 |
67 | anchors.fill: parent
68 | source: image
69 | }
70 |
71 | MouseArea {
72 | anchors.fill: parent
73 |
74 | onClicked: gameField.figureClicked(X, Y)
75 | }
76 | }
77 | }
78 | }
79 | }
80 |
81 |
--------------------------------------------------------------------------------
/qml/ChessFigure.qml:
--------------------------------------------------------------------------------
1 | /**
2 | * Chess figure object
3 | *
4 | */
5 | import QtQuick 2.0
6 |
7 |
8 | Item {
9 | id: chessFigure
10 |
11 | property string ImagePath
12 |
13 | signal clicked()
14 |
15 | Image {
16 | id: figImage
17 |
18 | asynchronous: true // we are loading svg
19 | source: ImagePath
20 |
21 | sourceSize.width: parent.width
22 | sourceSize.height: parent.height
23 | }
24 |
25 | onClicked: {
26 | // Inform about user interruct
27 | clicked()
28 | }
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/qml/GameFDialog.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Dialogs 1.2
3 |
4 |
5 | FileDialog {
6 | id: fileDialog
7 | title: "Please choose a file"
8 | nameFilters: [ "Game files (*.sav)", "All files (*)" ]
9 | }
10 |
--------------------------------------------------------------------------------
/qml/History.qml:
--------------------------------------------------------------------------------
1 | /**
2 | * History.qml
3 | *
4 | * Moves history. Can be used to watch a game
5 | *
6 | *
7 | * @author Petr Orlov
8 | * @date 22.08.2018
9 | */
10 |
11 | import QtQuick 2.4
12 | import QtQuick.Layouts 1.1
13 | import QtQuick.Controls 1.2
14 |
15 | ListView {
16 | id: historyNavigation
17 |
18 | anchors.fill: parent
19 |
20 | delegate: Rectangle{
21 | id: row
22 |
23 | Text {
24 | id: number
25 | text: historyNavigation.model.Number
26 | }
27 | Text {
28 | id: moveW
29 | text: historyNavigation.model.RecordW
30 | }
31 | Text {
32 | id: moveB
33 | text: historyNavigation.model.RecordB
34 | }
35 | }
36 | }
37 |
38 |
39 |
--------------------------------------------------------------------------------
/qml/Window.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | import QtQuick.Layouts 1.1
3 | import QtQuick.Controls 1.2
4 |
5 | import com.znocpmp.chess 1.0
6 |
7 | ApplicationWindow {
8 | title: "Title"
9 | width: 640
10 | height: 480
11 | visible: true
12 |
13 | ColumnLayout {
14 | id: columnLayout1
15 | anchors.rightMargin: 0
16 | anchors.bottomMargin: 0
17 | anchors.leftMargin: 0
18 | anchors.topMargin: 0
19 | anchors.fill: parent
20 |
21 | state: "init"
22 |
23 | RowLayout {
24 | id: rowLayout1
25 | x: 311
26 | y: 56
27 | width: 100
28 | height: 100
29 | Layout.fillHeight: true
30 | Layout.fillWidth: true
31 |
32 | Button {
33 | id: button1
34 | x: 145
35 | y: 93
36 | }
37 |
38 | Button {
39 | id: button2
40 | x: 243
41 | y: 93
42 |
43 | GameFDialog {
44 | id: dialog
45 | }
46 |
47 | GameFDialog {
48 | id: saveDialog
49 | title: "Save as"
50 | }
51 | }
52 |
53 | Button {
54 | id: button3
55 | text: "prev"
56 | enabled: false
57 | }
58 |
59 | Button {
60 | id: button4
61 | text: "next"
62 | enabled: false
63 | }
64 |
65 | Button {
66 | id: button5
67 | text: "exit"
68 | onClicked: Qt.quit()
69 | }
70 | }
71 |
72 | RowLayout {
73 | id: rowLayout2
74 | x: 333
75 | y: 222
76 | width: 100
77 | height: 100
78 | Layout.fillHeight: true
79 | Layout.fillWidth: true
80 |
81 |
82 | Board {
83 | id: board1
84 | Layout.fillHeight: true
85 | Layout.fillWidth: true
86 | anchors.fill: parent
87 |
88 | Layout.column: 0;
89 | onFigureClicked: GameEngine.itemClicked(x, y)
90 | }
91 | }
92 |
93 | Component.onCompleted: {
94 | if(debug) {
95 | console.debug("Loaded")
96 | }
97 | board1.figures = GameEngine.figures()
98 | //history1.model = GameEngine.history()
99 | }
100 |
101 | states: [
102 | State {
103 | name: "init"
104 | PropertyChanges {
105 | target: button1
106 |
107 | text: "Start"
108 | onClicked: {
109 | if(debug) {
110 | console.debug("Setup board figures ")
111 | }
112 | GameEngine.setupBoard()
113 | columnLayout1.state = "game"
114 | }
115 | }
116 | PropertyChanges {
117 | target: button2
118 | text: "Load"
119 |
120 | onClicked: {
121 | if(debug) {
122 | console.debug("Clicked load button")
123 | }
124 | dialog.visible = true
125 | }
126 | }
127 | },
128 | State {
129 | name: "game"
130 |
131 | PropertyChanges {
132 | target: button1
133 |
134 | text: "Stop"
135 | onClicked: {
136 | if(debug) {
137 | console.debug("Stop game")
138 | }
139 | GameEngine.clean()
140 | columnLayout1.state = "init"
141 | }
142 | }
143 | PropertyChanges {
144 | target: button2
145 | text: "Save"
146 |
147 | onClicked: {
148 | if(debug) {
149 | console.debug("save button")
150 | }
151 | GameEngine.save("")
152 | saveDialog.visible = true
153 | }
154 | }
155 | PropertyChanges {
156 | target: button3
157 | enabled: false
158 | }
159 | PropertyChanges {
160 | target: button4
161 | enabled: false
162 | }
163 | },
164 | State {
165 | name: "watch"
166 | PropertyChanges {
167 | target: button3
168 | enabled: true
169 | }
170 | PropertyChanges {
171 | target: button4
172 | enabled: true
173 | }
174 | }
175 | ]
176 | }
177 | }
178 |
179 |
--------------------------------------------------------------------------------
/resouces.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | qml/Board.qml
4 | qml/Window.qml
5 | qml/ChessFigure.qml
6 | qml/History.qml
7 | qml/GameFDialog.qml
8 |
9 |
10 | images/c_bb.svg
11 | images/c_bk.svg
12 | images/c_bn.svg
13 | images/c_bp.svg
14 | images/c_bq.svg
15 | images/c_br.svg
16 | images/c_wb.svg
17 | images/c_wk.svg
18 | images/c_wn.svg
19 | images/c_wp.svg
20 | images/c_wq.svg
21 | images/c_wr.svg
22 | images/point.svg
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | aux_source_directory(. SOURCES)
2 |
3 | set(CMAKE_AUTORCC On)
4 |
5 | # Block qt debug output
6 | if(CMAKE_BUILD_TYPE STREQUAL "Release")
7 | add_definitions(-DQT_NO_DEBUG_OUTPUT)
8 | endif()
9 |
10 | add_executable(${PROJECT_NAME} ${SOURCES} ${CMAKE_SOURCE_DIR}/resouces.qrc)
11 | target_link_libraries(${PROJECT_NAME}
12 | Qt5::Widgets
13 | Qt5::Svg
14 | Qt5::Qml
15 | Qt5::Quick)
16 |
--------------------------------------------------------------------------------
/src/chess.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | *
4 | *
5 | */
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | #include
12 |
13 | /// Default programm running
14 | int main(int argc, char* argv[]) {
15 | QApplication app(argc, argv);
16 |
17 | QQmlApplicationEngine engine;
18 |
19 | #ifdef QT_DEBUG
20 | engine.rootContext()->setContextProperty("debug", true);
21 | #else
22 | engine.rootContext()->setContextProperty("debug", false);
23 | #endif
24 |
25 | engine.rootContext()->setContextProperty("GameEngine", new GameEngine);
26 | engine.load(QUrl(QStringLiteral("qrc:/qt-chess/qml/Window.qml")));
27 |
28 | return app.exec();
29 | }
30 |
--------------------------------------------------------------------------------
/src/chessmodel.cc:
--------------------------------------------------------------------------------
1 |
2 | #include
3 |
4 | #include "chessmodel.hpp"
5 |
6 | #include
7 |
8 | ChessModel::ChessModel(QObject* parent) : QAbstractListModel(parent) {}
9 |
10 | int ChessModel::rowCount(const QModelIndex& parent) const {
11 | Q_UNUSED(parent)
12 | return m_data.size();
13 | }
14 |
15 | bool ChessModel::removeRows(int row, int count, const QModelIndex& parent) {
16 | if (count <= 0 || row < 0 || (row + count) > rowCount(parent)) return false;
17 |
18 | beginRemoveRows(QModelIndex(), row, row + count - 1);
19 |
20 | while (count > 0) {
21 | qDebug() << "Removing this " << row;
22 | m_data.removeAt(row);
23 | count--;
24 | }
25 |
26 | endRemoveRows();
27 |
28 | return true;
29 | }
30 |
31 | QHash ChessModel::roleNames() const {
32 | QHash out;
33 |
34 | out[XPosRole] = "X";
35 | out[YPosRole] = "Y";
36 | out[ImageRole] = "image";
37 |
38 | return out;
39 | }
40 |
41 | QVariant ChessModel::data(const QModelIndex& index, int role) const {
42 | if (index.isValid()) {
43 | if (index.row() < rowCount()) {
44 | switch (role) {
45 | case XPosRole:
46 | return m_data.at(index.row())->X();
47 | case YPosRole:
48 | return m_data.at(index.row())->Y();
49 | case ImageRole:
50 | return m_data.at(index.row())->imagePath();
51 | default:
52 | break;
53 | }
54 | }
55 | }
56 |
57 | return QVariant();
58 | }
59 |
60 | void ChessModel::addFigure(FigureIntf* in) {
61 | beginInsertRows(QModelIndex(), rowCount(), rowCount());
62 |
63 | m_data.append(in);
64 |
65 | connect(in, SIGNAL(moved(uint, uint)), SLOT(movedPiece(uint, uint)));
66 |
67 | endInsertRows();
68 | }
69 |
70 | FigureIntf* ChessModel::getFigure(const uint x, const uint y) {
71 | foreach (FigureIntf* item, m_data) {
72 | if (item->X() == x && item->Y() == y) return item;
73 | }
74 |
75 | // this case (with existing qml) shouldn't happend
76 | // and we do that only for ensurance
77 | return nullptr;
78 | }
79 |
80 | void ChessModel::addHitSpot(const QList > list) {
81 | QListIterator > iterList(list);
82 |
83 | while (iterList.hasNext()) {
84 | QPair point = iterList.next();
85 |
86 | addFigure(new FigureIntf(point.first, point.second, FigureIntf::HitPlace));
87 | }
88 | }
89 |
90 | void ChessModel::rmHitSpot() {
91 | foreach (FigureIntf* figure, m_data) {
92 | if (figure->side() == FigureIntf::HitPlace)
93 | removeRows(m_data.indexOf(figure), 1, QModelIndex());
94 | }
95 | }
96 |
97 | void ChessModel::removeAt(const uint x, const uint y) {
98 | qDebug() << "Removing " << x << " and " << y;
99 | foreach (FigureIntf* item, m_data) {
100 | if (item->X() == x && item->Y() == y) {
101 | removeRows(m_data.indexOf(item), 1, QModelIndex());
102 | }
103 | }
104 | }
105 |
106 | void ChessModel::erase() {
107 | removeRows(0, rowCount(), QModelIndex());
108 | }
109 |
110 | void ChessModel::movedPiece(const uint x, const uint y) {
111 | Q_UNUSED(x)
112 | Q_UNUSED(y)
113 |
114 | emit dataChanged(createIndex(0, 0), createIndex(rowCount(), 0));
115 | }
116 |
--------------------------------------------------------------------------------
/src/chessmodel.hpp:
--------------------------------------------------------------------------------
1 | #ifndef CHESSMODEL_HPP
2 | #define CHESSMODEL_HPP
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | class FigureIntf;
10 | class ChessModel : public QAbstractListModel {
11 | Q_OBJECT
12 |
13 | public:
14 | enum ChessRoles {
15 | XPosRole = Qt::UserRole + 10,
16 | YPosRole,
17 | SideRole,
18 | ImageRole
19 | };
20 |
21 | explicit ChessModel(QObject *parent = 0);
22 |
23 | int rowCount(const QModelIndex &parent = QModelIndex()) const;
24 | bool removeRows(int row, int count, const QModelIndex &parent);
25 |
26 | QHash roleNames() const;
27 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
28 |
29 | void addFigure(FigureIntf *in);
30 | FigureIntf *getFigure(const uint x, const uint y);
31 |
32 | void addHitSpot(const QList > list);
33 | void rmHitSpot();
34 |
35 | public Q_SLOTS:
36 | void removeAt(const uint x, const uint y);
37 | void erase();
38 | void movedPiece(const uint x, const uint y);
39 |
40 | private:
41 | QList m_data;
42 | };
43 |
44 | #endif // CHESSMODEL_HPP
45 |
--------------------------------------------------------------------------------
/src/figurebishop.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "figurebishop.hpp"
4 |
5 | FigureBishop::FigureBishop(const uint x, const uint y, FigureIntf::Color side,
6 | QObject *parent)
7 | : FigureIntf(x, y, side, new MoveVectors(), parent) {
8 | MoveVectors *vectors = qobject_cast(defMoveList());
9 |
10 | vectors->addPoint(1, 1);
11 | vectors->addPoint(-1, 1);
12 | vectors->addPoint(1, -1);
13 | vectors->addPoint(-1, -1);
14 | vectors->setCurrent(x, y);
15 | }
16 |
17 | QString FigureBishop::imagePath() const {
18 | return s_path;
19 | }
20 |
--------------------------------------------------------------------------------
/src/figurebishop.hpp:
--------------------------------------------------------------------------------
1 | #ifndef FIGUREBISHOP_HPP
2 | #define FIGUREBISHOP_HPP
3 |
4 | #include
5 |
6 | #include "figureintf.hpp"
7 |
8 | /**
9 | * @brief The FigureBishop class
10 | *
11 | * Bishop class
12 | */
13 | class FigureBishop : public FigureIntf {
14 | Q_OBJECT
15 | public:
16 | FigureBishop(const uint x = 0, const uint y = 0, Color side = White,
17 | QObject *parent = 0);
18 |
19 | QString imagePath() const;
20 |
21 | private:
22 | QString const s_path = QString(imgPrefix() + "b.svg");
23 | };
24 |
25 | #endif // FIGUREBISHOP_HPP
26 |
--------------------------------------------------------------------------------
/src/figureintf.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "figureintf.hpp"
4 |
5 | FigureIntf::FigureIntf(QObject *parent) : QObject(parent) {}
6 |
7 | FigureIntf::FigureIntf(const uint x, const uint y, Color side,
8 | MovePoints *point, QObject *parent)
9 | : QObject(parent), m_xPos(x), m_yPos(y), m_color(side), m_points(point) {}
10 |
11 | FigureIntf::~FigureIntf() {}
12 |
13 | QString FigureIntf::imagePath() const {
14 | return QString("qrc:/qt-chess/img/images/point.svg");
15 | }
16 |
17 | void FigureIntf::moveTo(const uint &x, const uint &y) {
18 | setX(x);
19 | setY(y);
20 |
21 | m_points->clear();
22 | m_points->setCurrent(x, y);
23 |
24 | emit moved(x, y);
25 | }
26 |
27 | QList > FigureIntf::moveList() {
28 | return m_points->moveList();
29 | }
30 |
31 | void FigureIntf::setX(const uint &x) {
32 | m_xPos = x;
33 | }
34 |
35 | uint FigureIntf::X() const {
36 | return m_xPos;
37 | }
38 |
39 | void FigureIntf::setY(const uint &y) {
40 | m_yPos = y;
41 | }
42 |
43 | uint FigureIntf::Y() const {
44 | return m_yPos;
45 | }
46 |
47 | FigureIntf::Color FigureIntf::side() const {
48 | return m_color;
49 | }
50 |
51 | MovePoints *FigureIntf::defMoveList() {
52 | return m_points.data();
53 | }
54 |
55 | QString FigureIntf::imgPrefix() const {
56 | QString out("qrc:/qt-chess/img/images/");
57 |
58 | if (m_color == White)
59 | out += "c_w";
60 | else
61 | out += "c_b";
62 |
63 | return out;
64 | }
65 |
--------------------------------------------------------------------------------
/src/figureintf.hpp:
--------------------------------------------------------------------------------
1 | #ifndef FIGUREINTF_HPP
2 | #define FIGUREINTF_HPP
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include
10 |
11 | /**
12 | * @brief The FigureIntf class
13 | *
14 | * The interface class for different
15 | * kind of pieces
16 | */
17 | class MovePoints;
18 | class FigureIntf : public QObject {
19 | Q_OBJECT
20 |
21 | Q_PROPERTY(Color Side MEMBER m_color)
22 | Q_PROPERTY(QString imagePath READ imagePath)
23 | Q_PROPERTY(int X MEMBER m_xPos)
24 | Q_PROPERTY(int Y MEMBER m_yPos)
25 |
26 | Q_ENUMS(Color)
27 | public:
28 | /**
29 | * @brief The Color enum
30 | *
31 | * Meh
32 | */
33 | enum Color { Black, White, HitPlace };
34 |
35 | explicit FigureIntf(QObject *parent = 0);
36 | FigureIntf(const uint x, const uint y, Color side,
37 | MovePoints *point = new MovePoints(), QObject *parent = 0);
38 | virtual ~FigureIntf();
39 |
40 | Q_INVOKABLE virtual QString imagePath() const;
41 | Q_INVOKABLE virtual void moveTo(const uint &x, const uint &y);
42 |
43 | /**
44 | * @brief Return posible moves
45 | *
46 | * Depend on current position
47 | * @return List of moves
48 | */
49 | virtual QList > moveList();
50 |
51 | uint X() const;
52 | void setX(const uint &x);
53 |
54 | void setY(const uint &y);
55 | uint Y() const;
56 |
57 | Color side() const;
58 |
59 | MovePoints *defMoveList();
60 |
61 | Q_SIGNALS:
62 | void moved(uint x, uint y);
63 | void clicked();
64 |
65 | protected:
66 | QString imgPrefix() const;
67 |
68 | private:
69 | uint m_xPos = 0; /**< Current x position */
70 | uint m_yPos = 0; /**< Current y position */
71 |
72 | Color m_color = White; /**< Side of 'war' */
73 | QSharedPointer m_points; /**< Points to move */
74 | };
75 |
76 | #endif // FIGUREINTF_HPP
77 |
--------------------------------------------------------------------------------
/src/figureking.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include
4 |
5 | #include "figureking.hpp"
6 |
7 | FigureKing::FigureKing(const uint x, const uint y, Color side, QObject *parent)
8 | : FigureIntf(x, y, side, new MovePoints(), parent) {
9 | MovePoints *points = defMoveList();
10 |
11 | points->addPoint(0, 1);
12 | points->addPoint(1, 1);
13 | points->addPoint(1, 0);
14 | points->addPoint(1, -1);
15 | points->addPoint(0, -1);
16 | points->addPoint(-1, -1);
17 | points->addPoint(-1, 0);
18 | points->addPoint(-1, 1);
19 | points->setCurrent(x, y);
20 | }
21 |
22 | FigureKing::~FigureKing() {}
23 |
24 | void FigureKing::setCastling(bool flag) {
25 | if (!m_castled) m_sRook = flag;
26 | }
27 |
28 | bool FigureKing::isCastled() const {
29 | return m_castled;
30 | }
31 |
32 | QString FigureKing::imagePath() const {
33 | return s_path;
34 | }
35 |
36 | void FigureKing::moveTo(const uint &x, const uint &y) {
37 | // Only once in a game
38 | if (m_sRook & isCastlingMove(x)) {
39 | m_castled = true;
40 | m_sRook = false;
41 | }
42 |
43 | FigureIntf::moveTo(x, y);
44 | }
45 |
46 | bool FigureKing::isCastlingMove(uint x) const {
47 | return abs(X() - x) == 2;
48 | }
49 |
--------------------------------------------------------------------------------
/src/figureking.hpp:
--------------------------------------------------------------------------------
1 | #ifndef FIGUREKING_HPP
2 | #define FIGUREKING_HPP
3 |
4 | #include
5 |
6 | #include "figureintf.hpp"
7 |
8 | /**
9 | * @brief The FigureKing class
10 | *
11 | * King class
12 | */
13 | class FigureKing : public FigureIntf {
14 | Q_OBJECT
15 | public:
16 | FigureKing(const uint x = 0, const uint y = 0, Color side = White,
17 | QObject *parent = 0);
18 | ~FigureKing();
19 |
20 | void setCastling(bool flag);
21 | bool isCastled() const;
22 |
23 | QString imagePath() const;
24 | void moveTo(const uint &x, const uint &y);
25 |
26 | Q_SIGNALS:
27 | void castling(uint x);
28 |
29 | private:
30 | bool m_sRook = false; /**< Allow to castling */
31 | bool m_castled = false; /**< Status*/
32 |
33 | bool isCastlingMove(uint x) const;
34 |
35 | private:
36 | QString const s_path = QString(imgPrefix() + "k.svg");
37 | };
38 |
39 | #endif // FIGUREKING_HPP
40 |
--------------------------------------------------------------------------------
/src/figureknight.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "figureknight.hpp"
4 |
5 | FigureKnight::FigureKnight(const uint x, const uint y, FigureIntf::Color side,
6 | QObject *parent)
7 | : FigureIntf(x, y, side, new MovePoints(), parent) {
8 | MovePoints *points = defMoveList();
9 |
10 | points->addPoint(2, 1);
11 | points->addPoint(2, -1);
12 | points->addPoint(-2, 1);
13 | points->addPoint(-2, -1);
14 | points->addPoint(1, 2);
15 | points->addPoint(1, -2);
16 | points->addPoint(-1, 2);
17 | points->addPoint(-1, -2);
18 | points->setCurrent(x, y);
19 | }
20 |
21 | QString FigureKnight::imagePath() const {
22 | return s_path;
23 | }
24 |
--------------------------------------------------------------------------------
/src/figureknight.hpp:
--------------------------------------------------------------------------------
1 | #ifndef FIGUREKNIGHT_HPP
2 | #define FIGUREKNIGHT_HPP
3 |
4 | #include
5 |
6 | #include "figureintf.hpp"
7 |
8 | /**
9 | * @brief The FigureKnight class
10 | *
11 | * Knight class
12 | */
13 | class FigureKnight : public FigureIntf {
14 | Q_OBJECT
15 | public:
16 | FigureKnight(const uint x = 0, const uint y = 0, Color side = White,
17 | QObject *parent = 0);
18 |
19 | QString imagePath() const;
20 |
21 | private:
22 | QString const s_path = QString(imgPrefix() + "n.svg");
23 | };
24 |
25 | #endif // FIGUREKNIGHT_HPP
26 |
--------------------------------------------------------------------------------
/src/figurepawn.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "figurepawn.hpp"
4 |
5 | FigurePawn::FigurePawn(const uint x, const uint y, Color side, QObject *parent)
6 | : FigureIntf(x, y, side, new MovePawn(), parent) {
7 | // This figure has a little different kind of moves
8 | MovePawn *points = qobject_cast(defMoveList());
9 |
10 | points->addPoint(side == White ? 1 : -1, 0);
11 | // only first
12 | points->addPoint(side == White ? 2 : -2, 0);
13 | points->addPoint(side == White ? 1 : -1, -1);
14 | points->addPoint(side == White ? 1 : -1, 1);
15 |
16 | // In here we have to get info for En passant (thinking how to make)
17 | // points->addPoint(0, -1);
18 | // points->addPoint(0, 1);
19 |
20 | points->setCurrent(x, y);
21 | }
22 |
23 | void FigurePawn::moveTo(const uint &x, const uint &y) {
24 | FigureIntf::moveTo(x, y);
25 |
26 | if (x == (side() == White ? 8 : 1)) emit askPromotion();
27 | }
28 |
29 | QString FigurePawn::imagePath() const {
30 | return s_path;
31 | }
32 |
--------------------------------------------------------------------------------
/src/figurepawn.hpp:
--------------------------------------------------------------------------------
1 | #ifndef FIGUREPAWN_HPP
2 | #define FIGUREPAWN_HPP
3 |
4 | #include
5 |
6 | #include "figureintf.hpp"
7 |
8 | /**
9 | * @brief The FigurePawn class
10 | *
11 | * Pawn figure
12 | */
13 | class FigurePawn : public FigureIntf {
14 | Q_OBJECT
15 | public:
16 | FigurePawn(const uint x = 0, const uint y = 0, Color side = White,
17 | QObject *parent = 0);
18 |
19 | void moveTo(const uint &x, const uint &y);
20 | QString imagePath() const;
21 |
22 | Q_SIGNALS:
23 | void askPromotion();
24 |
25 | private:
26 | QString const s_path = QString(imgPrefix() + "p.svg");
27 | };
28 |
29 | #endif // FIGUREPAWN_HPP
30 |
--------------------------------------------------------------------------------
/src/figurequeen.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "figurequeen.hpp"
4 |
5 | FigureQueen::FigureQueen(const uint x, const uint y, FigureIntf::Color side,
6 | QObject *parent)
7 | : FigureIntf(x, y, side, new MoveVectors(), parent) {
8 | MoveVectors *vectors = qobject_cast(defMoveList());
9 |
10 | vectors->addPoint(0, 1);
11 | vectors->addPoint(1, 1);
12 | vectors->addPoint(1, 0);
13 | vectors->addPoint(1, -1);
14 | vectors->addPoint(0, -1);
15 | vectors->addPoint(-1, -1);
16 | vectors->addPoint(-1, 0);
17 | vectors->addPoint(-1, 1);
18 | vectors->setCurrent(x, y);
19 | }
20 |
21 | QString FigureQueen::imagePath() const {
22 | return s_path;
23 | }
24 |
--------------------------------------------------------------------------------
/src/figurequeen.hpp:
--------------------------------------------------------------------------------
1 | #ifndef FIGUREQUEEN_HPP
2 | #define FIGUREQUEEN_HPP
3 |
4 | #include
5 |
6 | #include "figureintf.hpp"
7 |
8 | /**
9 | * @brief The FigureQueen class
10 | *
11 | * Queen class
12 | */
13 | class FigureQueen : public FigureIntf {
14 | Q_OBJECT
15 | public:
16 | FigureQueen(const uint x = 0, const uint y = 0, Color side = White,
17 | QObject *parent = 0);
18 |
19 | QString imagePath() const;
20 |
21 | private:
22 | QString const s_path = QString(imgPrefix() + "q.svg");
23 | };
24 |
25 | #endif // FIGUREQUEEN_HPP
26 |
--------------------------------------------------------------------------------
/src/figurerook.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "figurerook.hpp"
4 |
5 | FigureRook::FigureRook(const uint x, const uint y, FigureIntf::Color side,
6 | QObject *parent)
7 | : FigureIntf(x, y, side, new MoveVectors(), parent) {
8 | MoveVectors *vectors = qobject_cast(defMoveList());
9 |
10 | vectors->addPoint(1, 0);
11 | vectors->addPoint(0, 1);
12 | vectors->addPoint(-1, 0);
13 | vectors->addPoint(0, -1);
14 | vectors->setCurrent(x, y);
15 | }
16 |
17 | QString FigureRook::imagePath() const {
18 | return s_path;
19 | }
20 |
--------------------------------------------------------------------------------
/src/figurerook.hpp:
--------------------------------------------------------------------------------
1 | #ifndef FIGUREROOK_HPP
2 | #define FIGUREROOK_HPP
3 |
4 | #include
5 |
6 | #include "figureintf.hpp"
7 |
8 | /**
9 | * @brief The FigureRook class
10 | *
11 | * Rook class
12 | */
13 | class FigureRook : public FigureIntf {
14 | Q_OBJECT
15 | public:
16 | FigureRook(const uint x = 0, const uint y = 0, Color side = White,
17 | QObject *parent = 0);
18 |
19 | QString imagePath() const;
20 |
21 | private:
22 | QString const s_path = QString(imgPrefix() + "r.svg");
23 | };
24 |
25 | #endif // FIGUREROOK_HPP
26 |
--------------------------------------------------------------------------------
/src/gameengine.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | #include
17 | #include
18 |
19 | #include "gameengine.hpp"
20 | #include "movepoints.hpp"
21 |
22 | GameEngine::GameEngine(QObject *parent)
23 | : QObject(parent),
24 | m_history(new HistoryModel(this)),
25 | m_figures(new ChessModel(this)),
26 | m_isWhite(true),
27 | m_lastClick(nullptr) {
28 | qmlRegisterUncreatableType("com.znocpmp.chess", 1, 0, "Figure",
29 | "");
30 | qmlRegisterType("com.znocpmp.chess", 1, 0, "ChessModel");
31 | }
32 |
33 | GameEngine::~GameEngine() {}
34 |
35 | void GameEngine::setupBoard() {
36 | for (int row = 0; row < 2; row++) {
37 | FigureIntf::Color color = row == 0 ? FigureIntf::Black : FigureIntf::White;
38 | int place = 8 - 7 * row;
39 |
40 | // Pawns
41 | for (int count = 1; count < 9; count++)
42 | m_figures->addFigure(
43 | new FigurePawn(place + (row == 0 ? -1 : 1), count, color));
44 |
45 | // Rooks
46 | m_figures->addFigure(new FigureRook(place, 1, color));
47 | m_figures->addFigure(new FigureRook(place, 8, color));
48 |
49 | // Bishops
50 | m_figures->addFigure(new FigureBishop(place, 3, color));
51 | m_figures->addFigure(new FigureBishop(place, 6, color));
52 |
53 | // Knights
54 | m_figures->addFigure(new FigureKnight(place, 2, color));
55 | m_figures->addFigure(new FigureKnight(place, 7, color));
56 |
57 | // Queen
58 | m_figures->addFigure(new FigureQueen(place, 4, color));
59 |
60 | // King
61 | m_figures->addFigure(new FigureKing(place, 5, color));
62 | }
63 | }
64 |
65 | void GameEngine::clean() {
66 | m_figures->erase();
67 | }
68 |
69 | void GameEngine::save() {}
70 |
71 | void GameEngine::load() {}
72 |
73 | void GameEngine::move() {}
74 |
75 | QObject *GameEngine::figures() {
76 | return m_figures;
77 | }
78 |
79 | QObject *GameEngine::history() {
80 | return m_history;
81 | }
82 |
83 | void GameEngine::itemClicked(uint x, uint y) {
84 | FigureIntf *item = m_figures->getFigure(x, y);
85 |
86 | if (m_lastClick != nullptr) {
87 | if (m_lastClick->moveList().indexOf(QPair(x, y)) != -1) {
88 | m_figures->removeAt(x, y);
89 | m_lastClick->moveTo(x, y);
90 |
91 | // Clean all up
92 | // next side to move
93 | m_isWhite = !m_isWhite;
94 | m_lastClick = nullptr;
95 | m_figures->rmHitSpot();
96 | } else if (m_lastClick->side() == item->side()) {
97 | m_lastClick = nullptr;
98 | m_figures->rmHitSpot();
99 | itemClicked(x, y);
100 | }
101 | }
102 | // Moves order
103 | else if ((item->side() == FigureIntf::Black) ^ m_isWhite) {
104 | item->defMoveList()->clear();
105 |
106 | setFigureWays(item);
107 | m_lastClick = item;
108 | }
109 | }
110 |
111 | void GameEngine::setFigureWays(FigureIntf *figure) {
112 | qDebug() << "loading ways to move";
113 |
114 | MovePoints *points = figure->defMoveList();
115 |
116 | if (points->isEmpty()) {
117 | QListIterator > iterList(points->moves());
118 |
119 | while (iterList.hasNext()) {
120 | QPair point = iterList.next();
121 |
122 | FigureIntf *pFigure = m_figures->getFigure(point.first, point.second);
123 |
124 | if (!pFigure)
125 | points->append(point, MovePoints::Empty);
126 | else if (pFigure->side() == figure->side())
127 | points->append(point, MovePoints::Friendly);
128 | else
129 | points->append(point, MovePoints::Enemy);
130 | }
131 | }
132 |
133 | m_figures->addHitSpot(points->moveList());
134 | }
135 |
--------------------------------------------------------------------------------
/src/gameengine.hpp:
--------------------------------------------------------------------------------
1 | #ifndef GAMEENGINE_HPP
2 | #define GAMEENGINE_HPP
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | /**
13 | * @brief The GameEngine class
14 | *
15 | * Main game engine. Control figures position,
16 | * status of the game and moves history.
17 | *
18 | */
19 | class ChessModel;
20 | class FigureIntf;
21 | class HistoryModel;
22 | class GameEngine : public QObject {
23 | Q_OBJECT
24 | // Q_PROPERTY(QQmlListProperty figures READ figures)
25 |
26 | public:
27 | explicit GameEngine(QObject *parent = 0);
28 | virtual ~GameEngine();
29 |
30 | Q_INVOKABLE void setupBoard();
31 | Q_INVOKABLE void clean();
32 | Q_INVOKABLE void save();
33 | Q_INVOKABLE void load();
34 | Q_INVOKABLE void move();
35 |
36 | Q_INVOKABLE QObject *figures();
37 | Q_INVOKABLE QObject *history();
38 |
39 | public Q_SLOTS:
40 | void itemClicked(uint x, uint y);
41 |
42 | private:
43 | HistoryModel *m_history; /**< Move history*/
44 | ChessModel *m_figures; /**< Figures on the board */
45 |
46 | bool m_isWhite; /**< WHo is going now */
47 | FigureIntf *m_lastClick; /**< Figure to move */
48 |
49 | private:
50 | void setFigureWays(FigureIntf *figure);
51 | };
52 |
53 | #endif // GAMEENGINE_HPP
54 |
--------------------------------------------------------------------------------
/src/historymanager.cc:
--------------------------------------------------------------------------------
1 | #include "historymanager.hpp"
2 |
3 | HistoryManager::HistoryManager(QObject *parent) : QObject(parent) {}
4 |
5 | HistoryManager::HistoryManager(const QString &file, QObject *parent) {}
6 |
7 | void HistoryManager::load(const QString &file) {}
8 |
9 | void HistoryManager::save(const QString &file) {}
10 |
--------------------------------------------------------------------------------
/src/historymanager.hpp:
--------------------------------------------------------------------------------
1 | #ifndef HISTORYMANAGER_HPP
2 | #define HISTORYMANAGER_HPP
3 |
4 | #include
5 |
6 | /**
7 | * @brief The HistoryManager class.
8 | *
9 | * Allow to load and save history out of file
10 | */
11 | class QFile;
12 | class HistoryManager : public QObject {
13 | Q_OBJECT
14 | public:
15 | explicit HistoryManager(QObject *parent = 0);
16 | HistoryManager(const QString &file, QObject *parent = 0);
17 |
18 | /**
19 | * @brief Load game history
20 | * @param file Load from \a file. If input is empty
21 | * trying to load from \a default place
22 | */
23 | void load(const QString &file = "");
24 |
25 | /**
26 | * @brief Save game history
27 | * @param file Save in to \a file. If input is empty
28 | * trying to save in \a default place
29 | */
30 | void save(const QString &file = "");
31 |
32 | private:
33 | QFile *m_file; /**< Working file*/
34 |
35 | private:
36 | QString const s_default = "game.sav";
37 | };
38 |
39 | #endif // HISTORYMANAGER_HPP
40 |
--------------------------------------------------------------------------------
/src/historymodel.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "historymodel.hpp"
4 |
5 | HistoryModel::HistoryModel(QObject *parent) : QAbstractListModel(parent) {
6 | m_header.append("White");
7 | m_header.append("Black");
8 | }
9 |
10 | QHash HistoryModel::roleNames() const {
11 | QHash out;
12 |
13 | out[Number] = "Number";
14 | out[RecordW] = "RecordW";
15 | out[RecordB] = "RecordB";
16 |
17 | return out;
18 | }
19 |
20 | int HistoryModel::rowCount(const QModelIndex &parent) const {
21 | Q_UNUSED(parent)
22 |
23 | return m_data.size();
24 | }
25 |
26 | QVariant HistoryModel::headerData(int section, Qt::Orientation orientation,
27 | int role) const {
28 | Q_UNUSED(role)
29 |
30 | switch (orientation) {
31 | case Qt::Horizontal:
32 | if (section > 0) return m_header.at(section - 1);
33 | case Qt::Vertical:
34 | if (section > 1) return QString("[ %1 ]").arg(section);
35 | }
36 |
37 | return QVariant();
38 | }
39 |
40 | QVariant HistoryModel::data(const QModelIndex &index, int role) const {
41 | if (index.isValid()) {
42 | QRegExp exp(s_pattern);
43 |
44 | if (index.row() < rowCount()) {
45 | switch (role) {
46 | case Number:
47 | return index.row();
48 | case RecordW:
49 | m_data.at(index.row()).section(" ", 0, 0);
50 | case RecordB:
51 | m_data.at(index.row()).section(" ", 1, 1);
52 | default:
53 | break;
54 | }
55 | }
56 | }
57 |
58 | return QVariant();
59 | }
60 |
61 | void HistoryModel::setRecord(HistoryModel::Type type,
62 | QPair &from,
63 | QPair &to,
64 | HistoryModel::MoveStatus status) {
65 | beginInsertRows(QModelIndex(), rowCount(), rowCount());
66 |
67 | QString str = QString("%1%2%3%4%5%6")
68 | .arg(typeToString(type))
69 | .arg(from.first)
70 | .arg(from.second)
71 | .arg(statusToString(status))
72 | .arg(to.first)
73 | .arg(to.second);
74 |
75 | if (m_data.size() % 2 == 0)
76 | m_data.append(str);
77 | else
78 | m_data.replace(m_data.size() - 1, m_data.at(m_data.size() - 1) + " " + str);
79 |
80 | endInsertRows();
81 | }
82 |
83 | QByteArray HistoryModel::save() const {
84 | return QByteArray();
85 | }
86 |
87 | void HistoryModel::load(QByteArray) {}
88 |
89 | void HistoryModel::goForward() {
90 | if (m_data.size() > m_pos - 1) m_pos++;
91 |
92 | QRegExp exp(s_pattern);
93 |
94 | if (exp.indexIn(m_data.at(m_pos)) != -1)
95 | emit changed(toType(exp.cap(1)),
96 | QPair(exp.cap(2), exp.cap(3).toUInt()),
97 | QPair(exp.cap(4), exp.cap(5).toUInt()),
98 | toStatus(exp.cap(6)));
99 | }
100 |
101 | void HistoryModel::goBack() {}
102 |
103 | QString HistoryModel::typeToString(HistoryModel::Type type) const {
104 | switch (type) {
105 | case Bishop:
106 | return "B";
107 | case Rook:
108 | return "R";
109 | case Knight:
110 | return "N";
111 | case Queen:
112 | return "Q";
113 | case King:
114 | return "K";
115 | case Pawn:
116 | break;
117 | }
118 |
119 | return "";
120 | }
121 |
122 | QString HistoryModel::statusToString(HistoryModel::MoveStatus status) const {
123 | switch (status) {
124 | case Move:
125 | return "-";
126 | case Hit:
127 | return "x";
128 | case Check:
129 | return "+";
130 | case CheckMate:
131 | return "++";
132 | case CKS:
133 | return "O-O";
134 | case CQS:
135 | return "O-O-O";
136 | }
137 |
138 | return "";
139 | }
140 |
141 | HistoryModel::Type HistoryModel::toType(const QString &in) const {
142 | if (in == QString("B"))
143 | return Bishop;
144 | else if (in == QString("R"))
145 | return Rook;
146 | else if (in == QString("N"))
147 | return Knight;
148 | else if (in == QString("Q"))
149 | return Queen;
150 | else if (in == QString("K"))
151 | return King;
152 |
153 | return Pawn;
154 | }
155 |
156 | HistoryModel::MoveStatus HistoryModel::toStatus(const QString &in) const {
157 | if (in == QString("x")) return Hit;
158 |
159 | return Move;
160 | }
161 |
--------------------------------------------------------------------------------
/src/historymodel.hpp:
--------------------------------------------------------------------------------
1 | #ifndef HISTORYMODEL_HPP
2 | #define HISTORYMODEL_HPP
3 |
4 | #include
5 | #include
6 |
7 | /**
8 | * @brief The HistoryModel class
9 | *
10 | * Loggin all moves in here
11 | */
12 | class HistoryModel : public QAbstractListModel {
13 | Q_OBJECT
14 | public:
15 | enum ChessRoles { Number = Qt::UserRole + 10, RecordW, RecordB };
16 |
17 | enum MoveStatus {
18 | Move,
19 | Hit,
20 | Check,
21 | CheckMate,
22 | CKS,
23 | CQS,
24 | };
25 |
26 | enum Type { Pawn, Bishop, Rook, Knight, Queen, King };
27 |
28 | explicit HistoryModel(QObject *parent = 0);
29 |
30 | QHash roleNames() const;
31 |
32 | int rowCount(const QModelIndex &parent = QModelIndex()) const;
33 | QVariant headerData(int section, Qt::Orientation orientation,
34 | int role = Qt::DisplayRole) const;
35 | QVariant data(const QModelIndex &index, int role) const;
36 |
37 | void setRecord(HistoryModel::Type type, QPair &from,
38 | QPair &to, HistoryModel::MoveStatus status);
39 | QByteArray save() const;
40 | void load(QByteArray);
41 |
42 | public Q_SLOTS:
43 | void goForward();
44 | void goBack();
45 |
46 | Q_SIGNALS:
47 | void changed(HistoryModel::Type, QPair, QPair,
48 | HistoryModel::MoveStatus status);
49 |
50 | private:
51 | uint m_pos;
52 | QStringList m_data;
53 | QStringList m_header;
54 |
55 | private:
56 | QString typeToString(const Type type) const;
57 | QString statusToString(const MoveStatus status) const;
58 | Type toType(const QString &in) const;
59 | MoveStatus toStatus(const QString &in) const;
60 |
61 | // capture only for move and hit
62 | QString const s_pattern = "(\\w?)(\\w)(\\d)([\\-x])(\\w)(\\d)";
63 | };
64 |
65 | #endif // HISTORYMODEL_HPP
66 |
--------------------------------------------------------------------------------
/src/movepawn.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "movepawn.hpp"
4 |
5 | MovePawn::MovePawn(QObject *parent)
6 | : MovePoints(parent), m_first(true), m_x(0), m_y(0) {}
7 |
8 | void MovePawn::setCurrent(uint x, uint y) {
9 | if (m_x != 0 && m_first) m_first = false;
10 |
11 | m_x = x;
12 | m_y = y;
13 |
14 | MovePoints::setCurrent(x, y);
15 | }
16 |
17 | void MovePawn::append(const QPair &point, PlaceType type) {
18 | MovePoints::append(point, type);
19 |
20 | if (!m_first && abs(point.first - m_x) == 2)
21 | m_currentList.removeAt(m_currentList.indexOf(point));
22 |
23 | if (type == Empty) {
24 | if (!m_first && abs(point.first - m_x) == 2)
25 | m_currentList.removeAt(m_currentList.indexOf(point));
26 | if (abs(point.second - m_y) == 1)
27 | m_currentList.removeAt(m_currentList.indexOf(point));
28 | } else if (abs(point.second - m_y) == 0) {
29 | m_currentList.removeAt(m_currentList.indexOf(point));
30 |
31 | // we dont have to step over figures
32 | if (m_first && abs(point.first - m_x) == 1) {
33 | int index = m_currentList.indexOf(
34 | QPair(point.first + (point.first - m_x), point.second));
35 |
36 | if (index != -1) m_currentList.removeAt(index);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/movepawn.hpp:
--------------------------------------------------------------------------------
1 | #ifndef MOVEPAWN_HPP
2 | #define MOVEPAWN_HPP
3 |
4 | #include
5 |
6 | #include "movepoints.hpp"
7 |
8 | /**
9 | * @brief The MovePawn class
10 | *
11 | * Special case of moving pawn
12 | */
13 | class MovePawn : public MovePoints {
14 | Q_OBJECT
15 | public:
16 | explicit MovePawn(QObject *parent = 0);
17 |
18 | virtual void setCurrent(uint x, uint y);
19 | virtual void append(const QPair &point, PlaceType type);
20 |
21 | private:
22 | bool m_first; /**< first move */
23 | uint m_x; /**< x */
24 | uint m_y; /**< y */
25 | };
26 |
27 | #endif // MOVEPAWN_HPP
28 |
--------------------------------------------------------------------------------
/src/movepoints.cc:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "movepoints.hpp"
4 |
5 | MovePoints::MovePoints(QObject *parent) : QObject(parent) {}
6 |
7 | void MovePoints::addPoint(int x, int y) {
8 | m_steps.append(QPair(x, y));
9 | }
10 |
11 | QList > MovePoints::moves() const {
12 | return m_moveList;
13 | }
14 |
15 | QList > MovePoints::moveList() const {
16 | return m_currentList;
17 | }
18 |
19 | bool MovePoints::isEmpty() const {
20 | return m_currentList.empty();
21 | }
22 |
23 | void MovePoints::clear() {
24 | m_currentList.clear();
25 | }
26 |
27 | void MovePoints::setCurrent(uint x, uint y) {
28 | m_moveList.clear();
29 |
30 | QListIterator > stepIter(m_steps);
31 |
32 | while (stepIter.hasNext()) {
33 | QPair step = stepIter.next();
34 |
35 | uint newX = x + step.first;
36 | uint newY = y + step.second;
37 |
38 | if (newX == 0 || newX > 8 || newY == 0 || newY > 8) continue;
39 |
40 | m_moveList.append(QPair(newX, newY));
41 | }
42 | }
43 |
44 | void MovePoints::append(const QPair &point,
45 | MovePoints::PlaceType type) {
46 | switch (type) {
47 | case Empty:
48 | case Enemy:
49 | if (m_moveList.indexOf(point) != -1) m_currentList.append(point);
50 | break;
51 | default:
52 | break;
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/movepoints.hpp:
--------------------------------------------------------------------------------
1 | #ifndef MOVEPOINTS_HPP
2 | #define MOVEPOINTS_HPP
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | class MovePoints : public QObject {
9 | Q_OBJECT
10 | public:
11 | // Status of step
12 | enum PlaceType { Empty, Friendly, Enemy };
13 |
14 | explicit MovePoints(QObject *parent = 0);
15 |
16 | void addPoint(int x, int y);
17 |
18 | QList > moves() const;
19 | QList > moveList() const;
20 |
21 | bool isEmpty() const;
22 | virtual void clear();
23 |
24 | virtual void setCurrent(uint x, uint y);
25 | virtual void append(const QPair &point, PlaceType type);
26 |
27 | protected:
28 | QList > m_moveList; /**< Default ways to go */
29 | QList > m_steps; /**< How we can move */
30 | QList > m_currentList; /**< Allow to go */
31 | };
32 |
33 | #endif // MOVEPOINTS_HPP
34 |
--------------------------------------------------------------------------------
/src/movevectors.cc:
--------------------------------------------------------------------------------
1 | #include "movevectors.hpp"
2 |
3 | MoveVectors::MoveVectors(QObject *parent) : MovePoints(parent) {}
4 |
5 | void MoveVectors::setCurrent(uint x, uint y) {
6 | m_moveList.clear();
7 |
8 | QListIterator > stepIter(m_steps);
9 |
10 | // we have to know to construct a vector of movements
11 | m_x = x;
12 | m_y = y;
13 |
14 | while (stepIter.hasNext()) {
15 | QPair step = stepIter.next();
16 |
17 | uint newX = x;
18 | uint newY = y;
19 |
20 | while ((newX > 0 && newX < 9) && (newY > 0 && newY < 9)) {
21 | if (newX != x || newY != y)
22 | m_moveList.append(QPair(newX, newY));
23 |
24 | newX = newX + step.first;
25 | newY = newY + step.second;
26 | }
27 | }
28 | }
29 |
30 | void MoveVectors::append(const QPair &point,
31 | MovePoints::PlaceType type) {
32 | int vec_x = point.first - m_x;
33 | int vec_y = point.second - m_y;
34 |
35 | // just protection of unpredictable input
36 | if ((abs(vec_x) != abs(vec_y)) && (vec_x != 0 && vec_y != 0)) return;
37 |
38 | vec_x = vec_x == 0 ? 0 : vec_x / abs(vec_x);
39 | vec_y = vec_y == 0 ? 0 : vec_y / abs(vec_y);
40 |
41 | uint posX = m_x;
42 | uint posY = m_y;
43 |
44 | while (!(posX == point.first && posY == point.second)) {
45 | posX += vec_x;
46 | posY += vec_y;
47 |
48 | if (m_stops.indexOf(QPair(posX, posY)) != -1) return;
49 | }
50 |
51 | switch (type) {
52 | case Friendly:
53 | m_stops.append(point);
54 | checkExisting(point, vec_x, vec_y);
55 | break;
56 |
57 | // No break. That is not an error. We must add point to go then enemy or
58 | // nothing
59 | case Enemy:
60 | m_stops.append(
61 | QPair(point.first + vec_x, point.second + vec_y));
62 | checkExisting(
63 | QPair(point.first + vec_x, point.second + vec_y), vec_x,
64 | vec_y);
65 |
66 | default:
67 | MovePoints::append(point, type);
68 | }
69 | }
70 |
71 | void MoveVectors::clear() {
72 | m_stops.clear();
73 |
74 | MovePoints::clear();
75 | }
76 |
77 | void MoveVectors::checkExisting(QPair point, int x, int y) {
78 | while (point.first > 0 && point.first < 9 && point.second > 0 &&
79 | point.second < 9) {
80 | point.first += x;
81 | point.second += y;
82 |
83 | int index = m_currentList.indexOf(point);
84 |
85 | if (index != -1) m_currentList.removeAt(index);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/movevectors.hpp:
--------------------------------------------------------------------------------
1 | #ifndef MOVEVECTORS_HPP
2 | #define MOVEVECTORS_HPP
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include "movepoints.hpp"
9 |
10 | class MoveVectors : public MovePoints {
11 | Q_OBJECT
12 | public:
13 | explicit MoveVectors(QObject *parent = 0);
14 |
15 | void setCurrent(uint x, uint y);
16 | void append(const QPair &point, PlaceType type);
17 |
18 | void clear();
19 |
20 | private:
21 | QList> m_stops;
22 |
23 | uint m_x; /**< x */
24 | uint m_y; /**< y */
25 |
26 | private:
27 | void checkExisting(QPair point, int x, int y);
28 | };
29 |
30 | #endif // MOVEVECTORS_HPP
31 |
--------------------------------------------------------------------------------