├── .gitignore ├── LICENSE ├── Podfile ├── Podfile.lock ├── Pods ├── Local Podspecs │ └── Sage.podspec.json ├── Manifest.lock ├── Pods.xcodeproj │ ├── project.pbxproj │ └── xcuserdata │ │ └── javiers.xcuserdatad │ │ └── xcschemes │ │ ├── Pods-SwiftChessEngine.xcscheme │ │ ├── Sage.xcscheme │ │ └── xcschememanagement.plist ├── Sage │ ├── LICENSE.txt │ ├── README.md │ └── Sources │ │ ├── Bitboard.swift │ │ ├── Board.swift │ │ ├── CastlingRights.swift │ │ ├── Color.swift │ │ ├── File.swift │ │ ├── Game.swift │ │ ├── InternalTypes.swift │ │ ├── Move.swift │ │ ├── PGN.swift │ │ ├── Piece.swift │ │ ├── Player.swift │ │ ├── Rank.swift │ │ ├── Sequence+Sage.swift │ │ ├── Square.swift │ │ └── Variant.swift └── Target Support Files │ ├── Pods-SwiftChessEngine │ ├── Info.plist │ ├── Pods-SwiftChessEngine-acknowledgements.markdown │ ├── Pods-SwiftChessEngine-acknowledgements.plist │ ├── Pods-SwiftChessEngine-dummy.m │ ├── Pods-SwiftChessEngine-frameworks.sh │ ├── Pods-SwiftChessEngine-resources.sh │ ├── Pods-SwiftChessEngine-umbrella.h │ ├── Pods-SwiftChessEngine.debug.xcconfig │ ├── Pods-SwiftChessEngine.modulemap │ └── Pods-SwiftChessEngine.release.xcconfig │ └── Sage │ ├── Info.plist │ ├── Sage-dummy.m │ ├── Sage-prefix.pch │ ├── Sage-umbrella.h │ ├── Sage.modulemap │ └── Sage.xcconfig ├── README.md ├── SwiftChessEngine.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── javiers.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── javiers.xcuserdatad │ └── xcschemes │ ├── SwiftChessEngine.xcscheme │ └── xcschememanagement.plist ├── SwiftChessEngine.xcworkspace ├── contents.xcworkspacedata └── xcuserdata │ └── javiers.xcuserdatad │ ├── UserInterfaceState.xcuserstate │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist └── SwiftChessEngine ├── AppDelegate.swift ├── Assets.xcassets └── AppIcon.appiconset │ └── Contents.json ├── Base.lproj ├── LaunchScreen.storyboard └── Main.storyboard ├── ChessEngine └── ChessEngine.swift ├── Info.plist └── ViewController.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xcuserstate 23 | 24 | ## Obj-C/Swift specific 25 | *.hmap 26 | *.ipa 27 | *.dSYM.zip 28 | *.dSYM 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/Preview.html 64 | fastlane/screenshots 65 | fastlane/test_output 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Javier Soto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '10.0' 2 | swift_version="3" 3 | use_frameworks! 4 | 5 | target 'SwiftChessEngine' do 6 | pod 'Sage', :git => 'https://github.com/nvzqz/Sage.git', :branch => 'master' 7 | end 8 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Sage (2.0.0) 3 | 4 | DEPENDENCIES: 5 | - Sage (from `https://github.com/nvzqz/Sage.git`, branch `master`) 6 | 7 | EXTERNAL SOURCES: 8 | Sage: 9 | :branch: master 10 | :git: https://github.com/nvzqz/Sage.git 11 | 12 | CHECKOUT OPTIONS: 13 | Sage: 14 | :commit: 3c447476ec73920f46f81fe99b10c1c83127c92a 15 | :git: https://github.com/nvzqz/Sage.git 16 | 17 | SPEC CHECKSUMS: 18 | Sage: 0f22bee8c3b2310a55ffa27c118f6be6a0097edd 19 | 20 | PODFILE CHECKSUM: e4a17ad4bb9f13f1465d8ad370eff75b98e98c7c 21 | 22 | COCOAPODS: 1.1.0.beta.1 23 | -------------------------------------------------------------------------------- /Pods/Local Podspecs/Sage.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Sage", 3 | "version": "2.0.0", 4 | "summary": "A cross-platform chess library for Swift.", 5 | "homepage": "https://github.com/nvzqz/Sage", 6 | "license": { 7 | "type": "Apache License, Version 2.0", 8 | "file": "LICENSE.txt" 9 | }, 10 | "authors": "Nikolai Vazquez", 11 | "platforms": { 12 | "ios": "8.0", 13 | "osx": "10.9", 14 | "watchos": "2.0", 15 | "tvos": "9.0" 16 | }, 17 | "source": { 18 | "git": "https://github.com/nvzqz/Sage.git", 19 | "tag": "v2.0.0" 20 | }, 21 | "source_files": "Sources/*.swift" 22 | } 23 | -------------------------------------------------------------------------------- /Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Sage (2.0.0) 3 | 4 | DEPENDENCIES: 5 | - Sage (from `https://github.com/nvzqz/Sage.git`, branch `master`) 6 | 7 | EXTERNAL SOURCES: 8 | Sage: 9 | :branch: master 10 | :git: https://github.com/nvzqz/Sage.git 11 | 12 | CHECKOUT OPTIONS: 13 | Sage: 14 | :commit: 3c447476ec73920f46f81fe99b10c1c83127c92a 15 | :git: https://github.com/nvzqz/Sage.git 16 | 17 | SPEC CHECKSUMS: 18 | Sage: 0f22bee8c3b2310a55ffa27c118f6be6a0097edd 19 | 20 | PODFILE CHECKSUM: e4a17ad4bb9f13f1465d8ad370eff75b98e98c7c 21 | 22 | COCOAPODS: 1.1.0.beta.1 23 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/javiers.xcuserdatad/xcschemes/Pods-SwiftChessEngine.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 66 | 67 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/javiers.xcuserdatad/xcschemes/Sage.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 45 | 46 | 52 | 53 | 55 | 56 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /Pods/Pods.xcodeproj/xcuserdata/javiers.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Pods-SwiftChessEngine.xcscheme 8 | 9 | isShown 10 | 11 | 12 | Sage.xcscheme 13 | 14 | isShown 15 | 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | C7A03F0B962ACC7E028441A557BE1D1D 21 | 22 | primary 23 | 24 | 25 | CF5459EF9BFDF3B4F2D419EF54DA0910 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /Pods/Sage/LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Pods/Sage/README.md: -------------------------------------------------------------------------------- 1 | [![Sage](https://raw.githubusercontent.com/nvzqz/Sage/assets/Banner.png)](https://github.com/nvzqz/Sage) 2 | 3 |

4 | Swift 2.2 | 3.0 5 | Platforms 6 | Build Status 7 | Apache 2.0 License 8 |

9 | 10 |

11 | CocoaPods 12 | Carthage 13 | Swift Package Manager 14 |

15 | 16 | Sage is a cross-platform chess library for Swift. 17 | 18 | - [Features](#features) 19 | - [Installation](#installation) 20 | - [Compatibility](#compatibility) 21 | - [Swift Package Manager](#install-using-swift-package-manager) 22 | - [CocoaPods](#install-using-cocoapods) 23 | - [Carthage](#install-using-carthage) 24 | - [Manually](#install-manually) 25 | - [Usage](#usage) 26 | - [Game Management](#game-management) 27 | - [Move Generation](#move-generation) 28 | - [Move Validation](#move-validation) 29 | - [Undo and Redo Moves](#undo-and-redo-moves) 30 | - [Promotion Handling](#promotion-handling) 31 | - [Pretty Printing](#pretty-printing) 32 | - [Forsyth–Edwards Notation](#forsythedwards-notation) 33 | - [Iterating Through a Board](#iterating-through-a-board) 34 | - [Squares to Moves](#squares-to-moves) 35 | - [Playground Usage](#playground-usage) 36 | - [Board Quick Look](#board-quick-look) 37 | - [License](#license) 38 | 39 | ## Features 40 | 41 | - [x] Chess game management 42 | - [x] Chess board structuring 43 | - [x] Move generation / validation 44 | - [x] En passant and castling 45 | - [x] Pawn promotions 46 | - [x] FEN for games and boards 47 | - [x] PGN parsing and exporting 48 | - [x] [Documentation](https://nvzqz.github.io/Sage/docs/) 49 | 50 | ## Installation 51 | 52 | ### Compatibility 53 | 54 | - Platforms: 55 | - macOS 10.9+ 56 | - iOS 8.0+ 57 | - watchOS 2.0+ 58 | - tvOS 9.0+ 59 | - Linux 60 | - Xcode 7.3 and 8.0 61 | - Swift 2.2 and 3.0 62 | 63 | ### Install Using Swift Package Manager 64 | The [Swift Package Manager](https://swift.org/package-manager/) is a 65 | decentralized dependency manager for Swift. 66 | 67 | 1. Add the project to your `Package.swift`. 68 | 69 | ```swift 70 | import PackageDescription 71 | 72 | let package = Package( 73 | name: "MyAwesomeProject", 74 | dependencies: [ 75 | .Package(url: "https://github.com/nvzqz/Sage.git", 76 | majorVersion: 1) 77 | ] 78 | ) 79 | ``` 80 | 81 | 2. Import the Sage module. 82 | 83 | ```swift 84 | import Sage 85 | ``` 86 | 87 | ### Install Using CocoaPods 88 | [CocoaPods](https://cocoapods.org/) is a centralized dependency manager for 89 | Objective-C and Swift. Go [here](https://guides.cocoapods.org/using/index.html) 90 | to learn more. 91 | 92 | 1. Add the project to your [Podfile](https://guides.cocoapods.org/using/the-podfile.html). 93 | 94 | ```ruby 95 | use_frameworks! 96 | 97 | pod 'Sage', '~> 2.0.0' 98 | ``` 99 | 100 | If you want to be on the bleeding edge, replace the last line with: 101 | 102 | ```ruby 103 | pod 'Sage', :git => 'https://github.com/nvzqz/Sage.git' 104 | ``` 105 | 106 | 2. Run `pod install` and open the `.xcworkspace` file to launch Xcode. 107 | 108 | 3. Import the Sage framework. 109 | 110 | ```swift 111 | import Sage 112 | ``` 113 | 114 | ### Install Using Carthage 115 | [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency 116 | manager for Objective-C and Swift. 117 | 118 | 1. Add the project to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile). 119 | 120 | ``` 121 | github "nvzqz/Sage" 122 | ``` 123 | 124 | 2. Run `carthage update` and follow [the additional steps](https://github.com/Carthage/Carthage#getting-started) 125 | in order to add Sage to your project. 126 | 127 | 3. Import the Sage framework. 128 | 129 | ```swift 130 | import Sage 131 | ``` 132 | 133 | ### Install Manually 134 | 135 | 1. Download and drop the `/Sources` folder into your project. 136 | 137 | 2. Congratulations! 138 | 139 | ## Usage 140 | 141 | ### Game Management 142 | 143 | Running a chess game can be as simple as setting up a loop. 144 | 145 | ```swift 146 | import Sage 147 | 148 | let game = Game() 149 | 150 | while !game.isFinished { 151 | let move = ... 152 | try game.execute(move: move) 153 | } 154 | ``` 155 | 156 | ### Move Generation 157 | 158 | Sage is capable of generating legal moves for the current player with full 159 | support for special moves such as en passant and castling. 160 | 161 | - `availableMoves()` will return all moves currently available. 162 | 163 | - `movesForPiece(at:)` will return all moves for a piece at a square. 164 | 165 | - `movesBitboardForPiece(at:)` will return a `Bitboard` containing all of the 166 | squares a piece at a square can move to. 167 | 168 | ### Move Validation 169 | 170 | Sage can also validate whether a move is legal with the `isLegal(move:)` 171 | method for a `Game` state. 172 | 173 | The `execute(move:)` family of methods calls this method, so it would be faster 174 | to execute the move directly and catch any error from an illegal move. 175 | 176 | ### Undo and Redo Moves 177 | 178 | Move undo and redo operations are done with the `undoMove()` and `redoMove()` 179 | methods. The undone or redone move is returned. 180 | 181 | To just check what moves are to be undone or redone, the `moveToUndo()` and 182 | `moveToRedo()` methods are available. 183 | 184 | ### Promotion Handling 185 | 186 | The `execute(move:promotion:)` method takes a closure that returns a promotion 187 | piece kind. This allows for the app to prompt the user for a promotion piece or 188 | perform any other operations before choosing a promotion piece kind. 189 | 190 | ```swift 191 | try game.execute(move: move) { 192 | ... 193 | return .queen 194 | } 195 | ``` 196 | 197 | The closure is only executed if the move is a pawn promotion. An error is thrown 198 | if the promotion piece kind cannot promote a pawn, such as with a king or pawn. 199 | 200 | A piece kind can also be given without a closure. The default is a queen. 201 | 202 | ```swift 203 | try game.execute(move: move, promotion: .queen) 204 | ``` 205 | 206 | ### Pretty Printing 207 | 208 | The `Board` and `Bitboard` types both have an `ascii` property that can be used 209 | to print a visual board. 210 | 211 | ```swift 212 | let board = Board() 213 | 214 | print(board.ascii) 215 | // +-----------------+ 216 | // 8 | r n b q k b n r | 217 | // 7 | p p p p p p p p | 218 | // 6 | . . . . . . . . | 219 | // 5 | . . . . . . . . | 220 | // 4 | . . . . . . . . | 221 | // 3 | . . . . . . . . | 222 | // 2 | P P P P P P P P | 223 | // 1 | R N B Q K B N R | 224 | // +-----------------+ 225 | // a b c d e f g h 226 | 227 | print(board.occupiedSpaces.ascii) 228 | // +-----------------+ 229 | // 8 | 1 1 1 1 1 1 1 1 | 230 | // 7 | 1 1 1 1 1 1 1 1 | 231 | // 6 | . . . . . . . . | 232 | // 5 | . . . . . . . . | 233 | // 4 | . . . . . . . . | 234 | // 3 | . . . . . . . . | 235 | // 2 | 1 1 1 1 1 1 1 1 | 236 | // 1 | 1 1 1 1 1 1 1 1 | 237 | // +-----------------+ 238 | // a b c d e f g h 239 | ``` 240 | 241 | ### Forsyth–Edwards Notation 242 | 243 | The `Game.Position` and `Board` types can both generate a FEN string. 244 | 245 | ```swift 246 | let game = Game() 247 | 248 | print(game.position.fen()) 249 | // rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1 250 | 251 | print(game.board.fen()) 252 | // rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR 253 | ``` 254 | 255 | They can also be initialized from a FEN string. 256 | 257 | ```swift 258 | assert(Board(fen: game.board.fen()) == game.board) 259 | 260 | assert(Game.Position(fen: game.position.fen()) == game.position) 261 | ``` 262 | 263 | ### Iterating Through a Board 264 | 265 | The `Board` type conforms to `Sequence`, making iterating through its spaces 266 | seamless. 267 | 268 | ```swift 269 | for space in Board() { 270 | if let piece = space.piece { 271 | print("\(piece) at \(space.square)") 272 | } 273 | } 274 | ``` 275 | 276 | ### Squares to Moves 277 | 278 | `Sequence` and `Square` have two methods that return an array of moves that go 279 | from/to `self` to/from the parameter. 280 | 281 | ```swift 282 | print([.a1, .h3, .b5].moves(from: .b4)) 283 | // [b4 >>> a1, b4 >>> h3, b4 >>> b5] 284 | 285 | print([.c3, .d2, .f1].moves(to: .a6)) 286 | // [c3 >>> a6, d2 >>> a6, f1 >>> a6] 287 | 288 | print(Square.d4.moves(from: [.c2, .f8, .h2])) 289 | // [c2 >>> d4, f8 >>> d4, h2 >>> d4] 290 | 291 | print(Square.a4.moves(to: [.c3, .d4, .f6])) 292 | // [a4 >>> c3, a4 >>> d4, a4 >>> f6] 293 | ``` 294 | 295 | ### Playground Usage 296 | 297 | To use `Sage.playground`, first open `Sage.xcodeproj` and build the OS X target. 298 | You can then use the playground from within the project. 299 | 300 | #### Board Quick Look 301 | 302 | `Board` conforms to the `CustomPlaygroundQuickLookable` protocol. 303 | 304 | ![Playground quick look](https://raw.githubusercontent.com/nvzqz/Sage/assets/BoardPlaygroundView.png) 305 | 306 | ## License 307 | 308 | Sage is published under [version 2.0 of the Apache License](https://www.apache.org/licenses/LICENSE-2.0). 309 | -------------------------------------------------------------------------------- /Pods/Sage/Sources/CastlingRights.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CastlingRights.swift 3 | // Sage 4 | // 5 | // Copyright 2016 Nikolai Vazquez 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | /// Castling rights of a `Game`. 21 | /// 22 | /// Defines whether a `Color` has the right to castle for a `Board.Side`. 23 | public struct CastlingRights: CustomStringConvertible { 24 | 25 | /// A castling right. 26 | public enum Right: String, CustomStringConvertible { 27 | 28 | #if swift(>=3) 29 | 30 | /// White can castle kingside. 31 | case whiteKingside 32 | 33 | /// White can castle queenside. 34 | case whiteQueenside 35 | 36 | /// Black can castle kingside. 37 | case blackKingside 38 | 39 | /// Black can castle queenside. 40 | case blackQueenside 41 | 42 | /// All rights. 43 | public static let all: [Right] = [.whiteKingside, .whiteQueenside, .blackKingside, .blackQueenside] 44 | 45 | #else 46 | 47 | /// White can castle kingside. 48 | case WhiteKingside 49 | 50 | /// White can castle queenside. 51 | case WhiteQueenside 52 | 53 | /// Black can castle kingside. 54 | case BlackKingside 55 | 56 | /// Black can castle queenside. 57 | case BlackQueenside 58 | 59 | /// All rights. 60 | public static let all: [Right] = [.WhiteKingside, .WhiteQueenside, .BlackKingside, .BlackQueenside] 61 | 62 | #endif 63 | 64 | /// The color for `self`. 65 | public var color: Color { 66 | get { 67 | #if swift(>=3) 68 | switch self { 69 | case .whiteKingside, .whiteQueenside: 70 | return .white 71 | default: 72 | return .black 73 | } 74 | #else 75 | switch self { 76 | case .WhiteKingside, .WhiteQueenside: 77 | return .White 78 | default: 79 | return .Black 80 | } 81 | #endif 82 | } 83 | set { 84 | self = Right(color: newValue, side: side) 85 | } 86 | } 87 | 88 | /// The board side for `self`. 89 | public var side: Board.Side { 90 | get { 91 | #if swift(>=3) 92 | switch self { 93 | case .whiteKingside, .blackKingside: 94 | return .kingside 95 | default: 96 | return .queenside 97 | } 98 | #else 99 | switch self { 100 | case .WhiteKingside, .BlackKingside: 101 | return .Kingside 102 | default: 103 | return .Queenside 104 | } 105 | #endif 106 | } 107 | set { 108 | self = Right(color: color, side: side) 109 | } 110 | } 111 | 112 | /// The squares expected to be empty for a castle. 113 | public var emptySquares: Bitboard { 114 | #if swift(>=3) 115 | switch self { 116 | case .whiteKingside: 117 | return 0b01100000 118 | case .whiteQueenside: 119 | return 0b00001110 120 | case .blackKingside: 121 | return 0b01100000 << 56 122 | case .blackQueenside: 123 | return 0b00001110 << 56 124 | } 125 | #else 126 | switch self { 127 | case .WhiteKingside: 128 | return 0b01100000 129 | case .WhiteQueenside: 130 | return 0b00001110 131 | case .BlackKingside: 132 | return 0b01100000 << 56 133 | case .BlackQueenside: 134 | return 0b00001110 << 56 135 | } 136 | #endif 137 | } 138 | 139 | /// The castle destination square of a king. 140 | public var castleSquare: Square { 141 | #if swift(>=3) 142 | switch self { 143 | case .whiteKingside: 144 | return .g1 145 | case .whiteQueenside: 146 | return .c1 147 | case .blackKingside: 148 | return .g8 149 | case .blackQueenside: 150 | return .c8 151 | } 152 | #else 153 | switch self { 154 | case .WhiteKingside: 155 | return .G1 156 | case .WhiteQueenside: 157 | return .C1 158 | case .BlackKingside: 159 | return .G8 160 | case .BlackQueenside: 161 | return .C8 162 | } 163 | #endif 164 | } 165 | 166 | /// The character for `self`. 167 | public var character: Character { 168 | #if swift(>=3) 169 | switch self { 170 | case .whiteKingside: return "K" 171 | case .whiteQueenside: return "Q" 172 | case .blackKingside: return "k" 173 | case .blackQueenside: return "q" 174 | } 175 | #else 176 | switch self { 177 | case .WhiteKingside: return "K" 178 | case .WhiteQueenside: return "Q" 179 | case .BlackKingside: return "k" 180 | case .BlackQueenside: return "q" 181 | } 182 | #endif 183 | } 184 | 185 | /// A textual representation of `self`. 186 | public var description: String { 187 | return rawValue 188 | } 189 | 190 | private var _bit: Int { 191 | #if swift(>=3) 192 | switch self { 193 | case .whiteKingside: return 0b0001 194 | case .whiteQueenside: return 0b0010 195 | case .blackKingside: return 0b0100 196 | case .blackQueenside: return 0b1000 197 | } 198 | #else 199 | switch self { 200 | case .WhiteKingside: return 0b0001 201 | case .WhiteQueenside: return 0b0010 202 | case .BlackKingside: return 0b0100 203 | case .BlackQueenside: return 0b1000 204 | } 205 | #endif 206 | } 207 | 208 | /// Create a `Right` from `color` and `side`. 209 | public init(color: Color, side: Board.Side) { 210 | #if swift(>=3) 211 | switch (color, side) { 212 | case (.white, .kingside): self = .whiteKingside 213 | case (.white, .queenside): self = .whiteQueenside 214 | case (.black, .kingside): self = .blackKingside 215 | case (.black, .queenside): self = .blackQueenside 216 | } 217 | #else 218 | switch (color, side) { 219 | case (.White, .Kingside): self = .WhiteKingside 220 | case (.White, .Queenside): self = .WhiteQueenside 221 | case (.Black, .Kingside): self = .BlackKingside 222 | case (.Black, .Queenside): self = .BlackQueenside 223 | } 224 | #endif 225 | } 226 | 227 | /// Create a `Right` from a `Character`. 228 | public init?(character: Character) { 229 | #if swift(>=3) 230 | switch character { 231 | case "K": self = .whiteKingside 232 | case "Q": self = .whiteQueenside 233 | case "k": self = .blackKingside 234 | case "q": self = .blackQueenside 235 | default: return nil 236 | } 237 | #else 238 | switch character { 239 | case "K": self = .WhiteKingside 240 | case "Q": self = .WhiteQueenside 241 | case "k": self = .BlackKingside 242 | case "q": self = .BlackQueenside 243 | default: return nil 244 | } 245 | #endif 246 | } 247 | 248 | } 249 | 250 | #if swift(>=3) 251 | 252 | /// An iterator over the members of `CastlingRights`. 253 | public struct Iterator: IteratorProtocol { 254 | 255 | private var _base: SetIterator 256 | 257 | /// Advance to the next element and return it, or `nil` if no next element exists. 258 | public mutating func next() -> Right? { 259 | return _base.next() 260 | } 261 | 262 | } 263 | 264 | #else 265 | 266 | /// A generator over the members of `CastlingRights`. 267 | public struct Generator: GeneratorType { 268 | 269 | private var _base: SetGenerator 270 | 271 | /// Advance to the next element and return it, or `nil` if no next element exists. 272 | public mutating func next() -> Right? { 273 | return _base.next() 274 | } 275 | 276 | } 277 | 278 | #endif 279 | 280 | /// All castling rights. 281 | public static let all = CastlingRights(Right.all) 282 | 283 | /// The rights. 284 | private var _rights: Set 285 | 286 | /// A textual representation of `self`. 287 | public var description: String { 288 | if !_rights.isEmpty { 289 | #if swift(>=3) 290 | return String(_rights.map({ $0.character }).sorted()) 291 | #else 292 | return String(_rights.map({ $0.character }).sort()) 293 | #endif 294 | } else { 295 | return "-" 296 | } 297 | } 298 | 299 | /// Creates empty rights. 300 | public init() { 301 | _rights = Set() 302 | } 303 | 304 | /// Creates a `CastlingRights` from a `String`. 305 | /// 306 | /// - returns: `nil` if `string` is empty or invalid. 307 | public init?(string: String) { 308 | guard !string.isEmpty else { 309 | return nil 310 | } 311 | if string == "-" { 312 | _rights = Set() 313 | } else { 314 | var rights = Set() 315 | for char in string.characters { 316 | guard let right = Right(character: char) else { 317 | return nil 318 | } 319 | rights.insert(right) 320 | } 321 | _rights = rights 322 | } 323 | } 324 | 325 | #if swift(>=3) 326 | 327 | /// Creates a set of rights from a sequence. 328 | public init(_ sequence: S) { 329 | if let set = sequence as? Set { 330 | _rights = set 331 | } else { 332 | _rights = Set(sequence) 333 | } 334 | } 335 | 336 | #else 337 | 338 | /// Creates a set of rights from a sequence. 339 | public init(_ sequence: S) { 340 | if let set = sequence as? Set { 341 | _rights = set 342 | } else { 343 | _rights = Set(sequence) 344 | } 345 | } 346 | 347 | #endif 348 | 349 | } 350 | 351 | #if swift(>=3) 352 | 353 | extension CastlingRights: Sequence { 354 | 355 | /// Returns an iterator over the members. 356 | public func makeIterator() -> Iterator { 357 | return Iterator(_base: _rights.makeIterator()) 358 | } 359 | 360 | } 361 | 362 | extension CastlingRights: SetAlgebra { 363 | 364 | /// A Boolean value that indicates whether the set has no elements. 365 | public var isEmpty: Bool { 366 | return _rights.isEmpty 367 | } 368 | 369 | /// Returns a Boolean value that indicates whether the given element exists 370 | /// in the set. 371 | public func contains(_ member: Right) -> Bool { 372 | return _rights.contains(member) 373 | } 374 | 375 | /// Returns a new set with the elements of both this and the given set. 376 | public func union(_ other: CastlingRights) -> CastlingRights { 377 | return CastlingRights(_rights.union(other._rights)) 378 | } 379 | 380 | /// Returns a new set with the elements that are common to both this set and 381 | /// the given set. 382 | public func intersection(_ other: CastlingRights) -> CastlingRights { 383 | return CastlingRights(_rights.intersection(other._rights)) 384 | } 385 | 386 | /// Returns a new set with the elements that are either in this set or in the 387 | /// given set, but not in both. 388 | public func symmetricDifference(_ other: CastlingRights) -> CastlingRights { 389 | return CastlingRights(_rights.symmetricDifference(other._rights)) 390 | } 391 | 392 | /// Inserts the given element in the set if it is not already present. 393 | @discardableResult 394 | public mutating func insert(_ newMember: Right) -> (inserted: Bool, memberAfterInsert: Right) { 395 | return _rights.insert(newMember) 396 | } 397 | 398 | /// Removes the given element and any elements subsumed by the given element. 399 | @discardableResult 400 | public mutating func remove(_ member: Right) -> Right? { 401 | return _rights.remove(member) 402 | } 403 | 404 | /// Inserts the given element into the set unconditionally. 405 | @discardableResult 406 | public mutating func update(with newMember: Right) -> Right? { 407 | return _rights.update(with: newMember) 408 | } 409 | 410 | /// Adds the elements of the given set to the set. 411 | public mutating func formUnion(_ other: CastlingRights) { 412 | _rights.formUnion(other._rights) 413 | } 414 | 415 | /// Removes the elements of this set that aren't also in the given set. 416 | public mutating func formIntersection(_ other: CastlingRights) { 417 | _rights.formIntersection(other._rights) 418 | } 419 | 420 | /// Removes the elements of the set that are also in the given set and 421 | /// adds the members of the given set that are not already in the set. 422 | public mutating func formSymmetricDifference(_ other: CastlingRights) { 423 | _rights.formSymmetricDifference(other._rights) 424 | } 425 | 426 | /// Returns a new set containing the elements of this set that do not occur 427 | /// in the given set. 428 | public func subtracting(_ other: CastlingRights) -> CastlingRights { 429 | return CastlingRights(_rights.subtracting(other._rights)) 430 | } 431 | 432 | /// Returns a Boolean value that indicates whether the set is a subset of 433 | /// another set. 434 | public func isSubset(of other: CastlingRights) -> Bool { 435 | return _rights.isSubset(of: other._rights) 436 | } 437 | 438 | /// Returns a Boolean value that indicates whether the set has no members in 439 | /// common with the given set. 440 | public func isDisjoint(with other: CastlingRights) -> Bool { 441 | return _rights.isDisjoint(with: other._rights) 442 | } 443 | 444 | /// Returns a Boolean value that indicates whether the set is a superset of 445 | /// the given set. 446 | public func isSuperset(of other: CastlingRights) -> Bool { 447 | return _rights.isSuperset(of: other._rights) 448 | } 449 | 450 | /// Removes the elements of the given set from this set. 451 | public mutating func subtract(_ other: CastlingRights) { 452 | _rights.subtract(other) 453 | } 454 | 455 | } 456 | 457 | #else 458 | 459 | extension CastlingRights: SequenceType { 460 | 461 | /// Returns a generator over the members. 462 | /// 463 | /// - complexity: O(1). 464 | public func generate() -> Generator { 465 | return Generator(_base: _rights.generate()) 466 | } 467 | 468 | } 469 | 470 | extension CastlingRights: SetAlgebraType { 471 | 472 | /// Returns `true` if `self` contains `member`. 473 | public func contains(member: Right) -> Bool { 474 | return _rights.contains(member) 475 | } 476 | 477 | /// Returns the set of elements contained in `self`, in `other`, or in both `self` and `other`. 478 | @warn_unused_result(mutable_variant="unionInPlace") 479 | public func union(other: CastlingRights) -> CastlingRights { 480 | return CastlingRights(_rights.union(other._rights)) 481 | } 482 | 483 | /// Returns the set of elements contained in both `self` and `other`. 484 | @warn_unused_result(mutable_variant="intersectInPlace") 485 | public func intersect(other: CastlingRights) -> CastlingRights { 486 | return CastlingRights(_rights.intersect(other._rights)) 487 | } 488 | 489 | /// Returns the set of elements contained in `self` or in `other`, but not in both `self` and `other`. 490 | @warn_unused_result(mutable_variant="exclusiveOrInPlace") 491 | public func exclusiveOr(other: CastlingRights) -> CastlingRights { 492 | return CastlingRights(_rights.exclusiveOr(other._rights)) 493 | } 494 | 495 | /// Insert all elements of `other` into `self`. 496 | public mutating func unionInPlace(other: CastlingRights) { 497 | _rights.unionInPlace(other._rights) 498 | } 499 | 500 | /// Removes all elements of `self` that are not also present in `other`. 501 | public mutating func intersectInPlace(other: CastlingRights) { 502 | _rights.intersectInPlace(other._rights) 503 | } 504 | 505 | /// Replaces `self` with a set containing all elements contained in either `self` or `other`, but not both. 506 | public mutating func exclusiveOrInPlace(other: CastlingRights) { 507 | _rights.exclusiveOrInPlace(other._rights) 508 | } 509 | 510 | /// If `member` is not already contained in `self`, inserts it. 511 | public mutating func insert(member: Right) { 512 | _rights.insert(member) 513 | } 514 | 515 | /// Remove the member from the set and return it if it was present. 516 | public mutating func remove(member: Right) -> Right? { 517 | return _rights.remove(member) 518 | } 519 | 520 | } 521 | 522 | #endif 523 | 524 | extension CastlingRights: Hashable { 525 | /// The hash value. 526 | public var hashValue: Int { 527 | return _rights.reduce(0, combine: { $0 | $1._bit }) 528 | } 529 | } 530 | 531 | /// Returns `true` if both have the same rights. 532 | public func == (lhs: CastlingRights, rhs: CastlingRights) -> Bool { 533 | return lhs._rights == rhs._rights 534 | } 535 | -------------------------------------------------------------------------------- /Pods/Sage/Sources/Color.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Color.swift 3 | // Sage 4 | // 5 | // Copyright 2016 Nikolai Vazquez 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | /// A chess color. 21 | public enum Color: String, CustomStringConvertible { 22 | 23 | #if swift(>=3) 24 | 25 | /// White chess color. 26 | case white 27 | 28 | /// Black chess color. 29 | case black 30 | 31 | /// White color regardless of Swift version. 32 | internal static let _white = Color.white 33 | 34 | /// Black color regardless of Swift version. 35 | internal static let _black = Color.black 36 | 37 | /// An array of all colors. 38 | public static let all: [Color] = [.white, .black] 39 | 40 | #else 41 | 42 | /// White chess color. 43 | case White 44 | 45 | /// Black chess color. 46 | case Black 47 | 48 | /// White color regardless of Swift version. 49 | internal static let _white = Color.White 50 | 51 | /// Black color regardless of Swift version. 52 | internal static let _black = Color.Black 53 | 54 | /// An array of all colors. 55 | public static let all: [Color] = [.White, .Black] 56 | 57 | #endif 58 | 59 | /// Whether the color is white or not. 60 | public var isWhite: Bool { 61 | return self == ._white 62 | } 63 | 64 | /// Whether the color is black or not. 65 | public var isBlack: Bool { 66 | return self == ._black 67 | } 68 | 69 | /// A textual representation of `self`. 70 | public var description: String { 71 | return rawValue 72 | } 73 | 74 | /// The lowercase character for the color. `White` is "w", `Black` is "b". 75 | public var character: Character { 76 | return self.isWhite ? "w" : "b" 77 | } 78 | 79 | /// Create a color from a character of any case. 80 | public init?(character: Character) { 81 | switch character { 82 | case "W", "w": self = ._white 83 | case "B", "b": self = ._black 84 | default: return nil 85 | } 86 | } 87 | 88 | /// Returns the inverse of `self`. 89 | public func inverse() -> Color { 90 | return self.isWhite ? ._black : ._white 91 | } 92 | 93 | /// Inverts the color of `self`. 94 | public mutating func invert() { 95 | self = inverse() 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /Pods/Sage/Sources/File.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // Sage 4 | // 5 | // Copyright 2016 Nikolai Vazquez 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | /// A chess board file. 21 | /// 22 | /// Files refer to the eight columns of a chess board, beginning with A and ending with H from left to right. 23 | public enum File: Int, Comparable, CustomStringConvertible { 24 | 25 | /// A direction in file. 26 | public enum Direction { 27 | 28 | #if swift(>=3) 29 | 30 | /// Left direction. 31 | case left 32 | 33 | /// Right direction. 34 | case right 35 | 36 | #else 37 | 38 | /// Left direction. 39 | case Left 40 | 41 | /// Right direction. 42 | case Right 43 | 44 | #endif 45 | 46 | } 47 | 48 | #if swift(>=3) 49 | 50 | /// File "A". 51 | case a = 1 52 | 53 | /// File "B". 54 | case b = 2 55 | 56 | /// File "C". 57 | case c = 3 58 | 59 | /// File "D". 60 | case d = 4 61 | 62 | /// File "E". 63 | case e = 5 64 | 65 | /// File "F". 66 | case f = 6 67 | 68 | /// File "G". 69 | case g = 7 70 | 71 | /// File "H". 72 | case h = 8 73 | 74 | #else 75 | 76 | /// File "A". 77 | case A = 1 78 | 79 | /// File "B". 80 | case B = 2 81 | 82 | /// File "C". 83 | case C = 3 84 | 85 | /// File "D". 86 | case D = 4 87 | 88 | /// File "E". 89 | case E = 5 90 | 91 | /// File "F". 92 | case F = 6 93 | 94 | /// File "G". 95 | case G = 7 96 | 97 | /// File "H". 98 | case H = 8 99 | 100 | #endif 101 | 102 | } 103 | 104 | extension File { 105 | 106 | #if swift(>=3) 107 | 108 | /// An array of all files. 109 | public static let all: [File] = [.a, .b, .c, .d, .e, .f, .g, .h] 110 | 111 | #else 112 | 113 | /// An array of all files. 114 | public static let all: [File] = [.A, .B, .C, .D, .E, .F, .G, .H] 115 | 116 | #endif 117 | 118 | /// The column index of `self`. 119 | public var index: Int { 120 | return rawValue - 1 121 | } 122 | 123 | /// A textual representation of `self`. 124 | public var description: String { 125 | return String(character) 126 | } 127 | 128 | /// The character value of `self`. 129 | public var character: Character { 130 | #if swift(>=3) 131 | switch self { 132 | case .a: return "a" 133 | case .b: return "b" 134 | case .c: return "c" 135 | case .d: return "d" 136 | case .e: return "e" 137 | case .f: return "f" 138 | case .g: return "g" 139 | case .h: return "h" 140 | } 141 | #else 142 | switch self { 143 | case .A: return "a" 144 | case .B: return "b" 145 | case .C: return "c" 146 | case .D: return "d" 147 | case .E: return "e" 148 | case .F: return "f" 149 | case .G: return "g" 150 | case .H: return "h" 151 | } 152 | #endif 153 | } 154 | 155 | /// Create an instance from a character value. 156 | public init?(_ character: Character) { 157 | #if swift(>=3) 158 | switch character { 159 | case "A", "a": self = .a 160 | case "B", "b": self = .b 161 | case "C", "c": self = .c 162 | case "D", "d": self = .d 163 | case "E", "e": self = .e 164 | case "F", "f": self = .f 165 | case "G", "g": self = .g 166 | case "H", "h": self = .h 167 | default: return nil 168 | } 169 | #else 170 | switch character { 171 | case "A", "a": self = .A 172 | case "B", "b": self = .B 173 | case "C", "c": self = .C 174 | case "D", "d": self = .D 175 | case "E", "e": self = .E 176 | case "F", "f": self = .F 177 | case "G", "g": self = .G 178 | case "H", "h": self = .H 179 | default: return nil 180 | } 181 | #endif 182 | } 183 | 184 | /// Create a `File` from a zero-based column index. 185 | public init?(index: Int) { 186 | self.init(rawValue: index + 1) 187 | } 188 | 189 | /// Returns a rank from advancing `self` by `value`. 190 | public func advanced(by value: Int) -> File? { 191 | return File(rawValue: rawValue + value) 192 | } 193 | 194 | /// The next file after `self`. 195 | public func next() -> File? { 196 | return File(rawValue: (rawValue + 1)) 197 | } 198 | 199 | /// The previous file to `self`. 200 | public func previous() -> File? { 201 | return File(rawValue: (rawValue - 1)) 202 | } 203 | 204 | /// The opposite file of `self`. 205 | public func opposite() -> File { 206 | return File(rawValue: 9 - rawValue)! 207 | } 208 | 209 | /// The files from `self` to `other`. 210 | public func to(_ other: File) -> [File] { 211 | if other > self { 212 | return (rawValue...other.rawValue).flatMap(File.init(rawValue:)) 213 | } else if other < self { 214 | #if swift(>=3) 215 | let values = (other.rawValue...rawValue).reversed() 216 | #else 217 | let values = (other.rawValue...rawValue).reverse() 218 | #endif 219 | return values.flatMap(File.init(rawValue:)) 220 | } else { 221 | return [self] 222 | } 223 | } 224 | 225 | /// The files between `self` and `other`. 226 | public func between(_ other: File) -> [File] { 227 | if other > self { 228 | return (rawValue + 1 ..< other.rawValue).flatMap(File.init(rawValue:)) 229 | } else if other < self { 230 | #if swift(>=3) 231 | let values = (other.rawValue + 1 ..< rawValue).reversed() 232 | #else 233 | let values = (other.rawValue + 1 ..< rawValue).reverse() 234 | #endif 235 | return values.flatMap(File.init(rawValue:)) 236 | } else { 237 | return [] 238 | } 239 | } 240 | 241 | } 242 | 243 | extension File: ExtendedGraphemeClusterLiteralConvertible { 244 | 245 | /// Create an instance initialized to `value`. 246 | public init(unicodeScalarLiteral value: Character) { 247 | guard let file = File(value) else { 248 | fatalError("File value not within \"A\" and \"H\" or \"a\" and \"h\", inclusive") 249 | } 250 | self = file 251 | } 252 | 253 | /// Create an instance initialized to `value`. 254 | public init(extendedGraphemeClusterLiteral value: Character) { 255 | self.init(unicodeScalarLiteral: value) 256 | } 257 | 258 | } 259 | 260 | /// Returns `true` if one file is further left than the other. 261 | public func < (lhs: File, rhs: File) -> Bool { 262 | return lhs.rawValue < rhs.rawValue 263 | } 264 | -------------------------------------------------------------------------------- /Pods/Sage/Sources/InternalTypes.swift: -------------------------------------------------------------------------------- 1 | // 2 | // InternalTypes.swift 3 | // Sage 4 | // 5 | // Copyright 2016 Nikolai Vazquez 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #if os(OSX) 21 | import Cocoa 22 | internal typealias _View = NSView 23 | internal typealias _Color = NSColor 24 | #elseif os(iOS) || os(tvOS) 25 | import UIKit 26 | internal typealias _View = UIView 27 | internal typealias _Color = UIColor 28 | #endif 29 | 30 | internal extension Optional { 31 | 32 | var _altDescription: String { 33 | return self.map({ String($0) }) ?? "nil" 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Pods/Sage/Sources/Move.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Move.swift 3 | // Sage 4 | // 5 | // Copyright 2016 Nikolai Vazquez 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | /// A chess move from a start `Square` to an end `Square`. 21 | public struct Move: Hashable, CustomStringConvertible { 22 | 23 | /// The move's start square. 24 | public var start: Square 25 | 26 | /// The move's end square. 27 | public var end: Square 28 | 29 | /// The move's change in file. 30 | public var fileChange: Int { 31 | return end.file.rawValue - start.file.rawValue 32 | } 33 | 34 | /// The move's change in rank. 35 | public var rankChange: Int { 36 | return end.rank.rawValue - start.rank.rawValue 37 | } 38 | 39 | /// The move is a real change in location. 40 | public var isChange: Bool { 41 | return start != end 42 | } 43 | 44 | /// The move is diagonal. 45 | public var isDiagonal: Bool { 46 | let fileChange = self.fileChange 47 | return fileChange != 0 && abs(fileChange) == abs(rankChange) 48 | } 49 | 50 | /// The move is horizontal. 51 | public var isHorizontal: Bool { 52 | return start.file != end.file && start.rank == end.rank 53 | } 54 | 55 | /// The move is vertical. 56 | public var isVertical: Bool { 57 | return start.file == end.file && start.rank != end.rank 58 | } 59 | 60 | /// The move is horizontal or vertical. 61 | public var isAxial: Bool { 62 | return isHorizontal || isVertical 63 | } 64 | 65 | /// The move is leftward. 66 | public var isLeftward: Bool { 67 | return end.file < start.file 68 | } 69 | 70 | /// The move is rightward. 71 | public var isRightward: Bool { 72 | return end.file > start.file 73 | } 74 | 75 | /// The move is downward. 76 | public var isDownward: Bool { 77 | return end.rank < start.rank 78 | } 79 | 80 | /// The move is upward. 81 | public var isUpward: Bool { 82 | return end.rank > start.rank 83 | } 84 | 85 | /// The move is a knight jump two spaces horizontally and one space vertically, or two spaces vertically and one 86 | /// space horizontally. 87 | public var isKnightJump: Bool { 88 | let fileChange = abs(self.fileChange) 89 | let rankChange = abs(self.rankChange) 90 | return (fileChange == 2 && rankChange == 1) 91 | || (rankChange == 2 && fileChange == 1) 92 | } 93 | 94 | /// The move's direction in file, if any. 95 | public var fileDirection: File.Direction? { 96 | #if swift(>=3) 97 | if self.isLeftward { 98 | return .left 99 | } else if self.isRightward { 100 | return .right 101 | } else { 102 | return .none 103 | } 104 | #else 105 | if self.isLeftward { 106 | return .Left 107 | } else if self.isRightward { 108 | return .Right 109 | } else { 110 | return .None 111 | } 112 | #endif 113 | } 114 | 115 | /// The move's direction in rank, if any. 116 | public var rankDirection: Rank.Direction? { 117 | #if swift(>=3) 118 | if self.isUpward { 119 | return .up 120 | } else if self.isDownward { 121 | return .down 122 | } else { 123 | return .none 124 | } 125 | #else 126 | if self.isUpward { 127 | return .Up 128 | } else if self.isDownward { 129 | return .Down 130 | } else { 131 | return .None 132 | } 133 | #endif 134 | } 135 | 136 | /// A textual representation of `self`. 137 | public var description: String { 138 | return "\(start) >>> \(end)" 139 | } 140 | 141 | /// The hash value. 142 | public var hashValue: Int { 143 | return start.hashValue + (end.hashValue << 6) 144 | } 145 | 146 | /// Create a move with start and end squares. 147 | public init(start: Square, end: Square) { 148 | self.start = start 149 | self.end = end 150 | } 151 | 152 | /// Create a move with start and end locations. 153 | public init(start: Location, end: Location) { 154 | self.start = Square(location: start) 155 | self.end = Square(location: end) 156 | } 157 | 158 | /// A castle move for `color` in `direction`. 159 | public init(castle color: Color, direction: File.Direction) { 160 | let rank: Rank = color.isWhite ? 1 : 8 161 | #if swift(>=3) 162 | self = Move(start: Square(file: .e, rank: rank), 163 | end: Square(file: direction == .left ? .c : .g, rank: rank)) 164 | #else 165 | self = Move(start: Square(file: .E, rank: rank), 166 | end: Square(file: direction == .Left ? .C : .G, rank: rank)) 167 | #endif 168 | } 169 | 170 | /// Returns the castle squares for a rook. 171 | internal func _castleSquares() -> (old: Square, new: Square) { 172 | let rank = start.rank 173 | let movedLeft = self.isLeftward 174 | #if swift(>=3) 175 | let old = Square(file: movedLeft ? .a : .h, rank: rank) 176 | let new = Square(file: movedLeft ? .d : .f, rank: rank) 177 | #else 178 | let old = Square(file: movedLeft ? .A : .H, rank: rank) 179 | let new = Square(file: movedLeft ? .D : .F, rank: rank) 180 | #endif 181 | return (old, new) 182 | } 183 | 184 | /// Returns a move with the end and start of `self` reversed. 185 | public func reversed() -> Move { 186 | return Move(start: end, end: start) 187 | } 188 | 189 | /// Returns the result of rotating `self` 180 degrees. 190 | public func rotated() -> Move { 191 | let start = Square(file: self.start.file.opposite(), 192 | rank: self.start.rank.opposite()) 193 | let end = Square(file: self.end.file.opposite(), 194 | rank: self.end.rank.opposite()) 195 | return start >>> end 196 | } 197 | 198 | /// Returns `true` if `self` is castle move for `color`. 199 | /// 200 | /// - parameter color: The color to check the rank against. If `nil`, the rank can be either 1 or 8. The default 201 | /// value is `nil`. 202 | public func isCastle(for color: Color? = nil) -> Bool { 203 | #if swift(>=3) 204 | let e = File.e 205 | #else 206 | let e = File.E 207 | #endif 208 | let startRank = start.rank 209 | if let color = color { 210 | guard startRank == Rank(startFor: color) else { return false } 211 | } else { 212 | guard startRank == 1 || startRank == 8 else { return false } 213 | } 214 | return startRank == end.rank 215 | && start.file == e 216 | && abs(fileChange) == 2 217 | } 218 | 219 | } 220 | 221 | infix operator >>> { } 222 | 223 | /// Returns `true` if both moves are the same. 224 | public func == (lhs: Move, rhs: Move) -> Bool { 225 | return lhs.start == rhs.start && lhs.end == rhs.end 226 | } 227 | 228 | /// Returns a `Move` from the two squares. 229 | public func >>> (start: Square, end: Square) -> Move { 230 | return Move(start: start, end: end) 231 | } 232 | 233 | /// Returns a `Move` from the two locations. 234 | public func >>> (start: Location, rhs: Location) -> Move { 235 | return Square(location: start) >>> Square(location: rhs) 236 | } 237 | -------------------------------------------------------------------------------- /Pods/Sage/Sources/PGN.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PGN.swift 3 | // Sage 4 | // 5 | // Copyright 2016 Nikolai Vazquez 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | /// Portable game notation data. 21 | /// 22 | /// - seealso: [Portable Game Notation (Wikipedia)](https://en.wikipedia.org/wiki/Portable_Game_Notation), 23 | /// [PGN Specification](https://www.chessclub.com/user/help/PGN-spec) 24 | public struct PGN: Equatable { 25 | 26 | /// PGN tag. 27 | public enum Tag: String, CustomStringConvertible { 28 | 29 | #if swift(>=3) 30 | 31 | /// Event tag. 32 | case event = "Event" 33 | 34 | /// Site tag. 35 | case site = "Site" 36 | 37 | /// Date tag. 38 | case date = "Date" 39 | 40 | /// Round tag. 41 | case round = "Round" 42 | 43 | /// White tag. 44 | case white = "White" 45 | 46 | /// Black tag. 47 | case black = "Black" 48 | 49 | /// Result tag. 50 | case result = "Result" 51 | 52 | /// Annotator tag. 53 | case annotator = "Annotator" 54 | 55 | /// Ply (moves) count tag. 56 | case plyCount = "PlyCount" 57 | 58 | /// TimeControl tag. 59 | case timeControl = "TimeControl" 60 | 61 | /// Time tag. 62 | case time = "Time" 63 | 64 | /// Termination tag. 65 | case termination = "Termination" 66 | 67 | /// Playing mode tag. 68 | case mode = "Mode" 69 | 70 | /// FEN tag. 71 | case fen = "FEN" 72 | 73 | /// White player's title tag. 74 | case whiteTitle = "WhiteTitle" 75 | 76 | /// Black player's title tag. 77 | case blackTitle = "BlackTitle" 78 | 79 | /// White player's elo rating tag. 80 | case whiteElo = "WhiteElo" 81 | 82 | /// Black player's elo rating tag. 83 | case blackElo = "BlackElo" 84 | 85 | /// White player's United States Chess Federation rating tag. 86 | case whiteUSCF = "WhiteUSCF" 87 | 88 | /// Black player's United States Chess Federation rating tag. 89 | case blackUSCF = "BlackUSCF" 90 | 91 | /// White player's network or email address tag. 92 | case whiteNA = "WhiteNA" 93 | 94 | /// Black player's network or email address tag. 95 | case blackNA = "BlackNA" 96 | 97 | /// White player's type tag; either human or program. 98 | case whiteType = "WhiteType" 99 | 100 | /// Black player's type tag; either human or program. 101 | case blackType = "BlackType" 102 | 103 | /// The starting date tag of the event. 104 | case eventDate = "EventDate" 105 | 106 | /// Tag for the name of the sponsor of the event. 107 | case eventSponsor = "EventSponsor" 108 | 109 | /// The playing section tag of a tournament. 110 | case section = "Section" 111 | 112 | /// Tag for the stage of a multistage event. 113 | case stage = "Stage" 114 | 115 | /// The board number tag in a team event or in a simultaneous exhibition. 116 | case board = "Board" 117 | 118 | /// The traditional opening name tag. 119 | case opening = "Opening" 120 | 121 | /// Tag used to further refine the opening tag. 122 | case variation = "Variation" 123 | 124 | /// Used to further refine the variation tag. 125 | case subVariation = "SubVariation" 126 | 127 | /// Tag used for an opening designation from the five volume *Encyclopedia of Chess Openings*. 128 | case eco = "ECO" 129 | 130 | /// Tag used for an opening designation from the *New in Chess* database. 131 | case nic = "NIC" 132 | 133 | /// Tag similar to the Time tag but given according to the Universal Coordinated Time standard. 134 | case utcTime = "UTCTime" 135 | 136 | /// Tag similar to the Date tag but given according to the Universal Coordinated Time standard. 137 | case utcDate = "UTCDate" 138 | 139 | /// Tag for the "set-up" status of the game. 140 | case setUp = "SetUp" 141 | 142 | #else 143 | 144 | /// Event tag. 145 | case Event 146 | 147 | /// Site tag. 148 | case Site 149 | 150 | /// Date tag. 151 | case Date 152 | 153 | /// Round tag. 154 | case Round 155 | 156 | /// White tag. 157 | case White 158 | 159 | /// Black tag. 160 | case Black 161 | 162 | /// Result tag. 163 | case Result 164 | 165 | /// Annotator tag. 166 | case Annotator 167 | 168 | /// Ply (moves) count tag. 169 | case PlyCount 170 | 171 | /// TimeControl tag. 172 | case TimeControl 173 | 174 | /// Time tag. 175 | case Time 176 | 177 | /// Termination tag. 178 | case Termination 179 | 180 | /// Playing mode tag. 181 | case Mode 182 | 183 | /// FEN tag. 184 | case FEN 185 | 186 | /// White player's title tag. 187 | case WhiteTitle 188 | 189 | /// Black player's title tag. 190 | case BlackTitle 191 | 192 | /// White player's elo rating tag. 193 | case WhiteElo 194 | 195 | /// Black player's elo rating tag. 196 | case BlackElo 197 | 198 | /// White player's United States Chess Federation rating tag. 199 | case WhiteUSCF 200 | 201 | /// Black player's United States Chess Federation rating tag. 202 | case BlackUSCF 203 | 204 | /// White player's network or email address tag. 205 | case WhiteNA 206 | 207 | /// Black player's network or email address tag. 208 | case BlackNA 209 | 210 | /// White player's type tag; either human or program. 211 | case WhiteType 212 | 213 | /// Black player's type tag; either human or program. 214 | case BlackType 215 | 216 | /// The starting date tag of the event. 217 | case EventDate 218 | 219 | /// Tag for the name of the sponsor of the event. 220 | case EventSponsor 221 | 222 | /// The playing section tag of a tournament. 223 | case Section 224 | 225 | /// Tag for the stage of a multistage event. 226 | case Stage 227 | 228 | /// The board number tag in a team event or in a simultaneous exhibition. 229 | case Board 230 | 231 | /// The traditional opening name tag. 232 | case Opening 233 | 234 | /// Tag used to further refine the opening tag. 235 | case Variation 236 | 237 | /// Used to further refine the variation tag. 238 | case SubVariation 239 | 240 | /// Tag used for an opening designation from the five volume *Encyclopedia of Chess Openings*. 241 | case ECO 242 | 243 | /// Tag used for an opening designation from the *New in Chess* database. 244 | case NIC 245 | 246 | /// Tag similar to the Time tag but given according to the Universal Coordinated Time standard. 247 | case UTCTime 248 | 249 | /// Tag similar to the Date tag but given according to the Universal Coordinated Time standard. 250 | case UTCDate 251 | 252 | /// Tag for the "set-up" status of the game. 253 | case SetUp 254 | 255 | #endif 256 | 257 | /// A textual representation of `self`. 258 | public var description: String { 259 | return rawValue 260 | } 261 | 262 | } 263 | 264 | #if swift(>=3) 265 | 266 | /// An error thrown by `PGN.init(parse:)`. 267 | public enum ParseError: ErrorProtocol { 268 | 269 | /// Unexpected quote found in move text. 270 | case unexpectedQuote(String) 271 | 272 | /// Unexpected closing brace found outside of comment. 273 | case unexpectedClosingBrace(String) 274 | 275 | /// No closing brace for comment. 276 | case noClosingBrace(String) 277 | 278 | /// No closing quote for tag value. 279 | case noClosingQuote(String) 280 | 281 | /// No closing bracket for tag pair. 282 | case noClosingBracket(String) 283 | 284 | /// Wrong number of tokens for tag pair. 285 | case tagPairTokenCount([String]) 286 | 287 | /// Incorrect count of parenthesis for recursive annotation variation. 288 | case parenthesisCountForRAV(String) 289 | 290 | } 291 | 292 | #else 293 | 294 | /// An error thrown by `PGN.init(parse:)`. 295 | public enum ParseError: ErrorType { 296 | 297 | /// Unexpected quote found in move text. 298 | case UnexpectedQuote(String) 299 | 300 | /// Unexpected closing brace found outside of comment. 301 | case UnexpectedClosingBrace(String) 302 | 303 | /// No closing brace for comment. 304 | case NoClosingBrace(String) 305 | 306 | /// No closing quote for tag value. 307 | case NoClosingQuote(String) 308 | 309 | /// No closing bracket for tag pair. 310 | case NoClosingBracket(String) 311 | 312 | /// Wrong number of tokens for tag pair. 313 | case TagPairTokenCount([String]) 314 | 315 | /// Incorrect count of parenthesis for recursive annotation variation. 316 | case ParenthesisCountForRAV(String) 317 | 318 | } 319 | 320 | #endif 321 | 322 | /// The tag pairs for `self`. 323 | public var tagPairs: [String: String] 324 | 325 | /// The moves in standard algebraic notation. 326 | public var moves: [String] 327 | 328 | /// The game outcome. 329 | public var outcome: Game.Outcome? { 330 | get { 331 | #if swift(>=3) 332 | let resultTag = Tag.result 333 | #else 334 | let resultTag = Tag.Result 335 | #endif 336 | return self[resultTag].flatMap(Game.Outcome.init) 337 | } 338 | set { 339 | #if swift(>=3) 340 | let resultTag = Tag.result 341 | #else 342 | let resultTag = Tag.Result 343 | #endif 344 | self[resultTag] = newValue?.description 345 | } 346 | } 347 | 348 | /// Create PGN with `tagPairs` and `moves`. 349 | public init(tagPairs: [String: String] = [:], moves: [String] = []) { 350 | self.tagPairs = tagPairs 351 | self.moves = moves 352 | } 353 | 354 | /// Create PGN with `tagPairs` and `moves`. 355 | public init(tagPairs: [Tag: String], moves: [String] = []) { 356 | self.init(moves: moves) 357 | for (tag, value) in tagPairs { 358 | self[tag] = value 359 | } 360 | } 361 | 362 | /// Create PGN by parsing `string`. 363 | /// 364 | /// - throws: `ParseError` if an error occured while parsing. 365 | public init(parse string: String) throws { 366 | self.init() 367 | if string.isEmpty { return } 368 | for line in string._splitByNewlines() { 369 | if line.characters.first == "[" { 370 | let commentsStripped = try line._commentsStripped(strings: true) 371 | let (tag, value) = try commentsStripped._tagPair() 372 | tagPairs[tag] = value 373 | } else if line.characters.first != "%" { 374 | let commentsStripped = try line._commentsStripped(strings: false) 375 | let (moves, outcome) = try commentsStripped._moves() 376 | self.moves += moves 377 | if let outcome = outcome { 378 | self.outcome = outcome 379 | } 380 | } 381 | } 382 | } 383 | 384 | /// Get or set the value for `tag`. 385 | public subscript(tag: Tag) -> String? { 386 | get { 387 | return tagPairs[tag.rawValue] 388 | } 389 | set { 390 | tagPairs[tag.rawValue] = newValue 391 | } 392 | } 393 | 394 | /// Returns `self` in export string format. 395 | public func exported() -> String { 396 | var result = "" 397 | var tagPairs = self.tagPairs 398 | let sevenTags = [("Event", "?"), 399 | ("Site", "?"), 400 | ("Date", "????.??.??"), 401 | ("Round", "?"), 402 | ("White", "?"), 403 | ("Black", "?"), 404 | ("Result", "*")] 405 | for (tag, defaultValue) in sevenTags { 406 | if let value = tagPairs[tag] { 407 | tagPairs[tag] = nil 408 | result += "[\(tag) \"\(value)\"]\n" 409 | } else { 410 | result += "[\(tag) \"\(defaultValue)\"]\n" 411 | } 412 | } 413 | for (tag, value) in tagPairs { 414 | result += "[\(tag) \"\(value)\"]\n" 415 | } 416 | #if swift(>=3) 417 | let strideTo = stride(from: 0, to: moves.endIndex, by: 2) 418 | #else 419 | let strideTo = 0.stride(to: moves.endIndex, by: 2) 420 | #endif 421 | var moveLine = "" 422 | for num in strideTo { 423 | let moveNumber = (num + 2) / 2 424 | var moveString = "\(moveNumber). \(moves[num])" 425 | if num + 1 < moves.endIndex { 426 | moveString += " \(moves[num + 1])" 427 | } 428 | if moveString.characters.count + moveLine.characters.count < 80 { 429 | if !moveLine.isEmpty { 430 | moveString = " \(moveString)" 431 | } 432 | moveLine += moveString 433 | } else { 434 | result += "\n\(moveLine)" 435 | moveLine = moveString 436 | } 437 | } 438 | if !moveLine.isEmpty { 439 | result += "\n\(moveLine)" 440 | } 441 | if let outcomeString = outcome?.description { 442 | if moveLine.isEmpty { 443 | result += "\n\(outcomeString)" 444 | } else if outcomeString.characters.count + moveLine.characters.count < 80 { 445 | result += " \(outcomeString)" 446 | } else { 447 | result += "\n\(outcomeString)" 448 | } 449 | } 450 | return result 451 | } 452 | 453 | } 454 | 455 | private extension Character { 456 | 457 | static let newlines: Set = ["\u{000A}", "\u{000B}", "\u{000C}", "\u{000D}", 458 | "\u{0085}", "\u{2028}", "\u{2029}"] 459 | 460 | static let whitespaces: Set = ["\u{0020}", "\u{00A0}", "\u{1680}", "\u{180E}", "\u{2000}", 461 | "\u{2001}", "\u{2002}", "\u{2003}", "\u{2004}", "\u{2005}", 462 | "\u{2006}", "\u{2007}", "\u{2008}", "\u{2009}", "\u{200A}", 463 | "\u{200B}", "\u{202F}", "\u{205F}", "\u{3000}", "\u{FEFF}"] 464 | 465 | static let digits: Set = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"] 466 | 467 | var isDigit: Bool { 468 | return Character.digits.contains(self) 469 | } 470 | 471 | } 472 | 473 | private extension String { 474 | 475 | var _lastIndex: Index { 476 | #if swift(>=3) 477 | return index(before: endIndex) 478 | #else 479 | return endIndex.predecessor() 480 | #endif 481 | } 482 | 483 | @inline(__always) 484 | func _split(by set: Set) -> [String] { 485 | return characters.split(isSeparator: set.contains).map(String.init) 486 | } 487 | 488 | @inline(__always) 489 | func _splitByNewlines() -> [String] { 490 | return _split(by: Character.newlines) 491 | } 492 | 493 | @inline(__always) 494 | func _splitByWhitespaces() -> [String] { 495 | return _split(by: Character.whitespaces) 496 | } 497 | 498 | @inline(__always) 499 | func _tagPair() throws -> (String, String) { 500 | guard characters.last == "]" else { 501 | #if swift(>=3) 502 | throw PGN.ParseError.noClosingBracket(self) 503 | #else 504 | throw PGN.ParseError.NoClosingBracket(self) 505 | #endif 506 | } 507 | #if swift(>=3) 508 | let startIndex = index(after: self.startIndex) 509 | let endIndex = index(before: self.endIndex) 510 | #else 511 | let startIndex = self.startIndex.successor() 512 | let endIndex = self.endIndex.predecessor() 513 | #endif 514 | let tokens = self[startIndex ..< endIndex]._split(by: ["\""]) 515 | guard tokens.count == 2 else { 516 | #if swift(>=3) 517 | throw PGN.ParseError.tagPairTokenCount(tokens) 518 | #else 519 | throw PGN.ParseError.TagPairTokenCount(tokens) 520 | #endif 521 | } 522 | let tagParts = tokens[0]._splitByWhitespaces() 523 | guard tagParts.count == 1 else { 524 | #if swift(>=3) 525 | throw PGN.ParseError.tagPairTokenCount(tagParts) 526 | #else 527 | throw PGN.ParseError.TagPairTokenCount(tagParts) 528 | #endif 529 | } 530 | return (tagParts[0], tokens[1]) 531 | } 532 | 533 | @inline(__always) 534 | func _moves() throws -> (moves: [String], outcome: Game.Outcome?) { 535 | var stripped = "" 536 | var ravDepth = 0 537 | var startIndex = self.startIndex 538 | let lastIndex = _lastIndex 539 | for (index, character) in zip(characters.indices, characters) { 540 | if character == "(" { 541 | if ravDepth == 0 { 542 | stripped += self[startIndex ..< index] 543 | } 544 | ravDepth += 1 545 | } else if character == ")" { 546 | ravDepth -= 1 547 | if ravDepth == 0 { 548 | #if swift(>=3) 549 | startIndex = self.index(after: index) 550 | #else 551 | startIndex = index.successor() 552 | #endif 553 | } 554 | } else if index == lastIndex && ravDepth == 0 { 555 | stripped += self[startIndex ... index] 556 | } 557 | } 558 | guard ravDepth == 0 else { 559 | #if swift(>=3) 560 | throw PGN.ParseError.parenthesisCountForRAV(self) 561 | #else 562 | throw PGN.ParseError.ParenthesisCountForRAV(self) 563 | #endif 564 | } 565 | let tokens = stripped._split(by: [" ", "."]) 566 | let moves = tokens.filter({ $0.characters.first?.isDigit == false }) 567 | let outcome = tokens.last.flatMap(Game.Outcome.init) 568 | return (moves, outcome) 569 | } 570 | 571 | @inline(__always) 572 | func _commentsStripped(strings consideringStrings: Bool) throws -> String { 573 | var stripped = "" 574 | var startIndex = self.startIndex 575 | let lastIndex = _lastIndex 576 | var afterEscape = false 577 | var inString = false 578 | var inComment = false 579 | for (index, character) in zip(characters.indices, characters) { 580 | if character == "\\" { 581 | afterEscape = true 582 | continue 583 | } 584 | if character == "\"" { 585 | if !inComment { 586 | guard consideringStrings else { 587 | #if swift(>=3) 588 | throw PGN.ParseError.unexpectedQuote(self) 589 | #else 590 | throw PGN.ParseError.UnexpectedQuote(self) 591 | #endif 592 | } 593 | if !inString { 594 | inString = true 595 | } else if !afterEscape { 596 | inString = false 597 | } 598 | } 599 | } else if !inString { 600 | if character == ";" && !inComment { 601 | stripped += self[startIndex ..< index] 602 | break 603 | } else if character == "{" && !inComment { 604 | inComment = true 605 | stripped += self[startIndex ..< index] 606 | } else if character == "}" { 607 | guard inComment else { 608 | #if swift(>=3) 609 | throw PGN.ParseError.unexpectedClosingBrace(self) 610 | #else 611 | throw PGN.ParseError.UnexpectedClosingBrace(self) 612 | #endif 613 | } 614 | inComment = false 615 | #if swift(>=3) 616 | startIndex = self.index(after: index) 617 | #else 618 | startIndex = index.successor() 619 | #endif 620 | } 621 | } 622 | if index >= startIndex && index == lastIndex && !inComment { 623 | stripped += self[startIndex ... index] 624 | } 625 | afterEscape = false 626 | } 627 | guard !inString else { 628 | #if swift(>=3) 629 | throw PGN.ParseError.noClosingQuote(self) 630 | #else 631 | throw PGN.ParseError.NoClosingQuote(self) 632 | #endif 633 | } 634 | guard !inComment else { 635 | #if swift(>=3) 636 | throw PGN.ParseError.noClosingBrace(self) 637 | #else 638 | throw PGN.ParseError.NoClosingBrace(self) 639 | #endif 640 | } 641 | return stripped 642 | } 643 | 644 | } 645 | 646 | /// Returns a Boolean value indicating whether two values are equal. 647 | public func == (lhs: PGN, rhs: PGN) -> Bool { 648 | return lhs.tagPairs == rhs.tagPairs 649 | && lhs.moves == rhs.moves 650 | } 651 | -------------------------------------------------------------------------------- /Pods/Sage/Sources/Piece.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Piece.swift 3 | // Sage 4 | // 5 | // Copyright 2016 Nikolai Vazquez 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | /// A chess piece. 21 | public struct Piece: Hashable, CustomStringConvertible { 22 | 23 | /// A piece kind. 24 | public enum Kind: Int { 25 | 26 | #if swift(>=3) 27 | 28 | /// Pawn piece kind. 29 | case pawn 30 | 31 | /// Knight piece kind. 32 | case knight 33 | 34 | /// Bishop piece kind. 35 | case bishop 36 | 37 | /// Rook piece kind. 38 | case rook 39 | 40 | /// Queen piece kind. 41 | case queen 42 | 43 | /// King piece kind. 44 | case king 45 | 46 | /// Pawn regardless of Swift veersion. 47 | internal static let _pawn = Kind.pawn 48 | 49 | /// Knight regardless of Swift veersion. 50 | internal static let _knight = Kind.knight 51 | 52 | /// Bishop regardless of Swift veersion. 53 | internal static let _bishop = Kind.bishop 54 | 55 | /// Rook regardless of Swift veersion. 56 | internal static let _rook = Kind.rook 57 | 58 | /// Queen regardless of Swift veersion. 59 | internal static let _queen = Kind.queen 60 | 61 | /// King regardless of Swift veersion. 62 | internal static let _king = Kind.king 63 | 64 | /// An array of all piece kinds. 65 | public static let all: [Kind] = [.pawn, .knight, .bishop, .rook, .queen, .king] 66 | 67 | #else 68 | 69 | /// Pawn piece kind. 70 | case Pawn 71 | 72 | /// Knight piece kind. 73 | case Knight 74 | 75 | /// Bishop piece kind. 76 | case Bishop 77 | 78 | /// Rook piece kind. 79 | case Rook 80 | 81 | /// Queen piece kind. 82 | case Queen 83 | 84 | /// King piece kind. 85 | case King 86 | 87 | /// Pawn regardless of Swift veersion. 88 | internal static let _pawn = Kind.Pawn 89 | 90 | /// Knight regardless of Swift veersion. 91 | internal static let _knight = Kind.Knight 92 | 93 | /// Bishop regardless of Swift veersion. 94 | internal static let _bishop = Kind.Bishop 95 | 96 | /// Rook regardless of Swift veersion. 97 | internal static let _rook = Kind.Rook 98 | 99 | /// Queen regardless of Swift veersion. 100 | internal static let _queen = Kind.Queen 101 | 102 | /// King regardless of Swift veersion. 103 | internal static let _king = Kind.King 104 | 105 | /// An array of all piece kinds. 106 | public static let all: [Kind] = [.Pawn, .Knight, .Bishop, .Rook, .Queen, .King] 107 | 108 | #endif 109 | 110 | /// The piece kind's name. 111 | public var name: String { 112 | #if swift(>=3) 113 | switch self { 114 | case .pawn: return "Pawn" 115 | case .knight: return "Knight" 116 | case .bishop: return "Bishop" 117 | case .rook: return "Rook" 118 | case .queen: return "Queen" 119 | case .king: return "King" 120 | } 121 | #else 122 | switch self { 123 | case .Pawn: return "Pawn" 124 | case .Knight: return "Knight" 125 | case .Bishop: return "Bishop" 126 | case .Rook: return "Rook" 127 | case .Queen: return "Queen" 128 | case .King: return "King" 129 | } 130 | #endif 131 | } 132 | 133 | /// The piece kind's relative value. Can be used to determine how valuable a piece or combination of pieces is. 134 | public var relativeValue: Double { 135 | #if swift(>=3) 136 | switch self { 137 | case .pawn: return 1 138 | case .knight: return 3 139 | case .bishop: return 3.25 140 | case .rook: return 5 141 | case .queen: return 9 142 | case .king: return .infinity 143 | } 144 | #else 145 | switch self { 146 | case .Pawn: return 1 147 | case .Knight: return 3 148 | case .Bishop: return 3.25 149 | case .Rook: return 5 150 | case .Queen: return 9 151 | case .King: return .infinity 152 | } 153 | #endif 154 | } 155 | 156 | /// The piece is `Pawn`. 157 | public var isPawn: Bool { 158 | return self == ._pawn 159 | } 160 | 161 | /// The piece `Knight`. 162 | public var isKnight: Bool { 163 | return self == ._knight 164 | } 165 | 166 | /// The piece is `Bishop`. 167 | public var isBishop: Bool { 168 | return self == ._bishop 169 | } 170 | 171 | /// The piece is `Rook`. 172 | public var isRook: Bool { 173 | return self == ._rook 174 | } 175 | 176 | /// The piece is `Queen`. 177 | public var isQueen: Bool { 178 | return self == ._queen 179 | } 180 | 181 | /// The piece is `King`. 182 | public var isKing: Bool { 183 | return self == ._king 184 | } 185 | 186 | /// Returns `true` if `self` can be a promotion for a pawn. 187 | public func canPromote() -> Bool { 188 | return !(isPawn || isKing) 189 | } 190 | 191 | /// Returns `true` if `self` can be a promotion for `other`. 192 | public func canPromote(_ other: Kind) -> Bool { 193 | return canPromote() ? other.isPawn : false 194 | } 195 | 196 | } 197 | 198 | /// An array of all pieces. 199 | public static let all: [Piece] = { 200 | return [._white, ._black].reduce([]) { pieces, color in 201 | return pieces + Kind.all.map({ Piece(kind: $0, color: color) }) 202 | } 203 | }() 204 | 205 | 206 | /// An array of all white pieces. 207 | public static let whitePieces: [Piece] = all.filter({ $0.color.isWhite }) 208 | 209 | /// An array of all black pieces. 210 | public static let blackPieces: [Piece] = all.filter({ $0.color.isBlack }) 211 | 212 | /// Returns an array of all pieces for `color`. 213 | public static func pieces(for color: Color) -> [Piece] { 214 | return color.isWhite ? whitePieces : blackPieces 215 | } 216 | 217 | /// The piece's kind. 218 | public var kind: Kind 219 | 220 | /// The piece's color. 221 | public var color: Color 222 | 223 | /// The character for the piece. Uppercase if white or lowercase if black. 224 | public var character: Character { 225 | #if swift(>=3) 226 | switch kind { 227 | case .pawn: return color.isWhite ? "P" : "p" 228 | case .knight: return color.isWhite ? "N" : "n" 229 | case .bishop: return color.isWhite ? "B" : "b" 230 | case .rook: return color.isWhite ? "R" : "r" 231 | case .queen: return color.isWhite ? "Q" : "q" 232 | case .king: return color.isWhite ? "K" : "k" 233 | } 234 | #else 235 | switch kind { 236 | case .Pawn: return color.isWhite ? "P" : "p" 237 | case .Knight: return color.isWhite ? "N" : "n" 238 | case .Bishop: return color.isWhite ? "B" : "b" 239 | case .Rook: return color.isWhite ? "R" : "r" 240 | case .Queen: return color.isWhite ? "Q" : "q" 241 | case .King: return color.isWhite ? "K" : "k" 242 | } 243 | #endif 244 | } 245 | 246 | /// A textual representation of `self`. 247 | public var description: String { 248 | return "\(kind.name)(\(color))" 249 | } 250 | 251 | /// The hash value. 252 | public var hashValue: Int { 253 | return (kind.hashValue << 1) | color.hashValue 254 | } 255 | 256 | /// Create a piece from an integer value. 257 | internal init?(value: Int) { 258 | guard let kind = Kind(rawValue: value >> 1) else { 259 | return nil 260 | } 261 | self.init(kind: kind, color: value & 1 == 0 ? ._white : ._black) 262 | } 263 | 264 | /// Create a piece from `kind` and `color`. 265 | public init(kind: Kind, color: Color) { 266 | self.kind = kind 267 | self.color = color 268 | } 269 | 270 | /// Create a pawn piece with `color`. 271 | public init(pawn color: Color) { 272 | #if swift(>=3) 273 | self.init(kind: .pawn, color: color) 274 | #else 275 | self.init(kind: .Pawn, color: color) 276 | #endif 277 | } 278 | 279 | /// Create a knight piece with `color`. 280 | public init(knight color: Color) { 281 | #if swift(>=3) 282 | self.init(kind: .knight, color: color) 283 | #else 284 | self.init(kind: .Knight, color: color) 285 | #endif 286 | } 287 | 288 | /// Create a bishop piece with `color`. 289 | public init(bishop color: Color) { 290 | #if swift(>=3) 291 | self.init(kind: .bishop, color: color) 292 | #else 293 | self.init(kind: .Bishop, color: color) 294 | #endif 295 | } 296 | 297 | /// Create a rook piece with `color`. 298 | public init(rook color: Color) { 299 | #if swift(>=3) 300 | self.init(kind: .rook, color: color) 301 | #else 302 | self.init(kind: .Rook, color: color) 303 | #endif 304 | } 305 | 306 | /// Create a queen piece with `color`. 307 | public init(queen color: Color) { 308 | #if swift(>=3) 309 | self.init(kind: .queen, color: color) 310 | #else 311 | self.init(kind: .Queen, color: color) 312 | #endif 313 | } 314 | 315 | /// Create a king piece with `color`. 316 | public init(king color: Color) { 317 | #if swift(>=3) 318 | self.init(kind: .king, color: color) 319 | #else 320 | self.init(kind: .King, color: color) 321 | #endif 322 | } 323 | 324 | /// Create a piece from a character. 325 | public init?(character: Character) { 326 | switch character { 327 | case "P": self.init(pawn: ._white) 328 | case "p": self.init(pawn: ._black) 329 | case "N": self.init(knight: ._white) 330 | case "n": self.init(knight: ._black) 331 | case "B": self.init(bishop: ._white) 332 | case "b": self.init(bishop: ._black) 333 | case "R": self.init(rook: ._white) 334 | case "r": self.init(rook: ._black) 335 | case "Q": self.init(queen: ._white) 336 | case "q": self.init(queen: ._black) 337 | case "K": self.init(king: ._white) 338 | case "k": self.init(king: ._black) 339 | default: 340 | return nil 341 | } 342 | } 343 | 344 | /// Returns `true` if `self` can be a promotion for `other`. 345 | public func canPromote(_ other: Piece) -> Bool { 346 | return kind.canPromote(other.kind) && color == other.color 347 | } 348 | 349 | /// Returns `true` if `self` can be a promotion for `color`. 350 | public func canPromote(_ color: Color) -> Bool { 351 | return kind.canPromote() ? self.color == color : false 352 | } 353 | 354 | /// The special character for the piece. 355 | public func specialCharacter(background color: Color = ._white) -> Character { 356 | #if swift(>=3) 357 | switch kind { 358 | case .pawn: return color == self.color ? "♙" : "♟" 359 | case .knight: return color == self.color ? "♘" : "♞" 360 | case .bishop: return color == self.color ? "♗" : "♝" 361 | case .rook: return color == self.color ? "♖" : "♜" 362 | case .queen: return color == self.color ? "♕" : "♛" 363 | case .king: return color == self.color ? "♔" : "♚" 364 | } 365 | #else 366 | switch kind { 367 | case .Pawn: return color == self.color ? "♙" : "♟" 368 | case .Knight: return color == self.color ? "♘" : "♞" 369 | case .Bishop: return color == self.color ? "♗" : "♝" 370 | case .Rook: return color == self.color ? "♖" : "♜" 371 | case .Queen: return color == self.color ? "♕" : "♛" 372 | case .King: return color == self.color ? "♔" : "♚" 373 | } 374 | #endif 375 | } 376 | 377 | } 378 | 379 | /// Returns `true` if both pieces are the same. 380 | public func == (lhs: Piece, rhs: Piece) -> Bool { 381 | return lhs.kind == rhs.kind 382 | && lhs.color == rhs.color 383 | } 384 | -------------------------------------------------------------------------------- /Pods/Sage/Sources/Player.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Player.swift 3 | // Sage 4 | // 5 | // Copyright 2016 Nikolai Vazquez 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | /// A chess game player. 21 | public struct Player: Equatable, CustomStringConvertible { 22 | 23 | /// A player kind. 24 | public enum Kind: String, CustomStringConvertible { 25 | 26 | #if swift(>=3) 27 | 28 | /// Human player kind. 29 | case human = "Human" 30 | 31 | /// Computer player kind. 32 | case computer = "Computer" 33 | 34 | /// Human regardless of Swift version. 35 | internal static let _human = Kind.human 36 | 37 | /// Computer regardless of Swift version. 38 | internal static let _computer = Kind.computer 39 | 40 | #else 41 | 42 | /// Human player kind. 43 | case Human 44 | 45 | /// Computer player kind. 46 | case Computer 47 | 48 | /// Human regardless of Swift version. 49 | internal static let _human = Kind.Human 50 | 51 | /// Computer regardless of Swift version. 52 | internal static let _computer = Kind.Computer 53 | 54 | #endif 55 | 56 | /// Boolean indicating `self` is a human. 57 | public var isHuman: Bool { 58 | return self == ._human 59 | } 60 | 61 | /// Boolean indicating `self` is a computer. 62 | public var isComputer: Bool { 63 | return self == ._computer 64 | } 65 | 66 | /// A textual representation of this instance. 67 | public var description: String { 68 | return rawValue 69 | } 70 | 71 | } 72 | 73 | /// The the player's kind. 74 | public var kind: Kind 75 | 76 | /// The player's name. 77 | public var name: String? 78 | 79 | /// The player's elo rating. 80 | public var elo: UInt? 81 | 82 | /// A textual representation of this instance. 83 | public var description: String { 84 | return "Player(kind: \(kind), name: \(name._altDescription), elo: \(elo._altDescription))" 85 | } 86 | 87 | /// Create a player with `kind` and `name`. 88 | /// 89 | /// - parameter kind: The player's kind. Default is human. 90 | /// - parameter name: The player's name. Default is `nil`. 91 | /// - parameter elo: The player's elo rating. Default is `nil`. 92 | public init(kind: Kind = ._human, name: String? = nil, elo: UInt? = nil) { 93 | self.kind = kind 94 | self.name = name 95 | self.elo = elo 96 | } 97 | 98 | } 99 | 100 | /// Returns `true` if the players are the same. 101 | public func == (lhs: Player, rhs: Player) -> Bool { 102 | return lhs.kind == rhs.kind 103 | && lhs.name == rhs.name 104 | && lhs.elo == rhs.elo 105 | } 106 | -------------------------------------------------------------------------------- /Pods/Sage/Sources/Rank.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Rank.swift 3 | // Sage 4 | // 5 | // Copyright 2016 Nikolai Vazquez 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | /// A chess board rank. 21 | /// 22 | /// `Rank`s refer to the eight rows of a chess board, beginning with 1 at the bottom and ending with 8 at the top. 23 | public enum Rank: Int, Comparable, CustomStringConvertible { 24 | 25 | /// A direction in rank. 26 | public enum Direction { 27 | 28 | #if swift(>=3) 29 | 30 | /// Up direction. 31 | case up 32 | 33 | /// Down direction. 34 | case down 35 | 36 | #else 37 | 38 | /// Up direction. 39 | case Up 40 | 41 | /// Down direction. 42 | case Down 43 | 44 | #endif 45 | 46 | } 47 | 48 | #if swift(>=3) 49 | 50 | /// Rank 1. 51 | case one = 1 52 | 53 | /// Rank 2. 54 | case two = 2 55 | 56 | /// Rank 3. 57 | case three = 3 58 | 59 | /// Rank 4. 60 | case four = 4 61 | 62 | /// Rank 5. 63 | case five = 5 64 | 65 | /// Rank 6. 66 | case six = 6 67 | 68 | /// Rank 7. 69 | case seven = 7 70 | 71 | /// Rank 8. 72 | case eight = 8 73 | 74 | #else 75 | 76 | /// Rank 1. 77 | case One = 1 78 | 79 | /// Rank 2. 80 | case Two = 2 81 | 82 | /// Rank 3. 83 | case Three = 3 84 | 85 | /// Rank 4. 86 | case Four = 4 87 | 88 | /// Rank 5. 89 | case Five = 5 90 | 91 | /// Rank 6. 92 | case Six = 6 93 | 94 | /// Rank 7. 95 | case Seven = 7 96 | 97 | /// Rank 8. 98 | case Eight = 8 99 | 100 | #endif 101 | 102 | } 103 | 104 | extension Rank { 105 | 106 | /// An array of all ranks. 107 | public static let all: [Rank] = [1, 2, 3, 4, 5, 6, 7, 8] 108 | 109 | /// The row index of `self`. 110 | public var index: Int { 111 | return rawValue - 1 112 | } 113 | 114 | /// A textual representation of `self`. 115 | public var description: String { 116 | return String(rawValue) 117 | } 118 | 119 | /// Create an instance from an integer value. 120 | public init?(_ value: Int) { 121 | self.init(rawValue: value) 122 | } 123 | 124 | /// Create a `Rank` from a zero-based row index. 125 | public init?(index: Int) { 126 | self.init(rawValue: index + 1) 127 | } 128 | 129 | /// Creates the starting `Rank` for the color. 130 | public init(startFor color: Color) { 131 | self = color.isWhite ? 1 : 8 132 | } 133 | 134 | /// Creates the ending `Rank` for the color. 135 | public init(endFor color: Color) { 136 | self = color.isWhite ? 8 : 1 137 | } 138 | 139 | /// Returns a rank from advancing `self` by `value` with respect to `color`. 140 | public func advanced(by value: Int, for color: Color = ._white) -> Rank? { 141 | return Rank(rawValue: rawValue + (color.isWhite ? value : -value)) 142 | } 143 | 144 | /// The next rank after `self`. 145 | public func next() -> Rank? { 146 | return Rank(rawValue: (rawValue + 1)) 147 | } 148 | 149 | /// The previous rank to `self`. 150 | public func previous() -> Rank? { 151 | return Rank(rawValue: (rawValue - 1)) 152 | } 153 | 154 | /// The opposite rank of `self`. 155 | public func opposite() -> Rank { 156 | return Rank(rawValue: 9 - rawValue)! 157 | } 158 | 159 | /// The files from `self` to `other`. 160 | public func to(_ other: Rank) -> [Rank] { 161 | if other > self { 162 | return (rawValue...other.rawValue).flatMap(Rank.init(rawValue:)) 163 | } else if other < self { 164 | #if swift(>=3) 165 | let values = (other.rawValue...rawValue).reversed() 166 | #else 167 | let values = (other.rawValue...rawValue).reverse() 168 | #endif 169 | return values.flatMap(Rank.init(rawValue:)) 170 | } else { 171 | return [self] 172 | } 173 | } 174 | 175 | /// The files between `self` and `other`. 176 | public func between(_ other: Rank) -> [Rank] { 177 | if other > self { 178 | return (rawValue + 1 ..< other.rawValue).flatMap(Rank.init(rawValue:)) 179 | } else if other < self { 180 | #if swift(>=3) 181 | let values = (other.rawValue + 1 ..< rawValue).reversed() 182 | #else 183 | let values = (other.rawValue + 1 ..< rawValue).reverse() 184 | #endif 185 | return values.flatMap(Rank.init(rawValue:)) 186 | } else { 187 | return [] 188 | } 189 | } 190 | 191 | } 192 | 193 | extension Rank: IntegerLiteralConvertible { 194 | 195 | /// Create an instance initialized to `value`. 196 | public init(integerLiteral value: Int) { 197 | guard let rank = Rank(rawValue: value) else { 198 | fatalError("Rank value not within 1 and 8, inclusive") 199 | } 200 | self = rank 201 | } 202 | 203 | } 204 | 205 | /// Returns `true` if one rank is higher than the other. 206 | public func < (lhs: Rank, rhs: Rank) -> Bool { 207 | return lhs.rawValue < rhs.rawValue 208 | } 209 | -------------------------------------------------------------------------------- /Pods/Sage/Sources/Sequence+Sage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Sequence+Sage.swift 3 | // Sage 4 | // 5 | // Copyright 2016 Nikolai Vazquez 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | #if swift(>=3) 21 | 22 | extension Sequence where Iterator.Element == Square { 23 | 24 | /// Returns moves from `square` to the squares in `self`. 25 | public func moves(from square: Square) -> [Move] { 26 | return self.map({ square >>> $0 }) 27 | } 28 | 29 | /// Returns moves from the squares in `self` to `square`. 30 | public func moves(to square: Square) -> [Move] { 31 | return self.map({ $0 >>> square }) 32 | } 33 | 34 | } 35 | 36 | #else 37 | 38 | extension SequenceType where Generator.Element == Square { 39 | 40 | /// Returns moves from `square` to the squares in `self`. 41 | public func moves(from square: Square) -> [Move] { 42 | return self.map({ square >>> $0 }) 43 | } 44 | 45 | /// Returns moves from the squares in `self` to `square`. 46 | public func moves(to square: Square) -> [Move] { 47 | return self.map({ $0 >>> square }) 48 | } 49 | 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /Pods/Sage/Sources/Square.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Square.swift 3 | // Sage 4 | // 5 | // Copyright 2016 Nikolai Vazquez 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | /// A pair of a chess board `File` and `Rank`. 21 | public typealias Location = (file: File, rank: Rank) 22 | 23 | /// A chess board square. 24 | /// 25 | /// A `Square` can be one of sixty-four possible values, ranging from `A1` to `H8`. 26 | public enum Square: Int, CustomStringConvertible { 27 | 28 | #if swift(>=3) 29 | 30 | /// A1 square. 31 | case a1 32 | 33 | /// B1 square. 34 | case b1 35 | 36 | /// C1 square. 37 | case c1 38 | 39 | /// D1 square. 40 | case d1 41 | 42 | /// E1 square. 43 | case e1 44 | 45 | /// F1 square. 46 | case f1 47 | 48 | /// G1 square. 49 | case g1 50 | 51 | /// H1 square. 52 | case h1 53 | 54 | /// A2 square. 55 | case a2 56 | 57 | /// B2 square. 58 | case b2 59 | 60 | /// C2 square. 61 | case c2 62 | 63 | /// D2 square. 64 | case d2 65 | 66 | /// E2 square. 67 | case e2 68 | 69 | /// F2 square. 70 | case f2 71 | 72 | /// G2 square. 73 | case g2 74 | 75 | /// H2 square. 76 | case h2 77 | 78 | /// A3 square. 79 | case a3 80 | 81 | /// B3 square. 82 | case b3 83 | 84 | /// C3 square. 85 | case c3 86 | 87 | /// D3 square. 88 | case d3 89 | 90 | /// E3 square. 91 | case e3 92 | 93 | /// F3 square. 94 | case f3 95 | 96 | /// G3 square. 97 | case g3 98 | 99 | /// H3 square. 100 | case h3 101 | 102 | /// A4 square. 103 | case a4 104 | 105 | /// B4 square. 106 | case b4 107 | 108 | /// C4 square. 109 | case c4 110 | 111 | /// D4 square. 112 | case d4 113 | 114 | /// E4 square. 115 | case e4 116 | 117 | /// F4 square. 118 | case f4 119 | 120 | /// G4 square. 121 | case g4 122 | 123 | /// H4 square. 124 | case h4 125 | 126 | /// A5 square. 127 | case a5 128 | 129 | /// B5 square. 130 | case b5 131 | 132 | /// C5 square. 133 | case c5 134 | 135 | /// D5 square. 136 | case d5 137 | 138 | /// E5 square. 139 | case e5 140 | 141 | /// F5 square. 142 | case f5 143 | 144 | /// G5 square. 145 | case g5 146 | 147 | /// H5 square. 148 | case h5 149 | 150 | /// A6 square. 151 | case a6 152 | 153 | /// B6 square. 154 | case b6 155 | 156 | /// C6 square. 157 | case c6 158 | 159 | /// D6 square. 160 | case d6 161 | 162 | /// E6 square. 163 | case e6 164 | 165 | /// F6 square. 166 | case f6 167 | 168 | /// G6 square. 169 | case g6 170 | 171 | /// H6 square. 172 | case h6 173 | 174 | /// A7 square. 175 | case a7 176 | 177 | /// B7 square. 178 | case b7 179 | 180 | /// C7 square. 181 | case c7 182 | 183 | /// D7 square. 184 | case d7 185 | 186 | /// E7 square. 187 | case e7 188 | 189 | /// F7 square. 190 | case f7 191 | 192 | /// G7 square. 193 | case g7 194 | 195 | /// H7 square. 196 | case h7 197 | 198 | /// A8 square. 199 | case a8 200 | 201 | /// B8 square. 202 | case b8 203 | 204 | /// C8 square. 205 | case c8 206 | 207 | /// D8 square. 208 | case d8 209 | 210 | /// E8 square. 211 | case e8 212 | 213 | /// F8 square. 214 | case f8 215 | 216 | /// G8 square. 217 | case g8 218 | 219 | /// H8 square. 220 | case h8 221 | 222 | #else 223 | 224 | /// A1 square. 225 | case A1 226 | 227 | /// B1 square. 228 | case B1 229 | 230 | /// C1 square. 231 | case C1 232 | 233 | /// D1 square. 234 | case D1 235 | 236 | /// E1 square. 237 | case E1 238 | 239 | /// F1 square. 240 | case F1 241 | 242 | /// G1 square. 243 | case G1 244 | 245 | /// H1 square. 246 | case H1 247 | 248 | /// A2 square. 249 | case A2 250 | 251 | /// B2 square. 252 | case B2 253 | 254 | /// C2 square. 255 | case C2 256 | 257 | /// D2 square. 258 | case D2 259 | 260 | /// E2 square. 261 | case E2 262 | 263 | /// F2 square. 264 | case F2 265 | 266 | /// G2 square. 267 | case G2 268 | 269 | /// H2 square. 270 | case H2 271 | 272 | /// A3 square. 273 | case A3 274 | 275 | /// B3 square. 276 | case B3 277 | 278 | /// C3 square. 279 | case C3 280 | 281 | /// D3 square. 282 | case D3 283 | 284 | /// E3 square. 285 | case E3 286 | 287 | /// F3 square. 288 | case F3 289 | 290 | /// G3 square. 291 | case G3 292 | 293 | /// H3 square. 294 | case H3 295 | 296 | /// A4 square. 297 | case A4 298 | 299 | /// B4 square. 300 | case B4 301 | 302 | /// C4 square. 303 | case C4 304 | 305 | /// D4 square. 306 | case D4 307 | 308 | /// E4 square. 309 | case E4 310 | 311 | /// F4 square. 312 | case F4 313 | 314 | /// G4 square. 315 | case G4 316 | 317 | /// H4 square. 318 | case H4 319 | 320 | /// A5 square. 321 | case A5 322 | 323 | /// B5 square. 324 | case B5 325 | 326 | /// C5 square. 327 | case C5 328 | 329 | /// D5 square. 330 | case D5 331 | 332 | /// E5 square. 333 | case E5 334 | 335 | /// F5 square. 336 | case F5 337 | 338 | /// G5 square. 339 | case G5 340 | 341 | /// H5 square. 342 | case H5 343 | 344 | /// A6 square. 345 | case A6 346 | 347 | /// B6 square. 348 | case B6 349 | 350 | /// C6 square. 351 | case C6 352 | 353 | /// D6 square. 354 | case D6 355 | 356 | /// E6 square. 357 | case E6 358 | 359 | /// F6 square. 360 | case F6 361 | 362 | /// G6 square. 363 | case G6 364 | 365 | /// H6 square. 366 | case H6 367 | 368 | /// A7 square. 369 | case A7 370 | 371 | /// B7 square. 372 | case B7 373 | 374 | /// C7 square. 375 | case C7 376 | 377 | /// D7 square. 378 | case D7 379 | 380 | /// E7 square. 381 | case E7 382 | 383 | /// F7 square. 384 | case F7 385 | 386 | /// G7 square. 387 | case G7 388 | 389 | /// H7 square. 390 | case H7 391 | 392 | /// A8 square. 393 | case A8 394 | 395 | /// B8 square. 396 | case B8 397 | 398 | /// C8 square. 399 | case C8 400 | 401 | /// D8 square. 402 | case D8 403 | 404 | /// E8 square. 405 | case E8 406 | 407 | /// F8 square. 408 | case F8 409 | 410 | /// G8 square. 411 | case G8 412 | 413 | /// H8 square. 414 | case H8 415 | 416 | #endif 417 | 418 | } 419 | 420 | extension Square { 421 | 422 | /// An array of all squares. 423 | public static let all: [Square] = (0 ..< 64).flatMap(Square.init(rawValue:)) 424 | 425 | /// The file of `self`. 426 | public var file: File { 427 | get { 428 | return File(index: rawValue & 7)! 429 | } 430 | set(newFile) { 431 | self = Square(file: newFile, rank: rank) 432 | } 433 | } 434 | 435 | /// The rank of `self`. 436 | public var rank: Rank { 437 | get { 438 | return Rank(index: rawValue >> 3)! 439 | } 440 | set(newRank) { 441 | self = Square(file: file, rank: newRank) 442 | } 443 | } 444 | 445 | /// The location of `self`. 446 | public var location: Location { 447 | get { 448 | return (file, rank) 449 | } 450 | set(newLocation) { 451 | self = Square(location: newLocation) 452 | } 453 | } 454 | 455 | /// The square's color. 456 | public var color: Color { 457 | return (file.index & 1 != rank.index & 1) ? ._white : ._black 458 | } 459 | 460 | /// A textual representation of `self`. 461 | public var description: String { 462 | return "\(file)\(rank)" 463 | } 464 | 465 | /// Create a square from `file` and `rank`. 466 | public init(file: File, rank: Rank) { 467 | self.init(rawValue: file.index + (rank.index << 3))! 468 | } 469 | 470 | /// Create a square from `location`. 471 | public init(location: Location) { 472 | self.init(file: location.file, rank: location.rank) 473 | } 474 | 475 | /// Create a square from `file` and `rank`. Returns `nil` if either is `nil`. 476 | public init?(file: File?, rank: Rank?) { 477 | guard let file = file, rank = rank else { 478 | return nil 479 | } 480 | self.init(file: file, rank: rank) 481 | } 482 | 483 | /// Create a square from `string`. 484 | public init?(_ string: String) { 485 | let chars = string.characters 486 | guard chars.count == 2 else { 487 | return nil 488 | } 489 | guard let file = File(chars.first!) else { 490 | return nil 491 | } 492 | guard let rank = Int(String(chars.last!)).flatMap(Rank.init(_:)) else { 493 | return nil 494 | } 495 | self.init(file: file, rank: rank) 496 | } 497 | 498 | /// Returns a bitboard mask of attacks for a king at `self`. 499 | public func kingAttacks() -> Bitboard { 500 | return _kingAttackTable[rawValue] 501 | } 502 | 503 | /// Returns a bitboard mask of attacks for a knight at `self`. 504 | public func knightAttacks() -> Bitboard { 505 | return _knightAttackTable[rawValue] 506 | } 507 | 508 | /// Returns a bitboard mask of attacks for a piece at `self`. 509 | /// 510 | /// - parameter piece: The piece for the attacks. 511 | /// - parameter stoppers: The pieces stopping a sliding move. The returned bitboard includes the stopped space. 512 | /// 513 | /// - seealso: `attackMoves(for:stoppers:)` 514 | public func attacks(for piece: Piece, stoppers: Bitboard = 0) -> Bitboard { 515 | #if swift(>=3) 516 | switch piece.kind { 517 | case .king: 518 | return kingAttacks() 519 | case .knight: 520 | return knightAttacks() 521 | case .pawn: 522 | return _pawnAttackTable(for: piece.color)[rawValue] 523 | default: 524 | return Bitboard(square: self)._attacks(for: piece, stoppers: stoppers) 525 | } 526 | #else 527 | switch piece.kind { 528 | case .King: 529 | return kingAttacks() 530 | case .Knight: 531 | return knightAttacks() 532 | case .Pawn: 533 | return _pawnAttackTable(for: piece.color)[rawValue] 534 | default: 535 | return Bitboard(square: self)._attacks(for: piece, stoppers: stoppers) 536 | } 537 | #endif 538 | } 539 | 540 | /// Returns an array of attack moves for a piece at `self`. 541 | /// 542 | /// - seealso: `attacks(for:stoppers:)` 543 | public func attackMoves(for piece: Piece, stoppers: Bitboard = 0) -> [Move] { 544 | return attacks(for: piece, stoppers: stoppers).moves(from: self) 545 | } 546 | 547 | #if swift(>=3) 548 | 549 | /// Returns moves from the squares in `squares` to `self`. 550 | public func moves(from squares: S) -> [Move] { 551 | return squares.moves(to: self) 552 | } 553 | 554 | /// Returns moves from `self` to the squares in `squares`. 555 | public func moves(to squares: S) -> [Move] { 556 | return squares.moves(from: self) 557 | } 558 | 559 | #else 560 | 561 | /// Returns moves from the squares in `squares` to `self`. 562 | public func moves(from squares: S) -> [Move] { 563 | return squares.moves(to: self) 564 | } 565 | 566 | /// Returns moves from `self` to the squares in `squares`. 567 | public func moves(to squares: S) -> [Move] { 568 | return squares.moves(from: self) 569 | } 570 | 571 | #endif 572 | 573 | } 574 | 575 | extension Square: StringLiteralConvertible { 576 | 577 | /// Create an instance initialized to `value`. 578 | public init(stringLiteral value: String) { 579 | guard let square = Square(value) else { 580 | fatalError("Invalid string for square: \"\(value)\"") 581 | } 582 | self = square 583 | } 584 | 585 | /// Create an instance initialized to `value`. 586 | public init(unicodeScalarLiteral value: String) { 587 | self.init(stringLiteral: value) 588 | } 589 | 590 | /// Create an instance initialized to `value`. 591 | public init(extendedGraphemeClusterLiteral value: String) { 592 | self.init(stringLiteral: value) 593 | } 594 | 595 | } 596 | -------------------------------------------------------------------------------- /Pods/Sage/Sources/Variant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Variant.swift 3 | // Sage 4 | // 5 | // Copyright 2016 Nikolai Vazquez 6 | // 7 | // Licensed under the Apache License, Version 2.0 (the "License"); 8 | // you may not use this file except in compliance with the License. 9 | // You may obtain a copy of the License at 10 | // 11 | // http://www.apache.org/licenses/LICENSE-2.0 12 | // 13 | // Unless required by applicable law or agreed to in writing, software 14 | // distributed under the License is distributed on an "AS IS" BASIS, 15 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | // See the License for the specific language governing permissions and 17 | // limitations under the License. 18 | // 19 | 20 | /// A chess variant that defines how a `Board` is populated or how a `Game` is played. 21 | public enum Variant { 22 | 23 | #if swift(>=3) 24 | 25 | /// Standard chess. 26 | case standard 27 | 28 | /// Upside down chess where the piece colors swap starting squares. 29 | case upsideDown 30 | 31 | /// Standard regardless of Swift version. 32 | internal static let _standard = Variant.standard 33 | 34 | /// UpsideDown regardless of Swift version. 35 | internal static let _upsideDown = Variant.upsideDown 36 | 37 | #else 38 | 39 | /// Standard chess. 40 | case Standard 41 | 42 | /// Upside down chess where the piece colors swap starting squares. 43 | case UpsideDown 44 | 45 | /// Standard regardless of Swift version. 46 | internal static let _standard = Variant.Standard 47 | 48 | /// UpsideDown regardless of Swift version. 49 | internal static let _upsideDown = Variant.UpsideDown 50 | 51 | #endif 52 | 53 | /// `self` is standard variant. 54 | public var isStandard: Bool { 55 | return self == ._standard 56 | } 57 | 58 | /// `self` is upside down variant. 59 | public var isUpsideDown: Bool { 60 | return self == ._upsideDown 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SwiftChessEngine/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SwiftChessEngine/Pods-SwiftChessEngine-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Sage 5 | 6 | 7 | Apache License 8 | Version 2.0, January 2004 9 | http://www.apache.org/licenses/ 10 | 11 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 12 | 13 | 1. Definitions. 14 | 15 | "License" shall mean the terms and conditions for use, reproduction, 16 | and distribution as defined by Sections 1 through 9 of this document. 17 | 18 | "Licensor" shall mean the copyright owner or entity authorized by 19 | the copyright owner that is granting the License. 20 | 21 | "Legal Entity" shall mean the union of the acting entity and all 22 | other entities that control, are controlled by, or are under common 23 | control with that entity. For the purposes of this definition, 24 | "control" means (i) the power, direct or indirect, to cause the 25 | direction or management of such entity, whether by contract or 26 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 27 | outstanding shares, or (iii) beneficial ownership of such entity. 28 | 29 | "You" (or "Your") shall mean an individual or Legal Entity 30 | exercising permissions granted by this License. 31 | 32 | "Source" form shall mean the preferred form for making modifications, 33 | including but not limited to software source code, documentation 34 | source, and configuration files. 35 | 36 | "Object" form shall mean any form resulting from mechanical 37 | transformation or translation of a Source form, including but 38 | not limited to compiled object code, generated documentation, 39 | and conversions to other media types. 40 | 41 | "Work" shall mean the work of authorship, whether in Source or 42 | Object form, made available under the License, as indicated by a 43 | copyright notice that is included in or attached to the work 44 | (an example is provided in the Appendix below). 45 | 46 | "Derivative Works" shall mean any work, whether in Source or Object 47 | form, that is based on (or derived from) the Work and for which the 48 | editorial revisions, annotations, elaborations, or other modifications 49 | represent, as a whole, an original work of authorship. For the purposes 50 | of this License, Derivative Works shall not include works that remain 51 | separable from, or merely link (or bind by name) to the interfaces of, 52 | the Work and Derivative Works thereof. 53 | 54 | "Contribution" shall mean any work of authorship, including 55 | the original version of the Work and any modifications or additions 56 | to that Work or Derivative Works thereof, that is intentionally 57 | submitted to Licensor for inclusion in the Work by the copyright owner 58 | or by an individual or Legal Entity authorized to submit on behalf of 59 | the copyright owner. For the purposes of this definition, "submitted" 60 | means any form of electronic, verbal, or written communication sent 61 | to the Licensor or its representatives, including but not limited to 62 | communication on electronic mailing lists, source code control systems, 63 | and issue tracking systems that are managed by, or on behalf of, the 64 | Licensor for the purpose of discussing and improving the Work, but 65 | excluding communication that is conspicuously marked or otherwise 66 | designated in writing by the copyright owner as "Not a Contribution." 67 | 68 | "Contributor" shall mean Licensor and any individual or Legal Entity 69 | on behalf of whom a Contribution has been received by Licensor and 70 | subsequently incorporated within the Work. 71 | 72 | 2. Grant of Copyright License. Subject to the terms and conditions of 73 | this License, each Contributor hereby grants to You a perpetual, 74 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 75 | copyright license to reproduce, prepare Derivative Works of, 76 | publicly display, publicly perform, sublicense, and distribute the 77 | Work and such Derivative Works in Source or Object form. 78 | 79 | 3. Grant of Patent License. Subject to the terms and conditions of 80 | this License, each Contributor hereby grants to You a perpetual, 81 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 82 | (except as stated in this section) patent license to make, have made, 83 | use, offer to sell, sell, import, and otherwise transfer the Work, 84 | where such license applies only to those patent claims licensable 85 | by such Contributor that are necessarily infringed by their 86 | Contribution(s) alone or by combination of their Contribution(s) 87 | with the Work to which such Contribution(s) was submitted. If You 88 | institute patent litigation against any entity (including a 89 | cross-claim or counterclaim in a lawsuit) alleging that the Work 90 | or a Contribution incorporated within the Work constitutes direct 91 | or contributory patent infringement, then any patent licenses 92 | granted to You under this License for that Work shall terminate 93 | as of the date such litigation is filed. 94 | 95 | 4. Redistribution. You may reproduce and distribute copies of the 96 | Work or Derivative Works thereof in any medium, with or without 97 | modifications, and in Source or Object form, provided that You 98 | meet the following conditions: 99 | 100 | (a) You must give any other recipients of the Work or 101 | Derivative Works a copy of this License; and 102 | 103 | (b) You must cause any modified files to carry prominent notices 104 | stating that You changed the files; and 105 | 106 | (c) You must retain, in the Source form of any Derivative Works 107 | that You distribute, all copyright, patent, trademark, and 108 | attribution notices from the Source form of the Work, 109 | excluding those notices that do not pertain to any part of 110 | the Derivative Works; and 111 | 112 | (d) If the Work includes a "NOTICE" text file as part of its 113 | distribution, then any Derivative Works that You distribute must 114 | include a readable copy of the attribution notices contained 115 | within such NOTICE file, excluding those notices that do not 116 | pertain to any part of the Derivative Works, in at least one 117 | of the following places: within a NOTICE text file distributed 118 | as part of the Derivative Works; within the Source form or 119 | documentation, if provided along with the Derivative Works; or, 120 | within a display generated by the Derivative Works, if and 121 | wherever such third-party notices normally appear. The contents 122 | of the NOTICE file are for informational purposes only and 123 | do not modify the License. You may add Your own attribution 124 | notices within Derivative Works that You distribute, alongside 125 | or as an addendum to the NOTICE text from the Work, provided 126 | that such additional attribution notices cannot be construed 127 | as modifying the License. 128 | 129 | You may add Your own copyright statement to Your modifications and 130 | may provide additional or different license terms and conditions 131 | for use, reproduction, or distribution of Your modifications, or 132 | for any such Derivative Works as a whole, provided Your use, 133 | reproduction, and distribution of the Work otherwise complies with 134 | the conditions stated in this License. 135 | 136 | 5. Submission of Contributions. Unless You explicitly state otherwise, 137 | any Contribution intentionally submitted for inclusion in the Work 138 | by You to the Licensor shall be under the terms and conditions of 139 | this License, without any additional terms or conditions. 140 | Notwithstanding the above, nothing herein shall supersede or modify 141 | the terms of any separate license agreement you may have executed 142 | with Licensor regarding such Contributions. 143 | 144 | 6. Trademarks. This License does not grant permission to use the trade 145 | names, trademarks, service marks, or product names of the Licensor, 146 | except as required for reasonable and customary use in describing the 147 | origin of the Work and reproducing the content of the NOTICE file. 148 | 149 | 7. Disclaimer of Warranty. Unless required by applicable law or 150 | agreed to in writing, Licensor provides the Work (and each 151 | Contributor provides its Contributions) on an "AS IS" BASIS, 152 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 153 | implied, including, without limitation, any warranties or conditions 154 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 155 | PARTICULAR PURPOSE. You are solely responsible for determining the 156 | appropriateness of using or redistributing the Work and assume any 157 | risks associated with Your exercise of permissions under this License. 158 | 159 | 8. Limitation of Liability. In no event and under no legal theory, 160 | whether in tort (including negligence), contract, or otherwise, 161 | unless required by applicable law (such as deliberate and grossly 162 | negligent acts) or agreed to in writing, shall any Contributor be 163 | liable to You for damages, including any direct, indirect, special, 164 | incidental, or consequential damages of any character arising as a 165 | result of this License or out of the use or inability to use the 166 | Work (including but not limited to damages for loss of goodwill, 167 | work stoppage, computer failure or malfunction, or any and all 168 | other commercial damages or losses), even if such Contributor 169 | has been advised of the possibility of such damages. 170 | 171 | 9. Accepting Warranty or Additional Liability. While redistributing 172 | the Work or Derivative Works thereof, You may choose to offer, 173 | and charge a fee for, acceptance of support, warranty, indemnity, 174 | or other liability obligations and/or rights consistent with this 175 | License. However, in accepting such obligations, You may act only 176 | on Your own behalf and on Your sole responsibility, not on behalf 177 | of any other Contributor, and only if You agree to indemnify, 178 | defend, and hold each Contributor harmless for any liability 179 | incurred by, or claims asserted against, such Contributor by reason 180 | of your accepting any such warranty or additional liability. 181 | 182 | END OF TERMS AND CONDITIONS 183 | 184 | APPENDIX: How to apply the Apache License to your work. 185 | 186 | To apply the Apache License to your work, attach the following 187 | boilerplate notice, with the fields enclosed by brackets "[]" 188 | replaced with your own identifying information. (Don't include 189 | the brackets!) The text should be enclosed in the appropriate 190 | comment syntax for the file format. We also recommend that a 191 | file or class name and description of purpose be included on the 192 | same "printed page" as the copyright notice for easier 193 | identification within third-party archives. 194 | 195 | Copyright [yyyy] [name of copyright owner] 196 | 197 | Licensed under the Apache License, Version 2.0 (the "License"); 198 | you may not use this file except in compliance with the License. 199 | You may obtain a copy of the License at 200 | 201 | http://www.apache.org/licenses/LICENSE-2.0 202 | 203 | Unless required by applicable law or agreed to in writing, software 204 | distributed under the License is distributed on an "AS IS" BASIS, 205 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 206 | See the License for the specific language governing permissions and 207 | limitations under the License. 208 | 209 | Generated by CocoaPods - https://cocoapods.org 210 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SwiftChessEngine/Pods-SwiftChessEngine-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | 18 | Apache License 19 | Version 2.0, January 2004 20 | http://www.apache.org/licenses/ 21 | 22 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 23 | 24 | 1. Definitions. 25 | 26 | "License" shall mean the terms and conditions for use, reproduction, 27 | and distribution as defined by Sections 1 through 9 of this document. 28 | 29 | "Licensor" shall mean the copyright owner or entity authorized by 30 | the copyright owner that is granting the License. 31 | 32 | "Legal Entity" shall mean the union of the acting entity and all 33 | other entities that control, are controlled by, or are under common 34 | control with that entity. For the purposes of this definition, 35 | "control" means (i) the power, direct or indirect, to cause the 36 | direction or management of such entity, whether by contract or 37 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 38 | outstanding shares, or (iii) beneficial ownership of such entity. 39 | 40 | "You" (or "Your") shall mean an individual or Legal Entity 41 | exercising permissions granted by this License. 42 | 43 | "Source" form shall mean the preferred form for making modifications, 44 | including but not limited to software source code, documentation 45 | source, and configuration files. 46 | 47 | "Object" form shall mean any form resulting from mechanical 48 | transformation or translation of a Source form, including but 49 | not limited to compiled object code, generated documentation, 50 | and conversions to other media types. 51 | 52 | "Work" shall mean the work of authorship, whether in Source or 53 | Object form, made available under the License, as indicated by a 54 | copyright notice that is included in or attached to the work 55 | (an example is provided in the Appendix below). 56 | 57 | "Derivative Works" shall mean any work, whether in Source or Object 58 | form, that is based on (or derived from) the Work and for which the 59 | editorial revisions, annotations, elaborations, or other modifications 60 | represent, as a whole, an original work of authorship. For the purposes 61 | of this License, Derivative Works shall not include works that remain 62 | separable from, or merely link (or bind by name) to the interfaces of, 63 | the Work and Derivative Works thereof. 64 | 65 | "Contribution" shall mean any work of authorship, including 66 | the original version of the Work and any modifications or additions 67 | to that Work or Derivative Works thereof, that is intentionally 68 | submitted to Licensor for inclusion in the Work by the copyright owner 69 | or by an individual or Legal Entity authorized to submit on behalf of 70 | the copyright owner. For the purposes of this definition, "submitted" 71 | means any form of electronic, verbal, or written communication sent 72 | to the Licensor or its representatives, including but not limited to 73 | communication on electronic mailing lists, source code control systems, 74 | and issue tracking systems that are managed by, or on behalf of, the 75 | Licensor for the purpose of discussing and improving the Work, but 76 | excluding communication that is conspicuously marked or otherwise 77 | designated in writing by the copyright owner as "Not a Contribution." 78 | 79 | "Contributor" shall mean Licensor and any individual or Legal Entity 80 | on behalf of whom a Contribution has been received by Licensor and 81 | subsequently incorporated within the Work. 82 | 83 | 2. Grant of Copyright License. Subject to the terms and conditions of 84 | this License, each Contributor hereby grants to You a perpetual, 85 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 86 | copyright license to reproduce, prepare Derivative Works of, 87 | publicly display, publicly perform, sublicense, and distribute the 88 | Work and such Derivative Works in Source or Object form. 89 | 90 | 3. Grant of Patent License. Subject to the terms and conditions of 91 | this License, each Contributor hereby grants to You a perpetual, 92 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 93 | (except as stated in this section) patent license to make, have made, 94 | use, offer to sell, sell, import, and otherwise transfer the Work, 95 | where such license applies only to those patent claims licensable 96 | by such Contributor that are necessarily infringed by their 97 | Contribution(s) alone or by combination of their Contribution(s) 98 | with the Work to which such Contribution(s) was submitted. If You 99 | institute patent litigation against any entity (including a 100 | cross-claim or counterclaim in a lawsuit) alleging that the Work 101 | or a Contribution incorporated within the Work constitutes direct 102 | or contributory patent infringement, then any patent licenses 103 | granted to You under this License for that Work shall terminate 104 | as of the date such litigation is filed. 105 | 106 | 4. Redistribution. You may reproduce and distribute copies of the 107 | Work or Derivative Works thereof in any medium, with or without 108 | modifications, and in Source or Object form, provided that You 109 | meet the following conditions: 110 | 111 | (a) You must give any other recipients of the Work or 112 | Derivative Works a copy of this License; and 113 | 114 | (b) You must cause any modified files to carry prominent notices 115 | stating that You changed the files; and 116 | 117 | (c) You must retain, in the Source form of any Derivative Works 118 | that You distribute, all copyright, patent, trademark, and 119 | attribution notices from the Source form of the Work, 120 | excluding those notices that do not pertain to any part of 121 | the Derivative Works; and 122 | 123 | (d) If the Work includes a "NOTICE" text file as part of its 124 | distribution, then any Derivative Works that You distribute must 125 | include a readable copy of the attribution notices contained 126 | within such NOTICE file, excluding those notices that do not 127 | pertain to any part of the Derivative Works, in at least one 128 | of the following places: within a NOTICE text file distributed 129 | as part of the Derivative Works; within the Source form or 130 | documentation, if provided along with the Derivative Works; or, 131 | within a display generated by the Derivative Works, if and 132 | wherever such third-party notices normally appear. The contents 133 | of the NOTICE file are for informational purposes only and 134 | do not modify the License. You may add Your own attribution 135 | notices within Derivative Works that You distribute, alongside 136 | or as an addendum to the NOTICE text from the Work, provided 137 | that such additional attribution notices cannot be construed 138 | as modifying the License. 139 | 140 | You may add Your own copyright statement to Your modifications and 141 | may provide additional or different license terms and conditions 142 | for use, reproduction, or distribution of Your modifications, or 143 | for any such Derivative Works as a whole, provided Your use, 144 | reproduction, and distribution of the Work otherwise complies with 145 | the conditions stated in this License. 146 | 147 | 5. Submission of Contributions. Unless You explicitly state otherwise, 148 | any Contribution intentionally submitted for inclusion in the Work 149 | by You to the Licensor shall be under the terms and conditions of 150 | this License, without any additional terms or conditions. 151 | Notwithstanding the above, nothing herein shall supersede or modify 152 | the terms of any separate license agreement you may have executed 153 | with Licensor regarding such Contributions. 154 | 155 | 6. Trademarks. This License does not grant permission to use the trade 156 | names, trademarks, service marks, or product names of the Licensor, 157 | except as required for reasonable and customary use in describing the 158 | origin of the Work and reproducing the content of the NOTICE file. 159 | 160 | 7. Disclaimer of Warranty. Unless required by applicable law or 161 | agreed to in writing, Licensor provides the Work (and each 162 | Contributor provides its Contributions) on an "AS IS" BASIS, 163 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 164 | implied, including, without limitation, any warranties or conditions 165 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 166 | PARTICULAR PURPOSE. You are solely responsible for determining the 167 | appropriateness of using or redistributing the Work and assume any 168 | risks associated with Your exercise of permissions under this License. 169 | 170 | 8. Limitation of Liability. In no event and under no legal theory, 171 | whether in tort (including negligence), contract, or otherwise, 172 | unless required by applicable law (such as deliberate and grossly 173 | negligent acts) or agreed to in writing, shall any Contributor be 174 | liable to You for damages, including any direct, indirect, special, 175 | incidental, or consequential damages of any character arising as a 176 | result of this License or out of the use or inability to use the 177 | Work (including but not limited to damages for loss of goodwill, 178 | work stoppage, computer failure or malfunction, or any and all 179 | other commercial damages or losses), even if such Contributor 180 | has been advised of the possibility of such damages. 181 | 182 | 9. Accepting Warranty or Additional Liability. While redistributing 183 | the Work or Derivative Works thereof, You may choose to offer, 184 | and charge a fee for, acceptance of support, warranty, indemnity, 185 | or other liability obligations and/or rights consistent with this 186 | License. However, in accepting such obligations, You may act only 187 | on Your own behalf and on Your sole responsibility, not on behalf 188 | of any other Contributor, and only if You agree to indemnify, 189 | defend, and hold each Contributor harmless for any liability 190 | incurred by, or claims asserted against, such Contributor by reason 191 | of your accepting any such warranty or additional liability. 192 | 193 | END OF TERMS AND CONDITIONS 194 | 195 | APPENDIX: How to apply the Apache License to your work. 196 | 197 | To apply the Apache License to your work, attach the following 198 | boilerplate notice, with the fields enclosed by brackets "[]" 199 | replaced with your own identifying information. (Don't include 200 | the brackets!) The text should be enclosed in the appropriate 201 | comment syntax for the file format. We also recommend that a 202 | file or class name and description of purpose be included on the 203 | same "printed page" as the copyright notice for easier 204 | identification within third-party archives. 205 | 206 | Copyright [yyyy] [name of copyright owner] 207 | 208 | Licensed under the Apache License, Version 2.0 (the "License"); 209 | you may not use this file except in compliance with the License. 210 | You may obtain a copy of the License at 211 | 212 | http://www.apache.org/licenses/LICENSE-2.0 213 | 214 | Unless required by applicable law or agreed to in writing, software 215 | distributed under the License is distributed on an "AS IS" BASIS, 216 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 217 | See the License for the specific language governing permissions and 218 | limitations under the License. 219 | 220 | License 221 | Apache License, Version 2.0 222 | Title 223 | Sage 224 | Type 225 | PSGroupSpecifier 226 | 227 | 228 | FooterText 229 | Generated by CocoaPods - https://cocoapods.org 230 | Title 231 | 232 | Type 233 | PSGroupSpecifier 234 | 235 | 236 | StringsTable 237 | Acknowledgements 238 | Title 239 | Acknowledgements 240 | 241 | 242 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SwiftChessEngine/Pods-SwiftChessEngine-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_SwiftChessEngine : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_SwiftChessEngine 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SwiftChessEngine/Pods-SwiftChessEngine-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | 86 | if [[ "$CONFIGURATION" == "Debug" ]]; then 87 | install_framework "$BUILT_PRODUCTS_DIR/Sage/Sage.framework" 88 | fi 89 | if [[ "$CONFIGURATION" == "Release" ]]; then 90 | install_framework "$BUILT_PRODUCTS_DIR/Sage/Sage.framework" 91 | fi 92 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SwiftChessEngine/Pods-SwiftChessEngine-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | realpath() { 27 | DIRECTORY="$(cd "${1%/*}" && pwd)" 28 | FILENAME="${1##*/}" 29 | echo "$DIRECTORY/$FILENAME" 30 | } 31 | 32 | install_resource() 33 | { 34 | if [[ "$1" = /* ]] ; then 35 | RESOURCE_PATH="$1" 36 | else 37 | RESOURCE_PATH="${PODS_ROOT}/$1" 38 | fi 39 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 40 | cat << EOM 41 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 42 | EOM 43 | exit 1 44 | fi 45 | case $RESOURCE_PATH in 46 | *.storyboard) 47 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 48 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 49 | ;; 50 | *.xib) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 53 | ;; 54 | *.framework) 55 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 56 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 57 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 58 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 59 | ;; 60 | *.xcdatamodel) 61 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 62 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 63 | ;; 64 | *.xcdatamodeld) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 67 | ;; 68 | *.xcmappingmodel) 69 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 70 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 71 | ;; 72 | *.xcassets) 73 | ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") 74 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 75 | ;; 76 | *) 77 | echo "$RESOURCE_PATH" 78 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 79 | ;; 80 | esac 81 | } 82 | 83 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 85 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 86 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 87 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | fi 89 | rm -f "$RESOURCES_TO_COPY" 90 | 91 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 92 | then 93 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 94 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 95 | while read line; do 96 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 97 | XCASSET_FILES+=("$line") 98 | fi 99 | done <<<"$OTHER_XCASSETS" 100 | 101 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 102 | fi 103 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SwiftChessEngine/Pods-SwiftChessEngine-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double Pods_SwiftChessEngineVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char Pods_SwiftChessEngineVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SwiftChessEngine/Pods-SwiftChessEngine.debug.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Sage" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Sage/Sage.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "Sage" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SwiftChessEngine/Pods-SwiftChessEngine.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_SwiftChessEngine { 2 | umbrella header "Pods-SwiftChessEngine-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Pods-SwiftChessEngine/Pods-SwiftChessEngine.release.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/Sage" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/Sage/Sage.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "Sage" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Sage/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 2.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Sage/Sage-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Sage : NSObject 3 | @end 4 | @implementation PodsDummy_Sage 5 | @end 6 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Sage/Sage-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Sage/Sage-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double SageVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char SageVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Sage/Sage.modulemap: -------------------------------------------------------------------------------- 1 | framework module Sage { 2 | umbrella header "Sage-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Pods/Target Support Files/Sage/Sage.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/Sage 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftChessEngine 2 | Prototype chess engine written in Swift with nvzqz/Sage 3 | -------------------------------------------------------------------------------- /SwiftChessEngine.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4939D90CC0D47C7C68A5457F /* Pods_SwiftChessEngine.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EBE93CE73D6E5713B0A9868E /* Pods_SwiftChessEngine.framework */; }; 11 | BF2DD9621D29714D0028FEAF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF2DD9611D29714D0028FEAF /* AppDelegate.swift */; }; 12 | BF2DD9641D29714D0028FEAF /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF2DD9631D29714D0028FEAF /* ViewController.swift */; }; 13 | BF2DD9671D29714D0028FEAF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BF2DD9651D29714D0028FEAF /* Main.storyboard */; }; 14 | BF2DD9691D29714D0028FEAF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BF2DD9681D29714D0028FEAF /* Assets.xcassets */; }; 15 | BF2DD96C1D29714D0028FEAF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BF2DD96A1D29714D0028FEAF /* LaunchScreen.storyboard */; }; 16 | BF40C1CA1D2971CD002BD4C3 /* ChessEngine.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF40C1C91D2971CD002BD4C3 /* ChessEngine.swift */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | AE9930E21E305A958ED6B76E /* Pods-SwiftChessEngine.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftChessEngine.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftChessEngine/Pods-SwiftChessEngine.debug.xcconfig"; sourceTree = ""; }; 21 | BF2DD95E1D29714D0028FEAF /* SwiftChessEngine.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftChessEngine.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | BF2DD9611D29714D0028FEAF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 23 | BF2DD9631D29714D0028FEAF /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 24 | BF2DD9661D29714D0028FEAF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 25 | BF2DD9681D29714D0028FEAF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 26 | BF2DD96B1D29714D0028FEAF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 27 | BF2DD96D1D29714D0028FEAF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 28 | BF40C1C91D2971CD002BD4C3 /* ChessEngine.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ChessEngine.swift; path = ChessEngine/ChessEngine.swift; sourceTree = ""; }; 29 | E85C3F69F4B1350E3584567F /* Pods-SwiftChessEngine.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftChessEngine.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftChessEngine/Pods-SwiftChessEngine.release.xcconfig"; sourceTree = ""; }; 30 | EBE93CE73D6E5713B0A9868E /* Pods_SwiftChessEngine.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwiftChessEngine.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | BF2DD95B1D29714D0028FEAF /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | 4939D90CC0D47C7C68A5457F /* Pods_SwiftChessEngine.framework in Frameworks */, 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | BF2DD9551D29714D0028FEAF = { 46 | isa = PBXGroup; 47 | children = ( 48 | BF2DD9601D29714D0028FEAF /* SwiftChessEngine */, 49 | BF2DD95F1D29714D0028FEAF /* Products */, 50 | C5064F1E7977FE760E661FC6 /* Pods */, 51 | D7E4110F91DC7D3D417FECED /* Frameworks */, 52 | ); 53 | sourceTree = ""; 54 | }; 55 | BF2DD95F1D29714D0028FEAF /* Products */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | BF2DD95E1D29714D0028FEAF /* SwiftChessEngine.app */, 59 | ); 60 | name = Products; 61 | sourceTree = ""; 62 | }; 63 | BF2DD9601D29714D0028FEAF /* SwiftChessEngine */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | BF40C1C81D2971B8002BD4C3 /* Chess Engine */, 67 | BF2DD9611D29714D0028FEAF /* AppDelegate.swift */, 68 | BF2DD9631D29714D0028FEAF /* ViewController.swift */, 69 | BF2DD9651D29714D0028FEAF /* Main.storyboard */, 70 | BF2DD9681D29714D0028FEAF /* Assets.xcassets */, 71 | BF2DD96A1D29714D0028FEAF /* LaunchScreen.storyboard */, 72 | BF2DD96D1D29714D0028FEAF /* Info.plist */, 73 | ); 74 | path = SwiftChessEngine; 75 | sourceTree = ""; 76 | }; 77 | BF40C1C81D2971B8002BD4C3 /* Chess Engine */ = { 78 | isa = PBXGroup; 79 | children = ( 80 | BF40C1C91D2971CD002BD4C3 /* ChessEngine.swift */, 81 | ); 82 | name = "Chess Engine"; 83 | sourceTree = ""; 84 | }; 85 | C5064F1E7977FE760E661FC6 /* Pods */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | AE9930E21E305A958ED6B76E /* Pods-SwiftChessEngine.debug.xcconfig */, 89 | E85C3F69F4B1350E3584567F /* Pods-SwiftChessEngine.release.xcconfig */, 90 | ); 91 | name = Pods; 92 | sourceTree = ""; 93 | }; 94 | D7E4110F91DC7D3D417FECED /* Frameworks */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | EBE93CE73D6E5713B0A9868E /* Pods_SwiftChessEngine.framework */, 98 | ); 99 | name = Frameworks; 100 | sourceTree = ""; 101 | }; 102 | /* End PBXGroup section */ 103 | 104 | /* Begin PBXNativeTarget section */ 105 | BF2DD95D1D29714D0028FEAF /* SwiftChessEngine */ = { 106 | isa = PBXNativeTarget; 107 | buildConfigurationList = BF2DD9701D29714D0028FEAF /* Build configuration list for PBXNativeTarget "SwiftChessEngine" */; 108 | buildPhases = ( 109 | 67A5302AD14E26823142450C /* [CP] Check Pods Manifest.lock */, 110 | BF2DD95A1D29714D0028FEAF /* Sources */, 111 | BF2DD95B1D29714D0028FEAF /* Frameworks */, 112 | BF2DD95C1D29714D0028FEAF /* Resources */, 113 | F804C1842389F4EFE9ECA707 /* [CP] Embed Pods Frameworks */, 114 | 74721232E3723DFCCCDE0D9D /* [CP] Copy Pods Resources */, 115 | ); 116 | buildRules = ( 117 | ); 118 | dependencies = ( 119 | ); 120 | name = SwiftChessEngine; 121 | productName = SwiftChessEngine; 122 | productReference = BF2DD95E1D29714D0028FEAF /* SwiftChessEngine.app */; 123 | productType = "com.apple.product-type.application"; 124 | }; 125 | /* End PBXNativeTarget section */ 126 | 127 | /* Begin PBXProject section */ 128 | BF2DD9561D29714D0028FEAF /* Project object */ = { 129 | isa = PBXProject; 130 | attributes = { 131 | LastSwiftUpdateCheck = 0800; 132 | LastUpgradeCheck = 0800; 133 | ORGANIZATIONNAME = JaviSoto; 134 | TargetAttributes = { 135 | BF2DD95D1D29714D0028FEAF = { 136 | CreatedOnToolsVersion = 8.0; 137 | DevelopmentTeam = LQ6DVLLL6A; 138 | DevelopmentTeamName = "Javier Soto (Personal Team)"; 139 | LastSwiftMigration = 0800; 140 | ProvisioningStyle = Automatic; 141 | }; 142 | }; 143 | }; 144 | buildConfigurationList = BF2DD9591D29714D0028FEAF /* Build configuration list for PBXProject "SwiftChessEngine" */; 145 | compatibilityVersion = "Xcode 3.2"; 146 | developmentRegion = English; 147 | hasScannedForEncodings = 0; 148 | knownRegions = ( 149 | en, 150 | Base, 151 | ); 152 | mainGroup = BF2DD9551D29714D0028FEAF; 153 | productRefGroup = BF2DD95F1D29714D0028FEAF /* Products */; 154 | projectDirPath = ""; 155 | projectRoot = ""; 156 | targets = ( 157 | BF2DD95D1D29714D0028FEAF /* SwiftChessEngine */, 158 | ); 159 | }; 160 | /* End PBXProject section */ 161 | 162 | /* Begin PBXResourcesBuildPhase section */ 163 | BF2DD95C1D29714D0028FEAF /* Resources */ = { 164 | isa = PBXResourcesBuildPhase; 165 | buildActionMask = 2147483647; 166 | files = ( 167 | BF2DD96C1D29714D0028FEAF /* LaunchScreen.storyboard in Resources */, 168 | BF2DD9691D29714D0028FEAF /* Assets.xcassets in Resources */, 169 | BF2DD9671D29714D0028FEAF /* Main.storyboard in Resources */, 170 | ); 171 | runOnlyForDeploymentPostprocessing = 0; 172 | }; 173 | /* End PBXResourcesBuildPhase section */ 174 | 175 | /* Begin PBXShellScriptBuildPhase section */ 176 | 67A5302AD14E26823142450C /* [CP] Check Pods Manifest.lock */ = { 177 | isa = PBXShellScriptBuildPhase; 178 | buildActionMask = 2147483647; 179 | files = ( 180 | ); 181 | inputPaths = ( 182 | ); 183 | name = "[CP] Check Pods Manifest.lock"; 184 | outputPaths = ( 185 | ); 186 | runOnlyForDeploymentPostprocessing = 0; 187 | shellPath = /bin/sh; 188 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 189 | showEnvVarsInLog = 0; 190 | }; 191 | 74721232E3723DFCCCDE0D9D /* [CP] Copy Pods Resources */ = { 192 | isa = PBXShellScriptBuildPhase; 193 | buildActionMask = 2147483647; 194 | files = ( 195 | ); 196 | inputPaths = ( 197 | ); 198 | name = "[CP] Copy Pods Resources"; 199 | outputPaths = ( 200 | ); 201 | runOnlyForDeploymentPostprocessing = 0; 202 | shellPath = /bin/sh; 203 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftChessEngine/Pods-SwiftChessEngine-resources.sh\"\n"; 204 | showEnvVarsInLog = 0; 205 | }; 206 | F804C1842389F4EFE9ECA707 /* [CP] Embed Pods Frameworks */ = { 207 | isa = PBXShellScriptBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | ); 211 | inputPaths = ( 212 | ); 213 | name = "[CP] Embed Pods Frameworks"; 214 | outputPaths = ( 215 | ); 216 | runOnlyForDeploymentPostprocessing = 0; 217 | shellPath = /bin/sh; 218 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SwiftChessEngine/Pods-SwiftChessEngine-frameworks.sh\"\n"; 219 | showEnvVarsInLog = 0; 220 | }; 221 | /* End PBXShellScriptBuildPhase section */ 222 | 223 | /* Begin PBXSourcesBuildPhase section */ 224 | BF2DD95A1D29714D0028FEAF /* Sources */ = { 225 | isa = PBXSourcesBuildPhase; 226 | buildActionMask = 2147483647; 227 | files = ( 228 | BF40C1CA1D2971CD002BD4C3 /* ChessEngine.swift in Sources */, 229 | BF2DD9641D29714D0028FEAF /* ViewController.swift in Sources */, 230 | BF2DD9621D29714D0028FEAF /* AppDelegate.swift in Sources */, 231 | ); 232 | runOnlyForDeploymentPostprocessing = 0; 233 | }; 234 | /* End PBXSourcesBuildPhase section */ 235 | 236 | /* Begin PBXVariantGroup section */ 237 | BF2DD9651D29714D0028FEAF /* Main.storyboard */ = { 238 | isa = PBXVariantGroup; 239 | children = ( 240 | BF2DD9661D29714D0028FEAF /* Base */, 241 | ); 242 | name = Main.storyboard; 243 | sourceTree = ""; 244 | }; 245 | BF2DD96A1D29714D0028FEAF /* LaunchScreen.storyboard */ = { 246 | isa = PBXVariantGroup; 247 | children = ( 248 | BF2DD96B1D29714D0028FEAF /* Base */, 249 | ); 250 | name = LaunchScreen.storyboard; 251 | sourceTree = ""; 252 | }; 253 | /* End PBXVariantGroup section */ 254 | 255 | /* Begin XCBuildConfiguration section */ 256 | BF2DD96E1D29714D0028FEAF /* Debug */ = { 257 | isa = XCBuildConfiguration; 258 | buildSettings = { 259 | ALWAYS_SEARCH_USER_PATHS = NO; 260 | CLANG_ANALYZER_NONNULL = YES; 261 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 262 | CLANG_CXX_LIBRARY = "libc++"; 263 | CLANG_ENABLE_MODULES = YES; 264 | CLANG_ENABLE_OBJC_ARC = YES; 265 | CLANG_WARN_BOOL_CONVERSION = YES; 266 | CLANG_WARN_CONSTANT_CONVERSION = YES; 267 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 268 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 269 | CLANG_WARN_EMPTY_BODY = YES; 270 | CLANG_WARN_ENUM_CONVERSION = YES; 271 | CLANG_WARN_INT_CONVERSION = YES; 272 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 273 | CLANG_WARN_UNREACHABLE_CODE = YES; 274 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 275 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 276 | COPY_PHASE_STRIP = NO; 277 | DEBUG_INFORMATION_FORMAT = dwarf; 278 | ENABLE_STRICT_OBJC_MSGSEND = YES; 279 | ENABLE_TESTABILITY = YES; 280 | GCC_C_LANGUAGE_STANDARD = gnu99; 281 | GCC_DYNAMIC_NO_PIC = NO; 282 | GCC_NO_COMMON_BLOCKS = YES; 283 | GCC_OPTIMIZATION_LEVEL = 0; 284 | GCC_PREPROCESSOR_DEFINITIONS = ( 285 | "DEBUG=1", 286 | "$(inherited)", 287 | ); 288 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 289 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 290 | GCC_WARN_UNDECLARED_SELECTOR = YES; 291 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 292 | GCC_WARN_UNUSED_FUNCTION = YES; 293 | GCC_WARN_UNUSED_VARIABLE = YES; 294 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 295 | MTL_ENABLE_DEBUG_INFO = YES; 296 | ONLY_ACTIVE_ARCH = YES; 297 | SDKROOT = iphoneos; 298 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 299 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 300 | TARGETED_DEVICE_FAMILY = "1,2"; 301 | }; 302 | name = Debug; 303 | }; 304 | BF2DD96F1D29714D0028FEAF /* Release */ = { 305 | isa = XCBuildConfiguration; 306 | buildSettings = { 307 | ALWAYS_SEARCH_USER_PATHS = NO; 308 | CLANG_ANALYZER_NONNULL = YES; 309 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 310 | CLANG_CXX_LIBRARY = "libc++"; 311 | CLANG_ENABLE_MODULES = YES; 312 | CLANG_ENABLE_OBJC_ARC = YES; 313 | CLANG_WARN_BOOL_CONVERSION = YES; 314 | CLANG_WARN_CONSTANT_CONVERSION = YES; 315 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 316 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 317 | CLANG_WARN_EMPTY_BODY = YES; 318 | CLANG_WARN_ENUM_CONVERSION = YES; 319 | CLANG_WARN_INT_CONVERSION = YES; 320 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 321 | CLANG_WARN_UNREACHABLE_CODE = YES; 322 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 323 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 324 | COPY_PHASE_STRIP = NO; 325 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 326 | ENABLE_NS_ASSERTIONS = NO; 327 | ENABLE_STRICT_OBJC_MSGSEND = YES; 328 | GCC_C_LANGUAGE_STANDARD = gnu99; 329 | GCC_NO_COMMON_BLOCKS = YES; 330 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 331 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 332 | GCC_WARN_UNDECLARED_SELECTOR = YES; 333 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 334 | GCC_WARN_UNUSED_FUNCTION = YES; 335 | GCC_WARN_UNUSED_VARIABLE = YES; 336 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 337 | MTL_ENABLE_DEBUG_INFO = NO; 338 | SDKROOT = iphoneos; 339 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 340 | TARGETED_DEVICE_FAMILY = "1,2"; 341 | VALIDATE_PRODUCT = YES; 342 | }; 343 | name = Release; 344 | }; 345 | BF2DD9711D29714D0028FEAF /* Debug */ = { 346 | isa = XCBuildConfiguration; 347 | baseConfigurationReference = AE9930E21E305A958ED6B76E /* Pods-SwiftChessEngine.debug.xcconfig */; 348 | buildSettings = { 349 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 350 | INFOPLIST_FILE = SwiftChessEngine/Info.plist; 351 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 352 | PRODUCT_BUNDLE_IDENTIFIER = es.javisoto.SwiftChessEngine; 353 | PRODUCT_NAME = "$(TARGET_NAME)"; 354 | SWIFT_VERSION = 3.0; 355 | }; 356 | name = Debug; 357 | }; 358 | BF2DD9721D29714D0028FEAF /* Release */ = { 359 | isa = XCBuildConfiguration; 360 | baseConfigurationReference = E85C3F69F4B1350E3584567F /* Pods-SwiftChessEngine.release.xcconfig */; 361 | buildSettings = { 362 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 363 | INFOPLIST_FILE = SwiftChessEngine/Info.plist; 364 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 365 | PRODUCT_BUNDLE_IDENTIFIER = es.javisoto.SwiftChessEngine; 366 | PRODUCT_NAME = "$(TARGET_NAME)"; 367 | SWIFT_VERSION = 3.0; 368 | }; 369 | name = Release; 370 | }; 371 | /* End XCBuildConfiguration section */ 372 | 373 | /* Begin XCConfigurationList section */ 374 | BF2DD9591D29714D0028FEAF /* Build configuration list for PBXProject "SwiftChessEngine" */ = { 375 | isa = XCConfigurationList; 376 | buildConfigurations = ( 377 | BF2DD96E1D29714D0028FEAF /* Debug */, 378 | BF2DD96F1D29714D0028FEAF /* Release */, 379 | ); 380 | defaultConfigurationIsVisible = 0; 381 | defaultConfigurationName = Release; 382 | }; 383 | BF2DD9701D29714D0028FEAF /* Build configuration list for PBXNativeTarget "SwiftChessEngine" */ = { 384 | isa = XCConfigurationList; 385 | buildConfigurations = ( 386 | BF2DD9711D29714D0028FEAF /* Debug */, 387 | BF2DD9721D29714D0028FEAF /* Release */, 388 | ); 389 | defaultConfigurationIsVisible = 0; 390 | defaultConfigurationName = Release; 391 | }; 392 | /* End XCConfigurationList section */ 393 | }; 394 | rootObject = BF2DD9561D29714D0028FEAF /* Project object */; 395 | } 396 | -------------------------------------------------------------------------------- /SwiftChessEngine.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftChessEngine.xcodeproj/project.xcworkspace/xcuserdata/javiers.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JaviSoto/SwiftChessEngine/91af170925a6af85522f89db3fabaf3da77cd0eb/SwiftChessEngine.xcodeproj/project.xcworkspace/xcuserdata/javiers.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SwiftChessEngine.xcodeproj/xcuserdata/javiers.xcuserdatad/xcschemes/SwiftChessEngine.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /SwiftChessEngine.xcodeproj/xcuserdata/javiers.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SwiftChessEngine.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | BF2DD95D1D29714D0028FEAF 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /SwiftChessEngine.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SwiftChessEngine.xcworkspace/xcuserdata/javiers.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JaviSoto/SwiftChessEngine/91af170925a6af85522f89db3fabaf3da77cd0eb/SwiftChessEngine.xcworkspace/xcuserdata/javiers.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /SwiftChessEngine.xcworkspace/xcuserdata/javiers.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /SwiftChessEngine/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SwiftChessEngine 4 | // 5 | // Created by Javier Soto on 7/3/16. 6 | // Copyright © 2016 JaviSoto. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | return true 19 | } 20 | 21 | func applicationWillResignActive(_ application: UIApplication) { 22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 23 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 24 | } 25 | 26 | func applicationDidEnterBackground(_ application: UIApplication) { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | func applicationWillEnterForeground(_ application: UIApplication) { 32 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 33 | } 34 | 35 | func applicationDidBecomeActive(_ application: UIApplication) { 36 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 37 | } 38 | 39 | func applicationWillTerminate(_ application: UIApplication) { 40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 41 | } 42 | 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /SwiftChessEngine/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "83.5x83.5", 66 | "scale" : "2x" 67 | } 68 | ], 69 | "info" : { 70 | "version" : 1, 71 | "author" : "xcode" 72 | } 73 | } -------------------------------------------------------------------------------- /SwiftChessEngine/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /SwiftChessEngine/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 45 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /SwiftChessEngine/ChessEngine/ChessEngine.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ChessEngine.swift 3 | // SwiftChessEngine 4 | // 5 | // Created by Javier Soto on 7/3/16. 6 | // Copyright © 2016 JaviSoto. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Sage 11 | 12 | extension Collection where Iterator.Element == Piece { 13 | var valuation: ChessEngine.Valuation { 14 | return self.lazy.filter { !$0.kind.isKing }.map { $0.kind.relativeValue }.reduce(0, combine: +) 15 | } 16 | } 17 | 18 | private extension Board { 19 | private static let initialBoard = Board() 20 | 21 | func pieces(for color: Color) -> [Piece] { 22 | return color.isWhite ? self.whitePieces : self.blackPieces 23 | } 24 | 25 | func allAttackers(attackingColor: Color) -> Int { 26 | let oppositePiecesSquares = self.squares(for: attackingColor.inverse()) 27 | 28 | var total = 0 29 | 30 | for oppositePieceSquare in oppositePiecesSquares { 31 | total += self.attackers(to: oppositePieceSquare, color: attackingColor).count 32 | } 33 | 34 | return total 35 | } 36 | 37 | private func piecesOutsideOriginalPosition(for color: Color) -> Int { 38 | let pieces = self.pieces(for: color) 39 | 40 | var count = 0 41 | 42 | for piece in pieces { 43 | if self.bitboard(for: piece) != Board.initialBoard.bitboard(for: piece) { 44 | count += 1 45 | } 46 | } 47 | 48 | return count 49 | } 50 | 51 | func doubledPawns(for color: Color) -> Int { 52 | let pawnFiles = self.pieces(for: color) 53 | .filter { $0.kind.isPawn } 54 | .flatMap { self.locations(for: $0).map { $0.file.rawValue } } 55 | 56 | let uniqueFiles = Set(pawnFiles) 57 | 58 | return pawnFiles.count - uniqueFiles.count 59 | } 60 | } 61 | 62 | private extension CastlingRights { 63 | private static let whiteCastlingRights: CastlingRights = [.whiteQueenside, .whiteKingside] 64 | private static let blackCastlingRights: CastlingRights = [.blackQueenside, .blackKingside] 65 | 66 | static func rightsFor(color: Color) -> CastlingRights { 67 | return color.isWhite ? self.whiteCastlingRights : self.blackCastlingRights 68 | } 69 | 70 | func canCastle(side: Color) -> Bool { 71 | return !self.intersection(CastlingRights.rightsFor(color: side)).isEmpty 72 | } 73 | } 74 | 75 | extension Game { 76 | func currentPositionValuation() -> ChessEngine.Valuation { 77 | let movingSide = self.position.playerTurn 78 | let oppositeSide = movingSide.inverse() 79 | let board = self.position.board 80 | 81 | var extras: ChessEngine.Valuation = 0 82 | 83 | if board.kingIsChecked(for: oppositeSide) { 84 | extras += 1 85 | } 86 | else if board.kingIsChecked(for: movingSide) { 87 | extras -= 0.3 88 | } 89 | 90 | let myPieces = board.pieceCount(for: movingSide) 91 | let theirPieces = board.pieceCount(for: oppositeSide) 92 | 93 | extras += Double(myPieces - theirPieces) * 0.1 94 | 95 | extras += 0.001 * Double(board.allAttackers(attackingColor: movingSide)) 96 | extras -= 0.0005 * Double(board.allAttackers(attackingColor: oppositeSide)) 97 | extras += 0.01 * Double(board.piecesOutsideOriginalPosition(for: movingSide)) 98 | extras -= 0.01 * Double(board.piecesOutsideOriginalPosition(for: oppositeSide)) 99 | 100 | extras -= 0.01 * Double(board.doubledPawns(for: movingSide)) 101 | extras += 0.01 * Double(board.doubledPawns(for: oppositeSide)) 102 | 103 | let weHaveCastled = self.playedMoves(bySide: movingSide).contains { $0.isCastle() } 104 | let theyHaveCastled = self.playedMoves(bySide: oppositeSide).contains { $0.isCastle() } 105 | 106 | let pointsForCastling: ChessEngine.Valuation = 2 107 | let cantCastlePenalty: ChessEngine.Valuation = -pointsForCastling 108 | 109 | if weHaveCastled { 110 | extras += pointsForCastling 111 | } 112 | 113 | if theyHaveCastled { 114 | extras -= pointsForCastling 115 | } 116 | 117 | let weCanCastle = self.castlingRights.canCastle(side: movingSide) 118 | let theyCanCastle = self.castlingRights.canCastle(side: movingSide.inverse()) 119 | 120 | if !weCanCastle { 121 | extras += cantCastlePenalty 122 | } 123 | 124 | if !theyCanCastle { 125 | extras -= cantCastlePenalty 126 | } 127 | 128 | return (board.whitePieces.valuation - board.blackPieces.valuation) + (extras * (movingSide.isWhite ? 1 : -1)) 129 | } 130 | } 131 | 132 | private extension Int { 133 | var isEven: Bool { 134 | return self % 2 == 0 135 | } 136 | 137 | var isOdd: Bool { 138 | return !self.isEven 139 | } 140 | } 141 | 142 | private extension Game { 143 | func playedMoves(bySide side: Color) -> [Move] { 144 | return self.playedMoves.enumerated() 145 | .filter { (side.isWhite && $0.offset.isEven) || (side.isBlack && !$0.offset.isEven) } 146 | .map { $0.element } 147 | } 148 | } 149 | 150 | private extension Game { 151 | func deepEvaluation(depth: Int) throws -> ChessEngine.PositionAnalysis { 152 | return try self.deepEvaluation(depth: depth, alpha: ChessEngine.Valuation.infinity.negated(), beta: ChessEngine.Valuation.infinity) 153 | } 154 | 155 | private func deepEvaluation(depth: Int, alpha: ChessEngine.Valuation, beta: ChessEngine.Valuation) throws -> ChessEngine.PositionAnalysis { 156 | let movingSide = self.position.playerTurn 157 | 158 | guard depth > 0 else { 159 | return ChessEngine.PositionAnalysis(move: nil, valuation: self.currentPositionValuation(), movesAnalized: 1) 160 | } 161 | 162 | let availableMoves = self.availableMoves() 163 | 164 | guard availableMoves.count > 1 else { 165 | let valuation: ChessEngine.Valuation 166 | 167 | switch self.outcome { 168 | case .some(.win(let color)): 169 | valuation = color.isWhite ? ChessEngine.Valuation.infinity : ChessEngine.Valuation.infinity.negated() 170 | 171 | default: 172 | valuation = self.currentPositionValuation() 173 | } 174 | 175 | return ChessEngine.PositionAnalysis(move: availableMoves.first, valuation: valuation, movesAnalized: 1) 176 | } 177 | 178 | var bestMove: Move? 179 | var bestValuation: ChessEngine.Valuation = movingSide.isWhite ? Double.infinity.negated() : Double.infinity 180 | var movesAnalized = 0 181 | 182 | var alpha = alpha 183 | var beta = beta 184 | 185 | for move in availableMoves { 186 | try self.execute(move: move) 187 | 188 | let analysis = try self.deepEvaluation(depth: depth - 1, alpha: alpha, beta: beta) 189 | self.undoMove() 190 | 191 | movesAnalized += analysis.movesAnalized 192 | 193 | if movingSide.isWhite { 194 | if analysis.valuation > alpha { 195 | alpha = analysis.valuation 196 | bestValuation = analysis.valuation 197 | bestMove = move 198 | } 199 | if alpha >= beta { 200 | break 201 | } 202 | } 203 | else { 204 | if analysis.valuation < beta { 205 | beta = analysis.valuation 206 | bestValuation = analysis.valuation 207 | bestMove = move 208 | } 209 | 210 | if beta <= alpha { 211 | break 212 | } 213 | } 214 | } 215 | 216 | return ChessEngine.PositionAnalysis(move: bestMove, valuation: bestValuation, movesAnalized: movesAnalized) 217 | } 218 | } 219 | 220 | final class ChessEngine { 221 | typealias Valuation = Double 222 | 223 | struct PositionAnalysis { 224 | let move: Move? 225 | let valuation: Valuation 226 | let movesAnalized: Int 227 | } 228 | 229 | let game = Game(whitePlayer: Player(kind: .computer), blackPlayer: Player(kind: .computer), variant: Variant.standard) 230 | 231 | init() { 232 | 233 | } 234 | 235 | func bestMove(maxDepth: Int) throws -> PositionAnalysis { 236 | return try self.game.deepEvaluation(depth: maxDepth) 237 | } 238 | 239 | func benchmark() -> (Int, TimeInterval) { 240 | var iterations = 0 241 | 242 | let start = Date() 243 | while iterations < 10000 { 244 | iterations += 1 245 | 246 | guard let move = game.availableMoves().random else { break } 247 | try! game.execute(move: move) 248 | } 249 | 250 | let end = Date() 251 | 252 | let interval = end.timeIntervalSince(start) 253 | 254 | return (iterations, interval) 255 | } 256 | } 257 | 258 | extension Array { 259 | var random: Element? { 260 | guard !self.isEmpty else { return nil } 261 | 262 | let randomIndex = Int(arc4random_uniform(UInt32(self.count))) 263 | 264 | return self[randomIndex] 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /SwiftChessEngine/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /SwiftChessEngine/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SwiftChessEngine 4 | // 5 | // Created by Javier Soto on 7/3/16. 6 | // Copyright © 2016 JaviSoto. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Sage 11 | 12 | extension PlaygroundQuickLook { 13 | var view: UIView? { 14 | switch self { 15 | case .view(let view): return view as? UIView 16 | default: return nil 17 | } 18 | } 19 | } 20 | 21 | extension UIView { 22 | var image: UIImage { 23 | let renderer = UIGraphicsImageRenderer(bounds: self.bounds) 24 | 25 | return renderer.image() { context in 26 | self.drawHierarchy(in: self.bounds, afterScreenUpdates: true) 27 | } 28 | } 29 | } 30 | 31 | final class EngineViewController: UIViewController { 32 | @IBOutlet private var boardViewContainer: UIView! 33 | @IBOutlet private var boardImageView: UIImageView! 34 | @IBOutlet private var evaluationLabel: UILabel! 35 | @IBOutlet private var toggleCalculationButton: UIButton! 36 | 37 | private var currentBoard: Board! { 38 | didSet { 39 | let view = currentBoard.customPlaygroundQuickLook.view! 40 | let image = view.image 41 | 42 | self.boardImageView.image = image 43 | } 44 | } 45 | 46 | private let engine = ChessEngine() 47 | 48 | private let engineQueue = DispatchQueue(label: "engine") 49 | private static let maxDepth = 3 50 | 51 | override func viewDidLoad() { 52 | super.viewDidLoad() 53 | 54 | self.evaluationLabel.text = nil 55 | self.currentBoard = self.engine.game.position.board 56 | } 57 | 58 | private func presentAlertWithGamePGN() { 59 | let alert = UIAlertController(title: "Moves", message: "\(self.engine.game.playedMoves)", preferredStyle: .alert) 60 | let dismissAction = UIAlertAction(title: "OK", style: .`default`) { _ in 61 | alert.dismiss(animated: true) 62 | } 63 | alert.addAction(dismissAction) 64 | 65 | self.present(alert, animated: true) 66 | } 67 | 68 | var calculating: Bool = false { 69 | didSet { 70 | self.toggleCalculationButton.setTitle(calculating ? "Stop calculating" : "Start calculating", for: []) 71 | 72 | if calculating != oldValue { 73 | if calculating { 74 | self.tick() 75 | } 76 | else { 77 | self.presentAlertWithGamePGN() 78 | } 79 | } 80 | } 81 | } 82 | 83 | var totalMovesAnalized = 0 84 | 85 | private func tick() { 86 | guard self.calculating else { return } 87 | 88 | self.engineQueue.async { 89 | do { 90 | let analysis = try self.engine.bestMove(maxDepth: EngineViewController.maxDepth) 91 | 92 | DispatchQueue.main.async { 93 | if let move = analysis.move { 94 | try! self.engine.game.execute(move: move) 95 | self.currentBoard = self.engine.game.position.board 96 | } 97 | 98 | self.totalMovesAnalized += analysis.movesAnalized 99 | self.evaluationLabel.text = "Move \(self.engine.game.fullmoves). Valuation: \(analysis.valuation) (after \(self.totalMovesAnalized) moves analized)" 100 | self.tick() 101 | } 102 | } 103 | catch { 104 | DispatchQueue.main.async { 105 | self.evaluationLabel.text = "Error: \(error)" 106 | } 107 | } 108 | } 109 | } 110 | 111 | @IBAction func calculateButtonTapped() { 112 | self.calculating = !self.calculating 113 | } 114 | } 115 | 116 | 117 | --------------------------------------------------------------------------------