chessx-master/0000755000076500000240000000000014666636275012513 5ustar jensstaffchessx-master/lcov_clear.sh0000755000076500000240000000133014666426276015156 0ustar jensstaff#!/bin/sh ############################################################################################################ # You should edit the following 3 paths when necessary ############################################################################################################ PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/MacGPG2/bin:/Library/Apple/usr/bin # Get the path to the current folder SCRIPT_DIR=$PWD echo "Clear '.gc*' in $SCRIPT_DIR" # SRC_DIR is the directory containing the .gcno files (%{buildDir} in Qt Creator) SRC_DIR="$SCRIPT_DIR/obj_dbg" # COV_DIR is the directory where the coverage results will be stored COV_DIR="$SCRIPT_DIR/coverage" rm -r $SRC_DIR/*.gcno rm -r $SRC_DIR/*.gcda chessx-master/CMakeLists.txt0000755000076500000240000000620214666426276015254 0ustar jensstaffcmake_minimum_required(VERSION 3.10) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.13) project(chessx LANGUAGES CXX) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) option(ENABLE_SOUNDS "Enable sounds (requires Qt5::Multimedia)" ON) option(ENABLE_TTS "Enable text-to-speech (requires Qt5::TextToSpeech)" ON) option(ENABLE_SCID_SUPPORT "Enable support for Scid database format (*.si4)" ON) add_subdirectory(dep) # common definitions to use with Qt add_library(qt_config INTERFACE) target_compile_definitions(qt_config INTERFACE QT_DEPRECATED_WARNINGS QT_NO_CAST_TO_ASCII QT_USE_QSTRINGBUILDER ) set(REQUIRED_QT_COMPONENTS Core Xml DBus Network OpenGL Svg PrintSupport Gui Widgets ) if (ENABLE_SOUNDS) list(APPEND REQUIRED_QT_COMPONENTS Multimedia MultimediaWidgets) endif() if (ENABLE_TTS) list(APPEND REQUIRED_QT_COMPONENTS TextToSpeech) endif() find_package(Qt5 REQUIRED LinguistTools "${REQUIRED_QT_COMPONENTS}" Test ) # TODO: enable warnings # CONFIG += warn_on # put translations.rc alongside generated .qm files configure_file(translations.qrc ${CMAKE_CURRENT_BINARY_DIR} COPYONLY) # list of .ts files to compile into .qm set(TRANSLATIONS_SRC_FILES # i18n/chessx_da.ts i18n/chessx_de.ts # i18n/chessx_fr.ts # i18n/chessx_it.ts # i18n/chessx_cz.ts # i18n/chessx_ru.ts ) set_source_files_properties(${TRANSLATIONS_SRC_FILES} PROPERTIES OUTPUT_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/i18n" ) qt5_add_translation(TRANSLATIONS_BIN_FILES ${TRANSLATIONS_SRC_FILES}) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) add_subdirectory(src) set(OTHER_FILES #[[ data/templates/pgn-default.template data/templates/notation-default.template data/templates/latex-default.template data/templates/html-default.template ChangeLog COPYING ChangeLog.txt data/help/about.css data/help/about-dark.css data/help/about0.html data/help/about1.html data/help/about1a.html data/help/about2.html data/help/about3.html data/help/about4.html data/help/about5.html data/help/about6.html setup7-64.iss setup7-32.iss setupXP.iss data/styles/orange.css unix/chessx.desktop ]] ) add_executable(chessx WIN32 src/gui/main.cpp resources.qrc ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc ${OTHER_FILES} ) target_link_libraries(chessx PRIVATE qt_config quazip bitboard board eco gui ) if (CMAKE_HOST_APPLE) # Make macOS bundle instead of bare executable set_target_properties(chessx PROPERTIES MACOSX_BUNDLE TRUE # TODO: use variables in Info.plist template MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/mac_osx/Info.plist" ) # embed required resources target_sources(chessx PRIVATE mac_osx/Info.plist mac_osx/qt_menu.nib data/images/chessx.icns ) set_property( TARGET chessx APPEND PROPERTY RESOURCE mac_osx/qt_menu.nib data/images/chessx.icns ) # TODO: embed engines & timeseal endif() set(CMAKE_AUTOMOC OFF) set(CMAKE_AUTORCC OFF) set(CMAKE_AUTOUIC OFF) option(ENABLE_TESTING "Enable testing" OFF) if (ENABLE_TESTING) enable_testing() add_subdirectory(tests/unittests) endif() chessx-master/ChangeLog.md0000755000076500000240000011113114666426276014663 0ustar jensstaff## July 2024: Version 1.6.2 - Bugfix:#333 Accented letters in annotations in UTF8 - Bugfix: #349 Incorrect Pinned Move in Analysis Window - Bugfix: Three fold repetition if ep was possible - Bugfix: Openings Summary in Player Info - Bugfix: Random number selection issues on some OS - Bugfix: #341 ChessX Draw Game by Insufficient Material - Bugfix: CR #336 Nalimov TB gives wrong evaluation - Bugfix: Jumping through sibling variations - Bugfix: CR #334 Pressing 'Pin engine' resets the analysis - Bugfix: Move indicator shows wrong line in case of Multi-PV, prefer TB - Bugfix: CR #320 (PGN Setup->SetUp tag) - New feature: Lichess Broadcasts - New feature: Repainting same arrow or square removes special annotation - New feature: Shift+Click opens first link in comment - New feature: Export as localized text - New feature: Workaround Chessable's tokenizer by adding space bf comment - New feature: Load range of games from online bases - New feature: Allows piece specific sounds - New feature: Add a volume slider for sounds - New feature: CR #209 Hide lines in Analysiswidget - New feature: Give coordinates a color setting of their own - New feature: Configurable Text to Speech - Changed: AnalysisWidget toolbutton ## January 2023: Version 1.5.8 - New feature: Allow preserving existing ECO codes - New Feature: Add optional source tag when merging databases - New Feature: Lichess Opening Databases - New feature: Copy text fragments from game browser - New feature: Boardview as drop target for databases and games - New feature: Edit tags from the game list view - Changed: Allow editing ECO codes in the game list view - Changed: Cycling through variations - Changed: Performance update PGN Parser - Changed: #290 Windows hides dialogs if off-screen - Changed: CR #185 Recognize and annotate draw conditions - Changed: CR #191 Engine analysis not inserted in notation - Changed: Transfer board rotation from Board Setup - Bugfix: Fix issue with sending UCI BOOLs - Bugfix: Fix error message when theme cannot be installed - Bugfix: Fix font issue in Qt for windows - Bugfix: Fix broken DB download URLs - Bugfix: Crash drawing a piece from the board - Bugfix: Fix issue #307 Board style resets after editing preferences (macOS) - Bugfix: Memory Leak while reading evaluations - Bugfix: Tablebase evaluations - Bugfix: Update chart widget during auto analysis - Bugfix: Open Recent does not respect UTF8 - Bugfix: Loading of large games - Bugfix: Fix dirty notification from database to GUI - Bugfix: #287 Linux archive / build environment - Bugfix: #288 No speech engine available - Bugfix: Avoid nan in arrow painting ## December 2020: Version 1.5.6 - New Feature: Implement read support for Scid binary database (*.si4) - New feature: Spray fields in pen mode by pressing alt+Left Mouse - New feature: Add option to hide special annotations in view - New feature: Show variation arrows - New feature: Engine draws an arrow for its best move - New feature: Support online chess.com / lichess data access - New feature: Scroll through game with ChartWidget - New feature: Display eval annotations in the chart (%eval) - New feature: Open file from scratchpad / Drag file names to scratchpad - New feature: Visualization training - New feature: Indicate Draw percentage in OpeningTree - Bugfix: Opening tree - switching between Database and Filter did not trigger tree update - Bugfix: Display of symbolic pieces in OpeningTreeWidget and variation list - Bugfix: Hotkeys are not serialized properly - Bugfix: Duplicate hotkeys for menus with same name - Bugfix: Do not ask to save clipboard - Bugfix: Dark theme handling - Changed: Raise scratchpad when New or Open is invoked - Changed: Resize text fonts with Ctrl+ Ctrl- or Ctrl+Alt+Wheel - Changed: Increase max size for writable databases - Changed: Disable Raise of game list after filtering ## March 2020: Version 1.5.4 - New Feature: Support lc0 for Mac OS - New feature: blunder checking - New feature: Speak moves - New feature: Refactor complete database - Changed: Command-Key to force query for promotion dialog (instead of Meta) - Bugfix: Undo setting up board required two steps - Bugfix: Clearing database was broken - Bugfix: entering nags/null movees via keyboard ## February 2018: Version 1.5.0 - New Feature: Provide multi-selection for the database list view - New Feature: Load favorite databases at startup - New Feature: Read Chessbase Books (ctg) - New Feature: Read Arena Books (.abk) - New Feature: Drag databases into list of games - New feature: Dark Theme - New feature: FICS console with commandline - New feature: Syzygy 7 men online tablebase - New feature: Change font size via mouse wheel - New feature: Search depth for analysis - New feature: Filter operation from gamelist - New feature: Allow user-provided ECO files - New feature: Save dialog allows to store extra tags - New feature: Restrict search to start of word / end of word - New feature: Edit shortcuts by pressing key - New feature: Annotations beneath board view - New feature: Turn board for given player - New feature: Send database to Mail-Client - New feature: Show analysis of position with one piece moved - New feature: Merge internal and external themes, new option to scale board images - Bugfix: Reduced Memory Footprint - Bugfix: Removing a sub-variation kept some invisble moves - Bugfix: Internal engine produced silly suggestions in case of a check - Bugfix: Parse more than one tag in a line - Bugfix: Changing book in analysis should update moves immediately - Bugfix: Do not list read-only databases as copy targets - Bugfix: Update game list columns after leaving preferences - Bugfix: Console output and event info lacks termination of bold text - Bugfix: Avoid empty annotation when merging a game - Bugfix: "New Game" disabled after loading game - Bugfix: Invalid notation when inserting line from analysis - Bugfix: Puzzle mode not terminated properly - Bugfix: Performance reading Polyglot positions - Bugfix: Disconnecting a FICS session leaked some memory - Bugfix: Progress bar missing occasionally - Changed: Draw arrows with right mouse - Changed: Index file format updated - Changed: Support engines with state issues - Changed: time representation to ISO format - Changed: Do not ask to save deleted games - Changed: Copy current game instead of first selected game - Changed: Kick out hotkeys for database changes - Changed: Analysis and Endgametables display localised piece strings - Changed: Books support localized piece representation - Changed: Accept PGN with obscure RAVs - Changed: Index file format stores data size - Changed: If loading modifies db, mark db as changed - Changed: Always use DefaultDataPath (instead of last used folder) for Save Dialogs - Changed: Index file version ## April 2017: Version 1.4.6 - New feature: Indicate underprotected pieces - New feature: Indicate covered squares - New feature: Book building progress - Bugfix: Annotations remain visible after adding variation - Bugfix: Saving games on non-current database - Bugfix: Name of downloaded files - Bugfix: Crash engine accessing closed book - Changed: Use more threads for book building ## January 2017: Version 1.4.4 - New feature: Game time for 2-player mode - New Feature: Drag databases into list of games - New feature: Copy lists to IMG/HTML in Clipboard - New feature: Workaround UCI option issue in Stockfish 8 - New feature: Extended polyglot book generation - New feature: Reverse moving with mouse - New feature: Dragging piece with CTRL+SHIFT asks main engine / tablebase for eval - New feature: FICS with Clock above / below board - New feature: cz language pack - New feature: Message History - New feature: Rendering for Retina displays - New feature: Indicate number of pieces in Board Setup - New feature: Indicate King in check - New feature: Paint Tools - New feature: Show possible targets for selected piece - New feature: FICS rematch - New feature: Search Help pages for texts - New feature: FICS requests with color - New feature: Show all good tablebase moves - Bugfix: UCI_Chess960 occasionally not sent to Engine - Bugfix: Handling of UCI empty string tag - Bugfix: Renaming a player / event tag gave inconsistent index in case of existing target tag - Bugfix: Restoration of floating docks - Bugfix: Chess960 castling direction wrong - Bugfix: Chess960 with UCI engines - Bugfix: Resizing the application would sometimes fail - Bugfix: Matchparameter Dialog misplaced - Bugfix: Premoving allowed moving opponent pieces - Changed: Analysis time up to 10 minutes - Changed: Bundle Stockfish 8 - Changed: Icons in context menus - Changed: Matchparameter Dialog - Changed: Square annotations - Changed: Tock at 30..20..10s before Timeout - Changed: Move some preferences onto toolbar ## February 2016: Version 1.4.0 - New Feature: Filter duplicate games - New Feature: Chess960 / Fischerandom Support - New Feature: Game matches with sudden death timing - New Feature: Let two engines play out a game (engine match) - New Feature: #104 Display arbitrary tags in game list - New Feature: Scratchpad - New feature: Playerinfo filters complete openings - New feature: Support SCID format piece sets - New feature: Favorite web source with auto-increment - New feature: List of recently used games - New feature: Store some more FICS preferences - New feature: Start threat with '--' - New feature: Allow castling in normal game as in Chess960 with dragging King onto Rook - New feature: Parse mal-formed FEN with - - - - at end - New feature: Show folders on Linux desktops (similar to mac OS/Windows) - New feature: Engine logging to file - New feature: Helpbrowser with Index Combobox - New feature: Castling support for chess960 - New feature: Completer for FICS say messages - New feature: Added checkbox so that engine starts game - New feature: Premove against engine - New feature: GUI provides book moves for engine games - New feature: Plock 10s before end of FICS game - New feature: Select Promotion Dialog with Meta-Modifier - New feature: Show time annotation also for previous move (if available) - New feature: Accept resignations from winboard engines - New feature: FICS start button - New feature: Assign rating to databases - New feature: Test 50 moves/position repetition when playing out games - New feature: No hints during training or puzzling - New feature: Drag/drop PGN-Files/Text to other applications - New feature: Make images flipped if mainboard is flipped - New feature: B/W images of board - Bugfix: Crash loading small file from command line - Bugfix: Eco Info formatting - Bugfix: Castling not possible sometimes - Bugfix: Moving pieces with keyboard in auto-responder mode - Bugfix: Frame around square where drag starts - Bugfix: Undo move in FICS puzzle mode - Bugfix: FICS timeout handling - Bugfix: Undo move in FICS puzzle mode - Bugfix: FICS timeout handling - Bugfix: Openingthread crashes at end of FICS game - Bugfix: Fics matches were not continued - Bugfix: Copied games occasionally did not show up in game list immediately - Bugfix: Closing databases at shutdwon if saving was neglected was wrong / duplicated queries for saving - Bugfix: Copying games to active database occasionally forgot to update GUI - Bugfix: Opening Tree might crash - Bugfix: Player Opening Statistics wrong - Bugfix: Do not indicate premove in FICS puzzle mode - Bugfix: Output would occasionally write orphaned x... to HTML - Bugfix: Size of slider text (thx to Byrial Jensen) - Bugfix: Tablebase results would sometimes not fit to actual board - Bugfix: FICS text "puzzle almost solved" ends puzzle mode - Bugfix: Handle invalid password upon connecting to FICS - Bugfix: Terminate auto analysis upon changing of database - Bugfix: Doing moves while not at end of game broken - Bugfix: Autoplayer did not work together with backward analysis enabled - Bugfix: Chartwidget repaints occasionally fail - Bugfix: Copy games from main menu did not work for selections - Bugfix: Pasting into new game asserts - Bugfix: Progress not indicated for searching operations - Bugfix: Rendering board would occasionally draw offset twice - Bugfix: Qt4 compatibility - Changed: Skip empty parts when copying images - Changed: Always draw square around board - Changed: Training with Options - Changed: Force writing variations from Engine even if no move exists - Changed: Set Result at end of game against engine - Changed: Do not elide tab text of boards - Changed: Reduce memory needed for RW-Databases ## May 2015: Version 1.3.2 - New feature: Variation indicator in toolbox - New feature: FICS - Toggle board at beginning of puzzle - New feature: Toolbox for adding Nags (e.g. on WhiteBoards) - New feature: FICS - Filter computers and unrated users - New feature: Show date of last access to a database - New feature: Pin Opening Tree at a position - New feature: Clear filter before starting search from opening tree - New feature: Select board for searching position from open boards - New feature: Show threat after making move - Bugfix: Index file usage broken - Bugfix: Missing newline copying games into a closed file - Bugfix: Better status message when copying multiple games - Bugfix: Gamelist header configuration does not persist - Bugfix: Windows Installation does not show Pin Icon ## April 2015: Version 1.3.0 - New Feature: Play games on FICS with telnet or timeseal - New Feature: Boards now 1:1 with open databases - New Feature: Remove found items from filter - New feature: Flip board to side to move while loading game in training - New feature: Setup Board Dialog with Coordinates - New feature: #137 Extend Opening tree (Back button) - New feature: Undo last move in Opening Tree - New feature: Player Info filters games also for specific color - New feature: Player Info shows regularly played openings - New feature: Automatic analysis backward from end of game - New feature: Refactoring from context menu of game text - New feature: PlayerInfo with performance per eco code - New feature: Hide selected game from game list - New feature: Allow editing arbitrary tags - New feature: Draw annotations whith Shit+Left-Click with last color used - New feature: Saving w/o dialog - New feature: Material profile - New feature: New board "lanta" - New feature: Allow filtering of non-active DB from OpeningTree - New feature: Send PGN by mail - New feature: load project databases from Help menu - Bugfix: Autoanalysis runs over remaining game after adding variation - Bugfix: Annotation menu seems to contain duplicate entry - Bugfix: Do not limit num pv in analysis - Bugfix: Pressing Shift while dragging piece creates illegal baord view - Bugfix: Guess generation crashes when given an illegal position - Bugfix: In auto responder mode, arrows where painted too late - Bugfix: Dialogs non-modal - Bugfix: Loading translations failed - Bugfix: Open file with relative path from commandline ## October 2014: Version 1.2.2 - Bugfix: Entering a rook move or 0-0 did not work via keyboard - Bugfix: Plycount wrong saving a game from the non-current database - Bugfix: Crash saving a database upon closing chessx if database was not current DB - Bugfix: Enter-Key did not terminate entering a nag - Bugfix: Occasionally random move would get highlighted - Bugfix: Searching for Rounds and Moves did not work - Bugfix: Searching for ranges did not include limits - Bugfix: UCI Options containing a '.' were parsed incorrectly - Bugfix: Entering half-ply count was limited to 99 moves (thx to Niklas) - Bugfix: Retracing a game would fail at move one - Bugfix: Retracing a game beyond a move with variations would leave invisible variations - Bugfix: Pasting PGN into new game did not set modified flag - Bugfix: Pasting FEN into new game did not create new game - Bugfix: Changes to square and arrow annotations in annotation dialog are not painted immediately - New feature: CR#141 Edit game details - New feature: CR#140 Remember maximize state (and full-screen state) - New feature: Arrow as current move hint - New feature: Menu entry to clear clipboard database - New feature: Sorting of game list by clicking header (for databases<=4K) - New feature: Multi-Selection in the game list - Enhanced: Speed up polyglot book building - Changed: F3/F4 now load previous / next game ## July 2014: Version 1.2.0 - New Feature: Use polyglot books in Opening Tree - New Feature: Build polyglot books from Databaselist - New Feature: Enter games via keyboard - New Feature: Undo and Redo of game editing actions - New Feature: Support for external tools - New Feature: Paste variation from clipboard into game - New Feature: Danish Translation (thanks to Byrial Jensen) - New Feature: Allow removing found items from filter - New feature: Show title of game in Copy Game Dialog - New feature: Opening names in ECO Widget - New feature: Make position searches more comfortable - New feature: CR#206 Remember settings for more windows. - New feature: CR#203 Center the board inside its container - New feature: CR#118 Gameview: Make tags clickable - New feature: Auto analysis writes engine's name into final annotation - New feature: Asynchronous Searching - New feature: Allow several unsaved games at the same time (one per db) - New feature: Allow disabling menu icons - New feature: Allow constant move indicator - New feature: #117 Export screenshot to file - New feature: Filter in ECO widgets support regular expression - New feature: Checkbox in opening tree to add moves to game too - Changed: Pinned games have infinite analysis depth - Changed: Dialogs remember sizes and screen positions - Changed: CR#127 New navigation buttons order. - Changed: board tabs carry name of db instead of numbers - Changed: Auto analysis won't add move at end of game - Changed: Assignment of CTRL+C key to direct pasting of PGN - Changed: #121 Thicker, more visible arrows and colored squares - Changed: Show game title now in three lines - Changed: Copy of a game via context menu copies selected game - Changed: ECO Widget shows names of openings - Bugfix: Nags with bishops now exclusive - Bugfix: CR#205 line does not resume from the same indentation. - Bugfix: CR#204 Database is not released from memory upon closing - Bugfix: Annotations were not handled correctly when compacting database - Bugfix: Analysis/"Mate in" has inconsistent color - Bugfix: EGT Time annotation broken - Bugfix: Do not send ucinewgame after making a move ## February 2014: Version 1.1.0 - New feature: Traning with Toolbar Icon - New feature: Play out game against engine - New feature: Limit time that engines may use for analysis - New feature: Auto Responder for training openings etc. - New feature: Show name of opening in addition to ECO-Code - New feature: Use any open database as source for Opening Tree - New feature: Opening Tree with Filter as Source - New feature: Splitter in Detail Views - New Feature: CR#6 Configurable shortcuts - New feature: Visual indicator for results - New feature: Show location of AppSettings in About Dlg - New feature: CR#108 Lock engine to current position - New feature: Null moves at unusual positions - New feature: Incremental Opening Tree - New feature: Adjust columns in list views - New feature: Tabs switch if something is dragged to them (CR#112) - New feature: Hilite new favorite item - New feature: Select font for ChessBrowser from Preferences - New feature: Additional link targets in info widgets - New feature: PromotionDialog as suggested in CR#113 Pieces in promotion dialog - New feature: Added possibility to force loading english lang in German and French - Bugfix: #193 wrong nag $1-$6 - Bugfix: #191 Cannot edit an annotation-only comment - Bugfix: Time malformed - Bugfix: #189 Missing PNG for new board button - Bugfix: Searching for result 1-0 was not possible - Bugfix: Filtering if filter widget was changed from another widget - Bugfix: CR#105 few remarks - issue 1 - coherence with icons - Bugfix: CR#187 comments before first move are not read - Bugfix: HTML-Output in some special cases wrong - Bugfix: Worked around potential leak with smart pointer - Bugfix: Issue closing chessx while loading a database - Bugfix: Some columns won't display their content if the local setup is old enough - Bugfix: #180 - part 3 (user is asked several times to load database) - Bugfix: Nullmove issue - Bugfix: #180: Load Order of DLLs (did not start on Windows) - Bugfix: Better output of end of variations - Bugfix: Workaround for Apache Issue: #183 Download of PGN databases fails because of blocked user-agent - Bugfix: Guessengine crashes when accessing uninitialized memory - Bugfix: CR#182 Minimize - restore = tab switch bug - Bugfix: CR#181 typos - Bugfix: CR#178 Deleting a variation does not clear the annotation - Bugfix: Unterverwandlung - Fixed: textbrowserex.h case sensitivity (did not compile on Linux) - Fixed: a static leak (thanks to Albert for mentioning this) - Fixed: portability issue #185 Build error in enginelist.cpp for kFreeBSD - Changed: Flip Icon consistent with main GUI - Changed: Slider 'Move Interval' moved from Preferences to StatusBar ## September 2013: Version 1.0.0 - New feature: Get translation files from server - New feature: Copy Text or HTML from Notation - New feature: Offer to load a default database for first time users - New feature: CR#10 Configurable Game View - customize appearance of notation - New feature: Inserting moves (in addition to adding moves as variation - New Feature: CR#86 Merge games with Drag&Drop - New Feature: CR#46 Games whose position is [end] selectable - New Feature: CR#43 Frequency and score ~0% instead of 0% when not exactly 0 - New feature: Setup Dialog has new functions to mirror board or colors. - New feature: Select Language from Preferences (requires restart) - New feature: Online check for updates - New Feature: Column date of last modification - New Feature: Localized Piece Initials (see CR#3592733 Output / Input PGN - New feature: Create a Diagram Nag (201 like in SCID) from GUI - New Feature: Draw Board Coordinates (see CR#1715710 Numbers and ...) - New Feature: HTML Output with readable basic tags instead of PGN look - New feature: Diagrams in HTML Export and Notation - New feature: HTML Output with symbolic nags in HTML/UTF8 - New features: Navigation within siblings of variations with keyboard - New feature: Enter or Exit Variation now moves within mainline - New feature: Toolbar for commonly used actions - New Feature: ECO based Opening Overview of the current database - New Feature: MDI-Interface - New feature: Opening tree has its own board view. - New Feature: CR#3607996 Always on top feature - Bugfix: ChessBrowser does not indicate '?'-tags - Bugfix: HTML-Output contained one HTML-Header for each game - Bugfix: Sorting by size was not ideal - Bugfix: CR#171 - Board Setup dialog: wrong board size - Bugfix: Removing last arrow annotation leaves ugly comment - Bugfix: Stay On Top accidentally active in OS which were Non-Windows-OS - Bugfix: Concurrent loading of games (fix from James Coons) - Bugfix: Game List was not updated after bulk copy of games - Bugfix: Black ELo was only saved if a white ELO was given - Bugfix: CR#3612157 tablebase - Bugfix: Performance Boost for filtering with result-cache - Bugfix: CR#3611434 Local vs global menu inconsistency - Bugfix: Update Widgets after saving a database - Bugfix: Created PGN was invalid due to invalid date format - Bugfix: Opening new game did not clear selection on game list ## March 2013 Version 0.9.6 - Bugfix / Feature removal: Filtering opening tree was somewhat active - Bugfix: (thx to James!) Promoting into different pieces cannot start - Bugfix: Before closing a database ask to save a new or modified game - Bugfix: CR#3596577 - Game modifications lost when changing a game - Bugfix: Ctrl+Drag in BoardSetup-Dialog loses a button - Bugfix: DatabaseList view shows Linked local files with annoying scheme - Bugfix: Drawing board when resizing off by 1 - Bugfix: Enable Escape-Key for Dialogs - Bugfix: Flickering with OpeningTree open - Bugfix: New Game did not clear the tags from the last game - Bugfix: Openening ECO files missed some checks - Bugfix: Opening ZIP or URL from Commandline or event loop was missing - Bugfix: Parsing half move count in FEN (Francis Monkman) - Bugfix: Removing a variation removed the wrong variation - Bugfix: Saving a database did not reset the modified flag resulting in - Bugfix: Selected wrong game when deleting games from Database - New Feature: Accept FENs which do not have a valid EnPassant Encoding - New Feature: AutoPlayer - New Feature: Continuous Blunder Checking - New Feature: Drag Drop complete db onto other db - New Feature: Player List with linked ECO filtering - New Feature: PlayerList gives hints on openings played - New Feature: Sorting the list of databases with header click - New Feature: Support Team Tags when saving games - New feature: Accept FEN with invalid movenumber (James Coons suggestion) - New feature: Reload last game at open of database - New feature: Mass changing tags in database (Events, Player Names) - New feature: Shift+Rightclick on Boardview allows editing of colored - New feature: Training mode - New feature: Numbering variations - New feature: Refactor complete game (uncomment / remove all variations) - New feature: Saving a game can now be either cancelled (the new option) - New feature: Edit square colors like in chessbase with Shift+Right- - New feature: Delete games from a database - New feature: Auto Analysis with Engine 1 of one or more games - New feature: Clear cache between database changes - New feature: Reorder variations - CR#3558001 - New feature: Force adding a move as variation by pressing ALT while - New feature: Copy Fen in human readable form - CR#3580030 - New feature: DatabaseList double click opens file - New feature: Highlight last move done when scrolling through a game ## December 2012 Version 0.9.4 - Bugfix: Writing of files automatically made use of UTF8 instead of ANSI - Bugfix: Crash at loading PolyGlot 1.4 - Bugfix: Comment at start of empty game - Bugfix: Databases larger than 4G - Bugfix: Databases with UNIX-LF - Bugfix: Some nags were not properly accessible from keyboard - Bugfix: No keyboard nags for first white move - New Feature: Time Editor for elapsed game time - New Feature: CR#3580029 Add only first move from engine analysis - New feature: Close database from the database list with context menu - New feature: Toggle UTF8 flag in database list - New feature: Open compressed archives (from HTTP or local file) - New feature: Open a database from a URL (HTTP) - New Feature: Clear Nags from keyboard with - New Feature: Create Index File thus accelerating re-loading of large PGN enormously - New Feature: Searching of ranges, e.g. ELO "2000-2300" - New Feature: Automatic classification with ECO of unclassified / new games ## November 2012 Version 0.9.2 - Bugfix: Support engines which send multiple spaces - Bugfix: Close Database while updateing opening tree - Bugfix: Filtering for number of moves fails if an empty game is in the database - Bugfix: Not well behaving Xboard engines crash ChessX - Bugfix: Search of Board crashes when started together with OpeninTree Update - Bugfix: Press CTRL+drag to irritate the guessMove implementation - New Feature: Move Indicator adjusts itself in size (James Coons) - New Feature: Common Font Size for all widgets except game view - New Feature: Separate handling of UTF8 files - New feature: List views can be customized (right click title line) - New feature: UCI Option Parser - New Feature: CTRL+drag, CTRL-Shift-Drag replaces or inserts a move - New Feature: F1 starts Help View and some help contents are already there - New Feature: Games with errors insided are marked red in game list - New feature: Added Stockfish as internal Engine in case no engine is configured - New board themes Brazilwood and Maple - New Icons - Usability: Filterflag only influences gamelist ## September 2012 Version 0.9 - New Features - Player List as Dock Window - New Database List - Drag and Drop of games - Drag and Drop of Databases - Second analysis window - Locate Databases on harddisk in Explorer/Finder - Multi-Threading Support for opening DB and updating Opening Tree - Copy / Paste of PGN - Create Images of Boards - New Board Styles - All Resources internal - Parsing PGN to draw arrows on board (cf. chessbase) - Parsing PGN to color Squares (cf. chessbase) - Parse / Insert Zero Moves to document / analyze threats - Drag'n'Drop Support setting up a board - Relaxed FEN handling for easier pasting of FENs - Version Resource in Windows - Icon Resource in Windows - UTF8 Support - bugfixes in Parser - Fixed some strange PGN parsing issues - especially issues like the one described in #3396532 - bugfixes in GUI - It is not possible to add a variation from Analysis to a game text if standing at end of a variation - Bugfixes starting up engines - Disabled MultiPV on XBoard engines - Added elapsed time for analysis lines **issues closed:** - CR#2984375 Saving Clipboard fails silently - CR#3043278 Problem with LaTeX output - CR#3135871 No control performed on input date - CR#3135871 No control performed on input date - CR#2872974 Remove->Previous moves should be smarter - CR#3542101 Changing and saving a file does not update the game list view - CR#2881228 Crash on File->Close (or Quit) with OpeningTree updating - CR#3297478 Crash on move gxh2+ - CR#2823746 Crash when trying to analyze with non-existing New Engine - CR#2881228 Crash on File->Close (or Quit) with OpeningTree updating - CR#3170534 Crash if start of engine fails (0.8) - CR#3179203 Do not crash trying to show a special NAG; this should solve bug . - CR#2824024 Confusion between slash and backslash in file paths - CR#1773747 "Change guessed move on right click". The feature can be configured, as currently we have "take back a move" om mouse right click (if configured, CTRL+right-mouse will move back instead) - CR#1651405 "Comments in UTF-8 are broken" - CR#1715720 - CR#1984912 Names in GameList vs QuickTagSearch - CR#3043278 Problem with LaTeX output - CR#3396532 errors reading multi line pgn formats - CR#2955889. **Building** - Separate Debug/Release/Static folders ## November 20120 Version 0.8 - bug fixes: engine stuff - feature:Add engine variation to the game - feature:Implement MultiPV analysis for UCI engines (based on patch by Juan Carlos Girardi) - feature:Add basic NAG editing - feature:Simplify adding moves: always add variation if move exists. - feature:Add menu command to remove/promote variation. - feature:Show TableBase result in Analysis window. ## Wed 10 Feb 2010, 01:40:00 CET Version 0.7 - bugfix: do not crash when removing engines - bugfix: no problems with more than 10 engines - bugfix: do not stop running engine on minimize/hide - usability: browse for executable when adding new engines - bugfix: correctly display NAGs below the board - bugfix: correctly truncate previous moves - feature: global shortcut F2 to start/stop engine - change: speedup by canceling previous OpeningTree search before the next - bugfix: ignore clicks on illegal OpeningTree moves like [end] - feature: make editable PGN size limit configurable - feature: show progress bar when opening/saving files - feature: show progress bar for OpeningTree - feature: promote variation ## Wed 1 Jul 2009, 00:50:22 CET Version 0.6 - feature: warn when quitting with unsaved databases - feature: improve Engine tab of Preferences dialog, add reordering - feature: remember current engine - bugfix: show correct score for Crafty - bugfix: correctly display variations leading to mate in UCI engines - bugfix: update ECO database for opening detection and move guesser - bugfix: improve focus handling in game list and game text - feature: timer-delayed game loading when pressing Ctrl+Down/Up - bugfix: remove bold column names in TableView - bugfix: support NAGs not preceeded with space in PGN parser - bugfix: make PGN parser more robust - bugfix: optimize PGN output - bugfix: enable leading comment in mainline and variations - bugfix: slightly improve PGN export formatting - feature: allow creating new PGN databases - change: drop CXD databases support - bugfix: guess move only with mouse over the board - feature: truncate from the beginning - bugfix: correct tag order for QuickSearch - feature: search games by number or number range - bugfix: do not read a game beyong the end of file - feature: allow editing pre-move comments - bugfix: PGN standard compliant ep square in FEN - bugfix: reparent some dialogs - bugfix: remove flickering at startup - feature: make comments editable - feature: correctly read PGNs with FEN - feature: new Leipzig theme - feature: allow removing variations - feature: enable HTML export - feature: allow setting small fonts in chess text widgets (useful for laptops). - bugfix: save all PGN tags - bugfix: display correct move number in starting position - feature: allow copying games between databases - feature: allow copying pieces in BoardSetup by using Ctrl - change: add Advanced setting to BoardSetup - feature: PlayerInfo dialog with player statistics - feature: display FEN in BoardSetup - feature: copy/paste position in BoardSetup - bugfix: correctly recognize promotions in UCI engines - bugfix: correctly handle promotion in tablebases - bugfix: support 1/2 as a draw symbol ## Wed 13 Jun 2007 19:47:32 CET Version 0.5 - feature: engine analysis - feature: Opening Tree - feature: Setup Position dialog enhancements - feature: use ECO information to guess moves - feature: option to combine searches - feature: enable translations - feature: make frame color configurable - feature: remove last move with right click - feature: remember matching position in position search - feature: improve layout of Game Info - feature: display game length in Game List - feature: remove last move with right-click - feature: shortcuts for Game List and Game Text - bugfix: fix move loading failure in large databases - bugfix: open PGN files from command line - bugfix: don't flood tablebase servers with too many requests - bugfix: sometimes online tablebase wasn't used even if enabled - bugfix: flip setup board if main board is flipped - bugfix: various small fixes to move guesser - bugfix: some errors in Game/tags handling - bugfix: do not crash when loading random game from empty filter - change: lower network usage for EGTB server - change: new, much faster Board implementation - change: much faster Tag search - change: do not highlight first move in starting position - change: redesign Board tab in Preferences dialog ## Wed 9 May 2007 18:59:47 CET Version 0.4 - feature: new, much improved themes - feature: move guesser - feature: support for online tablebases - feature: binary ECO file format (faster startup) - feature: simple tag search dialog for single tag searches - feature: improve look&feel and usability of Tip of the day - feature: Apply button for Preferences dialog - feature: configurable square highlight color - bugfix: update theme when pieces are changed - bugfix: fix some drag&drop problems - bugfix: segfault when truncating moves from empty game - bugfix: ask for promoted piece only for legal moves - bugfix: allow variations in starting position - bugfix: correctly redraw board frame - bugfix: correctly show side to move in Setup Position dialog - bugfix: fix rare bug when # symbol was displayed instead of + - bugfix: correctly calculate hash value for en passant - bugfix: re-enable FEN tag support - change: optimize PGN loading (loads 10-20% faster) ## Mon 23 Apr 2007 18:59:47 CET Version 0.3 - feature: display ECO information - feature: move pieces by drag&drop - feature: remove moves/variations and truncate moves - feature: display side to move - feature: position search - feature: internal support for editable PGN databases (no GUI yet!) - feature: export games in filter/all games to PGN - feature: small sample player database (look for Adams) - bugfix: fix incorrect SAN representation of en-passant moves - bugfix: correctly calculate game length displayed in GameInfo - bugfix: display empty game - bugfix: more robust PGN parsing - bugfix: Sun-Solaris compilation (patch by Atul) - bugfix: some improvements to Windows installer - bugfix: more usual PGN format (space after move number etc.) ## Thu 28 Feb 2007 00:59:47 CET Version 0.2 - feature: highlight and display current move - feature: add variations - feature: support promotion when entering moves - feature: redesign Setup Position to improve usability - feature: check board validity in Setup position dialog - bugfix: correctly display move numbers for non-standard games - bugfix: keep move number and side to move when setting position - bugfix: copy/paste move number to/from FEN - bugfix: accept non-standard castling (0-0 instead of O-O) - bugfix: correctly draw large boards in unscaled pixmap mode - bugfix: insert all pieces in given color in Setup Position - bugfix: fix segfault when removing piece from empty square - bugfix: correctly finding installed data path on Debian. - change: clean configuration file format chessx-master/INSTALL.md0000755000076500000240000000632414666426276014151 0ustar jensstaff![Icon](https://github.com/Isarhamster/chessx/raw/master/data/images/chessx-64.png)ChessX ================================================================= # 1. Description A free and open source chess database application for Linux, Mac OS X and Windows. [ChessX Web Site](http://chessx.sourceforge.io/) # 2. Features * Multi-platform. Supports Windows, Linux and Mac OS X * Load and save PGN files * Work with multiple databases simultaneously * Browse chess games, including variations * Enter moves, variations, comments * Setup board, copy/paste FEN * Search in Databases for text or positions * Display tree of moves for the current position * Analyze using UCI and Winboard/Xboard Chess engines * Prepare for openings or opponents * Training mode (next move is hidden) * Integrated Stockfish engine * FICS Support # 3. Requirements To compile ChessX, you need zlib, qmake and **Qt5 version 5.14.1** or above. **known issue:** FICS does not work properly with Qt4 # 4. Compilation Compiling the source is simple. Execute: qmake and then make If the compilation is successful you should be able to run ChessX executable in **bin** (or **release**) subdirectory. It is called: **chessx** on Linux, **chessx.app** on Mac OS, and **chessx.exe** on Windows ## 4.1 Compilation in Linux x64 systems On Linux x64, the following commands are required for successful compilation: Build the translations lrelease-qt5 chessx.pro Run qmake, specifically qt5 version qmake-qt5 Compile with make If compilation finishes successfully, the executable will be found as: release/chessx # 5. Problems You may check your Qt version by running: qmake -v If you erroneously tried to build with Qt3, be sure to recreate makefiles using: qmake -recursive If your compiler does not support C++11, comment out ```CONFIG += c++11```, see file ***chessx.pro***. If your Qt libraries are compiled w/o Multimedia, comment out ```CONFIG += sound```, see file **chessx.pro** Depending on your installed libraries, you may have to experiment with ``` # DEFINES += ZLIB_WINAPI # LIBS += -lz # INCLUDEPATH += /QtZlib ``` # 6. Debugging If you want to help debugging ChessX, rebuild with debug option enabled: qmake -recursive -after "CONFIG+=debug" make ************* **License:** GPLv2 :copyright: 2021 -- 2005, Maintained by Jens Nissen and Ejner Borgbjerg
:copyright: 2021 -- 2005, Other developers: Michal Rudolf, Bruno Rizzuti, Marius Roets, Sean Estabrooks, Rico Zenklusen, William Hoggarth, and Heinz Hopfgartner This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. chessx-master/TODO.md0000755000076500000240000000137214666426276013606 0ustar jensstaff## TODO for 2.0 _(Stable Native-based version)_ * Native database format * Spellchecking * Annotation/Blunder check * Tournament tables * ELO rating calculation * ECO Browser ## TODO for 1.5 _(Extended PGN-based version)_ * File browser - recursively find database files * Searches - enhanced header search - board search (+variants) - material search * BoardView - move animation ## TODO for 1.0 _(Stable PGN-based version)_ * GameView - display custom tags in GameView - make GameView tags configurable (color, font) ## TODO _- Refactoring needed_ * Game class * Mainwindow class ## TODO _- Ideas/Suggestions. Non critical_ * Format for exercises, tactics/endgame training etc. * Faster PGN parser * Comment search * Crosstables * Rating graph chessx-master/README.md0000755000076500000240000000375414666426276014004 0ustar jensstaff# ![Icon](data/icons/64x64/apps/chessx.png)ChessX ![CI](https://github.com/erysaj/chessx/workflows/CI/badge.svg?branch=ci-sandbox) A free and open source chess database application for Linux, Mac OS X and Windows. ## Website [ChessX Homepage](https://chessx.sourceforge.io/) ## Features - Multi-platform. It supports Windows, Linux and Mac OS X - Load and save PGN files - Work with multiple databases simultaneously - Browse chess games, including variations - Enter moves, variations, and comments - Setup board, copy/paste FEN - Search in databases for text or positions - Display tree of moves for the current position - Analyze using UCI and Winboard/Xboard chess engines - Prepare for openings or opponents ## Project Samples [//]: # "This project samples migth be a bit dated, and could be replaced with screenshots of a newer version?" Project sample 1 Project sample 2 Project sample 3 ## Categories Database, board games, turn based strategy ## [License](COPYING.md) :copyright: 2021-2005, ChessX authors This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. chessx-master/unix/0000755000076500000240000000000014666426276013474 5ustar jensstaffchessx-master/unix/io.sourceforge.ChessX.metainfo.xml0000755000076500000240000000303414666426276022147 0ustar jensstaff io.sourceforge.ChessX.desktop CC0-1.0 GPL-2.0-or-later ChessX Free Chess Database

ChessX is an Open Source chess database. With ChessX you can operate on your collection of chess games in many ways: browse, edit, add, organize, analyze, etc.

  • Load and save PGN files
  • Work with multiple databases simultaneously
  • Browse games, including variations
  • Enter moves, variations, comments
  • Setup board, copy/paste FEN, merge games
  • Search in Databases for text or positions
  • Display tree of moves for the current position
  • Analyze using UCI and Winboard/Xboard Chess engines
  • Prepare for openings or opponents
  • Training mode (next move is hidden)
  • FICS Support
http://i1-win.softpedia-static.com/screenshots/ChessX_1.png https://chessx.sourceforge.io
chessx-master/unix/chessx.desktop0000755000076500000240000000070114666426276016365 0ustar jensstaff[Desktop Entry] Name=ChessX Name[de]=ChessX Name[fr]=ChessX Comment=Chess database Comment[de]=Schachdatenbank Comment[fr]=Base de données d'échecs GenericName=Chess Game GenericName[de]=Schachspiel GenericName[fr]=Jeu d'échecs Icon=chessx Exec=chessx %f Terminal=false Type=Application Categories=Game;BoardGame; MimeType=application/x-chess-pgn; Keywords=PGN;FEN;Database; Keywords[de]=PGN;FEN;Datenbank; Keywords[fr]=PGN;FEN;Base de données; chessx-master/dep/0000755000076500000240000000000014666426276013261 5ustar jensstaffchessx-master/dep/scid/0000755000076500000240000000000014666426276014203 5ustar jensstaffchessx-master/dep/scid/CMakeLists.txt0000755000076500000240000000201314666426276016742 0ustar jensstaffadd_library(scid STATIC code/src/attacks.h code/src/board_def.h code/src/bytebuf.h code/src/codec_native.h code/src/codec_scid4.cpp code/src/codec_scid4.h code/src/codec.h code/src/common.h code/src/containers.h code/src/date.h code/src/dstring.h code/src/error.h code/src/fastgame.h code/src/filebuf.h code/src/fullmove.h code/src/game.cpp code/src/game.h code/src/hash.h code/src/hfilter.h code/src/index.h code/src/indexentry.h code/src/matsig.cpp code/src/matsig.h code/src/misc.cpp code/src/misc.h code/src/movegen.h code/src/movelist.h code/src/movetree.h code/src/naglatex.h code/src/nagtext.h code/src/namebase.h code/src/position.cpp code/src/position.h code/src/sortcache.cpp code/src/sortcache.h code/src/sqmove.h code/src/stored.cpp code/src/stored.h code/src/textbuf.cpp code/src/textbuf.h ) target_include_directories(scid PUBLIC code/src ) target_compile_features(scid PUBLIC cxx_std_17 ) chessx-master/dep/scid/code/0000755000076500000240000000000014666426276015115 5ustar jensstaffchessx-master/dep/scid/code/src/0000755000076500000240000000000014666426276015704 5ustar jensstaffchessx-master/dep/scid/code/src/error.h0000755000076500000240000000463114666426276017215 0ustar jensstaff/////////////////////////////////////////////////////////////////////////// // // FILE: error.h // Error codes // // Part of: Scid (Shane's Chess Information Database) // Version: 1.6 // // Notice: Copyright (c) 1999 Shane Hudson. all rights reserved. // Copyright (c) 2014 Benini Fulvio. all rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // /////////////////////////////////////////////////////////////////////////// #ifndef SCID_ERROR_H #define SCID_ERROR_H typedef unsigned short errorT; const errorT OK = 0, // General Error: ERROR = 1, ERROR_UserCancel = 2, ERROR_BadArg = 3, // File I/O ERROR_FileOpen = 101, ERROR_FileWrite = 102, ERROR_FileRead = 103, ERROR_FileSeek = 104, ERROR_BadMagic = 105, ERROR_FileNotOpen = 106, ERROR_FileInUse = 107, ERROR_FileMode = 108, ERROR_FileVersion = 109, ERROR_OldScidVersion = 110, ERROR_FileReadOnly = 111, ERROR_CompactRemove = 121, // Memory Allocation, corrupt data ERROR_MallocFailed = 151, ERROR_CorruptData = 152, ERROR_Corrupt = 152, // Database errors ERROR_Full = 201, ERROR_NameNotFound = 202, ERROR_NotFound = 202, ERROR_NameExists = 203, ERROR_Exists = 203, ERROR_NameBaseEmpty = 204, ERROR_Empty = 204, ERROR_NoMatchFound = 205, ERROR_NameDataLoss = 206, ERROR_NameTooLong = 207, ERROR_NameLimit = 208, ERROR_OffsetLimit = 209, ERROR_GameLengthLimit= 210, ERROR_NumGamesLimit = 211, // Position errors ERROR_InvalidFEN = 301, ERROR_InvalidMove = 302, ERROR_PieceCount = 303, // Game Errors ERROR_Game = 400, ERROR_EndOfMoveList = 401, ERROR_StartOfMoveList = 402, ERROR_NoVariation = 403, ERROR_EmptyVariation = 404, ERROR_VariationLimit = 405, ERROR_Decode = 406, ERROR_GameFull = 407, ERROR_CastlingAvailability = 408, // Buffer errors ERROR_BufferFull = 601, ERROR_BufferRead = 602, // Codec errors ERROR_CodecUnsupFeat = 701; static_assert(OK == false); #endif // #ifdef SCID_ERROR_H /////////////////////////////////////////////////////////////////////////// // EOF: error.h /////////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/index.h0000755000076500000240000001311714666426276017172 0ustar jensstaff/* * Copyright (c) 1999-2002 Shane Hudson * Copyright (c) 2006-2009 Pascal Georges * Copyright (C) 2014-2016 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ #ifndef SCID_INDEX_H #define SCID_INDEX_H #include "common.h" #include "containers.h" #include "date.h" #include "indexentry.h" #include "filebuf.h" #include "hfilter.h" #include #include #include #include class NameBase; ////////////////////////////////////////////////////////////////////// // Index: Constants const char INDEX_SUFFIX[] = ".si4"; // Descriptions can be up to 107 bytes long. const uint SCID_DESC_LENGTH = 107; const uint CUSTOM_FLAG_DESC_LENGTH = 8; const uint CUSTOM_FLAG_MAX = 6; // Header on-disk size: magic=8, version=2, numGames=3, baseType=4, autoLoad=3 // Description length = 111 bytes including trailing '\0'. // Custom flag desc length = 9 bytes including trailing '\0'. // So total is 128 bytes + 9*6 = 182 bytes for the whole header. const uint INDEX_HEADER_SIZE = 8 + 2 + 3 + 4 + 3 + SCID_DESC_LENGTH + 1 + (CUSTOM_FLAG_DESC_LENGTH+1) * CUSTOM_FLAG_MAX; const uint OLD_INDEX_HEADER_SIZE = INDEX_HEADER_SIZE - (CUSTOM_FLAG_DESC_LENGTH+1) * CUSTOM_FLAG_MAX; ////////////////////////////////////////////////////////////////////// // Index: Class Definition class Index { private: // The complete index will be loaded in memory and can be pretty huge. // To avoid the slow reallocation when adding games we split the data in chunks. // CHUNKSHIFT is the base-2 logarithm of the number of index entries allocated as one chunk. // i.e 16 = 2^16 = 65536 (total size of one chunk: 65536*48 = 3MB) VectorChunked entries_; // A two-level array of the entire index. int nInvalidNameId_; gamenumT seqWrite_; struct { // one at the start of the index file. versionT version; // version number. 2 bytes. uint baseType; // Type, e.g. tournament, theory, etc. gamenumT numGames; // number of games in file. gamenumT autoLoad; // game number to autoload: 0=none, 1=1st, >numGames=last // description is a fixed-length string describing the database. char description [SCID_DESC_LENGTH + 1]; // short description (8 chars) for the CUSTOM_FLAG_MAX bits for CUSTOM flags char customFlagDesc [CUSTOM_FLAG_MAX][CUSTOM_FLAG_DESC_LENGTH+1] ; bool dirty_; // If true, Header needs rewriting to disk. } Header; friend class CodecSCID4; public: Index() { Init(); } errorT Close() { Init(); return OK; } const IndexEntry* GetEntry (gamenumT g) const { ASSERT(g < GetNumGames()); return &(entries_[g]); } /** * GetBadNameIdCount() - return the number of invalid name handles. * * To save space, avoiding duplicates, the index keep handles * to strings stored in the namebase file. * If one of the two files is corrupted, the index may have * handles to strings that do not exists. * This functions returns the number of invalid name handles. */ int GetBadNameIdCount() const { return nInvalidNameId_; } /** * Counts how many times every names contained in @e nb is used. * @param nb: the NameBase linked to this Index * @returns an array of std::vectors containing the count of each name. */ std::array, NUM_NAME_TYPES> calcNameFreq(const NameBase& nb) const { std::array, NUM_NAME_TYPES> resVec; for (nameT n = NAME_PLAYER; n < NUM_NAME_TYPES; n++) { resVec[n].resize(nb.GetNumNames(n), 0); } for (gamenumT i = 0, n = GetNumGames(); i < n; i++) { const IndexEntry* ie = GetEntry(i); resVec[NAME_PLAYER][ie->GetWhite()] += 1; resVec[NAME_PLAYER][ie->GetBlack()] += 1; resVec[NAME_EVENT][ie->GetEvent()] += 1; resVec[NAME_SITE][ie->GetSite()] += 1; resVec[NAME_ROUND][ie->GetRound()] += 1; } return resVec; } /** * Header getter functions */ gamenumT GetNumGames () const { return Header.numGames; } versionT GetVersion () const { return Header.version; } void addEntry(const IndexEntry& ie) { entries_.push_back(ie); Header.numGames++; } void replaceEntry(const IndexEntry& ie, gamenumT replaced) { ASSERT(replaced < this->GetNumGames()); entries_[replaced] = ie; } private: void Init() { Header.numGames = 0; Header.version = SCID_VERSION; Header.baseType = 0; Header.autoLoad = 1; Header.description[0] = 0; std::memset(Header.customFlagDesc, 0, sizeof(Header.customFlagDesc)); Header.dirty_ = false; nInvalidNameId_ = 0; seqWrite_ = 0; entries_.resize(0); } }; #endif // #ifdef SCID_INDEX_H ////////////////////////////////////////////////////////////////////// // EOF: index.h ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/hfilter.h0000755000076500000240000002126714666426276017525 0ustar jensstaff/* # Copyright (C) 2016-2018 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ #ifndef SCID_HFILTER_H #define SCID_HFILTER_H #include "common.h" #include #include #include /* * A database can be searched according to different criteria and the list of * matching games is stored into a Filter object. * A value of 0 indicates the game is excluded, or 1-255 indicates * the game is included, and what position to show when the game * is loaded: 1 means the start position, 2 means the position after * Whites first move, etc. */ class Filter { std::unique_ptr data_; // The actual filter data. gamenumT size_; // Number of values in filter. gamenumT nonzero_; // Number of nonzero values in filter. size_t capacity_; // Number of values allocated for data_. public: explicit Filter(gamenumT size) : size_(size), nonzero_(size), capacity_(0) {} void Init(gamenumT size) { data_ = nullptr; nonzero_ = size_ = size; } /// Return a pointer to the allocated data. byte* data() { return data_.get(); } /// Return the number of nonzero values in filter. gamenumT Count() const { return nonzero_; } /// Return the number of elements in filter. gamenumT Size() const { return size_; } /// Changes the number of elements stored. void Resize(gamenumT size) { if (!data_) { nonzero_ = size; } else if (size < size_) { nonzero_ = size - static_cast(std::count( data_.get(), data_.get() + size, 0)); } else if (size > size_) { if (size > capacity_) { auto tmp(std::move(data_)); allocate(size); std::copy_n(tmp.get(), size_, data_.get()); } byte val = 0; if (Count() == Size()) { val = 1; nonzero_ = size; } std::fill(data_.get() + size_, data_.get() + size, val); } size_ = size; } /// Gets the value at index. byte Get(gamenumT index) const { ASSERT(index < Size()); return data_ ? data_[index] : 1; } /// Sets the value at index. void Set(gamenumT index, byte value) { ASSERT(index < Size()); if (data_) { if (value == 0) { if (data_[index] != 0) --nonzero_; } else if (data_[index] == 0) { ++nonzero_; } data_[index] = value; } else if (value != 1) { allocate(size_); std::fill(data_.get(), data_.get() + size_, 1); data_[index] = value; if (value == 0) --nonzero_; } } /// Sets all values. void Fill(byte value) { if (value == 1) { data_ = nullptr; nonzero_ = size_; } else { if (!data_) { allocate(size_); } std::fill(data_.get(), data_.get() + size_, value); nonzero_ = (value == 0) ? 0 : size_; } } private: void allocate(size_t size) { auto capacity = (size | 63) + 1; data_ = std::make_unique(capacity); capacity_ = capacity; } }; /* * This class abstracts the Filter class providing an interface equivalent to a * pointer to a std::map object, where the keys are the * gamenumT of matching games and the mapped_types are the number of half-moves * necessary to reach the matching position. * Searches that use only header informations (player names, dates, ...) match * at the starting position (0 half-moves). * * It is also possible to combine two filters in an efficient and transparent * way. If a secondary "mask" filter is supplied, the functions get(), size() * and the const_iterator consider only the games included in both filters. * Their behavior is equal to: * using Filter = std::map; * Filter tmp_combined; * std::set_intersection(mask->begin(), mask->end(), main->begin(), main->end(), * std::inserter(tmp_combined, tmp_combined.end()), * [](auto& a, auto& b) { return a.first < b.first; }); * return HFilter(&tmp_combined).begin/get/size(); */ class HFilter { Filter* main_; const Filter* mask_; public: /** * class const_iterator - iterator for HFilter objects * * This class and the relative functions begin() and end() allow to use * HFilter objects with STL algorithms and c++11 for-ranged loops. * For example: * for (auto& gnum : *hfilter_obj) {} * is equal to: * for (gamenumT gnum = 0, gnum < scidBaseT::numGames(); gnum++) { * if (hfilter_obj->get(gnum) == 0) continue; * } */ class const_iterator { gamenumT gnum_; gamenumT end_; const HFilter* hfilter_; bool inFilter_; public: typedef std::forward_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; typedef gamenumT value_type; typedef const gamenumT* pointer; typedef const gamenumT& reference; const_iterator(gamenumT gnum, gamenumT end, const HFilter* hfilter, bool inFilter = true) : gnum_(gnum), end_(end), hfilter_(hfilter), inFilter_(inFilter) { ASSERT(hfilter != 0); if (gnum_ != end_) { bool included = (hfilter_->get(gnum_) != 0); if (included != inFilter_) operator++(); } } reference operator*() const { return gnum_; } const_iterator& operator++() { while (++gnum_ != end_) { bool included = (hfilter_->get(gnum_) != 0); if (included == inFilter_) break; } return *this; } bool operator!=(const const_iterator& b) const { return gnum_ != b.gnum_ || hfilter_ != b.hfilter_; } bool operator==(const const_iterator& b) const { return !operator!=(b); } }; const_iterator begin() const { return const_iterator(0, main_->Size(), this); } const_iterator end() const { return const_iterator(main_->Size(), main_->Size(), this); } const_iterator beginInverted() const { return const_iterator(0, main_->Size(), this, false); } const_iterator endInverted() const { return const_iterator(main_->Size(), main_->Size(), this, false); } size_t sizeInverted() const { return main_->Size() - size(); } public: // Pointer interface bool operator==(const Filter* b) const { return main_ == b; } bool operator!=(const Filter* b) const { return main_ != b; } HFilter* operator->() { return this; } const HFilter* operator->() const { return this; } HFilter& operator*() { return *this; } const HFilter& operator*() const { return *this; } public: explicit HFilter(Filter* main, const Filter* mask = 0) : main_(main), mask_(mask) {} void clear() { return main_->Fill(0); } void erase(gamenumT gnum) { return main_->Set(gnum, 0); } void insert_or_assign(gamenumT gnum, uint8_t ply) { return main_->Set(gnum, ply + 1); } gamenumT size() const { if (!mask_ || mask_->Count() == mask_->Size()) return main_->Count(); if (main_->Count() == main_->Size()) return mask_->Count(); return static_cast(std::distance(begin(), end())); } /// Returns the number of games included in the main filter size_t mainSize() const { return main_->Count(); } /* Convenience function, behave like: * for (gamenumT gnum = 0; gnum < scidBaseT::numGames(); gnum++) * std:map::insert_or_assign(gnum, 0); */ void includeAll() { return main_->Fill(1); } /* Convenience function, behave like: * auto it = std::map::find(gnum); * if (it == std::map::end()) return 0; * return 1 + it->second; */ byte get(gamenumT gnum) const { byte res = main_->Get(gnum); if (res != 0 && mask_ != 0) res = mask_->Get(gnum); return res; } /* Convenience function, behave like: * if (value == 0) * erase(gnum); * else * insert_or_assign(gnum, value - 1); */ void set(gamenumT gnum, byte value) { return main_->Set(gnum, value); } }; /** * class HFilterInverted - iterate through games excluded from a filter * * This class allow to iterate through games not included in HFilter objects * using STL algorithms and c++11 for-ranged loops. * For example: * for (auto& gnum : HFilterInverted(hfilter_obj)) {} * is equal to: * for (gamenumT gnum = 0, gnum < scidBaseT::numGames(); gnum++) { * if (hfilter_obj->get(gnum) != 0) continue; * } */ class HFilterInverted { const HFilter& hfilter_; public: explicit HFilterInverted(const HFilter& hfilter) : hfilter_(hfilter) { ASSERT(hfilter != 0); } HFilter::const_iterator begin() const { return hfilter_.beginInverted(); } HFilter::const_iterator end() const { return hfilter_.endInverted(); } size_t size() const { return hfilter_.sizeInverted(); } }; #endif chessx-master/dep/scid/code/src/matsig.h0000755000076500000240000002567214666426276017360 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: matsig.h // Material signatures and home-pawn signatures. // // Part of: Scid (Shane's Chess Information Database) // Version: 1.9 // // Notice: Copyright (c) 2000 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// #ifndef SCID_MATSIG_H #define SCID_MATSIG_H #include "common.h" #include #include // Matsigs are 32-bit unsigned ints. We only use 24 bits of this. typedef uint32_t matSigT; // From most significant bits down to least, the matsig layout is: // Bits 22-33: WQ Bits 10-11: BQ // Bits 20-21: WN Bits 08-09: BR // Bits 18-19: WB Bits 06-07: BB // Bits 16-17: WN Bits 04-05: BN // Bits 12-15: WP Bits 00-03: BP // This means that pawn counts from 0 to 8 are possible, but for other // pieces only counts up to 3 are possible. // Shifts: #define SHIFT_BP 0 #define SHIFT_BN 4 #define SHIFT_BB 6 #define SHIFT_BR 8 #define SHIFT_BQ 10 #define SHIFT_WP 12 #define SHIFT_WN 16 #define SHIFT_WB 18 #define SHIFT_WR 20 #define SHIFT_WQ 22 // Masks: // 28 24 20 16 12 8 4 0 #define MASK_BP 0x0000000F // 0- 3: .... .... .... .... .... .... .... 1111 #define MASK_BN 0x00000030 // 4- 5: .... .... .... .... .... .... ..11 .... #define MASK_BB 0x000000C0 // 6- 7: .... .... .... .... .... .... 11.. .... #define MASK_BR 0x00000300 // 8- 9: .... .... .... .... .... ..11 .... .... #define MASK_BQ 0x00000C00 //10-11: .... .... .... .... .... 11.. .... .... #define MASK_WP 0x0000F000 //12-15: .... .... .... .... 1111 .... .... .... #define MASK_WN 0x00030000 //16-17: .... .... .... ..11 .... .... .... .... #define MASK_WB 0x000C0000 //18-19: .... .... .... 11.. .... .... .... .... #define MASK_WR 0x00300000 //20-21: .... .... ..11 .... .... .... .... .... #define MASK_WQ 0x00C00000 //29-31: .... .... 11.. .... .... .... .... .... // The arrays MASK_BY_PIECE and SHIFT_BY_PIECE are useful for setting // matsigs by piece type: const matSigT MASK_BY_PIECE [16] = { 0, // 0: Empty 0, // 1: WK MASK_WQ, // 2: WQ MASK_WR, // 3: WR MASK_WB, // 4: WB MASK_WN, // 5: WN MASK_WP, // 6: WP 0, 0, // 7, 8: Invalid pieces 0, // 9: BK MASK_BQ, // 10: BQ MASK_BR, // 11: BR MASK_BB, // 12: BB MASK_BN, // 13: BN MASK_BP, // 14: BP 0 // 15: Invalid piece }; const uint SHIFT_BY_PIECE[16] = { 0, 0, // 0: Empty, 1: WK SHIFT_WQ, // 2: WQ SHIFT_WR, // 3: WR SHIFT_WB, // 4: WB SHIFT_WN, // 5: WN SHIFT_WP, // 6: WP 0, 0, 0, // 7, 8: Invalid pieces, 9: BK SHIFT_BQ, // 10: BQ SHIFT_BR, // 11: BR SHIFT_BB, // 12: BB SHIFT_BN, // 13: BN SHIFT_BP, // 14: BP 0 // 15: Invalid piece }; // Quick way to flip colors: just switch the upper/lower 12 bits #define MATSIG_FlipColor(x) ((x) >> 12) | (((x) & 0x00000FFF) << 12) // Quick tests for non-zero counts of a piece type: #define MATSIG_Has_WQ(x) ((x) & MASK_WQ) #define MATSIG_Has_BQ(x) ((x) & MASK_BQ) #define MATSIG_Has_WR(x) ((x) & MASK_WR) #define MATSIG_Has_BR(x) ((x) & MASK_BR) #define MATSIG_Has_WB(x) ((x) & MASK_WB) #define MATSIG_Has_BB(x) ((x) & MASK_BB) #define MATSIG_Has_WN(x) ((x) & MASK_WN) #define MATSIG_Has_BN(x) ((x) & MASK_BN) #define MATSIG_Has_WP(x) ((x) & MASK_WP) #define MATSIG_Has_BP(x) ((x) & MASK_BP) #define MATSIG_HasQueens(x) ((x) & (MASK_WQ | MASK_BQ)) #define MATSIG_HasRooks(x) ((x) & (MASK_WR | MASK_BR)) #define MATSIG_HasBishops(x) ((x) & (MASK_WB | MASK_BB)) #define MATSIG_HasKnights(x) ((x) & (MASK_WN | MASK_BN)) #define MATSIG_HasPawns(x) ((x) & (MASK_WP | MASK_BP)) // Macros to extract a particular count: #define MATSIG_Count_WQ(x) (((x) & MASK_WQ) >> SHIFT_WQ) #define MATSIG_Count_BQ(x) (((x) & MASK_BQ) >> SHIFT_BQ) #define MATSIG_Count_WR(x) (((x) & MASK_WR) >> SHIFT_WR) #define MATSIG_Count_BR(x) (((x) & MASK_BR) >> SHIFT_BR) #define MATSIG_Count_WB(x) (((x) & MASK_WB) >> SHIFT_WB) #define MATSIG_Count_BB(x) (((x) & MASK_BB) >> SHIFT_BB) #define MATSIG_Count_WN(x) (((x) & MASK_WN) >> SHIFT_WN) #define MATSIG_Count_BN(x) (((x) & MASK_BN) >> SHIFT_BN) #define MATSIG_Count_WP(x) (((x) & MASK_WP) >> SHIFT_WP) #define MATSIG_Count_BP(x) (((x) & MASK_BP) >> SHIFT_BP) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // matsig_getCount(): // Inline routine to extract a count of a certain piece type. // inline uint matsig_getCount (matSigT m, pieceT p) { return (m & MASK_BY_PIECE[p]) >> SHIFT_BY_PIECE[p]; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // matsig_setCount(): // Inline routine to set a particular count. // inline matSigT matsig_setCount (matSigT m, pieceT p, uint count) { // First we clear the old mask for this piece: m &= ~(MASK_BY_PIECE[p]); // Avoid overflow. if (p != PAWN && count > 3) count = 3; // Now we OR to add the new value in: m |= ((uint) count) << SHIFT_BY_PIECE[p]; return m; } // Common constant matsigs: const matSigT MATSIG_Empty = 0; const matSigT MATSIG_StdStart = ((1 << SHIFT_WQ) | (1 << SHIFT_BQ) | (2 << SHIFT_WR) | (2 << SHIFT_BR) | (2 << SHIFT_WB) | (2 << SHIFT_BB) | (2 << SHIFT_WN) | (2 << SHIFT_BN) | (8 << SHIFT_WP) | (8 << SHIFT_BP)); // // Public functions found in matsig.cpp: // // matsig_makeString: sets s to be a string representation of the sig, std::string matsig_makeString (matSigT matsig); // matsig_isReachable: returns true if a game currently // at a position with the signature , could possibly reach // the signature . This is useful for quick tests for material // searches. For example, if we store the final matsig of every game, // we can speedup a material search by ONLY searching the games that // have matsig_isReachable(searchsig, finalsig) = 1, or have promotions. // Example: if searchsig requires neither side to have queens, but // finalsig for a game shows a WQ (and no promotions), the game could // not possibly match. // If promos is true, only the pawn counts are checked, since other // material could reappear on the board due to a promotion. // If upromo is true, there are underpromotions (to R, B or N) but // if only promos is true, all promotions are to Queens only. bool matsig_isReachable (matSigT mStart, matSigT mTarget, bool promos, bool upromo); // matsig_isReachablePawns: // like matsig_isReachable, but considering pawns only. inline bool matsig_isReachablePawns (matSigT mStart, matSigT mTarget) { if (MATSIG_Count_WP(mStart) < MATSIG_Count_WP(mTarget)) { return false; } if (MATSIG_Count_BP(mStart) < MATSIG_Count_BP(mTarget)) { return false; } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // matsig_Make(): // Make a material sig, given an array of material counts as // stored in a Position. // inline matSigT matsig_Make(const byte* materialCounts) { matSigT m = 0; m |= std::min(3, materialCounts[WQ]) << SHIFT_WQ; m |= std::min(3, materialCounts[WR]) << SHIFT_WR; m |= std::min(3, materialCounts[WB]) << SHIFT_WB; m |= std::min(3, materialCounts[WN]) << SHIFT_WN; m |= matSigT(materialCounts[WP]) << SHIFT_WP; m |= std::min(3, materialCounts[BQ]) << SHIFT_BQ; m |= std::min(3, materialCounts[BR]) << SHIFT_BR; m |= std::min(3, materialCounts[BB]) << SHIFT_BB; m |= std::min(3, materialCounts[BN]) << SHIFT_BN; m |= matSigT(materialCounts[BP]) << SHIFT_BP; return m; } // Common HPSigs: // 0 => no pawns still on their original 2nd/7th rank squares. // 0xFFFF => all 16 pawns still on their original 2nd/7th rank squares. const uint HPSIG_Empty = 0x0; const uint HPSIG_StdStart = 0xFFFF; bool hpSig_PossibleMatch (uint hpSig, const byte * changeList); bool hpSig_Prefix (const byte * changeListA, const byte * changeListB); uint hpSig_Final (const byte * changeList); // hpSig_bitMask[]: used to add or clear bits in an hpSig. // static const uint hpSig_bitMask [16] = { // a2 to h2: 0x8000, 0x4000, 0x2000, 0x1000, 0x0800, 0x0400, 0x0200, 0x0100, // a7 to h7: 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; inline uint hpSig_AddPawn (uint hpSig, colorT color, fyleT fyle) { ASSERT (color == WHITE || color == BLACK); ASSERT (fyle <= H_FYLE); uint val = (uint) fyle; if (color == BLACK) val += 8; return hpSig | hpSig_bitMask [val]; } inline uint hpSig_ClearPawn (uint hpSig, colorT color, fyleT fyle) { ASSERT (color == WHITE || color == BLACK); ASSERT (fyle <= H_FYLE); uint val = (uint) fyle; if (color == BLACK) val += 8; return hpSig & ~(hpSig_bitMask [val]); } /** * Creates a 16-bits bitmap of the missing pawns in the home ranks. * * Used to speed up the searches of positions with the same pawn structure. * @returns a std::pair containing the bitmap and the number of moved pawns. */ inline std::pair hpSig_make(const pieceT* board) { int hpSig = 0; int nMoved = 0; const pieceT* b = board + A2; // clang-format off if (*b != WP) { hpSig |= 0x8000; ++nMoved; } b++; /* a2 */ if (*b != WP) { hpSig |= 0x4000; ++nMoved; } b++; /* b2 */ if (*b != WP) { hpSig |= 0x2000; ++nMoved; } b++; /* c2 */ if (*b != WP) { hpSig |= 0x1000; ++nMoved; } b++; /* d2 */ if (*b != WP) { hpSig |= 0x0800; ++nMoved; } b++; /* e2 */ if (*b != WP) { hpSig |= 0x0400; ++nMoved; } b++; /* f2 */ if (*b != WP) { hpSig |= 0x0200; ++nMoved; } b++; /* g2 */ if (*b != WP) { hpSig |= 0x0100; ++nMoved; } /* h2 */ b = board + A7; if (*b != BP) { hpSig |= 0x0080; ++nMoved; } b++; /* a7 */ if (*b != BP) { hpSig |= 0x0040; ++nMoved; } b++; /* b7 */ if (*b != BP) { hpSig |= 0x0020; ++nMoved; } b++; /* c7 */ if (*b != BP) { hpSig |= 0x0010; ++nMoved; } b++; /* d7 */ if (*b != BP) { hpSig |= 0x0008; ++nMoved; } b++; /* e7 */ if (*b != BP) { hpSig |= 0x0004; ++nMoved; } b++; /* f7 */ if (*b != BP) { hpSig |= 0x0002; ++nMoved; } b++; /* g7 */ if (*b != BP) { hpSig |= 0x0001; ++nMoved; } /* h7 */ // clang-format on return {static_cast(hpSig), static_cast(nMoved)}; } inline bool hpSig_match(int hpSig, int nMoved, const byte* changeList) { // The first byte of a changeList is the length (in halfbytes) of the // list, which can be any value from 0 to 16 inclusive. if (*changeList == 16 && nMoved == 16) return true; if (*changeList++ < nMoved) return false; int sig = 0; for (int i = 0, n = nMoved / 2; i < n; ++i) { sig |= 1 << (*changeList >> 4); sig |= 1 << (*changeList++ & 0x0F); } if (nMoved & 1) sig |= 1 << (*changeList >> 4); return sig == hpSig; } #endif ////////////////////////////////////////////////////////////////////// // EOF: matsig.h ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/movetree.h0000755000076500000240000001456614666426276017722 0ustar jensstaff/* * Copyright (C) 2017 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . * */ /** @file * A tree graph of moves representing a game. */ #ifndef SCID_MOVETREE_H #define SCID_MOVETREE_H #include "common.h" #include "movelist.h" #include enum markerT : byte { NO_MARKER = 0, START_MARKER = 1, END_MARKER = 2 }; // MAX_NAGS is the maximum number of NAGs (annotation symbols) a single // move can have: #define MAX_NAGS 8 // This class creates a tree graph of moves representing a game. // // For each node there are two edges: *next* (to the next move) and *varChild* // (to an alternative line). For example the graph for the move sequence // "1.d4 (1.e4 e5 ( 1...c5)) (1.c4) 1...d5 2.c4" is: // clang-format off // (START_MARKER, pgn_1) --next-> (d4, pgn_2) --next-> (d5, pgn_10) --next-> (c4, pgn_11) --next-> (END_MARKER, none) // | // |-child-> (START_MARKER, pgn_3) --next-> (e4, pgn_4) --next-> (e5, pgn_5) --next-> (END_MARKER, none) // | | // | |-child-> (START_MARKER, pgn_6) --next-> (c5, pgn_7) --next-> (END_MARKER, none) // | // |-child-> (START_MARKER, pgn_8) --next-> (c4, pgn_9) --next-> (END_MARKER, none) // clang-format on // The graph illustrates also that: // - each variation starts and ends with two nodes containing a START_MARKER // and a END_MARKER instead of a move. This implies that *next* never points // to a START_MARKER node and *varChild* always point to a START_MARKER. // - multiple variations are stored as a list of children. In the example there // are two alternatives to "1.d4": "1.e4" is stored as direct child of "1.d4", // instead "1.c4" is stored as the child of the START_MARKER of "1.e4". // - when represented as a PGN string, the moves creates a sequence that can be // counted (each new variation is counted as an additional move). This is used // to specify a location in the game. // struct moveT { simpleMoveT moveData; // piece moving, target square etc moveT* prev; moveT* next; moveT* varChild; char san[10]; // SAN representation of move markerT marker; // can be NO_MARKER, START_MARKER or END_MARKER byte numVariations; byte nagCount; byte nags[MAX_NAGS]; std::string comment; void clear() { moveData = simpleMoveT(); prev = nullptr; next = nullptr; varChild = nullptr; std::fill_n(san, sizeof(san), '\0'); marker = NO_MARKER; numVariations = 0; nagCount = 0; std::fill_n(nags, sizeof(nags), 0); comment.clear(); } bool startMarker() const { return marker == START_MARKER; } bool endMarker() const { return marker == END_MARKER; } bool isNull() const { return moveData.isNullMove(); } template moveT* cloneLine(moveT* parent, TNew newMove) const { const moveT* orig = this; moveT* top = newMove(); *top = *orig; top->prev = parent; parent = top; if (orig->varChild) { auto root = parent->startMarker() ? parent->prev : parent; parent->varChild = orig->varChild->cloneLine(root, newMove); } while (orig->next) { orig = orig->next; auto copy = newMove(); *copy = *orig; parent->setNext(copy); parent = copy; if (orig->varChild) { auto root = parent->startMarker() ? parent->prev : parent; parent->varChild = orig->varChild->cloneLine(root, newMove); } } return top; } void swapLine(moveT& move) { ASSERT(prev && move.prev); ASSERT(!startMarker() && !move.startMarker()); ASSERT(!endMarker() && !move.endMarker()); // Swap lines auto swap_tmp = move.prev; prev->setNext(&move); swap_tmp->setNext(this); // Swap children std::swap(varChild, move.varChild); std::swap(numVariations, move.numVariations); auto updateParentLink = [](moveT& parent) { for (auto tmp = parent.varChild; tmp; tmp = tmp->varChild) { tmp->prev = &parent; } }; updateParentLink(*this); updateParentLink(move); } const moveT* getPrevMove() const { if (!startMarker() && !prev->startMarker()) return prev; auto root = getParent().first; return root ? root->getPrevMove() : nullptr; } std::pair getParent() const { const moveT* varStart = this; while (!varStart->startMarker()) { varStart = varStart->prev; } return {varStart->prev, varStart}; } std::pair getParent() { moveT* varStart = this; while (!varStart->startMarker()) { varStart = varStart->prev; } return {varStart->prev, varStart}; } moveT* nextMoveInPGN() const { if (endMarker()) { auto parent = getParent(); auto nextVar = parent.second->varChild; return (nextVar) ? nextVar : (parent.first) ? parent.first->next : nullptr; } return (startMarker() || !varChild) ? next : varChild; } void setNext(moveT* move) { ASSERT(move); this->next = move; move->prev = this; } void insertChild(moveT* varStart, int pos) { ASSERT(!this->startMarker() && !this->endMarker()); ASSERT(this != varStart); ASSERT(varStart->startMarker()); auto parent = this; for (; parent->varChild && pos != 0; --pos) { parent = parent->varChild; } varStart->varChild = varStart; std::swap(parent->varChild, varStart->varChild); varStart->prev = this; ++numVariations; } void appendChild(moveT* varStart) { insertChild(varStart, -1); } void detachChild(moveT* varStart) { ASSERT(this != varStart); ASSERT(varStart->startMarker()); auto parent = this; while (parent->varChild != varStart) { parent = parent->varChild; } std::swap(parent->varChild, varStart->varChild); --numVariations; }; }; #endif // SCID_MOVETREE_H chessx-master/dep/scid/code/src/namebase.h0000755000076500000240000001751114666426276017640 0ustar jensstaff/* * Copyright (C) 2014-2017 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ #ifndef SCID_NAMEBASE_H #define SCID_NAMEBASE_H #include "common.h" #include "misc.h" #include #include #include #include /** * This class stores the database's names (players, events, sites and rounds). * Assigns a idNumberT (which will be used as reference) to each name. */ class NameBase { std::vector > names_[NUM_NAME_TYPES]; std::vector eloV_; struct idxCmp { bool operator()(const char* str1, const char* str2) const { // *** Compatibility *** // Older code used a custom StrTree class with a peculiar sorting: // - the first char was interpreted as an unsigned char; // - the remaining part was compared with the function // strComapare(), // which converts the chars to ints, and is not consistent with // the standard function strcmp(). // The old StrTree class did also have unpredictable behaviors when // fed with names not sorted according to that criteria, for example // it could create Namebase objects with duplicate entries. // *** if (*str1 == *str2) return strCompare(str1, str2) < 0; return static_cast(*str1) < static_cast(*str2); } }; std::map idx_[NUM_NAME_TYPES]; public: /** * A NameBase stores the max ELO for each player. This functions updates * the max ELO of a player if it's greater than the previous one. * @param id: a valid idNumberT corresponding to a NAME_PLAYER name. * @param elo: the ELO. */ void AddElo(idNumberT id, eloT elo) { ASSERT(id < GetNumNames(NAME_PLAYER)); if (elo > eloV_[id]) eloV_[id] = elo; } /** * Add a name (string) to the NameBase. * If the name already exists the corresponding ID is returned. * @param nt: @e nameT type of the name to add. * @param name: the name to add. * @param MAX_LEN: the max length for names of type @e nt * @param MAX_ID: the max ID allowed for names of type @e nt * @returns * - on success, a @e std::pair containing OK and the ID. * - on failure, a @e std::pair containing an error code and 0. */ std::pair addName(nameT nt, const char* name, size_t MAX_LEN, idNumberT MAX_ID) { ASSERT(IsValidNameType(nt) && name != NULL); auto exists = idx_[nt].lower_bound(name); if (exists != idx_[nt].end() && !idx_[nt].key_comp()(name, exists->first)) return std::make_pair(OK, exists->second); const size_t nameLen = strlen(name); if (nameLen > MAX_LEN) return std::make_pair(ERROR_NameTooLong, 0); if (names_[nt].size() >= MAX_ID) return std::make_pair(ERROR_NameLimit, 0); char* buf = new char[nameLen + 1]; std::copy_n(name, nameLen + 1, buf); idNumberT newID = static_cast(names_[nt].size()); names_[nt].emplace_back(buf); idx_[nt].emplace_hint(exists, buf, newID); if (nt == NAME_PLAYER) eloV_.push_back(0); return std::make_pair(OK, newID); } /** * Frees memory, leaving the object empty. */ void Clear() { *this = NameBase(); } /** * @returns references to the NameBase's containers. * (must be used only to read names from files) */ std::tuple getData() { return std::tuple( idx_, names_, eloV_); } /** * @param id: a valid idNumberT corresponding to a NAME_PLAYER name. * @returns the max ELO of a player. */ eloT GetElo(idNumberT id) const { ASSERT(id < GetNumNames(NAME_PLAYER)); return eloV_[id]; } /** * Get the first few matches of a name prefix. * @param nt: @e nameT type of the name to be searched. * @param str: name prefix be searched. * @param maxMatches: the max number of ID to return * @returns a vector containing the ID of the matching names. */ std::vector getFirstMatches(nameT nt, const char* str, size_t maxMatches) const { ASSERT(IsValidNameType(nt) && str != NULL); std::vector res; size_t len = strlen(str); for (auto it = idx_[nt].lower_bound(str); it != idx_[nt].end() && res.size() < maxMatches; ++it) { const char* s = it->first; if (strlen(s) < len || !std::equal(str, str + len, s)) break; res.emplace_back(it->second); } return res; } /** * Retrieve a name. * @param nt: the valid @e nameT type of the name to retrieve. * @param id: the valid ID of the name to retrieve. * @returns the name corresponding to @e id. */ const char* GetName(nameT nt, idNumberT id) const { ASSERT(IsValidNameType(nt) && id < GetNumNames(nt)); return names_[nt][id].get(); } /** * @returns a reference to a container with all the names and IDs (given as * std::pair). */ const decltype(idx_) & getNames() const { return idx_; } /** * @param nt: a valid @e nameT type. * @returns the first invalid idNumberT (which is equal to the number of * names stored). */ idNumberT GetNumNames(nameT nt) const { ASSERT(IsValidNameType(nt)); return static_cast(names_[nt].size()); } /** * Finds an exact full, case-sensitive name. * @param nt: @e nameT type of the name to be searched. * @param str: name to be be searched. * @param[out] idPtr: pointer which will receive the ID of the name. * @returns OK or ERROR_NameNotFound if the name does not exists. */ errorT FindExactName(nameT nt, const char* str, idNumberT* idPtr) const { ASSERT(IsValidNameType(nt) && str != NULL && idPtr != NULL); auto it = idx_[nt].find(str); if (it != idx_[nt].end()) { *idPtr = (*it).second; return OK; } return ERROR_NameNotFound; } /** * For every name generates a 32bit hash with the first 4 chars. * @param nt: @e nameT type of the names. * @returns a vector containing the hashes. */ std::vector generateHashMap(nameT nt) const { std::vector res(names_[nt].size()); std::transform(names_[nt].begin(), names_[nt].end(), res.begin(), [](const std::unique_ptr& name) { return strStartHash(name.get()); }); return res; } /** * Validate a @e nameT type. * @param nt: @e nameT type to be validated. * @returns true if @e nt is valid. */ static bool IsValidNameType(nameT nt) { return (nt < NUM_NAME_TYPES); } /** * Match a string to a nameT. * To match, the string should be a prefix of "player", "event", "site" or * "round", or be a superstring of it, e.g. "player ...." * @param str: the string to be matched. * @returns a valid nameT, or NAME_INVALID. */ static nameT NameTypeFromString(const char* str) { if (*str == '\0') return NAME_INVALID; if (strIsAlphaPrefix(str, "player")) return NAME_PLAYER; if (strIsAlphaPrefix(str, "event")) return NAME_EVENT; if (strIsAlphaPrefix(str, "site")) return NAME_SITE; if (strIsAlphaPrefix(str, "round")) return NAME_ROUND; if (strIsAlphaPrefix("player", str)) return NAME_PLAYER; if (strIsAlphaPrefix("event", str)) return NAME_EVENT; if (strIsAlphaPrefix("site", str)) return NAME_SITE; if (strIsAlphaPrefix("round", str)) return NAME_ROUND; return NAME_INVALID; } }; #endif // SCID_NAMEBASE_H chessx-master/dep/scid/code/src/nagtext.h0000755000076500000240000003342114666426276017535 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: nagtext.h // Translationtable for NAG values to text // // Part of: Scid (Shane's Chess Information Database) // Version: 3.6 // // Notice: Copyright (c) 2000-2003 Shane Hudson. All rights reserved. // // Author: A. Wagner // // ////////////////////////////////////////////////////////////////////// // 7-bit rewritten // following http://www.exeterchessclub.org.uk/nags.html const char * evalNagsRegular [] = { "", // 0 null annotation "!", // $1 1 good move (traditional "!") "?", // $2 2 poor move (traditional "?") "!!", // $3 3 very good move (traditional "!!") "??", // $4 4 very poor move (traditional "??") "!?", // $5 5 speculative move (traditional "!?") "?!", // $6 6 questionable move (traditional "?!") "forced", // $7 7 forced move (all others lose quickly) "□", // $8 8 singular move (no reasonable alternatives) "worst", // $9 9 worst move "=", // $10 10 drawish position "=, quiet", // $11 11 equal chances, quiet position (DR: traditional =) "↹", // $12 12 equal chances, active position (DR: ECO ->/<-) "~", // $13 13 unclear position (DR: emerging &) "+=", // $14 14 White has a slight advantage (DR: +=) "=+", // $15 15 Black has a slight advantage (DR: =+) "+/-", // $16 16 White has a moderate advantage (DR: +/-) "-/+", // $17 17 Black has a moderate advantage (DR: -/+) "+-", // $18 18 White has a decisive advantage (DR: +-) "-+", // $19 19 Black has a decisive advantage (DR: -+) "+--", // $20 20 White has a crushing advantage (Black should resign) (DR: +--) "--+", // $21 21 Black has a crushing advantage (White should resign) (DR: --+) "⊙", // $22 22 White is in zugzwang (DR: zz) "⊙", // $23 23 Black is in zugzwang (DR: zz) "◯", // $24 24 White has a slight space advantage "◯", // $25 25 Black has a slight space advantage "◯◯", // $26 26 White has a moderate space advantage (DR: O) "◯◯", // $27 27 Black has a moderate space advantage (DR: O) "◯◯◯", // $28 28 White has a decisive space advantage "◯◯◯", // $29 29 Black has a decisive space advantage "↻", // $30 30 White has a slight time (development) advantage "↺", // $31 31 Black has a slight time (development) advantage "↻↻", // $32 32 White has a moderate time (development) advantage (DR: @) "↺↺", // $33 33 Black has a moderate time (development) advantage (DR: @) "↻↻↻", // $34 34 White has a decisive time (development) advantage "↺↺↺", // $35 35 Black has a decisive time (development) advantage "↑", // $36 36 White has the initiative (DR: ^) "↓", // $37 37 Black has the initiative (DR: ^) "⇑", // $38 38 White has a lasting initiative "⇓", // $39 39 Black has a lasting initiative "→", // $40 40 White has the attack (DR: ->) "←", // $41 41 Black has the attack (DR: ->) "&/-", // $42 42 White has insufficient compensation for material deficit "&/+", // $43 43 Black has insufficient compensation for material deficit "=/&", // $44 44 White has sufficient compensation for material deficit (DR: =/&) "=/&", // $45 45 Black has sufficient compensation for material deficit (DR: =/&) "+/&", // $46 46 White has more than adequate compensation for material deficit "-/&", // $47 47 Black has more than adequate compensation for material deficit "⊞", // $48 48 White has a slight center control advantage "⊞", // $49 49 Black has a slight center control advantage "⊞⊞", // $50 50 White has a moderate center control advantage (DR: #) "⊞⊞", // $51 51 Black has a moderate center control advantage (DR: #) "⊞⊞⊞", // $52 52 White has a decisive center control advantage "⊞⊞⊞", // $53 53 Black has a decisive center control advantage "⟩", // $54 54 White has a slight kingside control advantage "⟩", // $55 55 Black has a slight kingside control advantage "⟫", // $56 56 White has a moderate kingside control advantage (DR: >>) "⟫", // $57 57 Black has a moderate kingside control advantage (DR: >>) "⋙", // $58 58 White has a decisive kingside control advantage "⋙", // $59 59 Black has a decisive kingside control advantage "⟨", // $60 60 White has a slight queenside control advantage "⟨", // $61 61 Black has a slight queenside control advantage "⟪", // $62 62 White has a moderate queenside control advantage (DR: <<) "⟪", // $63 63 Black has a moderate queenside control advantage (DR: <<) "⋘", // $64 64 White has a decisive queenside control advantage "⋘", // $65 65 Black has a decisive queenside control advantage "$66", // $66 66 White has a vulnerable first rank "$67", // $67 67 Black has a vulnerable first rank "$68", // $68 68 White has a well protected first rank "$69", // $69 69 Black has a well protected first rank "$70", // $70 70 White has a poorly protected king "$71", // $71 71 Black has a poorly protected king "$72", // $72 72 White has a well protected king "$73", // $73 73 Black has a well protected king "$74", // $74 74 White has a poorly placed king "$75", // $75 75 Black has a poorly placed king "$76", // $76 76 White has a well placed king "$77", // $77 77 Black has a well placed king "$78", // $78 78 White has a very weak pawn structure "$79", // $79 79 Black has a very weak pawn structure "$80", // $80 80 White has a moderately weak pawn structure (DR: x a5) "$81", // $81 81 Black has a moderately weak pawn structure (DR: x a5) "$82", // $82 82 White has a moderately strong pawn structure "$83", // $83 83 Black has a moderately strong pawn structure "$84", // $84 84 White has a very strong pawn structure "$85", // $85 85 Black has a very strong pawn structure "$86", // $86 86 White has poor knight placement "$87", // $87 87 Black has poor knight placement "$88", // $88 88 White has good knight placement "$89", // $89 89 Black has good knight placement "$90", // $90 90 White has poor bishop placement "$91", // $91 91 Black has poor bishop placement "↗", // $92 92 White has good bishop placement (DR: diagonal //) "↖", // $93 93 Black has good bishop placement "$94", // $94 94 White has poor rook placement "$95", // $95 95 Black has poor rook placement "⇈", // $96 96 White has good rook placement (DR: rank <=> file ||) "⇊", // $97 97 Black has good rook placement "$98", // $98 98 White has poor queen placement "$99", // $99 99 Black has poor queen placement "$100", // $100 100 White has good queen placement "$101", // $101 101 Black has good queen placement "$102", // $102 102 White has poor piece coordination "$103", // $103 103 Black has poor piece coordination "$104", // $104 104 White has good piece coordination "$105", // $105 105 Black has good piece coordination "$106", // $106 106 White has played the opening very poorly "$107", // $107 107 Black has played the opening very poorly "$108", // $108 108 White has played the opening poorly "$109", // $109 109 Black has played the opening poorly "$110", // $110 110 White has played the opening well "$111", // $111 111 Black has played the opening well "$112", // $112 112 White has played the opening very well "$113", // $113 113 Black has played the opening very well "$114", // $114 114 White has played the middlegame very poorly "$115", // $115 115 Black has played the middlegame very poorly "$116", // $116 116 White has played the middlegame poorly "$117", // $117 117 Black has played the middlegame poorly "$118", // $118 118 White has played the middlegame well "$119", // $119 119 Black has played the middlegame well "$120", // $120 120 White has played the middlegame very well "$121", // $121 121 Black has played the middlegame very well "$122", // $122 122 White has played the ending very poorly "$123", // $123 123 Black has played the ending very poorly "$124", // $124 124 White has played the ending poorly "$125", // $125 125 Black has played the ending poorly "$126", // $126 126 White has played the ending well "$127", // $127 127 Black has played the ending well "$128", // $128 128 White has played the ending very well "$129", // $129 129 Black has played the ending very well "⇄", // $130 130 White has slight counterplay "⇆", // $131 131 Black has slight counterplay "⇄⇄", // $132 132 White has moderate counterplay (DR: ->/<-) "⇆⇆", // $133 133 Black has moderate counterplay "⇄⇄⇄", // $134 134 White has decisive counterplay "⇆⇆⇆", // $135 135 Black has decisive counterplay "⊕", // $136 136 White has moderate time control pressure "⊖", // $137 137 Black has moderate time control pressure "⊕⊕", // $138 138 White has severe time control pressure "⊖⊖", // $139 139 Black has severe time control pressure "△", // $140 with the idea of "$141", // $141 "⌓", // $142 better is "$143", // $143 "R", // $144 various moves "RR", // $145 editorial comment "N", // $146 Novelty "×", // $147 weak square "⊥", // $148 endgame "⟺", // $149 file "⇗", // $150 diagonal "◫", // $151 bishop pair "$152", // $152 "◨", // $153 opposite coloured bishops "⊶", // $154 bishops of the same colour "$155", // $155 "$156", // $156 "$157", // $157 "$158", // $158 "$159", // $159 "$160", // $160 "$161", // $161 "$162", // $162 "$163", // $163 "$164", // $164 "$165", // $165 "$166", // $166 "$167", // $167 "$168", // $168 "$169", // $169 "$170", // $170 "$171", // $171 "$172", // $172 "$173", // $173 "$174", // $174 "$175", // $175 "$176", // $176 "$177", // $177 "$178", // $178 "$179", // $179 "$180", // $180 "$181", // $181 "$182", // $182 "$183", // $183 "$184", // $184 "$185", // $185 "$186", // $186 "$187", // $187 "$188", // $188 "$189", // $189 "ǁ", // $190 etc. "⡁", // $191 doubled pawn "⚯", // $192 separated pawn "⚮", // $193 connected pawn "$194", // $194 "$195", // $195 "$196", // $196 "$197", // $197 "$198", // $198 "$199", // $199 "$200", // $200 "D", // $201 Diagram "$202", // $202 "$203", // $203 "$204", // $204 "$205", // $205 "$206", // $206 "$207", // $207 "$208", // $208 "$209", // $209 "—", // $210 see "#", // $211 mate "⚨", // $212 passed pawn "$213", // $213 more pawns "⌊", // $214 with "⌋", // $215 without "$216", // $216 "$217", // $217 "$218", // $218 "$219", // $219 "$220", // $220 "$221", // $221 "$222", // $222 "$223", // $223 "$224" // $224 }; //-------------------- UTF-8 Edition -------------------- // to follow chessx-master/dep/scid/code/src/bytebuf.h0000755000076500000240000003001614666426276017520 0ustar jensstaff/* * Copyright (C) 2019 Fulvio Benini. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH * THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** @file * Defines a ByteBuffer class which will act like a std::string_view. * The caller must ensure that a ByteBuffer object does not outlive the * pointed-to data. */ #pragma once #include "board_def.h" #include "error.h" #include #include #include #include /** * The Tag section is a list of variable length records: * tag_length: 1-byte * tag name: [0:240] bytes * value_length: 1-byte * value: [0:255] bytes * The section is terminated with 1-byte with value 0, meaning that un empty * tag name cannot be stored. * Some common tags are encoded in one byte, using a tag_length value over 240 * and a tag name of 0 bytes. */ constexpr size_t MAX_TAG_LEN = 240; constexpr std::string_view commonTags[] = { // 241, 242: Country "WhiteCountry", "BlackCountry", // 243: Annotator "Annotator", // 244: PlyCount "PlyCount", // 245: EventDate (plain text encoding) "EventDate", // 246, 247: Opening, Variation "Opening", "Variation", // 248-250: Setup and Source "Setup", "Source", "SetUp" // 252-254: spare for future use // 255: Reserved for compact EventDate encoding }; template void encodeTags(const SourceT& tagList, DestT& dest) { for (auto& tag : tagList) { if (tag.first.length() == 0) continue; // Cannot store empty tag names const auto it = std::find(commonTags, std::end(commonTags), tag.first); if (it != std::end(commonTags)) { // Common tags are stored with just their 1-byte value [241:250] const auto tagnum = std::distance(commonTags, it) + MAX_TAG_LEN + 1; dest.emplace_back(static_cast(tagnum)); } else { // Other tags are stored as 1-byte length [1:240] + the tag name. const auto tag_name = tag.first.data(); const auto length = std::min(tag.first.length(), MAX_TAG_LEN); dest.emplace_back(static_cast(length)); dest.insert(dest.end(), tag_name, tag_name + length); } // The value is stored as 1-byte length [0:255] + the data. const auto value = tag.second.data(); const auto valueLen = std::min(tag.second.length(), 255); dest.emplace_back(static_cast(valueLen)); dest.insert(dest.end(), value, value + valueLen); } dest.emplace_back(0); } /** * The StartBoard section starts with a byte containing three flags: * 0-bit: true if the game doesn't start with the standard board * 1-bit: true if there are pawn to queen promotions * 2-bit: true if there are pawn to non-queen promotions. * If the 0-bit is true, the byte is followed by a null terminated string * containing the FEN of the start position. */ template void encodeStartBoard(bool promoFlag, bool underpromoFlag, const char* FEN, DestT& dest) { char flags = 0; if (FEN) { flags += 1; } if (promoFlag) { flags += 2; } if (underpromoFlag) { flags += 4; } dest.emplace_back(flags); if (FEN) { const auto len = std::strlen(FEN) + 1; // Include the null char dest.insert(dest.end(), FEN, FEN + len); } } class ByteBuffer { const unsigned char* data_; const unsigned char* const end_; public: ByteBuffer(const unsigned char* data, size_t length) : data_(data), end_(data + length) { assert(data_ || data_ == end_); } explicit operator bool() const { return data_ != end_; } /// Decodes the tag pairs not stored into the index. /// @param fn: a function that should accept 2 parameters /// (string_view tag_name, string_view tag_value) /// and that will be called for each tag pair. template errorT decodeTags(FuncT fn) { if (data_ == end_) return ERROR_BufferRead; auto it = data_; for (;;) { const auto tagLen = *it++; if (tagLen == 0) { data_ = it; return OK; // Reached the end of the tags section } const char* tag = nullptr; size_t tagID = 0; if (tagLen > MAX_TAG_LEN) { // A common tag name, not explicitly stored tagID = tagLen - MAX_TAG_LEN - 1; } else { tag = reinterpret_cast(it); it += tagLen; } if (it >= end_) return ERROR_Decode; // 255 was a special 3-bytes encoding of EventDate used in SCID2 const auto valueLen = (tagLen != 255) ? *it++ : 3; const char* value = reinterpret_cast(it); it += valueLen; if (it >= end_) return ERROR_Decode; if (tag) { fn(std::string_view(tag, tagLen), std::string_view(value, valueLen)); } else if (tagID < 10) { fn(commonTags[tagID], std::string_view(value, valueLen)); } } } /// Decodes the start position. /// @returns OK on success and the FEN of the start position (nullptr for /// the standard starting position). /// To decode the moves the correct index should be assigned to each piece: /// they are assigned from left to right, but the king should always have /// index 0. It is therefore swapped with the piece occupying the index 0. /// For example with "rnb1k2Q/1p5p/p7/4p3/4q3/8/PPP2R1P/2K5 b" the black /// rook on A8 gets index 3, the black night on B8 gets index 1 .... and the /// white queen on H8 gets index 6, the pawn on A2 gets index 1 ... std::pair decodeStartBoard() { if (data_ == end_) return {ERROR_Decode, nullptr}; const auto flags = *data_++; if ((flags & 1) == 0) return {OK, nullptr}; if (const auto FEN = GetTerminatedString()) return {OK, FEN}; return {ERROR_Decode, nullptr}; } /// Reads a null-terminated string from the buffer. const char* GetTerminatedString() { const char* res = reinterpret_cast(data_); data_ = std::find(data_, end_, 0); if (data_ == end_) return nullptr; ++data_; // skip the null char return res; } /// Extract the next move. /// @returns a std::pair containing OK and the move value. /// Returns ERROR_EndOfMoveList when the end of the game is /// reached, an error otherwise. template std::pair nextMove(int varDepth, MoveFn acceptMove, CommentFn commentMarker, VariationFn changeVar, NagFn addNag) { // The king has always index 0 and only 11 possible moves (8 destination // squares, 2 castle moves and the null move). The unused codes 11-15 // represent special markers for nags, comments and variations. // Note: 2-bytes queen moves use the second byte as (64 + destination // square) to avoid interferences with these markers. However the byte // immediatly after the ENCODE_NAG can have any possible value. enum { ENCODE_NAG = 11, ENCODE_COMMENT, ENCODE_START_MARKER, ENCODE_END_MARKER, ENCODE_END_GAME }; auto it = data_; for (; it != end_; ++it) { switch (*it) { case ENCODE_NAG: if (++it == end_) { return {ERROR_Decode, 0}; // ERROR: missing nag } if (!addNag(*it)) { return {ERROR_Decode, 0}; // ERROR: marker decoding } continue; case ENCODE_COMMENT: commentMarker(); continue; case ENCODE_START_MARKER: ++varDepth; if (!changeVar(true)) { return {ERROR_Decode, 0}; // ERROR: variation } continue; case ENCODE_END_MARKER: if (varDepth == 0) { return {ERROR_Decode, 0}; // ERROR: end marker in main line } --varDepth; if (!changeVar(false)) { return {ERROR_Decode, 0}; // ERROR: variation } continue; case ENCODE_END_GAME: if (varDepth != 0) { return {ERROR_Decode, 0}; // ERROR: unexpected end of game } data_ = ++it; return {ERROR_EndOfMoveList, 0}; // SUCCESS: end of game default: if (acceptMove(varDepth)) { data_ = it; return {OK, *data_++}; // SUCCESS } } } return {ERROR_Decode, 0}; // ERROR: missing ENCODE_END_GAME } /// Find the next move in the current line. /// Ignore variations, comments and nags. std::pair nextLineMove() { return nextMove( 0, [](auto varDepth) { return varDepth == 0; }, [] {}, // Ignore comments [](auto) { return true; }, // Ignore variations [](auto) { return true; } // Ignore nags ); } /// Decode a move encoded in SCID4 format. /// Excluding queens, the other chess pieces cannot reach more than 16 /// target squares from any given position. This allow to store the target /// square of a move into 4 bits, as an index of all the reachable squares. /// @param movingPiece: the type (PAWN, BISHOP, etc.) of the piece to move. /// @param from: the square where is the piece to move. /// @param moveCode: the SCID4 encoding of the move (a 0-15 value). /// @returns a pair containing the destination square and the new type of /// the piece for promotions (INVALID_PIECE for normal moves). /// Special moves are returned as: /// - castle kingside: {from, KING} /// - castle queenside: {from, QUEEN} /// - null move: {from, PAWN} /// On error returns an invalid square (<0 or >63) or {from, INVALID_PIECE}. template std::pair decodeMove(pieceT movingPiece, squareT from, unsigned char moveCode) { moveCode &= 0x0F; switch (movingPiece) { case PAWN: { static const pieceT promoPiece[] = { INVALID_PIECE, INVALID_PIECE, INVALID_PIECE, QUEEN, QUEEN, QUEEN, ROOK, ROOK, ROOK, BISHOP, BISHOP, BISHOP, KNIGHT, KNIGHT, KNIGHT, INVALID_PIECE}; static const int8_t sqdiff[] = {7, 8, 9, 7, 8, 9, 7, 8, 9, 7, 8, 9, 7, 8, 9, 16}; int to = (toMove == WHITE) ? from + sqdiff[moveCode] : from - sqdiff[moveCode]; return {to, promoPiece[moveCode]}; } case BISHOP: { int fylediff = square_Fyle(moveCode) - square_Fyle(from); int to = (moveCode >= 8) ? from - 7 * fylediff : from + 9 * fylediff; return {to, INVALID_PIECE}; } case KNIGHT: { static const int8_t sqdiff[] = {0, -17, -15, -10, -6, 6, 10, 15, 17, 0, 0, 0, 0, 0, 0, 0}; return {from + sqdiff[moveCode], INVALID_PIECE}; } case QUEEN: if (moveCode == square_Fyle(from)) { // 2 BYTES MOVE int to = (data_ != end_) ? *data_++ : 0; return {to - 64, INVALID_PIECE}; } /* FALLTHRU */ case ROOK: { int to = (moveCode >= 8) // a vertical move ? square_Make(square_Fyle(from), (moveCode - 8)) : square_Make(moveCode, square_Rank(from)); return {to, INVALID_PIECE}; } case KING: if (moveCode == 0) // NULL MOVE return {from, PAWN}; if (moveCode <= 8) { static const int8_t sqdiff[] = {0, -9, -8, -7, -1, 1, 7, 8, 9}; return {from + sqdiff[moveCode], INVALID_PIECE}; } if (moveCode == 9) // CASTLE QUEENSIDE return {from, QUEEN}; if (moveCode == 10) // CASTLE KINGSIDE return {from, KING}; } return {from, INVALID_PIECE}; // decode error } }; chessx-master/dep/scid/code/src/matsig.cpp0000755000076500000240000001476314666426276017712 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: matsig.cpp // Material signature routines // // Part of: Scid (Shane's Chess Information Database) // Version: 3.3 // // Notice: Copyright (c) 1999-2002 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// // A matsig (material signature) is a count of material by piece type, // compacted into three bytes. Because it is compacted, there are limits // that a game with an unusual number of promotions might break. // The maximum count for a non-pawn piece is three. #include "matsig.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // matsig_makeString(): Make a string representation of a matsig. std::string matsig_makeString (matSigT m) { std::string s; s.reserve(32); uint i; for (i=0; i < MATSIG_Count_WQ(m); i++) { s+= 'Q'; } for (i=0; i < MATSIG_Count_WR(m); i++) { s+= 'R'; } for (i=0; i < MATSIG_Count_WB(m); i++) { s+= 'B'; } for (i=0; i < MATSIG_Count_WN(m); i++) { s+= 'N'; } uint wp = MATSIG_Count_WP(m); if (wp > 0) s+= (wp + '0'); s+= ':'; for (i=0; i < MATSIG_Count_BQ(m); i++) { s+= 'Q'; } for (i=0; i < MATSIG_Count_BR(m); i++) { s+= 'R'; } for (i=0; i < MATSIG_Count_BB(m); i++) { s+= 'B'; } for (i=0; i < MATSIG_Count_BN(m); i++) { s+= 'N'; } uint bp = MATSIG_Count_BP(m); if (bp > 0) s+= (bp + '0'); return s; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // matsig_isReachable(): // Return 1 if start could transform into target with // captures and (maybe) promotions. This is used to exclude games // from a material or position search without needing to decode // them, by checking each game's final position matsig. // bool matsig_isReachable (matSigT mStart, matSigT mTarget, bool promos, bool upromo) { if (MATSIG_Count_WP(mStart) < MATSIG_Count_WP(mTarget)) { return false; } if (MATSIG_Count_BP(mStart) < MATSIG_Count_BP(mTarget)) { return false; } // If there are underpromotions, we can only check pawn counts: if (upromo) { return true; } // No underpromotions, so check non-queen piece counts: if (MATSIG_Count_WR(mStart) < MATSIG_Count_WR(mTarget)) { return false; } if (MATSIG_Count_BR(mStart) < MATSIG_Count_BR(mTarget)) { return false; } if (MATSIG_Count_WB(mStart) < MATSIG_Count_WB(mTarget)) { return false; } if (MATSIG_Count_BB(mStart) < MATSIG_Count_BB(mTarget)) { return false; } if (MATSIG_Count_WN(mStart) < MATSIG_Count_WN(mTarget)) { return false; } if (MATSIG_Count_BN(mStart) < MATSIG_Count_BN(mTarget)) { return false; } // If there were promotions we cannot check queen counts: if (promos) { return true; } // Check queen counts: if (MATSIG_Count_WQ(mStart) < MATSIG_Count_WQ(mTarget)) { return false; } if (MATSIG_Count_BQ(mStart) < MATSIG_Count_BQ(mTarget)) { return false; } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // hpSig_PossibleMatch(): // Returns 1 if a game could match the home pawn signature in hpSig. // The argument changeList is the ordered list of pawns that leave // their home rank (by moving or being captured). // // Used to exclude games in exact position searches. For example, // If we are looking for the position after "1.d4 d5 2.c4", the // target hpSig looks like "1100111111101111" (the c2, d2 and d7 // pawns are gone from the home ranks). // // The first byte of a changeList is the length (in halfbytes) of the // list, which can be any value from 0 to 16 inclusive. // bool hpSig_PossibleMatch (uint hpSig, const byte * changeList) { // First, the starting sig (all pawns home) can match any game: if (hpSig == HPSIG_StdStart) { return true; } uint hpCurrent = HPSIG_StdStart; uint count = (uint) changeList[0]; changeList++; uint halfByte = 0; byte change; for (uint i=0; i < count; i++) { if (halfByte == 0) { change = (*changeList) >> 4; halfByte = 1; } else { change = (*changeList) & 15; halfByte = 0; changeList++; } hpCurrent &= ~(1 << change); if (hpCurrent == hpSig) { return true; } // Here is an optimisation: If the target HP sig contains a home // pawn not in the current HP sig, it could never match since pawns // cannot reappear on their home rank! This test is easy and fast: if ((hpCurrent & hpSig) != hpSig) { return false; } } // Loop finished, no match was found. return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // hpSig_Prefix(): // Returns true if one of the changeLists provided is a prefix // of the other or if they are the same. // Used to quickly test if one game is possibly a truncated version // of another game. // bool hpSig_Prefix (const byte * changeListA, const byte * changeListB) { uint countA = changeListA[0]; uint countB = changeListB[0]; changeListA++; changeListB++; bool halfByte = false; byte changeA; byte changeB; // Use the shorter changeList length: uint count = (countA < countB ? countA : countB); // Check each corresponding value in the lists: for (uint i=0; i < count; i++) { if (halfByte) { changeA = *changeListA & 15; changeB = *changeListB & 15; changeListA++; changeListB++; halfByte = false; } else { changeA = *changeListA >> 4; changeB = *changeListB >> 4; halfByte = true; } if (changeA != changeB) { return false; } } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // hpSig_Final(): // Returns the final home pawn signature value of a changeList. // uint hpSig_Final (const byte * changeList) { uint hpSig = HPSIG_StdStart; uint count = (uint) changeList[0]; changeList++; bool halfByte = false; byte change; for (uint i=0; i < count; i++) { if (halfByte == false) { change = (*changeList) >> 4; halfByte = true; } else { change = (*changeList) & 15; halfByte = false; changeList++; } hpSig -= (1 << change); } return hpSig; } ////////////////////////////////////////////////////////////////////// // EOF: matsig.cpp ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/misc.cpp0000755000076500000240000004442514666426276017357 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: misc.cpp // Miscellaneous routines (File I/O, etc) // // Part of: Scid (Shane's Chess Information Database) // Version: 3.5 // // Notice: Copyright (c) 2001-2003 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// #include "common.h" #include "misc.h" #include #include // For isspace() function. #include ////////////////////////////////////////////////////////////////////// // ECO Code Routines //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // eco_FromString(): // Extract an ECO code from a string. // // Eco code numbering: no eco = 0, A00 = 1, A01 = 132, etc. // That is, each basic ECO code = previous + 131. // The extra 130 subcodes are the extended code: // a, a1, a2, a3, a4, b, b1, .... z, z1, z2, z3, z4. (130 in total). // // Improvement, March 2000: now case-insensitive for first letter, // for example, a41 == A41. ecoT eco_FromString (const char * ecoStr) { ecoT eco = ECO_None; // Get the basic Eco code from the first 3 characters: they MUST be in // the range "A00" to "E99" or the eco code will be considered empty. // Changed, June 1999: now accepts partial ECO codes, e.g. "C1" -> C10 if (*ecoStr >= 'A' && *ecoStr <= 'E') { eco = (*ecoStr - 'A') * 13100; } else if (*ecoStr >= 'a' && *ecoStr <= 'e') { eco = (*ecoStr - 'a') * 13100; } else { return 0; } ecoStr++; if (! *ecoStr) { return eco + 1; } if (*ecoStr < '0' || *ecoStr > '9') { return 0; } eco += (*ecoStr - '0') * 1310; ecoStr++; if (! *ecoStr) { return eco + 1; } if (*ecoStr < '0' || *ecoStr > '9') { return 0; } eco += (*ecoStr - '0') * 131; ecoStr++; // Now check for the optional extended code: a, a1, ... z2, z3, z4. if (*ecoStr >= 'a' && *ecoStr <= 'z') { eco++; eco += (*ecoStr - 'a') * 5; ecoStr++; if (*ecoStr >= '1' && *ecoStr <= '4') { eco += *ecoStr - '0'; } } return eco + 1; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // eco_ToString(): // Convert an ECO code to its string representation. void eco_ToString (ecoT ecoCode, char * ecoStr, bool extensions) { char * s = ecoStr; if (ecoCode == ECO_None) { *s = 0; return; } ecoCode--; // First the base code value: ecoT basicCode = ecoCode / 131; // 131 = 26 * 5 + 1 subcodes. *s++ = basicCode / 100 + 'A'; *s++ = (basicCode % 100) / 10 + '0'; *s++ = (basicCode % 10) + '0'; // Now the optional extensions: if (extensions) { ecoCode = ecoCode % 131; if (ecoCode > 0) { ecoCode--; *s++ = (ecoCode / 5) + 'a'; ecoCode = ecoCode % 5; if (ecoCode > 0) { *s++ = (ecoCode + '0'); } } *s = 0; } return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // eco_BasicCode(): // Converts an ECO code to its basic form, without any // Scid-specific extensions. ecoT eco_BasicCode (ecoT eco) { if (eco == ECO_None) { return ECO_None; } eco--; eco /= 131; eco *= 131; return eco + 1; } /** * ecoReduce() - maps eco to a smaller set * @param eco: the eco value to convert (must be != 0) * * Scid ECO subcodes use 131 values for each canonical ECO. * For example A00 is divided in A00,A00a,A00a1,A00a2,A00a3,A00a4,A00b...A00z4 * corresponding to eco values 1,2,3,4,5,6,7...131 (value 0 means no ECO). * This functions will map subECOs like A00a1...A00a4 into A00a, reducing * the 131 values to 27. The previous sequence will became 0,1,1,1,1,1,2...26 */ ecoT eco_Reduce(ecoT eco) { ASSERT(eco != 0); eco--; ecoT res = (eco / 131) * 27; return res + static_cast(std::ceil((eco % 131) / 5.0)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // eco_LastSubCode(): // Converts an ECO code to the deepest subcode it could contain. // Examples: B91a -> B91a4 and B91 -> B91z4. ecoT eco_LastSubCode (ecoT eco) { if (eco == ECO_None) { return ECO_None; } // if just a basic ECO code (1 letter, 2 digits), add the "z": eco--; if ((eco % 131) == 0) { eco += 126; } // 126 = 5 * 25 + 1. // Now if no final digit, add the "4": if (((eco % 131) % 5) == 1) { eco += 4; } return eco + 1; } ////////////////////////////////////////////////////////////////////// // String Routines //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strAppend(): // Appends extra to the end of target, and returns a pointer // to the new END of the string target. // char * strAppend (char * target, const char * extra) { ASSERT (target != NULL && extra != NULL); while (*target != 0) { target++; } // get to end of target string while (*extra != 0) { *target = *extra; target++; extra++; } *target = 0; return target; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strDuplicate(): Duplicates a string using new[] operator. // char * strDuplicate (const char * original) { ASSERT (original != NULL); char * newStr = new char [strLength(original) + 1]; if (newStr == NULL) return NULL; char *s = newStr; while (*original != 0) { *s = *original; s++; original++; } *s = 0; // Add trailing '\0'. //printf ("Dup: %p: %s\n", newStr, newStr); return newStr; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strPad(): // Copies original string to target, but copies *exactly* 'width' // bytes. If the original is longer than specified width, not all of // original will be copied to target. If original is shorter, then // target will be padded out to 'width' bytes with the padding char. // // If the width is negative, no trimming or padding is done and // the result is just a regular string copy. // // The return value is the length copied: always 'width' if // width is >= 0, or the length of original if 'width' is negative. // uint strPad (char * target, const char * original, int width, char padding) { ASSERT (target != NULL && original != NULL); if (width < 0) { strCopy (target, original); return strLength (original); } int len = width; while (len > 0) { if (*original == 0) { break; } *target = *original; target++; original++; len--; } while (len--) { *target++ = padding; } *target = 0; return width; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strFirstChar(): // Returns the pointer into the provided string where the // FIRST occurrence of matchChar is, or NULL if the string // does not contain matchChar at all. // Equivalent to strchr(). const char * strFirstChar (const char * target, char matchChar) { const char * s = target; while (*s != 0) { if (*s == matchChar) { return s; } s++; } return NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strLastChar(): // Returns the pointer into the provided string where the // LAST occurrence of matchChar is, or NULL if the string // does not contain matchChar at all. // Equivalent to strrchr(). const char * strLastChar (const char * target, char matchChar) { const char * s = target; const char * last = NULL; while (*s != 0) { if (*s == matchChar) { last = s; } s++; } return last; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strStrip(): // Removes all occurrences of the specified char from the string. void strStrip (char * str, char ch) { char * s = str; while (*str != 0) { if (*str != ch) { if (s != str) { *s = *str; } s++; } str++; } *s = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strTrimLeft(): // Returns the pointer into the provided string where the first // character that does NOT equal a trimChar occurs. const char * strTrimLeft (const char * target, const char * trimChars) { const char * s = target; while (*s != 0) { if (! strContainsChar (trimChars, *s)) { break; } s++; } return s; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strTrimSuffix(): // Trims the provided string in-place, at the last // occurrence of the provided suffix character. // Returns the number of characters trimmed. // E.g., strTrimSuffix ("file.txt", '.') would leave the // string as "file" and return 4. uint strTrimSuffix (char * target, char suffixChar) { uint trimCount = 0; char * lastSuffixPtr = NULL; char * s = target; while (*s) { if (*s == suffixChar) { lastSuffixPtr = s; trimCount = 0; } trimCount++; s++; } if (lastSuffixPtr == NULL) { return 0; } *lastSuffixPtr = 0; return trimCount; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strTrimDate(): // Takes a date string ("xxxx.xx.xx" format) and trims // the day part if it is ".??", and also the month part // if it too is ".??". void strTrimDate (char * str) { if (str[7] == '.' && str[8] == '?' && str[9] == '?') { str[7] = 0; if (str[4] == '.' && str[5] == '?' && str[6] == '?') { str[4] = 0; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strTrimMarkCodes(): // Trims in-place all Scid-recognised board mark codes // in a comment string, such as "[%mark ...]" and "[%arrow ...]" void strTrimMarkCodes (char * str) { char * in = str; char * out = str; bool inCode = false; char * startLocation = NULL; while (1) { char ch = *in; if (inCode) { // If we see end-of-string or code-starting '[', there is some // error so go back to the start of this code and treat it // normally. if (ch == 0 || ch == '[') { *out++ = *startLocation; inCode = false; in = startLocation; } else if (ch == ']') { // See a code-ending ']', so end the code. inCode = false; } // For all other characters in a code, just ignore it. } else { // Stop at end-of-string: if (ch == 0) { break; } // Look for the start of a code that is to be stripped: if (ch == '[' && in[1] == '%') { inCode = true; startLocation = in; } else { *out++ = ch; } } in++; } // Terminate the modified string: *out = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strTrimMarkup(): // Trims in-place all HTML-like markup codes (, , etc) // from the provided string. void strTrimMarkup (char * str) { char * in = str; char * out = str; bool inTag = false; while (*in != 0) { char ch = *in; if (inTag) { if (ch == '>') { inTag = false; } } else { if (ch == '<') { inTag = true; } else { *out++ = ch; } } in++; } *out = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strFirstWord: // Skips over all whitespace at the start of the // string to reach the first word. const char * strFirstWord (const char * str) { ASSERT (str != NULL); while (*str != 0 && isspace(static_cast(*str))) { str++; } return str; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strNextWord: // Skips over all successive non-whitespace characters // in the string, then all successive whitespace chars, // to reach the next word in the string. const char * strNextWord (const char * str) { ASSERT (str != NULL); while (*str != 0 && !isspace(static_cast(*str))) { str++; } while (*str != 0 && isspace(static_cast(*str))) { str++; } return str; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strIsUnknownName(): // Returns true if the string is an "unknown" name: the empty // string, "?" or "-". Used primarily to test if an event, site // or round name string contains information worth printing. bool strIsUnknownName (const char * str) { if (str[0] == 0) { return true; } if (str[0] == '-' && str[1] == 0) { return true; } if (str[0] == '?' && str[1] == 0) { return true; } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strIsSurnameOnly(): // Returns true if the name appears to be a surname only. bool strIsSurnameOnly (const char * name) { uint capcount = 0; const char * s = name; while (*s != 0) { unsigned char c = *s; if (! isalpha(c)) { return false; } if (isupper(c)) { capcount++; if (capcount > 1) { return false; } } s++; } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strGetBoolean(): // Extracts a boolean value from a string. // True strings start with one of "TtYy1", false strings with // one of "FfNn0". // Returns false if the string does not contain a boolean value. bool strGetBoolean (const char * str) { static const char * sTrue[] = { "true", "yes", "on", "1", "ja", "si", "oui", NULL }; static const char * sFalse[] = { "false", "no", "off", "0", NULL }; if (str[0] == 0) { return false; } bool matchedTrue = false; bool matchedFalse = false; const char ** next = sTrue; while (*next != NULL) { if (strIsCasePrefix (str, *next) || strIsCasePrefix (*next, str)) { matchedTrue = true; } next++; } next = sFalse; while (*next != NULL) { if (strIsCasePrefix (str, *next) || strIsCasePrefix (*next, str)) { matchedFalse = true; } next++; } if (matchedTrue && !matchedFalse) { return true; } if (matchedFalse && !matchedTrue) { return false; } // default: return false. return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strGetIntegers: // Extracts the specified number of signed integers in a // whitespace-separated string to an array. void strGetIntegers (const char * str, int * results, uint nResults) { for (uint i=0; i < nResults; i++) { while (*str != 0 && isspace(static_cast(*str))) { str++; } results[i] = strGetInteger (str); while (*str != 0 && !isspace(static_cast(*str))) { str++; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strGetUnsigneds: // Extracts the specified number of unsigned integers in a // whitespace-separated string to an array. void strGetUnsigneds (const char * str, uint * results, uint nResults) { for (uint i=0; i < nResults; i++) { while (*str != 0 && isspace(static_cast(*str))) { str++; } results[i] = strGetUnsigned (str); while (*str != 0 && !isspace(static_cast(*str))) { str++; } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strGetResult: // Extracts a game result value from a string. resultT strGetResult (const char * str) { switch (*str) { case '1': // Check for "1/2"-style draw result: if (str[1] == '/' && str[2] == '2') { return RESULT_Draw; } return RESULT_White; case '=': return RESULT_Draw; case '0': return RESULT_Black; case '*': return RESULT_None; } return RESULT_None; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strGetFlag(): // Extracts a flag (FLAG_YES, FLAG_NO or FLAG_BOTH) value from // a string. Defaults to FLAG_EMPTY. flagT strGetFlag (const char * str) { char c = *str; switch (c) { case 'T': case 't': case 'Y': case 'y': case 'J': case 'j': case 'O': case 'o': case 'S': case 's': case '1': return FLAG_YES; case 'F': case 'f': case 'N': case 'n': case '0': return FLAG_NO; case 'B': case 'b': case '2': return FLAG_BOTH; } // default: return empty. return FLAG_EMPTY; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strGetSquare(): // Extracts a square value from a string, such as "a2". squareT strGetSquare (const char * str) { char chFyle = str[0]; if (chFyle < 'a' || chFyle > 'h') { return NULL_SQUARE; } char chRank = str[1]; if (chRank < '1' || chRank > '8') { return NULL_SQUARE; } return square_Make (fyle_FromChar(chFyle), rank_FromChar(chRank)); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strUniqueExactMatch(): // Given a string and a null-terminated array of strings // , returns the index of the unique match of the key // string in the string table. If no match was found, or there was // more than one match, -1 is returned. // // If the flag is true, only complete matches are considered. // Otherwise, unique abbreviations are accepted. // Example: looking up "repl" in {"repeat", "replace", NULL} would // return 1 (matching "replace") but looking up "rep" would // return -1 because its match is ambiguous. // // The array "strTable" does NOT need to be in any order, but the last // entry must be NULL. int strUniqueExactMatch (const char * keyStr, const char ** strTable, bool exact) { int index = -1; int abbrevMatches = 0; const char * s1; const char * s2; const char ** entryPtr = strTable; // If keyStr or strTable are null, return no match: if (keyStr == NULL || strTable == NULL) { return -1; } // Check each entry in turn: for (int i=0; *entryPtr != NULL; entryPtr++, i++) { // Check the key against this entry, character by character: for (s1 = keyStr, s2 = *entryPtr; *s1 == *s2; s1++, s2++) { // If *s1 is 0, we found an EXACT match, so return it now: if (*s1 == 0) { return i; } } // If *s1 == 0 now, key is an abbreviation of this entry: if (*s1 == 0) { index = i; abbrevMatches++; } } // If we reach here, there is no exact match. If an exact match was // required, or there is not exactly one abbreviation, return no match: if (exact || abbrevMatches != 1) { return -1; } // Otherwise, return the match found: return index; } ////////////////////////////////////////////////////////////////////// // EOF: misc.cpp ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/misc.h0000755000076500000240000003036514666426276017022 0ustar jensstaff ////////////////////////////////////////////////////////////////////// // // FILE: misc.h // Miscellaneous routines (File I/O, etc) // // Part of: Scid (Shane's Chess Information Database) // Version: 3.5 // // Notice: Copyright (c) 2001-2003 Shane Hudson. All rights reserved. // Copyright (C) 2015 Fulvio Benini // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// #ifndef SCID_MISC_H #define SCID_MISC_H #include "common.h" #include #include #include #include #include // For isspace(), etc #include #include /** * class StrRange - parse a string interpreting its content as 1 or 2 integers * separated by whitespace. * The integers represent the min and max value of a range. * If only one integer is provided it will represent both the min and max value. */ class StrRange { protected: long min_; long max_; protected: StrRange() : min_(0), max_(0) {} public: explicit StrRange(const char* range) { char* next; min_ = std::strtol(range, &next, 10); char* end; max_ = std::strtol(next, &end, 10); if (next == end) max_ = min_; if (min_ > max_) std::swap(min_, max_); } /// @returns true if @e val is >= min_ and <= max_ bool inRange(long val) const { if (val < min_ || val > max_) return false; return true; } }; class Progress { public: struct Impl { virtual ~Impl() {} virtual bool report(size_t done, size_t total, const char* msg) = 0; }; Progress(Impl* f = NULL) : f_(f) {} Progress(const Progress&) = delete; ~Progress() { delete f_; } bool report(size_t done, size_t total) const { return operator()(done, total); } bool operator()(size_t done, size_t total, const char* msg = NULL) const { if (f_) return f_->report(done, total, msg); return true; } private: Impl* f_; }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strGetFilterOp: // Converts a string value to a filter operation value. enum filterOpT { FILTEROP_AND, FILTEROP_OR, FILTEROP_RESET }; inline filterOpT strGetFilterOp (const char * str) { switch (*str) { // AND: case 'A': case 'a': case '0': return FILTEROP_AND; // OR: case 'O': case 'o': case '1': return FILTEROP_OR; // RESET: case 'R': case 'r': case '2': return FILTEROP_RESET; } // Default is RESET. return FILTEROP_RESET; } // ECO string routines // void eco_ToString (ecoT ecoCode, char * ecoStr, bool extensions = true); inline void eco_ToBasicString (ecoT ecoCode, char * ecoStr) { eco_ToString (ecoCode, ecoStr, false); } inline void eco_ToExtendedString (ecoT ecoCode, char * ecoStr) { eco_ToString (ecoCode, ecoStr, true); } ecoT eco_FromString (const char * ecoStr); ecoT eco_LastSubCode (ecoT ecoCode); ecoT eco_BasicCode (ecoT ecoCode); ecoT eco_Reduce(ecoT eco); // String routines. Some are identical to ANSI standard functions, but // I have included them: // (a) to keep nice consistent naming conventions, e.g. strCopy. // (b) so stats can easily be kept by modifying the functions. // (c) so some can be made inline for speed if necessary. inline uint32_t strStartHash(const char* str) { ASSERT(str != 0); const unsigned char* s = reinterpret_cast(str); uint32_t tmp = static_cast(tolower(*s)); uint32_t result = tmp << 24; if (*s == '\0') return result; tmp = static_cast(tolower(*++s)); result += tmp << 16; if (*s == '\0') return result; tmp = static_cast(tolower(*++s)); result += tmp << 8; if (*s == '\0') return result; result += static_cast(tolower(*++s)); return result; } char * strDuplicate (const char * str); char * strAppend (char * target, const char * extra); uint strPad (char * target, const char * orig, int length, char pad); const char * strFirstChar (const char * target, char matchChar); const char * strLastChar (const char * target, char matchChar); void strStrip (char * str, char ch); const char * strTrimLeft (const char * target, const char * trimChars); inline const char * strTrimLeft (const char * target) { return strTrimLeft (target, " \t\r\n"); } uint strTrimSuffix (char * target, char suffixChar); void strTrimDate (char * str); void strTrimMarkCodes (char * str); void strTrimMarkup (char * str); const char * strFirstWord (const char * str); const char * strNextWord (const char * str); // strPlural: // Returns the empty string if its parameter is 1, or "s" otherwise. inline const char * strPlural (uint x) { return (x == 1 ? "" : "s"); } bool strIsUnknownName (const char * str); // strIsSurnameOnly: returns true if a string appears to only // contain a surname. bool strIsSurnameOnly (const char * name); bool strGetBoolean (const char * str); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strGetInteger(): // Extracts a signed base-10 value from a string. // Defaults to zero (as strtol does) for non-numeric strings. inline int strGetInteger(const char * str) { return std::strtol(str, NULL, 10); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strGetUnsigned(): // Extracts an unsigned base-10 value from a string. // Defaults to zero (as strtoul does) for non-numeric strings. // inline uint32_t strGetUnsigned(const char* str) { ASSERT(str != NULL); return static_cast(std::strtoul(str, NULL, 10)); } inline int strCaseCompare(const char* str1, const char* str2) { ASSERT(str1 != NULL && str2 != NULL); const unsigned char* s1 = reinterpret_cast(str1); const unsigned char* s2 = reinterpret_cast(str2); int c1, c2; do { c1 = tolower(*s1++); c2 = tolower(*s2++); if (c1 == '\0') break; } while (c1 == c2); return c1 - c2; } inline int strCompareRound(const char* str1, const char* str2) { ASSERT(str1 != NULL && str2 != NULL); uint32_t a = strGetUnsigned(str1); uint32_t b = strGetUnsigned(str2); if (a == b) return strCaseCompare(str1, str2); return (a < b) ? -1 : 1; } inline bool strEqual(const char* str1, const char* str2) { ASSERT(str1 != NULL && str2 != NULL); return (std::strcmp(str1, str2) == 0); } void strGetIntegers (const char * str, int * results, uint nResults); void strGetUnsigneds (const char * str, uint * results, uint nResults); resultT strGetResult (const char * str); typedef uint flagT; const flagT FLAG_EMPTY = 0; const flagT FLAG_YES = 1; const flagT FLAG_NO = 2; const flagT FLAG_BOTH = 3; inline bool flag_Yes (flagT t) { return (t & FLAG_YES); } inline bool flag_No (flagT t) { return (t & FLAG_NO); } flagT strGetFlag (const char * str); squareT strGetSquare (const char * str); inline uint strTrimFileSuffix (char * target) { return strTrimSuffix (target, '.'); } inline const char * strFileSuffix (const char * target) { return strLastChar (target, '.'); } int strUniqueExactMatch (const char * keyStr, const char ** strTable, bool exact); inline int strUniqueMatch (const char * keyStr, const char ** strTable) { return strUniqueExactMatch (keyStr, strTable, false); } inline int strExactMatch (const char * keyStr, const char ** strTable) { return strUniqueExactMatch (keyStr, strTable, true); } inline bool strContainsChar (const char * str, char ch) { while (*str) { if (*str == ch) { return true; } str++; } return false; } // WARNING: Avoid this function! // Considering that the sign of a char is implementation-defined [3.9.1], the // int conversion ("[4.7.3] If the destination type is signed, the value is // unchanged if it can be represented in the destination type") can yield // different results on different architectures or compilers. // A better alternative is the standard function strcmp() that returns the // difference between the values of the first pair of characters (both // interpreted as unsigned char) that differ in the strings being compared. inline int strCompare(const char* s1, const char* s2) { ASSERT (s1 != NULL && s2 != NULL); while (1) { if (*s1 != *s2) { return ((int) *s1) - ((int) *s2); } if (*s1 == 0) break; s1++; s2++; } return 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strCopy(): same as strcpy(). // inline void strCopy (char * target, const char * original) { ASSERT (target != NULL && original != NULL); while (*original != 0) { *target = *original; target++; original++; } *target = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strPrefix(): // Returns the length of the common prefix of two strings. // inline uint strPrefix (const char * s1, const char * s2) { ASSERT (s1 != NULL && s2 != NULL); uint count = 0; while (*s1 == *s2) { if (*s1 == 0) { // seen end of string, strings are identical return count; } count++; s1++; s2++; } return count; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strIsPrefix(): // Returns true if the prefix string is a prefix of longStr. inline bool strIsPrefix (const char * prefix, const char * longStr) { while (*prefix) { if (*longStr == 0) { return false; } if (*prefix != *longStr) { return false; } prefix++; longStr++; } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strIsCasePrefix(): // Returns true if the prefix string is a case-insensitive // prefix of longStr. inline bool strIsCasePrefix (const char * prefix, const char * longStr) { typedef unsigned char U; while (*prefix) { if (*longStr == 0) { return false; } if (tolower(U(*prefix)) != tolower(U(*longStr))) { return false; } prefix++; longStr++; } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strIsAlphaPrefix(): // Returns true if the prefix string is a prefix of longStr. // Unlike strIsPrexix(), this version is case-insensitive and // spaces are ignored. // Example: strIsAlphaPrefix ("smith,j", "Smith, John") == true. inline bool strIsAlphaPrefix (const char * prefix, const char * longStr) { typedef unsigned char U; while (*prefix) { while (*prefix == ' ') { prefix++; } while (*longStr == ' ') { longStr++; } if (*longStr == 0) { return false; } if (tolower(U(*prefix)) != tolower(U(*longStr))) { return false; } prefix++; longStr++; } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strContains(): // Returns true if longStr contains an occurrence of keyStr, // case-sensitive and NOT ignoring any characters such as spaces. inline bool strContains (const char * longStr, const char * keyStr) { while (*longStr) { if (strIsPrefix (keyStr, longStr)) { return true; } longStr++; } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strAlphaContains(): // Returns true if longStr contains an occurrence of keyStr, // case-insensitive and ignoring spaces. // Example: strAlphaContains ("Smith, John", "th,j") == true. // inline bool strAlphaContains (const char * longStr, const char * keyStr) { while (*longStr) { if (strIsAlphaPrefix (keyStr, longStr)) { return true; } longStr++; } return false; } inline uint strLength (const char * str) { ASSERT(str != NULL); uint len = 0; while (*str != 0) { len++; str++; } return len; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // strTrimRight(): // Trims the provided string in-place, removing the // end characters that match the trimChars. // Returns the number of characters trimmed. // E.g., strTrimRight("abcyzyz", "yz") would leave the string // as "abc". inline void strTrimRight(char* target, const char* trimChars, size_t nTrimCh) { const char* endTrim = trimChars + nTrimCh; size_t iCh = strlen(target); for (; iCh > 0; --iCh) { if (std::find(trimChars, endTrim, target[iCh - 1]) == endTrim) break; } target[iCh] = '\0'; } inline void strTrimRight(char* target) { return strTrimRight(target, " \t\r\n", 4); } #endif // #ifdef SCID_MISC_H ////////////////////////////////////////////////////////////////////// // EOF: misc.h ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/codec_scid4.cpp0000755000076500000240000004762214666426276020571 0ustar jensstaff/* * Copyright (C) 2017 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . * */ /** @file * Implements the CodecSCID4 class, which manages the databases encoded * in Scid format version 4. */ #include "codec_scid4.h" #include namespace { /** * A NameBase file starts with an header containing: * - header_magic (8 bytes): identify the file format * - unused (4 bytes): obsolete timeStamp * - number of NAME_PLAYER names stored in the file (3 bytes) * - number of NAME_EVENT names stored in the file (3 bytes) * - number of NAME_SITE names stored in the file (3 bytes) * - number of NAME_ROUND names stored in the file (3 bytes) * - unused (12 bytes): obsolete max frequency * Names are stored in alphabetical order using front-coding and each record is * composed by: * - name_id (2-3 bytes): the idx (idNumberT) stored in the Index (.si4) file * - unused (1-3 bytes): obsolete frequency * - length (1 byte): the total number of bytes of the name (max 255) * - prefix (1 byte): the number of bytes in common with the previous name * - name (0-255 bytes): the part of the name that differs from the previous * one. */ const char* NAMEBASE_MAGIC = "Scid.sn"; /** * Read a SCIDv4 NameBase file into memory. * @param filename: the full path of the file to open. * @param fMode: a valid file mode. * @param nb: reference to the object where the names will be stored. * @returns OK if successful or an error code. */ errorT namefileRead(const char* filename, fileModeT fmode, NameBase& nb) { auto nb_data = nb.getData(); auto& map = std::get<0>(nb_data); auto& names = std::get<1>(nb_data); auto& eloV = std::get<2>(nb_data); Filebuf file; if (file.Open(filename, fmode) != OK) return ERROR_FileOpen; char Header_magic[9] = {0}; // magic identifier must be "Scid.sn" file.sgetn(Header_magic, 8); if (strcmp(Header_magic, NAMEBASE_MAGIC) != 0) return ERROR_BadMagic; // *** Compatibility *** // Even if timeStamp is not used we still need to read the bytes file.ReadFourBytes(); // *** idNumberT Header_numNames[NUM_NAME_TYPES]; Header_numNames[NAME_PLAYER] = file.ReadThreeBytes(); Header_numNames[NAME_EVENT] = file.ReadThreeBytes(); Header_numNames[NAME_SITE] = file.ReadThreeBytes(); Header_numNames[NAME_ROUND] = file.ReadThreeBytes(); // *** Compatibility *** // Even if frequency is no longer used we still need to read the bytes uint obsolete_maxFreq[NUM_NAME_TYPES]; obsolete_maxFreq[NAME_PLAYER] = file.ReadThreeBytes(); obsolete_maxFreq[NAME_EVENT] = file.ReadThreeBytes(); obsolete_maxFreq[NAME_SITE] = file.ReadThreeBytes(); obsolete_maxFreq[NAME_ROUND] = file.ReadThreeBytes(); // *** eloV.resize(Header_numNames[NAME_PLAYER], 0); for (nameT nt : {NAME_PLAYER, NAME_EVENT, NAME_SITE, NAME_ROUND}) { names[nt].resize(Header_numNames[nt]); idNumberT id; std::string prevName; for (idNumberT i = 0; i < Header_numNames[nt]; i++) { if (Header_numNames[nt] >= 65536) { id = file.ReadThreeBytes(); } else { id = file.ReadTwoBytes(); } // *** Compatibility *** // Even if frequency is no longer used we still need to read the // bytes Frequencies can be stored in 1, 2 or 3 bytes: if (obsolete_maxFreq[nt] >= 65536) { file.ReadThreeBytes(); } else if (obsolete_maxFreq[nt] >= 256) { file.ReadTwoBytes(); } else { // Frequencies all <= 255: fit in one byte file.ReadOneByte(); } // *** // Read the name string. // All strings EXCEPT the first are front-coded. int length = file.ReadOneByte(); int prefix = (i > 0) ? file.ReadOneByte() : 0; if (prefix > length) return ERROR_Corrupt; char* name = new char[length + 1]; std::copy_n(prevName.c_str(), prefix, name); std::streamsize extra_chars = length - prefix; if (extra_chars != file.sgetn(name + prefix, extra_chars)) { delete[] name; return ERROR_FileRead; } name[length] = 0; prevName.assign(name, length); if (id < Header_numNames[nt] && names[nt][id] == 0) { names[nt][id].reset(name); map[nt].insert(map[nt].end(), std::make_pair(name, id)); } else { delete[] name; return ERROR_Corrupt; } } if (map[nt].size() != names[nt].size()) return ERROR_Corrupt; } return OK; } /** * Write a SCIDv4 NameBase file. * @param filename: the full path of the file to open. * @param nb: reference to the object where the names will be stored. * @returns OK if successful or an error code. */ template errorT namefileWrite(const char* filename, const TCont& names_ids, const TFreq& freq) { Filebuf file; if (file.Open(filename, FMODE_WriteOnly) != OK) return ERROR_FileOpen; file.sputn(NAMEBASE_MAGIC, 8); // *** Compatibility *** // Even if timeStamp is not used we still need to write these bytes file.WriteFourBytes(0); // *** ASSERT(1ULL << 24 > names_ids[NAME_PLAYER].size()); ASSERT(1ULL << 24 > names_ids[NAME_EVENT].size()); ASSERT(1ULL << 24 > names_ids[NAME_SITE].size()); ASSERT(1ULL << 24 > names_ids[NAME_ROUND].size()); file.WriteThreeBytes((uint32_t)names_ids[NAME_PLAYER].size()); file.WriteThreeBytes((uint32_t)names_ids[NAME_EVENT].size()); file.WriteThreeBytes((uint32_t)names_ids[NAME_SITE].size()); file.WriteThreeBytes((uint32_t)names_ids[NAME_ROUND].size()); // *** Compatibility *** // even if maxFrequency is no longer used we still need to write these bytes unsigned maxFreq[NUM_NAME_TYPES] = {0}; for (nameT nt : {NAME_PLAYER, NAME_EVENT, NAME_SITE, NAME_ROUND}) { auto it = std::max_element(freq[nt].begin(), freq[nt].end()); maxFreq[nt] = (it == freq[nt].end()) ? 0 : *it; file.WriteThreeBytes(maxFreq[nt]); } // *** for (nameT nt : {NAME_PLAYER, NAME_EVENT, NAME_SITE, NAME_ROUND}) { const char* prevName = nullptr; size_t numNames = names_ids[nt].size(); for (const auto& it : names_ids[nt]) { const char* name = it.first; idNumberT id = it.second; // *** Compatibility *** // Older code used a custom StrTree class with a peculiar sorting: // - the first char was interpreted as an unsigned char; // - the remaining part was compared with strComapare(), // which converts the chars to ints, and is not consistent with // the standard function strcmp(). // The old StrTree class did also have unpredictable behaviors when // fed with names not sorted according to that criteria, for example // it could create Namebase objects with duplicate entries. // *** ASSERT(prevName == nullptr || static_cast(*prevName) < static_cast(*name) || (static_cast(*prevName) == static_cast(*name) && strCompare(prevName, name) < 0)); // write idNumber in 2 bytes if possible, otherwise 3. if (numNames >= 65536) { file.WriteThreeBytes(id); } else { file.WriteTwoBytes(id); } // *** Compatibility *** // write these bytes even if they are not used anymore if (maxFreq[nt] >= 65536) { file.WriteThreeBytes(freq[nt][id]); } else if (maxFreq[nt] >= 256) { file.WriteTwoBytes(freq[nt][id]); } else { file.WriteOneByte(static_cast(freq[nt][id])); } // *** ASSERT(strlen(name) < 256); byte length = static_cast(strlen(name)); file.WriteOneByte(length); byte prefix = 0; if (prevName) { prefix = (byte)strPrefix(name, prevName); file.WriteOneByte(prefix); } file.sputn(name + prefix, (length - prefix)); prevName = name; } } return OK; } /** * An Index file starts with an header of 182 bytes containing: * - index_magic (8 bytes): identifies the file format. * - version (2 bytes): 300 or 400 * - baseType (4 bytes): e.g. tournament, theory, etc. * - numGames (3 bytes): total number of games contained into the index. * - autoLoad (3 bytes): number of the game to load at start * (0=none, 1=1st, >numGames=last). * - description (108 bytes): a null-terminated string describing the database. * - flag1 description (9 bytes): a null-terminated string describing flag1. * - flag2 description (9 bytes): a null-terminated string describing flag2. * - flag3 description (9 bytes): a null-terminated string describing flag3. * - flag4 description (9 bytes): a null-terminated string describing flag4. * - flag5 description (9 bytes): a null-terminated string describing flag5. * - flag6 description (9 bytes): a null-terminated string describing flag6. */ constexpr char INDEX_MAGIC[8] = "Scid.si"; /// Read the header section of a SCIDv4 Index file into memory. /// @param indexFile: file handle positioned at the start of the Index file. /// @param fMode: a valid file mode. /// @param header: reference to the object where the data will be stored. /// @returns OK if successful or an error code. template errorT readIndexHeader(FileT& indexFile, fileModeT fmode, HeaderT& header) { constexpr versionT SCID_VERSION = 400; // Current file format version = 4.0 constexpr versionT SCID_OLDEST_VERSION = 300; // Oldest readable version char magic[8]; indexFile.sgetn(magic, 8); if (!std::equal(std::begin(magic), std::end(magic), std::begin(INDEX_MAGIC), std::end(INDEX_MAGIC))) { return ERROR_BadMagic; } header.version = indexFile.ReadTwoBytes(); if (header.version < SCID_OLDEST_VERSION || header.version > SCID_VERSION) { return ERROR_FileVersion; } if (header.version != SCID_VERSION && fmode != FMODE_ReadOnly) { // Old versions must be opened readonly return ERROR_FileMode; } header.baseType = indexFile.ReadFourBytes(); header.numGames = indexFile.ReadThreeBytes(); header.autoLoad = indexFile.ReadThreeBytes(); indexFile.sgetn(header.description, SCID_DESC_LENGTH + 1); header.description[SCID_DESC_LENGTH] = 0; if (header.version >= 400) { for (uint i = 0; i < CUSTOM_FLAG_MAX; i++) { indexFile.sgetn(header.customFlagDesc[i], CUSTOM_FLAG_DESC_LENGTH + 1); header.customFlagDesc[i][CUSTOM_FLAG_DESC_LENGTH] = 0; } } return OK; } /// Write the header section of a SCIDv4 Index file. /// @param indexFile: file handle of the Index file. /// @param header: reference to the object containing the header data. /// @returns OK if successful or an error code. template errorT writeIndexHeader(FileT& indexFile, HeaderT& Header) { if (indexFile.pubseekpos(0) != std::streampos(0)) return ERROR_FileWrite; std::streamsize n = 0; n += indexFile.sputn(INDEX_MAGIC, 8); n += indexFile.WriteTwoBytes(Header.version); n += indexFile.WriteFourBytes(Header.baseType); n += indexFile.WriteThreeBytes(Header.numGames); n += indexFile.WriteThreeBytes(Header.autoLoad); n += indexFile.sputn(Header.description, SCID_DESC_LENGTH + 1); for (size_t i = 0; i < CUSTOM_FLAG_MAX; i++) { n += indexFile.sputn(Header.customFlagDesc[i], CUSTOM_FLAG_DESC_LENGTH + 1); } if (n != INDEX_HEADER_SIZE || indexFile.pubsync() == -1) return ERROR_FileWrite; return OK; } } // namespace /** * Decode SCID4 (or SCID3) data into an IndexEntry object. * @param buf_it: pointer to the buffer containing the data * (should contain INDEX_ENTRY_SIZE chars) * @param version: 400 for SCID4 or 300 for SCID3. * @param ie: pointer to the IndexEntry object where the data will be * stored. */ void decodeIndexEntry(const char* buf_it, versionT version, IndexEntry* ie) { auto ReadOneByte = [&buf_it]() { uint8_t res = *buf_it++; return res; }; auto ReadTwoBytes = [&ReadOneByte]() { uint16_t high = ReadOneByte(); uint16_t res = (high << 8) | ReadOneByte(); return res; }; auto ReadFourBytes = [&ReadTwoBytes]() { uint32_t high = ReadTwoBytes(); uint32_t res = (high << 16) | ReadTwoBytes(); return res; }; // Offset of the gamefile record (32 bits). ie->SetOffset(ReadFourBytes()); // Length of gamefile record for this game: 17 bits are used so the max // length is 128 ko (131071). // Lower bits of the extra byte are used for custom flags: LxFFFFFF ( L = // length for long games, x = spare, F = custom flags) uint32_t len_Low = ReadTwoBytes(); uint32_t len_flags = (version < 400) ? 0 : ReadOneByte(); ie->SetLength(((len_flags & 0x80) << 9) | len_Low); uint32_t Flags = ReadTwoBytes(); ie->clearFlags(); ie->SetFlag(((len_flags & 0x3F) << 16) | Flags, true); // WhiteID and BlackID are 20-bit values, EventID and SiteID are // 19-bit values, and RoundID is an 18-bit value. // WhiteID high 4 bits = bits 4-7 of WhiteBlack_High. // BlackID high 4 bits = bits 0-3 of WhiteBlack_High. // EventID high 3 bits = bits 5-7 of EventSiteRnd_high. // SiteID high 3 bits = bits 2-4 of EventSiteRnd_high. // RoundID high 2 bits = bits 0-1 of EventSiteRnd_high. uint32_t WhiteBlack_High = ReadOneByte(); uint32_t WhiteID_Low = ReadTwoBytes(); ie->SetWhite(((WhiteBlack_High & 0xF0) << 12) | WhiteID_Low); uint32_t BlackID_Low = ReadTwoBytes(); ie->SetBlack(((WhiteBlack_High & 0x0F) << 16) | BlackID_Low); uint32_t EventSiteRnd_High = ReadOneByte(); uint32_t EventID_Low = ReadTwoBytes(); ie->SetEvent(((EventSiteRnd_High & 0xE0) << 11) | EventID_Low); uint32_t SiteID_Low = ReadTwoBytes(); ie->SetSite(((EventSiteRnd_High & 0x1C) << 14) | SiteID_Low); uint32_t RoundID_Low = ReadTwoBytes(); ie->SetRound(((EventSiteRnd_High & 0x03) << 16) | RoundID_Low); // Counters for comments, variations, etc. (4 bits each) // VarCounts also stores the result (4 bits). uint32_t varCounts = ReadTwoBytes(); ie->SetRawVariationCount(varCounts & 0x0F); ie->SetRawCommentCount((varCounts >> 4) & 0x0F); ie->SetRawNagCount((varCounts >> 8) & 0x0F); ie->SetResult((varCounts >> 12) & 0x0F); // ECO code (16 bits) ie->SetEcoCode(ReadTwoBytes()); // Date and EventDate are stored in four bytes. // Due to a compact encoding format, the EventDate // must be within a few years of the Date. uint32_t date_edate = ReadFourBytes(); uint32_t date = date_edate & 0xFFFFF; ie->SetDate(date); uint32_t edate = date_edate >> 20; uint32_t eyear = date_GetYear(edate) & 0x07; if (eyear == 0) { edate = ZERO_DATE; } else { eyear += date_GetYear(date); eyear = (eyear < 4) ? 0 : eyear - 4; edate = DATE_MAKE(eyear, date_GetMonth(edate), date_GetDay(edate)); } ie->SetEventDate(edate); // The two ELO ratings and rating types take 2 bytes each. uint16_t whiteElo = ReadTwoBytes(); ie->SetWhiteElo(whiteElo & 0xFFF); ie->SetWhiteRatingType(whiteElo >> 12); uint16_t blackElo = ReadTwoBytes(); ie->SetBlackElo(blackElo & 0xFFF); ie->SetBlackRatingType(blackElo >> 12); // material of the final position in the game, // and the StoredLineCode in the top 8 bits. uint32_t finalMatSig = ReadFourBytes(); ie->SetFinalMatSig(finalMatSig & 0xFFFFFF); ie->SetStoredLineCode(finalMatSig >> 24); // Read the 9-byte homePawnData array: // The first byte of HomePawnData has high bits of the NumHalfMoves // counter in its top two bits: uint16_t NumHalfMoves = ReadOneByte(); uint16_t pawnData0 = ReadOneByte(); ie->SetNumHalfMoves(((pawnData0 & 0xC0) << 2) | NumHalfMoves); ie->SetHomePawnData(pawnData0 & 0x3F, reinterpret_cast(buf_it)); } errorT CodecSCID4::dyn_open(fileModeT fMode, const char* filename, const Progress& progress, Index* idx, NameBase* nb) { if (fMode == FMODE_WriteOnly || !filename || !idx || !nb) return ERROR; if (*filename == '\0') return ERROR_FileOpen; idx_ = idx; idx_->Init(); nb_ = nb; filenames_.resize(3); filenames_[0] = std::string(filename) + ".si4"; filenames_[1] = std::string(filename) + ".sn4"; filenames_[2] = std::string(filename) + ".sg4"; errorT err = gfile_.open(filenames_[2], fMode); if (err != OK) return err; const char* indexFilename = filenames_[0].c_str(); if (fMode == FMODE_Create) { // Check that the file does not exists if (idxfile_.Open(indexFilename, FMODE_ReadOnly) == OK) err = ERROR_FileOpen; if (err == OK) err = idxfile_.Open(indexFilename, FMODE_Create); if (err == OK) err = writeIndexHeader(idxfile_, idx_->Header); if (err == OK) { err = namefileWrite(filenames_[1].c_str(), nb_->getNames(), idx_->calcNameFreq(*nb_)); } } else { err = idxfile_.Open(indexFilename, fMode); if (err == OK) err = readIndexHeader(idxfile_, fMode, idx_->Header); if (err == OK) err = namefileRead(filenames_[1].c_str(), fMode, *nb_); if (err == OK) err = readIndex(progress); } return err; } errorT CodecSCID4::flush() { idx_->seqWrite_ = 0; errorT errHeader = OK; if (idx_->Header.dirty_) { errHeader = writeIndexHeader(idxfile_, idx_->Header); if (errHeader == OK) idx_->Header.dirty_ = false; } errorT errSync = (idxfile_.pubsync() != 0) ? ERROR_FileWrite : OK; errorT err = (errHeader == OK) ? errSync : errHeader; if (err == OK) { // *** Compatibility *** // Even if name's frequency is no longer used, it's necessary to // keep the compatibility with older Scid versions, forcing a // recalculation. err = namefileWrite(filenames_[1].c_str(), nb_->getNames(), idx_->calcNameFreq(*nb_)); } errorT errGfile = (gfile_.pubsync() == 0) ? OK : ERROR_FileWrite; return (err == OK) ? errGfile : err; } /** * Reads the entire index file into memory. * Invalid name IDs are replaced with "?" if possible. * @param progress: a Progress object used for GUI communications. * @returns OK if successful or an error code. */ inline errorT CodecSCID4::readIndex(const Progress& progress) { gamenumT nUnknowIDs = 0; idNumberT maxID[NUM_NAME_TYPES]; for (nameT nt = NAME_PLAYER; nt < NUM_NAME_TYPES; nt++) { maxID[nt] = nb_->GetNumNames(nt); } auto validateNameIDs = [&](IndexEntry* ie) { if (ie->GetWhite() >= maxID[NAME_PLAYER]) { auto unknown = dyn_addName(NAME_PLAYER, "?"); if (unknown.first != OK) return false; ie->SetWhite(unknown.second); ++nUnknowIDs; } if (ie->GetBlack() >= maxID[NAME_PLAYER]) { auto unknown = dyn_addName(NAME_PLAYER, "?"); if (unknown.first != OK) return false; ie->SetBlack(unknown.second); ++nUnknowIDs; } if (ie->GetEvent() >= maxID[NAME_EVENT]) { auto unknown = dyn_addName(NAME_EVENT, "?"); if (unknown.first != OK) return false; ie->SetEvent(unknown.second); ++nUnknowIDs; } if (ie->GetSite() >= maxID[NAME_SITE]) { auto unknown = dyn_addName(NAME_SITE, "?"); if (unknown.first != OK) return false; ie->SetSite(unknown.second); ++nUnknowIDs; } if (ie->GetRound() >= maxID[NAME_ROUND]) { auto unknown = dyn_addName(NAME_ROUND, "?"); if (unknown.first != OK) return false; ie->SetRound(unknown.second); ++nUnknowIDs; } return true; }; auto version = idx_->Header.version; auto nGames = idx_->GetNumGames(); idx_->entries_.resize(nGames); auto nBytes = (version < 400) ? OLD_INDEX_ENTRY_SIZE : INDEX_ENTRY_SIZE; for (gamenumT gNum = 0; idxfile_.sgetc() != EOF; ++gNum) { if (gNum == nGames) return ERROR_CorruptData; if ((gNum % 8192) == 0) { if (!progress.report(gNum, nGames)) return ERROR_UserCancel; } char buf[INDEX_ENTRY_SIZE]; if (idxfile_.sgetn(buf, nBytes) != nBytes) return ERROR_FileRead; IndexEntry& ie = idx_->entries_[gNum]; decodeIndexEntry(buf, version, &ie); if (!validateNameIDs(&ie)) return ERROR_CorruptData; nb_->AddElo(ie.GetWhite(), ie.GetWhiteElo()); nb_->AddElo(ie.GetBlack(), ie.GetBlackElo()); } progress.report(1, 1); if (nGames != idx_->GetNumGames()) return ERROR_FileRead; idx_->nInvalidNameId_ = nUnknowIDs; return (nUnknowIDs == 0) ? OK : ERROR_NameDataLoss; } chessx-master/dep/scid/code/src/fastgame.h0000755000076500000240000004021714666426276017653 0ustar jensstaff/* * Copyright (C) 2013-2015 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ #ifndef FASTGAME_H #define FASTGAME_H #include "bytebuf.h" #include "common.h" #include "fullmove.h" #include "movegen.h" #include "position.h" #include #include #include #include #include /// Store the number of pieces for each type and color. class MaterialCount { int8_t n_[2][8] = {}; public: /// Add one piece. void incr(colorT color, pieceT piece_type) { ASSERT(color == 0 || color == 1); ASSERT(piece_type > 0 && piece_type < 8); ++n_[color][0]; ++n_[color][piece_type]; } /// Subtract one piece. void decr(colorT color, pieceT piece_type) { ASSERT(color == 0 || color == 1); ASSERT(piece_type > 0 && piece_type < 8); --n_[color][0]; --n_[color][piece_type]; } /// Return the total number of pieces of the specified color. int8_t count(colorT color) const { ASSERT(color == 0 || color == 1); return n_[color][0]; } /// Return the number of pieces of the specified color and type. int8_t count(colorT color, pieceT piece_type) const { ASSERT(color == 0 || color == 1); ASSERT(piece_type > 0 && piece_type < 8); return n_[color][piece_type]; } bool operator==(const MaterialCount& b) const { const int8_t* a = n_[0]; const int8_t* b_ptr = b.n_[0]; return std::equal(a, a + 16, b_ptr); } bool operator!=(const MaterialCount& b) const { return !operator==(b); } }; /// Store the type and position of the pieces compatibly with the SCID4 coding. class PieceList { struct { squareT sq; pieceT piece_type; } pieces_[2][16]; public: /// SCID4 encoded games must use index 0 for kings. int8_t getKingIdx() const { return 0; } /// Return the type of the piece with index @e idx pieceT getPieceType(colorT color, int idx) const { ASSERT(color == 0 || color == 1); ASSERT(idx >= 0 && idx < 16); return pieces_[color][idx].piece_type; } /// Return the square position of the piece with index @e idx squareT getSquare(colorT color, int idx) const { ASSERT(color == 0 || color == 1); ASSERT(idx >= 0 && idx < 16); return pieces_[color][idx].sq; } /// Change the square position of the piece with index @e idx void changeSq(colorT color, int idx, squareT to) { ASSERT(color == 0 || color == 1); ASSERT(idx >= 0 && idx < 16); pieces_[color][idx].sq = to; } /// Change the type of the piece with index @e idx void promote(colorT color, int idx, pieceT piece_type) { ASSERT(color == 0 || color == 1); ASSERT(idx >= 0 && idx < 16); pieces_[color][idx].piece_type = piece_type; } /// Remove the piece with index @e removed_idx. /// Piece's indexes are important for decoding SCID4 moves: when a piece is /// removed it's index is used by the last valid index @e lastvalid_idx. /// Return the square of the new piece with index @e removed_idx. squareT remove(colorT color, int removed_idx, int lastvalid_idx) { ASSERT(color == 0 || color == 1); ASSERT(removed_idx >= 0 && removed_idx < 16); ASSERT(lastvalid_idx >= 0 && lastvalid_idx < 16); pieces_[color][removed_idx] = pieces_[color][lastvalid_idx]; return pieces_[color][lastvalid_idx].sq; } /// Set the type and square of the piece with index @e idx void set(colorT color, int idx, squareT sq, pieceT piece_type) { ASSERT(color == 0 || color == 1); ASSERT(idx >= 0 && idx < 16); ASSERT(piece_type != KING || idx == getKingIdx()); pieces_[color][idx].sq = sq; pieces_[color][idx].piece_type = piece_type; } }; class FastBoard { uint8_t board_[64]; MaterialCount mt_; PieceList pieces_; uint8_t castlingRook_[2][2]; // [WHITE|BLACK][long|short] the idx of the // rooks that can castle. 0 if none enum { EMPTY_SQ_ = 0xFF }; public: FastBoard() = default; explicit FastBoard(const Position& pos) { Init(pos); } static FastBoard stdStart() { static const auto std_start = FastBoard(Position::getStdStart()); return std_start; } void Init(const Position& pos) { std::fill_n(board_, 64, EMPTY_SQ_); std::fill_n(*castlingRook_, 4, 0); for (auto color : {WHITE, BLACK}) { const auto pos_count = pos.GetCount(color); const auto pos_list = pos.GetList(color); for (uint8_t idx = 0; idx < 16; ++idx) { if (idx < pos_count) { const squareT sq = pos_list[idx]; const pieceT piece_type = piece_Type(pos.GetPiece(sq)); pieces_.set(color, idx, sq, piece_type); board_[sq] = idx; mt_.incr(color, piece_type); if (piece_type == ROOK && square_Rank(sq) == rank_Relative(color, RANK_1)) { auto oldIdx = castlingRook_[color][0]; if (!oldIdx || sq < pieces_.getSquare(color, oldIdx)) castlingRook_[color][0] = idx; oldIdx = castlingRook_[color][1]; if (!oldIdx || sq > pieces_.getSquare(color, oldIdx)) castlingRook_[color][1] = idx; } } else { pieces_.set(color, idx, 0, INVALID_PIECE); } } } } bool isEqual(const pieceT* board, const MaterialCount& mt_count) const { if (mt_ != mt_count) return false; for (int idx = 0, n = mt_.count(WHITE); idx < n; ++idx) { const auto sq = pieces_.getSquare(WHITE, idx); const auto pt = pieces_.getPieceType(WHITE, idx); if (board[sq] != piece_Make(WHITE, pt)) return false; } for (int idx = 0, n = mt_.count(BLACK); idx < n; ++idx) { const auto sq = pieces_.getSquare(BLACK, idx); const auto pt = pieces_.getPieceType(BLACK, idx); if (board[sq] != piece_Make(BLACK, pt)) return false; } return true; } const MaterialCount& materialCount() const { return mt_; } squareT getSquare(colorT color, int idx) const { return pieces_.getSquare(color, idx); } pieceT getPiece(colorT color, int idx) const { return pieces_.getPieceType(color, idx); } /// The king and the rook are moved to the castle squares (even if they were /// no longer in their starting squares). /// @returns the previous position of the rook on success. /// On error returns the king's square (no piece is moved). template squareT castle(bool king_side) { const squareT king_to = king_side ? square_Relative(color, G1) : square_Relative(color, C1); const squareT rook_to = king_side ? square_Relative(color, F1) : square_Relative(color, D1); const int king_idx = pieces_.getKingIdx(); const squareT king_from = pieces_.getSquare(color, king_idx); const int rook_idx = castlingRook_[color][king_side ? 1 : 0]; const squareT rook_from = pieces_.getSquare(color, rook_idx); if (pieces_.getPieceType(color, rook_idx) != ROOK) return king_from; // No rook or captured pieces_.changeSq(color, rook_idx, rook_to); pieces_.changeSq(color, king_idx, king_to); board_[rook_from] = EMPTY_SQ_; board_[king_from] = EMPTY_SQ_; board_[rook_to] = rook_idx; board_[king_to] = king_idx; return rook_from; } template pieceT move(uint8_t idx, squareT to, pieceT promo) { if (promo != INVALID_PIECE) { pieces_.promote(color, idx, promo); mt_.incr(color, promo); mt_.decr(color, PAWN); } const auto from = pieces_.getSquare(color, idx); board_[from] = EMPTY_SQ_; pieces_.changeSq(color, idx, to); return remove<1 - color>(to, idx); } template pieceT remove(squareT sq, uint8_t newIdx = EMPTY_SQ_) { const uint8_t oldIdx = board_[sq]; board_[sq] = newIdx; if (oldIdx == EMPTY_SQ_) return INVALID_PIECE; pieceT removed_pt = pieces_.getPieceType(color, oldIdx); mt_.decr(color, removed_pt); int lastvalid_idx = mt_.count(color); if (oldIdx != lastvalid_idx) { squareT moved_sq = pieces_.remove(color, oldIdx, lastvalid_idx); board_[moved_sq] = oldIdx; for (auto& cRook : castlingRook_[color]) { if (cRook == lastvalid_idx) cRook = oldIdx; } } return removed_pt; } /** * Given the actual board position, find if the last move needs to be made * unambiguous and if it gives check (or TODO mate), and then sets the * appropriate bits in @e lastmove. * @param lastmove: the last move played. */ void fillSANInfo(FullMove& lastmove) const { const auto lastFrom = lastmove.getFrom(); const auto lastTo = lastmove.getTo(); const auto lastCol = lastmove.getColor(); auto lastPt = lastmove.getPiece(); if (lastPt == PAWN) { if (lastmove.isPromo()) lastPt = lastmove.getPromo(); } else if (mt_.count(lastCol, lastPt) > 1) { int ambiguity = ambiguousMove(lastFrom, lastTo, lastCol, lastPt); if (ambiguity) lastmove.setAmbiguity(ambiguity != 5, ambiguity >= 5); } // Look for checks ASSERT(mt_.count(WHITE) >= 1 && mt_.count(BLACK) >= 1); auto isOccupied = [this](auto sq) { return board_[sq] != EMPTY_SQ_; }; const auto enemyKingSq = getKingSquare(color_Flip(lastCol)); bool direct_check = (lastPt != KING) && movegen::attack(lastTo, enemyKingSq, lastCol, lastPt, isOccupied); if (direct_check || // Look for a discovered check find_attacker_slider(enemyKingSq, lastCol) >= 0) { lastmove.setCheck(); // TODO: Find if it's mate: // - it's not mate if the king can move to a safe square // - it's mate if it's double check or the attacker cannot be // captured or blocked. } } private: squareT getKingSquare(colorT color) const { return pieces_.getSquare(color, pieces_.getKingIdx()); } int ambiguousMove(squareT lastFrom, squareT lastTo, colorT lastCol, pieceT lastPt) const { int ambiguity = 0; const squareT kingSq = getKingSquare(lastCol); const colorT enemyCol = color_Flip(lastCol); for (int i = 1, n = mt_.count(lastCol); i < n; i++) { if (getPiece(lastCol, i) != lastPt) continue; // Skip: different type const squareT sq = getSquare(lastCol, i); if (sq == lastTo) continue; // Skip: this is the analyzed piece auto isOccupied = [sq, lastFrom, this](auto square) { if (square == sq) return false; if (square == lastFrom) return true; return board_[square] != EMPTY_SQ_; }; if (!movegen::pseudo(sq, lastTo, lastCol, lastPt, isOccupied)) continue; // Skip: illegal move const auto pin = movegen::opens_ray(sq, lastTo, kingSq, isOccupied); if (pin.first != INVALID_PIECE) { uint8_t idx = board_[pin.second]; if (idx != EMPTY_SQ_ && idx < mt_.count(enemyCol) && getSquare(enemyCol, idx) == pin.second) { const pieceT pt = getPiece(enemyCol, idx); if (pt == QUEEN || pt == pin.first) continue; // Skip: pinned piece } } // Ambiguity: // 1 (0001) --> need from-file (preferred) or from-rank // 3 (0011) --> need from-file // 5 (0101) --> need from-rank // 7 (0111) --> need both from-file and from-rank ambiguity |= 1; if (square_Rank(lastFrom) == square_Rank(sq)) { ambiguity |= 2; // 0b0010 } else if (square_Fyle(lastFrom) == square_Fyle(sq)) { ambiguity |= 4; // 0b0100 } } return ambiguity; } int find_attacker_slider(squareT destSq, colorT color) const { for (int idx = 0, n = mt_.count(color); idx < n; ++idx) { const pieceT pt = getPiece(color, idx); if (pt != QUEEN && pt != ROOK && pt != BISHOP) continue; auto isOccupied = [this](auto square) { return board_[square] != EMPTY_SQ_; }; const squareT sq = getSquare(color, idx); if (movegen::attack_slider(sq, destSq, pt, isOccupied)) { return idx; } } return -1; } }; class GameView { FastBoard board_; ByteBuffer bbuf_; colorT cToMove_; public: explicit GameView(const ByteBuffer& bbuf) : board_(FastBoard::stdStart()), bbuf_(bbuf), cToMove_(WHITE) {} GameView(const ByteBuffer& bbuf, const Position& startPos) : bbuf_(bbuf) { board_.Init(startPos); cToMove_ = startPos.GetToMove(); } template void mainLine(FuncT fn) { while (const auto move = (cToMove_ == WHITE) ? DecodeNextMove() : DecodeNextMove()) { cToMove_ = 1 - cToMove_; if (!fn(move)) return; } } FullMove getMove(int ply_to_skip) { for (int ply=0; ply <= ply_to_skip; ply++, cToMove_ = 1 - cToMove_) { auto move = (cToMove_ == WHITE) ? DecodeNextMove() : DecodeNextMove(); if (!move) break; if (ply == ply_to_skip) { board_.fillSANInfo(move); cToMove_ = 1 - cToMove_; return move; } } return {}; } std::string getMoveSAN(int ply_to_skip, int count) { std::stringstream res; const auto ply_num = (cToMove_ == WHITE)? 2 : 3; for (int ply=0; ply < ply_to_skip + count; ply++, cToMove_ = 1 - cToMove_) { FullMove move; if (cToMove_ == WHITE) { move = DecodeNextMove (); if (!move) break; if (ply < ply_to_skip) continue; if (ply > ply_to_skip) res << " "; res << (ply_num + ply) / 2 << "."; } else { move = DecodeNextMove (); if (!move) break; if (ply < ply_to_skip) continue; if (ply == ply_to_skip) res << (ply_num + ply) / 2 << "..."; else res << " "; } board_.fillSANInfo(move); res << move.getSAN(); } return res.str(); } template int search(const byte* board, const MaterialCount& mt_count) { int ply = 1; auto less_material = [](const MaterialCount& a, const MaterialCount& b, const colorT color, const auto move) { if (!move) return true; const auto captured_pt = move.getCaptured(); if (captured_pt == INVALID_PIECE) return false; if (a.count(color) < b.count(color)) return true; return a.count(color, PAWN) + a.count(color, captured_pt) < b.count(color, PAWN) + b.count(color, captured_pt); }; if (cToMove_ != toMove) { const auto move = DecodeNextMove(); if (!move) return 0; ply += 1; } for (;;) { if (board_.isEqual(board, mt_count)) return ply; { const auto move = DecodeNextMove(); if (less_material(board_.materialCount(), mt_count, 1 - toMove, move)) return 0; } { const auto move = DecodeNextMove(); if (less_material(board_.materialCount(), mt_count, toMove, move)) return 0; } ply += 2; } return 0; } private: template TResult DecodeNextMove() { auto [err, val] = bbuf_.nextLineMove(); if (err) return {}; return doPly(val); } template TResult doPly(byte v) { const auto idx_piece_moving = v >> 4; pieceT moving_piece = board_.getPiece(toMove, idx_piece_moving); squareT from = board_.getSquare(toMove, idx_piece_moving); auto [to, promo] = bbuf_.decodeMove(moving_piece, from, v); if (to < 0 || to > 63) return {}; // decode error if (to == from) { if (promo == INVALID_PIECE) return {}; // decode error if (promo == PAWN) // NULL MOVE return TResult(toMove, 0, 0, KING); // CASTLE const squareT rook_from = board_.castle(promo == KING); if (rook_from == from) return {}; // decode error return TResult(toMove, from, rook_from); } bool enPassant = moving_piece == PAWN && square_Fyle(from) != square_Fyle(to); pieceT captured = board_.move(idx_piece_moving, to, promo); TResult res(toMove, from, to, moving_piece); if (promo != INVALID_PIECE) res.setPromo(promo); if (captured != INVALID_PIECE) { res.setCapture(captured, false); } else if (enPassant) { squareT sq = (toMove == WHITE) ? to - 8 : to + 8; captured = board_.remove<1 - toMove>(0x3F & sq); res.setCapture(captured, true); } return res; } }; #endif chessx-master/dep/scid/code/src/date.h0000755000076500000240000001251714666426276017003 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: date.h // Date format and inline date functions. // // Part of: Scid (Shane's Chess Information Database) // Version: 1.9 // // Notice: Copyright (c) 1999 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// #ifndef SCID_DATE_H #define SCID_DATE_H #include "common.h" #include #include // DATE STORAGE FORMAT: // In memory, dates are stored in a 32-bit (4-byte) uint, of which only // the lowest 3 bytes need be used, with the lowest 5 bits for the // day, the next highest 4 bits for the month and the highest bits for // the year. This makes date comparisons easy: a bigger date value is // a more recent date. If a field is unknown, its value is set to zero. // On disk, the date is stored in 3 bytes. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CONSTANTS and MACROS: const dateT ZERO_DATE = 0; const uint YEAR_SHIFT = 9; const uint MONTH_SHIFT = 5; const uint DAY_SHIFT = 0; // DAY (31 days) 5 bits (32) , MONTH (12 months) 4 bits (16) const uint YEAR_MAX = 2047; // 2^11 - 1 #define DATE_MAKE(y,m,d) (((y) << YEAR_SHIFT) | ((m) << MONTH_SHIFT) | (d)) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // date_GetYear(): // Get the year from a date. inline uint date_GetYear (dateT date) { return (uint) (date >> YEAR_SHIFT); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // date_GetMonth(): // Get the month from a date. inline uint date_GetMonth (dateT date) { return (uint) ((date >> MONTH_SHIFT) & 15); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### date_GetDay(): // Get the day of the month from a date. inline uint date_GetDay (dateT date) { return (uint) (date & 31); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### date_GetMonthDay(): // Get the month and day; used to check for year-only dates. S.A inline uint date_GetMonthDay (dateT date) { return (uint) (date & 511); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // date_DecodeToString(): convert date to PGN tag string. inline void date_DecodeToString (dateT date, char * str) { ASSERT(str != NULL); uint year, month, day; year = date_GetYear (date); month = date_GetMonth (date); day = date_GetDay (date); if (year == 0) { *str++ = '?'; *str++ = '?'; *str++ = '?'; *str++ = '?'; } else { *str++ = '0' + (year / 1000); *str++ = '0' + (year % 1000) / 100; *str++ = '0' + (year % 100) / 10; *str++ = '0' + (year % 10); } *str++ = '.'; if (month == 0) { *str++ = '?'; *str++ = '?'; } else { *str++ = '0' + (month / 10); *str++ = '0' + (month % 10); } *str++ = '.'; if (day == 0) { *str++ = '?'; *str++ = '?'; } else { *str++ = '0' + (day / 10); *str++ = '0' + (day % 10); } *str = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // date_EncodeFromString(): convert PGN tag string to date. // The date string format is: "yyyy.mm.dd". inline dateT date_EncodeFromString (const char * str) { // Do checks on str's validity as a date string: ASSERT(str != NULL); dateT date; uint year, month, day; // convert year: year = std::strtoul(str, NULL, 10); if (year > YEAR_MAX) { year = 0; } date = year << YEAR_SHIFT; while (*str != 0 && *str != '.') { str++; } if (*str == '.') { str++; } // convert month: month = std::strtoul(str, NULL, 10); if (month > 12) { return date; } date |= (month << MONTH_SHIFT); while (*str != 0 && *str != '.') { str++; } if (*str == '.') { str++; } // convert day: day = std::strtoul(str, NULL, 10); if (day > 31) { return date; } date |= (day << DAY_SHIFT); return date; } /** * Creates a dateT object from a PGN tag value string. * "The Date tag value field always uses a standard ten character format: * "YYYY.MM.DD". If the any of the digit fields are not known, then question * marks are used in place of the digits." * @param str: pointer to the memory containing the tag value. * @param len: length of the tag value. * @returns the dateT object corresponding to @e str. */ inline dateT date_parsePGNTag(const char* str, size_t len) { char tmp[10] = {0}; std::transform(str, str + std::min(len, 10), tmp, [](char ch) { return (ch >= '0' && ch <= '9') ? ch - '0' : 0; }); uint32_t year = tmp[0] * 1000 + tmp[1] * 100 + tmp[2] * 10 + tmp[3]; uint32_t month = tmp[5] * 10 + tmp[6]; uint32_t day = tmp[8] * 10 + tmp[9]; if (year > YEAR_MAX) year = 0; if (month > 12) month = 0; constexpr unsigned char days[] = {31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; if (day > days[month]) { if (day != 29 || year % 4 || (year % 100 == 0 && year % 400)) { day = 0; } } return (year << YEAR_SHIFT) | (month << MONTH_SHIFT) | (day << DAY_SHIFT); } inline dateT date_parsePGNTag(std::pair str) { return date_parsePGNTag(str.first, std::distance(str.first, str.second)); } #endif // #ifndef SCID_DATE_H ////////////////////////////////////////////////////////////////////// // EOF: date.h ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/indexentry.h0000755000076500000240000004774614666426276020273 0ustar jensstaff/* * Copyright (c) 1999-2002 Shane Hudson * Copyright (c) 2006-2009 Pascal Georges * Copyright (C) 2014-2017 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ #ifndef SCID_INDEXENTRY_H #define SCID_INDEXENTRY_H #include "common.h" #include "date.h" #include "matsig.h" #include "namebase.h" // HPSIG_SIZE = size of HomePawnData array in an IndexEntry. // It is nine bytes: the first byte contains the number of valid entries // in the array, and the next 8 bytes contain up to 16 half-byte entries. const uint HPSIG_SIZE = 9; const eloT MAX_ELO = 4000; // Since we store Elo Ratings in 12 bits const byte CUSTOM_FLAG_MASK[] = { 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5 }; // Total on-disk size per index entry: currently 47 bytes. const uint INDEX_ENTRY_SIZE = 47; const uint OLD_INDEX_ENTRY_SIZE = 46; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class IndexEntry: one of these per game in the index file. // // It contains more than just the location of the game data in the main // data file. For fast searching, it also store some other important // values: players, event, site, date, result, eco, gamelength. // // It takes 56 bytes. class IndexEntry { uint64_t offset_ : 46; // Start of gamefile record for this game. uint64_t gameDataSize_ : 18; // Length of gamefile record for this game. uint64_t storedLineCode_ : 8; uint64_t whiteID_ : 28; uint64_t blackID_ : 28; uint32_t eventID_ : 28; uint32_t whiteEloType_ : 4; uint32_t siteID_ : 28; uint32_t blackEloType_ : 4; uint32_t roundID_ : 28; uint32_t result_ : 4; uint32_t whiteElo_ : 12; uint32_t date_ : 20; uint32_t blackElo_ : 12; uint32_t eventDate_ : 20; uint32_t numHalfMoves_ : 10; uint32_t flags_ : 22; uint32_t finalMatSig_ : 24; // material of the final position in the game uint32_t nVariations_ : 4; uint32_t nComments_ : 4; uint16_t ECOcode_; uint8_t nNags_ : 4; byte HomePawnData [HPSIG_SIZE]; // homePawnSig data. public: template errorT Write (T* file, versionT version) const; // get functions uint64_t GetOffset() const { return offset_; } uint32_t GetLength() const { return gameDataSize_; } idNumberT GetWhite() const { return whiteID_; } eloT GetWhiteElo() const { return whiteElo_; } byte GetWhiteRatingType() const { return whiteEloType_; } idNumberT GetBlack() const { return blackID_; } eloT GetBlackElo() const { return blackElo_; } byte GetBlackRatingType() const { return blackEloType_; } idNumberT GetEvent() const { return eventID_; } idNumberT GetSite() const { return siteID_; } idNumberT GetRound() const { return roundID_; } dateT GetDate() const { return date_; } dateT GetEventDate() const { return eventDate_; } resultT GetResult() const { return result_; } uint GetVariationCount() const { return DecodeCount(nVariations_); } uint GetCommentCount() const { return DecodeCount(nComments_); } uint GetNagCount() const { return DecodeCount(nNags_); } uint16_t GetNumHalfMoves() const { return numHalfMoves_; } matSigT GetFinalMatSig() const { return finalMatSig_; } byte GetStoredLineCode() const { return storedLineCode_; } ecoT GetEcoCode() const { return ECOcode_; } bool GetFlag(uint32_t mask) const { return (flags_ & mask) == mask; } const byte* GetHomePawnData() const { return HomePawnData; } void SetHomePawnData(byte hpCount, const byte hpVal[8]) { HomePawnData[0] = hpCount; // First byte stores the count std::copy_n(hpVal, 8, HomePawnData + 1); } // set functions, assert that the value is not truncated. void SetOffset(uint64_t offset) { offset_ = offset; ASSERT(GetOffset() == offset); } void SetLength(size_t length) { gameDataSize_ = length; ASSERT(GetLength() == length); } void SetWhite(idNumberT id) { whiteID_ = id; ASSERT(GetWhite() == id); } void SetWhiteElo(eloT elo) { whiteElo_ = elo; ASSERT(GetWhiteElo() == elo); } void SetWhiteRatingType(byte b) { whiteEloType_ = b; ASSERT(GetWhiteRatingType() == b); } void SetBlack(idNumberT id) { blackID_ = id; ASSERT(GetBlack() == id); } void SetBlackElo(eloT elo) { blackElo_ = elo; ASSERT(GetBlackElo() == elo); } void SetBlackRatingType(byte b) { blackEloType_ = b; ASSERT(GetBlackRatingType() == b); } void SetEvent(idNumberT id) { eventID_ = id; ASSERT(GetEvent() == id); } void SetSite(idNumberT id) { siteID_ = id; ASSERT(GetSite() == id); } void SetRound(idNumberT id) { roundID_ = id; ASSERT(GetRound() == id); } void SetDate(dateT date) { date_ = date; ASSERT(GetDate() == date); } void SetEventDate(dateT edate) { eventDate_ = edate; ASSERT(GetEventDate() == edate); } void SetResult(resultT res) { result_ = res; ASSERT(GetResult() == res); } void SetVariationCount(unsigned x) { nVariations_ = EncodeCount(x); } void SetCommentCount(unsigned x) { nComments_ = EncodeCount(x); } void SetNagCount(unsigned x) { nNags_ = EncodeCount(x); } void SetRawVariationCount(unsigned x) { nVariations_ = x; ASSERT(x == nVariations_); } void SetRawCommentCount(unsigned x) { nComments_ = x; ASSERT(x == nComments_); } void SetRawNagCount(unsigned x) { nNags_ = x; ASSERT(x == nNags_); } void SetNumHalfMoves(ushort b) { numHalfMoves_ = b; ASSERT(GetNumHalfMoves() == b); } void SetFinalMatSig(matSigT ms) { finalMatSig_ = ms; ASSERT(GetFinalMatSig() == ms); } void SetStoredLineCode(byte b) { storedLineCode_ = b; ASSERT(GetStoredLineCode() == b); } void SetEcoCode(ecoT eco) { ECOcode_ = eco; ASSERT(GetEcoCode() == eco); } void SetFlag(uint32_t flagMask, bool set) { if (set) flags_ |= flagMask; else flags_ &= ~flagMask; } // Handy functions that do not directly access member vars. uint GetYear () const { return date_GetYear (GetDate()); } uint GetMonth() const { return date_GetMonth (GetDate()); } uint GetDay () const { return date_GetDay (GetDate()); } void SetPlayer(colorT col, idNumberT id) { return (col == BLACK) ? SetBlack(id) : SetWhite(id); } const char* GetWhiteName (const NameBase* nb) const { return nb->GetName (NAME_PLAYER, GetWhite()); } const char* GetBlackName (const NameBase* nb) const { return nb->GetName (NAME_PLAYER, GetBlack()); } const char* GetEventName (const NameBase* nb) const { return nb->GetName (NAME_EVENT, GetEvent()); } const char* GetSiteName (const NameBase* nb) const { return nb->GetName (NAME_SITE, GetSite()); } const char* GetRoundName (const NameBase* nb) const { return nb->GetName (NAME_ROUND, GetRound()); } eloT GetWhiteElo (const NameBase* nb) const { eloT r = GetWhiteElo(); if (r == 0 && nb != 0) return nb->GetElo (GetWhite()); return r; } eloT GetBlackElo (const NameBase* nb) const { eloT r = GetBlackElo(); if (r == 0 && nb != 0) return nb->GetElo (GetBlack()); return r; } byte GetRating(const NameBase* nb) const; bool GetStartFlag () const { return GetFlag(1 << IDX_FLAG_START); } bool GetPromotionsFlag () const { return GetFlag(1 << IDX_FLAG_PROMO); } bool GetUnderPromoFlag() const { return GetFlag(1 << IDX_FLAG_UPROMO); } bool GetCommentsFlag () const { return (GetCommentCount() > 0); } bool GetVariationsFlag () const { return (GetVariationCount() > 0); } bool GetNagsFlag () const { return (GetNagCount() > 0); } bool GetDeleteFlag () const { return GetFlag(1 << IDX_FLAG_DELETE); } static uint CharToFlag (char ch); static uint32_t CharToFlagMask (char flag); static uint32_t StrToFlagMask (const char* flags); uint GetFlagStr(char* dest, const char* flags) const; void SetStartFlag (bool b) { SetFlag(1 << IDX_FLAG_START, b); } void SetPromotionsFlag (bool b) { SetFlag(1 << IDX_FLAG_PROMO, b); } void SetUnderPromoFlag (bool b) { SetFlag(1 << IDX_FLAG_UPROMO, b); } void SetDeleteFlag (bool b) { SetFlag(1 << IDX_FLAG_DELETE, b); } void clearFlags() { return SetFlag(IDX_MASK_ALLFLAGS, false); } enum { // IndexEntry Flag types: IDX_FLAG_START = 0, // Game has own start position. IDX_FLAG_PROMO = 1, // Game contains promotion(s). IDX_FLAG_UPROMO = 2, // Game contains promotion(s). IDX_FLAG_DELETE = 3, // Game marked for deletion. IDX_FLAG_WHITE_OP = 4, // White openings flag. IDX_FLAG_BLACK_OP = 5, // Black openings flag. IDX_FLAG_MIDDLEGAME = 6, // Middlegames flag. IDX_FLAG_ENDGAME = 7, // Endgames flag. IDX_FLAG_NOVELTY = 8, // Novelty flag. IDX_FLAG_PAWN = 9, // Pawn structure flag. IDX_FLAG_TACTICS = 10, // Tactics flag. IDX_FLAG_KSIDE = 11, // Kingside play flag. IDX_FLAG_QSIDE = 12, // Queenside play flag. IDX_FLAG_BRILLIANCY = 13, // Brilliancy or good play. IDX_FLAG_BLUNDER = 14, // Blunder or bad play. IDX_FLAG_USER = 15, // User-defined flag. IDX_FLAG_CUSTOM1 = 16, // Custom flag. IDX_FLAG_CUSTOM2 = 17, // Custom flag. IDX_FLAG_CUSTOM3 = 18, // Custom flag. IDX_FLAG_CUSTOM4 = 19, // Custom flag. IDX_FLAG_CUSTOM5 = 20, // Custom flag. IDX_FLAG_CUSTOM6 = 21, // Custom flag. IDX_NUM_FLAGS = 22, }; static const uint32_t IDX_MASK_ALLFLAGS = 0xFFFFFFFF; private: static uint EncodeCount (uint x) { if (x <= 10) { return x; } if (x <= 12) { return 10; } if (x <= 17) { return 11; } // 11 indicates 15 (13-17) if (x <= 24) { return 12; } // 12 indicates 20 (18-24) if (x <= 34) { return 13; } // 13 indicates 30 (25-34) if (x <= 44) { return 14; } // 14 indicates 40 (35-44) return 15; // 15 indicates 50 or more } static uint DecodeCount (uint x) { static uint countCodes[16] = {0,1,2,3,4,5,6,7,8,9,10,15,20,30,40,50}; return countCodes[x & 15]; } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // IndexEntry::Write(): // Writes a single index entry to an open index file. // INDEX_ENTRY_SIZE must be updated template errorT IndexEntry::Write(T* file, versionT version) const { if (version < 400) // Cannot write old-version index files: return ERROR_FileVersion; char buf[INDEX_ENTRY_SIZE]; char* buf_it = buf; auto WriteOneByte = [&buf_it](uint8_t v) { *buf_it++ = v; }; auto WriteTwoBytes = [&WriteOneByte](uint16_t v) { WriteOneByte(static_cast(v >> 8)); WriteOneByte(static_cast(v)); }; auto WriteFourBytes = [&WriteTwoBytes](uint32_t v) { WriteTwoBytes(static_cast(v >> 16)); WriteTwoBytes(static_cast(v)); }; const IndexEntry* ie = this; ASSERT(ie->GetOffset() < (1ULL << 32)); WriteFourBytes(static_cast(ie->GetOffset())); ASSERT(ie->GetLength() < (1ULL << 17)); WriteTwoBytes(static_cast(ie->GetLength())); uint8_t len_flags = static_cast(ie->GetLength() >> 9) & 0x80; len_flags |= static_cast(ie->flags_ >> 16) & 0x3F; WriteOneByte(len_flags); WriteTwoBytes(static_cast(ie->flags_)); // WhiteID and BlackID are 20-bit values, EventID and SiteID are // 19-bit values, and RoundID is an 18-bit value. // WhiteID high 4 bits = bits 4-7 of WhiteBlack_High. // BlackID high 4 bits = bits 0-3 of WhiteBlack_High. // EventID high 3 bits = bits 5-7 of EventSiteRnd_high. // SiteID high 3 bits = bits 2-4 of EventSiteRnd_high. // RoundID high 2 bits = bits 0-1 of EventSiteRnd_high. ASSERT(std::max(ie->GetWhite(), ie->GetBlack()) < (1ULL << 20)); uint32_t WhiteID_Low = ie->GetWhite(); uint32_t BlackID_Low = ie->GetBlack(); uint32_t WhiteBlack_High = (WhiteID_Low & 0x0F0000) >> 12; WhiteBlack_High |= (BlackID_Low & 0x0F0000) >> 16; WriteOneByte(static_cast(WhiteBlack_High)); WriteTwoBytes(static_cast(WhiteID_Low)); WriteTwoBytes(static_cast(BlackID_Low)); ASSERT(std::max(ie->GetEvent(), ie->GetSite()) < (1ULL << 19)); ASSERT(ie->GetRound() < (1ULL << 18)); uint32_t EventID_Low = ie->GetEvent(); uint32_t SiteID_Low = ie->GetSite(); uint32_t RoundID_Low = ie->GetRound(); uint32_t EventSiteRnd_High = (EventID_Low & 0x070000) >> 11; EventSiteRnd_High |= (SiteID_Low & 0x070000) >> 14; EventSiteRnd_High |= (RoundID_Low & 0x030000) >> 16; WriteOneByte(static_cast(EventSiteRnd_High)); WriteTwoBytes(static_cast(EventID_Low)); WriteTwoBytes(static_cast(SiteID_Low)); WriteTwoBytes(static_cast(RoundID_Low)); uint16_t varCounts = ie->nVariations_ & 0x0F; varCounts |= static_cast(ie->nComments_ & 0x0F) << 4; varCounts |= static_cast(ie->nNags_ & 0x0F) << 8; varCounts |= static_cast(ie->GetResult() & 0x0F) << 12; WriteTwoBytes(varCounts); WriteTwoBytes(ie->GetEcoCode()); // Due to a compact encoding format, the EventDate // must be within a few years of the Date. uint32_t date = ie->GetDate() & 0xFFFFF; uint32_t edate = ie->GetEventDate(); uint32_t eyear = date_GetYear(edate); uint32_t dyear = date_GetYear(date); if ((eyear + 3) < dyear || eyear > (dyear + 3)) { edate = ZERO_DATE; } else { eyear = (eyear + 4 - dyear) & 7; edate = (eyear << 9) | (date_GetMonth(edate) << 5) | date_GetDay(edate); } WriteFourBytes((edate << 20) | date); // Elo ratings and rating types: 2 bytes each. uint16_t wElo = std::min(MAX_ELO, ie->GetWhiteElo()); wElo |= static_cast(ie->GetWhiteRatingType()) << 12; uint16_t bElo = std::min(MAX_ELO, ie->GetBlackElo()); bElo |= static_cast(ie->GetBlackRatingType()) << 12; WriteTwoBytes(wElo); WriteTwoBytes(bElo); ASSERT(ie->GetFinalMatSig() < (1ULL << 24)); ASSERT(ie->GetStoredLineCode() < (1ULL << 8)); uint32_t FinalMatSig = ie->GetFinalMatSig(); FinalMatSig |= static_cast(ie->GetStoredLineCode()) << 24; WriteFourBytes(FinalMatSig); // The first byte of HomePawnData has high bits of the NumHalfMoves // counter in its top two bits: uint16_t nMoves = ie->GetNumHalfMoves(); ASSERT(nMoves < (1ULL << 10)); WriteOneByte(static_cast(nMoves)); uint8_t pawnData0 = static_cast(nMoves >> 8) << 6; // Write the 9-byte homePawnData array: const byte* pb = ie->GetHomePawnData(); pawnData0 |= *pb & 0x3F; WriteOneByte(pawnData0); std::copy(pb + 1, pb + HPSIG_SIZE, buf_it); return file->sputn(buf, INDEX_ENTRY_SIZE) == INDEX_ENTRY_SIZE ? OK : ERROR_FileWrite; } inline byte IndexEntry::GetRating(const NameBase* nb) const { eloT welo = GetWhiteElo(); eloT belo = GetBlackElo(); if (welo == 0) { welo = nb->GetElo (GetWhite()); } if (belo == 0) { belo = nb->GetElo (GetBlack()); } int rating = static_cast(welo + belo) / 140; // Bonus for comments or Nags if (GetCommentCount() > 2 || GetNagCount() > 2) { if (rating < 21) { // Missing elo rating = 40; } else { rating += 6; } } // Early draw penalty if (GetResult() == RESULT_Draw) { uint moves = GetNumHalfMoves(); if (moves < 80) { rating -= 3; if (moves < 60) { rating -= 2; if (moves < 40) rating -= 2; } } } if (rating < 0) return 0; else return static_cast (rating); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // IndexEntry::CharToFlag(): // Returns the flag number corresponding to the given character. inline uint IndexEntry::CharToFlag (char ch) { uint flag = 0; switch (toupper(ch)) { case 'D': flag = IDX_FLAG_DELETE; break; case 'W': flag = IDX_FLAG_WHITE_OP; break; case 'B': flag = IDX_FLAG_BLACK_OP; break; case 'M': flag = IDX_FLAG_MIDDLEGAME; break; case 'E': flag = IDX_FLAG_ENDGAME; break; case 'N': flag = IDX_FLAG_NOVELTY; break; case 'P': flag = IDX_FLAG_PAWN; break; case 'T': flag = IDX_FLAG_TACTICS; break; case 'K': flag = IDX_FLAG_KSIDE; break; case 'Q': flag = IDX_FLAG_QSIDE; break; case '!': flag = IDX_FLAG_BRILLIANCY; break; case '?': flag = IDX_FLAG_BLUNDER; break; case 'U': flag = IDX_FLAG_USER; break; case '1': flag = IDX_FLAG_CUSTOM1; break; case '2': flag = IDX_FLAG_CUSTOM2; break; case '3': flag = IDX_FLAG_CUSTOM3; break; case '4': flag = IDX_FLAG_CUSTOM4; break; case '5': flag = IDX_FLAG_CUSTOM5; break; case '6': flag = IDX_FLAG_CUSTOM6; break; } return flag; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // IndexEntry::CharToFlagMask(): // Transform a char in a mask that can be used with GetFlag() and SetFlag() inline uint32_t IndexEntry::CharToFlagMask(char flag) { switch (toupper(flag)) { case 'S': return 1 << IDX_FLAG_START; case 'X': return 1 << IDX_FLAG_PROMO; case 'Y': return 1 << IDX_FLAG_UPROMO; case 'D': return 1 << IDX_FLAG_DELETE; case 'W': return 1 << IDX_FLAG_WHITE_OP; case 'B': return 1 << IDX_FLAG_BLACK_OP; case 'M': return 1 << IDX_FLAG_MIDDLEGAME; case 'E': return 1 << IDX_FLAG_ENDGAME; case 'N': return 1 << IDX_FLAG_NOVELTY; case 'P': return 1 << IDX_FLAG_PAWN; case 'T': return 1 << IDX_FLAG_TACTICS; case 'K': return 1 << IDX_FLAG_KSIDE; case 'Q': return 1 << IDX_FLAG_QSIDE; case '!': return 1 << IDX_FLAG_BRILLIANCY; case '?': return 1 << IDX_FLAG_BLUNDER; case 'U': return 1 << IDX_FLAG_USER; case '1': return 1 << IDX_FLAG_CUSTOM1; case '2': return 1 << IDX_FLAG_CUSTOM2; case '3': return 1 << IDX_FLAG_CUSTOM3; case '4': return 1 << IDX_FLAG_CUSTOM4; case '5': return 1 << IDX_FLAG_CUSTOM5; case '6': return 1 << IDX_FLAG_CUSTOM6; } ASSERT(0); return 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // IndexEntry::StrToFlagMask(): // Transform a string in a mask that can be used with GetFlag() and SetFlag() inline uint32_t IndexEntry::StrToFlagMask(const char* flags) { if (flags == 0) return 0; uint32_t res = 0; while (*flags != 0) { res |= IndexEntry::CharToFlagMask(*(flags++)); } return res; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // IndexEntry::GetFlagStr(): // Fills in the provided flag string with information on the // user-settable flags set for this game. // Returns the number of specified flags that are turned on. inline uint IndexEntry::GetFlagStr(char* dest, const char* flags) const { if (flags == NULL) { flags = "DWBMENPTKQ!?U123456"; } uint count = 0; while (*flags != 0) { uint32_t mask = CharToFlagMask(*flags); ASSERT(mask != 0); if (GetFlag(mask)) { *dest++ = *flags; count++; } flags++; } *dest = 0; return count; } #endif chessx-master/dep/scid/code/src/textbuf.h0000755000076500000240000000661614666426276017552 0ustar jensstaff/////////////////////////////////////////////////////////////////////////// // // FILE: textbuf.h // TextBuffer class // // Part of: Scid (Shane's Chess Information Database) // Version: 2.7 // // Notice: Copyright (c) 1999-2001 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // /////////////////////////////////////////////////////////////////////////// #ifndef SCID_TEXTBUF_H #define SCID_TEXTBUF_H #include "common.h" #include class TextBuffer { private: //---------------------------------- // TextBuffer: Data Structures uint Column; uint IndentColumn; uint WrapColumn; uint LineIsEmpty; // true if current line is empty. uint LineCount; uint ByteCount; uint BufferSize; bool ConvertNewlines; // If true, convert newlines to spaces. char * Buffer; char * Current; bool PausedTranslations; bool HasTranslations; const char * Translation [256]; inline void AddChar (char ch); TextBuffer(const TextBuffer&); TextBuffer& operator=(const TextBuffer&); //---------------------------------- // TextBuffer: Public Functions public: TextBuffer() { Init(); SetBufferSize(1280000); } ~TextBuffer() { Free(); } void Init (); void Free (); void Empty (); void SetBufferSize (uint length); uint GetBufferSize() { return BufferSize; } uint GetByteCount() { return ByteCount; } uint GetLineCount() { return LineCount; } uint GetColumn() { return Column; } uint GetWrapColumn () { return WrapColumn; } void SetWrapColumn (uint column) { WrapColumn = column; } uint GetIndent () { return IndentColumn; } void SetIndent (uint column) { IndentColumn = column; } char * GetBuffer () { return Buffer; } void NewlinesToSpaces (bool b) { ConvertNewlines = b; } void AddTranslation (char ch, const char * str); // void ClearTranslation (char ch) { Translation[ch] = NULL; } // Changed ch to int, to avoid compiler warnings. void ClearTranslation (int ch) { Translation[ch] = NULL; } void ClearTranslations () { HasTranslations = false; } void PauseTranslations () { PausedTranslations = true; } void ResumeTranslations () { PausedTranslations = false; } errorT NewLine(); errorT Indent(); errorT PrintLine (const char * str); errorT PrintWord (const char * str); errorT PrintString (const char * str); errorT PrintSpace (); errorT PrintChar (char b); errorT PrintInt (uint i, const char * str); inline errorT PrintInt (uint i) { return PrintInt (i, ""); } }; inline void TextBuffer::AddChar (char ch) { if (HasTranslations && !PausedTranslations) { byte b = (byte) ch; const char * str = Translation[b]; if (str != NULL) { const char * s = str; while (*s) { *Current++ = *s++; ByteCount++; } return; } } *Current = ch; Current++; ByteCount++; } #endif // SCID_TEXTBUF_H /////////////////////////////////////////////////////////////////////////// // EOF: textbuf.h /////////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/sqmove.h0000755000076500000240000002741714666426276017405 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: sqmove.h // Square movement lookup table // // Part of: Scid (Shane's Chess Information Database) // Version: 3.4 // // Notice: Copyright (c) 1999-2002 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// #ifndef SCID_SQMOVE_H #define SCID_SQMOVE_H #include "common.h" constexpr uint MAX_SQUARELIST = 65; // 64 squares plus null square class SquareList { uint ListSize; squareT Squares[MAX_SQUARELIST]; public: SquareList() { ListSize = 0; } void Init() { ListSize = 0; } void Clear() { ListSize = 0; } void Add(squareT sq) { Squares[ListSize] = sq; ListSize++; } uint Size() { return ListSize; } squareT Get(uint index) { ASSERT(index < ListSize); return Squares[index]; } bool Contains(squareT sq) { for (uint i = 0; i < ListSize; i++) { if (Squares[i] == sq) { return true; } } return false; } void Remove(uint index) { ASSERT(index < ListSize); ListSize--; if (index != ListSize) { Squares[index] = Squares[ListSize]; } } }; class SquareSet { uint Bits_a1h4; uint Bits_a5h8; public: SquareSet() { Bits_a1h4 = Bits_a5h8 = 0; } SquareSet(squareT* squares) { Bits_a1h4 = Bits_a5h8 = 0; AddAll(squares); } void Clear(void) { Bits_a1h4 = Bits_a5h8 = 0; } void AddAll(void) { Bits_a1h4 = Bits_a5h8 = 0xFFFFFFFFu; } void Add(squareT sq) { ASSERT(sq <= H8); if (sq <= H4) { Bits_a1h4 |= (1 << sq); } else { Bits_a5h8 |= (1 << (sq & 31)); } } void AddAll(squareT* squares) { while (true) { squareT sq = *squares; if (sq == NULL_SQUARE) { break; } ASSERT(sq <= H8); squares++; if (sq <= H4) { Bits_a1h4 |= (1 << sq); } else { Bits_a5h8 |= (1 << (sq & 31)); } } } bool Contains(squareT sq) { ASSERT(sq <= H8); if (sq <= H4) { return (Bits_a1h4 & (1 << sq)) != 0; } else { return (Bits_a5h8 & (1 << (sq & 31))) != 0; } } void Remove(squareT sq) { ASSERT(sq <= H8); if (sq <= H4) { Bits_a1h4 &= ~(1 << sq); } else { Bits_a5h8 &= ~(1 << (sq & 31)); } } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // sqMove // Array indexed by square value and direction, giving the square // obtained by moving from the square in that direction. constexpr squareT sqMove[66][11] = { /* UP DOWN LEFT UL DL RIGHT UR DR */ { /* A1 */ NS, A2, NS, NS, NS, NS, NS, NS, B1, B2, NS }, { /* B1 */ NS, B2, NS, NS, A1, A2, NS, NS, C1, C2, NS }, { /* C1 */ NS, C2, NS, NS, B1, B2, NS, NS, D1, D2, NS }, { /* D1 */ NS, D2, NS, NS, C1, C2, NS, NS, E1, E2, NS }, { /* E1 */ NS, E2, NS, NS, D1, D2, NS, NS, F1, F2, NS }, { /* F1 */ NS, F2, NS, NS, E1, E2, NS, NS, G1, G2, NS }, { /* G1 */ NS, G2, NS, NS, F1, F2, NS, NS, H1, H2, NS }, { /* H1 */ NS, H2, NS, NS, G1, G2, NS, NS, NS, NS, NS }, { /* A2 */ NS, A3, A1, NS, NS, NS, NS, NS, B2, B3, B1 }, { /* B2 */ NS, B3, B1, NS, A2, A3, A1, NS, C2, C3, C1 }, { /* C2 */ NS, C3, C1, NS, B2, B3, B1, NS, D2, D3, D1 }, { /* D2 */ NS, D3, D1, NS, C2, C3, C1, NS, E2, E3, E1 }, { /* E2 */ NS, E3, E1, NS, D2, D3, D1, NS, F2, F3, F1 }, { /* F2 */ NS, F3, F1, NS, E2, E3, E1, NS, G2, G3, G1 }, { /* G2 */ NS, G3, G1, NS, F2, F3, F1, NS, H2, H3, H1 }, { /* H2 */ NS, H3, H1, NS, G2, G3, G1, NS, NS, NS, NS }, { /* A3 */ NS, A4, A2, NS, NS, NS, NS, NS, B3, B4, B2 }, { /* B3 */ NS, B4, B2, NS, A3, A4, A2, NS, C3, C4, C2 }, { /* C3 */ NS, C4, C2, NS, B3, B4, B2, NS, D3, D4, D2 }, { /* D3 */ NS, D4, D2, NS, C3, C4, C2, NS, E3, E4, E2 }, { /* E3 */ NS, E4, E2, NS, D3, D4, D2, NS, F3, F4, F2 }, { /* F3 */ NS, F4, F2, NS, E3, E4, E2, NS, G3, G4, G2 }, { /* G3 */ NS, G4, G2, NS, F3, F4, F2, NS, H3, H4, H2 }, { /* H3 */ NS, H4, H2, NS, G3, G4, G2, NS, NS, NS, NS }, { /* A4 */ NS, A5, A3, NS, NS, NS, NS, NS, B4, B5, B3 }, { /* B4 */ NS, B5, B3, NS, A4, A5, A3, NS, C4, C5, C3 }, { /* C4 */ NS, C5, C3, NS, B4, B5, B3, NS, D4, D5, D3 }, { /* D4 */ NS, D5, D3, NS, C4, C5, C3, NS, E4, E5, E3 }, { /* E4 */ NS, E5, E3, NS, D4, D5, D3, NS, F4, F5, F3 }, { /* F4 */ NS, F5, F3, NS, E4, E5, E3, NS, G4, G5, G3 }, { /* G4 */ NS, G5, G3, NS, F4, F5, F3, NS, H4, H5, H3 }, { /* H4 */ NS, H5, H3, NS, G4, G5, G3, NS, NS, NS, NS }, { /* A5 */ NS, A6, A4, NS, NS, NS, NS, NS, B5, B6, B4 }, { /* B5 */ NS, B6, B4, NS, A5, A6, A4, NS, C5, C6, C4 }, { /* C5 */ NS, C6, C4, NS, B5, B6, B4, NS, D5, D6, D4 }, { /* D5 */ NS, D6, D4, NS, C5, C6, C4, NS, E5, E6, E4 }, { /* E5 */ NS, E6, E4, NS, D5, D6, D4, NS, F5, F6, F4 }, { /* F5 */ NS, F6, F4, NS, E5, E6, E4, NS, G5, G6, G4 }, { /* G5 */ NS, G6, G4, NS, F5, F6, F4, NS, H5, H6, H4 }, { /* H5 */ NS, H6, H4, NS, G5, G6, G4, NS, NS, NS, NS }, { /* A6 */ NS, A7, A5, NS, NS, NS, NS, NS, B6, B7, B5 }, { /* B6 */ NS, B7, B5, NS, A6, A7, A5, NS, C6, C7, C5 }, { /* C6 */ NS, C7, C5, NS, B6, B7, B5, NS, D6, D7, D5 }, { /* D6 */ NS, D7, D5, NS, C6, C7, C5, NS, E6, E7, E5 }, { /* E6 */ NS, E7, E5, NS, D6, D7, D5, NS, F6, F7, F5 }, { /* F6 */ NS, F7, F5, NS, E6, E7, E5, NS, G6, G7, G5 }, { /* G6 */ NS, G7, G5, NS, F6, F7, F5, NS, H6, H7, H5 }, { /* H6 */ NS, H7, H5, NS, G6, G7, G5, NS, NS, NS, NS }, { /* A7 */ NS, A8, A6, NS, NS, NS, NS, NS, B7, B8, B6 }, { /* B7 */ NS, B8, B6, NS, A7, A8, A6, NS, C7, C8, C6 }, { /* C7 */ NS, C8, C6, NS, B7, B8, B6, NS, D7, D8, D6 }, { /* D7 */ NS, D8, D6, NS, C7, C8, C6, NS, E7, E8, E6 }, { /* E7 */ NS, E8, E6, NS, D7, D8, D6, NS, F7, F8, F6 }, { /* F7 */ NS, F8, F6, NS, E7, E8, E6, NS, G7, G8, G6 }, { /* G7 */ NS, G8, G6, NS, F7, F8, F6, NS, H7, H8, H6 }, { /* H7 */ NS, H8, H6, NS, G7, G8, G6, NS, NS, NS, NS }, { /* A8 */ NS, NS, A7, NS, NS, NS, NS, NS, B8, NS, B7 }, { /* B8 */ NS, NS, B7, NS, A8, NS, A7, NS, C8, NS, C7 }, { /* C8 */ NS, NS, C7, NS, B8, NS, B7, NS, D8, NS, D7 }, { /* D8 */ NS, NS, D7, NS, C8, NS, C7, NS, E8, NS, E7 }, { /* E8 */ NS, NS, E7, NS, D8, NS, D7, NS, F8, NS, F7 }, { /* F8 */ NS, NS, F7, NS, E8, NS, E7, NS, G8, NS, G7 }, { /* G8 */ NS, NS, G7, NS, F8, NS, F7, NS, H8, NS, H7 }, { /* H8 */ NS, NS, H7, NS, G8, NS, G7, NS, NS, NS, NS }, { /* NS */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS }, { /* NS */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // sqLast // Array indexed by square value and direction, giving the last // square reached by moving from the square in that direction. // The last square is the same as the original square if moving // in the specified direction would move off the board. constexpr squareT sqLast[66][11] = { /* UP DOWN LEFT UL DL RIGHT UR DR */ { /* A1 */ NS, A8, A1, NS, A1, A1, A1, NS, H1, H8, A1 }, { /* B1 */ NS, B8, B1, NS, A1, A2, B1, NS, H1, H7, B1 }, { /* C1 */ NS, C8, C1, NS, A1, A3, C1, NS, H1, H6, C1 }, { /* D1 */ NS, D8, D1, NS, A1, A4, D1, NS, H1, H5, D1 }, { /* E1 */ NS, E8, E1, NS, A1, A5, E1, NS, H1, H4, E1 }, { /* F1 */ NS, F8, F1, NS, A1, A6, F1, NS, H1, H3, F1 }, { /* G1 */ NS, G8, G1, NS, A1, A7, G1, NS, H1, H2, G1 }, { /* H1 */ NS, H8, H1, NS, A1, A8, H1, NS, H1, H1, H1 }, { /* A2 */ NS, A8, A1, NS, A2, A2, A2, NS, H2, G8, B1 }, { /* B2 */ NS, B8, B1, NS, A2, A3, A1, NS, H2, H8, C1 }, { /* C2 */ NS, C8, C1, NS, A2, A4, B1, NS, H2, H7, D1 }, { /* D2 */ NS, D8, D1, NS, A2, A5, C1, NS, H2, H6, E1 }, { /* E2 */ NS, E8, E1, NS, A2, A6, D1, NS, H2, H5, F1 }, { /* F2 */ NS, F8, F1, NS, A2, A7, E1, NS, H2, H4, G1 }, { /* G2 */ NS, G8, G1, NS, A2, A8, F1, NS, H2, H3, H1 }, { /* H2 */ NS, H8, H1, NS, A2, B8, G1, NS, H2, H2, H2 }, { /* A3 */ NS, A8, A1, NS, A3, A3, A3, NS, H3, F8, C1 }, { /* B3 */ NS, B8, B1, NS, A3, A4, A2, NS, H3, G8, D1 }, { /* C3 */ NS, C8, C1, NS, A3, A5, A1, NS, H3, H8, E1 }, { /* D3 */ NS, D8, D1, NS, A3, A6, B1, NS, H3, H7, F1 }, { /* E3 */ NS, E8, E1, NS, A3, A7, C1, NS, H3, H6, G1 }, { /* F3 */ NS, F8, F1, NS, A3, A8, D1, NS, H3, H5, H1 }, { /* G3 */ NS, G8, G1, NS, A3, B8, E1, NS, H3, H4, H2 }, { /* H3 */ NS, H8, H1, NS, A3, C8, F1, NS, H3, H3, H3 }, { /* A4 */ NS, A8, A1, NS, A4, A4, A4, NS, H4, E8, D1 }, { /* B4 */ NS, B8, B1, NS, A4, A5, A3, NS, H4, F8, E1 }, { /* C4 */ NS, C8, C1, NS, A4, A6, A2, NS, H4, G8, F1 }, { /* D4 */ NS, D8, D1, NS, A4, A7, A1, NS, H4, H8, G1 }, { /* E4 */ NS, E8, E1, NS, A4, A8, B1, NS, H4, H7, H1 }, { /* F4 */ NS, F8, F1, NS, A4, B8, C1, NS, H4, H6, H2 }, { /* G4 */ NS, G8, G1, NS, A4, C8, D1, NS, H4, H5, H3 }, { /* H4 */ NS, H8, H1, NS, A4, D8, E1, NS, H4, H4, H4 }, { /* A5 */ NS, A8, A1, NS, A5, A5, A5, NS, H5, D8, E1 }, { /* B5 */ NS, B8, B1, NS, A5, A6, A4, NS, H5, E8, F1 }, { /* C5 */ NS, C8, C1, NS, A5, A7, A3, NS, H5, F8, G1 }, { /* D5 */ NS, D8, D1, NS, A5, A8, A2, NS, H5, G8, H1 }, { /* E5 */ NS, E8, E1, NS, A5, B8, A1, NS, H5, H8, H2 }, { /* F5 */ NS, F8, F1, NS, A5, C8, B1, NS, H5, H7, H3 }, { /* G5 */ NS, G8, G1, NS, A5, D8, C1, NS, H5, H6, H4 }, { /* H5 */ NS, H8, H1, NS, A5, E8, D1, NS, H5, H5, H5 }, { /* A6 */ NS, A8, A1, NS, A6, A6, A6, NS, H6, C8, F1 }, { /* B6 */ NS, B8, B1, NS, A6, A7, A5, NS, H6, D8, G1 }, { /* C6 */ NS, C8, C1, NS, A6, A8, A4, NS, H6, E8, H1 }, { /* D6 */ NS, D8, D1, NS, A6, B8, A3, NS, H6, F8, H2 }, { /* E6 */ NS, E8, E1, NS, A6, C8, A2, NS, H6, G8, H3 }, { /* F6 */ NS, F8, F1, NS, A6, D8, A1, NS, H6, H8, H4 }, { /* G6 */ NS, G8, G1, NS, A6, E8, B1, NS, H6, H7, H5 }, { /* H6 */ NS, H8, H1, NS, A6, F8, C1, NS, H6, H6, H6 }, { /* A7 */ NS, A8, A1, NS, A7, A7, A7, NS, H7, B8, G1 }, { /* B7 */ NS, B8, B1, NS, A7, A8, A6, NS, H7, C8, H1 }, { /* C7 */ NS, C8, C1, NS, A7, B8, A5, NS, H7, D8, H2 }, { /* D7 */ NS, D8, D1, NS, A7, C8, A4, NS, H7, E8, H3 }, { /* E7 */ NS, E8, E1, NS, A7, D8, A3, NS, H7, F8, H4 }, { /* F7 */ NS, F8, F1, NS, A7, E8, A2, NS, H7, G8, H5 }, { /* G7 */ NS, G8, G1, NS, A7, F8, A1, NS, H7, H8, H6 }, { /* H7 */ NS, H8, H1, NS, A7, G8, B1, NS, H7, H7, H7 }, { /* A8 */ NS, A8, A1, NS, A8, A8, A8, NS, H8, A8, H1 }, { /* B8 */ NS, B8, B1, NS, A8, B8, A7, NS, H8, B8, H2 }, { /* C8 */ NS, C8, C1, NS, A8, C8, A6, NS, H8, C8, H3 }, { /* D8 */ NS, D8, D1, NS, A8, D8, A5, NS, H8, D8, H4 }, { /* E8 */ NS, E8, E1, NS, A8, E8, A4, NS, H8, E8, H5 }, { /* F8 */ NS, F8, F1, NS, A8, F8, A3, NS, H8, F8, H6 }, { /* G8 */ NS, G8, G1, NS, A8, G8, A2, NS, H8, G8, H7 }, { /* H8 */ NS, H8, H1, NS, A8, H8, A1, NS, H8, H8, H8 }, { /* NS */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS }, { /* NS */ NS, NS, NS, NS, NS, NS, NS, NS, NS, NS, NS } }; // square_Move(): Return the new square resulting from moving in // direction d from x. constexpr squareT square_Move(squareT sq, directionT dir) { return sqMove[sq][dir]; } // square_Last(): // Return the last square reached by moving as far as possible in // the direction d from the square sq. If sq is a valid on-board // square and d is a valid direction, the result will always be // a valid on-board square; the result will be the same as the // input square if moving in the specified direction would end // up off the board. constexpr squareT square_Last (squareT sq, directionT dir) { return sqLast[sq][dir]; } #endif ////////////////////////////////////////////////////////////////////// // EOF: sqmove.h ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/codec_scid4.h0000755000076500000240000001677014666426276020236 0ustar jensstaff/* * Copyright (C) 2016-2018 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . * */ /** @file * Implements the CodecSCID4 class that manages databases encoded in SCID * format v4. */ #ifndef CODEC_SCID4_H #define CODEC_SCID4_H #include "codec_native.h" #include "filebuf.h" #include /** * This class manages databases encoded in SCID format v4. */ class CodecSCID4 : public CodecNative { std::vector filenames_; Filebuf idxfile_; FilebufAppend gfile_; char gamecache_[1ULL << 17]; enum : uint64_t { LIMIT_GAMEOFFSET = 1ULL << 32, LIMIT_GAMELEN = 1ULL << 17, LIMIT_NUMGAMES = 16777214ULL, // Three bytes -1 because GetAutoLoad uses // 0 to mean "no autoload" LIMIT_NAMELEN = 255 }; public: // ICodecDatabase interface Codec getType() const final { return ICodecDatabase::SCID4; } /** * Returns the full path of the three files (index, namebase and gamefile) * used by the database. */ std::vector getFilenames() const final { return filenames_; }; std::vector> getExtraInfo() const final { std::vector> res; res.emplace_back("type", std::to_string(idx_->Header.baseType)); res.emplace_back("description", idx_->Header.description); const auto autoload = std::min(idx_->Header.autoLoad, idx_->GetNumGames()); res.emplace_back("autoload", std::to_string(autoload)); res.emplace_back("flag1", idx_->Header.customFlagDesc[0]); res.emplace_back("flag2", idx_->Header.customFlagDesc[1]); res.emplace_back("flag3", idx_->Header.customFlagDesc[2]); res.emplace_back("flag4", idx_->Header.customFlagDesc[3]); res.emplace_back("flag5", idx_->Header.customFlagDesc[4]); res.emplace_back("flag6", idx_->Header.customFlagDesc[5]); return res; } errorT setExtraInfo(const char* tagname, const char* new_value) override { if (std::strcmp(tagname, "type") == 0) { idx_->Header.baseType = strGetUnsigned(new_value); } else if (std::strcmp(tagname, "description") == 0) { strncpy(idx_->Header.description, new_value, SCID_DESC_LENGTH); idx_->Header.description[SCID_DESC_LENGTH] = 0; } else if (std::strcmp(tagname, "autoload") == 0) { idx_->Header.autoLoad = strGetUnsigned(new_value); } else { auto len = std::strlen(tagname); if (len != 5 || !std::equal(tagname, tagname + 4, "flag")) return ERROR_CodecUnsupFeat; uint flag = IndexEntry::CharToFlag(tagname[4]); if (flag < IndexEntry::IDX_FLAG_CUSTOM1 || flag > IndexEntry::IDX_FLAG_CUSTOM6) return ERROR_CodecUnsupFeat; const auto idx = flag - IndexEntry::IDX_FLAG_CUSTOM1; char* dest = idx_->Header.customFlagDesc[idx]; strncpy(dest, new_value, CUSTOM_FLAG_DESC_LENGTH); dest[CUSTOM_FLAG_DESC_LENGTH] = 0; } idx_->Header.dirty_ = true; return OK; } const byte* getGameData(uint64_t offset, uint32_t length) final { if (offset >= gfile_.size()) return NULL; if (length >= LIMIT_GAMELEN) return NULL; if (gfile_.pubseekpos(offset) == -1) return NULL; if (gfile_.sgetn(gamecache_, length) != std::streamsize(length)) return NULL; return reinterpret_cast(gamecache_); } errorT saveIndexEntry(const IndexEntry& ie, gamenumT replaced) final { return dyn_saveIndexEntry(ie, replaced); } std::pair addName(nameT nt, const char* name) final { return dyn_addName(nt, name); } errorT flush() final; errorT dyn_open(fileModeT, const char*, const Progress&, Index*, NameBase*) final; public: // CodecNative interface /** * Stores the data into the .sg4 file. * @param src: valid pointer to a buffer that contains the game data * (encoded in native format). * @param length: the length of the buffer @e src (in bytes). * @returns * - on success, a @e std::pair containing OK and the offset of the stored * data (needed for retrieving the data with getGameData()). * - on failure, a @e std::pair containing an error code and 0. */ std::pair dyn_addGameData(const byte* src, size_t length) { ASSERT(src != 0); const char* data = reinterpret_cast(src); if (length >= LIMIT_GAMELEN) return std::make_pair(ERROR_GameLengthLimit, 0); // The SCID4 format uses 32-bits to store games' offset. uint64_t offset = gfile_.size(); if (offset >= LIMIT_GAMEOFFSET - length) return std::make_pair(ERROR_OffsetLimit, 0); // The SCID4 format stores games into blocks of 128KB. // If the current block does not have enough space, we fill it with // random data and use the next one. uint64_t blockSpace = LIMIT_GAMELEN - (offset % LIMIT_GAMELEN); if (blockSpace < length) { errorT err = gfile_.append(data, blockSpace); if (err != OK) return std::make_pair(err, 0); offset += blockSpace; } errorT err = gfile_.append(data, length); return std::make_pair(err, offset); } /** * Given a name (string), retrieve the corresponding ID. * The name is added to @e nb_ if do not already exists in the NameBase. * @param nt: nameT type of the name to retrieve. * @param name: the name to retrieve. * @returns * - on success, a @e std::pair containing OK and the ID. * - on failure, a @e std::pair containing an error code and 0. */ std::pair dyn_addName(nameT nt, const char* name) { const idNumberT MAX_ID[] = { 1048575, /* Player names: Maximum of 2^20 -1 = 1,048,575 */ 524287, /* Event names: Maximum of 2^19 -1 = 524,287 */ 524287, /* Site names: Maximum of 2^19 -1 = 524,287 */ 262143 /* Round names: Maximum of 2^18 -1 = 262,143 */ }; return nb_->addName(nt, name, LIMIT_NAMELEN, MAX_ID[nt]); } /** * Add an IndexEntry to @e idx_. * @param ie: the IndexEntry object to add. * @returns OK if successful or an error code. */ errorT dyn_addIndexEntry(const IndexEntry& ie) { const auto nGames = idx_->GetNumGames(); if (nGames >= LIMIT_NUMGAMES) return ERROR_NumGamesLimit; idx_->addEntry(ie); idx_->Header.dirty_ = true; return writeEntry(ie, nGames); } /** * Replace an IndexEntry. * @param ie: the IndexEntry with the new data. * @param replaced: valid gamenumT of the game to be replaced. * @returns OK if successful or an error code. */ errorT dyn_saveIndexEntry(const IndexEntry& ie, gamenumT replaced) { idx_->replaceEntry(ie, replaced); return writeEntry(ie, replaced); } private: errorT readIndex(const Progress& progress); errorT writeEntry(const IndexEntry& ie, gamenumT gnum) { if (idx_->seqWrite_ == 0 || (gnum != idx_->seqWrite_ + 1)) { std::streampos pos = gnum; pos = pos * INDEX_ENTRY_SIZE + INDEX_HEADER_SIZE; if (idxfile_.pubseekpos(pos) != pos) { idx_->seqWrite_ = 0; return ERROR_FileWrite; } } errorT res = ie.Write(&idxfile_, idx_->Header.version); idx_->seqWrite_ = (res == OK) ? gnum : 0; return res; } }; #endif chessx-master/dep/scid/code/src/codec.h0000755000076500000240000001355014666426276017141 0ustar jensstaff/* * Copyright (C) 2016-2017 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . * */ /** @file * Defines the ICodecDatabase interface, which encapsulates the data * representation of databases. */ #ifndef CODEC_H #define CODEC_H #include "common.h" #include #include class Game; class Index; class IndexEntry; class NameBase; class Progress; /** * This interface separates the logic of a database from its representation. * Ideally all the file I/O should be encapsulated in classes derived from this * interface. */ class ICodecDatabase { public: virtual ~ICodecDatabase(){}; enum Codec { MEMORY, SCID4, PGN }; /** * Creates a new object and calls the virtual function dyn_open(). * @param codec: the type of the object to be created. * @param fMode: a valid file mode. * @param filename: the full path of the database to be opened. * @param progress: a Progress object used for GUI communications. * @param idx: valid pointer to the Index object for this database. * @param nb: valid pointer to the NameBase object for this database. * @returns * - on success: a valid pointer to the new object and OK. * - on error: nullptr and the error code. */ static std::pair open(Codec codec, fileModeT fMode, const char* filename, const Progress& progress, Index* idx, NameBase* nb); /** * Returns the Codec type. */ virtual Codec getType() const = 0; /** * Returns the full path of the files used by the database. * The order of the filenames must be consistent for objects of the same * Codec type. */ virtual std::vector getFilenames() const = 0; /** * Returns a vector of tag pairs containing extra information about the * database (type, description, autoload, etc..) */ virtual std::vector> getExtraInfo() const = 0; /** * Store an extra information about the database (type, description, etc..) */ virtual errorT setExtraInfo(const char* tagname, const char* new_value) = 0; /** * Fetches the data of a game (excluding index info), encoded in native * format. * @param offset: offset of the requested game. * @param length: length of the game data (in bytes). * @returns * - a pointer to the game data. * - 0 (nullptr) on error. */ virtual const byte* getGameData(uint64_t offset, uint32_t length) = 0; /** * Add a game to the database. * @param srcIe: valid pointer to the header data. * @param srcNb: valid pointer to the NameBase containing srcIe's names. * @param srcData: valid pointer to a buffer containing the game data * (encoded in native format). * @param dataLen: length of the game data (in bytes). * @returns OK if successful or an error code. */ virtual errorT addGame(const IndexEntry* srcIe, const NameBase* srcNb, const byte* srcData, size_t dataLen) = 0; /** * Add a game to the database. * @param game: valid pointer to a Game object with the data of the game. * @returns OK if successful or an error code. */ virtual errorT addGame(Game* game) = 0; /** * Replaces a game in the database. * @param game: valid pointer to a Game object with the new data. * @param replaced: valid gamenumT of the game to be replaced * @returns OK if successful or an error code. */ virtual errorT saveGame(Game* game, gamenumT replaced) = 0; /** * Replaces a game's IndexEntry (which contains the header data of a game). * @param ie: reference to the IndexEntry with the new data. * @param replaced: valid gamenumT of the game to be replaced * @returns OK if successful or an error code. */ virtual errorT saveIndexEntry(const IndexEntry& ie, gamenumT replaced) = 0; /** * Adds a name (player, event, site or round) to the database. * @param nt: nameT type of the name to add. * @param name: the name to add. * @returns * - on success, a @e std::pair containing OK and the corresponding ID. * - on failure, a @e std::pair containing an error code and 0. */ virtual std::pair addName(nameT nt, const char* name) = 0; /** * Writes all pending output to the files. * @returns OK if successful or an error code. */ virtual errorT flush() = 0; private: /** * Opens/Creates a database. * This virtual function is called only once immediately after the class * constructor. * @param fMode: a valid file mode. * @param filename: the full path of the database to open. * @param progress: a Progress object used for GUI communications. * @param idx: valid pointer to the Index object for this database. * @param nb: valid pointer to the NameBase object for this database. * @returns * - OK: the object is ready to be used. * - ERROR_NameDataLoss: some names are corrupted and cannot be recovered, * however the object can still be used. * - Other error codes: the operation failed (the object must be destroyed). */ virtual errorT dyn_open(fileModeT fMode, const char* filename, const Progress& progress, Index* idx, NameBase* nb) = 0; }; #endif chessx-master/dep/scid/code/src/game.h0000755000076500000240000005131614666426276016777 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: game.h // Game class for Scid. // // Part of: Scid (Shane's Chess Information Database) // Version: 3.5 // // Notice: Copyright (c) 2000-2003 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// #ifndef SCID_GAME_H #define SCID_GAME_H #include "common.h" #include "date.h" #include "indexentry.h" #include "matsig.h" #include "movetree.h" #include "namebase.h" #include "position.h" #include #include #include #include class ByteBuffer; class TextBuffer; void transPieces(char *s); char transPiecesChar(char c); // Piece letters translation extern int language; // default to english // 0 = en, 1 = fr, 2 = es, 3 = de extern const char * langPieces[]; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game: Constants // Common NAG Annotation symbol values: const byte NAG_GoodMove = 1, NAG_PoorMove = 2, NAG_ExcellentMove = 3, NAG_Blunder = 4, NAG_InterestingMove = 5, NAG_DubiousMove = 6, NAG_OnlyMove = 8, // new NAG_Equal = 10, NAG_Unclear = 13, NAG_WhiteSlight = 14, NAG_BlackSlight = 15, NAG_WhiteClear = 16, NAG_BlackClear = 17, NAG_WhiteDecisive = 18, NAG_BlackDecisive = 19, NAG_WhiteCrushing = 20, NAG_BlackCrushing = 21, NAG_ZugZwang = 22, // new NAG_BlackZugZwang = 23, // new NAG_MoreRoom = 26, // new NAG_DevelopmentAdvantage = 35, // new NAG_WithInitiative = 36, //new NAG_WithAttack = 40, // new NAG_WithBlackAttack = 41, // new NAG_Compensation = 44, // from Whites perspective NAG_SlightCentre = 48, // from Whites perspective NAG_Centre = 50, // new NAG_SlightKingSide = 54, // from Whites perspective NAG_ModerateKingSide = 56, // from Whites perspective NAG_KingSide = 58, // from Whites perspective NAG_SlightQueenSide = 60, // from Whites perspective NAG_ModerateQueenSide = 62, // from Whites perspective NAG_QueenSide = 64, // from Whites perspective NAG_SlightCounterPlay = 130, // new NAG_CounterPlay = 132, // new NAG_DecisiveCounterPlay = 134, // new NAG_BlackSlightCounterPlay = 131, // new NAG_BlackCounterPlay = 133, // new NAG_BlackDecisiveCounterPlay = 135, // new NAG_TimeLimit = 136, // new NAG_WithIdea = 140, // new NAG_BetterIs = 142, // new NAG_VariousMoves = 144, // new NAG_Comment = 145, // new NAG_Novelty = 146, NAG_WeakPoint = 147, // new NAG_Ending = 148, // new NAG_File = 149, // new NAG_Diagonal = 150, // new NAG_BishopPair = 151, // new NAG_OppositeBishops = 153, // new NAG_SameBishops = 154, // new NAG_Etc = 190, // new NAG_DoublePawns = 191, // new NAG_SeparatedPawns = 192, // new NAG_UnitedPawns = 193, // new NAG_Diagram = 201, // Scid-specific NAGs start at 201. NAG_See = 210, // new NAG_Mate = 211, // new NAG_PassedPawn = 212, // new NAG_MorePawns = 213, //new NAG_With = 214, // new NAG_Without = 215; // MAX_NAGS: Maximum id of NAG codes const byte MAX_NAGS_ARRAY = 215; // patternT structure: a pattern filter for material searches. // It can specify, for example, a white Pawn on the f-fyle, or // a black Bishop on f2 and white King on e1. struct patternT { pieceT pieceMatch; // EMPTY, WK, BK, etc... rankT rankMatch; // RANK_1 .. RANK_8 or NO_RANK fyleT fyleMatch; // A_FYLE .. H_FYLE or NO_FYLE byte flag; // 0 means this pattern must NOT occur. patternT * next; }; enum gameExactMatchT { GAME_EXACT_MATCH_Exact = 0, GAME_EXACT_MATCH_Pawns, GAME_EXACT_MATCH_Fyles, GAME_EXACT_MATCH_Material }; enum gameFormatT { PGN_FORMAT_Plain = 0, // Plain regular PGN output PGN_FORMAT_HTML = 1, // HTML format PGN_FORMAT_LaTeX = 2, // LaTeX (with chess12 package) format PGN_FORMAT_Color = 3 // PGN, with color tags etc }; #define PGN_STYLE_TAGS 1 #define PGN_STYLE_COMMENTS 2 #define PGN_STYLE_VARS 4 #define PGN_STYLE_INDENT_COMMENTS 8 #define PGN_STYLE_INDENT_VARS 16 #define PGN_STYLE_SYMBOLS 32 // e.g. "! +-" instead of "$2 $14" #define PGN_STYLE_SHORT_HEADER 64 #define PGN_STYLE_MOVENUM_SPACE 128 // Space after move numbers. #define PGN_STYLE_COLUMN 256 // Column style: one move per line. #define PGN_STYLE_SCIDFLAGS 512 #define PGN_STYLE_STRIP_MARKS 1024 // Strip [%mark] and [%arrow] codes. #define PGN_STYLE_NO_NULL_MOVES 2048 // Convert null moves to comments. #define PGN_STYLE_UNICODE 4096 // Use U+2654..U+2659 for figurine void game_printNag (byte nag, char * str, bool asSymbol, gameFormatT format); byte game_parseNag(std::pair strview); uint strGetRatingType (const char * name); ////////////////////////////////////////////////////////////////////// // Game: Class Definition class Game { // Header data: tag pairs std::vector > extraTags_; std::string WhiteStr; std::string BlackStr; std::string EventStr; std::string SiteStr; std::string RoundStr; dateT Date; dateT EventDate; ecoT EcoCode; eloT WhiteElo; eloT BlackElo; byte WhiteRatingType; byte BlackRatingType; resultT Result; char ScidFlags[22]; // Position and moves byte moveChunkUsed_; std::forward_list > moveChunks_; std::unique_ptr StartPos; std::unique_ptr CurrentPos{new Position}; moveT* FirstMove; moveT* CurrentMove; uint VarDepth; // Current variation depth. ushort NumHalfMoves; // Total half moves in the main line. // TODO: The following variables should not be part of this class. eloT WhiteEstimateElo; eloT BlackEstimateElo; uint NumMovesPrinted; // Used in recursive WriteMoveList method. uint PgnStyle; // see PGN_STYLE macros above. gameFormatT PgnFormat; // see PGN_FORMAT macros above. uint HtmlStyle; // HTML diagram style, see DumpHtmlBoard method in position.cpp. private: Game(const Game&); moveT* allocMove(); moveT* NewMove(markerT marker); void ClearMoves(); errorT DecodeVariation(ByteBuffer& buf); errorT WritePGN(TextBuffer* tb); /** * Contains the information of the current position in the game, so that * after an operation that alters the location, it can be restored. */ struct GameSavedPos { Position pos; moveT* move; uint varDepth; }; public: Game() { Clear(); } void Clear(); void strip(bool variations, bool comments, bool NAGs); bool HasNonStandardStart(char* outFEN = nullptr) const { if (!StartPos) return false; if (outFEN) StartPos->PrintFEN(outFEN, FEN_ALL_FIELDS); return true; } /// Setup the start position from a FEN string and remove all the moves. /// If the FEN is invalid the game is not changed. errorT SetStartFen(const char* fenStr); void SetScidFlags(const char* s, size_t len) { constexpr size_t size = sizeof(ScidFlags) / sizeof(*ScidFlags); std::fill_n(ScidFlags, size, 0); std::copy_n(s, std::min(size - 1, len), ScidFlags); } void SetScidFlags(const char* s) { SetScidFlags(s, std::strlen(s)); } ushort GetNumHalfMoves() { return NumHalfMoves; } ////////////////////////////////////////////////////////////// // Functions to add or delete moves: // errorT AddMove(const simpleMoveT* sm); errorT AddVariation(); errorT DeleteVariation(); errorT FirstVariation(); errorT MainVariation(); void Truncate(); void TruncateStart(); ////////////////////////////////////////////////////////////// // Functions that move the current location (only CurrentPos, // CurrentMove and VarDepth are modified by these functions): // errorT MoveForward(); errorT MoveBackup(); errorT MoveIntoVariation(uint varNumber); errorT MoveExitVariation(); errorT MoveForwardInPGN(); errorT MoveToLocationInPGN(unsigned stopLocation); void MoveToStart(); /// Move to the end of the main line. void MoveToEnd(); void MoveToPly(int hmNumber) { // Move to a specified MoveToStart(); // mainline ply in the game. for (int i = 0; i < hmNumber; ++i) MoveForward(); } GameSavedPos currentLocation() const { return GameSavedPos{*CurrentPos, CurrentMove, VarDepth}; } void restoreLocation(const GameSavedPos& savedPos) { *CurrentPos = savedPos.pos; CurrentMove = savedPos.move; VarDepth = savedPos.varDepth; } ////////////////////////////////////////////////////////////// // Functions that get information about the current location. // const Position* currentPos() const { return CurrentPos.get(); } Position* GetCurrentPos() { // Deprecated, use the const version return CurrentPos.get(); } /// @return an "UCI position" string that leads to the current position std::string currentPosUCI() const; simpleMoveT* GetCurrentMove() { // Deprecated return CurrentMove->endMarker() ? nullptr : &CurrentMove->moveData; } ushort GetCurrentPly() const { auto ply = CurrentPos->GetPlyCounter(); return StartPos ? ply - StartPos->GetPlyCounter() : ply; } uint GetNumVariations() const { return CurrentMove->numVariations; } // Each variation has a "level" and a "number". // - "level" is the number of times that is necessary to call // MoveExitVariation() to reach the main line. // - "number" is the ordered position in the list of variations for the // current root position (first variation is number 0). // The main line is 0,0. uint GetVarLevel() const { return VarDepth; } uint GetVarNumber() const { if (VarDepth != 0) { uint varNumber = 0; auto moves = CurrentMove->getParent(); for (auto parent = moves.first; parent; varNumber++) { parent = parent->varChild; if (parent == moves.second) return varNumber; } } return 0; // returns 0 if in main line } unsigned GetLocationInPGN() const; unsigned GetPgnOffset() const; bool AtVarStart() const { return CurrentMove->prev->startMarker(); } bool AtVarEnd() const { return CurrentMove->endMarker(); } bool AtStart() const { return (VarDepth == 0 && AtVarStart()); } bool AtEnd() const { return (VarDepth == 0 && AtVarEnd()); } ////////////////////////////////////////////////////////////// // Functions that get/set information about the last/next move. // Notice: when location is at the start of the game or a variation, // infomation are stored into the START_MARKER. // errorT AddNag(byte nag); errorT RemoveNag(bool isMoveNag); void ClearNags() { CurrentMove->prev->nagCount = 0; CurrentMove->prev->nags[0] = 0; } byte* GetNags() const { return CurrentMove->prev->nags; } byte* GetNextNags() const { return CurrentMove->nags; } /** * Return the comment on the move previously played by CurrentPos->ToMove * If there are no previous moves, return an empty comment. */ const char* GetPreviousMoveComment() const { const moveT* move = CurrentMove->getPrevMove(); if (move) move = move->getPrevMove(); return (move) ? move->comment.c_str() : ""; } const char* GetMoveComment() const { return CurrentMove->prev->comment.c_str(); } std::string& accessMoveComment() { return CurrentMove->prev->comment; } void SetMoveComment(const char* comment); const char* GetNextSAN(); void GetSAN(char* str); void GetPrevSAN(char* str); void GetPrevMoveUCI(char* str) const; void GetNextMoveUCI(char* str); ////////////////////////////////////////////////////////////// // Functions that get/set the tag pairs: // void AddPgnTag(const char* tag, const char* value); bool RemoveExtraTag(const char* tag); const char* FindExtraTag(const char* tag) const; std::string& accessTagValue(const char* tag, size_t tagLen); const decltype(extraTags_) & GetExtraTags() const { return extraTags_; } void ClearExtraTags() { extraTags_.clear(); } void LoadStandardTags(const IndexEntry* ie, const NameBase* nb); void SetEventStr (const char * str) { EventStr = str; } void SetSiteStr (const char * str) { SiteStr = str; } void SetWhiteStr (const char * str) { WhiteStr = str; } void SetBlackStr (const char * str) { BlackStr = str; } void SetRoundStr (const char * str) { RoundStr = str; } void SetDate (dateT date) { Date = date; } void SetEventDate (dateT date) { EventDate = date; } void SetResult (resultT res) { Result = res; } void SetWhiteElo (eloT elo) { WhiteElo = elo; } void SetBlackElo (eloT elo) { BlackElo = elo; } void SetWhiteRatingType (byte b) { WhiteRatingType = b; } void SetBlackRatingType (byte b) { BlackRatingType = b; } int setRating(colorT col, const char* ratingType, size_t ratingTypeLen, std::pair rating); void SetEco (ecoT eco) { EcoCode = eco; } const char* GetEventStr () const { return EventStr.c_str(); } const char* GetSiteStr () const { return SiteStr.c_str(); } const char* GetWhiteStr () const { return WhiteStr.c_str(); } const char* GetBlackStr () const { return BlackStr.c_str(); } const char* GetRoundStr () const { return RoundStr.c_str(); } dateT GetDate () const { return Date; } dateT GetEventDate () const { return EventDate; } resultT GetResult () const { return Result; } eloT GetWhiteElo () const { return WhiteElo; } eloT GetBlackElo () const { return BlackElo; } eloT GetWhiteEstimateElo() const { return WhiteEstimateElo; } eloT GetBlackEstimateElo() const { return BlackEstimateElo; } byte GetWhiteRatingType () const { return WhiteRatingType; } byte GetBlackRatingType () const { return BlackRatingType; } ecoT GetEco () const { return EcoCode; } eloT GetAverageElo (); // PGN conversion bool CommentEmpty ( const char * comment); void WriteComment (TextBuffer * tb, const char * preStr, const char * comment, const char * postStr); errorT WriteMoveList(TextBuffer* tb, moveT* oldCurrentMove, bool printMoveNum, bool inComment); std::pair WriteToPGN (uint lineWidth = 0, bool NewLineAtEnd = false, bool newLineToSpaces = true); void ResetPgnStyle (void) { PgnStyle = 0; } void ResetPgnStyle (uint flag) { PgnStyle = flag; } uint GetPgnStyle () { return PgnStyle; } void SetPgnStyle (uint mask, bool setting) { if (setting) { AddPgnStyle (mask); } else { RemovePgnStyle (mask); } } void AddPgnStyle (uint mask) { PgnStyle |= mask; } void RemovePgnStyle (uint mask) { PgnStyle &= ~mask; } void SetPgnFormat (gameFormatT gf) { PgnFormat = gf; } bool SetPgnFormatFromString (const char * str); static bool PgnFormatFromString (const char * str, gameFormatT * fmt); bool IsPlainFormat () { return (PgnFormat == PGN_FORMAT_Plain); } bool IsHtmlFormat () { return (PgnFormat == PGN_FORMAT_HTML); } bool IsLatexFormat () { return (PgnFormat == PGN_FORMAT_LaTeX); } bool IsColorFormat () { return (PgnFormat == PGN_FORMAT_Color); } void SetHtmlStyle (uint style) { HtmlStyle = style; } uint GetHtmlStyle () { return HtmlStyle; } errorT GetPartialMoveList (DString * str, uint plyCount); bool MaterialMatch (bool PromotionsFlag, ByteBuffer& buf, byte * min, byte * max, patternT * pattern, int minPly, int maxPly, int matchLength, bool oppBishops, bool sameBishops, int minDiff, int maxDiff); bool ExactMatch (Position * pos, ByteBuffer * buf, simpleMoveT * sm, gameExactMatchT searchType); bool VarExactMatch (Position * searchPos, gameExactMatchT searchType); errorT Encode(std::vector& dest, IndexEntry& ie) const; errorT DecodeSkipTags(ByteBuffer* buf); errorT DecodeNextMove (ByteBuffer * buf, simpleMoveT& sm); errorT Decode(ByteBuffer& buf); errorT DecodeMovesOnly(ByteBuffer& buf); Game* clone(); }; namespace gamevisit { template void tags_STR(const Game& game, TFunc visitor) { char dateBuf[16]; visitor("Event", game.GetEventStr()); visitor("Site", game.GetSiteStr()); date_DecodeToString(game.GetDate(), dateBuf); visitor("Date", dateBuf); visitor("Round", game.GetRoundStr()); visitor("White", game.GetWhiteStr()); visitor("Black", game.GetBlackStr()); visitor("Result", RESULT_LONGSTR[game.GetResult()]); } template void tags_extra(const Game& game, TFunc visitor) { char strBuf[256]; if (auto elo = game.GetWhiteElo()) { std::string rType = "White"; rType.append(ratingTypeNames[game.GetWhiteRatingType()]); visitor(rType.c_str(), std::to_string(elo).c_str()); } if (auto elo = game.GetBlackElo()) { std::string rType = "Black"; rType.append(ratingTypeNames[game.GetBlackRatingType()]); visitor(rType.c_str(), std::to_string(elo).c_str()); } if (game.GetEco() != ECO_None) { eco_ToExtendedString(game.GetEco(), strBuf); visitor("ECO", strBuf); } if (game.GetEventDate() != ZERO_DATE) { date_DecodeToString(game.GetEventDate(), strBuf); visitor("EventDate", strBuf); } // TODO: // if (*ScidFlags) // visitor("ScidFlags", ScidFlags); for (auto& e : game.GetExtraTags()) { visitor(e.first.c_str(), e.second.c_str()); } if (game.HasNonStandardStart(strBuf)) { visitor("FEN", strBuf); } } } // namespace gamevisit namespace gamepos { struct GamePos { uint32_t RAVdepth; uint32_t RAVnum; std::string FEN; // "Forsyth-Edwards Notation" describing the position. std::vector NAGs; // "Numeric Annotation Glyph" std::string comment; // text annotation of the position. std::string lastMoveSAN; // move that was played to reach the position. }; /** * Iterate all the positions of a game and store the corresponding GamePos * objects into a container. * * The order of positions and of Recursive Annotation Variations (RAV) follows * the PGN standard: "The alternate move sequence given by an RAV is one that * may be legally played by first unplaying the move that appears immediately * prior to the RAV. Because the RAV is a recursive construct, it may be nested" * Each position have a RAVdepth and a RAVnum that allows to follow a * variation from any given position: * - skip all the next positions with a bigger RAVdepth * - the variation ends with: * - a lower RAVdepth or * - an equal RAVdepth but different RAVnum or * - the end of @e dest * @param game: reference to the Game object where the positions are read. * @param dest: the container where the GamePos objects are appended. */ template inline void collectPositions(Game& game, TCont& dest) { do { if (game.AtVarStart() && !game.AtStart()) continue; dest.emplace_back(); auto& gamepos = dest.back(); gamepos.RAVdepth = game.GetVarLevel(); gamepos.RAVnum = game.GetVarNumber(); char strBuf[256]; game.currentPos()->PrintFEN(strBuf, FEN_ALL_FIELDS); gamepos.FEN = strBuf; for (byte* nag = game.GetNags(); *nag; nag++) { gamepos.NAGs.push_back(*nag); } gamepos.comment = game.GetMoveComment(); game.GetPrevSAN(strBuf); gamepos.lastMoveSAN = strBuf; } while (game.MoveForwardInPGN() == OK); } /** * Returns all the positions of a game * @param game: reference to the Game object where the positions are read. * @returns a std::vector containing the GamePos objects corresponding to all * the positions of @e game. */ inline std::vector collectPositions(Game& game) { std::vector res; game.MoveToStart(); collectPositions(game, res); return res; } } // namespace gamepos #endif // #ifndef SCID_GAME_H ////////////////////////////////////////////////////////////////////// // EOF: game.h ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/naglatex.h0000755000076500000240000001026314666426276017665 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: naglatex.h // Translationtable for NAG values to Tex. // // Part of: Scid (Shane's Chess Information Database) // Version: 3.6 // // Notice: Copyright (c) 2000-2003 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // Updated: W. van den Akker // ////////////////////////////////////////////////////////////////////// const char * evalNagsLatex [] = { "", // one for the offset "!", // $1 "?", // $2 "!!", // $3 "??", // $4 "!?", // $5 "?!", // $6 "forced", // $7 "{\\onlymove}", // $8 "worst", // $9 "{\\equal}", // $10 "", // $11 "{$\\leftrightarrows$}", // $12 "{\\unclear}", // $13 "{\\wbetter}", // $14 "{\\bbetter}", // $15 "{\\wupperhand}", // $16 "{\\bupperhand}", // $17 "{\\wdecisive}", // $18 "{\\bdecisive}", // $19 "", // $20 "", // $21 "{\\zugzwang}", // $22 "{\\zugzwang}", // $23 "", // $24 "", // $25 "{\\moreroom}", // $26 "", // $27 "", // $28 "", // $29 "{$\\circlearrowleft$}", // $30 "{$\\circlearrowright$}", // $31 "", // $32 "", // $33 "", // $34 "{\\devadvantage}", // $35 "{\\withinit}", // $36 "", // $37 "", // $38 "", // $39 "{\\withattack}", // $40 "", // $41 "", // $42 "", // $43 "{\\compensation}", // $44 "", // $45 "", // $46 "", // $47 "{$$\\boxplus$$}", // $48 "{$$\\boxplus$$}", // $49 "{\\centre}", // $50 "{\\centre}", // $51 "", // $52 "", // $53 "", // $54 "", // $55 "", // $56 "", // $57 "{\\kside}", // $58 "", // $59 "", // $60 "", // $61 "{\\qside}", // $62 "", // $63 "", // $64 "", // $65 "", // $66 "", // $67 "", // $68 "", // $69 "", // $70 "", // $71 "", // $72 "", // $73 "", // $74 "", // $75 "", // $76 "", // $77 "", // $78 "", // $79 "", // $80 "", // $81 "", // $82 "", // $83 "", // $84 "", // $85 "", // $86 "", // $87 "", // $88 "", // $89 "", // $90 "", // $91 "", // $92 "", // $93 "", // $94 "", // $95 "", // $96 "", // $97 "", // $98 "", // $99 "", // $100 "", // $101 "", // $102 "", // $103 "", // $104 "", // $105 "", // $106 "", // $107 "", // $108 "", // $109 "", // $110 "", // $111 "", // $112 "", // $113 "", // $114 "", // $115 "", // $116 "", // $117 "", // $118 "", // $119 "", // $120 "", // $121 "", // $122 "", // $123 "", // $124 "", // $125 "", // $126 "", // $127 "", // $128 "", // $129 "", // $130 "", // $131 "{\\counterplay}", // $132 "", // $133 "", // $134 "", // $135 "{\\timelimt}", // $136 "", // $137 "", // $138 "", // $139 "{\\withidea}", // $140 "", // $141 "{\\betteris}", // $142 "", // $143 "{\\various}", // $144 "{\\comment}", // $145 "{\\novelty}", // $146 "{\\weakpt}", // $147 "{\\ending}", // $148 "{\\file}", // $149 "{\\diagonal}", // $150 "{\\bishoppair}", // $151 "", // $152 "{\\opposbishops}", // $153 "{\\samebishops}", // $154 "", // $155 "", // $156 "", // $157 "", // $158 "", // $159 "", // $160 "", // $161 "", // $162 "", // $163 "", // $164 "", // $165 "", // $166 "", // $167 "", // $168 "", // $169 "", // $170 "", // $171 "", // $172 "", // $173 "", // $174 "", // $175 "", // $176 "", // $177 "", // $178 "", // $179 "", // $180 "", // $181 "", // $182 "", // $183 "", // $184 "", // $185 "", // $186 "", // $187 "", // $188 "", // $189 "{\\etc}", // $190 "{\\doublepawns}", // $191 "{\\seppawns}", // $192 "{\\unitedpawns}", // $193 "", // $194 "", // $195 "", // $196 "", // $197 "", // $198 "", // $199 "", // $200 "", // $201 "", // $202 "", // $203 "", // $204 "", // $205 "", // $206 "", // $207 "", // $208 "", // $209 "{\\see}", // $210 "{\\mate}", // $211 "{\\passedpawn}", // $212 "{\\morepawns}", // $213 "{\\with}", // $214 "{\\without}", // $215 "", // $216 "", // $217 "", // $218 "", // $219 "", // $220 "", // $221 "", // $222 "", // $223 "" // $224 }; chessx-master/dep/scid/code/src/common.h0000755000076500000240000003507014666426276017355 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: common.h // Common macros, structures and constants. // // Part of: Scid (Shane's Chess Information Database) // Version: 3.6.6 // // Notice: Copyright (c) 2000-2004 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // Copyright (c) 2006-2007 Pascal Georges // ////////////////////////////////////////////////////////////////////// #ifndef SCID_COMMON_H #define SCID_COMMON_H #include #if defined(_MSC_VER) && _MSC_VER <= 1600 typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int64 uint64_t; typedef __int32 int32_t; #else #include #endif // _MSC_VER <= 1600 #include "board_def.h" #include "error.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CONSTANTS: typedef unsigned short versionT; // Version: div by 100 for major number, modulo 100 for minor number // so 109 = 1.9, 110 = 1.10, etc. const versionT SCID_VERSION = 400; // Current file format version = 4.0 const versionT SCID_OLDEST_VERSION = 300; // Oldest readable file format: 3.0 const char SCID_VERSION_STRING[] = "4.7.1"; // Current Scid version const char SCID_WEBSITE[] = "http://scid.sourceforge.net/"; ////////////////////////////////////////////////////////////////////// // ASSERT macro: asserts an expression. Differs from the standard // assert in that it does NOT print the expression (this is a waste, // if an assert fails you can go to the code to see why) and that // it MUST be a statement, not part of a larger expression. // Adapted from the book "Writing Solid Code". #include #define ASSERT(f) assert(f) // Bit Manipulations #define BIT_7(x) ((x) & 128) #define BIT_6(x) ((x) & 64) #define BIT_5(x) ((x) & 32) #define BIT_4(x) ((x) & 16) #define BIT_3(x) ((x) & 8) #define BIT_2(x) ((x) & 4) #define BIT_1(x) ((x) & 2) #define BIT_0(x) ((x) & 1) // Upper or lower 4 bits of a byte, in the range 0..15 #define UPPER_4_BITS(x) (((x) & 240) >> 4) // 240 is (15 * 16) #define LOWER_4_BITS(x) ((x) & 15) // Upper or lower 12 bits of an integer, in the range 0..4095 // #define UPPER_12_BITS(x) (((x) & (4096 * 4095)) >> 12) #define LOWER_12_BITS(x) ((x) & 4095) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // TYPE DEFINITIONS // General types typedef unsigned char byte; // 8 bit unsigned typedef uint16_t ushort; // 16 bit unsigned typedef uint32_t uint; // 32 bit unsigned typedef int32_t sint; // 32 bit signed // compareT: comparison type typedef signed int compareT; const compareT LESS_THAN = -1, EQUAL_TO = 0, GREATER_THAN = 1; // Chess Types typedef byte directionT; // e.g. UP_LEFT typedef byte leftDiagT; // Up-left diagonals typedef byte rightDiagT; // Up-right diagonals // boardT: 64 squares plus two extra squares: one for storing the side // to move as a byte and one for the string terminator, so boards can // be compared using regular string functions: typedef pieceT boardT [66]; typedef byte smallBoardT [32]; // A more densely packed board, 2 squares // per byte. typedef byte castleDirT; // LEFT or RIGHT // Other Small Types typedef ushort statusT; // Fixed String Types typedef char sanStringT [ 10]; // SAN Move Notation // File-related Types typedef char fileNameT [512]; typedef uint fileLengthT; enum fileModeT { FMODE_None = 0, FMODE_ReadOnly, FMODE_WriteOnly, FMODE_Both, FMODE_Create }; // Date type: see date.h and date.cpp typedef uint dateT; // There are four name types: PLAYER, EVENT, SITE and ROUND tags. // Names are accessed through IDs. typedef uint32_t idNumberT; // Should be idNameT typedef unsigned nameT; enum { NAME_PLAYER, NAME_EVENT, NAME_SITE, NAME_ROUND, NUM_NAME_TYPES, NAME_INVALID = 99 }; // Game Information types typedef uint gamenumT; typedef ushort eloT; typedef ushort ecoT; typedef char ecoStringT [6]; /* "A00j1" */ const ecoT ECO_None = 0; // Rating types: const byte RATING_Elo = 0; const byte RATING_Rating = 1; const byte RATING_Rapid = 2; const byte RATING_ICCF = 3; const byte RATING_USCF = 4; const byte RATING_DWZ = 5; const byte RATING_BCF = 6; extern const char * ratingTypeNames [17]; // Defined in game.cpp // Result Type const uint NUM_RESULT_TYPES = 4; typedef byte resultT; const resultT RESULT_None = 0, RESULT_White = 1, RESULT_Black = 2, RESULT_Draw = 3; const uint RESULT_SCORE[4] = { 1, 2, 0, 1 }; const char RESULT_CHAR [4] = { '*', '1', '0', '=' }; const char RESULT_STR [4][4] = { "*", "1-0", "0-1", "=-=" }; const char RESULT_LONGSTR [4][8] = { "*", "1-0", "0-1", "1/2-1/2" }; const resultT RESULT_OPPOSITE [4] = { RESULT_None, RESULT_Black, RESULT_White, RESULT_Draw }; const castleDirT QSIDE = 0, KSIDE = 1; // Minor piece definitions, used for searching by material only: const pieceT WM = 16, BM = 17; const uint MAX_PIECE_TYPES = 18; // PIECE_FLIP[]: array of pieces, with colors reversed. const pieceT PIECE_FLIP [MAX_PIECE_TYPES] = { END_OF_BOARD, BK, BQ, BR, BB, BN, BP, EMPTY, EMPTY, WK, WQ, WR, WB, WN, WP, EMPTY, BM, WM }; const bool PIECE_IS_SLIDER [8] = { false, false, true, true, true, false, false, false, }; // PIECE_VALUE: Piece values, K=1000, Q=9, R=5, B=N=3, P=1 const int PIECE_VALUE [MAX_PIECE_TYPES] = { 0, 100, 9, 5, 3, 3, 1, 0, 0, -100, -9, -5, -3, -3, -1, 0, 3, -3 }; // // INLINE FUNCTIONS for pieces // inline bool piece_IsWhite(pieceT p) { return (p>=WK && p<=WP); } inline bool piece_IsBlack(pieceT p) { return (p>=BK && p<=BP); } inline bool piece_IsKing(pieceT p) { return (piece_Type(p) == KING); } inline bool piece_IsQueen(pieceT p) { return (piece_Type(p) == QUEEN); } inline bool piece_IsRook(pieceT p) { return (piece_Type(p) == ROOK); } inline bool piece_IsBishop(pieceT p) { return (piece_Type(p) == BISHOP); } inline bool piece_IsKnight(pieceT p) { return (piece_Type(p) == KNIGHT); } inline bool piece_IsPawn(pieceT p) { return (piece_Type(p) == PAWN); } inline bool piece_IsSlider(pieceT p) { return PIECE_IS_SLIDER[piece_Type(p)]; } inline pieceT piece_FromChar(int x) { switch (x) { case 'K': return KING; case 'Q': return QUEEN; case 'R': return ROOK; case 'N': return KNIGHT; case 'B': return BISHOP; default: return EMPTY; } } inline int piece_Value (pieceT p) { return PIECE_VALUE[p]; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // SQUARES AND SQUARE MACROS inline leftDiagT square_LeftDiag (squareT sq) { return square_Rank(sq) + square_Fyle(sq); } inline rightDiagT square_RightDiag (squareT sq) { return (7 + square_Rank(sq) - square_Fyle(sq)); } // square_Color: // Return WHITE for a light square, BLACK for a dark square. inline colorT square_Color (squareT sq) { return 1 - (square_LeftDiag(sq) & 1); } // square_FlipFyle: // Return the square with its file flipped: a1 <-> h1, b1 <-> g1, etc. inline squareT square_FlipFyle (squareT sq) { return square_Make (A_FYLE + H_FYLE - square_Fyle(sq), square_Rank(sq)); } // square_FlipRank: // Return the square with its rank flipped: a1 <-> a8, a2 <-> a7, etc. inline squareT square_FlipRank (squareT sq) { return square_Make (square_Fyle(sq), RANK_1 + RANK_8 - square_Rank(sq)); } // square_FlipDiag: // Return the square flipped along the a1-h8 diagonal. inline squareT square_FlipDiag (squareT sq) { return square_Make (square_Rank(sq), square_Fyle(sq)); } const uint rankFyleDist[64] = { 0, 1, 2, 3, 4, 5, 6, 7, 1, 0, 1, 2, 3, 4, 5, 6, 2, 1, 0, 1, 2, 3, 4, 5, 3, 2, 1, 0, 1, 2, 3, 4, 4, 3, 2, 1, 0, 1, 2, 3, 5, 4, 3, 2, 1, 0, 1, 2, 6, 5, 4, 3, 2, 1, 0, 1, 7, 6, 5, 4, 3, 2, 1, 0 }; // square_Distance: // Return the distance in king moves between two squares. inline uint square_Distance (squareT from, squareT to) { ASSERT (from <= H8 && to <= H8); uint rankd = rankFyleDist[(square_Rank(from) << 3) | square_Rank(to)]; uint fyled = rankFyleDist[(square_Fyle(from) << 3) | square_Fyle(to)]; return (rankd > fyled) ? rankd : fyled; } // square_NearestCorner: // Return the corner (A1/H1/A8/H8) closest to the specified square. inline squareT square_NearestCorner (squareT sq) { if (square_Rank(sq) <= RANK_4) { return (square_Fyle(sq) <= D_FYLE)? A1 : H1; } else { return (square_Fyle(sq) <= D_FYLE)? A8 : H8; } } inline bool square_IsCornerSquare (squareT sq) { return (sq == A1 || sq == H1 || sq == A8 || sq == H8); } inline bool square_IsEdgeSquare (squareT sq) { rankT rank = square_Rank(sq); if (rank == RANK_1 || rank == RANK_8) { return true; } fyleT fyle = square_Fyle(sq); if (fyle == A_FYLE || fyle == H_FYLE) { return true; } return false; } const int edgeDist[66] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 2, 2, 2, 2, 1, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 1, 2, 2, 2, 2, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1 }; inline int square_EdgeDistance (squareT sq) { return edgeDist[sq]; } inline bool square_IsKnightHop (squareT from, squareT to) { ASSERT (from <= H8 && to <= H8); uint rdist = rankFyleDist [(square_Rank(from) << 3) | square_Rank(to)]; uint fdist = rankFyleDist [(square_Fyle(from) << 3) | square_Fyle(to)]; // It is a knight hop only if one distance is two squares and the // other is one square -- that is, only if their product equals two. return ((rdist * fdist) == 2); } inline char square_FyleChar (squareT sq) { return square_Fyle(sq) + 'a'; } inline char square_RankChar (squareT sq) { return square_Rank(sq) + '1'; } inline void square_Print (squareT sq, char * str) { if (sq <= H8) { str[0] = square_FyleChar(sq); str[1] = square_RankChar(sq); str[2] = 0; } else if (sq == NULL_SQUARE) { str[0] = 'N'; str[1] = 'S'; str[2] = 0; } else { str[0] = 'X'; str[1] = 'X'; str[2] = 0; } return; } // Directions: // Up = 1, Down = 2, Left = 4, Right = 8, UpLeft = 5, UpRight = 9, // DownLeft = 6, DownRight = 10 const directionT NULL_DIR = 0, UP = 1, DOWN = 2, LEFT = 4, RIGHT = 8, UP_LEFT = (UP | LEFT), UP_RIGHT = (UP | RIGHT), DOWN_LEFT = (DOWN | LEFT), DOWN_RIGHT = (DOWN | RIGHT); const directionT dirOpposite[11] = { NULL_DIR, DOWN, // opposite of UP (1) UP, // opposite of DOWN (2) NULL_DIR, RIGHT, // opposite of LEFT (4) DOWN_RIGHT, // opposite of UP_LEFT (5) UP_RIGHT, // opposite of DOWN_LEFT (6) NULL_DIR, LEFT, // opposite of RIGHT (8) DOWN_LEFT, // opposite of UP_RIGHT (9) UP_LEFT // opposite of DOWN_RIGHT (10) }; // direction_Opposite(): return the opposite direction to d inline directionT direction_Opposite (directionT d) { return dirOpposite[d]; } // dirIsDiagonal[]: array listing the diagonal directions, for fast // lookup of whether a direction is a diagonal. const bool dirIsDiagonal [11] = { false, // 0 = NULL_DIR false, // 1 = UP false, // 2 = DOWN false, // 3 = Invalid false, // 4 = LEFT true, // 5 = UP_LEFT true, // 6 = DOWN_LEFT false, // 7 = Invalid false, // 8 = RIGHT true, // 9 = UP_RIGHT true // 10 = DOWN_RIGHT }; inline bool direction_IsDiagonal (directionT dir) { return dirIsDiagonal[dir]; } // dirDelta: // Array giving the board delta of moving to the next square // in that direction. const int dirDelta[11] = { 0, // NULL_DIR 8, // UP -8, // DOWN 0, // Invalid -1, // LEFT 7, // UP_LEFT -9, // DOWN_LEFT 0, // Invalid 1, // RIGHT 9, // UP_RIGHT -7 // DOWN_RIGHT }; inline int direction_Delta (directionT dir) { return dirDelta[dir]; } // The starting Board // const boardT START_BOARD = { WR, WN, WB, WQ, WK, WB, WN, WR, // A1--H1 WP, WP, WP, WP, WP, WP, WP, WP, // A2--H2 EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, EMPTY, BP, BP, BP, BP, BP, BP, BP, BP, BR, BN, BB, BQ, BK, BB, BN, BR, EMPTY, // COLOR_SQUARE END_OF_BOARD // NULL_SQUARE }; // Square colors for the standard chess board: // const colorT BOARD_SQUARECOLOR[66] = { BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, // a1-h1 WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, // a2-h2 BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, // a3-h3 WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, // a4-h4 BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, // a5-h5 WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, // a6-h6 BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, // a7-h7 WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, WHITE, BLACK, // a8-h8 NOCOLOR, NOCOLOR // Color square and Null square }; inline int board_Compare (const pieceT * b1, const pieceT * b2) { for (uint i=0; i < 64; i++) { if (*b1 < *b2) { return -1; } if (*b1 > *b2) { return 1; } b1++; b2++; } return 0; } // square_Adjacent: returns 1 if the two squares are adjacent. Note that // diagonal adjacency is included: a1 and b2 are adjacent. // Also note that a square is adjacent to itself. inline bool square_Adjacent (squareT from, squareT to) { ASSERT (from <= H8 && to <= H8); rankT fromRank = square_Rank(from); rankT toRank = square_Rank(to); int rdist = (int)fromRank - (int)toRank; if (rdist < -1 || rdist > 1) { return false; } fyleT fromFyle = square_Fyle(from); fyleT toFyle = square_Fyle(to); int fdist = (int)fromFyle - (int)toFyle; if (fdist < -1 || fdist > 1) { return false; } return true; } #endif // #ifdef SCID_COMMON_H ////////////////////////////////////////////////////////////////////// // EOF: common.h ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/sortcache.h0000755000076500000240000001237514666426276020043 0ustar jensstaff/* * Copyright (C) 2011 Gerd Lorscheid * Copyright (C) 2011-2017 Fulvio Benini * * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ /** @file * Defines the SortCache class, which sorts the games of an @e Index. */ #ifndef SORTCACHE_H #define SORTCACHE_H #include "common.h" #ifndef MULTITHREADING_OFF #include using std::atomic_bool; #else typedef bool atomic_bool; #endif class HFilter; class Index; class IndexEntry; class NameBase; /** * This class sorts games contained into an Index. * Multiple SortCache objects can be created for a single Index, allowing to * simultaneously sort the games by multiple criteria in an independent way. */ class SortCache { gamenumT nGames_; atomic_bool valid_fullMap_; atomic_bool th_interrupt_; bool partialHash_; gamenumT* fullMap_; void* th_; uint32_t* hash_; const Index* index_; const NameBase* nbase_; char criteria_[32]; int refCount_; // Valid fields that can be used to sort the games. enum { SORTING_date = 'd', SORTING_year = 'y', SORTING_event = 'e', SORTING_site = 's', SORTING_round = 'n', SORTING_white = 'w', SORTING_black = 'b', SORTING_eco = 'o', SORTING_result = 'r', SORTING_moveCount = 'm', SORTING_avgElo = 'R', SORTING_country = 'c', SORTING_deleted = 'D', SORTING_eventdate = 'E', SORTING_whiteelo = 'W', SORTING_blackelo = 'B', SORTING_commentcount = 'C', SORTING_varcount = 'V', SORTING_nagcount = 'A', SORTING_resultwin = '1', SORTING_resultdraw = '5', SORTING_resultloss = '0', SORTING_rating = 'i', SORTING_number = 'N', SORTING_sentinel = '\0' }; public: /** * Create a new SortCache object, builds the hash table, and asynchronously * sorts all the games. * @param idx: valid pointer to an Index object, witch contains the * header data of the games to be sorted. * @param nb: valid pointer to the NameBase corresponding to @e idx. * @param criteria: the list of fields by which games will be ordered. * Each field should be followed by '+' to indicate an * ascending order or by '-' for a descending order. * @returns a pointer to the new object in case of success, NULL otherwise. */ static SortCache* create(const Index* idx, const NameBase* nb, const char* criteria); ~SortCache(); /** * Notify the object that a game's header data has changed. * @param gameId: the id of the game whose data has been changed. */ void checkForChanges(gamenumT gameId); /** * Interrupt any asynchronous operation. This function must be called before * modifying the Index or the NameBase associated with the SortCache. */ void prepareForChanges() { th_interrupt(); } /** * Retrieve the sorted list of games' ids. * The behavior of this function is similar to the mySQL statement: * SELECT gameId FROM idx WHERE filter(gameId) != 0 ORDER BY criteria * LIMIT offset, row_count * @param row_offset: the offset of the first row to return. * The offset of the initial row is 0. * @param row_count: maximum number of rows to return. * @param filter: a reference to a valid (!= NULL) HFilter object. * Games not included into the filter will be ignored. * @param[out] result: valid pointer to an array where the sorted list of * games will be stored (should be able to contain at * least @e row_count elements). * @returns the number of games' ids stored into @e result. */ size_t select(size_t row_offset, size_t row_count, const HFilter& filter, gamenumT* result) const; /** * Get the sorted position of a game. * @param gameId: the id of the game. * @param filter: a reference to a valid (!= NULL) HFilter object. * Games not included into the filter will be ignored, * and @e gameId must be included into the filter. * @returns the sorted position of @e gameId. */ size_t sortedPosition(gamenumT gameId, const HFilter& filter) const; int incrRef(int incr) { return refCount_ += incr; } private: SortCache(const Index* idx, const NameBase* nbase); SortCache(const SortCache&); class CmpLess { const SortCache* sc_; public: CmpLess(const SortCache* sc) : sc_(sc) {} bool operator()(gamenumT g1, gamenumT g2) const; }; int fullCompare(gamenumT left, gamenumT right) const; uint32_t calcHash(gamenumT gameId); void generateHashCache(); void sortAsynchronously(); void th_interrupt() { th_interrupt_ = true; th_join(); th_interrupt_ = false; } void th_join(); void th_sort(); }; #endif chessx-master/dep/scid/code/src/movegen.h0000755000076500000240000001715114666426276017525 0ustar jensstaff/* * Copyright (C) 2011-2019 Fulvio Benini * * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ /** @file * Implements functions for the validation of chess moves. */ #include // These functions use the following move classification: // - a VALID move is a move that respects the basic rules for moving the pieces, // for example a bishop should move diagonally. Validating this type of moves // do not require any info about the current position. // - an ATTACK move is a valid move that can capture an enemy piece at the // destination square. It takes into account the special rule for pawns that // can capture only diagonally and the board position for obstacles, for // example a valid diagonal bishop move is an attack move only if the // in-between squares are empty. To validate this type of moves it is // necessary to know the location of empty squares in the current position. // - a PSEUDO-LEGAL move is an attack move, or a non-capture pawn move, or a // castle move. // - a LEGAL move is a pseudo-legal move where the destination square is not // occupied by a friendly piece and that do not leave the king in check. // To validate this type of moves it is necessary to know the type and // position of every piece. namespace movegen { const int NSQUARES = 8; inline bool valid_king(squareT sqFrom, squareT sqTo) { unsigned distRank = 1 + (sqTo / NSQUARES) - (sqFrom / NSQUARES); unsigned distFyle = 1 + (sqTo % NSQUARES) - (sqFrom % NSQUARES); return distRank <= 2 && distFyle <= 2; } inline bool valid_knight(squareT sqFrom, squareT sqTo) { int distRank = (sqTo / NSQUARES) - (sqFrom / NSQUARES); int distFyle = (sqTo % NSQUARES) - (sqFrom % NSQUARES); int distProduct = distRank * distFyle; return (distProduct == 2 || distProduct == -2); } inline int valid_slider(squareT sqFrom, squareT sqTo, pieceT pieceType) { ASSERT(pieceType == QUEEN || pieceType == ROOK || pieceType == BISHOP); int distRank = (sqTo / NSQUARES) - (sqFrom / NSQUARES); int distFyle = (sqTo % NSQUARES) - (sqFrom % NSQUARES); // Make sure the direction is valid: int sqStep; bool isDiagonal = false; if (distRank == 0) { sqStep = 1; // horizontal } else if (distFyle == 0) { sqStep = NSQUARES; // vertical } else if (distFyle == distRank) { sqStep = NSQUARES + 1; isDiagonal = true; } else if (distFyle == -distRank) { sqStep = NSQUARES - 1; isDiagonal = true; } else { return 0; } if (pieceType == ROOK && isDiagonal) return 0; if (pieceType == BISHOP && !isDiagonal) return 0; return sqStep; } inline bool attack_pawn(squareT sqFrom, squareT sqTo, colorT pieceCol) { int distRank = (sqTo / NSQUARES) - (sqFrom / NSQUARES); int distFyle = (sqTo % NSQUARES) - (sqFrom % NSQUARES); if (pieceCol == WHITE && distRank != 1) return false; if (pieceCol == BLACK && distRank != -1) return false; return (distFyle == 1 || distFyle == -1); } template bool attack_slider(squareT sqFrom, squareT sqTo, pieceT pieceType, TFunc isOccupied) { int sqStep = valid_slider(sqFrom, sqTo, pieceType); if (sqStep == 0) return false; // Make sure all the in-between squares are empty: if (sqFrom > sqTo) sqStep = -sqStep; for (int sq = sqFrom + sqStep; sq != sqTo; sq += sqStep) { if (isOccupied(sq)) return false; } return true; } /** * Validate an ATTACK move, that is if a piece placed at @e sqFrom can capture * an enemy piece at @e sqTo. * @param sqFrom: square of the piece. * @param sqTo: square of the piece to be captured. * @param pieceCol: color of the moving piece. * @param pieceType: type of the moving piece. * @param isOccupied: callable object which should returns true if a square is * occupied by a piece. Since it is not invoked with @e * sqFrom or @e sqTo, it's is irrelevant if the position is * the one before or after the move was made. * @returns true if the move is a valid ATTACK move. */ template bool attack(squareT sqFrom, squareT sqTo, pieceT pieceCol, pieceT pieceType, TFunc isOccupied) { switch (pieceType) { case KING: return valid_king(sqFrom, sqTo); case KNIGHT: return valid_knight(sqFrom, sqTo); case PAWN: return attack_pawn(sqFrom, sqTo, pieceCol); default: break; } return attack_slider(sqFrom, sqTo, pieceType, isOccupied); } template bool pseudo(squareT sqFrom, squareT sqTo, colorT /*pieceCol*/, pieceT pieceType, TFunc isOccupied) { // TODO: pawn and king moves ASSERT(pieceType != PAWN && pieceType != KING); switch (pieceType) { case KNIGHT: return valid_knight(sqFrom, sqTo); default: break; } return attack_slider(sqFrom, sqTo, pieceType, isOccupied); } /** * Given a pseudo-legal move, this functions return the type and the location of * the piece that can possibly pin the moving piece, making the move not legal. * @param sqFrom: start square of the pseudo-legal move. * @param sqTo: destination square of the pseudo-legal move. * @param sqRay: the projected ray starts from @e sqRay and goes through * @e sqFrom; it is usually the square where the king is. * @param isOccupied: callable object which should returns true if a square is * occupied by a piece. * @returns a std::pair with the type (INVALID_PIECE, BISHOP, ROOK) and the * square of the candidate pinning piece. If the type is INVALID_PIECE there is * no pin and the move is legal, otherwise it's necessary to test the board * position and if the returned square is occupied by an enemy QUEEN, or an * enemy piece matching the returned type, the move is not legal. */ template inline std::pair opens_ray(squareT sqFrom, squareT sqTo, squareT sqRay, TFunc isOccupied) { ASSERT(sqRay != sqFrom); int fyleFrom = sqFrom % NSQUARES; int distFyle = (sqRay % NSQUARES) - fyleFrom; int distRank = (sqRay / NSQUARES) - (sqFrom / NSQUARES); // Make sure the direction is valid: int fyleEdge; int sqStep; pieceT pt; if (distFyle == 0) { sqStep = NSQUARES; // vertical fyleEdge = -1; pt = ROOK; } else { if (fyleFrom == 0 || fyleFrom == (NSQUARES - 1)) return {INVALID_PIECE, 0}; if (distRank == 0) { sqStep = 1; // horizontal fyleEdge = 0; pt = ROOK; } else if (distFyle == distRank) { sqStep = NSQUARES + 1; fyleEdge = 0; pt = BISHOP; } else if (distFyle == -distRank) { sqStep = NSQUARES - 1; fyleEdge = NSQUARES - 1; pt = BISHOP; } else { return {INVALID_PIECE, 0}; } } if (sqFrom > sqRay) { sqStep = -sqStep; fyleEdge = NSQUARES - 1 - fyleEdge; } for (int sq = sqFrom + sqStep; sq != sqRay; sq += sqStep) { if (sq == sqTo || isOccupied(sq)) return {INVALID_PIECE, 0}; } for (int sq = sqFrom - sqStep; sq < NSQUARES * NSQUARES; sq -= sqStep) { if (sq < 0 || sq == sqTo) break; if (isOccupied(sq)) return {pt, static_cast(sq)}; if ((sq % NSQUARES) == fyleEdge) break; } return {INVALID_PIECE, 0}; } } // end of namespace movegen chessx-master/dep/scid/code/src/fullmove.h0000755000076500000240000001013714666426276017713 0ustar jensstaff/* * Copyright (C) 2014 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ #ifndef FULLMOVE_H #define FULLMOVE_H #include "common.h" #include class FullMove { // ** Lower 16 bits are compatible with Stockfish's Move ** // bits 0- 5: destination square (from 0 to 63) // bits 6-11: origin square (from 0 to 63) // bits 12-13: promotion piece type -2 (from QUEEN-2 to KNIGHT-2) // bits 14-15: special move flag: promotion (1), en passant (2), castling (3) // ** Info for undoing the move ** // bits 16-17: castling flags - TODO // bits 18-20: enpassant file - TODO // bits 21-23: captured pieceT // ** Info for direct SAN conversion ** // bits 24-26: moving pieceT // bit 27: black to move // bit 28: ambiguous move, insert from fyle // bit 29: ambiguous move, insert from rank // bit 30: check // ** TODO: Use this flag to embed tags, variations, etc.. in a move stream // bit 31: special flag uint32_t m_; public: constexpr FullMove(uint32_t m = 0) : m_(m){}; FullMove(colorT c, squareT kingSq, squareT rookSq) // Castle: encoding as king to rook allows the undoing of chess360 moves : FullMove(c, kingSq, rookSq, KING) { m_ |= (3 << 14); } FullMove(colorT c, squareT from, squareT to, pieceT pt) { m_ = to | (from << 6) | (pt << 24) | (c << 27); } explicit operator bool() const { return m_ != 0; } bool operator==(FullMove const& f) const { return m_ == f.m_; } bool isPromo() const { return (m_ & (3 << 14)) == (1 << 14); } bool isEnpassant() const { return (m_ & (3 << 14)) == (2 << 14); } bool isCastle() const { return (m_ & (3 << 14)) == (3 << 14); } squareT getTo() const { return m_ & 0x3F; } squareT getFrom() const { return (m_ >> 6) & 0x3F; } pieceT getPiece() const { return (m_ >> 24) & 0x07; } colorT getColor() const { return (m_ >> 27 & 1) ? BLACK : WHITE; } pieceT getPromo() const { return ((m_ >> 12) & 0x03) +2; } pieceT getCaptured() const { return (m_ >> 21) & 0x07; } std::string getSAN(colorT* toMove = 0) const { std::string res; if (toMove) *toMove = getColor(); squareT to = getTo(); squareT from = getFrom(); if (to == 0 && from == 0) return "--"; if (isCastle()) { res = (to > from) ? "O-O" : "O-O-O"; bool check = (m_ >> 30) & 1; if (check) res += "+"; return res; } bool fromFyle = (m_ >> 28) & 1; bool fromRank = (m_ >> 29) & 1; bool check = (m_ >> 30) & 1; bool capture = (getCaptured() != 0); switch (getPiece()) { case BISHOP: res += "B"; break; case KNIGHT: res += "N"; break; case ROOK: res += "R"; break; case QUEEN: res += "Q"; break; case KING: res += "K"; break; default: //PAWN if (capture) res += 'a' + (from % 8); } if (fromFyle) res += 'a' + (from % 8); if (fromRank) res += '1' + (from / 8); if (capture) res += "x"; res += 'a' + (to % 8); res += '1' + (to / 8); if (isPromo()) { switch (getPromo()) { case BISHOP: res += "=B"; break; case KNIGHT: res += "=N"; break; case ROOK: res += "=R"; break; case QUEEN: res += "=Q"; break; } } if (check) res += "+"; return res; } void setPromo(pieceT promo) { ASSERT(promo == QUEEN || promo == ROOK || promo == BISHOP || promo == KNIGHT); m_ |= ((promo - 2) << 12) | (1 << 14); } void setCapture(pieceT piece, bool enPassant) { m_ |= ((piece & 0x07) << 21); if (enPassant) m_ |= (2 << 14); } void setAmbiguity(bool fyle, bool rank) { m_ &= ~(3 << 28); if (fyle) m_ |= (1 << 28); if (rank) m_ |= (1 << 29); } void setCheck() { m_ |= (1 << 30); } }; #endif chessx-master/dep/scid/code/src/sortcache.cpp0000755000076500000240000004074614666426276020401 0ustar jensstaff/* * Copyright (C) 2011 Gerd Lorscheid * Copyright (C) 2011-2017 Fulvio Benini * * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ /** @file * Implements the SortCache class, which sorts the games of an @e Index. */ #include "sortcache.h" #include "hfilter.h" #include "index.h" #include "misc.h" #include #include #include #include #ifndef MULTITHREADING_OFF #include /** * Blocks the current thread until the thread @e th_ finishes its execution. */ void SortCache::th_join() { if (th_ != nullptr) { static_cast(th_)->join(); delete static_cast(th_); th_ = nullptr; } } /** * Populate @e fullMap_ with the sorted ids of all the games contained into @e * index_. This function can run in a worker thread and can be interrupted. * It is necessary to invoke th_interrupt() or th_join() before modifying the * SortCache object, or the associated Index and NameBase objects. */ void SortCache::th_sort() { size_t nGames = this->nGames_; gamenumT* v = this->fullMap_; gamenumT* begin = v; gamenumT* end = v + nGames; auto comp = SortCache::CmpLess(this); std::iota(begin, end, 0); // An interruptible implementation of: // std::make_heap(v.begin(), v.end(), comp); ASSERT(nGames < size_t(INT_MAX / 2)); const int lastNode = static_cast(nGames) - 1; const auto lastRoot = (lastNode - 1) / 2; for (auto node = lastRoot; node >= 0; --node) { if (this->th_interrupt_) return; // Sift down @e node for (auto toSift = node;;) { const auto leftChild = 2 * toSift + 1; const auto rightChild = 2 * toSift + 2; if (leftChild > lastNode) break; int maxChild = (rightChild <= lastNode && comp(v[leftChild], v[rightChild])) ? rightChild : leftChild; if (!comp(v[toSift], v[maxChild])) break; std::swap(v[toSift], v[maxChild]); toSift = maxChild; } } ASSERT(std::is_heap(begin, end, comp)); // An interruptible implementation of: // std::sort_heap(v.begin(), v.end(), comp); for (auto it = end; it != begin; --it) { if (this->th_interrupt_) return; std::pop_heap(begin, it, comp); } ASSERT(std::is_sorted(begin, end, comp)); this->valid_fullMap_ = true; } #else void SortCache::th_join() {} void SortCache::th_sort() {} #endif SortCache::SortCache(const Index* idx, const NameBase* nbase) : nGames_(0), valid_fullMap_(false), th_interrupt_(false), partialHash_(false), fullMap_(NULL), th_(NULL), hash_(NULL), index_(idx), nbase_(nbase), refCount_(0) {} SortCache::~SortCache() { th_interrupt(); delete[] hash_; delete[] fullMap_; } SortCache* SortCache::create(const Index* idx, const NameBase* nb, const char* criteria) { ASSERT(idx != NULL && nb != NULL && criteria != NULL); static const char fields[] = { SORTING_date, SORTING_year, SORTING_event, SORTING_site, SORTING_round, SORTING_white, SORTING_black, SORTING_eco, SORTING_result, SORTING_moveCount, SORTING_avgElo, SORTING_country, SORTING_deleted, SORTING_eventdate, SORTING_whiteelo, SORTING_blackelo, SORTING_commentcount, SORTING_varcount, SORTING_nagcount, SORTING_resultwin, SORTING_resultdraw, SORTING_resultloss, SORTING_rating, SORTING_number, SORTING_sentinel}; static const char* fields_end = fields + sizeof(fields); if (*criteria == '\0') // Invalid empty criteria. return NULL; SortCache* sc = new SortCache(idx, nb); // Parse the sorting criteria. size_t i = 0; for (const char *it = criteria; *it != 0; ++it) { bool valid = std::find(fields, fields_end, *it) != fields_end; sc->criteria_[i++] = *it++; bool reverse = (*it != '+'); sc->criteria_[i++] = reverse ? 1 : 0; if (!valid // Unknown field || (reverse && *it != '-') // Invalid asc/desc param || i >= sizeof(sc->criteria_)) // No space left for SORTING_sentinel { delete sc; return NULL; } } sc->criteria_[i] = SORTING_sentinel; sc->generateHashCache(); sc->sortAsynchronously(); return sc; } size_t SortCache::select(size_t row_offset, size_t row_count, const HFilter& filter, gamenumT* result) const { ASSERT(filter != NULL && filter->size() <= nGames_); ASSERT(result != NULL); const size_t maxResults = filter->size(); if (row_count == 0 || row_offset >= maxResults) return 0; size_t row_end = std::min(row_offset + row_count, maxResults); if (!valid_fullMap_) { gamenumT* v = new gamenumT[maxResults]; gamenumT* v_end = v + maxResults; if (maxResults == nGames_) { // std::iota(v, v_end, 0); for (gamenumT i = 0; i < maxResults; ++i) { v[i] = i; } } else { std::copy(filter->begin(), filter->end(), v); } size_t skip = 0; if (row_offset > 1000) { skip = row_offset; std::nth_element(v, v + row_offset, v_end, CmpLess(this)); } std::partial_sort(v + skip, v + row_end, v_end, CmpLess(this)); std::copy(v + row_offset, v + row_end, result); delete[] v; } else { if (maxResults == nGames_) { std::copy(fullMap_ + row_offset, fullMap_ + row_end, result); } else { size_t filterCount = 0; size_t i = 0; for (; filterCount < row_offset; i++) { if (filter->get(fullMap_[i]) != 0) filterCount++; } for (; filterCount != row_end; i++) { if (filter->get(fullMap_[i]) != 0) { *result++ = fullMap_[i]; filterCount++; } } } } return row_end - row_offset; } size_t SortCache::sortedPosition(gamenumT gameId, const HFilter& filter) const { ASSERT(filter != 0 && filter->size() <= nGames_); ASSERT(gameId < nGames_ && filter->get(gameId) != 0); size_t res = 0; if (valid_fullMap_) { for (gamenumT i = 0; i < nGames_; i++) { if (filter->get(fullMap_[i]) == 0) continue; if (fullMap_[i] == gameId) break; res++; } } else { CmpLess comp(this); for (gamenumT i = 0; i < nGames_; i++) { if (filter->get(i) == 0) continue; if (comp(i, gameId)) ++res; } } return res; } void SortCache::checkForChanges(gamenumT id) { th_interrupt(); if (id >= nGames_) { generateHashCache(); sortAsynchronously(); } else { hash_[id] = calcHash(id); if (valid_fullMap_) { gamenumT* begin = fullMap_; gamenumT* end = fullMap_ + nGames_; gamenumT* it = std::find(begin, end, id); ASSERT(it != end); // Reposition the game if necessary: // - to the left if it compares less than the previous element; // - to the right if the next element is lower. CmpLess comp(this); if (it != begin && comp(*it, *(it - 1))) { std::rotate( std::upper_bound(begin, it, *it, comp), it, it + 1); } else if (it + 1 != end && comp(*(it + 1), *it)) { std::rotate( it, it + 1, std::lower_bound(it + 1, end, *it, comp)); } ASSERT(std::is_sorted(begin, end, comp)); } else { sortAsynchronously(); } } } /* * Calculate the hashes of all games and store them into @e hash_. */ void SortCache::generateHashCache() { ASSERT(th_ == nullptr); valid_fullMap_ = false; nGames_ = index_->GetNumGames(); // Generate the hash table. delete[] hash_; hash_ = new uint32_t[nGames_]; for (gamenumT i = 0; i < nGames_; i++) { hash_[i] = calcHash(i); } } /* * Start a background thread that will sort the gameIds and will populate @e * fullMap_. */ void SortCache::sortAsynchronously() { ASSERT(th_ == nullptr); #ifndef MULTITHREADING_OFF delete[] fullMap_; fullMap_ = new gamenumT[nGames_]; th_ = new std::thread(&SortCache::th_sort, this); #endif } /* * Compare two games according to @e criteria_. * The @e index_ is accessed only if the games' hashes are equal. * @param g1: the id of the first game. * @param g2: the id of the second game. * @returns true if @e g1 is ordered before @e g2. */ bool SortCache::CmpLess::operator()(gamenumT g1, gamenumT g2) const { ASSERT(g1 < sc_->nGames_ && g2 < sc_->nGames_); if (sc_->hash_[g1] != sc_->hash_[g2]) return sc_->hash_[g1] < sc_->hash_[g2]; if (!sc_->partialHash_) return g1 < g2; int cmp = sc_->fullCompare(g1, g2); if (cmp != 0) return cmp < 0; return g1 < g2; } static const int RESULT_SORT[] = { 0, 3, 1, 2 }; static int nameComp(const NameBase* nbase, nameT nt, idNumberT id1, idNumberT id2) { ASSERT(nbase != NULL); return (id1 == id2) ? 0 : strCaseCompare(nbase->GetName(nt, id1), nbase->GetName(nt, id2)); } /* * Compare two games according to @e criteria_. * @param left: the id of the first game. * @param right: the id of the second game. * @returns * - <0 if @e left is ordered before @e right. * - >0 if @e right is ordered before @e left. * - 0 otherwise. */ int SortCache::fullCompare(gamenumT left, gamenumT right) const { const IndexEntry *ie1 = index_->GetEntry(left); const IndexEntry *ie2 = index_->GetEntry(right); for (const char* field = criteria_; *field != SORTING_sentinel; field += 2) { int res; switch (*field) { case SORTING_date: res = (int)ie1->GetDate() - (int)ie2->GetDate(); break; case SORTING_year: res = (int)ie1->GetYear() - (int)ie2->GetYear(); break; case SORTING_eco: res = (int)ie1->GetEcoCode() - (int)ie2->GetEcoCode(); break; case SORTING_moveCount: res = (int)ie1->GetNumHalfMoves() - (int)ie2->GetNumHalfMoves(); break; case SORTING_white: res = nameComp(nbase_, NAME_PLAYER, ie1->GetWhite(), ie2->GetWhite()); break; case SORTING_black: res = nameComp(nbase_, NAME_PLAYER, ie1->GetBlack(), ie2->GetBlack()); break; case SORTING_event: res = nameComp(nbase_, NAME_EVENT, ie1->GetEvent(), ie2->GetEvent()); break; case SORTING_site: res = nameComp(nbase_, NAME_SITE, ie1->GetSite(), ie2->GetSite()); break; case SORTING_round: { idNumberT id1 = ie1->GetRound(); idNumberT id2 = ie2->GetRound(); res = (id1 == id2) ? 0 : strCompareRound(nbase_->GetName(NAME_ROUND, id1), nbase_->GetName(NAME_ROUND, id2)); break; } case SORTING_resultwin: res = (ie1->GetResult() == RESULT_White ? 1 : 0) - (ie2->GetResult() == RESULT_White ? 1 : 0); break; case SORTING_resultdraw: res = (ie1->GetResult() == RESULT_Draw ? 1 : 0) - (ie2->GetResult() == RESULT_Draw ? 1 : 0); break; case SORTING_resultloss: res = (ie1->GetResult() == RESULT_Black ? 1 : 0) - (ie2->GetResult() == RESULT_Black ? 1 : 0); break; case SORTING_result: res = RESULT_SORT[ie1->GetResult()] - RESULT_SORT[ie2->GetResult()]; break; case SORTING_avgElo: // Average Elo rating: { int r1 = ie1->GetWhiteElo(nbase_) + ie1->GetBlackElo(nbase_); int r2 = ie2->GetWhiteElo(nbase_) + ie2->GetBlackElo(nbase_); res = r1 - r2; } break; case SORTING_country: // Last 3 characters of site field: { const char* sOne = ie1->GetSiteName(nbase_); const char* sTwo = ie2->GetSiteName(nbase_); size_t slenOne = std::strlen(sOne); size_t slenTwo = std::strlen(sTwo); if (slenOne > 3) { sOne += slenOne - 3; } if (slenTwo > 3) { sTwo += slenTwo - 3; } res = strCaseCompare (sOne, sTwo); } break; case SORTING_deleted: res = (int)ie1->GetDeleteFlag() - (int)ie2->GetDeleteFlag(); break; case SORTING_eventdate: res = (int)ie1->GetEventDate() - (int)ie2->GetEventDate(); break; case SORTING_whiteelo: res = (int)ie1->GetWhiteElo(nbase_) - (int)ie2->GetWhiteElo(nbase_); break; case SORTING_blackelo: res = (int)ie1->GetBlackElo(nbase_) - (int)ie2->GetBlackElo(nbase_); break; case SORTING_commentcount: res = (int) ie1->GetCommentCount() - (int) ie2->GetCommentCount(); break; case SORTING_varcount: res = (int) ie1->GetVariationCount() - (int) ie2->GetVariationCount(); break; case SORTING_nagcount: res = (int) ie1->GetNagCount() - (int) ie2->GetNagCount(); break; case SORTING_rating: res = (int)ie1->GetRating(nbase_) - (int)ie2->GetRating(nbase_); break; case SORTING_number: res = (int) left - (int) right; break; default: // Should never happen: ASSERT(0); return 0; } if (res != 0) return *(field + 1) ? -res : res; } return 0; } /* * Calculate an order-preserving hash corresponding to the current criteria. * @param gameId: the id of the game whose hash should be calculated. * @returns the hash value. */ uint32_t SortCache::calcHash(gamenumT gameId) { uint64_t retValue = 0; const size_t nHashBits = 32; size_t totalBitsUsed = 0; const IndexEntry* ie = index_->GetEntry(gameId); for (const char* field = criteria_; *field != SORTING_sentinel; ++field) { uint32_t value; size_t bitsUsed; switch (*field) { case SORTING_white: value = strStartHash(ie->GetWhiteName(nbase_)); bitsUsed = nHashBits; partialHash_ = true; break; case SORTING_black: value = strStartHash(ie->GetBlackName(nbase_)); bitsUsed = nHashBits; partialHash_ = true; break; case SORTING_site: value = strStartHash(ie->GetSiteName(nbase_)); bitsUsed = nHashBits; partialHash_ = true; break; case SORTING_event: value = strStartHash(ie->GetEventName(nbase_)); bitsUsed = nHashBits; partialHash_ = true; break; case SORTING_round: value = strGetUnsigned(ie->GetRoundName(nbase_)); bitsUsed = nHashBits; partialHash_ = true; break; case SORTING_country: { const char *scountry = ie->GetSiteName (nbase_); size_t slen = std::strlen(scountry); if (slen > 3) scountry += slen - 3; value = strStartHash(scountry); bitsUsed = nHashBits; partialHash_ = true; break; } case SORTING_date: value = ie->GetDate(); bitsUsed = 24; break; case SORTING_eventdate: value = ie->GetEventDate(); bitsUsed = 32; break; case SORTING_year: value = ie->GetYear(); bitsUsed = 16; break; case SORTING_whiteelo: value = ie->GetWhiteElo(nbase_); bitsUsed = 16; break; case SORTING_blackelo: value = ie->GetBlackElo(nbase_); bitsUsed = 16; break; case SORTING_avgElo: value = ie->GetWhiteElo(nbase_) + ie->GetBlackElo(nbase_); bitsUsed = 16; break; case SORTING_result: value = RESULT_SORT[ie->GetResult()]; bitsUsed = 8; break; case SORTING_resultwin: value = ie->GetResult() == RESULT_White ? 1 : 0; bitsUsed = 8; break; case SORTING_resultdraw: value = ie->GetResult() == RESULT_Draw ? 1 : 0; bitsUsed = 8; break; case SORTING_resultloss: value = ie->GetResult() == RESULT_Black ? 1 : 0; bitsUsed = 8; break; case SORTING_moveCount: value = ie->GetNumHalfMoves(); bitsUsed = 16; break; case SORTING_eco: value = ie->GetEcoCode(); bitsUsed = 16; break; case SORTING_commentcount: value = ie->GetCommentCount(); bitsUsed = 16; break; case SORTING_varcount: value = ie->GetVariationCount(); bitsUsed = 16; break; case SORTING_nagcount: value = ie->GetNagCount(); bitsUsed = 16; break; case SORTING_deleted: value = (ie->GetDeleteFlag() ? 1 : 0); bitsUsed = 8; break; case SORTING_rating: value = ie->GetRating(nbase_); bitsUsed = 8; break; case SORTING_number: value = gameId; bitsUsed = 32; break; default: // Should never happen: ASSERT(0); partialHash_ = true; return 0; } // If reverse order, just negate the cache value if (*++field) { value = ~value; if (sizeof(value) * 8 > bitsUsed) { // Clear the unused top bits value <<= sizeof(value) * 8 - bitsUsed; value >>= sizeof(value) * 8 - bitsUsed; } } // Combine with previous hash value retValue <<= bitsUsed; retValue |= value; totalBitsUsed += bitsUsed; // If not all search attributes fit, then it is a partial hash if (totalBitsUsed > nHashBits) { retValue >>= totalBitsUsed - nHashBits; partialHash_ = true; break; } if (totalBitsUsed == nHashBits) { if (*(field + 1) != SORTING_sentinel) partialHash_ = true; break; } } return static_cast(retValue); } chessx-master/dep/scid/code/src/stored.h0000755000076500000240000000361514666426276017365 0ustar jensstaff/* * Copyright (C) 2014 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ #ifndef SCID_STORED_H #define SCID_STORED_H #include "fullmove.h" class StoredLine { static constexpr int STORED_LINES = 255; static const FullMove* Moves_[STORED_LINES + 1]; int8_t matches_[STORED_LINES + 1]; public: StoredLine(const pieceT* board, colorT toMove); // Result: //-2 : the game cannot reach the searched position //-1 : the game can reach the searched position //>=0: the game reach the searched position at the returned ply int match(byte code) const { return matches_[code]; } template static byte classify(CompareOp comp) { int res = 0; std::ptrdiff_t longest = 0; for (int i = 1; i < STORED_LINES; ++i) { const auto begin = Moves_[i]; const auto end = Moves_[i + 1]; if (std::distance(begin, end) > longest && comp(begin, end)) { res = i; longest = std::distance(begin, end); } } return static_cast(res); } static FullMove getMove (byte code, uint ply = 0) { if ((code < STORED_LINES) && (Moves_[code] + ply) < Moves_[code +1]) { return Moves_[code][ply]; } return FullMove(); } }; #endif // #ifndef SCID_STORED_H ////////////////////////////////////////////////////////////////////// // EOF: stored.h ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/filebuf.h0000755000076500000240000001632114666426276017477 0ustar jensstaff/* * Copyright (C) 2014-2017 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ /** @file * Extends the std:filebuf class with performance improvements. */ #ifndef FILEBUF_H #define FILEBUF_H #include "common.h" #include #include /** * Adds some helper functions to std::filebuf: * - getline() * - read and write of unsigned integers with size of 32/24/16/8 bit. */ class Filebuf : public std::filebuf { public: /** * Opens a file. * @param filename: path to the file to be opened. * @param fmode: open the file for reading, writing, or both. * @returns OK on success, an @e errorT code on failure. */ errorT Open(const char* filename, fileModeT fmode) { std::ios::openmode mode = std::ios::binary; switch (fmode) { case FMODE_ReadOnly: mode |= std::ios::in; break; case FMODE_WriteOnly: mode |= std::ios::out; break; case FMODE_Both: mode |= std::ios::in | std::ios::out; break; case FMODE_Create: mode |= std::ios::in | std::ios::out | std::ios::trunc; break; default: return ERROR_FileMode; } return (open(filename, mode) != 0) ? OK : ERROR_FileOpen; } /** * Equivalent to std::fstream::getline, but faster (no sentry [27.7.2.1.3]). * * Extracts characters from @e *this and stores them in successive locations * of the array whose first element is pointed to by @p str, until the end * of line ('\\n' char) or the end of file condition occurs. * The '\\n' char is not stored into @p str, and a null character, even in * case of errors, is appended. * * Typical usage: @code * while (file.getline(buf, sizeof buf)) { * // use buf * } * if (file.sgetc() != EOF) // error * @endcode * @param str: pointer to the character string to store the characters to * @param count: size of character string pointed to by @p str * @returns * - the number of characters read, including the '\\n' char * - 0 on failure or if the buffer is too small. */ size_t getline(char* str, size_t count) { ASSERT(str != 0); ASSERT(count != 0); size_t n = 0; for (int ch = sgetc(); ch != EOF; ch = snextc()) { ++n; if (ch == '\n') { sbumpc(); break; } if (n >= count) { n = 0; // Fail: buffer too small break; } *str++ = static_cast(ch); } *str = 0; return n; } /** * Reads a 8-bit unsigned integer. * This function do not check for errors or EOF. */ byte ReadOneByte() { return static_cast(sbumpc()); } /** * Reads a 16-bit unsigned integer. * This function do not check for errors or EOF. */ uint16_t ReadTwoBytes() { return static_cast(read<2>()); } /** * Reads a 24-bit unsigned integer. * This function do not check for errors or EOF. */ uint32_t ReadThreeBytes() { return read<3>(); } /** * Reads a 32-bit unsigned integer. * This function do not check for errors or EOF. */ uint32_t ReadFourBytes() { return read<4>(); } /** * Writes a 8-bit unsigned integer. * @returns the number of characters successfully written. */ int WriteOneByte(byte value) { int_type ch = sputc(static_cast(value)); return (ch != traits_type::eof()) ? 1 : 0; } /** * Writes a 16-bit unsigned integer. * @returns the number of characters successfully written. */ int WriteTwoBytes(uint32_t value) { return WriteOneByte(static_cast(value >> 8)) + WriteOneByte(static_cast(value)); } /** * Writes a 24-bit unsigned integer. * @returns the number of characters successfully written. */ int WriteThreeBytes(uint32_t value) { return WriteOneByte(static_cast(value >> 16)) + WriteOneByte(static_cast(value >> 8)) + WriteOneByte(static_cast(value)); } /** * Writes a 32-bit unsigned integer. * @returns the number of characters successfully written. */ int WriteFourBytes(uint32_t value) { return WriteOneByte(static_cast(value >> 24)) + WriteOneByte(static_cast(value >> 16)) + WriteOneByte(static_cast(value >> 8)) + WriteOneByte(static_cast(value)); } private: template uint32_t read() { uint32_t res = 0; if (nBytes > 3) res += static_cast(ReadOneByte()) << 24; if (nBytes > 2) res += static_cast(ReadOneByte()) << 16; if (nBytes > 1) res += static_cast(ReadOneByte()) << 8; return res + ReadOneByte(); } }; /** * Optimizes std::filebuf for random-access reading. */ class FilebufAppend : protected Filebuf { std::streamoff fileSz_; std::streamoff filePos_; public: FilebufAppend() : fileSz_(0), filePos_(-1) {} /** * Opens a file and store its size. * @param filename: path to the file to be opened. * @param fmode: open the file for reading, writing, or both. * @returns OK on success, an @e errorT code on failure. */ errorT open(const std::string& filename, fileModeT fmode) { errorT res = Open(filename.c_str(), fmode); if (res != OK) return res; fileSz_ = pubseekoff(0, std::ios::end); if (fileSz_ == -1) return ERROR_FileSeek; return OK; } /** * Returns the size of the file. */ unsigned long long size() const { return fileSz_; } /** * Invokes std::filebuf::sync() to write all pending output to the file. * @returns 0 in case of success, -1 in case of failure. */ int pubsync() { return sync(); } /** * Writes, at the end of the file, @p count characters from the character * array whose first element is pointed to by @p s. * @returns OK in case of success, an error code otherwise. */ errorT append(const char_type* s, std::streamsize count) { assert(s != 0); if (filePos_ != -2) { // Seek to end of file, if necessary. filePos_ = seekpos(fileSz_); if (filePos_ == -1) return ERROR_FileSeek; filePos_ = -2; } std::streamsize n = xsputn(s, count); fileSz_ += n; return (n == count) ? OK : ERROR_FileWrite; } /** * Invoke filebuf::xsgetn() and update @e filePos_. */ std::streamsize sgetn(char_type* s, std::streamsize count) { std::streamsize res = xsgetn(s, count); filePos_ += res; return res; } /** * Repositions the internal buffer or invoke filebuf::seekpos(). * In the standard implementation, the buffer must be abandoned to ensure * consistency when transitioning from reading to writing. */ std::streamoff pubseekpos(std::streamoff pos) { if (filePos_ < 0 || pos < filePos_) return filePos_ = seekpos(pos); if (filePos_ != pos) { const std::streamsize avail = egptr() - gptr(); if (avail >= pos - filePos_) { ASSERT(pos - filePos_ <= INT_MAX); gbump(static_cast(pos - filePos_)); filePos_ = pos; } else { filePos_ = seekpos(pos); } } return filePos_; } }; #endif // FILEBUF_H chessx-master/dep/scid/code/src/containers.h0000755000076500000240000001130114666426276020221 0ustar jensstaff/* # Copyright (C) 2014-2017 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ #ifndef CONTAINERS_H #define CONTAINERS_H #include #include /** * A container useful for implementing a undo-redo behavior. * @e UNDOMAX: max number of copies to store. * Typical use: * store(obj_ptr); // (1) * modify obj; * obj_ptr = undo(obj_ptr); // obj_ptr now contains the copy of (1) */ template class UndoRedo { std::vector undo_; std::vector redo_; public: ~UndoRedo() { clear(); } void clear() { clear(undo_); clear(redo_); } size_t undoSize() const { return undo_.size(); } size_t redoSize() const { return redo_.size(); } /** * Stores a copy of an element into the undo queue. * Deletes all the objects of the redo queue. * @param current: the element to clone and store. */ void store(TElem* current) { clear(redo_); undo_.push_back(current->clone()); if (undo_.size() > UNDOMAX) { delete undo_.front(); undo_.erase(undo_.begin()); } } /** * Retrieve the last element from the undo queue. * @param current: pointer to the current element; it will be stored into * the redo queue. * @returns the pointer to the last element of the undo queue (the pointer * will be removed from the queue). If the queue is empty returns @e current */ TElem* undo(TElem* current) { return doUndoRedo(undo_, redo_, current); } /** * Retrieve the last element from the redo queue. * @param current: pointer to the current element; it will be stored into * the undo queue. * @returns the pointer to the last element of the redo queue (the pointer * will be removed from the queue). If the queue is empty returns @e current */ TElem* redo(TElem* current) { return doUndoRedo(redo_, undo_, current); } private: // Store current into cont2; remove and return the last element of cont1 template TElem* doUndoRedo(TCont& cont1, TCont& cont2, TElem* current) { if (cont1.empty()) return current; if (cont2.empty() || cont2.back() != current) cont2.push_back(current); auto res = cont1.back(); cont1.pop_back(); return res; } template void clear(TCont& cont) { for (auto& e : cont) delete e; cont.clear(); } }; /** * A vector-like container. Not all the elements are stored contiguously like in * a normal vector, but are allocated in separate chunks so that: * - growing in size do not move the elements and old references remain valid; * - very large containers can be created. * @e CHUNKSHIFT: is the base-2 logarithm of the number of T entries per chunk. * Total size of a chunk: (2^CHUNKSHIFT)*sizeof(T) */ template class VectorChunked { std::vector chunks_; size_t size_ = 0; static constexpr size_t low_mask = ((1ULL << CHUNKSHIFT) - 1); public: VectorChunked() = default; VectorChunked(const VectorChunked&) = delete; VectorChunked& operator=(const VectorChunked&) = delete; ~VectorChunked() { for (auto& chunk : chunks_) delete[] chunk; } const T& operator[](size_t idx) const { assert(idx < size_); return chunks_[idx >> CHUNKSHIFT][idx & low_mask]; } T& operator[](size_t idx) { assert(idx < size_); return chunks_[idx >> CHUNKSHIFT][idx & low_mask]; } size_t capacity() const { return chunks_.size() << CHUNKSHIFT; } /** * @returns * the count of contiguously allocated objects starting at @e pos (included) */ size_t contiguous(size_t pos) const { assert(pos < size()); return 1 + (~pos & low_mask); } void push_back(const T& e) { size_t idx = size_; resize(size_ + 1); operator[](idx) = e; } void resize(size_t count) { size_ = count; size_t newSize = (count > 0) ? 1 + (count >> CHUNKSHIFT) : 0; size_t chunksSz = chunks_.size(); if (newSize == chunksSz) return; if (newSize > chunksSz) { chunks_.resize(newSize); for (auto i = chunksSz; i < newSize; ++i) { chunks_[i] = new T[1ULL << CHUNKSHIFT]; } } else { for (auto i = newSize; i < chunksSz; ++i) { delete[] chunks_[i]; } chunks_.resize(newSize); } } size_t size() const { return size_; } }; #endif chessx-master/dep/scid/code/src/attacks.h0000755000076500000240000002121414666426276017512 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: attacks.h // Lists of attack squares // // Part of: Scid (Shane's Chess Information Database) // Version: 1.0 // // Notice: Copyright (c) 1999 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// #ifndef SCID_ATTACKS_H #define SCID_ATTACKS_H #include "board_def.h" // NOTE: These arrays have been automatically generated. Don't change // them unless the square or piece representations change! //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Knight Moves: // knightAttacks[sq] is an array of the squares a knight on sq // could move to. There are 9 target squares even though a knight // can only have at most 8 legal moves, so we can end the list with // an "NS" (null square). // // Example code to iterate through the knight moves for a square: // // squareT *dest = knightAttacks[fromSquare]; // while (*dest != NULL_SQUARE) { // /* do desired action.... */ // dest++; // } // const squareT knightAttacks[66][9] = { { /* A1 */ C2, B3, NS, NS, NS, NS, NS, NS, NS }, { /* B1 */ D2, A3, C3, NS, NS, NS, NS, NS, NS }, { /* C1 */ A2, E2, B3, D3, NS, NS, NS, NS, NS }, { /* D1 */ B2, F2, C3, E3, NS, NS, NS, NS, NS }, { /* E1 */ C2, G2, D3, F3, NS, NS, NS, NS, NS }, { /* F1 */ D2, H2, E3, G3, NS, NS, NS, NS, NS }, { /* G1 */ E2, F3, H3, NS, NS, NS, NS, NS, NS }, { /* H1 */ F2, G3, NS, NS, NS, NS, NS, NS, NS }, { /* A2 */ C1, C3, B4, NS, NS, NS, NS, NS, NS }, { /* B2 */ D1, D3, A4, C4, NS, NS, NS, NS, NS }, { /* C2 */ A1, E1, A3, E3, B4, D4, NS, NS, NS }, { /* D2 */ B1, F1, B3, F3, C4, E4, NS, NS, NS }, { /* E2 */ C1, G1, C3, G3, D4, F4, NS, NS, NS }, { /* F2 */ D1, H1, D3, H3, E4, G4, NS, NS, NS }, { /* G2 */ E1, E3, F4, H4, NS, NS, NS, NS, NS }, { /* H2 */ F1, F3, G4, NS, NS, NS, NS, NS, NS }, { /* A3 */ B1, C2, C4, B5, NS, NS, NS, NS, NS }, { /* B3 */ A1, C1, D2, D4, A5, C5, NS, NS, NS }, { /* C3 */ B1, D1, A2, E2, A4, E4, B5, D5, NS }, { /* D3 */ C1, E1, B2, F2, B4, F4, C5, E5, NS }, { /* E3 */ D1, F1, C2, G2, C4, G4, D5, F5, NS }, { /* F3 */ E1, G1, D2, H2, D4, H4, E5, G5, NS }, { /* G3 */ F1, H1, E2, E4, F5, H5, NS, NS, NS }, { /* H3 */ G1, F2, F4, G5, NS, NS, NS, NS, NS }, { /* A4 */ B2, C3, C5, B6, NS, NS, NS, NS, NS }, { /* B4 */ A2, C2, D3, D5, A6, C6, NS, NS, NS }, { /* C4 */ B2, D2, A3, E3, A5, E5, B6, D6, NS }, { /* D4 */ C2, E2, B3, F3, B5, F5, C6, E6, NS }, { /* E4 */ D2, F2, C3, G3, C5, G5, D6, F6, NS }, { /* F4 */ E2, G2, D3, H3, D5, H5, E6, G6, NS }, { /* G4 */ F2, H2, E3, E5, F6, H6, NS, NS, NS }, { /* H4 */ G2, F3, F5, G6, NS, NS, NS, NS, NS }, { /* A5 */ B3, C4, C6, B7, NS, NS, NS, NS, NS }, { /* B5 */ A3, C3, D4, D6, A7, C7, NS, NS, NS }, { /* C5 */ B3, D3, A4, E4, A6, E6, B7, D7, NS }, { /* D5 */ C3, E3, B4, F4, B6, F6, C7, E7, NS }, { /* E5 */ D3, F3, C4, G4, C6, G6, D7, F7, NS }, { /* F5 */ E3, G3, D4, H4, D6, H6, E7, G7, NS }, { /* G5 */ F3, H3, E4, E6, F7, H7, NS, NS, NS }, { /* H5 */ G3, F4, F6, G7, NS, NS, NS, NS, NS }, { /* A6 */ B4, C5, C7, B8, NS, NS, NS, NS, NS }, { /* B6 */ A4, C4, D5, D7, A8, C8, NS, NS, NS }, { /* C6 */ B4, D4, A5, E5, A7, E7, B8, D8, NS }, { /* D6 */ C4, E4, B5, F5, B7, F7, C8, E8, NS }, { /* E6 */ D4, F4, C5, G5, C7, G7, D8, F8, NS }, { /* F6 */ E4, G4, D5, H5, D7, H7, E8, G8, NS }, { /* G6 */ F4, H4, E5, E7, F8, H8, NS, NS, NS }, { /* H6 */ G4, F5, F7, G8, NS, NS, NS, NS, NS }, { /* A7 */ B5, C6, C8, NS, NS, NS, NS, NS, NS }, { /* B7 */ A5, C5, D6, D8, NS, NS, NS, NS, NS }, { /* C7 */ B5, D5, A6, E6, A8, E8, NS, NS, NS }, { /* D7 */ C5, E5, B6, F6, B8, F8, NS, NS, NS }, { /* E7 */ D5, F5, C6, G6, C8, G8, NS, NS, NS }, { /* F7 */ E5, G5, D6, H6, D8, H8, NS, NS, NS }, { /* G7 */ F5, H5, E6, E8, NS, NS, NS, NS, NS }, { /* H7 */ G5, F6, F8, NS, NS, NS, NS, NS, NS }, { /* A8 */ B6, C7, NS, NS, NS, NS, NS, NS, NS }, { /* B8 */ A6, C6, D7, NS, NS, NS, NS, NS, NS }, { /* C8 */ B6, D6, A7, E7, NS, NS, NS, NS, NS }, { /* D8 */ C6, E6, B7, F7, NS, NS, NS, NS, NS }, { /* E8 */ D6, F6, C7, G7, NS, NS, NS, NS, NS }, { /* F8 */ E6, G6, D7, H7, NS, NS, NS, NS, NS }, { /* G8 */ F6, H6, E7, NS, NS, NS, NS, NS, NS }, { /* H8 */ G6, F7, NS, NS, NS, NS, NS, NS, NS }, { /* COL*/ NS, NS, NS, NS, NS, NS, NS, NS, NS }, { /* NS */ NS, NS, NS, NS, NS, NS, NS, NS, NS } }; // King moves: // As for the knight moves, the secondary array size is 9 even // though there are only 8 possible king moves, so there can // always be a NULL_SQUARE terminating the list of moves for each // square. Castling moves are not included here. const squareT kingAttacks[66][9] = { { /* A1 */ B1, A2, B2, NS, NS, NS, NS, NS, NS }, { /* B1 */ A1, C1, A2, B2, C2, NS, NS, NS, NS }, { /* C1 */ B1, D1, B2, C2, D2, NS, NS, NS, NS }, { /* D1 */ C1, E1, C2, D2, E2, NS, NS, NS, NS }, { /* E1 */ D1, F1, D2, E2, F2, NS, NS, NS, NS }, { /* F1 */ E1, G1, E2, F2, G2, NS, NS, NS, NS }, { /* G1 */ F1, H1, F2, G2, H2, NS, NS, NS, NS }, { /* H1 */ G1, G2, H2, NS, NS, NS, NS, NS, NS }, { /* A2 */ A1, B1, B2, A3, B3, NS, NS, NS, NS }, { /* B2 */ A1, B1, C1, A2, C2, A3, B3, C3, NS }, { /* C2 */ B1, C1, D1, B2, D2, B3, C3, D3, NS }, { /* D2 */ C1, D1, E1, C2, E2, C3, D3, E3, NS }, { /* E2 */ D1, E1, F1, D2, F2, D3, E3, F3, NS }, { /* F2 */ E1, F1, G1, E2, G2, E3, F3, G3, NS }, { /* G2 */ F1, G1, H1, F2, H2, F3, G3, H3, NS }, { /* H2 */ G1, H1, G2, G3, H3, NS, NS, NS, NS }, { /* A3 */ A2, B2, B3, A4, B4, NS, NS, NS, NS }, { /* B3 */ A2, B2, C2, A3, C3, A4, B4, C4, NS }, { /* C3 */ B2, C2, D2, B3, D3, B4, C4, D4, NS }, { /* D3 */ C2, D2, E2, C3, E3, C4, D4, E4, NS }, { /* E3 */ D2, E2, F2, D3, F3, D4, E4, F4, NS }, { /* F3 */ E2, F2, G2, E3, G3, E4, F4, G4, NS }, { /* G3 */ F2, G2, H2, F3, H3, F4, G4, H4, NS }, { /* H3 */ G2, H2, G3, G4, H4, NS, NS, NS, NS }, { /* A4 */ A3, B3, B4, A5, B5, NS, NS, NS, NS }, { /* B4 */ A3, B3, C3, A4, C4, A5, B5, C5, NS }, { /* C4 */ B3, C3, D3, B4, D4, B5, C5, D5, NS }, { /* D4 */ C3, D3, E3, C4, E4, C5, D5, E5, NS }, { /* E4 */ D3, E3, F3, D4, F4, D5, E5, F5, NS }, { /* F4 */ E3, F3, G3, E4, G4, E5, F5, G5, NS }, { /* G4 */ F3, G3, H3, F4, H4, F5, G5, H5, NS }, { /* H4 */ G3, H3, G4, G5, H5, NS, NS, NS, NS }, { /* A5 */ A4, B4, B5, A6, B6, NS, NS, NS, NS }, { /* B5 */ A4, B4, C4, A5, C5, A6, B6, C6, NS }, { /* C5 */ B4, C4, D4, B5, D5, B6, C6, D6, NS }, { /* D5 */ C4, D4, E4, C5, E5, C6, D6, E6, NS }, { /* E5 */ D4, E4, F4, D5, F5, D6, E6, F6, NS }, { /* F5 */ E4, F4, G4, E5, G5, E6, F6, G6, NS }, { /* G5 */ F4, G4, H4, F5, H5, F6, G6, H6, NS }, { /* H5 */ G4, H4, G5, G6, H6, NS, NS, NS, NS }, { /* A6 */ A5, B5, B6, A7, B7, NS, NS, NS, NS }, { /* B6 */ A5, B5, C5, A6, C6, A7, B7, C7, NS }, { /* C6 */ B5, C5, D5, B6, D6, B7, C7, D7, NS }, { /* D6 */ C5, D5, E5, C6, E6, C7, D7, E7, NS }, { /* E6 */ D5, E5, F5, D6, F6, D7, E7, F7, NS }, { /* F6 */ E5, F5, G5, E6, G6, E7, F7, G7, NS }, { /* G6 */ F5, G5, H5, F6, H6, F7, G7, H7, NS }, { /* H6 */ G5, H5, G6, G7, H7, NS, NS, NS, NS }, { /* A7 */ A6, B6, B7, A8, B8, NS, NS, NS, NS }, { /* B7 */ A6, B6, C6, A7, C7, A8, B8, C8, NS }, { /* C7 */ B6, C6, D6, B7, D7, B8, C8, D8, NS }, { /* D7 */ C6, D6, E6, C7, E7, C8, D8, E8, NS }, { /* E7 */ D6, E6, F6, D7, F7, D8, E8, F8, NS }, { /* F7 */ E6, F6, G6, E7, G7, E8, F8, G8, NS }, { /* G7 */ F6, G6, H6, F7, H7, F8, G8, H8, NS }, { /* H7 */ G6, H6, G7, G8, H8, NS, NS, NS, NS }, { /* A8 */ A7, B7, B8, NS, NS, NS, NS, NS, NS }, { /* B8 */ A7, B7, C7, A8, C8, NS, NS, NS, NS }, { /* C8 */ B7, C7, D7, B8, D8, NS, NS, NS, NS }, { /* D8 */ C7, D7, E7, C8, E8, NS, NS, NS, NS }, { /* E8 */ D7, E7, F7, D8, F8, NS, NS, NS, NS }, { /* F8 */ E7, F7, G7, E8, G8, NS, NS, NS, NS }, { /* G8 */ F7, G7, H7, F8, H8, NS, NS, NS, NS }, { /* H8 */ G7, H7, G8, NS, NS, NS, NS, NS, NS }, { /* COL*/ NS, NS, NS, NS, NS, NS, NS, NS, NS }, { /* NS */ NS, NS, NS, NS, NS, NS, NS, NS, NS } }; #endif // #ifndef SCID_ATTACKS_H ////////////////////////////////////////////////////////////////////// // EOF: attacks.h ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/codec_native.h0000755000076500000240000001045514666426276020510 0ustar jensstaff/* * Copyright (C) 2017 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . * */ /** @file * Implements @e CodecNative, which is used as base class by native codecs. */ #ifndef CODEC_NATIVE_H #define CODEC_NATIVE_H #include "bytebuf.h" #include "codec.h" #include "game.h" #include "index.h" #include "namebase.h" #include /** * This class stores the pointers to the @e Index and @e NameBase objects used * by a native codec. It also implements the addGame() and saveGame() functions * of the ICodecDatabase interface, splitting them into 2 function calls to a * derived class (CRTP technique): * - dyn_addName() should return the ID corresponding to a name, eventually * adding the name to the @e nb_ if necessary; * - dyn_addGameData() should stores the data of the game, encoded in native * format, and returns the offset that can be used to retrieve the data. */ template class CodecNative : public ICodecDatabase { protected: Index* idx_ = nullptr; NameBase* nb_ = nullptr; std::vector bbuf_; public: // ICodecDatabase interface errorT addGame(const IndexEntry* srcIe, const NameBase* srcNb, const byte* srcData, size_t dataLen) override { IndexEntry ie = *srcIe; errorT err = addGameHelper( &ie, srcData, dataLen, srcNb->GetName(NAME_PLAYER, srcIe->GetWhite()), srcNb->GetName(NAME_PLAYER, srcIe->GetBlack()), srcNb->GetName(NAME_EVENT, srcIe->GetEvent()), srcNb->GetName(NAME_SITE, srcIe->GetSite()), srcNb->GetName(NAME_ROUND, srcIe->GetRound())); if (err != OK) return err; return derived()->dyn_addIndexEntry(ie); } errorT addGame(Game* game) override { bbuf_.clear(); IndexEntry ie; auto err = game->Encode(bbuf_, ie); if (err) return err; err = addGameHelper(&ie, bbuf_.data(), bbuf_.size(), game->GetWhiteStr(), game->GetBlackStr(), game->GetEventStr(), game->GetSiteStr(), game->GetRoundStr()); if (err) return err; return derived()->dyn_addIndexEntry(ie); } errorT saveGame(Game* game, gamenumT replaced) override { if (replaced >= idx_->GetNumGames()) return ERROR_BadArg; bbuf_.clear(); IndexEntry ie; auto err = game->Encode(bbuf_, ie); if (err) return err; err = addGameHelper(&ie, bbuf_.data(), bbuf_.size(), game->GetWhiteStr(), game->GetBlackStr(), game->GetEventStr(), game->GetSiteStr(), game->GetRoundStr()); if (err) return err; return derived()->dyn_saveIndexEntry(ie, replaced); } private: errorT addGameHelper(IndexEntry* ie, const byte* srcData, size_t dataLen, const char* white, const char* black, const char* event, const char* site, const char* round) { auto id = derived()->dyn_addName(NAME_PLAYER, white); if (id.first != OK) return id.first; ie->SetWhite(id.second); nb_->AddElo(id.second, ie->GetWhiteElo()); id = derived()->dyn_addName(NAME_PLAYER, black); if (id.first != OK) return id.first; ie->SetBlack(id.second); nb_->AddElo(id.second, ie->GetBlackElo()); id = derived()->dyn_addName(NAME_EVENT, event); if (id.first != OK) return id.first; ie->SetEvent(id.second); id = derived()->dyn_addName(NAME_SITE, site); if (id.first != OK) return id.first; ie->SetSite(id.second); id = derived()->dyn_addName(NAME_ROUND, round); if (id.first != OK) return id.first; ie->SetRound(id.second); auto offset = derived()->dyn_addGameData(srcData, dataLen); if (offset.first == OK) { ie->SetOffset(offset.second); ie->SetLength(dataLen); } return offset.first; } Derived* derived() { return static_cast(this); } }; #endif chessx-master/dep/scid/code/src/textbuf.cpp0000755000076500000240000001546414666426276020106 0ustar jensstaff/////////////////////////////////////////////////////////////////////////// // // FILE: textbuf.cpp // TextBuffer class methods // // Part of: Scid (Shane's Chess Information Database) // Version: 2.7 // // Notice: Copyright (c) 1999-2001 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // /////////////////////////////////////////////////////////////////////////// #include "textbuf.h" #include "misc.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### TextBuffer::Init(): Initialise the textbuffer. void TextBuffer::Init (void) { BufferSize = Column = IndentColumn = LineCount = ByteCount = 0; LineIsEmpty = 1; Buffer = Current = NULL; WrapColumn = 80; ConvertNewlines = true; HasTranslations = false; PausedTranslations = false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### TextBuffer::Free(): Free the TextBuffer. void TextBuffer::Free (void) { if (Buffer != NULL) { #ifdef WINCE my_Tcl_Free( Buffer); #else delete[] Buffer; #endif Buffer = NULL; BufferSize = 0; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### TextBuffer::Empty(): Empty the TextBuffer. void TextBuffer::Empty (void) { ASSERT(Buffer != NULL); ByteCount = Column = LineCount = 0; LineIsEmpty = 1; Current = Buffer; *Current = 0; ConvertNewlines = true; HasTranslations = false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // TextBuffer::AddTranslation(): // Adds a translation for a character. // The translation string will be printed in place of that character. void TextBuffer::AddTranslation (char ch, const char * str) { if (! HasTranslations) { HasTranslations = true; for (uint i=0; i < 256; i++) { Translation [i] = NULL; } } Translation [(byte) ch] = str; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### TextBuffer::SetBufferSize(): Set the buffer size. void TextBuffer::SetBufferSize (uint length) { #ifdef WINCE if (Buffer != NULL) { my_Tcl_Free( Buffer); } Buffer = my_Tcl_Alloc(sizeof(char[length])); #else if (Buffer != NULL) { delete[] Buffer; } Buffer = new char[length]; #endif BufferSize = length; ByteCount = Column = LineCount = 0; LineIsEmpty = 1; Current = Buffer; *Current = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### TextBuffer::NewLine(): Add a newline. errorT TextBuffer::NewLine () { ASSERT (Current != NULL); if (ByteCount >= BufferSize) { return ERROR_BufferFull; } *Current++ = '\n'; LineCount++; ByteCount++; LineIsEmpty = 1; Column = 0; while (Column < IndentColumn) { if (ByteCount >= BufferSize) { return ERROR_BufferFull; } *Current++ = ' '; Column++; ByteCount++; } *Current = 0; return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### TextBuffer::Indent(): Indent to the current Indentation level.. errorT TextBuffer::Indent () { ASSERT (Current != NULL); if (!LineIsEmpty) { return NewLine(); } else { while (Column < IndentColumn) { if (ByteCount >= BufferSize) { return ERROR_BufferFull; } *Current++ = ' '; Column++; ByteCount++; } *Current = 0; } return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### TextBuffer::PrintLine(): Print a string then newline. Does not // check for the line going past WrapColumn. errorT TextBuffer::PrintLine (const char * str) { ASSERT(Current != NULL); while (*str != 0) { if (ByteCount > BufferSize) { return ERROR_BufferFull; } AddChar (*str); str++; } return NewLine(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### TextBuffer::PrintWord(): Prints a word, wrapping if necessary. // It does NOT add a space, since that is left to the caller to // provide in the string. errorT TextBuffer::PrintWord (const char * str) { ASSERT(Current != NULL); uint length = strLength (str); if (Column + length >= WrapColumn) { NewLine(); } if (ByteCount + length >= BufferSize) { return ERROR_BufferFull; } while (*str != 0) { char ch = *str; AddChar (ch); str++; Column++; } *Current = 0; // add trailing end-of-string to buffer LineIsEmpty = 0; return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### TextBuffer::PrintSpace(): Prints a space OR a newline character, // but not both. errorT TextBuffer::PrintSpace (void) { if (ByteCount + 1 >= BufferSize) { return ERROR_BufferFull; } if (Column + 1 >= WrapColumn) { NewLine(); } else { *Current = ' '; Current++; ByteCount++; Column++; LineIsEmpty = 0; } return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### TextBuffer::PrintChar(): prints a single char, adding a newline // first if necessary. errorT TextBuffer::PrintChar (char b) { if (Column + 1 >= WrapColumn) { NewLine(); } if (ByteCount + 1 >= BufferSize) { return ERROR_BufferFull; } AddChar (b); Column++; LineIsEmpty = 0; return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### TextBuffer::PrintString(): Print a string, wrapping at spaces. // Also converts newlines in the string into spaces. errorT TextBuffer::PrintString (const char * str) { errorT err; char currentWord[1024]; // should be long enough for a word while (*str != 0) { char * b = currentWord; *b = 0; // get next word and print it: while (*str != ' ' && *str != '\n' && *str != '\0') { *b = *str; b++; str++; } // end of word/line/text reached *b = 0; err = PrintWord (currentWord); if (err != OK) { return err; } if (*str == 0) { return OK; } if (*str == '\n' && !ConvertNewlines) { err = NewLine(); } else { err = PrintSpace(); } if (err != OK) { return err; } str++; } return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //### TextBuffer::PrintInt(): Print a decimal number followed by string // as a word (so it appends a space at the end and wraps if // necessary). errorT TextBuffer::PrintInt (uint i, const char * str) { char temp[255]; snprintf(temp, 255, "%d%s", i, str); return PrintWord(temp); } /////////////////////////////////////////////////////////////////////////// // EOF: textbuf.cpp /////////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/dstring.h0000755000076500000240000000536414666426276017542 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: dstring.h // Dynamic String class // // Part of: Scid (Shane's Chess Information Database) // Version: 2.2 // // Notice: Copyright (c) 2000 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// #ifndef SCID_DSTRING_H #define SCID_DSTRING_H #include #include class DString { // DEPRECATED std::string s_; public: void Clear() { s_.clear(); } const char* Data() { return s_.c_str(); } size_t Length(void) { return s_.size(); } void AddChar(char ch) { s_.append(1, ch); } void AppendUint(uint i) { char s[16]; snprintf(s, 16, "%u", i); s_.append(s); } void AppendInt(int i) { char s[16]; snprintf(s, 16, "%d", i); s_.append(s); } void Append(uint i) { AppendUint(i); } void Append(const char* str) { s_.append(str); } // To allow convenient appending of multiple strings without resorting // to messy variable-length argument lists, we define DString::Append() // for up to five string arguments, and for up to four arguments where // one is an unsigned integer and the rest are strings. void Append(const char* s1, const char* s2) { Append(s1); Append(s2); } void Append(const char* s1, uint i2) { Append(s1); Append(i2); } void Append(uint i1, const char* s2) { Append(i1); Append(s2); } void Append(const char* s1, const char* s2, const char* s3) { Append(s1); Append(s2); Append(s3); } void Append(const char* s1, const char* s2, uint i3) { Append(s1); Append(s2); Append(i3); } void Append(const char* s1, uint i2, const char* s3) { Append(s1); Append(i2); Append(s3); } void Append(uint i1, const char* s2, const char* s3) { Append(i1); Append(s2); Append(s3); } void Append(const char* s1, const char* s2, const char* s3, const char* s4) { Append(s1); Append(s2); Append(s3); Append(s4); } void Append(const char* s1, const char* s2, const char* s3, uint i4) { Append(s1); Append(s2); Append(s3); Append(i4); } void Append(const char* s1, const char* s2, uint i3, const char* s4) { Append(s1); Append(s2); Append(i3); Append(s4); } void Append(const char* s1, uint i2, const char* s3, const char* s4) { Append(s1); Append(i2); Append(s3); Append(s4); } void Append(uint i1, const char* s2, const char* s3, const char* s4) { Append(i1); Append(s2); Append(s3); Append(s4); } void Append(const char* s1, const char* s2, const char* s3, const char* s4, const char* s5) { Append(s1); Append(s2); Append(s3); Append(s4); Append(s5); } }; #endif // SCID_DSTRING_H chessx-master/dep/scid/code/src/hash.h0000755000076500000240000002533014666426276017006 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: hash.h // Pre-generated random hash values // // Part of: Scid (Shane's Chess Information Database) // Version: 3.4 // // Notice: Copyright (c) 2002 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// #ifndef SCID_HASH_H #define SCID_HASH_H // goodHashValues // This is a table of 12 (pieces) * 64 (squares) = 768 pre-generated // "good" 32-bit hash values, to be used for Zobrist hashing. // The values were generated using a threshold of 10, meaning that // (a) every value has at least 10 and at most 32-10=22 bits set; // (b) every value differs from every other value by at least 10 // bits and at most 32-10=22 bits. // const uint goodHashValues [12 * 64] = { 0x039B11BFu,0x4890D6A4u,0x37539B8Au,0xA7E3A104u,0x8B263019u,0xEB71AE0Bu, 0x87099341u,0x32EF9CD4u,0x698B8BC1u,0x823FEACEu,0x8E607A5Au,0x7241E921u, 0x8E94A4B6u,0x2670B742u,0xD721044Cu,0xD1FC122Du,0xBD0CE70Eu,0xA4159629u, 0xAE24AD63u,0xAB5DA9E9u,0x83D1C843u,0x32E60A29u,0xABF131AAu,0x3C3CF99Du, 0x5553E1FDu,0xD8328308u,0x9B2FC0D4u,0x4EDC83D2u,0x852D84B3u,0x068D4A5Fu, 0x35CE432Fu,0xE4843746u,0x2B67AF9Eu,0xABCCC099u,0x217F1CAAu,0x7BF4C414u, 0x7C24E036u,0x29E3C6EAu,0x1053B4CCu,0x8D96DDA0u,0x4505DA02u,0x47EFD3ECu, 0x32B9D1EDu,0x4F688C67u,0x1FFD9115u,0xBC0156DBu,0x28BD842Eu,0xECE11B80u, 0x2088BE1Fu,0x3384DFE4u,0x05AAE96Eu,0xE697A8F5u,0x02E84551u,0x6E0B75ABu, 0xC8EE1CA1u,0x5387CC68u,0xB0991EB4u,0x332AD23Eu,0x7063DDB8u,0x844141B4u, 0x3D49AAA0u,0xB73790D3u,0x2009A159u,0x43BCD4B9u,0x3E47B851u,0x992161E6u, 0x5C73DE21u,0xA7185F26u,0xEAF78BCFu,0x9F46F244u,0x90E2E582u,0x2752602Au, 0x8D75AA38u,0x4429875Eu,0xDAB54C3Bu,0x15F07D87u,0x24936E7Du,0xD26AF16Au, 0xF0C1BAA7u,0x3A34F2E0u,0x0A86593Eu,0xBB870177u,0xF1BCB046u,0x91B63283u, 0x881BA73Au,0x7FB62D0Cu,0x9F06ED35u,0x4CF4B1ACu,0x24A21F70u,0x509421A2u, 0xE492FD51u,0x9DE1F22Fu,0xFCEADB75u,0x1244A7B5u,0x9ACABF60u,0xA32479B2u, 0x0396C362u,0x0CEF72D2u,0x9B9D27A1u,0x3306A989u,0x516008FCu,0xE544EA8Du, 0xC33DBE2Cu,0xE80D5B56u,0xDC6FC86Fu,0x4A3F3D4Du,0xAE160A34u,0x00512AA9u, 0xE6B8170Du,0x419DE2C5u,0x6B2E2517u,0x89D27208u,0x92847C09u,0x38E38217u, 0x2821286Fu,0x8AE2AAD5u,0x30FDAE11u,0x543C234Bu,0xE3A2FF38u,0x10194DDEu, 0x657AACB5u,0x9B7A5005u,0xE4F5DD9Eu,0x43C4B54Cu,0x7FB1E299u,0xBA0FBFADu, 0x6650C485u,0xA93F6201u,0x0D27DBDFu,0x03415B76u,0x6BB1E5F7u,0xFD2A98F8u, 0x3DB93342u,0xE14B1091u,0xBF290710u,0xF23142FCu,0xAB80B2CBu,0xFB60F74Du, 0x21F3BB77u,0x3888CAADu,0x8A9ADBEFu,0x789090FFu,0x9D730E8Du,0x49B24A39u, 0xD7910113u,0xD106D4B2u,0xD2EE43B5u,0x6D341063u,0xB61EDC4Eu,0x9550B69Bu, 0xB31BF6E6u,0xA77E70C6u,0xD5A2839Fu,0x36B5397Fu,0xB9ECCD6Au,0x5748A700u, 0xE55FD773u,0x05B1D3B3u,0x02C832FCu,0x44475068u,0x5A3FA331u,0x7E98673Fu, 0x019BD400u,0x2B500871u,0x1B11BBD3u,0xD9A16849u,0x3D28C47Du,0x5B5A17F8u, 0x11A56BBFu,0x7A49A7EAu,0x827A948Bu,0x9CFCA8F3u,0xD0139857u,0x66934246u, 0x010B6D83u,0x640E91CBu,0x14F7F949u,0x22E1DBDBu,0xFE39F428u,0xC1EFF01Du, 0xB7FBAA70u,0x24D621C8u,0x3E8CB46Cu,0x799C9A30u,0x9101AA6Au,0x50057267u, 0x4ABB8084u,0x96A69B26u,0x64430CE7u,0x29104757u,0xF895CE65u,0xACE8C5A7u, 0x8C311979u,0xC50D43F9u,0x74E82B12u,0x7DD3F51Au,0x024CB893u,0x1082235Au, 0x267DE6F9u,0xF07D4A07u,0x2269E0C4u,0x58CD4E12u,0xA5BECEC3u,0x548B6301u, 0x1DAD51A9u,0xEDD5C126u,0x82F2633Bu,0xC03AA07Cu,0xEF54151Fu,0xAA6B4422u, 0x065BC9E0u,0xC35692CEu,0xA1D7DB4Cu,0xD8633DF3u,0x7298EB8Au,0xFF0A0ACFu, 0x0DA1A674u,0x6DE7B4C7u,0xE761833Au,0xF9FF6F50u,0x84BC2B8Cu,0xE799B3BCu, 0x16161665u,0xF8F95501u,0x576662B2u,0x16C9842Au,0xB200D414u,0xF0B5A23Au, 0xDE336B9Eu,0x6E2C4FCEu,0x0DD75B71u,0xDA5F5B65u,0x10305BF5u,0x25459D34u, 0x9024995Au,0x9A35CB81u,0xB04481ECu,0x852EADD4u,0x3979197Eu,0x758912F3u, 0xC73CDAF6u,0xDF52A76Eu,0xC7340794u,0x6C5684BBu,0x9FA057F2u,0xD740B832u, 0xB7AF5E98u,0x0BB2995Du,0xB58AB9B7u,0xFE0BD190u,0xB992ECC8u,0x9FD77CDCu, 0xCD786AFDu,0x9D06944Bu,0x94DB6416u,0xF7086164u,0x06BA82F7u,0x897BFB24u, 0xA3F57351u,0x73087E2Bu,0x05857541u,0xA0BE3365u,0x4FB89F40u,0xCC8BF6FDu, 0xB6F359A4u,0x7FFAF82Du,0xFF05C5DDu,0x41C88B7Au,0xD94586E9u,0x8ECBE977u, 0xC02DB501u,0x085DD109u,0xE167E374u,0xE22877E1u,0xFC504828u,0x5A593E86u, 0xB82D503Cu,0x0E23B9A4u,0x1DA667E5u,0xD6E88E31u,0x87B13CBDu,0x73A7CB92u, 0x1176EFD8u,0x805EC39Fu,0x0FAA9AAAu,0xB2F707B2u,0xB67AE203u,0x8BCC0DAFu, 0xE1D2659Cu,0x481CC9B6u,0x4EA7AE2Du,0x3F0E1BB1u,0xA0EFE34Bu,0xFB8D54E2u, 0xEEE20096u,0x20F49785u,0xA059722Eu,0xF54885FBu,0xBB655656u,0xD674D353u, 0x1C2249E8u,0xA4718FF5u,0x61A84E05u,0xA3126E85u,0x61D9AD54u,0x07198C19u, 0xB972FB1Bu,0x5238CA6Fu,0xA1BFB910u,0x8645AEC8u,0xE6C48940u,0xAB771F63u, 0x17E50DB8u,0x2D864432u,0x1D832682u,0x90B555C4u,0xF57533F8u,0xD7CD623Cu, 0x30F276B1u,0x968A4BC2u,0x43D75E3Fu,0x232BD8E3u,0x09D8EEF6u,0xE43898C5u, 0x590FF714u,0x578FB433u,0x7CA18ACEu,0x5E8BBA1Eu,0x9377431Cu,0x352D8B78u, 0x5D64CBE6u,0xAC0E4DFBu,0x8CC6D71Au,0x357E5A72u,0xE52B7EC4u,0x8BA3C715u, 0x637A16E7u,0xE53DE860u,0x5D8D3992u,0x69FA014Cu,0xA741FD99u,0x1D446311u, 0xD1B7AD7Du,0xB09D684Au,0x2AB52F38u,0x115A6A4Eu,0x70FA8C72u,0x280593A6u, 0x90E51413u,0x40D69014u,0xFE54E992u,0x80B0DF0Bu,0xADCEAA5Cu,0x2CE5D77Du, 0xC848DD13u,0x1816469Cu,0xF29F0F0Eu,0x5267A846u,0x9519EB95u,0x36A0F7ABu, 0x47286387u,0x1FDDB6CAu,0xBCDB9881u,0xC2D197BBu,0x6EAEE818u,0x283E0B1Bu, 0xF2E87D37u,0x210662D0u,0x093BAE47u,0x7A2307D6u,0x79876ECFu,0x19DD55B6u, 0xC8903A3Eu,0x00A6B10Fu,0xF9C00FD4u,0x494BB0A6u,0x97FF861Bu,0x70BD145Du, 0x7F46D4ACu,0xE6F63ECCu,0x707613DFu,0x89A9805Fu,0x98035A70u,0xE941DB3Du, 0x84E3C899u,0x4E8CFB84u,0xB51B01EEu,0xBFF2D163u,0xC3A8202Bu,0x18BB798Au, 0x12DF54DBu,0xD10B9FFEu,0xCEB08E5Fu,0xA2250D9Du,0x0E5C8F05u,0x3BCB935Cu, 0x1BD051C9u,0x46214EF2u,0xDDF5D4D1u,0x37A19E57u,0x16DE6F73u,0x25AFB2B9u, 0xDD2E7E69u,0x082894FAu,0x1535FCF4u,0x7EECD60Fu,0x6E9FCEAAu,0x96D6D08Du, 0x79C709AAu,0x1CA5070Fu,0xB8A7AED2u,0x80684E96u,0xC7D6497Cu,0xB93DD3FBu, 0xFA20C05Bu,0xF55A0330u,0x6D226F9Bu,0x66A532A2u,0x73FD3ABBu,0xC77B9A07u, 0xCDC921ECu,0xB68E327Bu,0xB7F9555Cu,0x30BA9B4Eu,0x4C879967u,0xC9A75320u, 0xFC83700Cu,0x4027063Bu,0x1B630D64u,0x587C3550u,0x1CFC5B44u,0xA5AD192Eu, 0xFBE9177Bu,0x1EABD059u,0xAA4468C7u,0x76AA58BBu,0xB4B08556u,0x71EE9F17u, 0xB3F5AC8Cu,0xE6D8DBA1u,0x8B0AF89Eu,0xD36C2B70u,0x128D3DEAu,0x3D460CD8u, 0x16215910u,0xCC0F0785u,0x68CC3BCFu,0xDEB2B9C7u,0x6B633805u,0x780E1005u, 0x09E49837u,0x39E80ADBu,0x012CEA31u,0x3478872Cu,0x413C1D1Eu,0x233D57C2u, 0x4DED8698u,0x2812F838u,0xF3A213C0u,0xDB90565Cu,0x7B5BCA04u,0x085A189Du, 0xD3B15A8Au,0xCE88155Au,0xC6583EF3u,0x68BAE790u,0x2B1EB054u,0x71910CC2u, 0xD0D88984u,0x210634A7u,0x6A8140B0u,0xD61986A7u,0x777843EAu,0x6D565FEFu, 0x243864EEu,0xA5EB42F5u,0xF06EFA92u,0x37214225u,0x7FD632D3u,0x5270689Bu, 0x17D003A4u,0xBFA3F882u,0x3ABF601Fu,0x9462B2F6u,0x95506548u,0xDFE5AA96u, 0x6014EF4Cu,0x95AA0C22u,0x5AA2452Du,0x537E00C9u,0xF1DA7E65u,0xB35E0497u, 0xC000C9C9u,0xC9041E45u,0x43327CAEu,0x5E1EC5E3u,0x34618D4Bu,0x19EAD6D5u, 0x2EFD99E6u,0x670EBE60u,0x9308BC47u,0x8C167E0Fu,0xE79510C8u,0x7B6872B5u, 0x3E26A6CFu,0x15C2DC3Bu,0x2D58DB58u,0xF146A05Au,0x6FED31D9u,0xB72E86A4u, 0x4C41B38Bu,0xDBD4DBFAu,0x1EC10AD0u,0x4E58E234u,0xAB4167FCu,0x6B7E733Au, 0x097C2AC0u,0x8B071EBAu,0x776CFD58u,0x6C9B3130u,0x775F8863u,0x30ACC2D6u, 0xF2E16ED1u,0x7E7B4DDBu,0xE3BE881Fu,0xD50608E1u,0x5BEEA67Cu,0x2A6FDB10u, 0x532ACD1Bu,0xEF979FD2u,0xA7076C1Eu,0xE5ED7E0Bu,0xE0C08618u,0x0A419EE5u, 0xE8A39152u,0xF8049773u,0x60E262CDu,0xB64DCB36u,0x5BC10B4Fu,0x79ED7826u, 0xBDB0D600u,0xA73B4945u,0x15D99DF1u,0x2EB2322Fu,0x905CB323u,0x8E9D7BBAu, 0xF589DA5Cu,0x3239EC36u,0xBD1A727Cu,0x9A2B964Eu,0x2738E521u,0x3D32ADFEu, 0x7CCB6CC0u,0x9408173Fu,0x314D2743u,0xE07F1718u,0x07A67FCAu,0x9A96EA79u, 0x2C83A39Cu,0x553EFFB3u,0xC45666F4u,0xE870F6FBu,0x60578B32u,0x773C8652u, 0x05210BC4u,0xF8D963F3u,0xD93511B5u,0xF1719F52u,0x2B20CE90u,0x9995F672u, 0x6C198588u,0x38759A4Du,0xDFBB53D5u,0xD7685FBCu,0x77513427u,0x6180D195u, 0xAEC6B98Eu,0x92BD89BEu,0x9225B0FDu,0x5739B0FAu,0xA9033F59u,0x141F2599u, 0xC36254D4u,0x604A7F95u,0x9E6C065Du,0x31FBCC0Fu,0x5B9ADD8Cu,0xDFFA3B0Au, 0x0DFBFC78u,0xF9CA5EBAu,0x2ADB0F37u,0xDDCCB685u,0x8A5B515Eu,0x41C144ADu, 0x34657B2Cu,0x0D450F6Au,0x826FAC71u,0x9EC05C75u,0x74DDC8D9u,0x64C7389Bu, 0x09331092u,0x3EFEA384u,0x704FB6F1u,0x6B4FEF67u,0xCE61D945u,0x9EE52925u, 0xE5A82DC9u,0x0B78A412u,0xDFCBC5A9u,0x30DEC518u,0x1F783F75u,0x4E77188Eu, 0x40A76D52u,0x38B18960u,0x09891862u,0x459A5AA7u,0x42001B9Au,0x0831CA1Eu, 0xF49286E0u,0x877982DCu,0x3B5CC623u,0x807D7FFFu,0x55540A37u,0x6227F496u, 0x8A2A89B3u,0x795F2B97u,0xF63D1ECBu,0x1124A560u,0x4580D76Fu,0xD6D5BC5Bu, 0xB116155Cu,0x52AD63D8u,0x9845DC86u,0x6689C793u,0x7EE16506u,0xDC0190E2u, 0xC37420F7u,0xE598CC3Au,0x8DC81014u,0xB6812BB9u,0xE9F50AF2u,0x0F41261Fu, 0x0466D7E3u,0xDD946A80u,0x4E326865u,0x6E005C19u,0x4146B339u,0xC60EDF2Bu, 0xE0307009u,0x0E646DF4u,0x2654FA27u,0xF81D24FEu,0xC44C94DCu,0x339B61D1u, 0x7D771304u,0x61FF6433u,0x7CDCFC56u,0x76702E78u,0x4E461F5Cu,0x4F5E4893u, 0x41521503u,0x7D997DEDu,0x2F39368Cu,0xC2A0ABE2u,0xD8ABC763u,0x0B196104u, 0x209549ACu,0x34D15315u,0x0357D995u,0x40138F8Fu,0xDC525599u,0xF629FB1Bu, 0x6A62B298u,0x3C1A805Au,0xEE1674DAu,0xBA19460Du,0x3C72676Bu,0xC34DD53Eu, 0x8DD03D72u,0xADAA7B0Du,0xFA0949AEu,0x98DD7A1Du,0x3A545F3Du,0xF4AB0851u, 0xAA1C51A5u,0xC4FEEB56u,0x7E15A604u,0x61459EDFu,0xA64B7A31u,0xDC4DBA74u, 0x57277D9Du,0x0D694801u,0xBB4B34DAu,0xECBF05E2u,0x5C192BF8u,0xDF88AED8u, 0x10D59F2Eu,0x1F4CD1FFu,0x13C17092u,0x34E8D820u,0x8D0F4AE6u,0xC22A9F84u, 0x4F757B90u,0xF647C64Bu,0xB8D5F5EFu,0x4EF2ED32u,0x08CFE621u,0x6282A765u, 0xBB3B1A28u,0x7A00FEDEu,0x7EE74E77u,0x0E72CEC6u,0x7096E317u,0xC53A15F1u, 0xA36CBB05u,0x752139ABu,0x2B28AD4Cu,0x1AA3F3FEu,0xA67D4188u,0x9CB3B791u, 0x5130A6B6u,0xF38FF94Fu,0x4B18839Du,0x92741FE8u,0xA53A3E3Bu,0x5AA03303u, 0x88E42368u,0x7A62DB87u,0xCB918AECu,0x3FE0BBBCu,0x5ED7B7A7u,0x56148AA8u, 0x5B33902Fu,0x8EF7172Cu,0x5D756F5Fu,0x67D49CA2u,0xE5F2F3CAu,0x45B9AA3Fu, 0x35B6D0AAu,0xB086D241u,0xF561EC77u,0x817289AEu,0x4ABC59C3u,0x7171D0E6u, 0xAD03F121u,0x4FB6B316u,0x2F94FD3Bu,0xAB9B2D42u,0x9C39B806u,0x139BDA75u, 0xBCFDFFA0u,0xDE2D7D42u,0xC314E010u,0x91F7D7A9u,0x961D52D0u,0x4EEBB554u, 0x8E833C6Eu,0xEC7FD2C9u,0xACD9AE8Eu,0xD31873FFu,0x7E1551F6u,0x809C8D31u, 0x8873E4B5u,0x3221744Au,0xEB3B4FBDu,0xB17E5F84u,0xEFD0E469u,0xD08C2EC3u }; #endif // SCID_HASH_H ////////////////////////////////////////////////////////////////////// // EOF: hash.h ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/position.h0000755000076500000240000003076314666426276017735 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: position.h // Position class // // Part of: Scid (Shane's Chess Information Database) // Version: 3.5 // // Notice: Copyright (c) 1999-2003 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// #ifndef SCID_POSITION_H #define SCID_POSITION_H #include "common.h" #include "movelist.h" #include class DString; class SquareSet; class SquareList; ////////////////////////////////////////////////////////////////////// // Position: Constants const byte WQ_CASTLE = 1, WK_CASTLE = 2, BQ_CASTLE = 4, BK_CASTLE = 8; // SANFlag: since checking if a move is check (to add the "+" to its // SAN string) takes time, and checking for mate takes even // longer, we specify whether we want this done with a flag. typedef byte sanFlagT; const sanFlagT SAN_NO_CHECKTEST = 0, SAN_CHECKTEST = 1, SAN_MATETEST = 2; // Flags that Position::PrintFEN() recognises: // const uint FEN_COMPACT = 0, FEN_BOARD = 1, FEN_CASTLING_EP = 2, FEN_ALL_FIELDS = 3; // Flags that Position::GenerateMoves() recognises: // typedef uint genMovesT; const genMovesT GEN_CAPTURES = 1, GEN_NON_CAPS = 2, GEN_ALL_MOVES = (GEN_CAPTURES | GEN_NON_CAPS); // SANList: list of legal move strings in SAN. // struct sanListT { bool current; ushort num; sanStringT list [MAX_LEGAL_MOVES]; }; /////////////////////////////////////////////////////////////////////////// // Position: Class definition class Position { private: //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position: Data structures pieceT Board[66]; // the actual board + a color square // and a NULL square. uint Count[2]; // count of pieces & pawns each byte Material[16]; // count of each type of piece byte ListPos[64]; // ListPos stores the position in // List[][] for the piece on // square x. squareT List[2][16]; // list of piece squares for each side byte NumOnRank[16][8]; byte NumOnFyle[16][8]; byte NumOnLeftDiag[16][16]; // Num Queens/Bishops byte NumOnRightDiag[16][16]; byte NumOnSquareColor[16][2]; directionT Pinned[16]; // For each List[ToMove][x], stores // whether piece is pinned to its // own king and dir from king. squareT EPTarget; // square pawns can EP capture to colorT ToMove; ushort HalfMoveClock; // Count of halfmoves since last capture // or pawn move. ushort PlyCounter; byte Castling; // castling flags uint Hash; // Hash value. uint PawnHash; // Pawn structure hash value. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position: Private Functions inline void AddHash (pieceT p, squareT sq); inline void UnHash (pieceT p, squareT sq); inline void AddToBoard (pieceT p, squareT sq); inline void RemoveFromBoard (pieceT p, squareT sq); void CalcPinsDir (directionT dir, pieceT attacker); void GenSliderMoves (MoveList * mlist, colorT c, squareT sq, directionT dir, SquareSet * sqset, bool capturesOnly); void GenKnightMoves (MoveList * mlist, colorT c, squareT sq, SquareSet * sqset, bool capturesOnly); void AddLegalMove (MoveList * mlist, squareT from, squareT to, pieceT promo); void GenCastling (MoveList * mlist); squareT castlingKingSq(colorT color) const; template squareT castlingRookSq(colorT color) const; void GenKingMoves (MoveList * mlist, genMovesT genType, bool castling); void AddPromotions (MoveList * mlist, squareT from, squareT dest); bool IsValidEnPassant (squareT from, squareT to); void GenPawnMoves (MoveList * mlist, squareT from, directionT dir, SquareSet * sqset, genMovesT genType); void GenCheckEvasions(MoveList* mlist, pieceT mask, genMovesT genType, SquareList* checkSquares); errorT MatchPawnMove(MoveList* mlist, fyleT fromFyle, squareT to, pieceT promote); errorT ReadMove(simpleMoveT* sm, const char* str, int slen, pieceT p); errorT ReadMoveCastle(simpleMoveT* sm, const char* str, int slen); errorT ReadMovePawn(simpleMoveT* sm, const char* str, int slen, fyleT from); errorT ReadMoveKing(simpleMoveT* sm, const char* str, int slen); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position: Public Functions public: Position(); static const Position& getStdStart(); void Clear(); // No pieces on board void StdStart() { *this = getStdStart(); } bool IsStdStart() const; errorT AddPiece (pieceT p, squareT sq); // Set and Get attributes -- one-liners byte PieceCount (pieceT p) { return Material[p]; } const byte* GetMaterial() const { return Material; } void SetEPTarget (squareT s) { EPTarget = s; } squareT GetEPTarget () const { return EPTarget; } void SetToMove (colorT c) { ToMove = c; } colorT GetToMove () const { return ToMove; } void SetPlyCounter (ushort x) { PlyCounter = x; } ushort GetPlyCounter () const { return PlyCounter; } ushort GetFullMoveCount() const { return PlyCounter / 2 + 1; } // Methods to get the Board or piece lists -- used in game.cpp to // decode moves: const squareT* GetList(colorT c) const { return List[c]; } squareT * GetList (colorT c) { return List[c]; } uint GetCount (colorT c) const { return Count[c]; } uint TotalMaterial () { return Count[WHITE] + Count[BLACK]; } uint NumNonPawns (colorT c) { return Count[c] - Material[piece_Make(c,PAWN)]; } bool InPawnEnding () { return (NumNonPawns(WHITE) == 1 && NumNonPawns(BLACK) == 1); } uint MaterialValue (colorT c); inline uint FyleCount (pieceT p, fyleT f) const { return NumOnFyle[p][f]; } inline uint RankCount (pieceT p, rankT r) const { return NumOnRank[p][r]; } inline uint LeftDiagCount (pieceT p, leftDiagT diag) const { return NumOnLeftDiag[p][diag]; } inline uint RightDiagCount (pieceT p, rightDiagT diag) const { return NumOnRightDiag[p][diag]; } inline uint SquareColorCount (pieceT p, colorT sqColor) const { return NumOnSquareColor[p][sqColor]; } const pieceT* GetBoard() const { const_cast(this)->Board[COLOR_SQUARE] = COLOR_CHAR[ToMove]; return Board; } pieceT GetPiece(squareT sq) const { ASSERT(sq < 64); return Board[sq]; } // Other one-line methods squareT GetKingSquare (colorT c) const { return List[c][0]; } squareT GetKingSquare () const { return List[ToMove][0]; } squareT GetEnemyKingSquare () const { return List[1-ToMove][0]; } // Castling flags inline void SetCastling (colorT c, castleDirT dir, bool flag); void ClearCastlingFlags(colorT c) { Castling &= (c == WHITE) ? 0b11111100 : 0b11110011; } bool GetCastling(colorT c, castleDirT dir) const { int b = (c == WHITE) ? 1 : 4; if (dir == KSIDE) b += b; // Now b == 1 or 2 (white flags), or 4 or 8 (black flags) return Castling & b; } byte GetCastlingFlags () { return Castling; } // Hashing inline uint HashValue (void) { return Hash; } inline uint PawnHashValue (void) { return PawnHash; } uint GetHPSig (); // Move generation and execution void CalcPins(); void GenPieceMoves (MoveList * mlist, squareT sq, SquareSet * sqset, bool capturesOnly); // Generate all legal moves: void GenerateMoves (MoveList* mlist, pieceT mask, genMovesT genType, bool maybeInCheck); void GenerateMoves (MoveList * mlist) { GenerateMoves (mlist, EMPTY, GEN_ALL_MOVES, true); } void GenerateMoves (MoveList * mlist, genMovesT genType) { GenerateMoves (mlist, EMPTY, genType, true); } void GenerateCaptures (MoveList * mlist) { GenerateMoves (mlist, EMPTY, GEN_CAPTURES, true); } bool IsLegalMove (simpleMoveT * sm); /// Check that the minimum requirements for castling are satisfied: /// - both the king and the rook exists in the position /// - the final squares of the king and the rook are empty /// @param check_legal: also test for checks or blocking pieces. /// Ignore the castling flags and if the king is already in check. bool validCastling(bool king_side, bool check_legal) const; uint CalcAttacks (colorT toMove, squareT kingSq, SquareList * squares) const; int TreeCalcAttacks (colorT toMove, squareT target); uint CalcNumChecks () const { return CalcAttacks (1-ToMove, GetKingSquare(), NULL); } uint CalcNumChecks (squareT kingSq) const { return CalcAttacks (1-ToMove, kingSq, NULL); } uint CalcNumChecks (squareT kingSq, SquareList * checkSquares) const { return CalcAttacks (1-ToMove, kingSq, checkSquares); } uint Mobility (pieceT p, colorT color, squareT from); bool IsKingInCheck () { return (CalcNumChecks() > 0); } bool IsKingInCheckDir (directionT dir); bool IsKingInCheck (simpleMoveT * sm); bool IsKingInMate (); bool IsLegal (); bool IsPromoMove (squareT from, squareT to); // TODO: replace with DoSimpleMove(const simpleMoveT&) void DoSimpleMove(simpleMoveT sm) { return DoSimpleMove(&sm); } void DoSimpleMove (simpleMoveT * sm); // move execution ... void UndoSimpleMove (simpleMoveT const* sm); // ... and taking back errorT RelocatePiece (squareT fromSq, squareT toSq); void MakeSANString (simpleMoveT * sm, char * s, sanFlagT flag); void CalcSANStrings (sanListT *sanList, sanFlagT flag); errorT ReadCoordMove(simpleMoveT* m, const char* s, int slen, bool reverse); errorT ParseMove(simpleMoveT* sm, const char* str); errorT ParseMove(simpleMoveT* sm, const char* begin, const char* end); // Board I/O void MakeLongStr (char * str); errorT ReadFromLongStr (const char * str); errorT ReadFromCompactStr (const byte * str); errorT ReadFromFEN (const char * s); void PrintCompactStr (char * cboard); void PrintCompactStrFlipped (char * cboard); byte CompactStrFirstByte () { return (Board[0] << 4) | Board[1]; } void PrintFEN(char* str, uint flags) const; void DumpLatexBoard (DString * dstr, bool flip); void DumpLatexBoard (DString * dstr) { DumpLatexBoard (dstr, false); } void DumpHtmlBoard (DString * dstr, uint style, const char * dir, bool flip); void DumpHtmlBoard (DString * dstr, uint style, const char * dir) { DumpHtmlBoard (dstr, style, dir, false); } // Copy, compare positions int Compare (Position * p); void CopyFrom (Position * src) { *this = *src; } // Set up a random position: errorT Random (const char * material); }; ////////////////////////////////////////////////////////////////////// // Position: Public Inline Functions //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::SetCastling(): // Set a castling flag. // inline void Position::SetCastling (colorT c, castleDirT dir, bool flag) { byte b = (c==WHITE ? 1 : 4); if (dir == KSIDE) b += b; // Now b = 1 or 2 (white flags), or 4 or 8 (black flags) if (flag) { Castling |= b; } else { Castling &= (255-b); } return; } #endif // SCID_POSITION_H ////////////////////////////////////////////////////////////////////// // EOF: position.h ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/movelist.h0000755000076500000240000000735714666426276017736 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: movelist.h // MoveList class // // Part of: Scid (Shane's Chess Information Database) // Version: 3.4 // // Notice: Copyright (c) 1999-2002 Shane Hudson. All rights reserved. // Copyright (c) 2016 Fulvio Benini. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// #ifndef SCID_MOVELIST_H #define SCID_MOVELIST_H #include "common.h" ////////////////////////////////////////////////////////////////////// // MoveList: Constants const uint MAX_LEGAL_MOVES = 256; // max. length of the moves list /////////////////////////////////////////////////////////////////////////// // MoveList: Data Structures // *** SimpleMove: less expensive to store than a full move as defined // in game.h, but still fully undoable. // struct simpleMoveT { squareT from; squareT to; pieceT promote; // EMPTY if not a promotion, type (no color) otherwise pieceT movingPiece; byte pieceNum; byte capturedNum; pieceT capturedPiece; squareT capturedSquare; // ONLY different to "to" field if this capture // is an en passant capture. byte castleFlags; // pre-move information squareT epSquare; // pre-move information ushort oldHalfMoveClock; int32_t score; // used for alpha/beta ordering. bool isNullMove() const { return from == to && from != NULL_SQUARE && piece_Type(movingPiece) == KING; } int isCastle() const { ASSERT(piece_Type(movingPiece) == KING); if (square_Fyle(from) == E_FYLE) { squareT toFyle = square_Fyle(to); if (toFyle == G_FYLE) return 1; if (toFyle == C_FYLE) return 2; } return 0; } /// Converts the move to long algebraic notation. /// @return a pointer one past the last char written. template OutputIt toLongNotation(OutputIt dest) const { if (from == to) { // UCI standard for null move *dest++ = '0'; *dest++ = '0'; *dest++ = '0'; *dest++ = '0'; } else { *dest++ = square_FyleChar(from); *dest++ = square_RankChar(from); *dest++ = square_FyleChar(to); *dest++ = square_RankChar(to); if (promote != EMPTY) { constexpr const char promoChars[] = " qrbn "; *dest++ = promoChars[piece_Type(promote)]; } } return dest; } bool operator<(const simpleMoveT& b) const { // Highest score first return score > b.score; } }; struct cmpMove { const simpleMoveT& m; explicit cmpMove(const simpleMoveT& sm) : m(sm) {} }; inline bool operator==(const simpleMoveT& a, const cmpMove& b) { return a.from == b.m.from && a.to == b.m.to && a.promote == b.m.promote; } // typedef std::vector MoveList; class MoveList { uint ListSize = 0; simpleMoveT Moves[MAX_LEGAL_MOVES]; public: typedef simpleMoveT* iterator; iterator begin() { return Moves; }; iterator end() { return Moves + ListSize; } uint Size() { return ListSize; } void Clear() { ListSize = 0; } void emplace_back(squareT from, squareT to, pieceT promote, pieceT movingPiece, pieceT capturedPiece) { ASSERT(ListSize < MAX_LEGAL_MOVES); simpleMoveT& sm = Moves[ListSize++]; sm.from = from; sm.to = to; sm.promote = promote; sm.movingPiece = movingPiece; sm.capturedPiece = capturedPiece; } void resize(size_t count) { ASSERT(count <= MAX_LEGAL_MOVES); ListSize = static_cast(count); } void push_back(const simpleMoveT& sm) { ASSERT(ListSize < MAX_LEGAL_MOVES); Moves[ListSize++] = sm; } simpleMoveT* Get(size_t index) { ASSERT(index < ListSize); return &(Moves[index]); } }; #endif // SCID_MOVELIST_H chessx-master/dep/scid/code/src/game.cpp0000755000076500000240000031571014666426276017333 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: game.cpp // Game class methods // // Part of: Scid (Shane's Chess Information Database) // Version: 3.5 // // Notice: Copyright (c) 2000-2003 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// #include "game.h" #include "bytebuf.h" #include "common.h" #include "dstring.h" #include "naglatex.h" #include "nagtext.h" #include "position.h" #include "stored.h" #include "textbuf.h" #include #include // Piece letters translation int language = 0; // default to english // 0 = en, // 1 = fr, 2 = es, 3 = de, 4 = it, 5 = ne, 6 = cz // 7 = hu, 8 = no, 9 = sw, 10 = ca, 11 = fi, 12 = gr // TODO Piece translations for greek const char * langPieces[] = { "", "PPKRQDRTBFNC", "PPKRQDRTBANC", "PBKKQDRTBLNS", "PPKRQDRTBANC", "PpKKQDRTBLNP", "PPKKQDRVBSNJ", "PGKKQVRBBFNH", "PBKKQDRTBLNS", "PBKKQDRTBLNS", "PPKRQDRTBANC", "PSKKQDRTBLNR", "" }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // transPieces(): // Given a string, will translate pieces from english to another language void transPieces(char *s) { if (language == 0) return; char * ptr = s; int i; while (*ptr) { if (*ptr >= 'A' && *ptr <= 'Z') { for (i=0; i<12; i+=2) { if (*ptr == langPieces[language][i]) { *ptr = langPieces[language][i+1]; break; } } } ptr++; } } char transPiecesChar(char c) { char ret = c; if (language == 0) return c; for (int i=0; i<12; i+=2) { if (c == langPieces[language][i]) { ret = langPieces[language][i+1]; break; } } return ret; } const char * ratingTypeNames [17] = { "Elo", "Rating", "Rapid", "ICCF", "USCF", "DWZ", "ECF", // Reserved for future use: NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // End of array marker: NULL }; uint strGetRatingType (const char * name) { uint i = 0; while (ratingTypeNames[i] != NULL) { if (strEqual (name, ratingTypeNames[i])) { return i; } i++; } return 0; } typedef Game * GamePtr; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // printNag(): converts a numeric NAG to its string equivalent. // The parameter should point to a string at least 10 bytes long. // TODO // replace < and > in NAG codes by and void game_printNag (byte nag, char * str, bool asSymbol, gameFormatT format) { ASSERT (str != NULL); if (nag == 0) { *str = 0; return; } if (nag >= (sizeof evalNagsRegular / sizeof (const char *))) { if (format == PGN_FORMAT_LaTeX) *str = 0; else sprintf (str, "$%u", nag); return; } if (asSymbol) { if (format == PGN_FORMAT_LaTeX) { strcpy (str, evalNagsLatex[nag]); } else { strcpy (str, evalNagsRegular[nag]); } if (nag == NAG_Diagram) { if (format == PGN_FORMAT_LaTeX) { strcpy (str, evalNagsLatex[nag]); } else if (format == PGN_FORMAT_HTML) { strcpy(str, "(D)"); } else { str[0] = 'D'; str[1] = 0; } } return; } else { sprintf (str, "%s$%d", format == PGN_FORMAT_LaTeX ? "\\" : "", nag); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // game_parseNag(): // Parses an annotation symbol into its numeric equivalent. // Accepts numeric format ($51) or symbols such as // !, ?, +=, -/+, N, etc. // byte game_parseNag(std::pair strview) { auto slen = std::distance(strview.first, strview.second); if (slen == 0 || slen > 7) return 0; char strbuf[8] = {0}; std::copy_n(strview.first, slen, strbuf); const char* str = strbuf; if (*str == '$') { str++; return (byte) strGetUnsigned(str); } if ((*str <= '9' && *str >= '0')) { return (byte) strGetUnsigned(str); } if (*str == '!') { // Must be "!", "!!", "!?", or invalid: str++; if (*str == 0) { return NAG_GoodMove; } // ! $1 if (*str == '!') { return NAG_ExcellentMove; } // !! $3 if (*str == '?') { return NAG_InterestingMove; } // !? $5 return 0; } if (*str == '?') { // Must be "?", "??", "?!", or invalid: str++; if (*str == 0) { return NAG_PoorMove; } // ? $2 if (*str == '?') { return NAG_Blunder; } // ?? $4 if (*str == '!') { return NAG_DubiousMove; } // ?! $6 return 0; } if (*str == '+') { // Must be "+=", "+/=", "+/-", "+-", "+--", "+>" or invalid: str++; if (*str == '=') { return NAG_WhiteSlight; } // += $14 if (*str == '-' && str[1] == 0) { // +- $18 return NAG_WhiteDecisive; } if (*str == '>') { return NAG_WithAttack; } // +> $40 if (*str == '/' && str[1] == '-') { // +/- $16 return NAG_WhiteClear; } if (*str == '/' && str[1] == '=') { // +/= $14 return NAG_WhiteSlight; } if (*str == '-' && str[1] == '-') { // +-- $20 return NAG_WhiteCrushing; } return 0; } if (*str == '=') { // Must be "=" (equal), "=+", "=/+", "=/&" or invalid: str++; if (*str == 0) { return NAG_Equal; } // = $10 if (*str == '+') { return NAG_BlackSlight; } // =+ $15 if (*str == '/' && str[1] == '+') { // =/+ $15 return NAG_BlackSlight; } if (*str == '/' && str[1] == '&') { // =/& $44 return NAG_Compensation; } return 0; } if (*str == '-') { // Must be "-+", "-/+" or "--+", "->": str++; if (*str == '+') { return NAG_BlackDecisive; } // -+ $19 if (*str == '>') { return NAG_WithBlackAttack; } // -> $41 if (*str == '/' && str[1] == '+') { // -/+ $17 return NAG_BlackClear; } if (*str == '-' && str[1] == '+') { // --+ $21 return NAG_BlackCrushing; } if (*str == '-' && str[1] == 0) { // -- $210 return NAG_See; } return 0; } if (*str == '/') { // Must be "/\" or "/" str++; if (*str == 0) { return NAG_Diagonal; } // / $150 if (*str == '\\') { return NAG_WithIdea; } // Tri $140 return 0; } if (*str == 'R') { // Must be "R", "RR" str++; if (*str == 0) { return NAG_VariousMoves; } // R $144 if (*str == 'R') { return NAG_Comment; } // RR $145 return 0; } if (*str == 'z') { // Must be "zz" str++; if (*str == 'z') { return NAG_BlackZugZwang; } // zz $23 return 0; } if (*str == 'Z') { // Must be "ZZ" str++; if (*str == 'Z') { return NAG_ZugZwang; } // ZZ $22 return 0; } if (*str == 'B') { // Must be "BB", "Bb" str++; if (*str == 'B') { return NAG_BishopPair; } // BB $151 if (*str == 'b') { return NAG_OppositeBishops; } // Bb $153 return 0; } if (*str == 'o') { // Must be "BB", "Bb" str++; if (*str == '-' && str[1] == 'o') { // o-o $192 return NAG_SeparatedPawns; } if (*str == 'o' && str[1] == 0) { // [+] $193 return NAG_UnitedPawns; } if (*str == '^' && str[1] == 0) { // o^ $212 return NAG_PassedPawn; } return 0; } if (*str == '(') { // Must be (_) str++; if (*str == '_' && str[1] == ')') { // (_) $142 return NAG_BetterIs; } return 0; } if (*str == '[') { // Must be (_) str++; if (*str == ']' && str[1] == 0) { // [] $8 return NAG_OnlyMove; } if (*str == '+' && str[1] == ']') { // [+] $48 return NAG_SlightCentre; } if (*str == '+' && str[1] == '+' && str[2] == ']') { // [++] $50 return NAG_Centre; } return 0; } if (*str == '_') { // must be _|_ or _| str++; if (*str == '|' && str[1] == '_') { // _|_ $148 return NAG_Ending; } if (*str == '|' && str[1] == 0) { // _| $215 return NAG_Without; } return 0; } if (*str == '|') { // must be ||, |_ str++; if (*str == '|' ) { return NAG_Etc; } // || $190 if (*str == '_') { return NAG_With; } // |_ $214 return 0; } if (*str == '>') { // must be >, >>, >>> str++; if (*str == 0) { return NAG_SlightKingSide; } // > $54 if (*str == '>' && str[1] == 0) { // >> $56 return NAG_ModerateKingSide; } if (*str == '>' && str[1] == '>') { // >>> $58 return NAG_KingSide; } return 0; } if (*str == '<') { // must be <, <<, <<<, <=> str++; if (*str == 0) { return NAG_SlightQueenSide; } // < $60 if (*str == '<' && str[1] == 0) { // << $62 return NAG_ModerateQueenSide; } if (*str == '<' && // <<< $64 str[1] == '<' && str[2] == 0) { return NAG_QueenSide; } if (*str == '=' && // <=> $149 str[1] == '>' && str[2] == 0) { return NAG_File; } if (*str == '+' && // <+> $130 str[1] == '>' && str[2] == 0) { return NAG_SlightCounterPlay; } if (*str == '-' && // <-> $131 str[1] == '>' && str[2] == 0) { return NAG_BlackSlightCounterPlay; } if (*str == '+' && // <++> $132 str[1] == '+' && str[2] == '>' && str[3] == 0) { return NAG_CounterPlay; } if (*str == '-' && // <--> $133 str[1] == '-' && str[2] == '>' && str[3] == 0) { return NAG_BlackCounterPlay; } if (*str == '+' && // <+++> $134 str[1] == '+' && str[2] == '+' && str[3] == '>') { return NAG_DecisiveCounterPlay; } if (*str == '-' && // <---> $135 str[1] == '-' && str[2] == '-' && str[3] == '>') { return NAG_BlackDecisiveCounterPlay; } return 0; } if (*str == '~' && *(str+1) == '=') { // ~= $44 // alternative Compensation symbol: return NAG_Compensation; } if (*str == '~') { // ~ $13 // Unclear symbol: return NAG_Unclear; } if (*str == 'x') { // x $147 return NAG_WeakPoint; } if (str[0] == 'N' && str[1] == 0) { // N $146 // Novelty symbol: return NAG_Novelty; } if (str[0] == 'D' && str[1] == 0) { // D $201 // Diagram symbol: return NAG_Diagram; } return 0; } errorT Game::AddNag (byte nag) { moveT * m = CurrentMove->prev; if (m->nagCount + 1 >= MAX_NAGS) { return ERROR_GameFull; } if (nag == 0) { /* Nags cannot be zero! */ return OK; } // If it is a move nag replace an existing if( nag >= 1 && nag <= 6) for( int i=0; inagCount; i++) if( m->nags[i] >= 1 && m->nags[i] <= 6) { m->nags[i] = nag; return OK; } // If it is a position nag replace an existing if( nag >= 10 && nag <= 21) for( int i=0; inagCount; i++) if( m->nags[i] >= 10 && m->nags[i] <= 21) { m->nags[i] = nag; return OK; } if( nag >= 1 && nag <= 6) { // Put Move Nags at the beginning for( int i=m->nagCount; i>0; i--) m->nags[i] = m->nags[i-1]; m->nags[0] = nag; } else m->nags[m->nagCount] = nag; m->nagCount += 1; m->nags[m->nagCount] = 0; return OK; } errorT Game::RemoveNag (bool isMoveNag) { moveT * m = CurrentMove->prev; if( isMoveNag) { for( int i=0; inagCount; i++) if( m->nags[i] >= 1 && m->nags[i] <= 6) { m->nagCount -= 1; for( int j=i; jnagCount; j++) m->nags[j] = m->nags[j+1]; m->nags[m->nagCount] = 0; return OK; } } else { for( int i=0; inagCount; i++) if( m->nags[i] >= 10 && m->nags[i] <= 21) { m->nagCount -= 1; for( int j=i; jnagCount; j++) m->nags[j] = m->nags[j+1]; m->nags[m->nagCount] = 0; return OK; } } return OK; } ////////////////////////////////////////////////////////////////////// // PUBLIC FUNCTIONS ////////////////////////////////////////////////////////////////////// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Move allocation: // moves are allocated in chunks to save memory and for faster // performance. // constexpr int MOVE_CHUNKSIZE = 128; moveT* Game::allocMove() { if (moveChunkUsed_ == MOVE_CHUNKSIZE) { moveChunks_.emplace_front(new moveT[MOVE_CHUNKSIZE]); moveChunkUsed_ = 0; } return moveChunks_.front().get() + moveChunkUsed_++; } moveT* Game::NewMove(markerT marker) { moveT* res = allocMove(); res->clear(); res->marker = marker; return res; } Game::Game(const Game& obj) { extraTags_ = obj.extraTags_; WhiteStr = obj.WhiteStr; BlackStr = obj.BlackStr; EventStr = obj.EventStr; SiteStr = obj.SiteStr; RoundStr = obj.RoundStr; Date = obj.Date; EventDate = obj.EventDate; EcoCode = obj.EcoCode; WhiteElo = obj.WhiteElo; BlackElo = obj.BlackElo; WhiteRatingType = obj.WhiteRatingType; BlackRatingType = obj.BlackRatingType; Result = obj.Result; std::copy_n(obj.ScidFlags, sizeof(obj.ScidFlags), ScidFlags); if (obj.StartPos) StartPos = std::make_unique(*obj.StartPos); NumHalfMoves = obj.NumHalfMoves; WhiteEstimateElo = obj.WhiteEstimateElo; BlackEstimateElo = obj.BlackEstimateElo; NumMovesPrinted = obj.NumMovesPrinted; PgnStyle = obj.PgnStyle; PgnFormat = obj.PgnFormat; HtmlStyle = obj.HtmlStyle; moveChunkUsed_ = MOVE_CHUNKSIZE; FirstMove = obj.FirstMove->cloneLine(nullptr, [this]() { return allocMove(); }); MoveToLocationInPGN(obj.GetLocationInPGN()); } Game* Game::clone() { return new Game(*this); } void Game::strip(bool variations, bool comments, bool NAGs) { while (variations && MoveExitVariation() == OK) { // Go to main line } for (auto& chunk : moveChunks_) { moveT* move = chunk.get(); moveT* end = (chunk == moveChunks_.front()) ? move + moveChunkUsed_ : move + MOVE_CHUNKSIZE; for (; move != end; ++move) { if (variations) { move->numVariations = 0; move->varChild = nullptr; } if (comments) move->comment.clear(); if (NAGs) { move->nagCount = 0; std::fill_n(move->nags, sizeof(move->nags), 0); } } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::ClearMoves(): clear all moves. void Game::ClearMoves() { // Delete any chunks of moves except the first: if (moveChunks_.empty()) { moveChunkUsed_ = MOVE_CHUNKSIZE; } else { moveChunks_.erase_after(moveChunks_.begin(), moveChunks_.end()); moveChunkUsed_ = 0; } StartPos = nullptr; CurrentPos->StdStart(); // Initialize FirstMove: start and end of movelist markers FirstMove = NewMove(START_MARKER); CurrentMove = NewMove(END_MARKER); FirstMove->setNext(CurrentMove); VarDepth = 0; NumHalfMoves = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::Clear(): // Reset the game to its normal empty state. // void Game::Clear() { extraTags_.clear(); WhiteStr.clear(); BlackStr.clear(); EventStr.clear(); SiteStr.clear(); RoundStr.clear(); Date = ZERO_DATE; EventDate = ZERO_DATE; EcoCode = 0; WhiteElo = BlackElo = 0; WhiteEstimateElo = BlackEstimateElo = 0; WhiteRatingType = BlackRatingType = RATING_Elo; Result = RESULT_None; ScidFlags[0] = 0; NumMovesPrinted = 0; PgnStyle = PGN_STYLE_TAGS | PGN_STYLE_VARS | PGN_STYLE_COMMENTS; PgnFormat = PGN_FORMAT_Plain; HtmlStyle = 0; ClearMoves(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::PgnFormatFromString(): // Converts a string to a gameFormatT, returning true on success // or false on error. // The string should be a case-insensitive unique prefix of // "plain" (or "pgn"), "HTML", "LaTeX" or "Color". bool Game::PgnFormatFromString (const char * str, gameFormatT * fmt) { if (strIsCasePrefix (str, "Plain")) { *fmt = PGN_FORMAT_Plain; } else if (strIsCasePrefix (str, "PGN")) { *fmt = PGN_FORMAT_Plain; } else if (strIsCasePrefix (str, "HTML")) { *fmt = PGN_FORMAT_HTML; } else if (strIsCasePrefix (str, "LaTeX")) { *fmt = PGN_FORMAT_LaTeX; } else if (strIsCasePrefix (str, "Color")) { *fmt = PGN_FORMAT_Color; } else { return false; } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::SetPgnFormatFromString(): // Sets the PgnFormat from the provided string. // Returns true if the PgnFormat was successfully set. bool Game::SetPgnFormatFromString (const char * str) { return PgnFormatFromString (str, &PgnFormat); } errorT Game::SetStartFen (const char * fenStr) { auto pos = std::make_unique(); errorT err = pos->ReadFromFEN (fenStr); if (err != OK) return err; ClearMoves(); StartPos = std::move(pos); *CurrentPos = *StartPos; return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::AddPgnTag(): Add a PGN Tag. // void Game::AddPgnTag(const char* tag, const char* value) { // First, try to replace an existing tag: for (auto& e : extraTags_) { if (e.first == tag) { e.second.assign(value); return; } } extraTags_.emplace_back(tag, value); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::FindExtraTag(): // Finds and returns an extra PGN tag if it // exists, or NULL if it does not exist. const char* Game::FindExtraTag(const char* tag) const { for (auto& e : extraTags_) { if (e.first == tag) return e.second.c_str(); } return NULL; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::RemoveExtraTag(): // Remove an extra PGN tag if it exists. bool Game::RemoveExtraTag(const char* tag) { auto it = std::remove_if(extraTags_.begin(), extraTags_.end(), [&](const std::pair& e) { return e.first == tag; }); if (it != extraTags_.end()) { extraTags_.erase(it, extraTags_.end()); return true; } return false; } std::string& Game::accessTagValue(const char* tag, size_t tagLen) { if (tagLen == 5) { if (std::equal(tag, tag + 5, "Event")) return EventStr; if (std::equal(tag, tag + 5, "Round")) return RoundStr; if (std::equal(tag, tag + 5, "White")) return WhiteStr; if (std::equal(tag, tag + 5, "Black")) return BlackStr; } else if (tagLen == 4) { if (std::equal(tag, tag + 4, "Site")) return SiteStr; } for (auto& elem : extraTags_) { if (std::equal(tag, tag + tagLen, elem.first.begin(), elem.first.end())) return elem.second; } extraTags_.emplace_back(); extraTags_.back().first.assign(tag, tagLen); return extraTags_.back().second; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::SetMoveComment(): // Sets the comment for a move. A comment before the game itself // is stored as a comment of FirstMove. // void Game::SetMoveComment (const char * comment) { ASSERT (CurrentMove != NULL && CurrentMove->prev != NULL); moveT * m = CurrentMove->prev; if (comment == NULL) { m->comment.clear(); } else { m->comment = comment; // CommentsFlag = 1; } } int Game::setRating(colorT col, const char* ratingType, size_t ratingTypeLen, std::pair rating) { auto begin = ratingTypeNames; const size_t ratingSz = 7; auto it = std::find_if(begin, begin + ratingSz, [&](auto rType) { return std::equal(ratingType, ratingType + ratingTypeLen, rType, rType + std::strlen(rType)); }); byte rType = static_cast(std::distance(begin, it)); if (rType >= ratingSz) return -1; int res = 1; auto elo = strGetUnsigned(std::string{rating.first, rating.second}.c_str()); if (elo > MAX_ELO) { elo = 0; res = 0; } if (col == WHITE) { SetWhiteElo(static_cast(elo)); SetWhiteRatingType(rType); } else { SetBlackElo(static_cast(elo)); SetBlackRatingType(rType); } return res; } /////////////////////////////////////////////////////////////////////////// // A "location" in the game is represented by a position (Game::CurrentPos), the // next move to be played (Game::CurrentMove) and the number of parent variations // (Game::VarDepth). Since CurrentMove is the next move to be played, some // invariants must hold: it is never nullptr and it never points to a // START_MARKER (it will point to a END_MARKER if there are no more moves). This // also means that CurrentMove->prev is always valid: it will point to a // previous move or to a START_MARKER. // The following functions modify ONLY the current location of the game. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Move current position forward one move. // Also update all the necessary fields in the simpleMove structure // (CurrentMove->moveData) so it can be undone. // errorT Game::MoveForward(void) { if (CurrentMove->endMarker()) return ERROR_EndOfMoveList; CurrentPos->DoSimpleMove(&CurrentMove->moveData); CurrentMove = CurrentMove->next; // Invariants ASSERT(CurrentMove && CurrentMove->prev); ASSERT(!CurrentMove->startMarker()); return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::MoveBackup(): // Backup one move. // errorT Game::MoveBackup(void) { if (CurrentMove->prev->startMarker()) return ERROR_StartOfMoveList; CurrentMove = CurrentMove->prev; CurrentPos->UndoSimpleMove(&CurrentMove->moveData); // Invariants ASSERT(CurrentMove && CurrentMove->prev); ASSERT(!CurrentMove->startMarker()); return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::MoveIntoVariation(): // Move into a subvariation. Variations are numbered from 0. errorT Game::MoveIntoVariation(uint varNumber) { for (auto subVar = CurrentMove; subVar->varChild; --varNumber) { subVar = subVar->varChild; if (varNumber == 0) { CurrentMove = subVar->next; // skip the START_MARKER ++VarDepth; // Invariants ASSERT(CurrentMove && CurrentMove->prev); ASSERT(!CurrentMove->startMarker()); return OK; } } return ERROR_NoVariation; // there is no such variation } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::MoveExitVariation(): // Move out of a variation, to the parent. // errorT Game::MoveExitVariation(void) { if (VarDepth == 0) // not in a variation! return ERROR_NoVariation; // Algorithm: go back previous moves as far as possible, then // go up to the parent of the variation. while (MoveBackup() == OK) { } CurrentMove = CurrentMove->getParent().first; --VarDepth; // Invariants ASSERT(CurrentMove && CurrentMove->prev); ASSERT(!CurrentMove->startMarker()); return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Move to the beginning of the game. // void Game::MoveToStart() { if (StartPos) { *CurrentPos = *StartPos; } else { CurrentPos->StdStart(); } VarDepth = 0; CurrentMove = FirstMove->next; // Invariants ASSERT(CurrentMove && CurrentMove->prev); ASSERT(!CurrentMove->startMarker()); } void Game::MoveToEnd() { MoveToStart(); while (MoveForward() == OK) { } } errorT Game::MoveForwardInPGN() { if (CurrentMove->prev->varChild && MoveBackup() == OK) return MoveIntoVariation(0); while (MoveForward() != OK) { if (VarDepth == 0) return ERROR_EndOfMoveList; auto varnum = GetVarNumber(); MoveExitVariation(); if (MoveIntoVariation(varnum + 1) == OK) return OK; MoveForward(); } return OK; } errorT Game::MoveToLocationInPGN(unsigned stopLocation) { MoveToStart(); for (unsigned loc = 1; loc < stopLocation; ++loc) { errorT err = MoveForwardInPGN(); if (err != OK) return err; } return OK; } unsigned Game::GetLocationInPGN() const { unsigned res = 1; const moveT* last_move = CurrentMove->prev; const moveT* move = FirstMove; for (; move != last_move; move = move->nextMoveInPGN()) { if (!move->endMarker()) ++res; } return res; } unsigned Game::GetPgnOffset() const { unsigned res = 1; const moveT* last_move = CurrentMove->getPrevMove(); if (last_move) { const moveT* move = FirstMove; for (; move != last_move; move = move->nextMoveInPGN()) { if (!move->endMarker()) ++res; } } return res; } std::string Game::currentPosUCI() const { std::string res = "position startpos moves"; char FEN[256] = {}; std::vector moves; const moveT* move = CurrentMove; while ((move = move->getPrevMove())) { if (move->moveData.isNullMove()) { Position lastValidPos = *currentPos(); for (const moveT* m : moves) { lastValidPos.UndoSimpleMove(&m->moveData); } lastValidPos.PrintFEN(FEN, FEN_ALL_FIELDS); break; } moves.emplace_back(move); } if (*FEN || HasNonStandardStart(FEN)) { res.replace(9, 4, "fen "); res.replace(13, 4, FEN); } const auto allocSpeedup = res.size(); res.resize(allocSpeedup + moves.size() * 6); auto it = res.data() + allocSpeedup; for (auto m = moves.crbegin(), end = moves.crend(); m != end; ++m) { *it++ = ' '; it = (*m)->moveData.toLongNotation(it); } res.resize(std::distance(res.data(), it)); // shrink return res; } /////////////////////////////////////////////////////////////////////////// // The following functions modify the moves graph in order to add or delete // moves. Promoting variations also modifies the moves graph. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::AddMove(): // Add a move at current position and do it. // errorT Game::AddMove(const simpleMoveT* sm) { ASSERT(sm != NULL); // We must be at the end of a game/variation to add a move: if (!CurrentMove->endMarker()) Truncate(); CurrentMove->setNext(NewMove(END_MARKER)); CurrentMove->marker = NO_MARKER; CurrentMove->moveData.from = sm->from; CurrentMove->moveData.to = sm->to; CurrentMove->moveData.promote = sm->promote; CurrentMove->moveData.movingPiece = sm->movingPiece; if (VarDepth == 0) ++NumHalfMoves; return MoveForward(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::AddVariation(): // Add a variation for the current move. // Also moves into the variation. errorT Game::AddVariation() { auto err = MoveBackup(); if (err != OK) return err; auto newVar = NewMove(START_MARKER); newVar->setNext(NewMove(END_MARKER)); CurrentMove->appendChild(newVar); // Move into variation CurrentMove = newVar->next; ++VarDepth; // Invariants ASSERT(CurrentMove && CurrentMove->prev); ASSERT(!CurrentMove->startMarker()); return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::FirstVariation(): // Promotes the current variation to first variation. errorT Game::FirstVariation() { auto parent = CurrentMove->getParent(); auto root = parent.first; if (!root) return ERROR_NoVariation; root->detachChild(parent.second); root->insertChild(parent.second, 0); return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::MainVariation(): // Like FirstVariation, but promotes the variation to the main line, // demoting the main line to be the first variation. errorT Game::MainVariation() { auto parent = CurrentMove->getParent(); auto root = parent.first; if (!root) return ERROR_NoVariation; if (parent.second->next->endMarker()) // Do not promote empty variations return OK; // Make the current variation the first variation root->detachChild(parent.second); root->insertChild(parent.second, 0); // Swap the mainline with the current variation root->swapLine(*parent.second->next); ASSERT(VarDepth); if (--VarDepth == 0) { // Recalculate NumHalfMoves const auto count_moves = [](auto move) { int res = 0; while (!move->endMarker()) { ++res; move = move->next; } return res; }; ASSERT(FirstMove->startMarker() && FirstMove->next); NumHalfMoves = count_moves(FirstMove->next); } return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::DeleteVariation(): // Deletes a variation. Variations are numbered from 0. // Note that for speed and simplicity, freed moves are not // added to the free list. This means that repeatedly adding and // deleting variations will waste memory until the game is cleared. // errorT Game::DeleteVariation() { auto parent = CurrentMove->getParent(); auto root = parent.first; if (!root || MoveExitVariation() != OK) return ERROR_NoVariation; root->detachChild(parent.second); return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::Truncate(): // Truncate game at the current move. // For speed and simplicity, moves and comments are not freed. // So repeatedly adding moves and truncating a game will waste // memory until the game is cleared. void Game::Truncate() { if (CurrentMove->endMarker()) return; auto endMove = NewMove(END_MARKER); CurrentMove->prev->setNext(endMove); CurrentMove = endMove; if (VarDepth == 0) NumHalfMoves = GetCurrentPly(); // Invariants ASSERT(CurrentMove && CurrentMove->prev); ASSERT(!CurrentMove->startMarker()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::TruncateStart(): // Truncate all moves leading to current position. void Game::TruncateStart() { // It is necessary to rebuild the current position using ReadFromFEN() // because the order of pieces is important when encoding to SCIDv4 format. char tempStr[256]; CurrentPos->PrintFEN(tempStr, FEN_ALL_FIELDS); auto pos = std::make_unique(); if (pos->ReadFromFEN(tempStr) != OK) return; if (VarDepth != 0 && MainVariation() != OK) return; NumHalfMoves -= GetCurrentPly(); StartPos = std::move(pos); *CurrentPos = *StartPos; FirstMove->setNext(CurrentMove); // Do all the moves to update moveData.pieceNum to the new StartPos while (MoveForwardInPGN() == OK) { } MoveToStart(); } namespace { //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // calcHomePawnMask(): // Computes the homePawn mask for a position. // int calcHomePawnMask (pieceT pawn, const pieceT* board) { ASSERT (pawn == WP || pawn == BP); const pieceT* bd = &(board[ (pawn == WP ? H2 : H7) ]); int result = 0; if (*bd == pawn) { result |= 128; } bd--; // H-fyle pawn if (*bd == pawn) { result |= 64; } bd--; // G-fyle pawn if (*bd == pawn) { result |= 32; } bd--; // F-fyle pawn if (*bd == pawn) { result |= 16; } bd--; // E-fyle pawn if (*bd == pawn) { result |= 8; } bd--; // D-fyle pawn if (*bd == pawn) { result |= 4; } bd--; // C-fyle pawn if (*bd == pawn) { result |= 2; } bd--; // B-fyle pawn if (*bd == pawn) { result |= 1; } // A-fyle pawn return result; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // patternsMatch(): // Used by Game::MaterialMatch() to test patterns. // Returns 1 if all the patterns in the list match, 0 otherwise. // int patternsMatch(const Position* pos, patternT* ptn) { const pieceT* board = pos->GetBoard(); while (ptn != NULL) { if (ptn->rankMatch == NO_RANK) { if (ptn->fyleMatch == NO_FYLE) { // Nothing to test! } else { // Test this fyle: squareT sq = square_Make (ptn->fyleMatch, RANK_1); int found = 0; for (uint i=0; i < 8; i++, sq += 8) { if (board[sq] == ptn->pieceMatch) { found = 1; break; } } if (found != ptn->flag) { return 0; } } } else { // rankMatch is a rank from 1 to 8: if (ptn->fyleMatch == NO_FYLE) { // Test the whole rank: int found = 0; squareT sq = square_Make (A_FYLE, ptn->rankMatch); for (uint i=0; i < 8; i++, sq++) { if (board[sq] == ptn->pieceMatch) { found = 1; break; } } if (found != ptn->flag) { return 0; } } else { // Just test one square: squareT sq = square_Make(ptn->fyleMatch, ptn->rankMatch); int found = 0; if (board[sq] == ptn->pieceMatch) { found = 1; } if (found != ptn->flag) { return 0; } } } // If we get this far, this pattern matched. Try the next one: ptn = ptn->next; } // If we reach here, all patterns matched: return 1; } } // end of anonymous namespace //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::MaterialMatch(): Material search test. // The parameters min and max should each be an array of 15 // counts, to specify the maximum and minimum number of counts // of each type of piece. // bool Game::MaterialMatch (bool PromotionsFlag, ByteBuffer& buf, byte * min, byte * max, patternT * patterns, int minPly, int maxPly, int matchLength, bool oppBishops, bool sameBishops, int minDiff, int maxDiff) { ASSERT (matchLength >= 1); int matchesNeeded = matchLength; int matDiff; uint plyCount = 0; errorT err = DecodeSkipTags(&buf); while (err == OK) { bool foundMatch = false; byte wMinor, bMinor; // If current pos has LESS than the minimum of pawns, this // game can never match so return false; if (CurrentPos->PieceCount(WP) < min[WP]) { return false; } if (CurrentPos->PieceCount(BP) < min[BP]) { return false; } // If not in the valid move range, go to the next move or return: if ((int)plyCount > maxPly) { return false; } if ((int)plyCount < minPly) { goto Next_Move; } // For these comparisons, we really could only do half of them each move, // according to which side just moved. // For non-pawns, the count could be increased by promotions: if (CurrentPos->PieceCount(WQ) < min[WQ]) { goto Check_Promotions; } if (CurrentPos->PieceCount(BQ) < min[BQ]) { goto Check_Promotions; } if (CurrentPos->PieceCount(WR) < min[WR]) { goto Check_Promotions; } if (CurrentPos->PieceCount(BR) < min[BR]) { goto Check_Promotions; } if (CurrentPos->PieceCount(WB) < min[WB]) { goto Check_Promotions; } if (CurrentPos->PieceCount(BB) < min[BB]) { goto Check_Promotions; } if (CurrentPos->PieceCount(WN) < min[WN]) { goto Check_Promotions; } if (CurrentPos->PieceCount(BN) < min[BN]) { goto Check_Promotions; } wMinor = CurrentPos->PieceCount(WB) + CurrentPos->PieceCount(WN); bMinor = CurrentPos->PieceCount(BB) + CurrentPos->PieceCount(BN); if (wMinor < min[WM]) { goto Check_Promotions; } if (bMinor < min[BM]) { goto Check_Promotions; } // Now test maximum counts: if (CurrentPos->PieceCount(WQ) > max[WQ]) { goto Next_Move; } if (CurrentPos->PieceCount(BQ) > max[BQ]) { goto Next_Move; } if (CurrentPos->PieceCount(WR) > max[WR]) { goto Next_Move; } if (CurrentPos->PieceCount(BR) > max[BR]) { goto Next_Move; } if (CurrentPos->PieceCount(WB) > max[WB]) { goto Next_Move; } if (CurrentPos->PieceCount(BB) > max[BB]) { goto Next_Move; } if (CurrentPos->PieceCount(WN) > max[WN]) { goto Next_Move; } if (CurrentPos->PieceCount(BN) > max[BN]) { goto Next_Move; } if (CurrentPos->PieceCount(WP) > max[WP]) { goto Next_Move; } if (CurrentPos->PieceCount(BP) > max[BP]) { goto Next_Move; } if (wMinor > max[WM]) { goto Next_Move; } if (bMinor > max[BM]) { goto Next_Move; } // If both sides have ONE bishop, we need to check if the search // was restricted to same-color or opposite-color bishops: if (CurrentPos->PieceCount(WB) == 1 && CurrentPos->PieceCount(BB) == 1) { if (!oppBishops || !sameBishops) { // Check the restriction: colorT whiteBishCol = NOCOLOR; colorT blackBishCol = NOCOLOR; // Search for the white and black bishop, to find their // square color: const pieceT* bd = CurrentPos->GetBoard(); for (squareT sq = A1; sq <= H8; sq++) { if (bd[sq] == WB) { whiteBishCol = BOARD_SQUARECOLOR [sq]; } else if (bd[sq] == BB) { blackBishCol = BOARD_SQUARECOLOR [sq]; } } // They should be valid colors: ASSERT (blackBishCol != NOCOLOR && whiteBishCol != NOCOLOR); // If the square colors do not match the restriction, // then this game cannot match: if (oppBishops && blackBishCol == whiteBishCol) { return false; } if (sameBishops && blackBishCol != whiteBishCol) { return false; } } } // Now check if the material difference is in-range: matDiff = (int)CurrentPos->MaterialValue(WHITE) - (int)CurrentPos->MaterialValue(BLACK); if (matDiff < minDiff || matDiff > maxDiff) { goto Next_Move; } // At this point, the Material matches; do the patterns match? if (patterns == NULL || patternsMatch(currentPos(), patterns)) { foundMatch = true; matchesNeeded--; if (matchesNeeded <= 0) { return true; } } // No? well, keep trying... goto Next_Move; Check_Promotions: // We only continue if this game has promotion moves: if (! PromotionsFlag) { return false; } Next_Move: { simpleMoveT sm; err = DecodeNextMove(&buf, sm); if (err == OK) { CurrentPos->DoSimpleMove(&sm); } } plyCount++; if (! foundMatch) { matchesNeeded = matchLength; } } // End of game reached, and no match: return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::ExactMatch(): // Exact position search test. // If sm is not NULL, its from, to, promote etc will be filled with // the next move at the matching position, if there is one. // If neverMatch is non-NULL, the boolean it points to is set to // true if the game could never match even with extra moves. // bool Game::ExactMatch (Position * searchPos, ByteBuffer * buf, simpleMoveT * sm, gameExactMatchT searchType) { // If buf is NULL, the game is in memory. Otherwise, Decode only // the necessary moves: errorT err = OK; if (buf == NULL) { MoveToStart(); } else { err = DecodeSkipTags(buf); } uint plyCount = 0; //uint skip = 0; // Just for statistics on number of moves skipped. uint search_whiteHPawns = 0; uint search_blackHPawns = 0; uint current_whiteHPawns, current_blackHPawns; bool check_pawnMaskWhite, check_pawnMaskBlack; bool doHomePawnChecks = false; uint wpawnFyle [8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint bpawnFyle [8] = {0, 0, 0, 0, 0, 0, 0, 0};; if (searchType == GAME_EXACT_MATCH_Fyles) { const pieceT* board = searchPos->GetBoard(); uint fyle = 0; for (squareT sq = A1; sq <= H8; sq++, board++) { if (*board == WP) { wpawnFyle[fyle]++; } else if (*board == BP) { bpawnFyle[fyle]++; } fyle = (fyle + 1) & 7; } } if (searchType == GAME_EXACT_MATCH_Exact || searchType == GAME_EXACT_MATCH_Pawns) { doHomePawnChecks = true; search_whiteHPawns = calcHomePawnMask (WP, searchPos->GetBoard()); search_blackHPawns = calcHomePawnMask (BP, searchPos->GetBoard()); } check_pawnMaskWhite = check_pawnMaskBlack = false; while (err == OK) { const pieceT* currentBoard = CurrentPos->GetBoard(); const pieceT* board = searchPos->GetBoard(); const pieceT* b1 = currentBoard; const pieceT* b2 = board; bool found = true; // If NO_SPEEDUPS is defined, a slower search is done without // optimisations that detect insufficient material. #ifndef NO_SPEEDUPS // Insufficient material optimisation: if (searchPos->GetCount(WHITE) > CurrentPos->GetCount(WHITE) || searchPos->GetCount(BLACK) > CurrentPos->GetCount(BLACK)) { return false; } // Insufficient pawns optimisation: if (searchPos->PieceCount(WP) > CurrentPos->PieceCount(WP) || searchPos->PieceCount(BP) > CurrentPos->PieceCount(BP)) { return false; } // HomePawn mask optimisation: // If current pos doesn't have a pawn on home rank where // the search pos has one, it can never match. // This happens when (current_xxHPawns & search_xxHPawns) is // not equal to search_xxHPawns. // We do not do this optimisation for a pawn files search, // because the exact pawn squares are not important there. if (searchType != GAME_EXACT_MATCH_Fyles) { if (check_pawnMaskWhite) { current_whiteHPawns = calcHomePawnMask (WP, currentBoard); if ((current_whiteHPawns & search_whiteHPawns) != search_whiteHPawns) { return false; } } if (check_pawnMaskBlack) { current_blackHPawns = calcHomePawnMask (BP, currentBoard); if ((current_blackHPawns & search_blackHPawns) != search_blackHPawns) { return false; } } } #endif // #ifndef NO_SPEEDUPS // Not correct color: skip to next move if (searchPos->GetToMove() != CurrentPos->GetToMove()) { //skip++; goto Move_Forward; } // Extra material: skip to next move if (searchPos->GetCount(WHITE) < CurrentPos->GetCount(WHITE) || searchPos->GetCount(BLACK) < CurrentPos->GetCount(BLACK)) { //skip++; goto Move_Forward; } // Extra pawns/pieces: skip to next move if (searchPos->PieceCount(WP) != CurrentPos->PieceCount(WP) || searchPos->PieceCount(BP) != CurrentPos->PieceCount(BP) || searchPos->PieceCount(WN) != CurrentPos->PieceCount(WN) || searchPos->PieceCount(BN) != CurrentPos->PieceCount(BN) || searchPos->PieceCount(WB) != CurrentPos->PieceCount(WB) || searchPos->PieceCount(BB) != CurrentPos->PieceCount(BB) || searchPos->PieceCount(WR) != CurrentPos->PieceCount(WR) || searchPos->PieceCount(BR) != CurrentPos->PieceCount(BR) || searchPos->PieceCount(WQ) != CurrentPos->PieceCount(WQ) || searchPos->PieceCount(BQ) != CurrentPos->PieceCount(BQ)) { //skip++; goto Move_Forward; } // NOW, compare the actual boards piece-by-piece. if (searchType == GAME_EXACT_MATCH_Exact) { if (searchPos->HashValue() == CurrentPos->HashValue()) { for (squareT sq = A1; sq <= H8; sq++, b1++, b2++) { if (*b1 != *b2) { found = false; break; } } } else { found = false; } } else if (searchType == GAME_EXACT_MATCH_Pawns) { if (searchPos->PawnHashValue() == CurrentPos->PawnHashValue()) { for (squareT sq = A1; sq <= H8; sq++, b1++, b2++) { if (*b1 != *b2 && (*b1 == WP || *b1 == BP)) { found = false; break; } } } else { found = false; } } else if (searchType == GAME_EXACT_MATCH_Fyles) { for (fyleT f = A_FYLE; f <= H_FYLE; f++) { if (searchPos->FyleCount(WP,f) != CurrentPos->FyleCount(WP,f) || searchPos->FyleCount(BP,f) != CurrentPos->FyleCount(BP,f)) { found = false; break; } } } else { // searchType == GAME_EXACT_Match_Material, so do nothing. } if (found) { // Found a match! Set the returned next-move: if (sm) { // We need to decode the next move. if (buf == NULL) { MoveForward(); if (CurrentMove->marker == END_MARKER) { // Position matched at last move in the game. sm->from = sm->to = NULL_SQUARE; sm->promote = EMPTY; } else { *sm = CurrentMove->prev->moveData; MoveBackup(); } } else { err = DecodeNextMove(buf, *sm); if (err != OK) { // Position matched at last move in the game. sm->from = sm->to = NULL_SQUARE; sm->promote = EMPTY; } } } return true; } Move_Forward: #ifndef NO_SPEEDUPS if (doHomePawnChecks) { check_pawnMaskWhite = false; check_pawnMaskBlack = false; rankT rTo = square_Rank (CurrentMove->moveData.to); rankT rFrom = square_Rank (CurrentMove->moveData.from); // We only re-check the home pawn masks when something moves // to or from the 2nd/7th rank: if (rTo == RANK_2 || rFrom == RANK_2) { check_pawnMaskWhite = true; } if (rTo == RANK_7 || rFrom == RANK_7) { check_pawnMaskBlack = true; } } #endif if (buf == NULL) { MoveForward (); if (CurrentMove->marker == END_MARKER) { err = ERROR_EndOfMoveList; } } else { simpleMoveT nextMove; err = DecodeNextMove(buf, nextMove); if (err == OK) { CurrentPos->DoSimpleMove(&nextMove); } if (err != OK && err != ERROR_EndOfMoveList) { return false; } } plyCount++; } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::VarExactMatch(): // Like ExactMatch(), but also searches in variations. // This is much slower than ExactMatch(), since it will // search every position until a match is found. bool Game::VarExactMatch (Position * searchPos, gameExactMatchT searchType) { uint wpawnFyle [8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint bpawnFyle [8] = {0, 0, 0, 0, 0, 0, 0, 0};; if (searchType == GAME_EXACT_MATCH_Fyles) { const pieceT* board = searchPos->GetBoard(); uint fyle = 0; for (squareT sq = A1; sq <= H8; sq++, board++) { if (*board == WP) { wpawnFyle[fyle]++; } else if (*board == BP) { bpawnFyle[fyle]++; } fyle = (fyle + 1) & 7; } } errorT err = OK; while (err == OK) { // Check if this position matches: bool match = false; if (searchPos->GetToMove() == CurrentPos->GetToMove() && searchPos->GetCount(WHITE) == CurrentPos->GetCount(WHITE) && searchPos->GetCount(BLACK) == CurrentPos->GetCount(BLACK) && searchPos->PieceCount(WP) == CurrentPos->PieceCount(WP) && searchPos->PieceCount(BP) == CurrentPos->PieceCount(BP) && searchPos->PieceCount(WN) == CurrentPos->PieceCount(WN) && searchPos->PieceCount(BN) == CurrentPos->PieceCount(BN) && searchPos->PieceCount(WB) == CurrentPos->PieceCount(WB) && searchPos->PieceCount(BB) == CurrentPos->PieceCount(BB) && searchPos->PieceCount(WR) == CurrentPos->PieceCount(WR) && searchPos->PieceCount(BR) == CurrentPos->PieceCount(BR) && searchPos->PieceCount(WQ) == CurrentPos->PieceCount(WQ) && searchPos->PieceCount(BQ) == CurrentPos->PieceCount(BQ)) { match = true; const pieceT* b1 = CurrentPos->GetBoard(); const pieceT* b2 = searchPos->GetBoard(); if (searchType == GAME_EXACT_MATCH_Pawns) { for (squareT sq = A1; sq <= H8; sq++, b1++, b2++) { if (*b1 != *b2 && (*b1 == WP || *b1 == BP)) { match = false; break; } } } else if (searchType == GAME_EXACT_MATCH_Fyles) { uint wpf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint bpf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; uint fyle = 0; for (squareT sq = A1; sq <= H8; sq++, b1++) { if (*b1 == WP) { wpf[fyle]++; if (wpf[fyle] > wpawnFyle[fyle]) { match = false; break; } } else if (*b1 == BP) { bpf[fyle]++; if (bpf[fyle] > bpawnFyle[fyle]) { match = false; break; } } fyle = (fyle + 1) & 7; } } else if (searchType == GAME_EXACT_MATCH_Exact) { if (searchPos->HashValue() == CurrentPos->HashValue()) { for (squareT sq = A1; sq <= H8; sq++, b1++, b2++) { if (*b1 != *b2) { match = false; break; } } } else { match = false; } } else { // searchType == GAME_EXACT_MATCH_Material, so do nothing. } } if (match) { return true; } // Now try searching each variation in turn: for (uint i=0; i < CurrentMove->numVariations; i++) { MoveIntoVariation (i); match = VarExactMatch (searchPos, searchType); MoveExitVariation(); if (match) { return true; } } // Continue down this variation: MoveForward(); if (CurrentMove->marker == END_MARKER) { err = ERROR_EndOfMoveList; } } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::GetPartialMoveList(): // Write the first few moves of a game. // errorT Game::GetPartialMoveList (DString * outStr, uint plyCount) { // First, copy the relevant data so we can leave the game state // unaltered: auto location = currentLocation(); MoveToStart(); char temp [80]; for (uint i=0; i < plyCount; i++) { if (CurrentMove->marker == END_MARKER) { break; } if (i != 0) { outStr->Append (" "); } if (i == 0 || CurrentPos->GetToMove() == WHITE) { snprintf (temp, 80, "%d%s", CurrentPos->GetFullMoveCount(), (CurrentPos->GetToMove() == WHITE ? "." : "...")); outStr->Append (temp); } moveT * m = CurrentMove; if (m->san[0] == 0) { CurrentPos->MakeSANString(&(m->moveData), m->san, SAN_CHECKTEST); } // add one space for indenting to work out right outStr->Append (" "); outStr->Append (m->san); MoveForward(); } // Now reconstruct the original game state: restoreLocation(location); return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Returns the SAN representation of the next move or an empty string ("") if // not at a move. const char* Game::GetNextSAN() { ASSERT(!CurrentMove->endMarker() || *CurrentMove->san == '\0'); if (!CurrentMove->endMarker() && *CurrentMove->san == '\0') { CurrentPos->MakeSANString( &CurrentMove->moveData, CurrentMove->san, CurrentMove->next->endMarker() ? SAN_MATETEST : SAN_CHECKTEST); } return CurrentMove->san; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::GetSAN(): // Print the SAN representation of the current move to a string. // Prints an empty string ("") if not at a move. void Game::GetSAN(char* str) { ASSERT(str != NULL); strcpy(str, GetNextSAN()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::GetPrevSAN(): // Print the SAN representation of the previous move to a string. // Prints an empty string ("") if not at a move. void Game::GetPrevSAN (char * str) { ASSERT (str != NULL); moveT * m = CurrentMove->prev; if (m->marker == START_MARKER || m->marker == END_MARKER) { str[0] = 0; return; } if (m->san[0] == 0) { MoveBackup(); CurrentPos->MakeSANString (&(m->moveData), m->san, SAN_MATETEST); MoveForward(); } strcpy (str, m->san); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::GetPrevMoveUCI(): // Print the UCI representation of the current move to a string. // Prints an empty string ("") if not at a move. void Game::GetPrevMoveUCI(char* str) const { ASSERT(str != NULL); const auto m = CurrentMove->prev; if (!m->startMarker()) str = m->moveData.toLongNotation(str); *str = '\0'; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::GetNextMoveUCI(): // Print the UCI representation of the next move to a string. // Prints an empty string ("") if not at a move. void Game::GetNextMoveUCI (char * str) { ASSERT (str != NULL); if (!CurrentMove->endMarker()) str = CurrentMove->moveData.toLongNotation(str); *str = '\0'; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // commentEmpty: // Called by WriteMoveList to check there is really // something to print given display options. // comment is supposed to be non null bool Game::CommentEmpty ( const char * comment) { char * s = NULL; bool ret = false; if (comment == NULL) return true; if (comment[0] == '\0') return true; if (PgnStyle & PGN_STYLE_STRIP_MARKS) { s = strDuplicate (comment); strTrimMarkCodes (s); char * tmp = s; bool empty = true; while (tmp[0] != 0) { if (tmp[0] != ' ') { empty = false; break; } tmp++; } ret = empty; delete[] s; } return ret; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // writeComment: // Called by WriteMoveList to write a single comment. void Game::WriteComment (TextBuffer * tb, const char * preStr, const char * comment, const char * postStr) { char* s_duplicate = nullptr; const char* s = comment; if (PgnStyle & PGN_STYLE_STRIP_MARKS) { s_duplicate = strDuplicate(comment); strTrimMarkCodes(s_duplicate); s = s_duplicate; } if (s[0] != '\0') { if (IsColorFormat()) { tb->PrintString ("PrintInt (NumMovesPrinted); tb->PrintChar ('>'); } if (IsColorFormat()) { // Translate "<", ">" in comments: tb->AddTranslation ('<', ""); tb->AddTranslation ('>', ""); // S.A any issues ? tb->NewlinesToSpaces (0); tb->PrintString (s); tb->ClearTranslation ('<'); tb->ClearTranslation ('>'); } else { tb->PrintString (preStr); tb->PrintString (s); tb->PrintString (postStr); } if (IsColorFormat()) { tb->PrintString (""); } } if (PgnStyle & PGN_STYLE_STRIP_MARKS) { delete[] s_duplicate; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::WriteMoveList(): // Write the moves, variations and comments in PGN notation. // Recursive; calls itself to write variations. // errorT Game::WriteMoveList(TextBuffer* tb, moveT* oldCurrentMove, bool printMoveNum, bool inComment) { char tempTrans[10]; const char * preCommentStr = "{"; const char * postCommentStr = "}"; const char * startTable = "\n"; const char * startColumn = "\t"; const char * nextColumn = "\t"; const char * endColumn = "\n"; const char * endTable = "\n"; bool printDiagrams = false; if (IsHtmlFormat()) { preCommentStr = ""; postCommentStr = ""; startTable = "\n"; startColumn = "\n \n \n\n"; endTable = "
"; nextColumn = ""; endColumn = "
\n"; printDiagrams = true; } if (IsLatexFormat()) { preCommentStr = "\\begin{nochess}{\\rm "; postCommentStr = "}\\end{nochess}"; startTable = "\n\\begin{tabular}{p{1cm}p{2cm}p{2cm}}\n"; startColumn = ""; nextColumn = "&"; endColumn = "\\\\\n"; endTable = "\\end{tabular}\n\n"; printDiagrams = true; } if (IsColorFormat()) { startTable = "
"; endColumn = "
"; } if (IsHtmlFormat() && VarDepth == 0) { tb->PrintString (""); } if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) { tb->PrintString (startTable); } if (IsPlainFormat() && inComment) { preCommentStr = ""; postCommentStr = ""; } moveT * m = CurrentMove; // Print null moves: if ((PgnStyle & PGN_STYLE_NO_NULL_MOVES) && !inComment && IsPlainFormat() && m->isNull()) { inComment = true; tb->PrintString(preCommentStr); preCommentStr = ""; postCommentStr = ""; } // If this is a variation and it starts with a comment, print it: if ((VarDepth > 0 || CurrentMove->prev == FirstMove) && ! CurrentMove->prev->comment.empty()) { if (PgnStyle & PGN_STYLE_COMMENTS) { WriteComment (tb, preCommentStr, CurrentMove->prev->comment.c_str(), postCommentStr); tb->PrintSpace(); if (!VarDepth) { tb->ClearTranslation ('\n'); tb->NewLine(); if (IsColorFormat() || IsLatexFormat()) { tb->NewLine(); } } } } while (CurrentMove->marker != END_MARKER) { moveT *m = CurrentMove; bool commentLine = false; if (m->san[0] == 0) { // If there is a next move we can skip the SAN_MATETEST CurrentPos->MakeSANString( &(m->moveData), m->san, (m->next->marker != END_MARKER) ? SAN_CHECKTEST : SAN_MATETEST); } bool printThisMove = true; if (m->isNull()) { // Null moves are not printed in LaTeX or HTML: if (IsLatexFormat() || IsHtmlFormat()) { printThisMove = false; printMoveNum = true; } // If Plain PGN format, check whether to convert the // null move and remainder of the line to a comment: if ((PgnStyle & PGN_STYLE_NO_NULL_MOVES) && IsPlainFormat()) { if (!inComment) { // Enter inComment mode to convert rest of line // to a comment: inComment = true; tb->PrintString(preCommentStr); preCommentStr = ""; postCommentStr = ""; } printThisMove = false; printMoveNum = true; } } int colWidth = 6; NumMovesPrinted++; if (printThisMove) { // Print the move number and following dots if necessary: if (IsColorFormat()) { tb->PrintString ("PrintInt (NumMovesPrinted); tb->PrintChar ('>'); } if (printMoveNum || (CurrentPos->GetToMove() == WHITE)) { if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) { tb->PrintString (startColumn); char temp [10]; snprintf (temp, 10, "%4u.", CurrentPos->GetFullMoveCount()); tb->PrintString (temp); if (CurrentPos->GetToMove() == BLACK) { tb->PauseTranslations(); tb->PrintString (nextColumn); tb->PrintString ("..."); if (IsPlainFormat() || IsColorFormat()) { tb->PrintString (" "); } tb->ResumeTranslations(); } } else { if (PgnStyle & PGN_STYLE_MOVENUM_SPACE) { tb->PrintInt(CurrentPos->GetFullMoveCount(), (CurrentPos->GetToMove() == WHITE ? "." : ". ...")); } else { tb->PrintInt(CurrentPos->GetFullMoveCount(), (CurrentPos->GetToMove() == WHITE ? "." : "...")); } if (PgnStyle & PGN_STYLE_MOVENUM_SPACE) { if (IsLatexFormat()) { tb->PrintChar ('~'); } else { tb->PrintChar (' '); } } } printMoveNum = false; } // Now print the move: only regenerate the SAN string if necessary. if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) { tb->PauseTranslations(); tb->PrintString (nextColumn); tb->ResumeTranslations(); } if (IsColorFormat() && (PgnStyle & PGN_STYLE_UNICODE)) { char buf[100]; char* q = buf; for (char const* p = m->san; *p; ++p) { ASSERT(q - buf < static_cast(sizeof(buf) - 4)); switch (*p) { case 'K': q = std::copy_n("\xe2\x99\x94", 3, q); break; case 'Q': q = std::copy_n("\xe2\x99\x95", 3, q); break; case 'R': q = std::copy_n("\xe2\x99\x96", 3, q); break; case 'B': q = std::copy_n("\xe2\x99\x97", 3, q); break; case 'N': q = std::copy_n("\xe2\x99\x98", 3, q); break; case 'P': q = std::copy_n("\xe2\x99\x99", 3, q); break; default: *q++ = *p; break; } } *q = '\0'; tb->PrintWord (buf); } else { // translate pieces strcpy(tempTrans, m->san); transPieces(tempTrans); //tb->PrintWord (m->san); tb->PrintWord (tempTrans); } colWidth -= (int) std::strlen(m->san); if (IsColorFormat()) { tb->PrintString (""); } } bool endedColumn = false; // Print NAGs and comments if the style indicates: if (PgnStyle & PGN_STYLE_COMMENTS) { bool printDiagramHere = false; if (IsColorFormat() && m->nagCount > 0) { tb->PrintString (""); } for (uint i = 0; i < (uint) m->nagCount; i++) { char temp[20]; game_printNag (m->nags[i], temp, PgnStyle & PGN_STYLE_SYMBOLS, PgnFormat); // Do not print a space before the Nag if it is the // first nag and starts with "!" or "?" -- those symbols // look better printed next to the move: if (i > 0 || (temp[0] != '!' && temp[0] != '?')) { tb->PrintSpace(); colWidth--; } if (printDiagrams && m->nags[i] == NAG_Diagram) { printDiagramHere = true; } tb->PrintWord (temp); colWidth -= (int) std::strlen(temp); } if (IsColorFormat() && m->nagCount > 0) { tb->PrintString (""); } tb->PrintSpace(); colWidth--; if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) { if (IsPlainFormat() || IsColorFormat()) { while (colWidth-- > 0) { tb->PrintSpace(); } } } if (printDiagramHere) { if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) { if (! endedColumn) { if (CurrentPos->GetToMove() == WHITE) { tb->PauseTranslations (); tb->PrintString (nextColumn); tb->ResumeTranslations (); } tb->PrintString (endColumn); tb->PrintString (endTable); endedColumn = true; } } if (IsHtmlFormat() && VarDepth == 0) { tb->PrintString (""); } if (IsLatexFormat()) { // The commented-out code below will print diagrams // in variations smaller than game diagrams: //if (VarDepth == 0) { // tb->PrintString("\n\\font\\Chess=chess20\n"); //} else { // tb->PrintString("\n\\font\\Chess=chess10\n"); //} tb->PrintString ("\n\\begin{diagram}\n"); } MoveForward (); DString * dstr = new DString; if (IsHtmlFormat()) { CurrentPos->DumpHtmlBoard (dstr, HtmlStyle, NULL); } else { CurrentPos->DumpLatexBoard (dstr); } MoveBackup (); tb->PrintString (dstr->Data()); delete dstr; if (IsHtmlFormat() && VarDepth == 0) { tb->PrintString (""); } if (IsLatexFormat()) { tb->PrintString ("\n\\end{diagram}\n"); } printMoveNum = true; } if (!m->comment.empty() && ! CommentEmpty(m->comment.c_str()) ) { if (!inComment && IsPlainFormat() && (PgnStyle & PGN_STYLE_NO_NULL_MOVES)) { // If this move has no variations, but the next move // is a null move, enter inComment mode: if (m->next->isNull() && ((!(PgnStyle & PGN_STYLE_VARS)) || (CurrentMove->next->numVariations == 0))) { inComment = true; tb->PrintString(preCommentStr); preCommentStr = ""; postCommentStr = ""; } } /* Code commented to remove extra lines if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) { if (! endedColumn) { if (CurrentPos->GetToMove() == WHITE) { tb->PauseTranslations (); tb->PrintString (nextColumn); tb->ResumeTranslations (); } tb->PrintString (endColumn); tb->PrintString (endTable); endedColumn = true; } } */ if (IsHtmlFormat() && VarDepth == 0) { tb->PrintString ("
"); } if ((PgnStyle & PGN_STYLE_INDENT_COMMENTS) && VarDepth == 0) { if (IsColorFormat()) { tb->PrintString ("
"); } else { tb->SetIndent (tb->GetIndent() + 4); tb->Indent(); } } WriteComment (tb, preCommentStr, m->comment.c_str(), postCommentStr); if ((PgnStyle & PGN_STYLE_INDENT_COMMENTS) && VarDepth == 0) { if (IsColorFormat()) { tb->PrintString ("
"); commentLine = true; } else { tb->SetIndent (tb->GetIndent() - 4); tb->Indent(); } } else { tb->PrintSpace(); } if (printDiagrams && strIsPrefix ("#", m->comment.c_str())) { if (IsLatexFormat()) { tb->PrintString ("\n\\begin{diagram}\n"); } MoveForward (); DString * dstr = new DString; if (IsHtmlFormat()) { CurrentPos->DumpHtmlBoard (dstr, HtmlStyle, NULL); } else { CurrentPos->DumpLatexBoard (dstr); } MoveBackup (); tb->PrintString (dstr->Data()); if (IsLatexFormat()) { tb->PrintString ("\n\\end{diagram}\n"); } delete dstr; } if (IsHtmlFormat() && VarDepth == 0) { tb->PrintString ("
"); } printMoveNum = true; } } else { tb->PrintSpace(); } // Print any variations if the style indicates: if ((PgnStyle & PGN_STYLE_VARS) && (m->numVariations > 0)) { if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) { if (! endedColumn) { if (CurrentPos->GetToMove() == WHITE) { tb->PauseTranslations (); tb->PrintString (nextColumn); tb->ResumeTranslations (); } // Doesn't seem wanted!! S.A (see a few lines below) // tb->PrintString (endColumn); tb->PrintString (endTable); endedColumn = true; } } if (IsColorFormat() && VarDepth == 0) { tb->PrintString (""); } // Doesn't indent first var in column mode properly // if including !(PgnStyle & PGN_STYLE_COLUMN) here. // But as-is, depth 3 vars don't indent in COLUMN mode (bug) if ((PgnStyle & PGN_STYLE_INDENT_VARS) && IsColorFormat()) { if ( !commentLine ) { tb->PrintString ("
"); } } for (uint i=0; i < m->numVariations; i++) { if (PgnStyle & PGN_STYLE_INDENT_VARS) { if (IsColorFormat()) { if (VarDepth < 19) { char tmp_str[16]; snprintf(tmp_str, 16, "", VarDepth + 1); tb->PrintString(tmp_str); } } else { tb->SetIndent (tb->GetIndent() + 4); tb->Indent(); } } if (IsHtmlFormat()) { if (VarDepth == 0) { tb->PrintString ("
"); } } if (IsLatexFormat() && VarDepth == 0) { if (PgnStyle & PGN_STYLE_INDENT_VARS) { tb->PrintLine ("\\begin{variation}"); } else { tb->PrintString ("{\\rm "); } } if (IsColorFormat()) { tb->PrintString (""); } // Note tabs in column mode don't work after this VarDepth>1 for some reason // this VarDepth check is redundant i think if (!IsLatexFormat() || VarDepth != 0) { tb->PrintChar ('('); } MoveIntoVariation (i); NumMovesPrinted++; tb->PrintSpace(); // Recursively print the variation: WriteMoveList (tb, oldCurrentMove, true, inComment); MoveExitVariation(); if (!IsLatexFormat() || VarDepth != 0) { tb->PrintChar (')'); } if (IsColorFormat()) { tb->PrintString (""); } if (IsHtmlFormat()) { if (VarDepth == 0) { tb->PrintString ("
"); } } if (IsLatexFormat() && VarDepth == 0) { if (PgnStyle & PGN_STYLE_INDENT_VARS) { tb->PrintLine ("\\end{variation}"); } else { tb->PrintString ("}"); } } if (PgnStyle & PGN_STYLE_INDENT_VARS) { if (IsColorFormat()) { if (VarDepth < 19) { char tmp_str[16]; snprintf(tmp_str, 16, "
", VarDepth + 1); tb->PrintString(tmp_str); } } else { tb->SetIndent (tb->GetIndent() - 4); tb->Indent(); } } else { tb->PrintSpace(); } printMoveNum = true; } if (IsColorFormat() && VarDepth == 0) { tb->PrintString (""); } } if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) { if (endedColumn) { tb->PrintString(startTable); } if (!endedColumn && CurrentPos->GetToMove() == BLACK) { tb->PrintString (endColumn); endedColumn = true; } } MoveForward(); } if (inComment) { tb->PrintString ("}"); } if (IsHtmlFormat() && VarDepth == 0) { tb->PrintString ("
"); } if ((PgnStyle & PGN_STYLE_COLUMN) && VarDepth == 0) { tb->PrintString(endTable); } return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::WritePGN(): // Write a game in PGN to a textbuffer. // errorT Game::WritePGN(TextBuffer* tb) { char temp[256]; char dateStr [20]; const char * newline = "\n"; tb->NewlinesToSpaces (false); if (IsHtmlFormat()) { newline = "
\n"; } if (IsLatexFormat()) { newline = "\\\\\n"; tb->AddTranslation ('#', "\\#"); tb->AddTranslation ('%', "\\%"); tb->AddTranslation ('&', "\\&"); tb->AddTranslation ('<', "$<$"); tb->AddTranslation ('>', "$>$"); tb->AddTranslation ('_', "\\_"); // tb->AddTranslation ('[', "$[$"); // tb->AddTranslation (']', "$]$"); } if (IsColorFormat()) { newline = "
"; } if (PgnStyle & PGN_STYLE_COLUMN) { PgnStyle |= PGN_STYLE_INDENT_COMMENTS; PgnStyle |= PGN_STYLE_INDENT_VARS; } // First: is there a pre-game comment? If so, print it: // if (FirstMove->comment != NULL && (PgnStyle & PGN_STYLE_COMMENTS) // && ! strIsAllWhitespace (FirstMove->comment)) { // tb->AddTranslation ('\n', newline); // char * s = FirstMove->comment; // if (PgnStyle & PGN_STYLE_STRIP_MARKS) { // s = strDuplicate (FirstMove->comment); // strTrimMarkCodes (s); // } // if (IsColorFormat()) { // sprintf (temp, "", NumMovesPrinted); // tb->PrintString (temp); // tb->AddTranslation ('<', ""); // tb->AddTranslation ('>', ""); // tb->PrintString (s); // tb->ClearTranslation ('<'); // tb->ClearTranslation ('>'); // tb->PrintLine (""); // } else { // tb->PrintLine (s); // } // if (PgnStyle & PGN_STYLE_STRIP_MARKS) { delete[] s; } // tb->ClearTranslation ('\n'); // tb->NewLine(); // } date_DecodeToString (Date, dateStr); if (IsHtmlFormat()) { tb->PrintLine("

"); } if (IsLatexFormat()) { tb->PrintLine ("{\\bf"); } // if (IsColorFormat()) { // tb->AddTranslation ('<', ""); // tb->AddTranslation ('>', ""); // } if (PgnStyle & PGN_STYLE_SHORT_HEADER) { // Print tags in short, 3-line format: //if (IsHtmlFormat()) { tb->PrintString (""); } if (IsLatexFormat()) { tb->PrintString ("$\\circ$ "); } if (PgnFormat==PGN_FORMAT_Color) {tb->PrintString (""); } tb->PrintString (GetWhiteStr()); if (WhiteElo > 0) { snprintf (temp, 256, " (%u)", WhiteElo); tb->PrintString (temp); } switch (PgnFormat) { case PGN_FORMAT_HTML: tb->PrintString ("    --    "); break; case PGN_FORMAT_LaTeX: tb->PrintString (newline); tb->PrintString ("$\\bullet$ "); break; default: tb->PrintString (" -- "); break; } tb->PrintString (GetBlackStr()); if (BlackElo > 0) { snprintf (temp, 256, " (%u)", BlackElo); tb->PrintString (temp); } //if (IsHtmlFormat()) { tb->PrintString (""); } tb->PrintString (newline); tb->PrintString (GetEventStr()); if (!RoundStr.empty() && RoundStr != "?") { tb->PrintString (IsHtmlFormat() ? "  (" : " ("); tb->PrintString (GetRoundStr()); tb->PrintString (")"); } tb->PrintString (IsHtmlFormat() ? "   " : " "); if (IsLatexFormat()) { tb->PrintString (newline); } if (!SiteStr.empty() && SiteStr != "?") { tb->PrintString (GetSiteStr()); tb->PrintString (newline); } // Remove ".??" or ".??.??" from end of dateStr, then print it: if (dateStr[4] == '.' && dateStr[5] == '?') { dateStr[4] = 0; } if (dateStr[7] == '.' && dateStr[8] == '?') { dateStr[7] = 0; } tb->PrintString (dateStr); // Print ECO code: tb->PrintString (IsHtmlFormat() ? "     " : " "); if (IsLatexFormat()) { tb->PrintString ("\\hfill "); } tb->PrintString (RESULT_LONGSTR[Result]); if (EcoCode != 0) { tb->PrintString (IsHtmlFormat() ? "     " : " "); if (IsLatexFormat()) { tb->PrintString ("\\hfill "); } ecoStringT ecoStr; eco_ToExtendedString (EcoCode, ecoStr); tb->PrintString (ecoStr); } auto annotator = FindExtraTag("Annotator"); if (annotator != NULL) { snprintf(temp, 256, " (%s)", annotator); tb->PrintString(temp); } tb->PrintString (newline); if (PgnFormat==PGN_FORMAT_Color) {tb->PrintString (""); } // Print FEN if non-standard start: if (StartPos) { if (IsLatexFormat()) { tb->PrintString ("\n\\begin{diagram}\n"); DString dstr; StartPos->DumpLatexBoard (&dstr); tb->PrintString (dstr.Data()); tb->PrintString ("\n\\end{diagram}\n"); } else if (IsHtmlFormat()) { DString dstr; StartPos->DumpHtmlBoard (&dstr, HtmlStyle, NULL); tb->PrintString (dstr.Data()); } else { StartPos->PrintFEN(std::copy_n("Position: ", 10, temp), FEN_ALL_FIELDS); std::strcat(temp, newline); tb->PrintString (temp); } } } else { // Print tags in standard PGN format, one per line: // Note: we want no line-wrapping when printing PGN tags // so set it to a huge value for now: uint wrapColumn = tb->GetWrapColumn(); tb->SetWrapColumn (99999); if (IsColorFormat()) { tb->PrintString (""); } snprintf (temp, 256, "[Event \"%s\"]%s", GetEventStr(), newline); tb->PrintString (temp); snprintf (temp, 256, "[Site \"%s\"]%s", GetSiteStr(), newline); tb->PrintString (temp); snprintf (temp, 256, "[Date \"%s\"]%s", dateStr, newline); tb->PrintString (temp); snprintf (temp, 256, "[Round \"%s\"]%s", GetRoundStr(), newline); tb->PrintString (temp); snprintf (temp, 256, "[White \"%s\"]%s", GetWhiteStr(), newline); tb->PrintString (temp); snprintf (temp, 256, "[Black \"%s\"]%s", GetBlackStr(), newline); tb->PrintString (temp); snprintf (temp, 256, "[Result \"%s\"]%s", RESULT_LONGSTR[Result], newline); tb->PrintString (temp); // Print all tags, not just the standard seven, if applicable: if (PgnStyle & PGN_STYLE_TAGS) { if (WhiteElo > 0) { snprintf (temp, 256, "[White%s \"%u\"]%s", ratingTypeNames [WhiteRatingType], WhiteElo, newline); tb->PrintString (temp); } if (BlackElo > 0) { snprintf (temp, 256, "[Black%s \"%u\"]%s", ratingTypeNames [BlackRatingType], BlackElo, newline); tb->PrintString (temp); } if (EcoCode != 0) { ecoStringT ecoStr; eco_ToExtendedString (EcoCode, ecoStr); snprintf (temp, 256, "[ECO \"%s\"]%s", ecoStr, newline); tb->PrintString (temp); } if (EventDate != ZERO_DATE) { char edateStr [20]; date_DecodeToString (EventDate, edateStr); snprintf (temp, 256, "[EventDate \"%s\"]%s", edateStr, newline); tb->PrintString (temp); } if (PgnStyle & PGN_STYLE_SCIDFLAGS && *ScidFlags != 0) { snprintf (temp, 256, "[ScidFlags \"%s\"]%s", ScidFlags, newline); tb->PrintString (temp); } // Now print other tags for (auto& e : extraTags_) { snprintf(temp, 256, "[%s \"%s\"]%s", e.first.c_str(), e.second.c_str(), newline); tb->PrintString(temp); } } // Finally, write the FEN tag if necessary: if (StartPos) { StartPos->PrintFEN(std::copy_n("[FEN \"", 6, temp), FEN_ALL_FIELDS); auto it_end = std::copy_n("\"]", 2, temp + std::strlen(temp)); std::strcpy(it_end, newline); tb->PrintString (temp); } if (IsColorFormat()) { tb->PrintString (""); } // Now restore the linewrap column: tb->SetWrapColumn (wrapColumn); } // if (IsColorFormat()) { // tb->ClearTranslation ('<'); // tb->ClearTranslation ('>'); // } if (IsHtmlFormat()) { tb->PrintLine("

"); } if (IsLatexFormat()) { tb->PrintLine ("}\n\\begin{chess}{\\bf "); } else { tb->PrintString (newline); } MoveToStart(); if (IsHtmlFormat()) { tb->PrintString ("

"); } NumMovesPrinted = 1; WriteMoveList(tb, CurrentMove, true, false); if (IsHtmlFormat()) { tb->PrintString (""); } if (IsLatexFormat()) { tb->PrintString ("\n}\\end{chess}\n{\\bf "); } if (IsColorFormat()) { tb->PrintString (""); } tb->PrintWord (RESULT_LONGSTR [Result]); if (IsLatexFormat()) { tb->PrintString ("}\n\\begin{center} \\hrule \\end{center}"); } if (IsHtmlFormat()) { tb->PrintString ("


"); } if (IsColorFormat()) { tb->PrintString (""); } tb->NewLine(); return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::WriteToPGN(): // Print the entire game. // std::pair Game::WriteToPGN(uint lineWidth, bool NewLineAtEnd, bool newLineToSpaces) { static TextBuffer tbuf; auto location = currentLocation(); tbuf.Empty(); tbuf.SetWrapColumn(lineWidth ? lineWidth : tbuf.GetBufferSize()); tbuf.NewlinesToSpaces(newLineToSpaces); WritePGN(&tbuf); if (NewLineAtEnd) tbuf.NewLine(); restoreLocation(location); return std::make_pair(tbuf.GetBuffer(), tbuf.GetByteCount()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::LoadStandardTags(): // Sets the standard tag values for this game, given an // index file entry and a namebase that stores the // player/site/event/round names. // void Game::LoadStandardTags (const IndexEntry* ie, const NameBase* nb) { ASSERT (ie != NULL && nb != NULL); SetEventStr (ie->GetEventName (nb)); SetSiteStr (ie->GetSiteName (nb)); SetWhiteStr (ie->GetWhiteName (nb)); SetBlackStr (ie->GetBlackName (nb)); SetRoundStr (ie->GetRoundName (nb)); SetDate (ie->GetDate()); SetEventDate (ie->GetEventDate()); SetWhiteElo (ie->GetWhiteElo()); SetBlackElo (ie->GetBlackElo()); WhiteEstimateElo = nb->GetElo (ie->GetWhite()); BlackEstimateElo = nb->GetElo (ie->GetBlack()); SetWhiteRatingType (ie->GetWhiteRatingType()); SetBlackRatingType (ie->GetBlackRatingType()); SetResult (ie->GetResult()); SetEco (ie->GetEcoCode()); ie->GetFlagStr (ScidFlags, NULL); } eloT Game::GetAverageElo () { eloT white = WhiteElo; eloT black = BlackElo; if (white == 0) { white = WhiteEstimateElo; } if (black == 0) { black = BlackEstimateElo; } return (white + black) / 2; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // makeMoveByte(): inline routine used for encoding most moves. // static inline byte makeMoveByte (byte pieceNum, byte value) { ASSERT (pieceNum <= 15 && value <= 15); return (byte)((pieceNum & 15) << 4) | (byte)(value & 15); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // encodeKing(): encoding of King moves. // static byte encodeKing(const simpleMoveT* sm) { // Valid King difference-from-old-square values are: // -9, -8, -7, -1, 1, 7, 8, 9, and -2 and 2 for castling. // To convert this to a val in the range [1-10], we add 9 and // then look up the val[] table. // Coded values 1-8 are one-square moves; 9 and 10 are Castling. ASSERT(sm->pieceNum == 0); // Kings MUST be piece Number zero. int diff = (int) sm->to - (int) sm->from; static const byte val[] = { /* -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 */ 1, 2, 3, 0, 0, 0, 0, 9, 4, 0, 5, 10, 0, 0, 0, 0, 6, 7, 8 }; // If target square is the from square, it is the null move, which // is represented as a king move to its own square and is encoded // as the byte value zero. if (sm->to == sm->from) { return 0; } // Verify we have a valid King move: ASSERT(diff >= -9 && diff <= 9 && val[diff+9] != 0); return val[diff + 9]; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // encodeKnight(): encoding Knight moves. // static byte encodeKnight(const simpleMoveT* sm) { // Valid Knight difference-from-old-square values are: // -17, -15, -10, -6, 6, 10, 15, 17. // To convert this to a value in the range [1-8], we add 17 to // the difference and then look up the val[] table. int diff = (int) sm->to - (int) sm->from; static const byte val[] = { /* -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 */ 1, 0, 2, 0, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 */ 0, 0, 0, 0, 0, 5, 0, 0, 0, 6, 0, 0, 0, 0, 7, 0, 8 }; // Verify we have a valid knight move: ASSERT (diff >= -17 && diff <= 17 && val[diff + 17] != 0); return val[diff + 17]; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // encodeRook(): encoding rook moves. // static byte encodeRook(const simpleMoveT* sm) { // Valid Rook moves are to same rank, OR to same fyle. // We encode the 8 squares on the same rank 0-8, and the 8 // squares on the same fyle 9-15. This means that for any particular // rook move, two of the values in the range [0-15] will be // meaningless, as they will represent the from-square. ASSERT (sm->from <= H8 && sm->to <= H8); // Check if the two squares share the same rank: if (square_Rank(sm->from) == square_Rank(sm->to)) { return square_Fyle(sm->to); } return 8 + square_Rank(sm->to); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // encodeBishop(): encoding Bishop moves. // static byte encodeBishop(const simpleMoveT* sm) { // We encode a Bishop move as the Fyle moved to, plus // a one-bit flag to indicate if the direction was // up-right/down-left or vice versa. ASSERT (sm->to <= H8 && sm->from <= H8); int rankdiff = (int)square_Rank(sm->to) - (int)square_Rank(sm->from); int fylediff = (int)square_Fyle(sm->to) - (int)square_Fyle(sm->from); // If (rankdiff * fylediff) is negative, it's up-left/down-right: if (rankdiff * fylediff < 0) return square_Fyle(sm->to) + 8; return square_Fyle(sm->to); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // encodeQueen(): encoding Queen moves. // template void encodeQueen(DestT* buf, const simpleMoveT* sm) { // We cannot fit all Queen moves in one byte, so Rooklike moves // are in one byte (encoded the same way as Rook moves), // while diagonal moves are in two bytes. ASSERT (sm->to <= H8 && sm->from <= H8); byte val; if (square_Rank(sm->from) == square_Rank(sm->to)) { // Rook-horizontal move: val = square_Fyle(sm->to); buf->emplace_back(makeMoveByte (sm->pieceNum, val)); } else if (square_Fyle(sm->from) == square_Fyle(sm->to)) { // Rook-vertical move: val = 8 + square_Rank(sm->to); buf->emplace_back(makeMoveByte (sm->pieceNum, val)); } else { // Diagonal move: ASSERT(std::abs(sm->to / 8 - sm->from / 8) == std::abs(sm->to % 8 - sm->from % 8)); // First, we put a rook-horizontal move to the from square (which // is illegal of course) to indicate it is NOT a rooklike move: val = square_Fyle(sm->from); buf->emplace_back(makeMoveByte (sm->pieceNum, val)); // Now we put the to-square in the next byte. We add a 64 to it // to make sure that it cannot clash with the Special tokens (which // are in the range 0 to 15, since they are special King moves). buf->emplace_back(sm->to + 64); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // encodePawn(): encoding Pawn moves. // static byte encodePawn(const simpleMoveT* sm) { // Pawn moves require a promotion encoding. // The pawn moves are: // 0 = capture-left, // 1 = forward, // 2 = capture-right (all no promotion); // 3/4/5 = 0/1/2 with Queen promo; // 6/7/8 = 0/1/2 with Rook promo; // 9/10/11 = 0/1/2 with Bishop promo; // 12/13/14 = 0/1/2 with Knight promo; // 15 = forward TWO squares. byte val; int diff = (int)(sm->to) - (int)(sm->from); if (diff < 0) { diff = -diff; } if (diff == 16) { // Move forward two squares val = 15; ASSERT (sm->promote == EMPTY); } else { if (diff == 7) { val = 0; } else if (diff == 8) { val = 1; } else { // diff is 9: ASSERT (diff == 9); val = 2; } if (sm->promote != EMPTY) { // Handle promotions. // sm->promote must be Queen=2,Rook=3, Bishop=4 or Knight=5. // We add 3 for Queen, 6 for Rook, 9 for Bishop, 12 for Knight. ASSERT (sm->promote >= QUEEN && sm->promote <= KNIGHT); val += 3 * ((sm->promote) - 1); } } return val; } // Special-move tokens: // Since king-move values 1-10 are taken for actual King moves, only // 11-15 (and zero) are available for non-move information. #define ENCODE_NAG 11 #define ENCODE_COMMENT 12 #define ENCODE_START_MARKER 13 #define ENCODE_END_MARKER 14 #define ENCODE_END_GAME 15 #define ENCODE_FIRST 11 #define ENCODE_LAST 15 // The end-game and end-variation tokens could be the same single token, // but having two different tokens allows for detecting corruption, since // a game must end with the end-game token. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // decodeMove(): // Decode a move from a bytebuffer. Assumes the byte val is an // actual move, not the value of a "special" (non-move) token. // This function needs to be passed the bytebuffer because some // moves (only Queen diagonal moves) are encoded in two bytes, so // it may be necessary to read the next byte as well. // static errorT decodeMove(ByteBuffer* buf, simpleMoveT* sm, byte val, const Position* pos) { const colorT toMove = pos->GetToMove(); const squareT from = pos->GetList(toMove)[val >> 4]; if (from > H8) return ERROR_Decode; sm->from = from; sm->to = from; sm->promote = EMPTY; sm->movingPiece = pos->GetBoard()[from]; const auto [to, promo] = (toMove == WHITE) ? buf->decodeMove(piece_Type(sm->movingPiece), from, val) : buf->decodeMove(piece_Type(sm->movingPiece), from, val); if (to < 0 || to > 63) return ERROR_Decode; if (to == from) { if (promo == INVALID_PIECE) return ERROR_Decode; if (promo == PAWN) // NULL MOVE return OK; if (!pos->validCastling(promo == KING, false)) return ERROR_Decode; sm->to += (promo == KING) ? 2 : -2; return OK; // CASTLE } if (to == pos->GetKingSquare(WHITE) || to == pos->GetKingSquare(BLACK)) return ERROR_Decode; if (promo != INVALID_PIECE) sm->promote = promo; sm->to = static_cast(to); return OK; } template void encodeMove(const simpleMoveT& sm, DestT& dest) { byte val; switch (piece_Type(sm.movingPiece)) { case KING: val = encodeKing(&sm); break; case QUEEN: return encodeQueen(&dest, &sm); case ROOK: val = encodeRook(&sm); break; case BISHOP: val = encodeBishop(&sm); break; case KNIGHT: val = encodeKnight(&sm); break; default: ASSERT(PAWN == piece_Type(sm.movingPiece)); val = encodePawn(&sm); } const auto encoded = makeMoveByte(sm.pieceNum, val); dest.emplace_back(encoded); } /// Encode the moves, the nags, the comment mark and the variations. template std::pair encodeMovelist(const MoveT* m, DestT& dest) { ASSERT(m && m->startMarker()); // Check if there is a pre-game comment if (!m->comment.empty()) dest.emplace_back(ENCODE_COMMENT); unsigned n_vars = 0; unsigned n_nags = 0; while ((m = m->nextMoveInPGN())) { if (m->startMarker()) { ++n_vars; dest.emplace_back(ENCODE_START_MARKER); if (!m->comment.empty()) dest.emplace_back(ENCODE_COMMENT); } else if (m->endMarker()) { if (m->nextMoveInPGN()) dest.emplace_back(ENCODE_END_MARKER); } else { encodeMove(m->moveData, dest); for (int i = 0, n = m->nagCount; i < n; ++i) { dest.emplace_back(ENCODE_NAG); dest.emplace_back(m->nags[i]); ++n_nags; } if (!m->comment.empty()) dest.emplace_back(ENCODE_COMMENT); } } dest.emplace_back(ENCODE_END_GAME); return {n_vars, n_nags}; } /// Decodes the game moves errorT Game::DecodeVariation(ByteBuffer& buf) { simpleMoveT sm; for (;;) { auto [err, val] = buf.nextMove( this->VarDepth, [&](auto) { return true; }, [&] { // Mark this comment as needing to be read this->CurrentMove->prev->comment = '*'; }, [&](auto newVariation) { if (newVariation) return AddVariation() == OK; return (MoveExitVariation() == OK && MoveForward() == OK); }, [&](auto nag) { return this->AddNag(nag) == OK; }); if (err) return (err == ERROR_EndOfMoveList) ? OK : err; auto errMove = decodeMove(&buf, &sm, val, currentPos()); if (!errMove) errMove = AddMove(&sm); if (errMove) return errMove; } } /** * The Comments section is composed by null-terminated strings. The comments are * stored in the order in which they will appear in the PGN notation: * {C1} 1.d4 {C2} (1.b4 {C3} 1...e5 {C4} (1...Na6 {C5}) 2.e4 {C6}) * ({C7} 1.g4 {C8}) 1...d5 {C9} */ template auto encodeComments(const MoveT* m, DestT& dest) { ASSERT(m); unsigned n_comments = 0; do { if (!m->comment.empty()) { const auto len = m->comment.size() + 1; // Include the null char const auto data = m->comment.c_str(); dest.insert(dest.end(), data, data + len); ++n_comments; } } while ((m = m->nextMoveInPGN())); return n_comments; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // decodeComments(): // Decodes the comments of the game. When decoding the moves, the // comment field of each move that has a comment is marked (made // not empty), so this function recurses the movelist and subvariations // and allocates each comment to its move. // template static errorT decodeComments(SourceT& buf, MoveT* m) { ASSERT(m); do { if (!m->comment.empty()) { ASSERT(m->comment == "*"); auto str = buf.GetTerminatedString(); if (!str) return ERROR_BufferRead; m->comment = str; } } while ((m = m->nextMoveInPGN())); return OK; } /// Calculate the game's main line information: /// - home pawn delta information /// - promotions flags /// - number of half moves /// - final material signature /// - stored line code template std::pair mainlineInfo(const Position* customStart, const MoveT* firstMove, IndexEntry& dest) { ushort nHalfMoves = 0; bool PromoFlag = false; bool UnderPromosFlag = false; unsigned hpCount = 0; byte hpVal[8] = {}; Position pos = customStart ? *customStart : Position::getStdStart(); auto hpOld = HPSIG_StdStart; // All 16 pawns are on their home squares. for (auto move = firstMove; !move->endMarker(); move = move->next) { ++nHalfMoves; if (move->moveData.promote != EMPTY) { PromoFlag = true; if (piece_Type(move->moveData.promote) != QUEEN) { UnderPromosFlag = true; } } pos.DoSimpleMove(move->moveData); if (!customStart) { const auto hpNew = pos.GetHPSig(); if (unsigned changed = hpOld - hpNew) { hpOld = hpNew; byte idxMovedPawn = 0; // __builtin_ctz(changed) while (changed >>= 1) { ++idxMovedPawn; } assert(idxMovedPawn <= 0x0F); if ((hpCount & 1) == 0) // There are only 16 pawns, so we can idxMovedPawn <<= 4; // store two pawn moves in every byte hpVal[hpCount++ / 2] |= idxMovedPawn; } } } byte storedCode = 0; if (!customStart) { storedCode = StoredLine::classify([&](auto begin, auto end) { if (std::distance(begin, end) > nHalfMoves) return false; const moveT* gameMove = firstMove; for (; begin != end; ++begin) { if (gameMove->moveData.from != begin->getFrom() || gameMove->moveData.to != begin->getTo()) return false; gameMove = gameMove->next; } return true; }); } dest.SetHomePawnData(static_cast(hpCount), hpVal); dest.SetPromotionsFlag(PromoFlag); dest.SetUnderPromoFlag(UnderPromosFlag); dest.SetNumHalfMoves(nHalfMoves); dest.SetFinalMatSig(matsig_Make(pos.GetMaterial())); dest.SetStoredLineCode(storedCode); return {PromoFlag, UnderPromosFlag}; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::Encode(): Encode the game to a buffer for disk storage. // If passed a NON-null IndexEntry pointer, it will fill in the // following fields of that index entry, which are computed as // the game is encoded: // - result, ecoCode, whiteElo, blackElo // - promotion flag // - nMoves: the number of halfmoves // - finalMatSig: the material signature of the final position. // - homePawnData: the home pawn change list. // errorT Game::Encode(std::vector& dest, IndexEntry& ie) const { ie.clearFlags(); // Set the fields in the IndexEntry: ie.SetDate(Date); ie.SetEventDate(EventDate); ie.SetResult(Result); ie.SetEcoCode(EcoCode); ie.SetWhiteElo(WhiteElo); ie.SetBlackElo(BlackElo); ie.SetWhiteRatingType(WhiteRatingType); ie.SetBlackRatingType(BlackRatingType); ie.SetStartFlag(HasNonStandardStart()); ie.SetFlag(IndexEntry::StrToFlagMask(ScidFlags), true); const auto [promo, underPromo] = mainlineInfo(StartPos.get(), FirstMove->next, ie); // First, encode info not already stored in the index // This will be the non-STR (non-"seven tag roster") PGN tags. encodeTags(GetExtraTags(), dest); // Encode the promotion flags and the start position char FEN[256]; encodeStartBoard(promo, underPromo, HasNonStandardStart(FEN) ? FEN : nullptr, dest); // Now the movelist: auto [varCount, nagCount] = encodeMovelist(FirstMove, dest); // Now do the comments const auto commentCount = encodeComments(FirstMove, dest); ie.SetCommentCount(commentCount); ie.SetVariationCount(varCount); ie.SetNagCount(nagCount); return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::DecodeNextMove(): // Decodes one more mainline move of the game from the bytebuffer. // Used in searches for speed, since it is usually possible to // determine if a game matches the search criteria without decoding // all of it. // If the game flag KeepDecodedMoves is true, the move decodes is // added normally. If it is false, only the current position is // updated and the list of moves is not updated -- this is done // in searches for speed. // Returns OK if a move was found, or ERROR_EndOfMoveList if all the // moves have been decoded. Returns ERROR_Game if some corruption was // detected. // errorT Game::DecodeNextMove(ByteBuffer* buf, simpleMoveT& sm) { ASSERT(buf != NULL); auto [err, val] = buf->nextLineMove(); if (err) return err; return decodeMove(buf, &sm, val, currentPos()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::DecodeStart(): // Decodes the starting information from the game's on-disk // representation in the bytebuffer. After this is called, // DecodeNextMove() can be called to decode each successive // mainline move. // errorT Game::DecodeSkipTags(ByteBuffer* buf) { ASSERT(buf != NULL); Clear(); errorT err = buf->decodeTags([](auto, auto) {}); if (err != OK) return err; const auto [err_startpos, fen] = buf->decodeStartBoard(); if (err_startpos) return err_startpos; if (fen) return SetStartFen(fen); return OK; } errorT Game::DecodeMovesOnly(ByteBuffer& buf) { if (errorT err = DecodeSkipTags(&buf)) return err; return DecodeVariation(buf); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Game::Decode(): // Decodes a game from its on-disk representation in a bytebuffer. // Decodes all the information: comments, variations, non-standard // tags, etc. // errorT Game::Decode(ByteBuffer& buf) { Clear(); errorT err = buf.decodeTags([&](const auto& tag, const auto& value) { accessTagValue(tag.data(), tag.size()).assign(value); }); if (err) return err; const auto [err_startpos, fen] = buf.decodeStartBoard(); if (err_startpos) return err_startpos; if (fen) err = SetStartFen(fen); if (err == OK) err = DecodeVariation(buf); if (err == OK) err = decodeComments(buf, FirstMove); return err; } ////////////////////////////////////////////////////////////////////// // EOF: game.cpp ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/position.cpp0000755000076500000240000030550014666426276020262 0ustar jensstaff////////////////////////////////////////////////////////////////////// // // FILE: position.cpp // Position class methods // // Part of: Scid (Shane's Chess Information Database) // Version: 3.5 // // Notice: Copyright (c) 1999-2003 Shane Hudson. All rights reserved. // // Author: Shane Hudson (sgh@users.sourceforge.net) // ////////////////////////////////////////////////////////////////////// #include "common.h" #include "position.h" #include "attacks.h" #include "misc.h" #include "hash.h" #include "sqmove.h" #include "dstring.h" #include "movegen.h" #include static uint hashVal [16][64]; static uint stdStartHash = 0; static uint stdStartPawnHash = 0; // HASH and UNHASH are identical: XOR the hash value for a (piece,square). #define HASH(h,p,sq) (h) ^= hashVal[(p)][(sq)] #define UNHASH(h,p,sq) (h) ^= hashVal[(p)][(sq)] inline void Position::AddHash (pieceT p, squareT sq) { HASH (Hash, p, sq); if (piece_Type(p) == PAWN) { HASH (PawnHash, p, sq); } } inline void Position::UnHash (pieceT p, squareT sq) { UNHASH (Hash, p, sq); if (piece_Type(p) == PAWN) { UNHASH (PawnHash, p, sq); } } inline void Position::AddToBoard (pieceT p, squareT sq) { ASSERT (Board[sq] == EMPTY); Board[sq] = p; NumOnRank[p][square_Rank(sq)]++; NumOnFyle[p][square_Fyle(sq)]++; NumOnLeftDiag[p][square_LeftDiag(sq)]++; NumOnRightDiag[p][square_RightDiag(sq)]++; NumOnSquareColor[p][square_Color(sq)]++; AddHash (p, sq); } inline void Position::RemoveFromBoard (pieceT p, squareT sq) { ASSERT (Board[sq] == p); Board[sq] = EMPTY; NumOnRank[p][square_Rank(sq)]--; NumOnFyle[p][square_Fyle(sq)]--; NumOnLeftDiag[p][square_LeftDiag(sq)]--; NumOnRightDiag[p][square_RightDiag(sq)]--; NumOnSquareColor[p][square_Color(sq)]--; UnHash (p, sq); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // initHashValues: // Initialises the table of Zobrist hash values. static void initHashValues (void) { // Ensure we set up the hash values only once: static int firstCall = 1; if (! firstCall) { return; } firstCall = 0; // First, set all values to 0: uint sq; for (uint p = 0; p < 16; p++) { for (sq = A1; sq <= H8; sq++) { hashVal[p][sq] = 0; } } // Fill in the hash values for each valid [piece][square] index, // using a table of pre-generated good values: const unsigned int * hash = goodHashValues; for (sq=A1; sq <= H8; sq++) { hashVal[WK][sq] = *hash; hash++; } for (sq=A1; sq <= H8; sq++) { hashVal[WQ][sq] = *hash; hash++; } for (sq=A1; sq <= H8; sq++) { hashVal[WR][sq] = *hash; hash++; } for (sq=A1; sq <= H8; sq++) { hashVal[WB][sq] = *hash; hash++; } for (sq=A1; sq <= H8; sq++) { hashVal[WN][sq] = *hash; hash++; } for (sq=A1; sq <= H8; sq++) { hashVal[WP][sq] = *hash; hash++; } for (sq=A1; sq <= H8; sq++) { hashVal[BK][sq] = *hash; hash++; } for (sq=A1; sq <= H8; sq++) { hashVal[BQ][sq] = *hash; hash++; } for (sq=A1; sq <= H8; sq++) { hashVal[BR][sq] = *hash; hash++; } for (sq=A1; sq <= H8; sq++) { hashVal[BB][sq] = *hash; hash++; } for (sq=A1; sq <= H8; sq++) { hashVal[BN][sq] = *hash; hash++; } for (sq=A1; sq <= H8; sq++) { hashVal[BP][sq] = *hash; hash++; } // Compute the hash values for the standard starting position: uint h = 0; // First the pawns: HASH (h,WP,A2); HASH (h,WP,B2); HASH (h,WP,C2); HASH (h,WP,D2); HASH (h,WP,E2); HASH (h,WP,F2); HASH (h,WP,G2); HASH (h,WP,H2); HASH (h,BP,A7); HASH (h,BP,B7); HASH (h,BP,C7); HASH (h,BP,D7); HASH (h,BP,E7); HASH (h,BP,F7); HASH (h,BP,G7); HASH (h,BP,H7); stdStartPawnHash = h; // Now the nonpawns: HASH (h,WR,A1); HASH (h,WN,B1); HASH (h,WB,C1); HASH (h,WQ,D1); HASH (h,WK,E1); HASH (h,WB,F1); HASH (h,WN,G1); HASH (h,WR,H1); HASH (h,BR,A8); HASH (h,BN,B8); HASH (h,BB,C8); HASH (h,BQ,D8); HASH (h,BK,E8); HASH (h,BB,F8); HASH (h,BN,G8); HASH (h,BR,H8); stdStartHash = h; } /////////////////////////////////////////////////////////////////////////// // sqDir[][]: Array listing the direction between any two squares. // For example, sqDir[A1][B2] == UP_RIGHT, and sqDir[A1][C2] == NULL_DIR. directionT sqDir[66][66]; struct sqDir_Init { sqDir_Init() { // Initialise the sqDir[][] array of directions between every pair // of squares. squareT i, j; directionT dirArray[] = { UP, DOWN, LEFT, RIGHT, UP_LEFT, UP_RIGHT, DOWN_LEFT, DOWN_RIGHT, NULL_DIR }; // First, set everything to NULL_DIR: for (i=A1; i <= NS; i++) { for (j=A1; j <= NS; j++) { sqDir[i][j] = NULL_DIR; } } // Now fill in the valid directions: for (i=A1; i <= H8; i++) { directionT * dirptr = dirArray; while (*dirptr != NULL_DIR) { j = square_Move (i, *dirptr); while (j != NS) { sqDir[i][j] = *dirptr; j = square_Move (j, *dirptr); } dirptr++; } } } } sqDir_Init_singleton; /////////////////////////////////////////////////////////////////////////// // PRIVATE FUNCTIONS -- small ones are inline for speed //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::CalcPinsDir(): // Look for a pinned piece in the direction 'dir' relative to // the position of the king to move. // inline void Position::CalcPinsDir (directionT dir, pieceT attacker) { // Two pieces can pin along any path. A queen is always one, // the other is a bishop or rook. To save calculating it here, the // appropriate piece (BISHOP) or (ROOK) is passed along with the // direction. squareT king = GetKingSquare (ToMove); squareT friendly = NULL_SQUARE; squareT x = king; squareT last = square_Last (king, dir); int delta = direction_Delta (dir); while (x != last) { x += delta; pieceT p = Board[x]; if (p == EMPTY) { // Empty square, so keep searching. } else if (piece_Color_NotEmpty(p) == ToMove) { // Found a friendly piece. if (friendly == NULL_SQUARE) { // Found first friendly in this direction friendly = x; } else { // Found second friendly in this direction, so stop. return; } } else { // Found an enemy piece if (friendly != NULL_SQUARE) { // Potential pin: pieceT ptype = piece_Type(p); if (ptype == QUEEN || ptype == attacker) { Pinned[ListPos[friendly]] = dir; } } return; // found an enemy piece, so end search } } return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::AddLegalMove(): // Add a legal move to the move list. // inline void Position::AddLegalMove (MoveList * mlist, squareT from, squareT to, pieceT promo) { ASSERT (mlist != NULL); // We do NOT set the pre-move castling/ep flags, or the captured // piece info, here since that is ONLY needed if the move is // going to be executed with DoSimpleMove() and then undone. mlist->emplace_back(from, to, promo, Board[from], Board[to]); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenSliderMoves(): // Generate slider moves along a direction, for a sliding // piece of the specified color from the specified square. // If sqset != NULL, moves must be to a square in sqset. inline void Position::GenSliderMoves (MoveList * mlist, colorT color, squareT fromSq, directionT dir, SquareSet * sqset, bool capturesOnly) { squareT dest = fromSq; squareT last = square_Last (fromSq, dir); int delta = direction_Delta (dir); while (dest != last) { dest += delta; pieceT p = Board[dest]; if (p == EMPTY) { if (! capturesOnly) { if (sqset == NULL || sqset->Contains(dest)) { AddLegalMove (mlist, fromSq, dest, EMPTY); } } continue; } // We have reached a piece. Add the capture if it is an enemy. if (piece_Color_NotEmpty(p) != color) { if (sqset == NULL || sqset->Contains(dest)) { AddLegalMove (mlist, fromSq, dest, EMPTY); } } break; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenKnightMoves(): // Generate knight moves. // If sqset != NULL, moves must be to a square in sqset. inline void Position::GenKnightMoves (MoveList * mlist, colorT c, squareT fromSq, SquareSet * sqset, bool capturesOnly) { const squareT * destPtr = knightAttacks[fromSq]; while (true) { squareT dest = *destPtr; if (dest == NULL_SQUARE) { break; } destPtr++; pieceT p = Board[dest]; if (capturesOnly && p == EMPTY) { continue; } if (piece_Color(p) != c) { if (sqset == NULL || sqset->Contains(dest)) { AddLegalMove (mlist, fromSq, dest, EMPTY); } } } } squareT Position::castlingKingSq(colorT color) const { return square_Relative(color, E1); } template squareT Position::castlingRookSq(colorT color) const { return king_side ? square_Relative(color, H1) : square_Relative(color, A1); } bool Position::validCastling(bool king_side, bool check_legal) const { const squareT kingFrom = castlingKingSq(ToMove); const squareT rookFrom = king_side ? castlingRookSq(ToMove) : castlingRookSq(ToMove); const squareT rookTo = king_side ? square_Relative(ToMove, F1) : square_Relative(ToMove, D1); const squareT kingTo = king_side ? square_Relative(ToMove, G1) : square_Relative(ToMove, C1); if (Board[kingFrom] != piece_Make(ToMove, KING) || Board[rookFrom] != piece_Make(ToMove, ROOK)) return false; const int stepRook = rookFrom < rookTo ? -1 : 1; for (int sq = rookTo; sq != rookFrom; sq += stepRook) { if (Board[sq] != EMPTY && sq != kingFrom) return false; if (!check_legal) break; } const int stepKing = kingFrom < kingTo ? -1 : 1; for (int sq = kingTo; sq != kingFrom; sq += stepKing) { if (Board[sq] != EMPTY && sq != rookFrom) return false; if (!check_legal) break; if (CalcNumChecks(sq) > 0) return false; } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenCastling(): // Generate the legal castling moves. // Assumes the side to move is NOT in check, so the caller // should verify this first. // void Position::GenCastling(MoveList* mlist) { const squareT from = square_Relative(ToMove, E1); if (GetCastling(ToMove, KSIDE) && validCastling(true, true)) AddLegalMove(mlist, from, from + 2, EMPTY); if (GetCastling(ToMove, QSIDE) && validCastling(false, true)) AddLegalMove(mlist, from, from - 2, EMPTY); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenKingMoves(): // Generate the legal King moves. Castling is generated as well, if // the specified flag is true. // void Position::GenKingMoves (MoveList * mlist, genMovesT genType, bool castling) { squareT kingSq = GetKingSquare(); squareT enemyKingSq = GetEnemyKingSquare(); colorT enemy = color_Flip(ToMove); const squareT * destPtr; pieceT king = piece_Make (ToMove, KING); bool genNonCaptures = (genType & GEN_NON_CAPS); ASSERT (Board[kingSq] == king); destPtr = kingAttacks[kingSq]; while (*destPtr != NULL_SQUARE) { // Try this move and see if it legal: squareT destSq = *destPtr; bool addThisMove = false; // Only try this move if the target square has an enemy piece, // or if it is empty and noncaptures are to be generated: if ( (genNonCaptures && Board[destSq] == EMPTY) || piece_Color (Board[destSq]) == enemy) { // Empty or enemy piece there, so try the move: pieceT captured = Board[destSq]; Board[destSq] = king; Board[kingSq] = EMPTY; // It is legal if the two kings will not be adjacent and the // moving king will not be in check on its new square: if (! square_Adjacent (destSq, enemyKingSq)) { if (CalcNumChecks (destSq) == 0) { addThisMove = true; } } Board[kingSq] = king; Board[destSq] = captured; } if (addThisMove) { AddLegalMove (mlist, kingSq, destSq, EMPTY); } destPtr++; } // Now generate castling moves, if possible: if (genNonCaptures && castling) { GenCastling (mlist); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::AddPromotions(): // Add promotion moves. // Called by GenPawnMoves() when a pawn can be promoted. // inline void Position::AddPromotions (MoveList * mlist, squareT from, squareT dest) { ASSERT (piece_Type (Board[from]) == PAWN); ASSERT (square_Rank (dest) == RANK_1 || square_Rank (dest) == RANK_8); AddLegalMove (mlist, from, dest, QUEEN); AddLegalMove (mlist, from, dest, ROOK); AddLegalMove (mlist, from, dest, BISHOP); AddLegalMove (mlist, from, dest, KNIGHT); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::IsValidEnPassant // Used to verify that an en passant pawn capture is valid. // This is needed because illegal en passant captures can appear // legal according to calculations of pinned pieces. For example, // consider WK d5, WP e5, BP f5 (just moved there), BR h5 and // the en passant capture exf6 would be illegal. inline bool Position::IsValidEnPassant (squareT from, squareT to) { ASSERT (from <= H8 && to <= H8); ASSERT (to == EPTarget); // Check that this en passant capture is legal: pieceT ownPawn = piece_Make(ToMove, PAWN); pieceT enemyPawn = piece_Make (color_Flip(ToMove), PAWN); squareT enemyPawnSq = (ToMove == WHITE) ? to - 8 : to + 8; ASSERT (Board[from] == ownPawn); ASSERT (Board[enemyPawnSq] == enemyPawn); Board[from] = EMPTY; // PG Board[to] = ownPawn; Board[enemyPawnSq] = EMPTY; bool isValid = ! IsKingInCheck(); //PG Board[to] = EMPTY; Board[from] = ownPawn; Board[enemyPawnSq] = enemyPawn; return isValid; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenPawnMoves(): // Generate legal pawn moves. // If dir != NULL_DIR, pawn MUST move in direction dir or its opposite. // If sqset != NULL, pawn MUST move to a square in sqset. // The dir and sq parameters are for pinned pawns and check evasions. void Position::GenPawnMoves (MoveList * mlist, squareT from, directionT dir, SquareSet * sqset, genMovesT genType) { bool genNonCaptures = (genType & GEN_NON_CAPS); directionT oppdir = direction_Opposite(dir); directionT forward; rankT promoRank; rankT secondRank; if (ToMove == WHITE) { forward = UP; promoRank = RANK_8; secondRank = RANK_2; } else { forward = DOWN; promoRank = RANK_1; secondRank = RANK_7; } squareT dest; ASSERT (Board[from] == piece_Make (ToMove, PAWN)); if (genNonCaptures && (dir == NULL_DIR || dir == forward || oppdir == forward)) { dest = square_Move (from, forward); if (Board[dest]==EMPTY && (sqset==NULL || sqset->Contains(dest))) { if (square_Rank(dest) == promoRank) { AddPromotions (mlist, from, dest); } else { AddLegalMove (mlist, from, dest, EMPTY); } } if (square_Rank(from) == secondRank && Board[dest] == EMPTY) { dest = square_Move (dest, forward); if (Board[dest]==EMPTY && (sqset==NULL || sqset->Contains(dest))) { AddLegalMove (mlist, from, dest, EMPTY); } } } // Now do captures: left, then right // To be a possible capture, dest square must be EPTarget or hold // an enemy piece. #define POSSIBLE_CAPTURE(d) ((d != NULL_SQUARE) \ && ((piece_Color (Board[d]) == (color_Flip(ToMove))) \ || (d == EPTarget && IsValidEnPassant(from,d)))) directionT capdir = forward | LEFT; if (dir == NULL_DIR || dir == capdir || oppdir == capdir) { dest = square_Move (from, capdir); if (POSSIBLE_CAPTURE(dest) && (sqset==NULL || sqset->Contains(dest))) { if (square_Rank(dest) == promoRank) { AddPromotions (mlist, from, dest); } else { AddLegalMove (mlist, from, dest, EMPTY); } } } capdir = forward | RIGHT; if (dir == NULL_DIR || dir == capdir || oppdir == capdir) { dest = square_Move (from, capdir); if (POSSIBLE_CAPTURE(dest) && (sqset==NULL || sqset->Contains(dest))) { if (square_Rank(dest) == promoRank) { AddPromotions (mlist, from, dest); } else { AddLegalMove (mlist, from, dest, EMPTY); } } } return; } ////////////////////////////////////////////////////////////////////// // PUBLIC FUNCTIONS //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GetHPSig(): // Return the position's home pawn signature. // uint Position::GetHPSig (void) { uint hpSig = 0; pieceT * b = &(Board[A2]); if (*b == WP) { hpSig |= 0x8000; } b++; /* a2 */ if (*b == WP) { hpSig |= 0x4000; } b++; /* b2 */ if (*b == WP) { hpSig |= 0x2000; } b++; /* c2 */ if (*b == WP) { hpSig |= 0x1000; } b++; /* d2 */ if (*b == WP) { hpSig |= 0x0800; } b++; /* e2 */ if (*b == WP) { hpSig |= 0x0400; } b++; /* f2 */ if (*b == WP) { hpSig |= 0x0200; } b++; /* g2 */ if (*b == WP) { hpSig |= 0x0100; } /* h2 */ b = &(Board[A7]); if (*b == BP) { hpSig |= 0x0080; } b++; /* a7 */ if (*b == BP) { hpSig |= 0x0040; } b++; /* b7 */ if (*b == BP) { hpSig |= 0x0020; } b++; /* c7 */ if (*b == BP) { hpSig |= 0x0010; } b++; /* d7 */ if (*b == BP) { hpSig |= 0x0008; } b++; /* e7 */ if (*b == BP) { hpSig |= 0x0004; } b++; /* f7 */ if (*b == BP) { hpSig |= 0x0002; } b++; /* g7 */ if (*b == BP) { hpSig |= 0x0001; } /* h7 */ return hpSig; } Position::Position() { // Setting up a valid board is left to StdStart() or Clear(). Board [COLOR_SQUARE] = EMPTY; Board [NULL_SQUARE] = END_OF_BOARD; // Make sure all tables used for move generation, hashing, // square tests, etc have been computed: initHashValues(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::Clear(): // Clear the board and associated structures. // void Position::Clear (void) { int i; for (i=A1; i <= H8; i++) { Board[i] = EMPTY; } for (i=WK; i <= BP; i++) { Material[i] = 0; for (uint j=0; j < 8; j++) { NumOnRank[i][j] = NumOnFyle[i][j] = 0; } for (uint d=0; d < 15; d++) { NumOnLeftDiag[i][d] = NumOnRightDiag[i][d] = 0; } NumOnSquareColor[i][WHITE] = NumOnSquareColor[i][BLACK] = 0; } Count[WHITE] = Count[BLACK] = 0; EPTarget = NULL_SQUARE; Castling = 0; Board [NULL_SQUARE] = END_OF_BOARD; PlyCounter = 0; HalfMoveClock = 0; Hash = 0; PawnHash = 0; return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::StdStart(): // Set up the standard chess starting position. For performance the data is copied from a // template. // const Position& Position::getStdStart() { static Position startPositionTemplate; static bool init = true; if (init){ init = false; Position* p = &startPositionTemplate; p->Clear(); p->Material[WK] = p->Material[BK] = 1; p->Material[WQ] = p->Material[BQ] = 1; p->Material[WR] = p->Material[BR] = 2; p->Material[WB] = p->Material[BB] = 2; p->Material[WN] = p->Material[BN] = 2; p->Material[WP] = p->Material[BP] = 8; p->Count[WHITE] = p->Count[BLACK] = 16; p->AddToBoard(WK, E1); p->List[WHITE][0] = E1; p->ListPos[E1] = 0; p->AddToBoard(BK, E8); p->List[BLACK][0] = E8; p->ListPos[E8] = 0; p->AddToBoard(WR, A1); p->List[WHITE][1] = A1; p->ListPos[A1] = 1; p->AddToBoard(BR, A8); p->List[BLACK][1] = A8; p->ListPos[A8] = 1; p->AddToBoard(WN, B1); p->List[WHITE][2] = B1; p->ListPos[B1] = 2; p->AddToBoard(BN, B8); p->List[BLACK][2] = B8; p->ListPos[B8] = 2; p->AddToBoard(WB, C1); p->List[WHITE][3] = C1; p->ListPos[C1] = 3; p->AddToBoard(BB, C8); p->List[BLACK][3] = C8; p->ListPos[C8] = 3; p->AddToBoard(WQ, D1); p->List[WHITE][4] = D1; p->ListPos[D1] = 4; p->AddToBoard(BQ, D8); p->List[BLACK][4] = D8; p->ListPos[D8] = 4; p->AddToBoard(WB, F1); p->List[WHITE][5] = F1; p->ListPos[F1] = 5; p->AddToBoard(BB, F8); p->List[BLACK][5] = F8; p->ListPos[F8] = 5; p->AddToBoard(WN, G1); p->List[WHITE][6] = G1; p->ListPos[G1] = 6; p->AddToBoard(BN, G8); p->List[BLACK][6] = G8; p->ListPos[G8] = 6; p->AddToBoard(WR, H1); p->List[WHITE][7] = H1; p->ListPos[H1] = 7; p->AddToBoard(BR, H8); p->List[BLACK][7] = H8; p->ListPos[H8] = 7; for (uint i=0; i < 8; i++) { p->AddToBoard(WP, A2+i); p->List[WHITE][i+8] = A2+i; p->ListPos[A2+i] = i+8; p->AddToBoard(BP, A7+i); p->List[BLACK][i+8] = A7+i; p->ListPos[A7+i] = i+8; } p->Castling = 0; p->SetCastling (WHITE, QSIDE, true); p->SetCastling (WHITE, KSIDE, true); p->SetCastling (BLACK, QSIDE, true); p->SetCastling (BLACK, KSIDE, true); p->EPTarget = NULL_SQUARE; p->ToMove = WHITE; p->PlyCounter = 0; p->HalfMoveClock = 0; p->Board [NULL_SQUARE] = END_OF_BOARD; p->Hash = stdStartHash; p->PawnHash = stdStartPawnHash; } return startPositionTemplate; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::IsStdStart // Returns true if the position is the standard starting position. bool Position::IsStdStart() const { if (ToMove != WHITE || Hash != stdStartHash || PawnHash != stdStartPawnHash || GetCount(WHITE) != 16 || GetCount(BLACK) != 16 || RankCount(WP,RANK_2) != 8 || RankCount(BP,RANK_7) != 8 || RankCount(WN,RANK_1) != 2 || RankCount(BN,RANK_8) != 2 || !GetCastling(WHITE,KSIDE) || !GetCastling(WHITE,QSIDE) || !GetCastling(BLACK,KSIDE) || !GetCastling(BLACK,QSIDE)) { return false; } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::AddPiece(): // Add a piece to the board and piecelist. // Checks that a side cannot have more than 16 pieces or more // than one king. // errorT Position::AddPiece (pieceT p, squareT sq) { ASSERT (p != EMPTY); colorT c = piece_Color(p); if ((c != WHITE && c != BLACK) || Count[c] > 15) return ERROR_PieceCount; if (piece_Type(p) == KING) { // Check there is not already a King: if (Material[p] > 0) { return ERROR_PieceCount; } // King is always at the start of the piecelist, so move the piece // already at location 0 if there is one: if (Count[c] > 0) { squareT oldsq = List[c][0]; List[c][Count[c]] = oldsq; ListPos[oldsq] = Count[c]; } List[c][0] = sq; ListPos[sq] = 0; } else { ListPos[sq] = Count[c]; List[c][Count[c]] = sq; } Count[c]++; Material[p]++; AddToBoard (p, sq); return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::CalcPins(): // Calculate the pieces for the side to move that are // pinned to their king. The array Pinned[] stores, for // each piece, the direction in which it is pinned. // // For example WK on e1, WQ on e2, BQ on e7 on the e-fyle // means the WQ is Pinned in the direction UP. // void Position::CalcPins (void) { Pinned[ 0] = Pinned[ 1] = Pinned[ 2] = Pinned[ 3] = Pinned[ 4] = Pinned[ 5] = Pinned[ 6] = Pinned[ 7] = Pinned[ 8] = Pinned[ 9] = Pinned[10] = Pinned[11] = Pinned[12] = Pinned[13] = Pinned[14] = Pinned[15] = NULL_DIR; squareT kingSq = GetKingSquare (ToMove); colorT enemy = color_Flip (ToMove); pieceT enemyQueen = piece_Make (enemy, QUEEN); pieceT enemyRook = piece_Make (enemy, ROOK); pieceT enemyBishop = piece_Make (enemy, BISHOP); // Pins and checks from Bishops/Queens/Rooks: fyleT fyle = square_Fyle (kingSq); if (FyleCount(enemyQueen,fyle) + FyleCount(enemyRook,fyle) > 0) { CalcPinsDir (UP, ROOK); CalcPinsDir (DOWN, ROOK); } rankT rank = square_Rank (kingSq); if (RankCount(enemyQueen,rank) + RankCount(enemyRook,rank) > 0) { CalcPinsDir (LEFT, ROOK); CalcPinsDir (RIGHT, ROOK); } leftDiagT ld = square_LeftDiag (kingSq); if (LeftDiagCount(enemyQueen,ld) + LeftDiagCount(enemyBishop,ld) > 0) { CalcPinsDir (UP_LEFT, BISHOP); CalcPinsDir (DOWN_RIGHT, BISHOP); } rightDiagT rd = square_RightDiag (kingSq); if (RightDiagCount(enemyQueen,rd) + RightDiagCount(enemyBishop,rd) > 0) { CalcPinsDir (UP_RIGHT, BISHOP); CalcPinsDir (DOWN_LEFT, BISHOP); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenPieceMoves(): // Generates moves for a nonpawn, nonking piece. // If sqset != NULL, moves must be to a square in sqset.< void Position::GenPieceMoves (MoveList * mlist, squareT fromSq, SquareSet * sqset, bool capturesOnly) { colorT c = ToMove; pieceT p = Board[fromSq]; pieceT ptype = piece_Type(p); ASSERT (p != EMPTY && ptype != KING && ptype != PAWN); if (ptype == KNIGHT) { GenKnightMoves (mlist, c, fromSq, sqset, capturesOnly); return; } if (ptype != BISHOP) { GenSliderMoves (mlist, c, fromSq, UP, sqset, capturesOnly); GenSliderMoves (mlist, c, fromSq, DOWN, sqset, capturesOnly); GenSliderMoves (mlist, c, fromSq, LEFT, sqset, capturesOnly); GenSliderMoves (mlist, c, fromSq, RIGHT, sqset, capturesOnly); } if (ptype != ROOK) { GenSliderMoves (mlist, c, fromSq, UP_LEFT, sqset, capturesOnly); GenSliderMoves (mlist, c, fromSq, DOWN_LEFT, sqset, capturesOnly); GenSliderMoves (mlist, c, fromSq, UP_RIGHT, sqset, capturesOnly); GenSliderMoves (mlist, c, fromSq, DOWN_RIGHT, sqset, capturesOnly); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenerateMoves // Generate the legal moves list. // If the specified pieceType is not EMPTY, then only legal // moves for that type of piece are generated. void Position::GenerateMoves (MoveList* mlist, pieceT pieceType, genMovesT genType, bool maybeInCheck) { ASSERT(mlist != NULL); bool genNonCaptures = (genType & GEN_NON_CAPS); bool capturesOnly = !genNonCaptures; uint mask = 0; if (pieceType != EMPTY) { mask = 1 << pieceType; } else { mask = (1 << KING) | (1 << QUEEN) | (1 << ROOK) | (1 << BISHOP) | (1 << KNIGHT) | (1 << PAWN); } // Use the objects own move list if none was provided: mlist->Clear(); // Compute which pieces of the side to move are pinned to the king: CalcPins(); // Determine if the side to move is in check and find where the // checking pieces are, unless the caller has passed maybeInCheck=false // indicating it is CERTAIN the side to move is not in check here. uint numChecks = 0; if (maybeInCheck) { SquareList checkSquares; numChecks = CalcNumChecks (GetKingSquare(ToMove), &checkSquares); if (numChecks > 0) { // The side to move IS in check: GenCheckEvasions (mlist, pieceType, genType, &checkSquares); return; } } // The side to move is NOT in check. Iterate over each non-king // piece, and then generate King moves last of all: uint npieces = Count[ToMove]; for (uint x = 1; x < npieces; x++) { squareT sq = List[ToMove][x]; pieceT p = Board[sq]; pieceT ptype = piece_Type(p); if (! (mask & (1 << ptype))) { continue; } directionT pinned = Pinned[x]; // If Pinned[x] == dir (not NULL_DIR), x can ONLY move along // that direction or its opposite. if (pinned != NULL_DIR) { // piece x is pinned to king if (ptype == PAWN) { GenPawnMoves (mlist, sq, pinned, NULL, genType); } else if (ptype == KNIGHT) { // do nothing -- pinned knights cannot move } else { // Piece is a pinned Queen/Rook/Bishop. Only generate // moves along the pinned direction and its opposite: if (ptype == QUEEN || (ptype == ROOK && !direction_IsDiagonal(pinned)) || (ptype == BISHOP && direction_IsDiagonal(pinned))) { GenSliderMoves (mlist, ToMove, sq, pinned, NULL, capturesOnly); GenSliderMoves (mlist, ToMove, sq, dirOpposite[pinned], NULL, capturesOnly); } } } else { // This piece is free to move anywhere if (ptype == PAWN) { GenPawnMoves (mlist, sq, NULL_DIR, NULL, genType); } else { // Knight/Queen/Bishop/Rook: GenPieceMoves (mlist, sq, NULL, capturesOnly); } } } // Lastly, king moves... if (mask & (1 << KING)) { bool castling = !numChecks; GenKingMoves (mlist, genType, castling); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::IsLegalMove // Determines whether the specified move is legal in this position, // without requiring move generation (except for castling moves). bool Position::IsLegalMove (simpleMoveT * sm) { squareT from = sm->from; squareT to = sm->to; if (from > H8 || to > H8) { return false; } if (from == to) { return false; } pieceT mover = Board[from]; pieceT captured = Board[to]; if (piece_Color(mover) != ToMove) { return false; } if (piece_Color(captured) == ToMove) { return false; } if (sm->movingPiece != mover) { return false; } mover = piece_Type (mover); if (sm->promote != EMPTY && mover != PAWN) { return false; } if (mover == PAWN) { rankT rfrom = square_Rank(from); rankT rto = square_Rank(to); if (ToMove == BLACK) { rfrom = RANK_8 - rfrom; rto = RANK_8 - rto; } int rdiff = (int)rto - (int)rfrom; int fdiff = (int)square_Fyle(to) - (int)square_Fyle(from); if (rdiff < 1 || rdiff > 2) { return false; } if (fdiff < -1 || fdiff > 1) { return false; } if (fdiff == 0) { // Pawn push: if (captured != EMPTY) { return false; } if (rdiff == 2) { // Two-square push: if (rfrom != RANK_2) { return false; } // Make sure the square in between is empty: squareT midsquare = from + ((to - from) / 2); if (Board[midsquare] != EMPTY) { return false; } } } else { // Pawn capture: if (rdiff != 1) { return false; } if (captured == EMPTY) { // It must be en passant, or illegal if (to != EPTarget) { return false; } } } // Check the promotion piece: if (rto == RANK_8) { pieceT p = sm->promote; if (p != QUEEN && p != ROOK && p != BISHOP && p != KNIGHT) { return false; } } else { if (sm->promote != EMPTY) { return false; } } } else if (piece_IsSlider(mover)) { // Make sure the direction is valid: directionT dir = sqDir[from][to]; if (dir == NULL_DIR) { return false; } if (mover == ROOK && direction_IsDiagonal(dir)) { return false; } if (mover == BISHOP && !direction_IsDiagonal(dir)) { return false; } int delta = direction_Delta (dir); // Make sure all the in-between squares are empty: squareT dest = from + delta; while (dest != to) { if (Board[dest] != EMPTY) { return false; } dest += delta; } } else if (mover == KNIGHT) { if (! square_IsKnightHop (from, to)) { return false; } } else /* (mover == KING) */ { colorT enemy = color_Flip(ToMove); if (! square_Adjacent (from, to)) { // The move must be castling, or illegal. if (IsKingInCheck()) { return false; } MoveList mlist; GenCastling (&mlist); return std::find(mlist.begin(), mlist.end(), cmpMove(*sm)) != mlist.end(); } if (square_Adjacent (to, GetKingSquare(enemy))) { return false; } } // The move looks good, but does it leave the king in check? squareT kingSq = (mover == KING) ? to : GetKingSquare(ToMove); colorT enemy = color_Flip(ToMove); DoSimpleMove (sm); uint nchecks = CalcAttacks (enemy, kingSq, NULL); UndoSimpleMove (sm); return (nchecks == 0); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::MatchPawnMove(): // Sets the LegalMoves list to contain the matching pawn move, // if there is one. // errorT Position::MatchPawnMove (MoveList * mlist, fyleT fromFyle, squareT to, pieceT promote) { ASSERT(mlist != NULL); mlist->Clear(); sint diff = (int)square_Fyle(to) - (int)fromFyle; if (diff < -1 || diff > 1) { return ERROR_InvalidMove; } pieceT pawn; rankT toRank = square_Rank(to); fyleT toFyle = square_Fyle(to); rankT promoteRank = (ToMove == WHITE ? RANK_8 : RANK_1); // from is the from square; backup is the alternative from square // for a pawn move two squares forward. squareT from, backup = NS; if (ToMove == WHITE) { pawn = WP; if (toRank < RANK_3) { return ERROR_InvalidMove; } from = square_Make(fromFyle, toRank - 1); if (toRank == RANK_4 && fromFyle == toFyle) { backup = to - 16; } } else { pawn = BP; if (toRank > RANK_6) { return ERROR_InvalidMove; } from = square_Make(fromFyle, toRank + 1); if (toRank == RANK_5 && fromFyle == toFyle) { backup = to + 16; } } // See if the promotion piece is valid: if (toRank == promoteRank) { // if (promote == EMPTY) { return ERROR_InvalidMove; } if (promote == EMPTY) { // autopromote to queen promote = QUEEN; } } else { if (promote != EMPTY) { return ERROR_InvalidMove; } } if (Board[from] != pawn) { // No match; but it could be a foward-two-squares move: if (backup == NS || Board[from] != EMPTY || Board[backup] != pawn) { // A forward-two-squares move is impossible. return ERROR_InvalidMove; } from = backup; } // OK, now 'from' is the only possible from-square. Is the move legal? // We make the move on the board and see if the King is in check. uint legal = 0; if (fromFyle == toFyle) { // Not a capture: if (Board[to] != EMPTY) { return ERROR_InvalidMove; } Board[to] = pawn; Board[from] = EMPTY; if (CalcNumChecks (GetKingSquare()) == 0) { legal = 1; } Board[to] = EMPTY; Board[from] = pawn; } else { // It is a capture -- is it legal? pieceT captured = Board[to]; if (captured == EMPTY) { // Must be an en passant or illegal move. if (to != EPTarget) { return ERROR_InvalidMove; } squareT epSquare = square_Make(toFyle, square_Rank(from)); pieceT enemyPawn = piece_Make (color_Flip(ToMove), PAWN); // If following assert fails, eptarget was corrupt ASSERT (Board[epSquare] == enemyPawn); Board[to] = pawn; Board[from] = EMPTY; Board[epSquare] = EMPTY; Material[enemyPawn] --; if (CalcNumChecks (GetKingSquare()) == 0) { legal = 1; } Board[epSquare] = enemyPawn; Board[to] = EMPTY; Board[from] = pawn; Material[enemyPawn]++; } else { if (piece_Color(captured) == ToMove) { // Capturing a friendly! return ERROR_InvalidMove; } else { // A regular capture. See if it leaves King in check: Board[to] = pawn; Board[from] = EMPTY; Material[captured]--; if (CalcNumChecks (GetKingSquare()) == 0) { legal = 1; } Material[captured]++; Board[to] = captured; Board[from] = pawn; } } } if (legal == 1) { AddLegalMove (mlist, from, to, promote); return OK; } return ERROR_InvalidMove; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::GenCheckEvasions(): // Generate legal moves for the side to move when the // King is in check. // void Position::GenCheckEvasions (MoveList * mlist, pieceT mask, genMovesT genType, SquareList * checkSquares) { ASSERT(mlist != NULL); uint numChecks = checkSquares->Size(); // Assert that king IS actually in check: ASSERT (numChecks > 0); bool genNonCaptures = (genType & GEN_NON_CAPS); bool capturesOnly = !genNonCaptures; mlist->Clear(); squareT king = GetKingSquare (ToMove); // if it's double check, we can ONLY move the king if (numChecks == 1) { // OK, it is NOT a double check // Try to block piece/capture piece. Remember en passant! // First, generate a list of targets: squares between the king // and attacker to block, and the attacker's square. squareT attackSq = checkSquares->Get(0); directionT dir = sqDir[king][attackSq]; SquareSet targets; // Set of blocking/capturing squares. targets.Add(attackSq); // Now add squares we can might be able to block on. if (dir != NULL_DIR) { squareT sq = square_Move (king, dir); while (sq != attackSq) { if (Board[sq] == EMPTY) { targets.Add(sq); } sq = square_Move (sq, dir); } } // Try each non-King piece in turn. If a piece is pinned to // the king, don't bother since it cannot possibly block or // capture the piece that is giving check! uint numPieces = Count[ToMove]; for (uint p2 = 1; p2 < numPieces; p2++) { squareT from = List[ToMove][p2]; pieceT p2piece = Board[from]; if (Pinned[p2] != NULL_DIR) { continue; } if (mask == EMPTY || mask == piece_Type(p2piece)) { if (piece_Type(p2piece) == PAWN) { GenPawnMoves (mlist, from, NULL_DIR, &targets, genType); // Capturing a pawn en passant will only get out // of check if the pawn that moved two squares // is doing the checking. If it is not, that means // a discovered check with the last pawn move so // taking en passant cannot get out of check. if (EPTarget != NULL_SQUARE) { squareT pawnSq = (ToMove == WHITE ? EPTarget - 8 : EPTarget + 8); if (pawnSq == attackSq) { SquareSet epset; epset.Add(EPTarget); GenPawnMoves (mlist, from, NULL_DIR, &epset, genType); } } } else { GenPieceMoves (mlist, from, &targets, capturesOnly); } } } // end of search for captures/blocks } // Now king moves -- just compute them normally: if (mask == EMPTY || mask == KING) { GenKingMoves(mlist, genType, false); } return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::TreeCalcAttacks(): // Calculate attack score for a side on a square, // using a recursive tree search. int Position::TreeCalcAttacks(colorT side, squareT target) { int maxScore = -2; uint moveCount = 0, zeroCount = 0; MoveList moveList; GenerateCaptures(&moveList); for (uint i=0; i < moveList.Size(); i++) { simpleMoveT *smPtr = moveList.Get(i); if (smPtr->to == target) { if (piece_IsKing(Board[target])) return -1; moveCount++; DoSimpleMove(smPtr); int score = TreeCalcAttacks(color_Flip(side), target); UndoSimpleMove(smPtr); if (!score && ++zeroCount > 1) return -2; if (score > maxScore) maxScore = score; } } if (!moveCount) return 0; if (!maxScore) return -1; return -maxScore; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::CalcAttacks(): // Calculate the number of attacks by a side on a square. // This function also puts a list of the attacking piece squares // in the fromSqs parameter if it is non-NULL. // // It ONLY uses the Board[] and Material[] lists of the Position, and // ASSUMES they are correct with respect to each other, but it does // NOT use the List[] or ListPos[] information. // This allows us to move pieces quickly (altering only Board[] and // Material[]) and detect whether they leave the king in check, // without having to update other information. uint Position::CalcAttacks (colorT side, squareT target, SquareList * fromSquares) const { // If squares is NULL, caller doesn't want a list of the squares of // attacking pieces. To avoid comparing fromSquares with NULL every time // we find a check, we set up a local array to use instead if fromSquares // is NULL. SquareList fromSqs; if (fromSquares == NULL) { fromSquares = &fromSqs; } fromSquares->Clear(); squareT sq; // Bishop/Queen/Rook attacks: look at each of the 8 directions pieceT king, queen, rook, bishop, knight; if (side == WHITE) { king = WK; queen = WQ; rook = WR; bishop = WB; knight = WN; } else { king = BK; queen = BQ; rook = BR; bishop = BB; knight = BN; } uint numQueensRooks = Material[queen] + Material[rook]; uint numQueensBishops = Material[queen] + Material[bishop]; // We only bother if there are any sliding pieces of each type: if (numQueensRooks > 0) { fyleT fyle = square_Fyle (target); rankT rank = square_Rank (target); directionT dirs[4]; uint ndirs = 0; if (FyleCount(queen,fyle) + FyleCount(rook,fyle) > 0) { dirs[ndirs++] = UP; dirs[ndirs++] = DOWN; } if (RankCount(queen,rank) + RankCount(rook,rank) > 0) { dirs[ndirs++] = LEFT; dirs[ndirs++] = RIGHT; } for (uint i = 0; i < ndirs; i++) { directionT dir = dirs[i]; int delta = direction_Delta (dir); squareT dest = target; squareT last = square_Last (target, dir); while (dest != last) { dest += delta; pieceT p = Board[dest]; if (p == EMPTY) { // empty square: keep searching } else if (p == queen || p == rook) { // Found an attacking piece fromSquares->Add(dest); break; } else { // Found a piece, but not a queen or rook break; } } } } // Now diagonal sliders: Queens/Bishops: if (numQueensBishops > 0) { leftDiagT left = square_LeftDiag (target); rightDiagT right = square_RightDiag (target); directionT dirs[4]; uint ndirs = 0; if (LeftDiagCount(queen,left) + LeftDiagCount(bishop,left) > 0) { dirs[ndirs++] = UP_LEFT; dirs[ndirs++] = DOWN_RIGHT; } if (RightDiagCount(queen,right) + RightDiagCount(bishop,right) > 0) { dirs[ndirs++] = UP_RIGHT; dirs[ndirs++] = DOWN_LEFT; } for (uint i = 0; i < ndirs; i++) { directionT dir = dirs[i]; int delta = direction_Delta (dir); squareT dest = target; squareT last = square_Last (target, dir); while (dest != last) { dest += delta; pieceT p = Board[dest]; if (p == EMPTY) { // empty square: keep searching } else if (p == queen || p == bishop) { // Found an attacking piece fromSquares->Add(dest); break; } else { // Found a piece, but not an enemy queen or bishop break; } } } } // Now knight checks: we only bother if there is a knight on the // opposite square color of the target square color. if (Material[knight] > 0 && SquareColorCount(knight, color_Flip(square_Color(target))) > 0) { const squareT * destPtr = knightAttacks[target]; while (true) { squareT dest = *destPtr; if (dest == NULL_SQUARE) { break; } if (Board[dest] == knight) { fromSquares->Add(dest); } destPtr++; } } // Now pawn attacks: if (side == WHITE) { if (square_Rank(target) != RANK_1) { //if (Material[WP] > 0) { sq = square_Move (target, DOWN_LEFT); if (Board[sq] == WP) { fromSquares->Add(sq); } sq = square_Move (target, DOWN_RIGHT); if (Board[sq] == WP) { fromSquares->Add(sq); } } } else { if (square_Rank(target) != RANK_8) { //if (Material[BP] > 0) { sq = square_Move (target, UP_LEFT); if (Board[sq] == BP) { fromSquares->Add(sq); } sq = square_Move (target, UP_RIGHT); if (Board[sq] == BP) { fromSquares->Add(sq); } } } // King attacks: const squareT *destPtr = kingAttacks[target]; do if (Board[*destPtr] == king) fromSquares->Add(*destPtr); while (*++destPtr != NULL_SQUARE); return fromSquares->Size(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::IsKingInCheckDir // Returns true if the King of the side to move is attacked // by an enemy sliding piece (Queen/Rook/Bishop) from the // specified direction. bool Position::IsKingInCheckDir (directionT dir) { ASSERT (dir != NULL_DIR); squareT kingSq = GetKingSquare(ToMove); colorT enemy = color_Flip(ToMove); bool isDiagonal = direction_IsDiagonal(dir); pieceT queen = piece_Make (enemy, QUEEN); pieceT slider = piece_Make (enemy, (isDiagonal ? BISHOP : ROOK)); // First, make sure the enemy has sliding pieces that could give check: uint nSliders = PieceCount(queen) + PieceCount(slider); if (nSliders == 0) { return false; } // Now make sure the enemy has a sliding piece on the appropriate // rank, file or diagonal: fyleT fyle = square_Fyle (kingSq); rankT rank = square_Rank (kingSq); leftDiagT ldiag = square_LeftDiag (kingSq); rightDiagT rdiag = square_RightDiag (kingSq); switch (dir) { case UP: case DOWN: nSliders = FyleCount(queen,fyle) + FyleCount(slider,fyle); break; case LEFT: case RIGHT: nSliders = RankCount(queen,rank) + RankCount(slider,rank); break; case UP_LEFT: case DOWN_RIGHT: nSliders = LeftDiagCount(queen,ldiag) + LeftDiagCount(slider,ldiag); break; case UP_RIGHT: case DOWN_LEFT: nSliders = RightDiagCount(queen,rdiag) + RightDiagCount(slider,rdiag); break; } if (nSliders == 0) { return false; } // Now move along the specified direction looking for a checking piece: squareT dest = kingSq; squareT last = square_Last (kingSq, dir); int delta = direction_Delta (dir); while (dest != last) { dest += delta; pieceT p = Board[dest]; if (p == EMPTY) { // empty square: keep searching } else if (p == queen || p == slider) { // Found an checking slider piece return true; } else { // Found a piece, but not an enemy queen or rook/bishop break; } } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::IsKingInCheck // Returns true if the king of the side to move is in check. // If the specified move is not NULL, it must be the legal move // that the opponent played to reach this position. This will // be used as a speed optimization, by skipping cases where the // move could not have left the king in check. // bool Position::IsKingInCheck (simpleMoveT * sm) { if (sm == NULL) { return IsKingInCheck(); } squareT kingSq = GetKingSquare(ToMove); pieceT p = piece_Type (sm->movingPiece); if (sm->promote != EMPTY) { p = piece_Type(sm->promote); } // No optimization of the last move was castling: if (p == KING && square_Fyle(sm->from) == E_FYLE) { fyleT toFyle = square_Fyle(sm->to); if (toFyle == C_FYLE || toFyle == G_FYLE) { return IsKingInCheck(); } } // No optimization for en passant capture: if (p == PAWN && piece_Type(sm->capturedPiece) == PAWN) { rankT fromRank = square_Rank(sm->from); rankT capturedRank = square_Rank(sm->capturedSquare); if (fromRank == capturedRank) { return IsKingInCheck(); } } if (p == PAWN) { if (ToMove == WHITE) { if (Material[BP] > 0) { squareT sq = square_Move (kingSq, UP_LEFT); if (Board[sq] == BP) { return true; } sq = square_Move (kingSq, UP_RIGHT); if (Board[sq] == BP) { return true; } } } else { if (Material[WP] > 0) { squareT sq = square_Move (kingSq, DOWN_LEFT); if (Board[sq] == WP) { return true; } sq = square_Move (kingSq, DOWN_RIGHT); if (Board[sq] == WP) { return true; } } } } else if (p == KNIGHT) { if (square_IsKnightHop (kingSq, sm->to)) { return true; } } else if (p == KING) { // A king cannot directly check its adversary. } else { // A sliding piece: directionT toDir = sqDir[kingSq][sm->to]; if (toDir != NULL_DIR && IsKingInCheckDir(toDir)) { return true; } } // Now look for a discovered check from a sliding piece: directionT dir = sqDir[kingSq][sm->from]; if (dir != NULL_DIR && IsKingInCheckDir(dir)) { return true; } ASSERT (IsKingInCheck() == false); return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::Mobility // Returns the number of squares a rook or bishop of the specified // color would attack from the specified square. uint Position::Mobility (pieceT p, colorT color, squareT from) { ASSERT (p == ROOK || p == BISHOP); uint mobility = 0; directionT rookDirs[4] = { UP, DOWN, LEFT, RIGHT }; directionT bishopDirs[4] = { UP_LEFT, UP_RIGHT, DOWN_LEFT, DOWN_RIGHT }; directionT * dirPtr = (p == ROOK ? rookDirs : bishopDirs); for (uint i=0; i < 4; i++) { directionT dir = dirPtr[i]; int delta = direction_Delta (dir); squareT dest = from; squareT last = square_Last (from, dir); while (dest != last) { dest += delta; pieceT p = Board[dest]; if (p == EMPTY) { // Empty square mobility++; } else if (piece_Color(p) == color) { // Friendly piece break; // Finished with this direction. } else { // Enemy piece mobility++; break; // Finished with this direction. } } } return mobility; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::IsKingInMate(): // Quick check if king is in mate. // bool Position::IsKingInMate (void) { SquareList checkSquares; uint numChecks = CalcNumChecks (GetKingSquare(ToMove), &checkSquares); if (numChecks == 0) { return false; } CalcPins (); MoveList mlist; GenCheckEvasions (&mlist, EMPTY, GEN_ALL_MOVES, &checkSquares); if (mlist.Size() == 0) { return true; } return false; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::IsLegal() // Verifies the position as being legal. // Returns false for any of the following: // - if the two kings are adjacent; // - if there are any pawns on the 1st/8th rank; // - if the side to move is already checking the enemy king. bool Position::IsLegal (void) { squareT stmKing = GetKingSquare(); squareT enemyKing = GetEnemyKingSquare(); if (square_Adjacent (stmKing, enemyKing)) { return false; } if (RankCount (WP, RANK_1) != 0) { return false; } if (RankCount (WP, RANK_8) != 0) { return false; } if (RankCount (BP, RANK_1) != 0) { return false; } if (RankCount (BP, RANK_8) != 0) { return false; } if (CalcAttacks (ToMove, enemyKing, NULL) > 0) { return false; } return true; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::IsPromoMove(): // Returns true if the move is a promotion move. // NOTE that the move may not actually be legal! // The arguments 'from' and 'to' can be in either order. bool Position::IsPromoMove (squareT from, squareT to) { rankT seventh, eighth; pieceT pawn; if (ToMove == WHITE) { seventh = RANK_7; eighth = RANK_8; pawn = WP; } else { seventh = RANK_2; eighth = RANK_1; pawn = BP; } rankT fromR, toR; fromR = square_Rank(from); toR = square_Rank(to); if ( (fromR == seventh && toR == eighth && Board[from] == pawn) || (toR == seventh && fromR == eighth && Board[to] == pawn) ) { return 1; } return 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::DoSimpleMove(): // Make the move on the board and update all the necessary // fields in the simpleMove structure so it can be undone. // void Position::DoSimpleMove (simpleMoveT * sm) { ASSERT (sm != NULL); // The caller must have set the first 4 members of sm const squareT from = sm->from; const squareT to = sm->to; const auto promo = sm->promote; const auto ptype = piece_Type(sm->movingPiece); const auto pieceNum = ListPos[from]; // update move fields that (maybe) have not yet been set: sm->pieceNum = pieceNum; sm->capturedPiece = Board[to]; sm->capturedSquare = to; sm->castleFlags = Castling; sm->epSquare = EPTarget; sm->oldHalfMoveClock = HalfMoveClock; HalfMoveClock++; PlyCounter++; auto finalUpdate = [&](auto enPassantSq) { EPTarget = enPassantSq; ToMove = color_Flip(ToMove); }; auto addPiece = [&](auto idx, auto pieceType, squareT destSq) { List[ToMove][idx] = destSq; ListPos[destSq] = idx; AddToBoard(piece_Make(ToMove, pieceType), destSq); }; if (sm->isNullMove()) return finalUpdate(NULL_SQUARE); if (ptype == KING) { ClearCastlingFlags(ToMove); if (auto castleSide = sm->isCastle()) { squareT rookfrom, rookto; if (castleSide == 1) { rookfrom = castlingRookSq(ToMove); rookto = to - 1; } else { rookfrom = castlingRookSq(ToMove); rookto = to + 1; } const int kingIdx = 0; const int rookIdx = ListPos[rookfrom]; RemoveFromBoard(piece_Make(ToMove, ROOK), rookfrom); RemoveFromBoard(piece_Make(ToMove, KING), GetKingSquare(ToMove)); addPiece(kingIdx, KING, to); addPiece(rookIdx, ROOK, rookto); sm->pieceNum = kingIdx; sm->capturedPiece = EMPTY; return finalUpdate(NULL_SQUARE); } } colorT enemy = color_Flip(ToMove); ASSERT(ptype == piece_Type(Board[from])); // Handle en passant capture: if (ptype == PAWN && sm->capturedPiece == EMPTY && square_Fyle(from) != square_Fyle(to)) { // This was an EP capture. We do not need to check it was a capture // since if a pawn lands on EPTarget it must capture to get there. sm->capturedSquare = (ToMove == WHITE ? (to - 8) : (to + 8)); ASSERT (Board[sm->capturedSquare] == piece_Make(enemy, PAWN)); sm->capturedPiece = Board[sm->capturedSquare]; } // handle captures: if (sm->capturedPiece != EMPTY) { ASSERT (piece_Type(sm->capturedPiece) != KING); sm->capturedNum = ListPos[sm->capturedSquare]; // update opponents List of pieces Count[enemy]--; ListPos[List[enemy][Count[enemy]]] = sm->capturedNum; List[enemy][sm->capturedNum] = List[enemy][Count[enemy]]; Material[sm->capturedPiece]--; HalfMoveClock = 0; RemoveFromBoard (sm->capturedPiece, sm->capturedSquare); } // now make the move: ASSERT(sm->movingPiece == Board[from]); const pieceT movingPiece = Board[from]; RemoveFromBoard(movingPiece, from); if (promo != EMPTY) { ASSERT(movingPiece == piece_Make(ToMove, PAWN)); Material[movingPiece]--; Material[piece_Make(ToMove, promo)]++; addPiece(pieceNum, promo, to); } else { addPiece(pieceNum, ptype, to); } // Handle clearing of castling flags: if (Castling) { // See if a rook moved or was captured: if (from == castlingRookSq(ToMove)) SetCastling(ToMove, QSIDE, false); if (from == castlingRookSq(ToMove)) SetCastling(ToMove, KSIDE, false); if (to == castlingRookSq(enemy)) SetCastling(enemy, QSIDE, false); if (to == castlingRookSq(enemy)) SetCastling(enemy, KSIDE, false); } // Set the EPTarget square, if a pawn advanced two squares and an // enemy pawn is on a square where en passant may be possible. EPTarget = NULL_SQUARE; if (ptype == PAWN) { rankT fromRank = square_Rank(from); rankT toRank = square_Rank(to); if (fromRank == RANK_2 && toRank == RANK_4 && (Board[square_Move(to,LEFT)] == BP || Board[square_Move(to,RIGHT)] == BP)) { EPTarget = square_Move(from, UP); } if (fromRank == RANK_7 && toRank == RANK_5 && (Board[square_Move(to,LEFT)] == WP || Board[square_Move(to,RIGHT)] == WP)) { EPTarget = square_Move(from, DOWN); } HalfMoveClock = 0; // 50-move clock resets on pawn moves. } ToMove = enemy; return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::UndoSimpleMove(): // Take back a simple move that has been made with DoSimpleMove(). // void Position::UndoSimpleMove (simpleMoveT const* m) { ASSERT (m != NULL); const squareT from = m->from; const squareT to = m->to; const auto pieceNum = ListPos[to]; pieceT p = Board[to]; EPTarget = m->epSquare; Castling = m->castleFlags; HalfMoveClock = m->oldHalfMoveClock; PlyCounter--; ToMove = color_Flip(ToMove); // Check for a null move: if (m->isNullMove()) { return; } auto addPiece = [&](auto idx, auto pieceType, squareT destSq) { List[ToMove][idx] = destSq; ListPos[destSq] = idx; AddToBoard(piece_Make(ToMove, pieceType), destSq); }; // handle Castling: if (piece_Type(p) == KING) { if (auto castleSide = m->isCastle()) { squareT rookfrom, rookto; if (castleSide == 1) { rookfrom = to - 1; rookto = castlingRookSq(ToMove); } else { rookfrom = to + 1; rookto = castlingRookSq(ToMove); } const int kingIdx = 0; const int rookIdx = ListPos[rookfrom]; RemoveFromBoard(piece_Make(ToMove, KING), GetKingSquare(ToMove)); RemoveFromBoard(piece_Make(ToMove, ROOK), rookfrom); addPiece(rookIdx, ROOK, rookto); addPiece(kingIdx, KING, castlingKingSq(ToMove)); return; } } // Handle a capture: insert piece back into piecelist. // This works for EP captures too, since the square of the captured // piece is in the "capturedSquare" field rather than assuming the // value of the "to" field. The only time these two fields are // different is for an en passant move. if (m->capturedPiece != EMPTY) { colorT c = color_Flip(ToMove); ListPos[List[c][m->capturedNum]] = Count[c]; ListPos[m->capturedSquare] = m->capturedNum; List[c][Count[c]] = List[c][m->capturedNum]; List[c][m->capturedNum] = m->capturedSquare; Material[m->capturedPiece]++; Count[c]++; } // handle promotion: if (m->promote != EMPTY) { Material[p]--; RemoveFromBoard (p, to); p = piece_Make(ToMove, PAWN); Material[p]++; AddToBoard (p, to); } // now make the move: List[ToMove][pieceNum] = from; ListPos[from] = pieceNum; RemoveFromBoard (p, to); AddToBoard (p, from); if (m->capturedPiece != EMPTY) { AddToBoard (m->capturedPiece, m->capturedSquare); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::RelocatePiece(): // Given a from-square and to-square, modifies the position so // the piece on the from-square is relocated to the to-square. // Returns an error if the from square is empty, or the target // square is not empty, or the relocation would otherwise // produce an illegal position (e.g. pawn on the 1st or 8th rank // or a King in check). // errorT Position::RelocatePiece (squareT fromSq, squareT toSq) { // Must have on-board squares: if (fromSq == NS || toSq == NS) { return ERROR; } // If squares are identical, just return success: if (fromSq == toSq) { return OK; } pieceT piece = Board[fromSq]; pieceT ptype = piece_Type(piece); colorT pcolor = piece_Color(piece); // Must be relocating a nonempty piece to an empty square: if (piece == EMPTY || Board[toSq] != EMPTY) { return ERROR; } // Pawns cannot relocate to the first or last rank: if (ptype == PAWN) { rankT toRank = square_Rank(toSq); if (toRank == RANK_1 || toRank == RANK_8) { return ERROR; } } // Locate the piece index in the appropriate list of pieces: uint index = ListPos[fromSq]; ASSERT(List[pcolor][index] == fromSq); // Relocate the piece: List[pcolor][index] = toSq; ListPos[toSq] = index; RemoveFromBoard (piece, fromSq); AddToBoard (piece, toSq); // Check for adjacent kings or side to move giving check: if (! IsLegal()) { // Undo the relocation and return error: List[pcolor][index] = fromSq; RemoveFromBoard (piece, toSq); AddToBoard (piece, fromSq); return ERROR; } // Relocation successful: return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::MaterialValue(): // Returns the sum value of material for a particular side, // where piece values are: // King: 0 (since both sides always have one) // Queen: 9 // Rook: 5 // Bishop, Knight: 3 each // Pawn: 1 uint Position::MaterialValue (colorT c) { ASSERT (c == WHITE || c == BLACK); uint value = 0; if (c == WHITE) { value += 9 * PieceCount(WQ); value += 5 * PieceCount(WR); value += 3 * PieceCount(WB); value += 3 * PieceCount(WN); value += 1 * PieceCount(WP); } else { value += 9 * PieceCount(BQ); value += 5 * PieceCount(BR); value += 3 * PieceCount(BB); value += 3 * PieceCount(BN); value += 1 * PieceCount(BP); } return value; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::MakeSANString(): // Make the SAN string for a simpleMove. // The parameter 'sanFlag' indicates whether '+' and '#' symbols // should be added to checking or mating moves. // void Position::MakeSANString (simpleMoveT * m, char * s, sanFlagT flag) { ASSERT (m != NULL && s != NULL); auto isOccupied = [this](auto square) { return Board[square] != EMPTY; }; ASSERT(m->from == List[ToMove][ListPos[m->from]]); const squareT from = m->from; const squareT to = m->to; char * c = s; pieceT piece = Board[from]; pieceT p = piece_Type(piece); if (p == PAWN) { if (square_Fyle(from) != square_Fyle(to)) { // pawn capture *c++ = square_FyleChar(from); *c++ = 'x'; } *c++ = square_FyleChar(to); *c++ = square_RankChar(to); if ((square_Rank(to)==RANK_1) || (square_Rank(to)==RANK_8)) { *c++ = '='; *c++ = piece_Char(m->promote); p = piece_Type(m->promote); } } else if (p == KING) { if (m->isNullMove()) { //*c++ = 'n'; *c++ = 'u'; *c++ = 'l'; *c++ = 'l'; *c++ = '-'; *c++ = '-'; } else { switch (m->isCastle()) { case 0: *c++ = 'K'; if (Board[to] != EMPTY) *c++ = 'x'; *c++ = square_FyleChar(to); *c++ = square_RankChar(to); break; case 1: *c++ = 'O'; *c++ = '-'; *c++ = 'O'; break; case 2: *c++ = 'O'; *c++ = '-'; *c++ = 'O'; *c++ = '-'; *c++ = 'O'; break; } } } else { // Queen/Rook/Bishop/Knight *c++ = piece_Char(p); // We only need to calculate legal moves to disambiguate if there // are more than one of this type of piece. if (Material[piece] > 1) { int ambiguity = 0; for (uint i = 1, n = Count[ToMove]; i < n; i++) { squareT sq = List[ToMove][i]; if (sq == from || Board[sq] != piece) continue; if (!movegen::pseudo(sq, to, ToMove, p, isOccupied)) continue; // Skip illegal move const auto pin = movegen::opens_ray(sq, to, GetKingSquare(), isOccupied); if (pin.first != INVALID_PIECE && piece_Color_NotEmpty(Board[pin.second]) != ToMove) { pieceT pt = piece_Type(Board[pin.second]); if (pt == QUEEN || pt == pin.first) continue; // Skip pinned piece } // Ambiguity: // 1 (0001) --> need from-file (preferred) or from-rank // 3 (0011) --> need from-file // 5 (0101) --> need from-rank // 7 (0111) --> need both from-file and from-rank ambiguity |= 1; if (square_Rank(from) == square_Rank(sq)) { ambiguity |= 2; // 0b0010 } else if (square_Fyle(from) == square_Fyle(sq)) { ambiguity |= 4; // 0b0100 } } if (ambiguity) { if (ambiguity != 5) *c++ = square_FyleChar(from); // print from-fyle if (ambiguity >= 5) *c++ = square_RankChar(from); // print from-rank } } if (Board[to] != EMPTY) *c++ = 'x'; *c++ = square_FyleChar(to); *c++ = square_RankChar(to); } bool check; if (flag != SAN_NO_CHECKTEST) { squareT oldTo = Board[to]; Board[to] = Board[from]; Board[from] = EMPTY; squareT enemyKingSq = GetEnemyKingSquare(); check = (p != KING) && movegen::attack(to, enemyKingSq, ToMove, p, isOccupied); if (!check) { bool enpassant = (p == PAWN && oldTo == EMPTY && square_Fyle(from) != square_Fyle(to)); if (!enpassant && (p != KING || !m->isCastle()) && !movegen::attack_slider(from, enemyKingSq, QUEEN, isOccupied)) { flag = SAN_NO_CHECKTEST; } } else if (flag != SAN_MATETEST) { *c++ = '+'; flag = SAN_NO_CHECKTEST; } Board[from] = Board[to]; Board[to] = oldTo; } // Now do the check or mate symbol: if (flag != SAN_NO_CHECKTEST) { // Now we make the move to test for check: DoSimpleMove (m); if (check || CalcNumChecks(GetKingSquare()) > 0) { char ch = '+'; if (flag == SAN_MATETEST) { MoveList mlist; GenerateMoves (&mlist); if (mlist.Size() == 0) { ch = '#'; } } *c++ = ch; } UndoSimpleMove (m); } *c = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::ReadCoordMove(): // Given a move in coordinate notation, // e.g. "e2e4" or "g1f3", generates the legal move it represents. // Returns: OK or ERROR_InvalidMove. // If "reverse" is true, coordinates in reverse order are acceptable, // e.g. "f3g1" for 1.Nf3. // errorT Position::ReadCoordMove(simpleMoveT* m, const char* str, int slen, bool reverse) { ASSERT (m != NULL && str != NULL); fyleT fromFyle, toFyle; rankT fromRank, toRank; squareT from, to; pieceT promo = EMPTY; if (slen == 5) { promo = piece_FromChar(toupper(str[4])); } else if (slen != 4) { return ERROR_InvalidMove; } fromFyle = fyle_FromChar (str[0]); fromRank = rank_FromChar (str[1]); from = square_Make (fromFyle, fromRank); if (from == NS) { return ERROR_InvalidMove; } toFyle = fyle_FromChar (str[2]); toRank = rank_FromChar (str[3]); to = square_Make (toFyle, toRank); if (to == NS) { return ERROR_InvalidMove; } MoveList mlist; GenerateMoves(&mlist); for (size_t i = 0, n = mlist.Size(); i < n; i++) { simpleMoveT* sm = mlist.Get(i); if (sm->promote == promo) { if (sm->from == from && sm->to == to) { *m = *sm; return OK; } if (reverse && sm->to == from && sm->from == to) { *m = *sm; return OK; } } } return ERROR_InvalidMove; } static int trimCheck(const char* str, int slen) { while (slen > 0) { // trim mate '#' or check '+' --slen; if (str[slen] != '#' && str[slen] != '+') { ++slen; break; } } return slen; } errorT Position::ReadMovePawn(simpleMoveT* sm, const char* str, int slen, fyleT frFyle) { ASSERT(sm != NULL && str != NULL && frFyle <= H_FYLE); slen = trimCheck(str, slen); if (slen < 2) return ERROR_InvalidMove; auto is_digit = [](char ch) { return isdigit(static_cast(ch)); }; auto is_lower = [](char ch) { return islower(static_cast(ch)); }; if (slen >= 4 && // Check if it is a coordinates-style move ("e2e4") is_digit(str[1]) && is_lower(str[2]) && is_digit(str[3])) { return ReadCoordMove(sm, str, slen, false); } MoveList mlist; pieceT promo = EMPTY; auto last_ch = static_cast(str[slen - 1]); if (!is_digit(last_ch)) { // Promotion, last char must be Q/R/B/N. promo = piece_FromChar(toupper(last_ch)); if (promo != QUEEN && promo != ROOK && promo != KNIGHT && promo != BISHOP) { return ERROR_InvalidMove; } slen--; // Accept the move even if it is of the form "a8Q" not "a8=Q": if (str[slen - 1] == '=') { slen--; } } if (slen < 2) return ERROR_InvalidMove; // Check for the compact form of capture with no rank, // e.g. "ed" or "de=Q": if (slen == 2 && (str[1] >= 'a' && str[1] <= 'h')) { auto toFyle = fyle_FromChar(str[1]); // Check each rank in turn, looking for the capture: for (rankT r = RANK_1; r <= RANK_8; r++) { auto to = square_Make(toFyle, r); if (MatchPawnMove(&mlist, frFyle, to, promo) == OK) { *sm = *(mlist.Get(0)); return OK; } } // It is NOT a valid capture with no rank: return ERROR_InvalidMove; } auto toFyle = fyle_FromChar(str[slen - 2]); auto toRank = rank_FromChar(str[slen - 1]); if (toRank == NO_RANK || toFyle == NO_FYLE) return ERROR_InvalidMove; auto to = square_Make(toFyle, toRank); if (MatchPawnMove(&mlist, frFyle, to, promo) != OK) return ERROR_InvalidMove; *sm = *(mlist.Get(0)); return OK; } errorT Position::ReadMoveKing(simpleMoveT* sm, const char* str, int slen) { ASSERT(sm != NULL && str != NULL); slen = trimCheck(str, slen); if (slen < 3 || slen > 6) return ERROR_InvalidMove; auto toRank = rank_FromChar(str[slen - 1]); auto toFyle = fyle_FromChar(str[slen - 2]); if (toRank == NO_RANK || toFyle == NO_FYLE) return ERROR_InvalidMove; auto target = square_Make(toFyle, toRank); squareT kingSq = GetKingSquare(ToMove); if (!movegen::valid_king(kingSq, target)) return ERROR_InvalidMove; pieceT captured = Board[target]; if (captured != EMPTY && (piece_Color_NotEmpty(captured) == ToMove || piece_Type(captured) == KING)) { return ERROR_InvalidMove; } // XXX We should also check for adjacency to enemy King!! if (movegen::valid_king(GetKingSquare(color_Flip(ToMove)), target)) return ERROR_InvalidMove; // Now make the move on the Board and Material lists, and see if it // leaves the King in check: auto movingPiece = piece_Make(ToMove, KING); Board[target] = movingPiece; Board[kingSq] = EMPTY; if (captured != EMPTY) { Material[captured]--; } auto nChecks = CalcNumChecks(target); if (captured != EMPTY) { Material[captured]++; } Board[target] = captured; Board[kingSq] = movingPiece; if (nChecks) return ERROR_InvalidMove; sm->from = kingSq; sm->to = target; sm->promote = EMPTY; sm->movingPiece = movingPiece; return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::ReadMove(): // Given a move in (possibly sloppy) PGN notation, // generates the legal move it corresponds to. // Returns: OK or ERROR_InvalidMove. // errorT Position::ReadMove(simpleMoveT* sm, const char* str, int slen, pieceT piece) { ASSERT(sm != NULL && str != NULL); ASSERT(piece == QUEEN || piece == ROOK || piece == BISHOP || piece == KNIGHT); slen = trimCheck(str, slen); if (slen < 3 || slen > 6) return ERROR_InvalidMove; auto toRank = rank_FromChar(str[slen - 1]); auto toFyle = fyle_FromChar(str[slen - 2]); if (toRank == NO_RANK || toFyle == NO_FYLE) return ERROR_InvalidMove; auto to = square_Make(toFyle, toRank); pieceT captured = Board[to]; if (captured != EMPTY && (piece_Color_NotEmpty(captured) == ToMove || piece_Type(captured) == KING)) { return ERROR_InvalidMove; } auto frFyle = NO_FYLE; auto frRank = NO_RANK; if (slen > 3) { // There is some ambiguity information in the input string. frFyle = fyle_FromChar(str[1]); frRank = rank_FromChar(str[1]); if (frRank == NO_RANK && slen > 4) { frRank = rank_FromChar(str[2]); } } // Loop through looking for pieces of the corresponding type. We start at 1 // since the King is always the piece at position 0 in the list. int matchCount = 0; auto movingPiece = piece_Make(ToMove, piece); int nPieces = Material[movingPiece]; squareT kingSq = GetKingSquare(ToMove); for (unsigned i = 1, n = Count[ToMove]; i < n && nPieces; i++) { auto from = List[ToMove][i]; if (Board[from] != movingPiece) continue; --nPieces; if ((frFyle != NO_FYLE && frFyle != square_Fyle(from)) || (frRank != NO_RANK && frRank != square_Rank(from))) continue; auto isOccupied = [this](auto sq) { return Board[sq] != EMPTY; }; if (!movegen::pseudo(from, to, ToMove, piece, isOccupied)) continue; const auto pin = movegen::opens_ray(from, to, kingSq, isOccupied); if (pin.first != INVALID_PIECE) { auto p = Board[pin.second]; if (piece_Color_NotEmpty(p) != ToMove && (piece_Type(p) == QUEEN || piece_Type(p) == pin.first)) continue; } ++matchCount; sm->from = from; sm->to = to; sm->promote = EMPTY; sm->movingPiece = movingPiece; } return (matchCount == 1) ? OK // ok. : ERROR_InvalidMove; // No match, or too many // (ambiguous) moves match. } errorT Position::ReadMoveCastle(simpleMoveT* sm, const char* str, int slen) { slen = trimCheck(str, slen); auto str_equal = [&](const char* const_str, const int len) { return slen == len && std::equal(str, str + len, const_str); }; sm->from = square_Relative(ToMove, E1); sm->promote = EMPTY; sm->movingPiece = piece_Make(ToMove, KING); sm->capturedPiece = EMPTY; if (str_equal("O-O", 3) || str_equal("OO", 2)) { sm->to = sm->from + 2; if (!IsKingInCheck() && validCastling(true, true)) // short castle return GetCastling(ToMove, KSIDE) ? OK : ERROR_CastlingAvailability; return validCastling(true, false) ? ERROR_CastlingAvailability : ERROR_InvalidMove; } if (str_equal("O-O-O", 5) || str_equal("OOO", 3)) { sm->to = sm->from - 2; if (!IsKingInCheck() && validCastling(false, true)) // long castle return GetCastling(ToMove, QSIDE) ? OK : ERROR_CastlingAvailability; return validCastling(false, false) ? ERROR_CastlingAvailability : ERROR_InvalidMove; } return ERROR_InvalidMove; } errorT Position::ParseMove(simpleMoveT* sm, const char* str) { while (!isalpha(static_cast(*str)) && *str != '\0') { str++; // trim left } const char* begin = str; while (!isspace(static_cast(*str)) && *str != '\0') { str++; // trim right } return ParseMove(sm, begin, str); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::ParseMove(): // Parse a single move from SAN-style notation. // errorT Position::ParseMove(simpleMoveT* sm, const char* str, const char* strEnd) { ASSERT(str != NULL); int length = static_cast(std::distance(str, strEnd)); if (length < 2 || length > 9) return ERROR_InvalidMove; switch (str[0]) { case 'a': return ReadMovePawn(sm, str, length, A_FYLE); case 'b': return ReadMovePawn(sm, str, length, B_FYLE); case 'c': return ReadMovePawn(sm, str, length, C_FYLE); case 'd': return ReadMovePawn(sm, str, length, D_FYLE); case 'e': return ReadMovePawn(sm, str, length, E_FYLE); case 'f': return ReadMovePawn(sm, str, length, F_FYLE); case 'g': return ReadMovePawn(sm, str, length, G_FYLE); case 'h': return ReadMovePawn(sm, str, length, H_FYLE); case 'K': return ReadMoveKing(sm, str, length); case 'Q': return ReadMove(sm, str, length, QUEEN); case 'R': return ReadMove(sm, str, length, ROOK); case 'B': return ReadMove(sm, str, length, BISHOP); case 'N': return ReadMove(sm, str, length, KNIGHT); case 'O': return ReadMoveCastle(sm, str, length); } // Check for a null move: if ((length == 2 && std::equal(str, str + 2, "--")) || (length == 2 && std::equal(str, str + 2, "Z0")) || (length == 4 && std::equal(str, str + 4, "null"))) { sm->from = GetKingSquare(ToMove); sm->to = sm->from; sm->movingPiece = Board[sm->from]; sm->promote = EMPTY; return OK; } // Invalid move, check for a misspelled first char: switch (str[0]) { case 'A': return ReadMovePawn(sm, str, length, A_FYLE); case 'C': return ReadMovePawn(sm, str, length, C_FYLE); case 'D': return ReadMovePawn(sm, str, length, D_FYLE); case 'E': return ReadMovePawn(sm, str, length, E_FYLE); case 'F': return ReadMovePawn(sm, str, length, F_FYLE); case 'G': return ReadMovePawn(sm, str, length, G_FYLE); case 'H': return ReadMovePawn(sm, str, length, H_FYLE); case 'P': return ParseMove(sm, str + 1, strEnd); case 'k': return ReadMoveKing(sm, str, length); case 'q': return ReadMove(sm, str, length, QUEEN); case 'r': return ReadMove(sm, str, length, ROOK); case 'n': return ReadMove(sm, str, length, KNIGHT); } return ERROR_InvalidMove; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::CalcSANStrings(): // Calculate the SAN string for each move in the legal moves list. // void Position::CalcSANStrings (sanListT *sanList, sanFlagT flag) { MoveList mlist; GenerateMoves(&mlist); for (size_t i = 0, n = mlist.Size(); i < n; i++) { MakeSANString(mlist.Get(i), sanList->list[i], flag); } sanList->num = mlist.Size(); sanList->current = true; } errorT Position::ReadFromLongStr (const char * str) { pieceT pieceFromByte [256] = {EMPTY}; pieceFromByte [(int) 'K'] = WK; pieceFromByte [(int) 'k'] = BK; pieceFromByte [(int) 'Q'] = WQ; pieceFromByte [(int) 'q'] = BQ; pieceFromByte [(int) 'R'] = WR; pieceFromByte [(int) 'r'] = BR; pieceFromByte [(int) 'B'] = WB; pieceFromByte [(int) 'b'] = BB; pieceFromByte [(int) 'N'] = WN; pieceFromByte [(int) 'n'] = BN; pieceFromByte [(int) 'P'] = WP; pieceFromByte [(int) 'p'] = BP; Clear(); for (squareT sq=A1; sq <= H8; sq++) { if (str[sq] == '.') { continue; } pieceT p = pieceFromByte [(byte) str[sq]]; if (p == EMPTY) { return ERROR_Corrupt; } if (AddPiece (p,sq) != OK) { return ERROR_Corrupt; } } switch (str[65]) { case 'w': SetToMove (WHITE); break; case 'b': SetToMove (BLACK); break; default: return ERROR_Corrupt; } return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::MakeLongStr(): // Make a string representing the board. It will be 66 characters // long, encoding the 64 squares (in the order a1,b1,...,g8,h8 // with white pieces in upper case, black pieces in lower case, // and empty squares as dots) then a space, and finally "w" or "b" // indicating the side to move. Example for the starting position: // "RNBQKBNRPPPPPPPP................................pppppppprbnqkbnr w" // void Position::MakeLongStr (char * str) { ASSERT (str != NULL); char * s = str; for (squareT sq = A1; sq <= H8; sq++) { *s++ = PIECE_CHAR[Board[sq]]; } *s++ = ' '; *s++ = (ToMove == WHITE ? 'w' : 'b'); *s = 0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::ReadFromCompactStr(): // Sets the position from the provided Null-terminated 33-byte // compact string. // The first 32 bytes contain the square valued, 4 bits per value, // for the square order A1, B1, ...., G8, H8. // The next byte contains the side to move, 1 for White or 2 for Black. // The final two bytes contain castling and en passant rights. // To ensure no bytes within the staring are zero-valued (so it // can be used as a regular null-terminated string), the value 1 // is added to the color, castling and en passant fields. errorT Position::ReadFromCompactStr (const byte * str) { Clear(); for (uint i=0; i < 32; i++) { pieceT p = str[i] >> 4; if (p != EMPTY) { if (AddPiece (p, i * 2) != OK) { return ERROR_Corrupt; } } p = str[i] & 15; if (p != EMPTY) { if (AddPiece (p, i * 2 + 1) != OK) { return ERROR_Corrupt; } } } colorT toMove = str[32] - 1; if (toMove != WHITE && toMove != BLACK) { return ERROR_Corrupt; } ToMove = toMove; Castling = str[33] - 1; EPTarget = str[34] - 1; return OK; } void Position::PrintCompactStr (char * cboard) { for (uint i=0; i < 32; i++) { uint i2 = i << 1; cboard[i] = (byte)(Board[i2] << 4) | Board[i2+1]; } cboard[32] = 1 + ToMove; cboard[33] = 1 + Castling; // Check that there really is an enemy pawn that might // be able to capture to the en passant square. For example, // if the EP square is c6 but there is no white pawn on // b5 or d5, then en passant should be ignored. squareT ep = EPTarget; if (ToMove == WHITE) { if (Board[square_Move (ep, DOWN_LEFT)] != WP && Board[square_Move (ep, DOWN_RIGHT)] != WP) { ep = NULL_SQUARE; } } else { if (Board[square_Move (ep, UP_LEFT)] != BP && Board[square_Move (ep, UP_RIGHT)] != BP) { ep = NULL_SQUARE; } } cboard[34] = 1 + ep; cboard[35] = 0; } void Position::PrintCompactStrFlipped (char * cboard) { for (uint i=0; i < 32; i++) { uint i2 = i << 1; // Flip 1st rank to 8th, etc: i2 = ((7 - (i2)/8) * 8 + ((i2) % 8)); cboard[i] = (byte)(PIECE_FLIP[Board[i2]] << 4) | (byte)(PIECE_FLIP[Board[i2+1]]); } cboard[32] = 1 + color_Flip(ToMove); cboard[33] = 1 + Castling; cboard[34] = 1 + EPTarget; cboard[35] = 0; } /// Setup the position from a FEN string. /// Note: the slashes usually found in Fen strings to mark the start /// of a new row do not need to be present, but if they are, they must /// appear at the actual start of a new row or the string will be /// considered corrupt. /// /// IMPORTANT: the shortcut of having a two-digit number to represent /// a number of empty rows (e.g. "/24/" instead of "/8/8/8/") is NOT /// accepted by this function. /// /// It is not considered an error for the halfmove clock or fullmove /// counter to be invalid, so this routine can also read positions /// from EPD lines (which only share the first four fields with FEN). errorT Position::ReadFromFEN(const char* str) { ASSERT (str != NULL); auto is_space = [](char ch) { return isspace(static_cast(ch)); }; auto skip_spaces = [&]() { while (isspace(*str)) { str++; } }; // pieceFromByte[] converts a character to its piece, e.g. 'k' -> BK. static pieceT pieceFromByte [256]; // Note the first Call to set up the static arrays only once: static int firstCall = 1; if (firstCall) { firstCall = 0; // Set up pieceFromByte[]: for (int i=0; i < 256; i++) { pieceFromByte[i] = EMPTY; } pieceFromByte [(int) 'K'] = WK; pieceFromByte [(int) 'k'] = BK; pieceFromByte [(int) 'Q'] = WQ; pieceFromByte [(int) 'q'] = BQ; pieceFromByte [(int) 'R'] = WR; pieceFromByte [(int) 'r'] = BR; pieceFromByte [(int) 'B'] = WB; pieceFromByte [(int) 'b'] = BB; pieceFromByte [(int) 'N'] = WN; pieceFromByte [(int) 'n'] = BN; pieceFromByte [(int) 'P'] = WP; pieceFromByte [(int) 'p'] = BP; } Clear(); // Piece placement skip_spaces(); for (int row = 7; row >= 0; --row) { for (int col = 0; col < 8;) { const auto ch = *str++; if (ch == '/') { // A FEN string does not have to contain '/'s but if one // appears anywhere except the start of a row, it is an error: if (col != 0) return ERROR_InvalidFEN; } else if (ch > '0' && ch < '9') { col += (ch - '0'); if (col > 8) return ERROR_InvalidFEN; } else { auto piece = pieceFromByte[static_cast(ch)]; if (piece == EMPTY) return ERROR_InvalidFEN; if (AddPiece(piece, static_cast(row * 8 + col)) != OK) return ERROR_InvalidFEN; col++; } } } if (Material[WK] != 1 || Material[BK] != 1) { return ERROR_InvalidFEN; } // Now the side to move: skip_spaces(); switch (*str++) { case 'w': SetToMove (WHITE); break; case 'b': SetToMove (BLACK); break; default: return ERROR_InvalidFEN; } if (! IsLegal()) { return ERROR_InvalidFEN; } // Now the castling flags: skip_spaces(); if (*str == '-') { str++; // do nothing } else if (*str == 0) { // The FEN has no castling field, so just guess that // castling is possible whenever a king and rook are // still on their starting squares: if (Board[E1] == WK) { if (Board[A1] == WR) { SetCastling (WHITE, QSIDE, true); } if (Board[H1] == WR) { SetCastling (WHITE, KSIDE, true); } } if (Board[E8] == BK) { if (Board[A8] == BR) { SetCastling (BLACK, QSIDE, true); } if (Board[H8] == BR) { SetCastling (BLACK, KSIDE, true); } } } else { while (!is_space(*str) && *str != 0) { switch (*str++) { case 'Q': SetCastling (WHITE, QSIDE, true); break; case 'q': SetCastling (BLACK, QSIDE, true); break; case 'K': SetCastling (WHITE, KSIDE, true); break; case 'k': SetCastling (BLACK, KSIDE, true); break; default: return ERROR_InvalidFEN; } } } // Now the EP target: skip_spaces(); if (*str == '-') { EPTarget = NULL_SQUARE; str++; // No EP target } else if (*str) { char fylec = *str++; if (fylec < 'a' || fylec > 'h') { return ERROR_InvalidFEN; } char rankc = *str++; if (rankc != '3' && rankc != '6') { return ERROR_InvalidFEN; } EPTarget = square_Make(fyle_FromChar(fylec), rank_FromChar(rankc)); } // Now the capture/pawn halfmove clock: skip_spaces(); if (*str) { char* end; HalfMoveClock = (ushort)std::max(0l, strtol(str, &end, 10)); str = end; } // Finally, the fullmove counter: skip_spaces(); if (*str) { int i = atoi(str); if (i >= 1) { PlyCounter = (i - 1) * 2; } } if (ToMove == BLACK) { PlyCounter++; } return OK; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::PrintFEN(): // Print the FEN representation of the position. // If flags == FEN_COMPACT, only the board and side-to-move fields // are printed, in compact form (no slashes between rows). // If flags == FEN_BOARD, only the board and side-to-move fields // are printed. // If flags == FEN_CASTLING_EP, the castling and en passant fields // are also printed. // If flags == FEN_ALL_FIELDS, all fields are printed including // the halfmove clock and ply counter. // void Position::PrintFEN(char* str, uint flags) const { ASSERT (str != NULL); uint emptyRun, iRank, iFyle; for (iRank = 0; iRank < 8; iRank++) { const pieceT* pBoard = &(Board[(7 - iRank) * 8]); emptyRun = 0; if (iRank > 0 && flags > FEN_COMPACT) { *str++ = '/'; } for (iFyle = 0; iFyle < 8; iFyle++, pBoard++) { if (*pBoard != EMPTY) { if (emptyRun) { *str++ = (byte) emptyRun + '0'; } emptyRun = 0; *str++ = PIECE_CHAR[*pBoard]; } else { emptyRun++; } } if (emptyRun) { *str++ = (byte) emptyRun + '0'; } } if (flags > FEN_COMPACT) { *str++ = ' '; } *str++ = (ToMove == WHITE ? 'w' : 'b'); *str = 0; if (flags >= FEN_CASTLING_EP) { // Add the castling flags and EP flag as well: *str++ = ' '; if (Castling == 0) { *str++ = '-'; } else { if (GetCastling (WHITE, KSIDE)) { *str++ = 'K'; } if (GetCastling (WHITE, QSIDE)) { *str++ = 'Q'; } if (GetCastling (BLACK, KSIDE)) { *str++ = 'k'; } if (GetCastling (BLACK, QSIDE)) { *str++ = 'q'; } } *str++ = ' '; // Now the EP target square: if (EPTarget == NULL_SQUARE) { *str++ = '-'; } else { *str++ = square_FyleChar (EPTarget); *str++ = square_RankChar (EPTarget); } *str = 0; if (flags >= FEN_ALL_FIELDS) { // Also print the Halfmove and ply counters: *str++ = ' '; sprintf (str, "%d %d", HalfMoveClock, (PlyCounter / 2) + 1); } } return; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::DumpHtmlBoard(): // Prints the board in a format for use in HTML documents. // Assumes that the HTML document will be in a directory that // has a subdirectory bitmapsDir with files "bwr.gif", etc. // The numeric arguments are the pixel width and height for each // square -- if zero, then the bitmaps are not scaled. // The following values define the available HTML styles. // Style 0 has 40x40 non-transparent images in the "bitmaps" directory. // Style 1 has 36x35 non-transparent images in the "bitmaps2" directory. struct htmlStyleT { const char * dir; // directory containing images. uint width; // width value specified in tag. uint height; // height value specified in tag. bool transparent; // True if the style uses transparent images, // with square colors set by "bgcolor". }; void Position::DumpHtmlBoard (DString * dstr, uint style, const char * dir, bool flip) { const uint HTML_DIAG_STYLES = 2; htmlStyleT hs [HTML_DIAG_STYLES]; hs[0].dir = "bitmaps"; hs[0].width = 40; hs[0].height = 40; hs[1].dir = "bitmaps2"; hs[1].width = 36; hs[1].height = 35; if (style >= HTML_DIAG_STYLES) { style = 0; } uint width = hs[style].width; uint height = hs[style].height; uint iRank, iFyle; pieceT * pBoard; if (dir == NULL) { dir = hs[style].dir; } dstr->Append ("

\n"); dstr->Append ("\n"); for (iRank = 0; iRank < 8; iRank++) { dstr->Append ("\n"); pBoard = &(Board[(7 - iRank) * 8]); for (iFyle = 0; iFyle < 8; iFyle++, pBoard++) { pieceT piece = *pBoard; if (flip) { piece = Board[iRank * 8 + (7 - iFyle)]; } dstr->Append (" \n"); } dstr->Append ("\n"); } dstr->Append ("
0) { char temp[40]; snprintf (temp, 40, "width=%u ", width); dstr->Append (temp); } if (height > 0) { char temp[40]; snprintf (temp, 40, "height=%u ", height); dstr->Append (temp); } dstr->Append ("src=\""); dstr->Append (dir); dstr->AddChar ('/'); bool lightSq = ((iRank % 2) == (iFyle % 2)); if (lightSq) { dstr->AddChar ('w'); } else { dstr->AddChar ('b'); } if (piece == EMPTY) { dstr->Append ("sq.gif"); } else { colorT c = piece_Color(piece); dstr->AddChar (c == WHITE ? 'w' : 'b'); dstr->AddChar (tolower (PIECE_CHAR[piece])); dstr->Append (".gif"); } dstr->Append ("\" alt=\""); if (piece == EMPTY) { if (! lightSq) { dstr->Append ("::"); } } else { colorT c = piece_Color(piece); dstr->AddChar (c == WHITE ? 'W' : 'B'); dstr->AddChar (toupper (PIECE_CHAR[piece])); } dstr->Append ("\">
\n"); //if (ToMove == WHITE) { // dstr->Append ("
White to move.\n"); //} else { // dstr->Append ("
Black to move.\n"); //} dstr->Append("

"); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::DumpLatexBoard(): // Prints the board in a format used by a chess package that is // available for the LaTeX or TeX typesetting language. void Position::DumpLatexBoard (DString * dstr, bool flip) { uint iRank, iFyle; pieceT * pBoard; dstr->Append ("\\board{"); for (iRank = 0; iRank < 8; iRank++) { pBoard = &(Board[(7 - iRank) * 8]); for (iFyle = 0; iFyle < 8; iFyle++, pBoard++) { pieceT piece = *pBoard; if (flip) { piece = Board[iRank * 8 + (7 - iFyle)]; } if (piece != EMPTY) { dstr->AddChar (PIECE_CHAR[piece]); } else { // put a space or a '*': dstr->AddChar (((iRank % 2) == (iFyle % 2)) ? ' ' : '*'); } } if (iRank < 7) { dstr->Append ("}\n {"); } else { dstr->AddChar ('}'); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::Compare(): // Compare another position with this one. // sint Position::Compare (Position * p) { int i = 32; byte *p1, *p2; p1 = Board; p2 = p->Board; while (i && *p1 == *p2) { i--; p1++; p2++; } if (p1 < p2) { return -1; } if (p1 > p2) { return 1; } return (ToMove - p->GetToMove()); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Position::Random // Given a string such as "KRPKR" or "KRP-kr", sets up a // random position with that material configuration. inline squareT randomSquare (void) { return rand() % 64; } inline squareT randomPawnSquare (void) { return (rand() % 48) + A2; } errorT Position::Random (const char * material) { pieceT pieces [32]; // List of pieces excluding kings uint nPieces[2] = {0, 0}; // Number of pieces per side excluding kings. uint total = 0; // Total number of pieces excluding kings. colorT side = WHITE; // The material string must start with a king: if (toupper(*material) != 'K') { return ERROR_Corrupt; } material++; // Read the material string: while (1) { char ch = toupper(*material); if (ch == 0) { break; } switch (ch) { case 'K': if (side == BLACK) { return ERROR_Corrupt; } // Seen third king! side = BLACK; break; case 'Q': case 'R': case 'B': case 'N': case 'P': if (nPieces[side] >= 15) { return ERROR_Corrupt; } nPieces[side]++; if (ch == 'P') { pieces[total] = piece_Make (side, PAWN); } else { pieces[total] = piece_Make (side, piece_FromChar(ch)); } total++; break; case ' ': case '-': case '.': case ',': case ':': // Ignore spaces, commas, etc: break; default: return ERROR_Corrupt; } material++; } if (side != BLACK) { return ERROR_Corrupt; } // Never saw Black king! // Generate two non-adjacent king squares: squareT wk = randomSquare(); squareT bk = randomSquare(); while (wk == bk || square_Adjacent (wk, bk)) { bk = randomSquare(); } // Now add all other pieces to empty squares, looping until a legal // position is found: while (1) { Clear(); ToMove = (rand() % 2) ? WHITE : BLACK; AddPiece (WK, wk); AddPiece (BK, bk); for (uint i=0; i < total; i++) { squareT sq; pieceT p = pieces[i]; bool isPawn = (piece_Type(p) == PAWN); while (1) { sq = isPawn ? randomPawnSquare() : randomSquare(); if (Board[sq] == EMPTY) { break; } } // Add this piece on the random empty square: AddPiece (p, sq); } // Generated a random position with kings not adjacent and // every piece on its own square. We can stop at this // attempt if the enemy king is not in check: squareT enemyKing = (ToMove == WHITE) ? bk : wk; if (CalcAttacks (ToMove, enemyKing, NULL) == 0) { break; } } return OK; } ////////////////////////////////////////////////////////////////////// // EOF: position.cpp ////////////////////////////////////////////////////////////////////// chessx-master/dep/scid/code/src/board_def.h0000755000076500000240000001034714666426276017772 0ustar jensstaff/* * Copyright (C) 2000-2004 Shane Hudson.. * * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ /** @file * Constants and definitions of the chess board. */ #pragma once typedef unsigned char pieceT; // e.g ROOK or WK typedef unsigned char colorT; // WHITE or BLACK typedef unsigned char squareT; // e.g. A3 typedef unsigned char rankT; // Chess board rank typedef unsigned char fyleT; // Chess board file //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // PIECES COLORS const unsigned NUM_COLOR_TYPES = 2; const colorT WHITE = 0, BLACK = 1, NOCOLOR = 2; const char COLOR_CHAR[3] = {'W', 'B', '_'}; inline colorT color_Flip(colorT c) { return 1 - c; } inline char color_Char(colorT c) { return COLOR_CHAR[c]; } // PIECE TYPES (without color; same value as a white piece) const pieceT INVALID_PIECE = 0, KING = 1, QUEEN = 2, ROOK = 3, BISHOP = 4, KNIGHT = 5, PAWN = 6; // PIECES: // Note that color(x) == ((x & 0x8) >> 3) and type(x) == (x & 0x7) // EMPTY is deliberately nonzero, and END_OF_BOARD is zero, so that // a board can be used as a regular 0-terminated string, provided // that board[NULL_SQUARE] == END_OF_BOARD, as it always should be. const pieceT EMPTY = 7; const pieceT END_OF_BOARD = 0; const pieceT WK = 1, WQ = 2, WR = 3, WB = 4, WN = 5, WP = 6; const pieceT BK = 9, BQ = 10, BR = 11, BB = 12, BN = 13, BP = 14; inline colorT piece_Color(pieceT p) { return (p == EMPTY) ? NOCOLOR : ((p & 8) >> 3); } // Slightly faster piece_Color when we are sure the piece is not empty: inline colorT piece_Color_NotEmpty(pieceT p) { return (p & 8) >> 3; } inline pieceT piece_Type(pieceT p) { return (p & 7); } inline pieceT piece_Make(colorT c, pieceT p) { return ((c << 3) | (p & 7)); } // PIECE_CHAR[]: array of piece characters, capitals for White pieces. const char PIECE_CHAR[] = "xKQRBNP.xkqrbnpxMm"; inline char piece_Char(pieceT p) { return PIECE_CHAR[piece_Type(p)]; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // SQUARES const squareT A1 = 0, B1 = 1, C1 = 2, D1 = 3, E1 = 4, F1 = 5, G1 = 6, H1 = 7, A2 = 8, B2 = 9, C2 = 10, D2 = 11, E2 = 12, F2 = 13, G2 = 14, H2 = 15, A3 = 16, B3 = 17, C3 = 18, D3 = 19, E3 = 20, F3 = 21, G3 = 22, H3 = 23, A4 = 24, B4 = 25, C4 = 26, D4 = 27, E4 = 28, F4 = 29, G4 = 30, H4 = 31, A5 = 32, B5 = 33, C5 = 34, D5 = 35, E5 = 36, F5 = 37, G5 = 38, H5 = 39, A6 = 40, B6 = 41, C6 = 42, D6 = 43, E6 = 44, F6 = 45, G6 = 46, H6 = 47, A7 = 48, B7 = 49, C7 = 50, D7 = 51, E7 = 52, F7 = 53, G7 = 54, H7 = 55, A8 = 56, B8 = 57, C8 = 58, D8 = 59, E8 = 60, F8 = 61, G8 = 62, H8 = 63, COLOR_SQUARE = 64, NULL_SQUARE = 65, NS = 65; // NS is abbreviation for NULL_SQUARE. const rankT RANK_1 = 0, RANK_2 = 1, RANK_3 = 2, RANK_4 = 3, RANK_5 = 4, RANK_6 = 5, RANK_7 = 6, RANK_8 = 7, NO_RANK = 64; const fyleT // we use "fyle" instead of "file" to avoid confusion with disk files. A_FYLE = 0, B_FYLE = 1, C_FYLE = 2, D_FYLE = 3, E_FYLE = 4, F_FYLE = 5, G_FYLE = 6, H_FYLE = 7, NO_FYLE = 64; inline rankT rank_FromChar(char c) { if (c < '1' || c > '8') { return NO_RANK; } else return (c - '1'); } inline fyleT fyle_FromChar(char c) { if (c < 'a' || c > 'h') { return NO_FYLE; } else return (c - 'a'); } inline squareT square_Make(fyleT f, rankT r) { return ((r << 3) | f); } inline fyleT square_Fyle(squareT sq) { return (sq & 0x7); } inline rankT square_Rank(squareT sq) { return ((sq >> 3) & 0x7); } constexpr squareT square_Relative(colorT c, squareT sq) { return static_cast(sq ^ (c * 56)); } constexpr rankT rank_Relative(colorT c, rankT r) { return static_cast(r ^ (c * 7)); } chessx-master/dep/scid/code/src/stored.cpp0000755000076500000240000007705514666426276017731 0ustar jensstaff/* * Copyright (C) 2014 Fulvio Benini * This file is part of Scid (Shane's Chess Information Database). * * Scid is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * Scid is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Scid. If not, see . */ #include "stored.h" #include // Stored line codes: used to speed up tree searches. // The basic idea is: keep a fixed dictionary of popular opening lines where // move order is significant (e.g. 1.d4 e6 2.e4 is NOT equal to 1.e4 e6 2.d4). // For each game, the longest sequence of initial moves found in the // dictionary is stored in the index file, as an integer value. // When tree-searching for a position, each stored line is searched // first and if an exact match is found for one (and it has a further // move), all games with that stored line code can be found as matches // without decoding. // Furthermore, if we detect that a line cannot possibly lead to a match // because of its end material value or pawn configuration, all games with // that stored line code can be excluded and skipped without decoding. namespace { class Board { pieceT b_[64]; public: Board(const pieceT* b) { for (int i=0; i < 64; i++) b_[i] = b[i]; } void doMove(FullMove m) { //No promo, no null moves, no queenside castle if (! m.isCastle()) { b_[m.getFrom()] = EMPTY; b_[m.getTo()] = piece_Make(m.getColor(), m.getPiece()); } else { b_[m.getFrom()] = EMPTY; b_[m.getTo()] = EMPTY; int black = (m.getColor() == BLACK) ? 56 : 0; b_[black + G1] = piece_Make(m.getColor(), KING); b_[black + F1] = piece_Make(m.getColor(), ROOK); } } bool operator==(const Board& b) const { return (std::memcmp(b_, b.b_, sizeof b_) == 0); } bool neverMatch(const Board& m) const { // Pawns allows to exclude some games: int p[3][8] = {{0}}; for (int i=0; i < 64; i++) { pieceT a = b_[i]; pieceT b = m.b_[i]; // 1) because a pawn will never go back to home position if (b == WP && a != WP && (i/8) == 1) return true; if (b == BP && a != BP && (i/8) == 6) return true; p[piece_Color(a)][piece_Type(a)] += 1; p[piece_Color(b)][piece_Type(b)] -= 1; } int df[2] = {0}; for (pieceT i=QUEEN; i < PAWN; i++) { if (p[WHITE][i] < 0) df[WHITE] -= p[WHITE][i]; if (p[BLACK][i] < 0) df[BLACK] -= p[BLACK][i]; } // 2) because only extra pawns can be promoted to create other pieces. if (p[WHITE][PAWN] < df[WHITE] || p[BLACK][PAWN] < df[BLACK]) return true; return false; } }; constexpr FullMove fm[] = { // "1.b3" 0x6000251, // "1.c4" 0x600029a, // "1.c4 c5" 0x600029a, 0xe000ca2, // "1.c4 c5 2.Nf3" 0x600029a, 0xe000ca2, 0x5000195, // "1.c4 e5" 0x600029a, 0xe000d24, // "1.c4 e5 2.Nc3" 0x600029a, 0xe000d24, 0x5000052, // "1.c4 e5 2.Nc3 Nf6" 0x600029a, 0xe000d24, 0x5000052, 0xd000fad, // "1.c4 e6" 0x600029a, 0xe000d2c, // "1.c4 e6 2.Nf3" 0x600029a, 0xe000d2c, 0x5000195, // "1.c4 g6" 0x600029a, 0xe000dae, // "1.c4 Nf6" 0x600029a, 0xd000fad, // "1.c4 Nf6 2.Nc3" 0x600029a, 0xd000fad, 0x5000052, // "1.c4 Nf6 2.Nc3 e6" 0x600029a, 0xd000fad, 0x5000052, 0xe000d2c, // "1.c4 Nf6 2.Nc3 g6" 0x600029a, 0xd000fad, 0x5000052, 0xe000dae, // "1.d4" 0x60002db, // "1.d4 d5" 0x60002db, 0xe000ce3, // "1.d4 d5 2.c4" 0x60002db, 0xe000ce3, 0x600029a, // "1.d4 d5 2.c4 c6" 0x60002db, 0xe000ce3, 0x600029a, 0xe000caa, // "1.d4 d5 2.c4 c6 3.Nc3" 0x60002db, 0xe000ce3, 0x600029a, 0xe000caa, 0x5000052, // "1.d4 d5 2.c4 c6 3.Nc3 Nf6" 0x60002db, 0xe000ce3, 0x600029a, 0xe000caa, 0x5000052, 0xd000fad, // "1.d4 d5 2.c4 c6 3.Nc3 Nf6 4.Nf3" 0x60002db, 0xe000ce3, 0x600029a, 0xe000caa, 0x5000052, 0xd000fad, 0x5000195, // "1.d4 d5 2.c4 c6 3.Nf3" 0x60002db, 0xe000ce3, 0x600029a, 0xe000caa, 0x5000195, // "1.d4 d5 2.c4 c6 3.Nf3 Nf6" 0x60002db, 0xe000ce3, 0x600029a, 0xe000caa, 0x5000195, 0xd000fad, // "1.d4 d5 2.c4 c6 3.Nf3 Nf6 4.Nc3" 0x60002db, 0xe000ce3, 0x600029a, 0xe000caa, 0x5000195, 0xd000fad, 0x5000052, // "1.d4 d5 2.c4 c6 3.Nf3 Nf6 4.Nc3 e6" 0x60002db, 0xe000ce3, 0x600029a, 0xe000caa, 0x5000195, 0xd000fad, 0x5000052, 0xe000d2c, // "1.d4 d5 2.c4 dxc4" 0x60002db, 0xe000ce3, 0x600029a, 0xec008da, // "1.d4 d5 2.c4 dxc4 3.Nf3" 0x60002db, 0xe000ce3, 0x600029a, 0xec008da, 0x5000195, // "1.d4 d5 2.c4 dxc4 3.Nf3 Nf6" 0x60002db, 0xe000ce3, 0x600029a, 0xec008da, 0x5000195, 0xd000fad, // "1.d4 d5 2.c4 e6" 0x60002db, 0xe000ce3, 0x600029a, 0xe000d2c, // "1.d4 d5 2.c4 e6 3.Nc3" 0x60002db, 0xe000ce3, 0x600029a, 0xe000d2c, 0x5000052, // "1.d4 d5 2.c4 e6 3.Nc3 c6" 0x60002db, 0xe000ce3, 0x600029a, 0xe000d2c, 0x5000052, 0xe000caa, // "1.d4 d5 2.c4 e6 3.Nc3 Nf6" 0x60002db, 0xe000ce3, 0x600029a, 0xe000d2c, 0x5000052, 0xd000fad, // "1.d4 d5 2.c4 e6 3.Nf3" 0x60002db, 0xe000ce3, 0x600029a, 0xe000d2c, 0x5000195, // "1.d4 d5 2.Nf3" 0x60002db, 0xe000ce3, 0x5000195, // "1.d4 d5 2.Nf3 Nf6" 0x60002db, 0xe000ce3, 0x5000195, 0xd000fad, // "1.d4 d5 2.Nf3 Nf6 3.c4" 0x60002db, 0xe000ce3, 0x5000195, 0xd000fad, 0x600029a, // "1.d4 d5 2.Nf3 Nf6 3.c4 c6" 0x60002db, 0xe000ce3, 0x5000195, 0xd000fad, 0x600029a, 0xe000caa, // "1.d4 d5 2.Nf3 Nf6 3.c4 e6" 0x60002db, 0xe000ce3, 0x5000195, 0xd000fad, 0x600029a, 0xe000d2c, // "1.d4 d6" 0x60002db, 0xe000ceb, // "1.d4 d6 2.Nf3" 0x60002db, 0xe000ceb, 0x5000195, // "1.d4 e6" 0x60002db, 0xe000d2c, // "1.d4 e6 2.c4" 0x60002db, 0xe000d2c, 0x600029a, // "1.d4 e6 2.c4 Nf6" 0x60002db, 0xe000d2c, 0x600029a, 0xd000fad, // "1.d4 f5" 0x60002db, 0xe000d65, // "1.d4 f5 2.g3 Nf6 3.Bg2" 0x60002db, 0xe000d65, 0x6000396, 0xd000fad, 0x400014e, // "1.d4 g6" 0x60002db, 0xe000dae, // "1.d4 g6 2.c4 Bg7" 0x60002db, 0xe000dae, 0x600029a, 0xc000f76, // "1.d4 Nf6" 0x60002db, 0xd000fad, // "1.d4 Nf6 2.Bg5" 0x60002db, 0xd000fad, 0x40000a6, // "1.d4 Nf6 2.Bg5 Ne4" 0x60002db, 0xd000fad, 0x40000a6, 0xd000b5c, // "1.d4 Nf6 2.c4" 0x60002db, 0xd000fad, 0x600029a, // "1.d4 Nf6 2.c4 c5" 0x60002db, 0xd000fad, 0x600029a, 0xe000ca2, // "1.d4 Nf6 2.c4 c5 3.d5" 0x60002db, 0xd000fad, 0x600029a, 0xe000ca2, 0x60006e3, // "1.d4 Nf6 2.c4 c5 3.d5 b5" 0x60002db, 0xd000fad, 0x600029a, 0xe000ca2, 0x60006e3, 0xe000c61, // "1.d4 Nf6 2.c4 c5 3.d5 b5 4.cxb5 a6" 0x60002db, 0xd000fad, 0x600029a, 0xe000ca2, 0x60006e3, 0xe000c61, 0x6c006a1, 0xe000c28, // "1.d4 Nf6 2.c4 e6 3.g3" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x6000396, // "1.d4 Nf6 2.c4 e6 3.g3 d5" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x6000396, 0xe000ce3, // "1.d4 Nf6 2.c4 e6 3.Nc3" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000052, // "1.d4 Nf6 2.c4 e6 3.Nc3 Bb4" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000052, 0xc000f59, // "1.d4 Nf6 2.c4 e6 3.Nc3 Bb4 4.e3" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000052, 0xc000f59, 0x6000314, // "1.d4 Nf6 2.c4 e6 3.Nc3 Bb4 4.e3 O-O" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000052, 0xc000f59, 0x6000314, 0x900cf3f, // "1.d4 Nf6 2.c4 e6 3.Nc3 Bb4 4.Qc2" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000052, 0xc000f59, 0x20000ca, // "1.d4 Nf6 2.c4 e6 3.Nc3 Bb4 4.Qc2 O-O" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000052, 0xc000f59, 0x20000ca, 0x900cf3f, // "1.d4 Nf6 2.c4 e6 3.Nc3 Bb4 4.Qc2 O-O 5.a3 Bxc3+ 6.Qxc3" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000052, 0xc000f59, 0x20000ca, 0x900cf3f, 0x6000210, 0x4ca00652, 0x2800292, // "1.d4 Nf6 2.c4 e6 3.Nc3 d5" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000052, 0xe000ce3, // "1.d4 Nf6 2.c4 e6 3.Nf3" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000195, // "1.d4 Nf6 2.c4 e6 3.Nf3 b6" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000195, 0xe000c69, // "1.d4 Nf6 2.c4 e6 3.Nf3 b6 4.a3" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000195, 0xe000c69, 0x6000210, // "1.d4 Nf6 2.c4 e6 3.Nf3 b6 4.g3" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000195, 0xe000c69, 0x6000396, // "1.d4 Nf6 2.c4 e6 3.Nf3 b6 4.g3 Ba6" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000195, 0xe000c69, 0x6000396, 0xc000ea8, // "1.d4 Nf6 2.c4 e6 3.Nf3 Bb4+" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000195, 0x4c000f59, // "1.d4 Nf6 2.c4 e6 3.Nf3 d5" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000195, 0xe000ce3, // "1.d4 Nf6 2.c4 e6 3.Nf3 d5 4.Nc3" 0x60002db, 0xd000fad, 0x600029a, 0xe000d2c, 0x5000195, 0xe000ce3, 0x5000052, // "1.d4 Nf6 2.c4 g6" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, // "1.d4 Nf6 2.c4 g6 3.Nc3 Bg7" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xc000f76, // "1.d4 Nf6 2.c4 g6 3.Nc3 Bg7 4.e4" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xc000f76, 0x600031c, // "1.d4 Nf6 2.c4 g6 3.Nc3 Bg7 4.e4 d6" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xc000f76, 0x600031c, 0xe000ceb, // "1.d4 Nf6 2.c4 g6 3.Nc3 Bg7 4.e4 d6 5.Be2 O-O" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xc000f76, 0x600031c, 0xe000ceb, 0x400014c, 0x900cf3f, // "1.d4 Nf6 2.c4 g6 3.Nc3 Bg7 4.e4 d6 5.Be2 O-O 6.Nf3" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xc000f76, 0x600031c, 0xe000ceb, 0x400014c, 0x900cf3f, 0x5000195, // "1.d4 Nf6 2.c4 g6 3.Nc3 Bg7 4.e4 d6 5.f3" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xc000f76, 0x600031c, 0xe000ceb, 0x6000355, // "1.d4 Nf6 2.c4 g6 3.Nc3 Bg7 4.e4 d6 5.f3 O-O" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xc000f76, 0x600031c, 0xe000ceb, 0x6000355, 0x900cf3f, // "1.d4 Nf6 2.c4 g6 3.Nc3 Bg7 4.e4 d6 5.f3 O-O 6.Be3" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xc000f76, 0x600031c, 0xe000ceb, 0x6000355, 0x900cf3f, 0x4000094, // "1.d4 Nf6 2.c4 g6 3.Nc3 Bg7 4.e4 d6 5.Nf3 O-O" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xc000f76, 0x600031c, 0xe000ceb, 0x5000195, 0x900cf3f, // "1.d4 Nf6 2.c4 g6 3.Nc3 Bg7 4.e4 d6 5.Nf3 O-O 6.Be2" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xc000f76, 0x600031c, 0xe000ceb, 0x5000195, 0x900cf3f, 0x400014c, // "1.d4 Nf6 2.c4 g6 3.Nc3 Bg7 4.e4 d6 5.Nf3 O-O 6.Be2 e5" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xc000f76, 0x600031c, 0xe000ceb, 0x5000195, 0x900cf3f, 0x400014c, 0xe000d24, // "1.d4 Nf6 2.c4 g6 3.Nc3 Bg7 4.e4 d6 5.Nf3 O-O 6.Be2 e5 7.O-O" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xc000f76, 0x600031c, 0xe000ceb, 0x5000195, 0x900cf3f, 0x400014c, 0xe000d24, 0x100c107, // "1.d4 Nf6 2.c4 g6 3.Nc3 Bg7 4.e4 d6 5.Nf3 O-O 6.Be2 e5 7.O-O Nc6 8.d5 Ne7" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xc000f76, 0x600031c, 0xe000ceb, 0x5000195, 0x900cf3f, 0x400014c, 0xe000d24, 0x100c107, 0xd000e6a, 0x60006e3, 0xd000ab4, // "1.d4 Nf6 2.c4 g6 3.Nc3 d5" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xe000ce3, // "1.d4 Nf6 2.c4 g6 3.Nc3 d5 4.Nf3" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xe000ce3, 0x5000195, // "1.d4 Nf6 2.c4 g6 3.Nc3 d5 4.cxd5 Nxd5" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xe000ce3, 0x6c006a3, 0xdc00b63, // "1.d4 Nf6 2.c4 g6 3.Nc3 d5 4.cxd5 Nxd5 5.e4 Nxc3 6.bxc3 Bg7" 0x60002db, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, 0xe000ce3, 0x6c006a3, 0xdc00b63, 0x600031c, 0xda008d2, 0x6a00252, 0xc000f76, // "1.d4 Nf6 2.Nf3" 0x60002db, 0xd000fad, 0x5000195, // "1.d4 Nf6 2.Nf3 c5" 0x60002db, 0xd000fad, 0x5000195, 0xe000ca2, // "1.d4 Nf6 2.Nf3 d5" 0x60002db, 0xd000fad, 0x5000195, 0xe000ce3, // "1.d4 Nf6 2.Nf3 e6" 0x60002db, 0xd000fad, 0x5000195, 0xe000d2c, // "1.d4 Nf6 2.Nf3 e6 3.Bg5" 0x60002db, 0xd000fad, 0x5000195, 0xe000d2c, 0x40000a6, // "1.d4 Nf6 2.Nf3 e6 3.c4" 0x60002db, 0xd000fad, 0x5000195, 0xe000d2c, 0x600029a, // "1.d4 Nf6 2.Nf3 g6" 0x60002db, 0xd000fad, 0x5000195, 0xe000dae, // "1.d4 Nf6 2.Nf3 g6 3.Bg5" 0x60002db, 0xd000fad, 0x5000195, 0xe000dae, 0x40000a6, // "1.d4 Nf6 2.Nf3 g6 3.c4" 0x60002db, 0xd000fad, 0x5000195, 0xe000dae, 0x600029a, // "1.d4 Nf6 2.Nf3 g6 3.c4 Bg7" 0x60002db, 0xd000fad, 0x5000195, 0xe000dae, 0x600029a, 0xc000f76, // "1.d4 Nf6 2.Nf3 g6 3.c4 Bg7 4.Nc3" 0x60002db, 0xd000fad, 0x5000195, 0xe000dae, 0x600029a, 0xc000f76, 0x5000052, // "1.d4 Nf6 2.Nf3 g6 3.c4 Bg7 4.Nc3 O-O" 0x60002db, 0xd000fad, 0x5000195, 0xe000dae, 0x600029a, 0xc000f76, 0x5000052, 0x900cf3f, // "1.d4 Nf6 2.Nf3 g6 3.g3" 0x60002db, 0xd000fad, 0x5000195, 0xe000dae, 0x6000396, // "1.d4 Nf6 2.Nf3 g6 3.g3 Bg7 4.Bg2" 0x60002db, 0xd000fad, 0x5000195, 0xe000dae, 0x6000396, 0xc000f76, 0x400014e, // "1.e4" 0x600031c, // "1.e4 c5" 0x600031c, 0xe000ca2, // "1.e4 c5 2.c3" 0x600031c, 0xe000ca2, 0x6000292, // "1.e4 c5 2.c3 d5 3.exd5 Qxd5 4.d4" 0x600031c, 0xe000ca2, 0x6000292, 0xe000ce3, 0x6c00723, 0xac00ee3, 0x60002db, // "1.e4 c5 2.c3 d5 3.exd5 Qxd5 4.d4 Nf6" 0x600031c, 0xe000ca2, 0x6000292, 0xe000ce3, 0x6c00723, 0xac00ee3, 0x60002db, 0xd000fad, // "1.e4 c5 2.c3 Nf6 3.e5 Nd5" 0x600031c, 0xe000ca2, 0x6000292, 0xd000fad, 0x6000724, 0xd000b63, // "1.e4 c5 2.c3 Nf6 3.e5 Nd5 4.d4 cxd4" 0x600031c, 0xe000ca2, 0x6000292, 0xd000fad, 0x6000724, 0xd000b63, 0x60002db, 0xec0089b, // "1.e4 c5 2.d4 cxd4" 0x600031c, 0xe000ca2, 0x60002db, 0xec0089b, // "1.e4 c5 2.Nc3" 0x600031c, 0xe000ca2, 0x5000052, // "1.e4 c5 2.Nc3 Nc6" 0x600031c, 0xe000ca2, 0x5000052, 0xd000e6a, // "1.e4 c5 2.Nc3 Nc6 3.g3" 0x600031c, 0xe000ca2, 0x5000052, 0xd000e6a, 0x6000396, // "1.e4 c5 2.Nc3 Nc6 3.g3 g6" 0x600031c, 0xe000ca2, 0x5000052, 0xd000e6a, 0x6000396, 0xe000dae, // "1.e4 c5 2.Nc3 Nc6 3.g3 g6 4.Bg2 Bg7" 0x600031c, 0xe000ca2, 0x5000052, 0xd000e6a, 0x6000396, 0xe000dae, 0x400014e, 0xc000f76, // "1.e4 c5 2.Nc3 Nc6 3.g3 g6 4.Bg2 Bg7 5.d3" 0x600031c, 0xe000ca2, 0x5000052, 0xd000e6a, 0x6000396, 0xe000dae, 0x400014e, 0xc000f76, 0x60002d3, // "1.e4 c5 2.Nf3" 0x600031c, 0xe000ca2, 0x5000195, // "1.e4 c5 2.Nf3 d6" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, // "1.e4 c5 2.Nf3 d6 3.Bb5+" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x44000161, // "1.e4 c5 2.Nf3 d6 3.d4" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 a6" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000c28, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 a6 6.Bc4" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000c28, 0x400015a, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 a6 6.Be2" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000c28, 0x400014c, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 a6 6.Be3" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000c28, 0x4000094, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 a6 6.Bg5" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000c28, 0x40000a6, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 a6 6.Bg5 e6" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000c28, 0x40000a6, 0xe000d2c, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 g6" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000dae, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 g6 6.Be3 Bg7 7.f3" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000dae, 0x4000094, 0xc000f76, 0x6000355, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 g6 6.Be3 Bg7 7.f3 O-O" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000dae, 0x4000094, 0xc000f76, 0x6000355, 0x900cf3f, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 Nc6" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xd000e6a, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 Nc6 6.Bg5" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xd000e6a, 0x40000a6, // "1.e4 c5 2.Nf3 d6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 Nc6 6.Bg5 e6 7.Qd2" 0x600031c, 0xe000ca2, 0x5000195, 0xe000ceb, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xd000e6a, 0x40000a6, 0xe000d2c, 0x20000cb, // "1.e4 c5 2.Nf3 e6" 0x600031c, 0xe000ca2, 0x5000195, 0xe000d2c, // "1.e4 c5 2.Nf3 e6 3.d3" 0x600031c, 0xe000ca2, 0x5000195, 0xe000d2c, 0x60002d3, // "1.e4 c5 2.Nf3 e6 3.d4 cxd4 4.Nxd4" 0x600031c, 0xe000ca2, 0x5000195, 0xe000d2c, 0x60002db, 0xec0089b, 0x5c0055b, // "1.e4 c5 2.Nf3 e6 3.d4 cxd4 4.Nxd4 a6" 0x600031c, 0xe000ca2, 0x5000195, 0xe000d2c, 0x60002db, 0xec0089b, 0x5c0055b, 0xe000c28, // "1.e4 c5 2.Nf3 e6 3.d4 cxd4 4.Nxd4 a6 5.Bd3" 0x600031c, 0xe000ca2, 0x5000195, 0xe000d2c, 0x60002db, 0xec0089b, 0x5c0055b, 0xe000c28, 0x4000153, // "1.e4 c5 2.Nf3 e6 3.d4 cxd4 4.Nxd4 Nc6" 0x600031c, 0xe000ca2, 0x5000195, 0xe000d2c, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000e6a, // "1.e4 c5 2.Nf3 e6 3.d4 cxd4 4.Nxd4 Nc6 5.Nc3" 0x600031c, 0xe000ca2, 0x5000195, 0xe000d2c, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000e6a, 0x5000052, // "1.e4 c5 2.Nf3 e6 3.d4 cxd4 4.Nxd4 Nc6 5.Nc3 Qc7" 0x600031c, 0xe000ca2, 0x5000195, 0xe000d2c, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000e6a, 0x5000052, 0xa000ef2, // "1.e4 c5 2.Nf3 e6 3.d4 cxd4 4.Nxd4 Nf6" 0x600031c, 0xe000ca2, 0x5000195, 0xe000d2c, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, // "1.e4 c5 2.Nf3 e6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3" 0x600031c, 0xe000ca2, 0x5000195, 0xe000d2c, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, // "1.e4 c5 2.Nf3 e6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 d6" 0x600031c, 0xe000ca2, 0x5000195, 0xe000d2c, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000ceb, // "1.e4 c5 2.Nf3 Nc6" 0x600031c, 0xe000ca2, 0x5000195, 0xd000e6a, // "1.e4 c5 2.Nf3 Nc6 3.Bb5" 0x600031c, 0xe000ca2, 0x5000195, 0xd000e6a, 0x4000161, // "1.e4 c5 2.Nf3 Nc6 3.Bb5 g6" 0x600031c, 0xe000ca2, 0x5000195, 0xd000e6a, 0x4000161, 0xe000dae, // "1.e4 c5 2.Nf3 Nc6 3.d4 cxd4 4.Nxd4" 0x600031c, 0xe000ca2, 0x5000195, 0xd000e6a, 0x60002db, 0xec0089b, 0x5c0055b, // "1.e4 c5 2.Nf3 Nc6 3.d4 cxd4 4.Nxd4 e5" 0x600031c, 0xe000ca2, 0x5000195, 0xd000e6a, 0x60002db, 0xec0089b, 0x5c0055b, 0xe000d24, // "1.e4 c5 2.Nf3 Nc6 3.d4 cxd4 4.Nxd4 g6" 0x600031c, 0xe000ca2, 0x5000195, 0xd000e6a, 0x60002db, 0xec0089b, 0x5c0055b, 0xe000dae, // "1.e4 c5 2.Nf3 Nc6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3" 0x600031c, 0xe000ca2, 0x5000195, 0xd000e6a, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, // "1.e4 c5 2.Nf3 Nc6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 d6" 0x600031c, 0xe000ca2, 0x5000195, 0xd000e6a, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000ceb, // "1.e4 c5 2.Nf3 Nc6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 d6 6.Bg5" 0x600031c, 0xe000ca2, 0x5000195, 0xd000e6a, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000ceb, 0x40000a6, // "1.e4 c5 2.Nf3 Nc6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 e5" 0x600031c, 0xe000ca2, 0x5000195, 0xd000e6a, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000d24, // "1.e4 c5 2.Nf3 Nc6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 e5 6.Ndb5 d6" 0x600031c, 0xe000ca2, 0x5000195, 0xd000e6a, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000d24, 0x150006e1, 0xe000ceb, // "1.e4 c5 2.Nf3 Nc6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 e5 6.Ndb5 d6 7.Bg5 a6" 0x600031c, 0xe000ca2, 0x5000195, 0xd000e6a, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000d24, 0x150006e1, 0xe000ceb, 0x40000a6, 0xe000c28, // "1.e4 c5 2.Nf3 Nc6 3.d4 cxd4 4.Nxd4 Nf6 5.Nc3 e5 6.Ndb5 d6 7.Bg5 a6 8.Na3 b5" 0x600031c, 0xe000ca2, 0x5000195, 0xd000e6a, 0x60002db, 0xec0089b, 0x5c0055b, 0xd000fad, 0x5000052, 0xe000d24, 0x150006e1, 0xe000ceb, 0x40000a6, 0xe000c28, 0x5000850, 0xe000c61, // "1.e4 c6" 0x600031c, 0xe000caa, // "1.e4 c6 2.d4 d5" 0x600031c, 0xe000caa, 0x60002db, 0xe000ce3, // "1.e4 c6 2.d4 d5 3.e5" 0x600031c, 0xe000caa, 0x60002db, 0xe000ce3, 0x6000724, // "1.e4 c6 2.d4 d5 3.e5 Bf5" 0x600031c, 0xe000caa, 0x60002db, 0xe000ce3, 0x6000724, 0xc000ea5, // "1.e4 c6 2.d4 d5 3.exd5 cxd5" 0x600031c, 0xe000caa, 0x60002db, 0xe000ce3, 0x6c00723, 0xec00aa3, // "1.e4 c6 2.d4 d5 3.exd5 cxd5 4.c4 Nf6 5.Nc3" 0x600031c, 0xe000caa, 0x60002db, 0xe000ce3, 0x6c00723, 0xec00aa3, 0x600029a, 0xd000fad, 0x5000052, // "1.e4 c6 2.d4 d5 3.Nc3" 0x600031c, 0xe000caa, 0x60002db, 0xe000ce3, 0x5000052, // "1.e4 c6 2.d4 d5 3.Nc3 dxe4 4.Nxe4" 0x600031c, 0xe000caa, 0x60002db, 0xe000ce3, 0x5000052, 0xec008dc, 0x5c0049c, // "1.e4 c6 2.d4 d5 3.Nd2 dxe4 4.Nxe4" 0x600031c, 0xe000caa, 0x60002db, 0xe000ce3, 0x500004b, 0xec008dc, 0x5c002dc, // "1.e4 d5 2.exd5 Nf6" 0x600031c, 0xe000ce3, 0x6c00723, 0xd000fad, // "1.e4 d5 2.exd5 Qxd5" 0x600031c, 0xe000ce3, 0x6c00723, 0xac00ee3, // "1.e4 d5 2.exd5 Qxd5 3.Nc3" 0x600031c, 0xe000ce3, 0x6c00723, 0xac00ee3, 0x5000052, // "1.e4 d5 2.exd5 Qxd5 3.Nc3 Qa5" 0x600031c, 0xe000ce3, 0x6c00723, 0xac00ee3, 0x5000052, 0xa0008e0, // "1.e4 d6" 0x600031c, 0xe000ceb, // "1.e4 d6 2.d4" 0x600031c, 0xe000ceb, 0x60002db, // "1.e4 d6 2.d4 Nf6" 0x600031c, 0xe000ceb, 0x60002db, 0xd000fad, // "1.e4 d6 2.d4 Nf6 3.Nc3" 0x600031c, 0xe000ceb, 0x60002db, 0xd000fad, 0x5000052, // "1.e4 d6 2.d4 Nf6 3.Nc3 g6" 0x600031c, 0xe000ceb, 0x60002db, 0xd000fad, 0x5000052, 0xe000dae, // "1.e4 d6 2.d4 Nf6 3.Nc3 g6 4.f4 Bg7 5.Nf3" 0x600031c, 0xe000ceb, 0x60002db, 0xd000fad, 0x5000052, 0xe000dae, 0x600035d, 0xc000f76, 0x5000195, // "1.e4 d6 2.d4 Nf6 3.Nc3 g6 4.Nf3 Bg7" 0x600031c, 0xe000ceb, 0x60002db, 0xd000fad, 0x5000052, 0xe000dae, 0x5000195, 0xc000f76, // "1.e4 e5" 0x600031c, 0xe000d24, // "1.e4 e5 2.f4" 0x600031c, 0xe000d24, 0x600035d, // "1.e4 e5 2.Nc3" 0x600031c, 0xe000d24, 0x5000052, // "1.e4 e5 2.Nf3" 0x600031c, 0xe000d24, 0x5000195, // "1.e4 e5 2.Nf3 Nc6" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, // "1.e4 e5 2.Nf3 Nc6 3.Bb5" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x4000161, // "1.e4 e5 2.Nf3 Nc6 3.Bb5 a6" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x4000161, 0xe000c28, // "1.e4 e5 2.Nf3 Nc6 3.Bb5 a6 4.Ba4" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x4000161, 0xe000c28, 0x4000858, // "1.e4 e5 2.Nf3 Nc6 3.Bb5 a6 4.Ba4 Nf6" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x4000161, 0xe000c28, 0x4000858, 0xd000fad, // "1.e4 e5 2.Nf3 Nc6 3.Bb5 a6 4.Ba4 Nf6 5.O-O" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x4000161, 0xe000c28, 0x4000858, 0xd000fad, 0x100c107, // "1.e4 e5 2.Nf3 Nc6 3.Bb5 a6 4.Ba4 Nf6 5.O-O b5 6.Bb3" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x4000161, 0xe000c28, 0x4000858, 0xd000fad, 0x100c107, 0xe000c61, 0x4000611, // "1.e4 e5 2.Nf3 Nc6 3.Bb5 a6 4.Ba4 Nf6 5.O-O Be7" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x4000161, 0xe000c28, 0x4000858, 0xd000fad, 0x100c107, 0xc000f74, // "1.e4 e5 2.Nf3 Nc6 3.Bb5 a6 4.Ba4 Nf6 5.O-O Be7 6.Re1 b5 7.Bb3 d6" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x4000161, 0xe000c28, 0x4000858, 0xd000fad, 0x100c107, 0xc000f74, 0x3000144, 0xe000c61, 0x4000611, 0xe000ceb, // "1.e4 e5 2.Nf3 Nc6 3.Bb5 a6 4.Ba4 Nf6 5.O-O Be7 6.Re1 b5 7.Bb3 d6 8.c3 O-O" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x4000161, 0xe000c28, 0x4000858, 0xd000fad, 0x100c107, 0xc000f74, 0x3000144, 0xe000c61, 0x4000611, 0xe000ceb, 0x6000292, 0x900cf3f, // "1.e4 e5 2.Nf3 Nc6 3.Bb5 a6 4.Ba4 Nf6 5.O-O Be7 6.Re1 b5 7.Bb3 d6 8.c3 O-O 9.h3" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x4000161, 0xe000c28, 0x4000858, 0xd000fad, 0x100c107, 0xc000f74, 0x3000144, 0xe000c61, 0x4000611, 0xe000ceb, 0x6000292, 0x900cf3f, 0x60003d7, // "1.e4 e5 2.Nf3 Nc6 3.Bb5 a6 4.Ba4 Nf6 5.O-O Be7 6.Re1 b5 7.Bb3 d6 8.c3 O-O 9.h3 Na5 10.Bc2 c5 11.d4" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x4000161, 0xe000c28, 0x4000858, 0xd000fad, 0x100c107, 0xc000f74, 0x3000144, 0xe000c61, 0x4000611, 0xe000ceb, 0x6000292, 0x900cf3f, 0x60003d7, 0xd000aa0, 0x400044a, 0xe000ca2, 0x60002db, // "1.e4 e5 2.Nf3 Nc6 3.Bb5 a6 4.Ba4 Nf6 5.O-O Be7 6.Re1 b5 7.Bb3 O-O" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x4000161, 0xe000c28, 0x4000858, 0xd000fad, 0x100c107, 0xc000f74, 0x3000144, 0xe000c61, 0x4000611, 0x900cf3f, // "1.e4 e5 2.Nf3 Nc6 3.Bb5 Nf6" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x4000161, 0xd000fad, // "1.e4 e5 2.Nf3 Nc6 3.Bc4" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x400015a, // "1.e4 e5 2.Nf3 Nc6 3.Bc4 Nf6" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x400015a, 0xd000fad, // "1.e4 e5 2.Nf3 Nc6 3.d4 exd4" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x60002db, 0xec0091b, // "1.e4 e5 2.Nf3 Nc6 3.d4 exd4 4.Nxd4" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x60002db, 0xec0091b, 0x5c0055b, // "1.e4 e5 2.Nf3 Nc6 3.Nc3" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x5000052, // "1.e4 e5 2.Nf3 Nc6 3.Nc3 Nf6" 0x600031c, 0xe000d24, 0x5000195, 0xd000e6a, 0x5000052, 0xd000fad, // "1.e4 e5 2.Nf3 Nf6" 0x600031c, 0xe000d24, 0x5000195, 0xd000fad, // "1.e4 e5 2.Nf3 Nf6 3.Nxe5 d6" 0x600031c, 0xe000d24, 0x5000195, 0xd000fad, 0x5c00564, 0xe000ceb, // "1.e4 e6" 0x600031c, 0xe000d2c, // "1.e4 e6 2.d3" 0x600031c, 0xe000d2c, 0x60002d3, // "1.e4 e6 2.d4" 0x600031c, 0xe000d2c, 0x60002db, // "1.e4 e6 2.d4 d5" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, // "1.e4 e6 2.d4 d5 3.e5 c5" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x6000724, 0xe000ca2, // "1.e4 e6 2.d4 d5 3.e5 c5 4.c3" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x6000724, 0xe000ca2, 0x6000292, // "1.e4 e6 2.d4 d5 3.Nc3" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x5000052, // "1.e4 e6 2.d4 d5 3.Nc3 Bb4" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x5000052, 0xc000f59, // "1.e4 e6 2.d4 d5 3.Nc3 Bb4 4.e5" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x5000052, 0xc000f59, 0x6000724, // "1.e4 e6 2.d4 d5 3.Nc3 Bb4 4.e5 c5" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x5000052, 0xc000f59, 0x6000724, 0xe000ca2, // "1.e4 e6 2.d4 d5 3.Nc3 Bb4 4.e5 c5 5.a3 Bxc3+ 6.bxc3" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x5000052, 0xc000f59, 0x6000724, 0xe000ca2, 0x6000210, 0x4ca00652, 0x6800252, // "1.e4 e6 2.d4 d5 3.Nc3 Nf6" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x5000052, 0xd000fad, // "1.e4 e6 2.d4 d5 3.Nc3 Nf6 4.Bg5" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x5000052, 0xd000fad, 0x40000a6, // "1.e4 e6 2.d4 d5 3.Nd2" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x500004b, // "1.e4 e6 2.d4 d5 3.Nd2 c5" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x500004b, 0xe000ca2, // "1.e4 e6 2.d4 d5 3.Nd2 Nf6" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x500004b, 0xd000fad, // "1.e4 e6 2.d4 d5 3.Nd2 Nf6 4.e5 Nfd7" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x500004b, 0xd000fad, 0x6000724, 0x1d000b73, // "1.e4 e6 2.d4 d5 3.Nd2 Nf6 4.e5 Nfd7 5.Bd3 c5 6.c3 Nc6 7.Ne2" 0x600031c, 0xe000d2c, 0x60002db, 0xe000ce3, 0x500004b, 0xd000fad, 0x6000724, 0x1d000b73, 0x4000153, 0xe000ca2, 0x6000292, 0xd000e6a, 0x500018c, // "1.e4 g6" 0x600031c, 0xe000dae, // "1.e4 g6 2.d4" 0x600031c, 0xe000dae, 0x60002db, // "1.e4 g6 2.d4 Bg7" 0x600031c, 0xe000dae, 0x60002db, 0xc000f76, // "1.e4 g6 2.d4 Bg7 3.Nc3" 0x600031c, 0xe000dae, 0x60002db, 0xc000f76, 0x5000052, // "1.e4 g6 2.d4 Bg7 3.Nc3 d6" 0x600031c, 0xe000dae, 0x60002db, 0xc000f76, 0x5000052, 0xe000ceb, // "1.e4 Nf6" 0x600031c, 0xd000fad, // "1.e4 Nf6 2.e5 Nd5" 0x600031c, 0xd000fad, 0x6000724, 0xd000b63, // "1.e4 Nf6 2.e5 Nd5 3.d4 d6" 0x600031c, 0xd000fad, 0x6000724, 0xd000b63, 0x60002db, 0xe000ceb, // "1.e4 Nf6 2.e5 Nd5 3.d4 d6 4.Nf3" 0x600031c, 0xd000fad, 0x6000724, 0xd000b63, 0x60002db, 0xe000ceb, 0x5000195, // "1.f4" 0x600035d, // "1.g3" 0x6000396, // "1.Nf3" 0x5000195, // "1.Nf3 c5" 0x5000195, 0xe000ca2, // "1.Nf3 c5 2.c4" 0x5000195, 0xe000ca2, 0x600029a, // "1.Nf3 d5" 0x5000195, 0xe000ce3, // "1.Nf3 d5 2.c4" 0x5000195, 0xe000ce3, 0x600029a, // "1.Nf3 d5 2.d4" 0x5000195, 0xe000ce3, 0x60002db, // "1.Nf3 d5 2.g3" 0x5000195, 0xe000ce3, 0x6000396, // "1.Nf3 g6" 0x5000195, 0xe000dae, // "1.Nf3 Nf6" 0x5000195, 0xd000fad, // "1.Nf3 Nf6 2.c4" 0x5000195, 0xd000fad, 0x600029a, // "1.Nf3 Nf6 2.c4 c5" 0x5000195, 0xd000fad, 0x600029a, 0xe000ca2, // "1.Nf3 Nf6 2.c4 e6" 0x5000195, 0xd000fad, 0x600029a, 0xe000d2c, // "1.Nf3 Nf6 2.c4 g6" 0x5000195, 0xd000fad, 0x600029a, 0xe000dae, // "1.Nf3 Nf6 2.c4 g6 3.Nc3" 0x5000195, 0xd000fad, 0x600029a, 0xe000dae, 0x5000052, // "1.Nf3 Nf6 2.g3" 0x5000195, 0xd000fad, 0x6000396, // "1.Nf3 Nf6 2.g3 g6" 0x5000195, 0xd000fad, 0x6000396, 0xe000dae }; } // End of anonymous namespace const FullMove* StoredLine::Moves_ [STORED_LINES +1] = { // index zero is unused // last index ( Moves_[STORED_LINES] ) is used to detect the end of the array fm + 0, fm + 0, fm + 1, fm + 2, fm + 4, fm + 7, fm + 9, fm + 12, fm + 16, fm + 18, fm + 21, fm + 23, fm + 25, fm + 28, fm + 32, fm + 36, fm + 37, fm + 39, fm + 42, fm + 46, fm + 51, fm + 57, fm + 64, fm + 69, fm + 75, fm + 82, fm + 90, fm + 94, fm + 99, fm + 105, fm + 109, fm + 114, fm + 120, fm + 126, fm + 131, fm + 134, fm + 138, fm + 143, fm + 149, fm + 155, fm + 157, fm + 160, fm + 162, fm + 165, fm + 169, fm + 171, fm + 176, fm + 178, fm + 182, fm + 184, fm + 187, fm + 191, fm + 194, fm + 198, fm + 203, fm + 209, fm + 217, fm + 222, fm + 228, fm + 233, fm + 239, fm + 246, fm + 254, fm + 261, fm + 269, fm + 280, fm + 286, fm + 291, fm + 297, fm + 304, fm + 311, fm + 319, fm + 325, fm + 331, fm + 338, fm + 342, fm + 348, fm + 355, fm + 363, fm + 373, fm + 384, fm + 393, fm + 403, fm + 414, fm + 424, fm + 435, fm + 447, fm + 460, fm + 476, fm + 482, fm + 489, fm + 497, fm + 509, fm + 512, fm + 516, fm + 520, fm + 524, fm + 529, fm + 534, fm + 538, fm + 543, fm + 548, fm + 554, fm + 561, fm + 569, fm + 574, fm + 581, fm + 582, fm + 584, fm + 587, fm + 594, fm + 602, fm + 608, fm + 616, fm + 620, fm + 623, fm + 627, fm + 632, fm + 638, fm + 646, fm + 655, fm + 658, fm + 662, fm + 667, fm + 672, fm + 678, fm + 685, fm + 693, fm + 702, fm + 712, fm + 723, fm + 734, fm + 745, fm + 756, fm + 768, fm + 778, fm + 791, fm + 805, fm + 815, fm + 826, fm + 839, fm + 843, fm + 848, fm + 855, fm + 863, fm + 872, fm + 880, fm + 889, fm + 899, fm + 907, fm + 916, fm + 926, fm + 930, fm + 935, fm + 941, fm + 948, fm + 956, fm + 964, fm + 973, fm + 983, fm + 994, fm +1004, fm +1016, fm +1030, fm +1046, fm +1048, fm +1052, fm +1057, fm +1063, fm +1069, fm +1078, fm +1083, fm +1090, fm +1097, fm +1101, fm +1105, fm +1110, fm +1116, fm +1118, fm +1121, fm +1125, fm +1130, fm +1136, fm +1145, fm +1153, fm +1155, fm +1158, fm +1161, fm +1164, fm +1168, fm +1173, fm +1179, fm +1186, fm +1194, fm +1203, fm +1214, fm +1224, fm +1238, fm +1254, fm +1271, fm +1292, fm +1306, fm +1312, fm +1317, fm +1323, fm +1329, fm +1336, fm +1341, fm +1347, fm +1351, fm +1357, fm +1359, fm +1362, fm +1365, fm +1369, fm +1375, fm +1382, fm +1387, fm +1393, fm +1400, fm +1408, fm +1419, fm +1425, fm +1432, fm +1437, fm +1443, fm +1449, fm +1457, fm +1470, fm +1472, fm +1475, fm +1479, fm +1484, fm +1490, fm +1492, fm +1496, fm +1502, fm +1509, fm +1510, fm +1511, fm +1512, fm +1514, fm +1517, fm +1519, fm +1522, fm +1525, fm +1528, fm +1530, fm +1532, fm +1535, fm +1539, fm +1543, fm +1547, fm +1552, fm +1555, fm +1559 }; StoredLine::StoredLine(const pieceT* board, colorT toMove) { Board search(board); matches_[0] = -1; matches_[STORED_LINES] = -1; for (int line = 1; line < STORED_LINES; line++) { Board b(START_BOARD); const FullMove* end = Moves_[line +1]; for (int ply=0; ply < 99; ply++) { if (((ply %2) == toMove) && b == search) { matches_[line] = ply; break; } const FullMove* m = Moves_[line] + ply; if (m == end) { matches_[line] = b.neverMatch(search) ? -2 : -1; break; } b.doMove(*m); } } } chessx-master/dep/CMakeLists.txt0000755000076500000240000000007214666426276016023 0ustar jensstaffif (ENABLE_SCID_SUPPORT) add_subdirectory(scid) endif() chessx-master/COPYING.md0000755000076500000240000004274714666426276014164 0ustar jensstaff### GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. ### Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. ### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION **0.** This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. **1.** You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. **2.** You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: **a)** You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. **b)** You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. **c)** If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. **3.** You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: **a)** Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, **b)** Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, **c)** Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. **4.** You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. **5.** You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. **6.** Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. **7.** If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. **8.** If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. **9.** The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. **10.** If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. **NO WARRANTY** **11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. **12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. ### END OF TERMS AND CONDITIONS ### How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. one line to give the program's name and an idea of what it does. Copyright (C) yyyy name of author This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands \`show w' and \`show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than \`show w' and \`show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the [GNU Lesser General Public License](https://www.gnu.org/licenses/lgpl.html) instead of this License. chessx-master/chessx.pro0000755000076500000240000004403014666426276014534 0ustar jensstaff# Main application DEFINES += QT_DEPRECATED_WARNINGS CONFIG += uic warn_on sdk_no_version_check QT += network svg TEMPLATE = app greaterThan(QT_MAJOR_VERSION, 4) { QT += printsupport QT += core gui widgets QT += xml QT -= multimediawidgets # Comment out sound for Ubuntu with Qt5 if multimedia is not available (default in Ubuntu) CONFIG += sound # Comment out speech for Linux - there is a bug in Speech which will make ChessX crash (QTBUG-90626) # Also comment out speech if libspeechdis is not available win32|macx { CONFIG += speech } # Scid requires c++17 CONFIG += c++17 # Add lc0 to package # CONFIG += lc0 DEFINES += USE_C11 CONFIG += scid } greaterThan(QT_MAJOR_VERSION, 5) { # Needed for QStringRef etc. QT += core5compat } speech { DEFINES += USE_SPEECH QT += texttospeech } sound { DEFINES += USE_SOUND QT += multimedia } DEFINES += QUAZIP_STATIC DEFINES += QT_NO_CAST_TO_ASCII DEFINES *= QT_USE_QSTRINGBUILDER macx { QMAKE_CXXFLAGS += -fvisibility=hidden QMAKE_LFLAGS_RELEASE -= -O2 QMAKE_LFLAGS_RELEASE += -m64 -Ofast QMAKE_CXXFLAGS_RELEASE -= -O2 QMAKE_CXXFLAGS_RELEASE *= -m64 -Ofast QMAKE_LFLAGS_DEBUG += -m64 -O0 QMAKE_CXXFLAGS_DEBUG *= -m64 -O0 } unix|!macx { isEmpty(PREFIX) { bsd { PREFIX = /usr/local } PREFIX = /usr } BINDIR = $$PREFIX/bin DATADIR = $$PREFIX/share INSTALLS += appdata desktop icons binfiles appdata.files = unix/io.sourceforge.ChessX.metainfo.xml appdata.path = $$DATADIR/metainfo desktop.files = unix/chessx.desktop desktop.path = $$DATADIR/applications icons.path = $$DATADIR/icons/hicolor icons.commands = install -Dm644 data/images/chessx.png $${icons.path}/128x128/apps/chessx.png; \ install -Dm644 data/images/chessx-32.png $${icons.path}/32x32/apps/chessx.png; \ install -Dm644 data/images/chessx-64.png $${icons.path}/64x64/apps/chessx.png; binfiles.files = release/chessx binfiles.path = $$BINDIR # Note: Compile SSL 1.1.1, uncomment the following line and put the lib path here # LIBS += -L/home/parallels/openssl-1.1.1q -lcrypto -lssl } scid { # Scid sources HEADERS += \ dep/scid/code/src/attacks.h \ dep/scid/code/src/board_def.h \ dep/scid/code/src/bytebuf.h \ dep/scid/code/src/codec_native.h \ dep/scid/code/src/codec_scid4.h \ dep/scid/code/src/codec.h \ dep/scid/code/src/common.h \ dep/scid/code/src/containers.h \ dep/scid/code/src/date.h \ dep/scid/code/src/dstring.h \ dep/scid/code/src/error.h \ dep/scid/code/src/fastgame.h \ dep/scid/code/src/filebuf.h \ dep/scid/code/src/fullmove.h \ dep/scid/code/src/game.h \ dep/scid/code/src/hash.h \ dep/scid/code/src/hfilter.h \ dep/scid/code/src/index.h \ dep/scid/code/src/indexentry.h \ dep/scid/code/src/matsig.h \ dep/scid/code/src/misc.h \ dep/scid/code/src/movegen.h \ dep/scid/code/src/movelist.h \ dep/scid/code/src/movetree.h \ dep/scid/code/src/naglatex.h \ dep/scid/code/src/nagtext.h \ dep/scid/code/src/namebase.h \ dep/scid/code/src/position.h \ dep/scid/code/src/sortcache.h \ dep/scid/code/src/sqmove.h \ dep/scid/code/src/stored.h \ dep/scid/code/src/textbuf.h SOURCES += \ dep/scid/code/src/codec_scid4.cpp \ dep/scid/code/src/game.cpp \ dep/scid/code/src/matsig.cpp \ dep/scid/code/src/misc.cpp \ dep/scid/code/src/position.cpp \ dep/scid/code/src/sortcache.cpp \ dep/scid/code/src/stored.cpp \ dep/scid/code/src/textbuf.cpp INCLUDEPATH += dep/scid/code/src # database implementation HEADERS += src/database/scid/sciddatabase.h SOURCES += src/database/scid/sciddatabase.cpp INCLUDEPATH += src/database/scid DEFINES += USE_SCID } FORMS += \ src/dialogs/aboutdlg.ui \ src/dialogs/actiondialog.ui \ src/dialogs/boardsearchdialog.ui \ src/dialogs/commentdialog.ui \ src/dialogs/copydialog.ui \ src/dialogs/databasetagdialog.ui \ src/dialogs/dlgsavebook.ui \ src/dialogs/matchparameterdlg.ui \ src/dialogs/onlinebase.ui \ src/dialogs/preferences.ui \ src/dialogs/promotiondialog.ui \ src/dialogs/quicksearch.ui \ src/dialogs/recipientaddressdialog.ui \ src/dialogs/renametagdialog.ui \ src/dialogs/savedialog.ui \ src/dialogs/tagdialog.ui \ src/dialogs/tournamentselectiondialog.ui \ src/gui/analysiswidget.ui \ src/gui/annotationwidget.ui \ src/gui/boardsetup.ui \ src/gui/boardviewex.ui \ src/gui/engineoptiondialog.ui \ src/gui/ficsconsole.ui \ src/gui/gamewindow.ui \ src/gui/helpbrowsershell.ui \ src/gui/loadquery.ui \ src/gui/openingtreewidget.ui \ src/gui/tagdetailwidget.ui HEADERS += src/database/board.h \ src/database/abk.h \ src/database/analysis.h \ src/database/annotation.h \ src/database/arenabook.h \ src/database/bitboard.h \ src/database/bitfind.h \ src/database/circularbuffer.h \ src/database/clipboarddatabase.h \ src/database/ctg.h \ src/database/ctgbookwriter.h \ src/database/ctgdatabase.h \ src/database/database.h \ src/database/databaseconversion.h \ src/database/databaseinfo.h \ src/database/datesearch.h \ src/database/downloadmanager.h \ src/database/duplicatesearch.h \ src/database/ecoinfo.h \ src/database/ecopositions.h \ src/database/editaction.h \ src/database/elosearch.h \ src/database/enginedata.h \ src/database/enginelist.h \ src/database/engineoptiondata.h \ src/database/engineparameter.h \ src/database/enginex.h \ src/database/eventinfo.h \ src/database/ficsclient.h \ src/database/ficsdatabase.h \ src/database/filter.h \ src/database/filtermodel.h \ src/database/filteroperator.h \ src/database/filtersearch.h \ src/database/gamecursor.h \ src/database/gameid.h \ src/database/gameundocommand.h \ src/database/gamex.h \ src/database/historylist.h \ src/database/index.h \ src/database/indexitem.h \ src/database/lichessopening.h \ src/database/lichessopeningdatabase.h \ src/database/lichesstransfer.h \ src/database/memorydatabase.h \ src/database/move.h \ src/database/movedata.h \ src/database/nag.h \ src/database/networkhelper.h \ src/database/numbersearch.h \ src/database/openingtree.h \ src/database/openingtreethread.h \ src/database/output.h \ src/database/outputoptions.h \ src/database/partialdate.h \ src/database/pdbtest.h \ src/database/pgndatabase.h \ src/database/piece.h \ src/database/playerdata.h \ src/database/playerdatabase.h \ src/database/playerinfo.h \ src/database/polyglotdatabase.h \ src/database/polyglotwriter.h \ src/database/positionsearch.h \ src/database/refcount.h \ src/database/result.h \ src/database/search.h \ src/database/settings.h \ src/database/spellchecker.h \ src/database/square.h \ src/database/streamdatabase.h \ src/database/tablebase.h \ src/database/tags.h \ src/database/tagsearch.h \ src/database/telnetclient.h \ src/database/threadedguess.h \ src/database/uciengine.h \ src/database/version.h \ src/database/wbengine.h \ src/dialogs/aboutdlg.h \ src/dialogs/actiondialog.h \ src/dialogs/boardsearchdialog.h \ src/dialogs/commentdialog.h \ src/dialogs/copydialog.h \ src/dialogs/databasetagdialog.h \ src/dialogs/dlgsavebook.h \ src/dialogs/matchparameterdlg.h \ src/dialogs/onlinebase.h \ src/dialogs/preferences.h \ src/dialogs/promotiondialog.h \ src/dialogs/quicksearch.h \ src/dialogs/recipientaddressdialog.h \ src/dialogs/renametagdialog.h \ src/dialogs/savedialog.h \ src/dialogs/tagdialog.h \ src/dialogs/tournamentselectiondialog.h \ src/guess/guess.h \ src/guess/guess_attacks.h \ src/guess/guess_common.h \ src/guess/guess_compileeco.h \ src/guess/guess_error.h \ src/guess/guess_guessengine.h \ src/guess/guess_hash.h \ src/guess/guess_misc.h \ src/guess/guess_movelist.h \ src/guess/guess_position.h \ src/guess/guess_recog.h \ src/guess/guess_sqlist.h \ src/guess/guess_sqmove.h \ src/guess/guess_sqset.h \ src/gui/GameMimeData.h \ src/gui/analysiswidget.h \ src/gui/annotationtimeedit.h \ src/gui/annotationwidget.h \ src/gui/boardsetup.h \ src/gui/boardsetuptoolbutton.h \ src/gui/boardtheme.h \ src/gui/boardview.h \ src/gui/boardviewex.h \ src/gui/chartwidget.h \ src/gui/chessbrowser.h \ src/gui/chessxsettings.h \ src/gui/colorlist.h \ src/gui/databaselist.h \ src/gui/databaselistmodel.h \ src/gui/digitalclock.h \ src/gui/dockwidgetex.h \ src/gui/ecolistwidget.h \ src/gui/ecothread.h \ src/gui/engineoptiondialog.h \ src/gui/engineoptionlist.h \ src/gui/engineoptionmodel.h \ src/gui/eventlistwidget.h \ src/gui/exclusiveactiongroup.h \ src/gui/exttool.h \ src/gui/ficsconsole.h \ src/gui/gamelist.h \ src/gui/gamelistsortmodel.h \ src/gui/gamenotationwidget.h \ src/gui/gametoolbar.h \ src/gui/gamewindow.h \ src/gui/helpbrowser.h \ src/gui/helpbrowsershell.h \ src/gui/historylabel.h \ src/gui/htmlitemdelegate.h \ src/gui/kbaction.h \ src/gui/listwidgetex.h \ src/gui/loadquery.h \ src/gui/logstream.h \ src/gui/mainwindow.h \ src/gui/messagedialog.h \ src/gui/ooo/converter.h \ src/gui/ooo/document.h \ src/gui/ooo/formatproperty.h \ src/gui/ooo/kzip.h \ src/gui/ooo/styleinformation.h \ src/gui/ooo/styleparser.h \ src/gui/openingtreewidget.h \ src/gui/plaintextedit.h \ src/gui/playerlistwidget.h \ src/gui/qled.h \ src/gui/qt6compat.h \ src/gui/shellhelper.h \ src/gui/simplelabel.h \ src/gui/style.h \ src/gui/tableview.h \ src/gui/testadapter.h \ src/gui/textbrowserex.h \ src/gui/textedit.h \ src/gui/toolmainwindow.h \ src/gui/translatingslider.h \ src/quazip/JlCompress.h \ src/quazip/crypt.h \ src/quazip/ioapi.h \ src/quazip/quaadler32.h \ src/quazip/quachecksum32.h \ src/quazip/quacrc32.h \ src/quazip/quagzipfile.h \ src/quazip/quaziodevice.h \ src/quazip/quazip.h \ src/quazip/quazip_global.h \ src/quazip/quazipdir.h \ src/quazip/quazipfile.h \ src/quazip/quazipfileinfo.h \ src/quazip/quazipnewinfo.h \ src/quazip/unzip.h \ src/quazip/zip.h SOURCES += \ src/database/analysis.cpp \ src/database/annotation.cpp \ src/database/arenabook.cpp \ src/database/bitboard.cpp \ src/database/board.cpp \ src/database/clipboarddatabase.cpp \ src/database/ctgbookwriter.cpp \ src/database/ctgdatabase.cpp \ src/database/database.cpp \ src/database/databaseconversion.cpp \ src/database/databaseinfo.cpp \ src/database/datesearch.cpp \ src/database/downloadmanager.cpp \ src/database/duplicatesearch.cpp \ src/database/ecoinfo.cpp \ src/database/ecopositions.cpp \ src/database/editaction.cpp \ src/database/elosearch.cpp \ src/database/enginedata.cpp \ src/database/enginelist.cpp \ src/database/engineoptiondata.cpp \ src/database/enginex.cpp \ src/database/eventinfo.cpp \ src/database/ficsclient.cpp \ src/database/ficsdatabase.cpp \ src/database/filter.cpp \ src/database/filtermodel.cpp \ src/database/filtersearch.cpp \ src/database/gamecursor.cpp \ src/database/gamex.cpp \ src/database/historylist.cpp \ src/database/index.cpp \ src/database/indexitem.cpp \ src/database/lichessopening.cpp \ src/database/lichessopeningdatabase.cpp \ src/database/lichesstransfer.cpp \ src/database/memorydatabase.cpp \ src/database/movedata.cpp \ src/database/nag.cpp \ src/database/networkhelper.cpp \ src/database/numbersearch.cpp \ src/database/openingtree.cpp \ src/database/openingtreethread.cpp \ src/database/output.cpp \ src/database/outputoptions.cpp \ src/database/partialdate.cpp \ src/database/pdbtest.cpp \ src/database/pgndatabase.cpp \ src/database/piece.cpp \ src/database/playerdata.cpp \ src/database/playerdatabase.cpp \ src/database/playerinfo.cpp \ src/database/polyglotdatabase.cpp \ src/database/polyglotwriter.cpp \ src/database/positionsearch.cpp \ src/database/refcount.cpp \ src/database/result.cpp \ src/database/search.cpp \ src/database/settings.cpp \ src/database/spellchecker.cpp \ src/database/streamdatabase.cpp \ src/database/tablebase.cpp \ src/database/tags.cpp \ src/database/tagsearch.cpp \ src/database/telnetclient.cpp \ src/database/threadedguess.cpp \ src/database/uciengine.cpp \ src/database/wbengine.cpp \ src/dialogs/aboutdlg.cpp \ src/dialogs/actiondialog.cpp \ src/dialogs/boardsearchdialog.cpp \ src/dialogs/commentdialog.cpp \ src/dialogs/copydialog.cpp \ src/dialogs/databasetagdialog.cpp \ src/dialogs/dlgsavebook.cpp \ src/dialogs/matchparameterdlg.cpp \ src/dialogs/onlinebase.cpp \ src/dialogs/preferences.cpp \ src/dialogs/promotiondialog.cpp \ src/dialogs/quicksearch.cpp \ src/dialogs/recipientaddressdialog.cpp \ src/dialogs/renametagdialog.cpp \ src/dialogs/savedialog.cpp \ src/dialogs/tagdialog.cpp \ src/dialogs/tournamentselectiondialog.cpp \ src/guess/guess.cpp \ src/guess/guess_compileeco.cpp \ src/guess/guess_guessengine.cpp \ src/guess/guess_misc.cpp \ src/guess/guess_movelist.cpp \ src/guess/guess_position.cpp \ src/guess/guess_recog.cpp \ src/gui/analysiswidget.cpp \ src/gui/annotationtimeedit.cpp \ src/gui/annotationwidget.cpp \ src/gui/boardsetup.cpp \ src/gui/boardsetuptoolbutton.cpp \ src/gui/boardtheme.cpp \ src/gui/boardview.cpp \ src/gui/boardviewex.cpp \ src/gui/chartwidget.cpp \ src/gui/chessbrowser.cpp \ src/gui/chessxsettings.cpp \ src/gui/colorlist.cpp \ src/gui/databaselist.cpp \ src/gui/databaselistmodel.cpp \ src/gui/digitalclock.cpp \ src/gui/dockwidgetex.cpp \ src/gui/ecolistwidget.cpp \ src/gui/engineoptiondialog.cpp \ src/gui/engineoptionlist.cpp \ src/gui/engineoptionmodel.cpp \ src/gui/eventlistwidget.cpp \ src/gui/exclusiveactiongroup.cpp \ src/gui/exttool.cpp \ src/gui/ficsconsole.cpp \ src/gui/gamelist.cpp \ src/gui/gamelistsortmodel.cpp \ src/gui/gamenotationwidget.cpp \ src/gui/gametoolbar.cpp \ src/gui/gamewindow.cpp \ src/gui/helpbrowser.cpp \ src/gui/helpbrowsershell.cpp \ src/gui/historylabel.cpp \ src/gui/htmlitemdelegate.cpp \ src/gui/kbaction.cpp \ src/gui/listwidgetex.cpp \ src/gui/loadquery.cpp \ src/gui/logstream.cpp \ src/gui/main.cpp \ src/gui/mainwindow.cpp \ src/gui/mainwindowabout.cpp \ src/gui/mainwindowactions.cpp \ src/gui/messagedialog.cpp \ src/gui/ooo/converter.cpp \ src/gui/ooo/document.cpp \ src/gui/ooo/formatproperty.cpp \ src/gui/ooo/kzip.cpp \ src/gui/ooo/styleinformation.cpp \ src/gui/ooo/styleparser.cpp \ src/gui/openingtreewidget.cpp \ src/gui/plaintextedit.cpp \ src/gui/playerlistwidget.cpp \ src/gui/qled.cpp \ src/gui/shellhelper.cpp \ src/gui/simplelabel.cpp \ src/gui/style.cpp \ src/gui/tableview.cpp \ src/gui/testadapter.cpp \ src/gui/textedit.cpp \ src/gui/toolmainwindow.cpp \ src/gui/translatingslider.cpp \ src/quazip/JlCompress.cpp \ src/quazip/qioapi.cpp \ src/quazip/quaadler32.cpp \ src/quazip/quacrc32.cpp \ src/quazip/quagzipfile.cpp \ src/quazip/quaziodevice.cpp \ src/quazip/quazip.cpp \ src/quazip/quazipdir.cpp \ src/quazip/quazipfile.cpp \ src/quazip/quazipnewinfo.cpp \ src/quazip/unzip.cpp \ src/quazip/zip.cpp INCLUDEPATH += src/database INCLUDEPATH += src/guess INCLUDEPATH += src/gui INCLUDEPATH += src/dialogs INCLUDEPATH += src/quazip INCLUDEPATH += $$[QT_INSTALL_PREFIX]/src/3rdparty/zlib win32 { # DEFINES += ZLIB_WINAPI # LIBS += -lz INCLUDEPATH += $$[QT_INSTALL_HEADERS]/QtZlib win32-g++:LIBS += -lz } UI_DIR = src/generated MOC_DIR = src/generated RCC_DIR = src/generated CONFIG(debug, debug|release) { DESTDIR = "debug" OBJECTS_DIR = "obj_dbg" DEFINES += _DEBUG } CONFIG(release, debug|release) { DESTDIR = "release" OBJECTS_DIR = "obj_rel" DEFINES += QT_NO_DEBUG_OUTPUT NDEBUG } !win32 { CONFIG(debug, debug|release) { LIBS += -lz } CONFIG(release, debug|release) { LIBS += -lz } } TARGET = chessx ICON = data/images/chessx.icns RC_FILE = src/chessx.rc macx { INSTALLATION_DATA.files = mac_osx/qt_menu.nib INSTALLATION_DATA.path = Contents/Resources/ QMAKE_BUNDLE_DATA += INSTALLATION_DATA TIMESEAL_DATA.files = data/timeseal/mac/timeseal TIMESEAL_DATA.path = Contents/MacOS/data/timeseal/mac QMAKE_BUNDLE_DATA += TIMESEAL_DATA QMAKE_INFO_PLIST = mac_osx/Info.plist } RESOURCES = \ resources.qrc translations.qrc TRANSLATIONS = i18n/chessx_de.ts # i18n/chessx_fr.ts \ # i18n/chessx_da.ts \ # i18n/chessx_fr.ts \ # i18n/chessx_it.ts \ # i18n/chessx_cz.ts \ # i18n/chessx_ru.ts \ # i18n/chessx_es.ts # i18n/chessx_nl.ts \ # i18n/chessx_pl.ts \ # i18n/chessx_pt_BR.ts \ # i18n/chessx_ro.ts \ # i18n/chessx_zh.ts isEmpty(QMAKE_LRELEASE) { win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease } isEmpty(TS_DIR):TS_DIR = i18n TSQM.name = lrelease ${QMAKE_FILE_IN} TSQM.input = TRANSLATIONS TSQM.output = $$TS_DIR/${QMAKE_FILE_BASE}.qm TSQM.commands = $$QMAKE_LRELEASE ${QMAKE_FILE_IN} -qm ${QMAKE_FILE_PATH}/${QMAKE_FILE_BASE}.qm TSQM.CONFIG += no_link target_predeps QMAKE_EXTRA_COMPILERS += TSQM PRE_TARGETDEPS += compiler_TSQM_make_all OTHER_FILES += \ data/templates/pgn-default.template \ data/templates/notation-default.template \ data/templates/latex-default.template \ data/templates/html-default.template \ ChangeLog.md \ COPYING.md \ ChangeLog.txt \ data/help/about.css \ data/help/about-dark.css \ data/help/about0.html \ data/help/about1.html \ data/help/about1a.html \ data/help/about2.html \ data/help/about3.html \ data/help/about4.html \ data/help/about5.html \ setup7-64.iss \ data/styles/orange.css \ unix/chessx.desktop macx { OTHER_FILES += \ mac_osx/Info.plist \ mac_osx/qt_menu.nib \ data/timeseal/mac/timeseal } win32 { OTHER_FILES += \ src/chessx.rc \ src/chessx.ico } DISTFILES += \ INSTALL.md \ TODO.md \ Doxyfile \ License.txt \ README.developers.md \ unix/make_tarball \ mac_osx/svnlist \ mac_osx/fix_paths.sh \ mac_osx/mac_deploy_dyn \ mac_osx/qt_menu.nib \ data/lang/readme-lang.txt chessx-master/lib/0000755000076500000240000000000014666636300013246 5ustar jensstaffchessx-master/lib/chessx-eco/0000755000076500000240000000000014666426276015320 5ustar jensstaffchessx-master/lib/chessx-eco/chessx-eco.pro0000755000076500000240000000323214666426276020106 0ustar jensstaffQT -= gui TEMPLATE = lib CONFIG += staticlib CONFIG += c++11 # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 win32:CONFIG(debug, debug|release) { DESTDIR = "debug" } win32:CONFIG(release, debug|release) { DESTDIR = "release" } SOURCES += \ ../../src/database/ecopositions.cpp \ ../../src/guess/guess_compileeco.cpp HEADERS += \ ../../src/database/ecopositions.h \ ../../src/guess/guess_compileeco.h # Default rules for deployment. unix { target.path = $$[QT_INSTALL_PLUGINS]/generic } !isEmpty(target.path): INSTALLS += target win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../chessx-board/release/ -lchessx-board else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../chessx-board/debug/ -lchessx-board else:unix: LIBS += -L$$OUT_PWD/../chessx-board/ -lchessx-board INCLUDEPATH += $$PWD/../../src/database INCLUDEPATH += $$PWD/../../src/guess DEPENDPATH += $$PWD/../../src/database DEPENDPATH += $$PWD/../../src/guess win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/release/libchessx-board.a else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/debug/libchessx-board.a else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/release/chessx-board.lib else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/debug/chessx-board.lib else:unix: PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/libchessx-board.a chessx-master/lib/chessx-pgn/0000755000076500000240000000000014666426276015336 5ustar jensstaffchessx-master/lib/chessx-pgn/pgn.cpp0000755000076500000240000000004114666426276016624 0ustar jensstaff#include "pgn.h" pgn::pgn() { } chessx-master/lib/chessx-pgn/pgn.h0000755000076500000240000000012014666426276016267 0ustar jensstaff#ifndef PGN_H #define PGN_H class pgn { public: pgn(); }; #endif // PGN_H chessx-master/lib/chessx-pgn/chessx-pgn.pro0000755000076500000240000000564014666426276020147 0ustar jensstaffQT -= gui TEMPLATE = lib CONFIG += staticlib CONFIG += c++11 # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 win32:CONFIG(debug, debug|release) { DESTDIR = "debug" } win32:CONFIG(release, debug|release) { DESTDIR = "release" } SOURCES += \ ../../src/database/annotation.cpp \ ../../src/database/database.cpp \ ../../src/database/filter.cpp \ ../../src/database/gamecursor.cpp \ ../../src/database/gamex.cpp \ ../../src/database/index.cpp \ ../../src/database/indexitem.cpp \ ../../src/database/memorydatabase.cpp \ ../../src/database/nag.cpp \ ../../src/database/output.cpp \ ../../src/database/outputoptions.cpp \ ../../src/database/partialdate.cpp \ ../../src/database/pgndatabase.cpp \ ../../src/database/refcount.cpp \ ../../src/database/result.cpp \ ../../src/database/search.cpp \ ../../src/database/settings.cpp \ ../../src/database/streamdatabase.cpp \ ../../src/database/tags.cpp HEADERS += \ ../../src/database/annotation.h \ ../../src/database/database.h \ ../../src/database/filter.h \ ../../src/database/gamecursor.h \ ../../src/database/gameid.h \ ../../src/database/gamex.h \ ../../src/database/index.h \ ../../src/database/indexitem.h \ ../../src/database/memorydatabase.h \ ../../src/database/nag.h \ ../../src/database/output.h \ ../../src/database/outputoptions.h \ ../../src/database/partialdate.h \ ../../src/database/pgndatabase.h \ ../../src/database/refcount.h \ ../../src/database/result.h \ ../../src/database/search.h \ ../../src/database/settings.h \ ../../src/database/streamdatabase.h \ ../../src/database/tags.h \ ../../src/database/version.h # Default rules for deployment. unix { target.path = $$[QT_INSTALL_PLUGINS]/generic } !isEmpty(target.path): INSTALLS += target win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../chessx-eco/release/ -lchessx-eco else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../chessx-eco/debug/ -lchessx-eco else:unix: LIBS += -L$$OUT_PWD/../chessx-eco/ -lchessx-eco INCLUDEPATH += $$PWD/../../src/database INCLUDEPATH += $$PWD/../../src/guess DEPENDPATH += $$PWD/../../src/database DEPENDPATH += $$PWD/../../src/guess win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-eco/release/libchessx-eco.a else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-eco/debug/libchessx-eco.a else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-eco/release/chessx-eco.lib else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-eco/debug/chessx-eco.lib else:unix: PRE_TARGETDEPS += $$OUT_PWD/../chessx-eco/libchessx-eco.a chessx-master/lib/chessx-board/0000755000076500000240000000000014666426276015641 5ustar jensstaffchessx-master/lib/chessx-board/chessx-board.pro0000755000076500000240000000156014666426276020752 0ustar jensstaffQT -= gui TEMPLATE = lib CONFIG += staticlib CONFIG += c++17 # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 win32:CONFIG(debug, debug|release) { DESTDIR = "debug" } win32:CONFIG(release, debug|release) { DESTDIR = "release" } SOURCES += \ ../../src/database/bitboard.cpp \ ../../src/database/board.cpp \ ../../src/database/piece.cpp HEADERS += \ ../../src/database/bitboard.h \ ../../src/database/bitfind.h \ ../../src/database/board.h \ ../../src/database/move.h \ ../../src/database/piece.h \ ../../src/database/square.h # Default rules for deployment. unix { target.path = $$[QT_INSTALL_PLUGINS]/generic } !isEmpty(target.path): INSTALLS += target chessx-master/lib/pgn-convert/0000755000076500000240000000000014666426276015521 5ustar jensstaffchessx-master/lib/pgn-convert/pgn-convert.pro0000755000076500000240000000752614666426276020522 0ustar jensstaffQT -= gui CONFIG += c++11 console CONFIG -= app_bundle # You can make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp RESOURCES = \ ../../resources.qrc # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target CONFIG(debug, debug|release) { DESTDIR = "debug" } CONFIG(release, debug|release) { DESTDIR = "release" } win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../chessx-board/release/ -lchessx-board else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../chessx-board/debug/ -lchessx-board else:unix: LIBS += -L$$OUT_PWD/../chessx-board/ -lchessx-board win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../chessx-board/release/ -lchessx-board else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../chessx-board/debug/ -lchessx-board else:unix: LIBS += -L$$OUT_PWD/../chessx-board/ -lchessx-board win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../chessx-eco/release/ -lchessx-eco else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../chessx-eco/debug/ -lchessx-eco else:unix: LIBS += -L$$OUT_PWD/../chessx-eco/ -lchessx-eco win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../chessx-pgn/release/ -lchessx-pgn else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../chessx-pgn/debug/ -lchessx-pgn else:unix: LIBS += -L$$OUT_PWD/../chessx-pgn/ -lchessx-pgn INCLUDEPATH += $$PWD/../../src/database INCLUDEPATH += $$PWD/../../src/guess DEPENDPATH += $$PWD/../../src/database DEPENDPATH += $$PWD/../../src/guess win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/release/libchessx-board.a else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/debug/libchessx-board.a else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/release/chessx-board.lib else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/debug/chessx-board.lib else:unix: PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/libchessx-board.a win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/release/libchessx-board.a else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/debug/libchessx-board.a else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/release/chessx-board.lib else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/debug/chessx-board.lib else:unix: PRE_TARGETDEPS += $$OUT_PWD/../chessx-board/libchessx-board.a win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-eco/release/libchessx-eco.a else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-eco/debug/libchessx-eco.a else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-eco/release/chessx-eco.lib else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-eco/debug/chessx-eco.lib else:unix: PRE_TARGETDEPS += $$OUT_PWD/../chessx-eco/libchessx-eco.a win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-pgn/release/libchessx-pgn.a else:win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-pgn/debug/libchessx-pgn.a else:win32:!win32-g++:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-pgn/release/chessx-pgn.lib else:win32:!win32-g++:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../chessx-pgn/debug/chessx-pgn.lib else:unix: PRE_TARGETDEPS += $$OUT_PWD/../chessx-pgn/libchessx-pgn.a chessx-master/lib/pgn-convert/main.cpp0000755000076500000240000000134414666426276017156 0ustar jensstaff#include #include #include "output.h" #include "memorydatabase.h" #include "settings.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); AppSettings = new Settings("pgn-convert.settings"); if (argc >= 2) { PgnDatabase db; QString filename = argv[1]; QFileInfo fi(filename); QString outfile = fi.baseName() + ".processed.pgn"; if (db.open(filename, true) && db.parseFile()) { qDebug() << "Processing" << db.count() << "games in file" << filename; Output output(Output::Pgn); output.output(outfile, db); qDebug() << "Done"; } return 0; } return 1; } chessx-master/lib/pgn-convert/debug/0000755000076500000240000000000014666426276016607 5ustar jensstaffchessx-master/lib/pgn-convert/debug/pgn-convert0000755000076500000240002040273014666426276021007 0ustar jensstaff !H__PAGEZEROx__TEXT@7@7__text__TEXT :n :__stubs__TEXTB'__stub_helper__TEXTE` E__gcc_except_tab__TEXT0PU0P__cstring__TEXT8O28__const__TEXT|O.__unwind_info__TEXT '7 '7__DATA@7@7__nl_symbol_ptr__DATA@7@7__got__DATA@70@7__la_symbol_ptr__DATA8A7X48A7__mod_init_func__DATAu78u7 __const__DATAu7u7__data__DATA~7~7__bss__DATA 7__common__DATA 7(H__LINKEDIT9 7E "07``7@7@8((89=H> P"4"4`<'P==  /usr/lib/dyld7:ky9E$  *( : H@rpath/QtWidgets.framework/Versions/5/QtWidgets @@rpath/QtGui.framework/Versions/5/QtGui Xu-/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit X /System/Library/Frameworks/Metal.framework/Versions/A/Metal H@rpath/QtCore.framework/Versions/5/QtCore h/System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration X/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit X/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL P/System/Library/Frameworks/AGL.framework/Versions/A/AGL 0/usr/lib/libc++.1.dylib 8< /usr/lib/libSystem.B.dylib0 @executable_path/../Frameworks0 /Users/jens/Qt/5.15.2/clang_64/lib&9()9UHHH7HHEDžD@H8H8H(H@ m HƅHH5jHHHHHot9ƅHHH@NHY%H8HpHHHHH=HiHH HmHH'H@H5riH tiHHHH5ViH HxHvSHpHxHpHhH5 iHhH`HH`HH5hH1HHHHHHHH9BH59hH ;hHHHaH57hHHHH蘙>H H H H& HzH 9H H H HH H HH HfH H HHHZIDžDDžHH HH$IHHHH#RDžDDžH( DH 7H HUH9щ\)\Hİ]H(H   @UHHH}HuH}HuCH]f.UHHH}H}H]DUHHPHH}HuHUEHuH}HEHuH}غHuH}H}EE/!HEЉU(HEЉUH}SH}EHEHP]H}2H} UHH H}HuUHMH}HuUHM%H ]f.DUHH@H}HuHEH8HuHMH}HHEHMH}HuuH}H}H@]HEUH}nH} UHH H}HuHEH8HuHE4H}HEmH ]fUHH H}HuHEH}HEH}HE6H}Hu1H}H ]fUHH0H}HuHEH}H}HEH}H}pE EEH}HMHH0]f.fUHH H}HEHHHEHEH8MH ]HHUUHH H}HEHHEE} E!} EH}T$EE$H ]f.DUHHH}H}H]f.PH$UHHH}H}H]DUHHH}H}$H]UHH1H}HEHH]UHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHHH}HEHH]fDUHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]f.fUHHH}HuH}HuH]f.UHH@HHHMHuUHuH}H}HEHu}H}]EEE̋EH}HuЉHEH@]f.DUHHH}HuH}HuH]f.UHH H}HuHEHMH HH9EHEH=^H5^F%HEHHZH ]fUHH H}HEHHEE} E} H}EE$H ]fUHH H}H}EE$H ]HHUfUHHH}HEHH]fDUHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HmHMHcHEHMEGEHME4EHME!EHMEEHMEE]ÐUHH H}HuUHMH}HuUHML\H ]UHH0H}HuUHMLEH}HuUHMLE H0]UHH}HuUHMLEHEUPHMHHHMHHHMHH]f.DUHHH}HEHA HEHEH8 HEH]@UHHH}HEH8H]fUHH}HEH@]f.fUHHH}HEHH]fUHHH}HExHEHEHxHEHxH= [H5Y[<UHEHMHAH]ÐUHHE}H5wHH ɴEH]@UHHE<MM}H5)HH {EH]fDUHH6]UHHH}H}+H]DUHHH}H}+H]DUHHH}H]fUHHH}/H]HHUXUHH=57`HyHH557H ]ÐUH]ÐUHH0HH}HEXH5[HEHHE!H}HutH}6HEH0]HEUH}H} UHHH}H} H]DUHH`H}HuHUHMLELMHEHEH5fXHHEHEHHEHuHHEHHEHuHHEHHEHuHhHEH HEHuHPHEH(HEHuH8HEH0HEH5WHH`]HEUHEHMH9HE+HEHHHEHEHMH9HEH}[ f.UHH0H}HuHUHMLELMH}HuHUHMLELMH0]f.UHHPH}H}H5WHEH}H H5WH}H5WH}H5WH}H5iH}HuHUHMLELMH}H}H}H}H}H}HP]HEUOHEU:HEU%HEUHEUH}PH}GH}>H}5H},H} UHHPH}H}H5VHEH}HH5VH}H5rVH}H5_VH}H5hH}zHuHUHMLELMH}H}zH}qH}hH}_H}VHP]HEUOHEU:HEU%HEUHEUH}H}H}H}H}H} UHH@=A17H=417QH5HUH}vH5H}mrr0H}ZtHhHhƳH}ggHHMH#AHH1<H}ff1;H}ee^1:H}kdd0H}XsHXHXֲHEHH#H@HMHEH57HH#UHUH}WH}ƬWWEH}rHHuHEHHRHEH HH!HMH#A8HEH}/H}>GGEMdH}!rH8} Ǻ77MʉH}DDhH8DrH}qH(} c''MʉH}DDhAH(DtH}XqH} MʉH}DDhAHDH}pH} 虹MʉH}DDhAHD誰H}pH} 4MʉH}DDhAHDEHEHHH!HMH#A8HEH}/H}EMdH}oH}lMʉH}DDhHDH}boH}MʉH}DDhAHDH}nH}裷MʉH}DDhAHD贮H}nH}>MʉH}DDhAHDOH}3nH}ٶMʉH}DDhAHDHEHHMHQHHH!HEHEHEH}H}胧EMQH}fmH} UHIH}mH}軵UH\H}lHx}jwwUHx H}slHh}ggUHh身H}"lHX}ȴWWUHXi)HEHHH!HMHQHHH!HEH}nH}聥VVEH}tkHH}GGUHH,HEHHH#L8HMH}H}FFEuH}H8HEHT8HH8H!HuH}_H}聤77EH}tjH(uEHUL hH(/)HEHHH#L8HMH}H}''EuH}HHEHT8HHH!HuH}_H}萣EH}iHuEHUL hH8)HEHHH#L8HMH}H}EuH}HHEHT8HHH!HuH}_H}蟢EH}hHuEHUL hH )HEHH(H#L8HMH}H}EuH}'HHEHT8HHH!HuH}_H}计EH}gHuEHUL hH8)HEH\HHEHT8HHH!HuH}H}EHMuHω֋cH}fHHEMʉ|hHH׉ʋ/EE H}HEH`]H}蓟 UHHH6HHEH0H(H0H8HHHƺH ]H(H H8iH8H 6H HUH9ш$H] UHH H}uHE}HEEHMH;BH=.LH5mWHJ舞H}HcMHHH ]f.@UHHH}HEHHuLEB~$H]UHHH}H}{H]DUHHPH}HEH}HHEEEH}EEEċM9ruH}JHEH}HuEE*EEJHE؉UH}:LEEiH}ӿEE4$EEH}E$HP]H}ޜ f.@UHH@H}HuHUH}HEHuHEH}H,4EE0EE#E8E;E?E= EEE8E>E:GE>Pe1H}:EEWH}:EE=H}:EE;#H}:EE= EHEH;E7HEH3EHMH3A0HA0UuDhEEM9EEM9EM9EωHUD hEΉHUD hEωH5p9H EΉH3 H3JHJEωH EΉH3 H3L8HL8EωH5&9H EΉH3 H3JPHJPEωH59H EΉH3 H3JXHJXEωH59H EΉH3 H3J`HJ`*HEfǀHMH3MH3HUDhUHEfǀHMHH1H@@@H}9HMHHMHcHHEHMH3AHAUDheHEHMH3AHAUDhEHEHMH3AHAUDh%HEHMH3A(HA(UDhH}uʃHUVHHMHcHEM9OEHK9H HUH3JPHJPEH5.9H H3JXHJXEH59H H3J`HJ`EHU@ @@ E@ @@ fǂHMH3 H HMЋEH3L8HL8}EHU@ @@ fǂHMH3JHJHMЋEH3L8HL83EHU@ @@ fǂHMH3JHJHMЋEH3L8HL8EHU@ @@ fǂHMH3JHJHMЋEH3L8HL8uH_&HEHH H#MHuH}UaEHU@ @@ fǂHMH3J(HJ(HMЋEH3L8HL8EHU@ @@ E@ @@ fǂ@uD@Ɖ}NjuuċuĉHUD huĉL 9I H3 H uĉI ȋuAJ3L8JL8uL 9I ȋuAK3 H3JPHJPuL_9I ȋuAK3 H3JXHJXuL<9I ȋuAK3 H3J`HJ`H}虞EEHUD hHEH;EjHEH3EHMH3D8HD8UH5 9HH3APHAPUH59HH3AXHAXUH59HH3A`HA`HEHH8HH@HHHHEHEHEH胗EE$Hp]Q-xMW_ NepNNNNNNN7UHHH9H}HMHHƺH]UHHH9H}HMHHƺթH]UHH}HEƀƀ]@UHH}@uHEMU]UHH H}uHE}HE'}EHM舁H菕 H}_H ]fUHH}HEHEOHE@@(M@u@}EEEȋUʃHu HEƀ]UHH@H}@uHEM@HEH= H5 HEHT8MH=?9H#HHEEHUD hȉHMHHMHcHH}uHEH}u`HEH}uDHEH}u"HEH}uHEHEHHEHE#H{9H EHEHL9H EHE7HEH9H EHEH9H EHEHEHT8HH#UHUH}EH} EH}HuHUHM!H}n EEE$H@]fof.fUHH}@uHEH H=6HMHHxHHH!HUH}HE;HEH H5F6HMHHpHHH!H UHUHEDHEH H56HMHHcH#T8H UHUVHEH H56HMHHcHt8L9I 4H!H UHUHE]f.fUH1H}HUHHuH+H!HUHMHUH3 H H}HEHH??)M EE]fDUHHPHL۟6MLEIL0H(H HH(H D A@HHHH@HEH H9HHHHHH @0HH@nH HDDhDH DHHATnHĕ$HHT8H#HHHzDHHT8H#HU!HHLhHH DnH܁H襁HHDDhDH蝁H菔8HHmHH^C_HHqm?HH0H#HHHBb8H H0 H#HHHB HH9H'HHH H=>6HH H#HHBHHH=6H#HH}HDž"HH0蠛H"HH0hHi"HH0BH2HH0HHH#HHH@*H8HHHHֺHHHXH8BH8tHH:@H H ~Hff fDAA DE fDHc}HH?H6HHMH9HHP]֝ f.UHH0H}@uUHEM@HEH=H5)x}v }H=H5wEHW8H HMHMHQHH#UH H}u,}wE}}uEEHU@ @@ EȉHMHpHMHcHHEHMH HU@@@HEHMH AHAHEHMH AHAHEHMH AHAtHEHMH A(HA(_HEHH0UH#L8HEH}HU HEHMH A0HA0UuEMHu؈DhHUH3VHHVHHUMH3T8HT8MH=8HH3VPHVPMH=8HH3VXHVXMH=u9HH3V`HV`H0]UHH}}CuE }(uEE$H]UHH0H}@uHEM@HEH=H5LuEH8H HMHMHQHH#UHHEHH8HUH!H@@}}@@@}|hωHM&HHMHcHHEHMH3HU@@@HEHMH3AHAHEHMH3AHAHEHMH3AHAH{*EH6U6 HM!@+HEHH H#MHuH}UDžGHEHMH3A(HA(2HEHMH3A0HA0UƄuHhEHUD hHMH3JHHJHHMEH3L8HL8EH58H H3JPHJPEH58H H3JXHJXEH58H H3J`HJ`H0]L7gUHH}}mr1ɨEʉH]fUHH}HE]fUHH0H}uUHEEHE}uH}9 U9EHHHMHHMHcH}HEr}HEL}HE&}HEEEH0]fHnUHH}uHEM!@]fUHHH6HHEH0H(H0H8H H蜝H(H HȃH8HGH56H6H}H9$H] f.DUHHH}HuUHEHuHMHHEHx8 1HxTwwEϾH}<MH} HEǀƀEE81}v"1Mσ v }@vv4EσщCHhHoHhHcHHEUEЃEEЃEEЃEEЃEEЃEEЃExEЃEjEЃE\EЃENEЉHUD hEЉH538H H H EЉH H J@HJ@@@@@@@EЃEEЉHUD hEЉH58H H JHJEЉH H J@HJ@@@@EЃEEЉHUD hEЉH5u8H H JHJEЉH H J@HJ@@@@EЃE9EЉHUD hEЉH58H H JHJEЉH H J@HJ@@@@EЃEEЉHUD hEЉH58H H J(HJ(EЉH H J@HJ@@@@EЃEEЉHUD hEЉH5p8H H J0HJ0EЉH H J@HJ@EЈ}Ѓ}/EЉHUD hEЉH58H H H EЉH H J8HJ8@@@@@@EЃEEЉHUD hEЉH58H H JHJEЉH H J8HJ8@@@EЃEqEЉHUD hEЉH5V8H H JHJEЉH H J8HJ8@@@EЃEEЉHUD hEЉH58H H JHJEЉH H J8HJ8@@@EЃEEЉHUD hEЉH58H H J(HJ(EЉH H J8HJ8@@@EЃElEЉHUD hEЉH5Q8H H J0HJ0EЉH H J8HJ8EЈ}Ѓ}EE EEH}؉薁ggE}EEt HEHH8HH@HHHE}@}HcEH 8HHMH#AHHIHcEH l8HHMH APHAPHcEHQ8HH AXHAXHcEH:8HH A`HA`EEyEEH}؉貀ffEMσwHEƀOEσbHEƀ-EσEEXEEHEEԋEEH}؉eeEMσEEHEH@ Mσ-Eσ Eσ&HXqHHXHcH1H}4zf1H}zQH}z9H}y!EσaEσhuϿguWWEMHU9JH}FEH8H HUHr H Hr HLyfEHM9JH}EH8H HUHr H Hr HxEσAEσHu1btVVEMHU9GH}AEH8H HUHr H Hr 1HJxcEHM9GH}EH8H HUHr H Hr 1HwEE+EEH}؉|UUE EԃEHEHx 1H}Ɖ1H}‰EEH}؉}|TTEMσEE]Eσ-DEEσa&EσhEσaHMkEσA&EσHEσAHM3Eσ0 Eσ9EEEEEEH}؉{SSEHMEσ6EELHEEσ3EEH}uEEԋEEH}؉zRREMσEEEσ-HEfǀMԃMEσ0 Eσ9EE`EԉE1Mσ0QEσ9QQ,EEH}؉yPPEEM)H}Hu؉讁1H} yLLfHUfH}HEUH}EEH}؉byKKEMσEEBEσ-HEǀEσ0 Eσ9EEUH}Huع貀1H} xDHEDH}1Mσ0CEσ9CCAEEH}؉LxBBEHEUH})IHEHEǀEEH}LE$H]H}2H}^ 3H]uiiiiiiiiiiiiiiiiii iiiJ_iiiiiiiiiiiiiiiiiiiiiiiiii+@UHH0H}HuHEHuHHE0HuH}HuȃH}Hu؉$EEE$H0]f.UHHPH}HEEEEEEEEHE}@EH}bEЃ}EE}EE}.} }8 EEE} .} }8 EEEK}\E؃E#}\ E܃EEԃEEHM9H=H5j\EHM9H=H57\EEEHM9H=|H5a\EEEHM9H=gH5(\} EP} E:} } E} E} EEEE؃ E EEE܃ E HEHHuLEB|$EH}LcLMC{$EEE E,E EHEm1H}{ 1H} E 1H}Z{#H} E H}{#H}8}  E TH}z#H}??  E 1H}z#H} E H}z#H}< E 1H}az5HEH58HHH E KH}z8HEH5P8HH#j$EH}7jHU$E݀}HU1uVE EEHMH}HM1u~VE EEHMH}HMu@VE EEHMH}HMuV HME}HcEDEHcEЊLEMHcEЊLEM͊MΈMẺH8H HMHMHQH#UHTHcELց#EHcMT 9 EjNE EREEM9ȸLH}̉ UEM9OEЃEEEH /h6H HUH9ш~~$HĐ]zl f.@UHH}HuEH} HEH-H#EHEMME]f.UHHHg6HHEH}uHEHǾH@} }H@Q1H}H'6HMH8Hω4HƺPkH84 kEUUЙEEHcD bEUUЙEEHcD bEUUЙEDž|Hc|L||}.||HcD  EEHc|DqHcELŠMDž|Hc|L||}.||HcD  EEHc|DnHcELŤMHc|L||}.||HcD  EEHc|DnDž|Hc|L||}.||HcD  EEHc|DrDž|Hc|L||}.||HcD  EEHc|DkDž|Hc|L||}.||HcD  EEHc|DrHpHu2bH5H`bHHHpUfHhH`HpHHaHHbH`aHhH@HhaHpaHb6HHMH9H]HXTUHXTHXTHHbaH`VaHXTHh8aHp,aHX? f UHHHL+b6MLEIL@H8H0H(H8HHH?HH H0fH(HfHHMHHMHHMHEHEHHxH@HEHuH`VHuHHVLEHxHMHHUHEHMH`HEHHHEHEHEHEHEHEHEHEHEHEHuHUHUH`6HHMH9HH]5e fUHH HHHMHuHuHEMHEH ]UHHHn`6HHEH}HEEHH#HHHHE EHEHH#H8HHEHH#H@HH9 EnHEHE E:HEHpH EHEHpH EHEHpHp EHEHp(HK EHEHp0H& EHEHHHHMH} EWH}<eKLcLELELcMMDMLEMPIULUH} EH}M<HcHUHUHcuH։uEEEEEEEH#$6HUH $6HUEE/H}uf EH}uGH}u1H}u} E  EEE EEEEEE EEJH}u/E EEE EEH}I}CE9E/EẺEHcMDEEkE`ẺE̋ẺEEEH v\6H HUH9щE EHĀ]` UH@}uE+E]fUHHH}H}[HH]DUHH H}H}HEH}H0H}HuKH}JH ]@UHH}HE]f.fUHH}HE]f.fUHH}uUHEMU с` ]f.UHH}uUMHEMU с`U щ]f.@UHH}uUMDEHEMU с`U ыU с]f.fUHH}uUHEMU с`]fUHH}uUMHEMU с`U с]UHH}uUHEMU с`]UHH}HE]f.fUHH}HE]f.fUH@}uEE]fUHH}uUMHEMU сPU щ]f.@UHH}uUMHEMU с@U щ]f.@UHH}uUMHEMU с0U щ]f.@UHH}uUMHEMU с U щ]f.@UHH}uUMHEMU сU щ]f.@UHH H}H}EEH}E?*H}u5EE1H}DEH ]ÐUHHX6}HcM]fUHH H}uHEMH}DUHEH ]f.DUHH}HE]fUHH0HHHMHuHMH}HEHMH};HM H}Y;HEfHUfJDBA fDBDAA DRE fDRHEH0]DUHH}HEH]DUHH0HHHMHuHMH}HEHMH}X:HM H}:HEfHUfJDBA fDBDAA DRE fDRHEH0]DUHH}HEf@]fDUHH@HHHMHuHMH}HEHMHE@@u,HE<@U@uEΈE͊E͈EϊEψEHMЀ#HEHlj1E,HE>@U@uEˈEʊEʈE̊ËEH}HuHUHMHEH@]UHH@HHHMHuHMH}HEHMHE@@u,HE<@U@uEΈE͊E͈EϊEψEHMЀ HEHlj$E,HE:@U@uEˈEʊEʈE̊ËEH}HuHUHMHEH@]f.UHHHH}HuHUHMHuHUHHHHHVHHEH}nIHHHEHMHMHMHHHU@1@uEEEEH}oH}H5HQ-HuHEHEȉUEoEO E0H}CWHHH'HuH}2H5Hx1H}Hx2H}H5VHxmgH}dgQHHEyHEȉUHEȉUHxgH}geWH}UHHHHuHp0H5Hh0HpHh2H}H5fYUHhfHpfTHHHE#HEȉUHEȉUHheHpe H}H5T$HHEH}ETHHHvH}ƅ_ƅOH5  TzHuH`.ƅ_H5ϵHP.ƅOH`HPO HP;d_ H`d}HHWE2HEȉU*HEȉUO HPc_ H`c HuH@n-H5H8Q-H@H8^|H8'cH@c|THHiE4 HEȉUHEȉUH8bH@b HuHE E-XH}H5kQxx$HHEo EZXH}H5$Qtt$HHE jEnXH}H5²Ppp$HH*E EHhH HhHcHEHEHHHMUEHEHHHMUEHEHHHMUpEHEHHHMUMEHEHHHMU*HEHHHMUEE},)ggyEEHMHHHU@1@u}(ff.E1EEEHMHHHUEO}(ee#E1EHMHHHU@1@uExE- E:HEHHHMU}'ddE4HMHHHU@1@u}'cc&HuHEE14EHMHHHUE EEEE=!HuHEf}eE= EEEHD hE}!HuH6E}Dž0Eƅ'=bE(b|H5H(SFƅ'}b&\H \! H(1ҹEXXbb'W H(EWCE= E(FHEHHHMU*HEȉU' H(E}h%PPHHSHHHHcHDž0Dž0zDž0kDž0\1HD‰U9!HuHEE=HDщ}%HE'HE}1GGEMH58HHHHt8H#HlHE'H)EH}+1jEM9,}ȉ0FFE'}0EEEE=EHD hHHUHMHģH}H'H}:DD&00H}'HuHHEE=EȉH8*HZH8HcHuHBH0H0HH#A(HEuHBH(H(HH#AHEuHBH H HH#AHEuHSBHHHH#AHEXuHBHHHH#A0HE!HuHEHHT8H#UHU}HcEH Ԥ8HH#EHE&}HcEH n8HH#EHEH}"H}E!HuH EH}qHHUHMHH)8"H}w EEMHLh9!HuH\E'HUHMHH0EH}UHH]H}UH}W <<<<<<<<<<<j$[CaaaaaaaaaaaRaa%4UHH`UHEH}HHMHuHHEAH}4HEH}HuAH}4HEHcUH}HuyCEH}^TH}UTEH`]HEUHEUH}0TH}'TH} f.fUH1@}MaE EhME$]f.DUH1@}M1E E8ME$]f.DUHH}}cBH]UHH}uHEH=MHcHAI D]@UHH}HE ?]UHH}HE]UHHpH}HuHEH}HE4EH}w4EHMUUH=8H4HuUH4HuEEEH}74EH}3pEȉ%HMWHHMHcHHEH3EHMH3HUDh!HEH3EHMH3AHAUDhHEH3EHMH3AHAUDhHEH3EHMH3AHAUDhHEH3EHMH3A(HA(UDhHEH3EHMH3A0HA0UuuDh^HEH;E3HEH3EHMH3A0HA0UuuDhEH}踧EE8E4E:0E>,4EE,EEE8E;E?E=EE8E>E:GE>Pe1H}cEESH}IEE9H}/EE;H}EE=HEM9EEM9EM9E։HUD hE׉HUD hE׉H5P8H E։H3 H3JHJE׉H E։H3 EH3L8HL8E׉H5 8H E։H3 H3JPHJPE׉H58H E։H3 H3JXHJXE׉H5Ģ8H E։H3 H3J`HJ`HEHMHH1HuDhu@@@H}Z0HMhHHMHcHHEHMH3AHADHEHMH3AHA/HEHMH3AHAHEHMH3A(HA(H}z/EH}/ʃHUHHMHcHEM9OEH8H HUH3JPHJPEH5o8H H3JXHJXEH5V8H H3J`HJ`HE@@@@@@HUH3HHUH3T8HT8CHE@@@HUH3PHPHUH3T8HT8HE@@@HUH3PHPHUH3T8HT8HE@@@HUH3PHPHUH3T8HT8hHE@@@HUH3P(HP(HUH3T8HT8HE@@@@@@E@uMD@Ή}ϋup"ȉMȋMȉLEADhMȉL /8II3IMȉIAAK3T8KT8ML 8IыMAK3I3PPIPPML ל8IыMAK3I3PXIPXML 8IыMAK3I3P`IP`H},EEMHuDhHEH;EfHEH3E؋MHuH3D8HD8MH<8HH3FPHFPMH#8HH3FXHFXMH 8HH3F`HF`HEHH8HH@HHHHEHEHEHHEfHUr@HUz @H$Hp]f[9||||||||||||||9|||||||||||||||m$wUHH}HE]UHH0H}@uHEH@ HEE}:H}zEMU9 E܉EE܃EEEH0]fUHH0H}@uUHEEHEBEHM9#EHM9 EBEHM9#EHM9 E\1u7Eu&EML8IMAK HUHULBL#EI$EE$H0]f.DUH@}@uEM]fUHH}u} } EHcEH 5UE]ÐUHH}u} } EHcEH Q5UE]ÐUHH}HEH@ ]f.@UHHH}@uUH}EU*4H]@UHH}HEH]DUHH}@uHEHM ]UHH}@uHEHM ]UHH0H}HuHEHHE/ EIH}ϛ1H}o& EHuH}$EH}&EHMlEHEHHHHH E~1H}.fHEHHHH`HMH}ؾ.-H}ؾk.H}E6EHEHHHHH E~1H}.fHEHHHHHMH}ؾ--H}ؾ-H}kErE?HHMH#AHH E>~H}ؾe-cH`HMH#AHHG1H}غ<-*1H}غ=,H}EE8HHMH#AHH E:~H}ؾ,cHHMH#AHHG1H}غ<`,*1H}غ;H,H}EEE$H0]ÐUHHH}HEH HǾH]UHH}HEH]DUHH}HEʾH ]@UHH0H}HuHEH}HE"H}E} EuH}aEuH}EH}"EH}"EHME1H}+%E1H}*EMUH}DUDŠEDETJEH}ؾM*%1H}uUH}mEE>H}ؾ<*(E:H}ؾ *EMUH}DUDŠEDE~G1EH}M)%1H}uU= H} EEE$H0]f.@UHH0H}@uUMDEHEMMHEEM9{EM94EM9$H}u{ EaEM9"EM9ȸNH}luEM98EM9(H}uE} EEEEM9{EM94EM9$H}u袱 EEM9"EM9ȸNH}uEM98EM9(H}u'E} E EE$H0]f.UHH H}uUMHEMMHEEM9_uH}U'$EE ELEM9"EM9ȸNH}uH}U&$EE$H ]f.UHH}HuHEHUDD9HEZHEHU9<HEHU9HEHU9 EEE$]f.DUHH@H}HEHEHEHEHEHEHx(HEHx EHEу EHEHx ErHEHx EZHEHHHMH}ЉHMH}ЉHMHMHM؉MԋMԃ$E EE$H@]f.UHH}uHEM]fUHH0H}@uHEM@HEH=@H5 |EH8H HMHMHQHH#UH.HEHH8H#MH EEEEH0]DUHHHHHMHuUHMEH}H53HEHMQ"EE}EE߃}uH}άxxE}}^uH} HuH}=H}!E!HEЉUHEЉUH}!|}JfvfvfEuH} EEEE}RuH} HuH}H}!EHEЉUH}!}/H}CEESHEHHhHHhHhH}HH}!ggȃH5JH}cEE1H}E!ff0H}eeȃaM\H} dd+H}詭ccȃaM1H} bb-1H}SaaȃaM\H}+ ``+H}__ȃaME/uUH}ڴ^^H}]]ȃ:1H}h\\ȃAH} H}J[[ȃ=H}ZZȃAH}- H}YYȃ=H}蜫XXȃaH} H}~WWȃ=H}6VVȃaH}a  H}UUȃKH} H}TTȃQH} H}SSȃkH} H}PRRȃqH}X  H}; HEH5H} ]HEaH} HE81H}  H} H}XLH} L HuH}c H}H5H}? HEHHEHHH} u HuH} H}EE8*HEЉUH}\+HEЉUH}GH}9HEH]H}#H} UHH}}  ?EEH@4 @uEH}~fEH]@UHH}HE]f.UHH}HE]f.UHHpH1HHUHuHUHuHHH5RLTHLAHH}0E}EEۃ}uHqEԃ}QH}Hu(HHH5օH}HLEۃaH}5}H} uH}:DEUH}Hu1EH} uH}DMH}Hu1A HuH.H}H}H}KHEȉUHEȉU%HEȉUHEȉUH}yH}pH}gPEEEE܃E$H.H5%H1HxA|.H5~H1HxANHp~ Hhr DžddH}HdWVHp.H5Hp HEȉUdfff``HpH}HdOHHH53HPHpHXHPH HpHXHXXHPL0HEȉUHEȉUHX(HPHdPTDžLLH}HL JHh"H5HhLifffHHHhH}HLHHH5H8HH@H8H HhH@qH@H80HEȉUHEȉUH@~H8r7HLO`ƅ7HuHpHhLxH"H5<{HHH HDH H1A zHH >H[DH(H 1A H(HH(H Hƅ77eTHEȉUHEȉU+HEȉUHEȉUH(H HRHHh|HppHxdH}kH}RHHp]H6Hh*HpHxH}H}H} DUHHH}H}KH]DUHHpH}HuHEHHE&HEH8Hu6HEH}wHuHEHHuHE yH}HuHUHEHEHEH} HEHEHEH}x#HEȉUH}xHEH HEHEHp]H} UHHH}HuHEH8HufHH]f.UHH}}  ?EEH9x@4 @uEH}>tfEH]@UHH@HHHMHuHUHMH}HHEbH}HEH}HE\H}HuHUȉHEH@]f.UHHH}H}kH]DUHHHH}HuHUMHUH}HHEHUHӘH5ȘHEH}KH5{H};HEH} U uH}.DMH}Hu1A U HUEH}E1HuPHuHUHMH} H} H} H} H} HEHĀ]HEU:HEU%HEUHEUH}{ H}r H}i H}` H} DUHH@H}HuHEHuH}ع HxHpq1H}fU؋MH}HxA HEH EEEE}uH}GHhH}HhE}\uH}dHXHXHEdMH} fVfVfEMȋUΉ׍ MH}Ѓ¾փ0HHHTHHHcHHEU!HEUH} u Hpsou HpgsPu HpHs1u Hp)suHp suHpruHpruHpruHprwuHporXuHpPr9uHp1ruHptEEH} EăEċEȃEAH}H@H57vH@ ??!EHuHpqH}$H0H5pH0 //!EHuHp\H} H 1ƺ H &EuHp eH} \H1ƺ H 1HpH} H1ƺ Hn1Hp&H} H1ƺ H HpH} 6H1ƺ HHp^1HpƉژH}H1ƺ H.Hp)EEH}poE$H@]H}VoH}; QQQQQQQQ2QQQQQQQQQQQQQQQQQQQQQQQQQQxQQQY:@UHH0H}uHE}HEH=H5Vk7H}AUH}Hu) HEUH0]f.fUHH H}HEHHH;J@@@@HE)HEHH9BHMHcQH}4P!1pH} fEH ]f.UHH}HuHEHM]fUHH}uHEM􉈰]fDUHH0H}uUHEEMɉH LT6IMI%8HMH3HEHN@HMH3HEHdx-JHMH3HH ]UHH}HE]f.UHH`H}@uHUHMH}uHEH=HQ8HuH}H}H=Q8HuHMHHHM!1H}dHEHEHU H}Ⱦ@HEHEHU؉ H}HEUH}~EEE$H`]H} UHH}@uHEHMH=5H3]fDUHH 1H}HuHMHuHHMHHMH;AAAH ]f.fUHHpH}HuHEHHE|HuH}HU7HEHEHHMH;HEH8HuUH}HE؋uHUHEHljuHUHE LEH}uHUHMHEHEHHEH}&HEȉUH}HEHHHEHEHp]H}4 @UHHH}HuH}Hus H]f.UHH H}uHE}HE"EHMHωEU9H=?jH5wH;wC设H}HEuHHfH ]UHHH}H} H]DUHHpH}HuHEHHE^H}ؾ蒖uH}8EEH}HuqH}Hu}\;H5nM8H}m!HEЉUPHEЉUH};EEH} EEH}E$Hp]H}H}C UHHH}HuH}HuH]f.UHH}HEH]f.UHHH}HEHHtH]f.fUHH HHHMHuHMHHHEHEH ]fUHHH}HEHHH]f.fUHH HHHMHuHMHHHEHEH ]fUHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]f.fUHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HmHMHcHEHMEGEHME4EHME!EHMEEHMEE]ÐUHH5H}HMH]UHH H}HEHHHHErHEH0HH ]HHU7UHHHi5H}HuH}HH]UHHH}H}]H#H]f.UHH}HE]fUHHH}H} H]DUHHH}HEHH"H]f.fUHH0H}HuHUHEEHy HE H}2HEH8HEHq$շEH} EHMHuUH}1H0]f.UHH}uHEHH3EH!3E]f.fUHH0H}HuUHEHy HEHEHHIUH01v ҉HHHMHMH HuH;HEHH8H=ZH5[ݷ1HMH HUH; EHEH8uHU(4E׊EרHEHHEHEHEHEH0]fUH1H}uHUHMu;qHMEHEHHMH;AˆUߊE$]fUHHH}HEHHHHE H}~H]f.@UHHPH}uHUHMLEHEH8HEH}5H}dHuHUMH}LHHExHEHEHUHuHHUH2NNHEHP]f.UHHH}H}H]DUHH H}HEH8HEH}蔿H55Hz5H} AHEHEHHHHEH0HhHEHMHH ]f.DUHH H}HuH})1AHEHEHUHHuHH}OHHuHHU:H ]@UHHEEH}HuH]DUHH0H}HuHUMLEH}HuHUMLE H0]UHH0H}HuHUMLEHEHUHMHHUHHPHHuHH0]ÐUHH%5H}HMH]UHHPH}HuHEHMH HH8HEhHEHqH(H}HEH}HE~H}HE}H}HuHUH3EHEUH}HMH9HE8HEU HP]H}輱 HHU f.@UHHPH}HuHUHMHEHEHEH;EHEHEHHEHUHHUHHUHUHHUHEЉUH}HEHHHMH;E(HEHHHE H} 3HEЉUHP]H}衰 HHU UHH H}HEH8HElHEH0HcH ]HHU1UHHH}HuH}HEHHMHcIHHHMHHUHcR HHHHļH}H]f.DUHH H}HuHUHEH;E1HEHHEHEHHHE H}TH ]UHHH}HEH8HE H}H]UHH}HEH]f.DUHHH}HEHqH輻H]f.fUHHPH}uHEHHE HEuH}}HEH}H}HEHMH}HuH蕻MHE؉UH}IH}HE@HEHMHEQHE؉U$H} HuH}HP]H} HHU f.DUHHH}HuHuH}H} H}HugEE;EH}H}HuQHEHuH}H}#EE;H}茸EJHE؉UHE؉UH}H}HuHU7HEHEHEEH}bE ẼEHEEH}HErHEHĀ]H}\H}q  f.DUHH H}H}HEH}HpH}Hu衷H}HEvH ]UHHH}HuH}Hu}H]f.UHH@H}HuHUHEHHHE%HEH8_HMHuHHU܈EHEHEȋuHUHMLEHŶH}HHEH@]ÐUHH H}HuHEH}HE/H}H3H}Hu膶H}}HEH ]UHH}HE]fUHHH}HuH}HuCH]f.UHHH}HuHEHMHHëH]UHH 5H}HuHMHUHHHMH]fDUHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHPH}HuHuH}S{H}H}Hu説H}uEE;E|H}HuH}tEEă(H}{:HE؉UH}M|@H}HuUẼExHEH}HE|HEHP]H} f.UHH H}H}HEH}H`H}HuH}HEfH ]UHH H}uHEHQ;UHE>HEH8uH}OHEuH[H ]fDUHH H}HuH}HuMHU HUHEHH ]fUHHPH}HuHEH8HEfzH}´HEHuHUH}觴CHEUH}HMHr Ήr HEHEUn{pH}6HEHuHUH}7CHEUH}!HMHr Ήr HE'8HEU HP]H} HHU f.UHH H}HuHEH}HE/H}H3H}Hu蔳H}-HEH ]UHH}HE]fUHHH}HuH}HuCH]f.UHHH}HuHEHMHH?H]UHH5H}HuHMHUHHHMH]fDUHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHpH}uUHEHHEHEUHuH}HEH}H}HEHcMHHMH}Hu9MHE؉UH}H}HEHEHMH1HE؉UH}HcMHHcMH4H}HuHMHcUH H}HuH蠱}HE؉UH}TH}HEH}HEHcMHH}HuH}HEHMH hHE؉U;H} HuH}HEH%HcMHHHp]H} HHU UHH H}HuHUHMDDHMHH ]f.UHH= 38H5H 28HHH]f.@UHH=28Hi5H 28HHHu]f.@UHw]UHH}HE8 HEHEHEHEHEHE]f.DUHH H}uHEMH}MHEH ]UHHH}HHE諲HEH28HuHMHHMJH}ؾ~zuH}$EEH}Hu]H}Hu荤}\FH5:28H}_EE,HEЉUSHEЉUH}>EEH} EEH}zE$HĀ]H}`H}! UHHH}HuH}Hu衸H]f.UHHHHHMH \18H}HHuHE&HEH}GHEH}4HEH}HuH}HEH}HuwEHuHJHMHHuHHMfH}1xDMAH}HuHUH}]EE#HEUH}:7H},H}KH}˵HEHĀ]H}蓟 UHH}HE]fUHHH}HEH8TH}HHEH]fUHHH}HEH8H}H\HEH]fUHH}HuHEHHMH;€]f.UHH}HEHH ]fUHHH}HEH8HE0HMHHH]@UHHHHHMH /8H}HHuHE֟HEH}HEH}HEH}Hu͹H}豹HEH}Hu'EHuHkHHMHHxHHpH}1EvDMAH}HxHp菾H}H}:#uH}sooH5~'H}胾H}1ƉhuDMH}HUHuhDhH}Hu蝭H}H`WH}N6HEUH}9tHEU1HEUH}EE H}*H})H} $H}荲HEHĠ]H}U DUHH 1fuH}UH}fMfMMuѼAAAH ]f.fUHHHy,8HEHj,8HEHHEH}HEHH]DUHHH}H};H]DUHH`H}Hu ,849H=+8 EH},HEH=+8HuȶvH5+8HEHHuHE H}HUHuHM腶H}Hu{H}HE,H}#EHEȉUH} EE$H`]H}舚 UHHH}HuHEH8HuڽHH]f.UHH@HILEHuHUHMHMH HuH}HHE聽HEH}HEH HEHEHEHEH}H-HEH@]UHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]f.fUHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}HuHuH}hH}H}HuEE;EH}TH}HuHEHuH}ӽH}ӯEE;H}脟EJHE؉UHE؉UH}H}HuHU虭HEHEHEEH}E ẼEHEEH}HE"iHEHĀ]H} iH}!  f.DUHH H}H}HEH}H`H}Hu荞H}HE&H ]UHHPH}HuHUHEHHHEMHEH8胪HEHEH8HEEH}[HEHHuH•4$EHMHMEH}踹HE H}貹HEHEHEHEH8HuHUHMDEAE۩HEHuH}HEHP]UHH H}HuHEH}HE/H}H3H}Hu>H}HEH ]UHH}HE]fUHHH}HuH}HuCH]f.UHHH}HuH}Hu3H]f.UHH5H}HuHMHUHHHMH]fDUHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}HEHHHE觸 H}跛H]DUHH}HEH]f.fUHH}HEH@]f.@UHH}HuHEHHMH;€]f.UHH}HEH@]f.@UHH}HEH@]f.@UHH0H}HuHUHMADEHEHMDEAHǾ(E莕HEHEHMH HHHEH HuHaHEH0]UHH H}HEHEɦHEHEHHy9HEHHIHuHHMHAHEHxHEHHjHEHHq HEH8]HEHMHHH蹔H ]fUH蕔]DUHH01E1H}HuHUH}HHII HULѥHEHEHMHHEߩH}؉誔HMHy6H},HuHzHMHAHEHxHEHp HEH@HEHx6H}HuH)HMHAHEHxHEH HEH@HEH0]fUHHH}HEHHExH*H}eH˥HEHMHqHǺLHEH:H]f.@UHH H}HEHHHHEZHEH HH}WH ]fUHH}]fDUHH H}HEHxHEH}螳HHEHxH}芳HH ]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HmHMHcHEHMEGEHME4EHME!EHMEEHMEE]ÐUHH H}HEHHE(HHEHH HM H}vHEHEH ]fUHHH}HEHtH]fUHH H}HEHHHE9HEH8%H ]HHUUHH0H}HuH}kHEH}LH}Hu跢HEH}+H}HEHH HEHE HEHEH0]f.UHH H}HuHEHEHEH}JHEHHuH蝌HEHEH}蜰HE H}薰HEHEH ]ÐUHH`H}HE1ɉHHEVH5HHUHHHHE@HHHE5HE@`HhHHEHEHH=5HE虋HEHEH=w5HE|HEH}E1HuHUHMLE虚H}H`]HEU%HEUHEUH}H}THEHTH}͊ f.UHHH}H}{H]DUHHH}H}{H]DUHHH5HH}HMHHHhHHMUHEHHHEH詙H]UHH} fDUHH} fDUHH}HEH`]fUHH}@@uHEMH`]ÐUHH}HEH]f.fUHH}HEH]f.fUH1H}]@UH1H}$]f.DUHHH}uHEHuH$H]ÐUHHH}uHEHuH%$H]ÐUHHPHH}HuHMHHRpHuH}HHuHHEH}HuH}HuH}茭H}HEHP]HE؉UH}ʩHE؉UH}ǞH}J f.UHH}$]f.DUH1H}uHU$]UHH H}uHUHEHuHUHH ]f.@UHH H}uHUHMHEHuHUHMHlH ]fDUHH0HILEHuUHMHMHHUDMHDHEHEH0]UHH HILEHuUMHuHUMHE HEH ]UHHHn5HHEHHHLLHHHHHHHHHH~HʥHHHRHHHHLHLLAH輎HHHhHhH_dQHhdQ&DždHxtVHHdܒdHXMHhd QgHhdHHHPHLHXHPHHX$HHHHHHHHivHXHH@HX1AHHH@HH8HHHH8HXE1HHHHH8H8H虤rH5\H^1H0AHHH0脓HHHHHwH0H"HHHPHXHHHHH5,H Hx詣H(H Hx$H 裣H5,H(LwwWHHHH+HxtH 2HxtH5+H(Ģvv'HHHH装H5+H(luu'HHHHK$HHH1H'HHHHhsddH $H$HDHH軡HHHh6 H赡HHH01ɉH HXƠTHXTHHHH5$HHHHHHH H HHH@H5<+HH@跠H1ƉH@]HEUH}H}zHEH8sH}Cb UHHPH}HuHEH;EHEHEH@ HMHA HEPQHAHHEH}HEH诇)HHHuHvHHMHU1HMHUHQA(A,H0HqwE1DHMA@ADHHHHEOwHEUH} HEHP]H},a f.fUHHH}HuH}HuH]f.UHHH}HuH}HusH]f.UHH H}HuHEHMHHHEdHMHEHH ]UHH H}HuHEHMHHHEMdHMHEHH ]UHH}HEH@ ]f.@UHHH}HuHEHuHHHuH]@UHH}HEH@ ]f.@UHH H}ufUHEMHHEMM9uH}U9f}&uH}HEHH6f}&uH} HEHHfEHMHyufEqfUfH ]UHHH}HEHxH]ÐUHHH}uHEHxuɀH]UHH0H}uHEMHxHEM螀M9$HEHxuw€UEE$H0]fUHH H}uHE}HEEHMH;BH= H5H ]H}pHcMHHH ]f.@UHH H}fuHEHHEHEHxHuJpf}H}vE 1EEHMAH ]@UHH@H}HuUHEHMfDfDE}HEHEHQUEE̋EH}ЉoHMHzZ1HMH9/b1҉HEHEH8'bHEHEH;EfEHMHHHUfAHEH@]UHH}HEH@]f.fUHH H}uHE}HEEHMH;BH= H5H \1HMH9\aHcMHHH ]UHH}HEH@]f.fUHH0H}uUHEMMHE؋EH}؉EM99uH} HE؋HHEEH}AEHMHyunEEE;E1E$HUHzufMmfMfEEEE+EHMAAH0]f.UHH0H}uHEMH;JHEH}]mEHMHr9H}j|]1MHUH2~9OH}2HUH:G%EH}HuZ0MMUH}lEHMH;B6H}lHcMHHH}HElH}HuHl1H}elH}HEjlHcMHHH}HuH7lEHMHBH0]fDUHH H}HEHHEH}KHM+AAEH2EE;E\HEHxu{f8HEHxukfHEHxukfEEH ]ÐUHHH}HuUHEHuH=[5HEHuXH=[5HEXHME1HHuHULEHMLIgH}&[HEHMHDHHR`HHDMDHHHEVH^HMHcHEH}E؋E;EHEHDxuHEMHHljuRhH}uEܙ*kEdH}EME1ҋuH}>E܃EgEH}HEЋE;EHEHDuH}h4HEuHHQhẼ}uԋEH}Eԙ0kEdH}EM|1ҋ|H}=EԃE;EH}kEċE;EHEHDuH}4HEuHHQhE}uȋEH}$Eș6kEdH}xxt1ҋtH}<EȃE:EH}EE;EHEHDuH}'HEuHHQh1ҋuH}IE6kEdH}ppl1ҋlH}<EEBHĠ]Ð`=@UHH0H}HEHH0HHExHEHEP@UH}.HuUH}H}XdEH}ldHEHEH0HxHHE HEHHQ H}d(;HEHD H};H0]fUHHH}uUH}uUH]fUHHH}H}xH]DUHHH}H}wH]DUHH0H}HuUHE}HE 1H}pHE@DHuH0HhMHUJ@H׾HEcH0]DUHHH}H}H]DUHHH}H}H]DUHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]f.fUHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHH H}uUHEHE!HMHAUQ H ]UH]DUHH]UHH@H}uHUHE}HEH=H5H97P}1Hc}HEH}Hw(uH}uUHMHHEH8Q1ƋEHMHBH9+UHE1HMHUH:HMUHMH9"HEHHHMHMffP THMHH@]ÐUHH uH}HUEEMQH ]f.DUHH H}HuHEHHEnTHMHcQHHH ]f.UHHH}HuH}5TH]ÐUHP]DUHHH}HEH|PH]fUHHH}H}gH]DUHH H}HEHHHEIfHEH0H.aH ]HHUsf.@UHH 1H}HuH}HUH}HHYSE1DH}HE:SH}HuH`HEH SH ]UHH}HuHU]f.@UHHH}H}IOH]f.UHHPH}HuHEHMH HHE+eHEHHMHRHEHHo1HEHHɉHEH}HM%uH}KRHUHHEH8YNHEHQQM1HEHHcxHEH}H$uH}QHMHHEH8MHEHQb1HMH9Q1҉HMH9HErQ1҉HMH9HEjQH}HuHUH^HEHD@HEHDAHP]ÐUHH H}HuHUHMHEHMHUHuH)HHHHrH ]f.fUHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HmHMHcHEHMEGEHME4EHME!EHMEEHMEE]ÐUHH}HE]fUHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}HEHHE@\1ɉHEH8NH]f.@UHH H}HEHHE6k\HEHQ`NHMH-1HEHQH}UD!UH}u[H}jH=H5;JH ]UHHH}HEHHm4$H]UHHH} 1NjuMH]UHHUH}uHEMH8;OHEH=6H5IHEHHMH8*mEHc}UU؋u)MHEHEHEH};0I,HEЉUH}TnH}HEL[nHEHlH}fH=sH5HHEHblH=H5HHEHQHMQH81҉(LHEHEHEHMH91҉KHEHEHEH}1ɉKHEHEHEE1EGHEH;E/HEHHHMHMHHHUf1f0]HEH;EEHEHHHMHMHHHUHHxf0Hxf0AHEHMHUHuH)HHHHlHEHMH)HHHEHEHEЉU,lHEHQHMq ։qHH;MH=H5FHEHH\K}E#1HEH0HWHEHHIHEHMHH9IHH=H5cEHEHQHq9H=H5(EHEHHpeIHpH9H=H5EHEHHhIHhH9H=H5DEHEHQ;UH=H5rEHĠ]H}LC HH`-h f.UHH}HE]fUHHH}HEHHEU1ɉHEH8hHH]f.@UHHH}HEHHEU1ɉHEH8HH]f.@UHH 1H}HuHUHMHUHuH)HHHωiH ]UHHH}H}c[H]ÐUHHPH}HEHHEHMqhHHHHMHUUtHEHMHHUHHHUQHE@f@HHHEtHEHHuH}]HP]HEUH}Tg%HEUHEUH}H}H}MA f.UHHPH}HEHHHUHHEHMHUqH}HuMH}vHEH8:HE@HHMH9H1ɨMuH}@EE$H ]f.DUHH H}HEEEHE}*EEHMHuHGRPUEH ]f.@UHH H}uHEuHHEE}(HEHuHQHJȉMEEH ]fUHH}HEH ]DUHH0H}uHEuHHEnE}HuH}5E}#HEHMșEEEEH0]fUHH H}HEEEHEuH}E*EEHMHuHPPUEH ]UHH H}uHEuHHEnE} EjuH} EEuH}4HEHuHOMEEEH ]fUHH0H}uHEHǾHEL E~uH}E}_HEHuHwOHMHEHuH\O;MHEHuHGHuH}=H}NH}H5HEHxHvNHuHx=H}N*HEȉUH}nN-HEȉUH}YNH}qH}cEE$HĐ]H}, f.@UHHH}H};;H]DUHHH}HuHEHuH=H]f.UHH H}uHE}HE"EHMHωE_QU9H=H5HC+H}y8HEuH QH>8H ]UHH}HEHx]fUHH@HHHMHuHMHH}HHEHMLH=H5>,HEH<HMHHELHcHHUHH}HHMHUHHMmLH}ȉ<HEH@]DUHH1H}HuH}Huab$H]fDUHH H}HEHHExD1ЃMH}dDȃEE$H ]UHHH}HuH}HuU:H]f.UHH0HHHMHuHMH}HHEHMCH}H5fK^H}CH}H5>J3H}CH}H5CJ H}HuNCHEH0]UHHH}H};H]DUHH0H}uHEEHEHEHHMqH51҃xU E;EME_HEHHMqH5PHEPUUH8HHMqH}Hj5HH}H6]EH0]fDUHH0H}uHEEHEHEHHMqH 51҃8U E;EMEbHEH8HHMqH}H4HH}H[6HEHHMqH4HEPUU[EH0]@UHHH}HuH}Hu._H]UHHH}H}H]@UHHH}HE@HHH8H5DHEDH]f.@UHHH}HEHEHEHHMqH3x,HEHHMqHt31ҋpH}H}$H]fUHH H}uHEHHEHHuEH=H5ձ'HEH8HuH}H2HH}He4MHUJH ]f.UHH H}HuH}HuD$H ]UHHH}HuHEH}HEHEHMEHMHHUrH&2HEHEHMHuH}+H}>EEGH}EEfH}&FHEUH}ZH}EEH}n&HEHHuH1HEHHHE_CHMAAuH}E 1HEHEMHHUH:Hu2HEHH}Љ||HĐ]H}$ @UHH}HuHEH;EHEHEHEHUfrfpHE]@UHH H}fuHEH HEH=H5"))%fEHMfA H ]fUHH0H}HuHEHMHHpHHE/HMHuH}jEEHUHHu؋NH׉ΉE/MԉHHEHuH/HHHu0MHEHuHljMq/MЉHEH0]f.@UHHPH}uHUHEuHHEzE}HH} H}Hu/HEHuH.HH#HEHuH}TAHuH};AH}Hu"A,H}AMċuHUH}7H}B/HEHuHh.pHUH}HEHuHC.MHEHuH).HM}(E;EHEHuH-@HEHuH-H"HP]f.UHHH}HE@@HHHHEz.H}w"H]UHHPH}uHUHEuHHEE}HEHuH'-pHUH}HEHuH-HH!HEHuH}g?HuH}N?H}Hu5?,H}?MċuHUH}JH}U-HP]fDUHHH}uHUHEuHHEE}LH}G"H}H}|HEHMH}HEHMHHUrH+HpHp7fnfnfH} HEHHMqHH`}+HXHX0H`\+HPHPHHU;JHEHHMqHHH+H@H@0HH*H8H8HH}H ,HuH}c51}7%HEHHHHH<77H}iMHEUhH}<H(H(M}`u1H}HEHuH *H H EHEUH}LH}*EEHEH1H)HHuHHEHHMqHa)HHH}HEH0HH*u1ɉH}H'H}H]H}H} f.fUHH H}HuHEHHUH; HE#HuH};H}Hup)H}EHEH ]f.UHH0H}uUHE}HEREE}BEHMHuHωE(U܉PHEHuH(HMH0]f.DUHH0H}HuHEHMHHDAD@fDI fDH HHHUHHHHEl!HMHHUHHHHE(HMHEHH0]fDUHH0H}uHEHMHEuH}74HEHuH'MHEHuH&HMHEHuH&pUH}JuHEHMHlju܉&PH}uHEHuH}&1HHHu8EHuHEHN&HH}HuHE1&HuHX'H}Hn1ɉʋuH} H0]f.UHH H}HuUH}HuU0H ]UHHH}HuH}Hus-H]f.UHH@H}uHEHǾHEL EluH}EHMHuH7PUHEHuHh71HHEH}Hu7Eԃ}AADEE$H@]f.fUHH@H}uHEHǾHE EuH}EHMHuH6PUHEHuH61HHEH}Hu61E1ED;EԈUEԃH}؉E6M9ˆUNJE$EE$H@]DUHH@H}uHEHǾHE EuH}EHMHuH#PUHEHuHz#1HHEH}Hu5Eԃ}AADEEH}؋uԋEԃ$E$EE$H@]fDUHHH}uUH}uU#H]fUHH@H}uHEHǾHE EuH} EHMHuH"PUHEHuHj"1HHEH}Hu41E1ED;EԈUEԃH}؉E4M9ˆUNJE$EEH}؋uԋEԃ"E$EE$H@]f.DUHH@H}uHE}HE EHEHuH!1ɉʋHMuH}+1ɉʋuH}HUHH}ЋwH׈ER!1HHEH}Hu3EH}uD"EE$H@]@UHH@H}uHE}HEEHMHωE_9U93H}H5MH ̠66H}H5-3H}!HEȋuH8H}H-!HEȋuH~*H@]fDUHH H}HEEHEEHMHHωET2U9HEHuH HH245HEHuH1HH;20H}EE]H ]f.fUHH H}uHE}HE"EHMHωE7U9H=]H5cH ;~HEuH7HH ]ÐUHHPH}HEHHH}HHEHEHH}HzH}Hu1H}0HEH}*HEHHd+HEMHEHM؃}[}"EHMHuHωE0ỦPEHMHuHωEUȉH}<HEHHYH}HMH}HHE))ЃH}H}HP]f.UHH0HHHMHuHMH}HHEHM6HEH5H}H@HEH0]UHH}HuHEHHMH;€]f.UHH0HHHMHuHMH}HHEHMHEHR5H}H:@HEH0]UHHH}HEH8XH]fUHH}HEf@]fDUHH}HEHHH]DUHH`HH}HuHMEH@H8H0EHuH@H(H(H0HHUHHH H-H}H -H}HH}H \EEH}Hu- H}t-HHHEH}&HEUH@ H}-HH}%-HHHEHuH@zHHH}|EEH}EEH0HH}HuHH}HH}HUHMHH0HHEHuH}HuHxH}Hx ,H}+HHHpHpHH@HFHHHpJHpH@HHHp HpHH@HHHHpJHpHHhHhH`HhHXH`HXU+mH`6+HHHPHPH@HHHP H`EsHpHDžLHLH)HpHDžHHHHH}H0HH@HeHHH0JEE H@6H8H`]H}  f.UHH@H}HuHEHHEHEH8Hu-HEH}.HuEH}HUHEH}%HEHEHHEHEH@]f.UHH HHHMHuHMH}HHE/H}H9HEH ]UHH HHHMHuHMH}HHE.H}H9HEH ]UHHH}HuH}Hu3H]f.UHH}HuHEHHMH;€]f.UHHH}HEH8hH]fUHH}HEHHH]DUHHHILEHuHuH}HHuHHMHUHEj'H=H5HsH}Hu,'H=^H5H5HEH8-HEHHUHHM=-HMH)HMHEHHuHHU-HUH)HUH}Hu1H}HuHH}HuHx4HcuH}Hp&HcuH}HhHEHHMHEHMH; HuH}HEHHEH}HuH}Hu&EHMuH}HUdHHXH}Hu%HXdH}Hu=HcUH}Hu%HEHİ]UHH0HHHMHuHMH}HHEHM2HEH+H}H6HEH0]UHH0HHHMHuHMH}HHEHMHEHR+H}H:6HEH0]UHH}HuHEHHMH;€]f.UHHH}HEH8TH]fUHH}HEHHH]DUHHP1H}HuHEHuHHE$E} EHEMH}HEuHf*HEHEH\*HEHEHEHuH}yHEHHEH;EGH};MHuH}@HEHMHHHUHHHEHMH)HEċEHMHr )Ɖr EĉEEHP]DUHHH}H} /H]DUHH@H&5HHEHHHDžHHH HHHH #jHH !9DžHH HHHV"HHH1HH DžDžIHHH!HHHH HH H $5H HUH9щH@]H< A) DUHH H}HuHEHH}HEDHMH9€H ]fUHHH}uHE}H HHM}H5KH fHEȺHHx#HEHHxHpH5YHp!HhuHhH}H5όH HEHH`P#HEHH`HXH5HXHPHHuHHHHHpHPyH}GH5*H EHhHH@"HEHH@H8rH5RH8H0HHuHH(H(0H0H}H5H H@HH "H`HH HH5HSHHHuHKHHpH'H` H5ՊH HHHS!H8HHHH5H HHHuHHHȃHR H8) H5 H 'HHH HHHHQH5gH HHHuHHHHHH Hp H5SH nHHHHHHHH5H# HHHHHuHHHHHHH"H H H H5jH HHHHHHHH5H: HHHuH2HHHHHHH HxH5|Hx HpHHuHHhHhHHdHpd{ HXH5HX> HPHHuH6HHHHHH=fFfFHP H8H5H8 HIH HEUH}~ HEUH}i HEUH}T HEUH`< HEUH8$ HEUH iHEUHEUHH9HEUHEUHbH H]H} f.UHH H}uHEH8uHEH}HE?H ]f.UHH H}uHE}HE"EHMHωEU9H=H5#H˱;>HEuHUHH ]ÐUHH H}@@uHEH8MHL4LELHEH}HEbH ]f.@UHH@HH}HUHMH}HHEHMUHMHH}HuH}HEH@]HEUH}H}: f.UHHH}HuH}Hus H]f.UHH H}uHEH8uHE*H}HEoH ]f.UHH}HE]UHH H}fuHEH8uHEH}HEH ]fUHH}HE@]f.@UHHH}HEHHHHEHEHHxH]fUHH H}HuHEHHUHHֺHEHEHHMHHHEHHHHEHHMHHHH ]fUHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HmHMHcHEHMEGEHME4EHME!EHMEEHMEE]ÐUHH0H}HEHHHHEmHEHHHE?HE@@H}HEf@ H0]HEUH}æH}8 UHH H}H}HEH}H?H}HuH}HEvH ]UHH H}HuHEH}HE/H}HCMH}HuXH}-HEH ]UHH}HE]fUHHH}HuHEHMHHH]UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]f.fUHHH}HEHH2H]f.fUHH}HuHEHMHMfDAfD@]UHH}HEf@]fDUHHH}HEHH]fUHHH}HEHEHMHH]f.UH]DUHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH}HEȺH!H@@@]fDUHHpHH}HuHMEH}HEHMTH} EEȃaH}HEЉUgH}NH}HhRHEЉU$HEHQHMq ։qHH;MH=H5HEHHHEH0HuHEHMHH9`HH=PH53HEHQHq9H=H5\HEHH`H`H9H=H5HEHHXHXH9H=։H5܈xHEHQ;UH=H5BHİ]H} HHPa f.DUHH}HE]fUHH uH}HUEEMH}Hu H ]f.fUHHH}j1NjuH]UHHH}HEHHEb1ɉHEH8nH]f.@UHH}HEH@]f.fUHH0H}uHEMH;JHEH}EHMHr9H}]1MHUH2~9OH}fHUH:G%EH}Hu_0MMUH}mEHMH;B6H}3HcMHHH}HEH}HuH/1H}H}HEHcMHHH}HuHEHMHBH0]fDUHH H}HEHHE~\HEHQHMH-1HEHQH}U4UH}u_H}H=H5+H ]UHHH}HEHHE1ɉHEH8H]f.@UHHH}HEHHE1ɉHEH8H]f.@UHH H}HuHUHEH;EHEHHHMH脡H ]fUHH0H}HuHEHHHEHEHEHHEHEH;E8H}HE; EHEHHEEE$H0]ÐUHH}HE]fUHHPH}HuU}3EHMHωEU‰UEH}Hu=UEHMHωEU9HEMHljHEHEHHEHEHHEH;ECH}HE;'HEHMHHEpHMH)HMEEHP]f.UHH H}uUHE}HEIEHMHωEU9,}"EHMHωEU9H=>cH5YHtH}HEHHHruHcHHHHH8wuHcHHHH*H ]f.fUHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH}HuHEHMH H]@UHH H}HEHHHE)HEH8H ]HHUUHHH}HEHHELH*H}9HHEHMHqHǺ,HEHH]f.@UHH}HEH@]f.@UHH H}HEHHHHEHEHHH}H ]fUHH}]fDUHH}]fDUHHH}HEHHHEG H}?H]DUHH0H}HuH}HEH}LH}HuUHEH}+H}HEHH HEHE HEHEH0]f.UHHPH}HuHUHEHHEHEH8hHEHEH8HEHEEH}ZHEHEHEHHuHHEHEEH}HEEH}HEH}=H}HEHHHEHEȉHHuH}h5HEH8HuHUHMDEAEHEHuH}.HEHP]@UHH}HEHH]fUHH H}HEHEHEHEHHy9HEHHIHuHHMHAHEHxHEHHJHEHHQ HEH8HEHMHHHH ]fUHu]DUHH01E1H}HuHUH}HHIIHULHEHEHMHHEH}؉HMHy6H}HuHzHMHAHEHxHEHP HEH@HEHx6H}HuH)HMHAHEHxHEH HEH@HEH0]fUHH0H}HuHUHMADEHEHMDEAHǾ EHEHEHMPHEHMPHEH0]fUHH}HEH@]f.@UHH}HEH@]f.@UHH H}HuHEHEHEH}JHEHHuHgHEHEH}ZHE H}NHEHEH ]ÐUHH}HuHEHE;€]f.UHH}HEH]f.fUHH`H}HuHE %4MHUHHUH}HHE6HEHEH}HuHUoE1MEFH}HuHEHEHEHHEH}HuHU EE4EE$H`]HHUfDUHH}HuHEHMH H]@UHH}HuHEHMHHH]UHH H}HuHEHHHEH}’HEHH ]UHH}HEHHH)H]DUHH HHHMHuHUHMH HUHHHHEHEH ]f.@UHH}HuHUHEHHMH;AAA]@UHHpHILEHUHMH}HHuHE($EH}HuH HǾ(HuH}HErHuH}YH}Hu@!H}$0H}H}HEfH}Hu:H}H5ouH}HE0H}uH}HEH})OMH}HE H}H}H HEHp]fDUHH}HEHH ]fDUHH}HEHA ]f.UHH H}@uHEH8uHEH}HEmH ]fUHH}@@uHEMHH ]ÐUHH H}HE1ɉHHEHi$5HHUHHHHEHHHEHHHEHHHEHH5HEƀ H ]HEUHEH]H} fDUHHH}H}+H]DUHH`H}HuHE1ɉHHEH#5HHUHHHEHHHHU/HEHHMHHHHEHEHHMHHHHE]HEHHMHHHHEdHEHHMHHHHE{HE HE؈ HHGHEHEHHEHH|HEHEHdH}<QHEUoHEUZHEUEHEU0HEUHEUH}6H`]H}H})H} H}NjHEH7H} UHHH}HuH}HusH]f.UHHH}HuH}HuH]f.UHH}HEH]f.DUHH}HEH]f.DUHH H}HEHHHHE蚟H}E莉H ]UHHH}H}H]DUHHH}H}H]DUHHH}HuH}HuH]f.UHH@H}HuHEH;EHEHEHHMHHHHMHHUHHHHEaHMHHUHHHHE<HMHHUHHHHEHMHHUHHHHE`HMD AHMD HHHEH%HEHHQH H}HEH@]f.DUHH H}HuHEHHUH; HE#HuH}+H}HuH}HEH ]f.UHH H}HuHEHHUH; HE#HuH}H}HudH}HEH ]f.UHH0H}HuHEHHUH; HExHEHHEHEHHHMHHH׈EHEH0HHEHMHHP( H}UHEH0]fDUHHH5HH}HMHHHHHMHEHHHEHHHEHHHEHH#HEHH]ÐUHHH}H}[H]DUHHH}HEHHEHEHH]fUHHpH>4HHEHHHHHHHHHH5O1ɉH HHHRHqHH4HHMH9NHp]HHHHH  fUHH0HLN5ILMHuHUMHUHMDULEHE3HEH0]UHHPH}HuHUHEHHHuHHMHEZEH}QHuHEHHEBUH}Hu}H}HEЉUH} ?HEH"HEHHHuHHuEHP]H}[ f.UHH@H}UMHEHHMHuȉHE.E} E<H}HuHUHMc~H}о}FH}uк}XH}HEHHHu"HEHHHuHHuuH}U}H}HuabH}%}HEHHHu\"HEHHHuYHHuEE$H@]f.@UHH}HEHx]fUHHpH}HuHEHHErHEH8HuHEH}wHuHEHHuHEH}HuHU0HEHEHEH}HEHEHEH}ą#HEȉUH}诅HEH HEHEHp]H}跽 UHH H}HuHEHHUHHHEHMHEHH ]DUHHH4HHEHHHHHHHhH`HHHHhHXHHPHH`HXHPH腄H`HHH5$J1HpJHHpH`|HpHH`HHVLHH4HHMH9LH]H|UH|H脃7H|H|HpHhH\H^ c UHHH}HuH}HuH]f.UHHH}HEHHHHEHM0EUH}Hu胋H}莼HEHEHuHHEH}HuH}UH}Hu貙H}HEHHEH}HEHEHHHEHEHuHHEH}HuH}H}{HĀ]HEU%HEUH}VHEUH}AH}8H}͹ f.UHHpH}HuHUHEHHHHMHEBHUH}H.H}kH}bHUHEHHuHUHEHuH}HUHMEEEH}߀HEȉUH}ʀEEHp]H}ڸ f.UHHpH}HuHUHEHHHHMHERHUH}H>H}{H}bHUHEHHuHUHEHuH}HUHMEEEH}HEȉUH}EEHp]H} f.UHH`H}HuHEHuH}ع H H=1H} fU؋MH}H AHEHEEH}JH1ƺ H EH}HHEHHH=H}+<uHH}#<uH}H}HH}HH5DH}H}HuH}H5BH}QH}HuXH}\Hx:<Hp1MpxH}HuAIHhHEHH5:CHPH}1xHHH0;DHHXHPH\H}!HH@00;D@H`HXHHhH`WH`HHXHPHEUHEUHEUHEUH}HEUH}HEUrHEUHEUHXxHPlB}H5AH} EEHhxmH8HhHHHHH8HEUH8eEE&H} HH5@Hȃ44HHHQ9H("zHuHhH(HH(z00ME&HEUH(y:EEHhEH};H}3H}*,HhH};H}H}H};EH`]H};H}p UHHH4HHEHHHH`HHXHHH`HPcHXHPOH-OHXHHH5>1HpOHHpHX聜HpH$ƅDžl}H|HeH|H|H|Hp#HTƅDžlHH 4H HUH9шN.N$H]HBHD I f.UHHH}HEHH"H]f.fUHHH}HuHEH}HHEyHuH}lH}H}evH}rHuHHMHH}1ҹALMH}HuHuHUHMH}EM9H}UuUUUH}UpH}uH}^H}H}UHĀ]HEȉUXHEȉU:HEȉU%HEȉUHEȉUH}juH}H}XuH}H}6H}-H}b fUHHH}HuH}HucH]f.UHH H}uHEHHuHHE贃E} H}oEH ]DUHHHLUIL]HuUMDELMHuIIMHXLHPHHL@sEԃ}%}HPHuHEԃ}HXVHPHuHHEH}"H}HXEHPHuHEEHPHHω<<9+HPHH1ɉʉEċuHP<H}HPHHH0H0,,EuHP(H} ( HXNH}Hu8H}HulH}H}.HEUHEUHEUH}H}HPHHH H EuHPH} HVMH}Hu9H}HumH}H}*HEUHEUH}H}HPHH HHUȋEH}E1HW H}HuϹH}gEUHpHP23HxHp1H}HxmHxHpfpEHEUH} HEUHEUHxHp!pH}>UHhHP{2H}Hh薶HhHoH}CUH`HP0H}H`^H`H}u1HPlHXHu<H}H}HHH]H}G UHHH}H}H]DUHHpH}HuH}HEH}HHMHHHMIiEH}0EEH}EEEH}HuNH}HuH}HuH}HEH}HHEH}HuHuH}EE#EHE؉UH}}X^H}u1輮EH}螳&EH}E(XE$Hp]H}菥 f.DUHH H}HuHEHHHU2HHE~H}gH ]ÐUHHH}HuHEH}HHEH}0H}lHuHHMHH}1ҹALMH}HuxHuHUHMH}EH}mlM9H}EE4H}"HuH}@EENEEHEUHEUHEUHEUH}kHuH}H}-EE EEH}H}SkH}H}1E$HĀ]H}H}kH}H}H}1 UHHH}HuHEH}HHEH} H}jHuHHMHH}1ҹALMH}HuhHuHUHMH}EH}]jM9H}蠾EE4H}HuH}0EENEEHEUHEUHEUHEUH}iHuH}H}-EE EEH}H}CiH}H}!E$HĀ]H}H}iH}H}H}! UHHpH}HuHUHEHHHHMHE袢HUH}HoH}˺H}`bHUHEHHuHUHEKHuH}HUHMf1EEEH}?hHEȉUH}*hEEHp]H}: f.UHH0H}HuHEEEEEHEH}H}HEH}H荛E9}EEE- EEEEH}ؾ`E!H}ؾ襻EE}'HEHHtEEH0]fUHH}HEH]f.fUHHH}HEHHʽH]f.fUHHHN4HHEHHHHHHHPƶHHHHHHHH5CBHuHHHHuH5 BH2HHHcH2HHHxγHjGGTH@FF*HEE.HDDH5FH菭HHHHHHHrHHH!CCH5EHĬH5)Hh;HpHhHHL:HxHpHHH8H0HH0H(HhH`HH8H HH H`証<HHh芼HH`lHHP\\HP \1HxH^HP讶HHPHHP\1HޢHHPHPHHω9 1HPhHP HxͺHH赺H詺H-Hƻ4HHMH9SH]HxqHeHYHMHHӘ ؿ f.fUHHH}HEHHHHEq H}9[H]UHH HHHMHuHUHMHHUHHEGHEH ]ÐUHH0HH}HuHMEHHH(H5 <H}(H}HUH_H}HuкBH5fAH}H}HuHH}HH}׸H}θH}ŸH}輸H5W;H}|H}HUHH}Hu薷H5@H}7H}Hu>HH}H4H}+H}"H}H}H}oHuH苦H5}:Hx葷H}HxHH5?H}XH}|HxpBH59HhH59HXH`HXH3HH 轠HHPڠDPHpHhH`1蒵HpH`Hp蝶H`葶HX腶HhyYHEUAHEU:HEU%HEUHEUH}4H}+H}"H}HEUHEU:HEU%HEUHEUH}ԵH}˵H}µH}蹵cHEUNHEUHEUH}茵Hx耵!HEUCHEU+HEUHEUHpDH`8HX,Hh H}z"H57H臣HuHtH58H8zH@H8HH5<H0CH@H04H01H@%H8H>eH56HsHHEU+HEUHEUH0蘳H@茳H8耳!H56H 8H(H HiH5HH(HHHH觡HH(زH ̲HHEU+HEUHEUH蜲H(萲H 脲%EH}rH}iE(H}QH}HH7HH0]HH}谐 UHHPHL +4M LMILHHHLHHHHӐHHHHHtHHaHHMHHMHHxHHpHhHEHHXH@H`HxH@HpH(ѦHhH辦LEHXH`HHUHEHMH@HEH(HEHHEHEHEHEHEHEHEHEHEHEHEHEHuHUH#H4HHMH9HHP]յ fUHH H}uHEHHuHHEfE} H}.QEH ]DUHH0H}HEHHHUHHHEHU~HEHHHuHHEHHuH-HEHHuH H}xH0]HEUH}bH}Ǎ UHHH>4HHEHHHHHHxHHxHHH51H HHHx4HHEHHHHHHHHHBHۭ4HHMH9;$H`]HHH  fUHHH}HuHEHT$H]fUHHPH}@uUHEHHHHE͢ EH}HEH}HuH}vH}HuϗHuH}誩H}HugdH}KH}Hu*H}U9!H}գU9 EH}OuEE$HP]@UHHH}HEHHRH]f.fUHHH}H}H]DUHH HHHMHuHMH}HHE~H}HZHEH ]UHH}HuHEHMH H]@UHH HHHMHuHMH}HHEH}HHEH ]UHH0H}@uUHEMHUHE EHEHH豠E} EXHEHUH}H\PH}1DED9ˆMH}U9E׊E$EE$H0]f.DUHHH}HEHHE}H]f.fUHH H}H}H}HHujH}EXH}EH}$E 1EEH}MU҉$H ]@UHHH}@uUMHEHHHE&E}HEHUH}HNH}蛠U9hH}}U9P}/H}+0H}3;EH}EHEHHOHMHHHMwHH}H}Hu诓H}HuH}HuxH}HuHMH},HEHEH}Hu趡H}zU9H}K~~U9}`H}}}H}ߞxx蓆tt;EOH}FHhH}Hh8EE4HEUH}7\H}XEH}6E EE$HĠ]H}'  DUHH}}C EE3}EE 1EEEEH]fUHH}HuHEHMH H]@UHH@H4HHEHpHhH`AD_HpHHHH裼HHHf XX`HhH`H@HHHHzH@HHHdH@cJHHH51H89HH8HknH8芣HƅDž4HPL+HPLH@I HPLHPLH8 H葾HhHHXHHEHHHH蕢JHHHXH)HHHp&HHHXH҈H`H(HHXHH/H(ΡH-_9H:EHPLH(wGHvHHHH2H5 1H {HH HkH ̠HPƅDž4<HPLHPLH HCHH 4H HUH9ш.$H@]H读HP~ 趥 f.UHHH}uHEHuH@HH]UHH0H}HuHEHHEREHEH8Hu菡HEH}HEH8Hu蠒MMEH0]UHHH~4HHEHHHHHx-HxkHHH5 1HLHHHx~iH蝞H!HH4HHMH9lHĐ]H7HHH(H謹H蠹H| 解 f.UHHH4HHEHHHHHXHX;HPHHP>HH辉HH艉HHSHHX[HHHHXHH HXH)H5MHKH-HHHH1AHxAHXHHX?HpސHhbBHHxHpHhDHhEBHpɛD9HXHH艒@@ddHXHHHHhAHp'HHXo<<HXHNHx貚H+HHÛ4HHMH9GH]HHxbHv+HHx  DUHHH}HEHHHHEZfH}1H]f.UHHPH}HuHEHHHHEzHUH}H GH}pH}?HuHUHMAH}EH}?H}mE$HP]HEЉUHEЉUH}?H}:H}w f.DUHHPH}HEH}HuHƉỦDẺMDHEH}HuUHUHME1H}HuEH}?H}蜘E$HP]HEUHEUH}>H}iH}v f.@UHHHILEHuUMHuIIMH}LHuHE=E} }bHEHH5HMHHEHM螗HUH}HuHM襑H}諗wHEЉUH}薗oHEHH5%HMHHEHM4HHEHHHHHHHhHHHhkddHhHH胭H51Hp|HHpHh_HpH衰NH|zH|H|HpϔHS>H`6H ϕ4H HUH9)`HĠ]HHs  f.DUHHpH}HuHUHEH}HES E@H}诎EEEH}E M9H}uH}HE茈H}:HUHMH}Hu H} :H}蒓H}E؃EwHEUHEUH}9H}QH}諒SHuHEHHE'H}Hu`H}HEUH}1‹uH}LzM܉MEHp]H}^q f.@UHHHΓ4HHEHHHHHHH`HXnHHHH`HPHHH|HHXHPHHDH_8DHXWHH©H541Hh yHHhHX=\Hh\HlHxtHxtH7zHxtHxtHhHt>H@WH 4H HUH9)@H]H%Hx'o , UHHPH}HuHUHEHHHuHHMHEKEH}規QHuHEHHE"UH}Hu]H}HEЉUH}?HEHˏ"HEHHHu{vHHu|EHP]H};n f.UHHH4HHEHHHHHHHhUHHHhkddHh舲HHH5e1HpH`覩H ?4H HUH9)`HĠ]HtHvl { f.DUHHH}HuHUHEH}Hp轍 E HpEEHp+HpчH}ȺHp͇HpH}l赁H}<3HuHUHMHpOhhEH}"3H}詌EHEUHEUH}2H}xH}茌H}H`H}2HUHMHpH`\\EH}2H} *HEUHEUH}Z2H}y1‹uHp=sMԉMEH}艅X͋X9H}uŋH}HPGH}1HUHMHpHP辨H}1H}GHp覼EEeHEUHEUH}|1H}H}]eHuHxHHHӐHpHHHx襊HEUHx荊%1‹uHpqM؉MEH]H}h UHHHn4HHEHHHHHHH`HXHHHH`HPHHHHHXHPHH&DH/DHXHHbH51HhpHHhHXSHhH耤lHxtHxtH0/zHxtHxtHh萈H>H@H 4H HUH9)@H]HţHxf ̍ UHH}HEH@]f.fUHH H}uHE}HEEHMH;BH=H5=HZXf1HMH9jHcMHHH ]UHHH}uHEHuH1$H]ÐUHHH}HEHHE\H=HH5]gH}H]UHH H}uHEuHHE`HEHuHJH ]f.UHHH}uHEHuH.$H]ÐUHHH4HHEHHHHx HHx3HxHH H51HRmHHHxPH装H'HZH7HHHIH͠H HU4HHMH9HĐ]Hc 裊 UHH H}uHEHHuHHETN$EE H}E$H ]f.@UHHH4HHEHHHHHx]HxKww$HHH51H[kHHHxNH謃H0NHHHH^HCHvŞH ^4H HUH9.v$HĐ]H莞Ha 蕈 fUHH`H}uHEHMHHEHMɬHEHuHHU>H}bHEHuH}kHuH}RH}Hu9H}HEHEMHUHHuH iHEHHuHiHEHHuHhH}naHEUH}H}H`]H}H` UHHH}uHE}HE!1HMHHϾP?}HEHHxd1HMHHϾ?HMHHwH5P6HEH}GHuH}1^HEHH5H}HE艀HuH}#iHEHEH}HHEoH}HE}H}tHEHH5"HMHHEHMH}HuhHEH5 H}eoH}?HEЉUHEЉUH}H}1HEЉUH}H}HĀ]H}P^ UHH}HEH]f.fUHHH}HuH}Hu}4$H]fDUHH HHHMHuHMHH}HHEu1H}Ha\HEH ]UHH HHHMHuHMHH}HHEuH}HSeHEH ]fUHH@H}HuH}HuHEH}HHE蔄1ҹH}Hu谫H}r~H@]HEUH}\~H}\ UHHH}HEHHHHE*IH}QH]f.UHHH.4HHEHHHHHHwHH迕H5{1HeHHH:HHY}HݘHјHj~4HHMH9lHĀ]H7HHH|HhH\H^[ c UHHH}HEHHHHEncHEHH\cHEHHcH}H]UHH H}H}HEH}H@kH}Hu%cH}HEH ]UHH H}H}HEH}HkH}HubH}HE覓H ]UHHH}HuHF4H0HEHHEs{H}1HuiH}{H}H}HbHEHEHEHMHMH}bHEHEHEH}Hu.uEEH}uHEHEHHuHEHuH}iHxH}HxjH}HMHpHHhtH`HpH`aHXHXHuiH}HPZzH}MaHE؉UH}7z<HE؉U'HE؉UH}zH}BhHİ]H}0hH}X f.UHH H}HEHHE`HEH8mH}H|HEH ]fUHH}HuHEHHMH;€]f.UHH H}HEHHE>`HEH8lH}H HEH ]fUHH}HEHH ]fUHHpH}HuHEHHE_HEH8HuzHEH}wHuHEHHuHEymH}HuHU_HEHEHEH}rHEHEHEH}tx#HEȉUH}_xHEH HEHEHp]H}V UHH}HEHH]fUHHH}HEH8HEXlHMHHH]@UHHH}HEHHHHH]DUHHHx4HHEHHHHH胏HHH_H5-1H^HHHAHvH}HqH x4HHMH9lHĀ]H7HHHvHHHT | UHHHnw4HHEHHHHH#H'HHH51HH]HHHz@HuHHHv4HHMH9lHĀ]H7HHH$uH訐H蜐HS z UHHH}HEHHH5|HUHHEHMHUtH}HuHU?pH5H}JtEH}}tH}ttE6EHE؉UHE؉UH}pH}5pEEHĠ]H}N fUHHH.q4HHEHHHH8HH0ЇHHH8H(uHH(KHzoH`HH8H ]uHhH0H #H`2oHXH0dHXHhsHHh]HH8H]`HxtHn1HxtH`nHxtHxtHPHH8H;tH0HlHPnH0fHHޅH5HHmHHHH0b8HHmHƅDžDkHxtHPFmHxtHxtHHmH蚈xƅDžDHXlHhlHlHTH m4H HUH9шR$H]HXlHhulHilHHxJ q UHHHHHMUH}HHuHE|kEH4H0HEHHEkH}1HuZHuH}ZH}YH}k*HE؉UHE؉UH}YH}|kIEH4H0HEHHEkH}Ⱥ1HunYHuH}ZH}TYH}k*HE؉UHE؉UH}*YH}jEH4H0HEHHEjH}1HuXHuH}{YH}XH}|j*HE؉UHE؉UH}XH}RjH}HuHEHĀ]H}H UHHHH}HuEH}HUHE^H5&6H}_1}%HEHHHHHf!EH}FHEUH}FfHpH}HpPo}!EH}6iHEUH}Hu1EWEUH}1HugllEH}Hu1VHuH}XH}hH}.ghhEE}HEU?HEU*HEUH}ZhH}VEH}qVH}.h!H}MREE-H}+EEE H}gHEHĠ]H}gH}[F f.UHH`HH}HuUMHuUMLEH}LHuHELE!HEHHuHE]mH}HuHU,H}>gH}5gHEH`]HEЉUH}gH}gH}E UHHHh4HHEHHHH`HHX~HHH`HPlHXHPOH]fOHX辉HH6~H5HHpeHHpHX0HpeH]ƅDžl}H|HeH|H|H|Hp\eHTƅDžlH辀H Qf4H HUH9шN.N$H]H{H}C j fDUHH`H}UMHEH}H}HuHHEHH}Hu=SHEHuHHErjUMH}Hu诂EH}NdH}EdE$H`]HEUHEUH}dH}dH}B UHHpH}UMDEHEH}H}HuHHEtH}bEE0uH}juH}-R HE؉UqH}HupRHEHuHHEQiUMH}Hu莁EH}-cH}$cE$Hp]HE؉UH}cH}bH}A fUHHPH}HuHUHMHEHHHHEnHMHMHH\HMHHωEi\DEAHMDH}HEHEHHEH}[HEH}[HEH}Hu[?H}[HEHEHb HEH}HHP]UHH0H}HuHEHHEHEHEH8HucHEH}HEH8HuTMMEH0]UHH H}uHEHHuHHEEuH}[E#HEHuHWH}[EE$H ]UHHH}HEHMHHuHEHMdH}HuOH}HE`H}HuDHE4H0H}Q`H}Huغ1NH}Hu>OH}NH}?`H}_H5QH}_H} IuH}IDEH}Hu1HU^H}HupNH}_H}_`HEЉUHEЉUHEЉUH}MH}q_HEЉUHEЉUH}P_H}G_vHEHuHHp+eH}Hpa}H}_H}JH}^$HĐ]HEЉUH}^H}^H}X= UHHH}HEHHEH})H]DUHHpH_4HHEfH@HHHHEvHRHHQ H IHX@4HHhH]H=]1ff`HXkf`XobuH5H@5]ff8H( G(H0GD08HHH@1[H FH FD HPHHHh1[HHPKHPH\HH\H@z\rHxtk HxtM Hxt/ HxtHxtHH\H@\ H5FH[HHHh`HH1IH5FHe[HHHJHe[HIHM[HA[H5|HZHHHh)`HHH`HH1IH5jHZHHHIHZHHHqZHeZHYZH5HZHHHhA_HH1MHUH}HuH}x>H}5PEE8*HEЉUHEЉUH}@>H}OH}OHEH`]H}z. f.UHH0HP4HHEfH@HDAH= ƅ HHXgHCHH H IHk14HHhHNH IH@14HH`HNH%N1ffXHPSfXPWS`H5˻H8Nff0H 7 H(8D(0H@H81LHHH@HhH`LHHH<HHHMH@MH8MHxt Hxt Hxt Hxtk HxtHxtH@MH8M/ H5CHLHHHhQHHH`QHH1:H5$HCLHHH`;HCLHq:H+LHLHLH5NHKHHHhPHHH`PH6HHPHH19H5HH5pH}>H} (uH}(DEH}Hu1HUl=H}Hu@-H}>H}w>`HEЉUHEЉUHEЉUH},H}A>HEЉUHEЉUH} >H}>vHEHuHHpCH}Hp1\H}=H}H}=$HĐ]HEЉUH}=H}=H}( UHHpHILEHuHUMHUHHMH}HHEHUE}H}H5ɢ<HEHHMHUHHHM 7H}.<EE6H5vH}<EHEЉUH}<}H}Hu1‰+;EEEă}#HuH}:EH5H}<EH}/H}Hu)H}HEd:H}HuH}N:?HEUHEUH}g(H}$:"HEUH}: HEHĀ]H} fUHHH}uHEHuH~7H]@UHHpH}UHEHHUHHuHE>E}OUH}HuHw4H0H})9H}Huغ1t'H}Hu(H}Z'H}9HEHuHHE?UH}Hu>WH}8HEHHuHE>UH}HuH}8H}8iHEЉUOHEЉUHEЉUH}&H}j8%HEЉUH}U8HEЉUH}@8H}78Hp]H} UHH@HILEHuHUHMHMH HuH}HHE9HEH}HEH HEHEHEHEH}H=HEH@]UHH HHHMHuHMH}HHEZH}H*HEH ]UHHPH}H6H0H~HMHHuHHM6H}HuHU.H}q:E1MEH}E+H}6EHP]HE؉UHE؉UH}+H}6H}G UHHPH}Hݥ6H0HHMHHuHHM<6H}HuHU-H}9EE"";EEE 1EEH}E*H}5EHP]HE؉UHE؉UH}*H}5H}X UH}uE E]f.@UHH`HH}HuUMDEHuUMLMH}LHELMHEHHuHE=;UH}HuH}5H}5HEH`]HEȉUH}4H}4H} UHHH}uHEHuH,$H]ÐUHH0H}uUHEHHuHHE1E}4}*HEHHHuuHEEE$H0]f.@UHHH>54HHEHHHHHHh~$HHhKHhHH{KH51HpHHpHhHp3HNƅHNaH|7H|H|Hp2H8NH,N>ƅH 34H HUH9шg"g$HĠ]H 7 @UHHH^34HHEHHHHHHpHhHHhIHp1gg\HhHHH?HXHXHp8HHhHHHHHIH51HxdHHxHhHx0H9LƅH&LOHHHxf0HKHK>ƅH e14H HUH9шW"W$Hİ]H 5 fDUHH@H}uH}HEH}HHEUH}HuyEH}E$H@]HEUH}H} f.DUHH@HILEHuHUHMHMH HuH}HHE-1HEH}HEH HEHEHEHEH}HMRHEH@]UHH}HEH@]f.fUHHH}HEH8!H}H|=HEH]fUHHH}HEH8!H}HL=HEH]fUHH}HuHEHHMH;€]f.UHH}HEHH ]fUHHH}HEH8HE0HMHHH]@UHH 1H}H}HuHUEEAADEDEAAH ]UHHH.4HHEHHHHHxmEHxHHwwHH#EH51HlHHHxH,HAHNHhHHHo,HG,HGH{-4HHMH9#HĐ]HGH  1 UHHH.-4HHEHHHHHxCHxHH4wwHHCH5!1HHHHxH-+HFNHhHHH*HcF,HRFH+4HHMH9#HĐ]H&FH(  -0 UHH0H+4HHEHHHǾH$HHHHHAHHHk HHHG HHHxHxk'DžttHx'9/Hxt;'HHHh1H蝐H5HX(H`HX1HhH`H`HX(H58H8>(tH0H  H(D(0H@H81&H HDHHH@Hh1&HPHH+HH'H@'H8v'HHPc-Hxtu%HHH1HwEH'HP 'Hh&ttHHHHH`HX&H7HHHHM&H@A&H85&%HH&HP &Hh%HH=H51H@ HHHrH%HA<HHHU%H@H@H@ HK&4HHMH9H0]H * f.UHHH}uHEHuHn"@H]UHHH}uHEHuH>"HH]UHH H}uHE}HE"EHMHωE/(U9H=_H5H[?HEuH'HCH ]ÐUHH HHHMHuHuHEMHEH ]UHH H}HEEHHuHHEE}$EEHMHuHWEEH ]fDUHHH}uHEHuH @H]UHH H}uHE}HEuH}sTE1+EH}rEEH ]f.DUHH 1H}uHMuHHM  H}H ]f.@UHHH}HEHHHHEz H}H]UHHH}HEHHHHEZHEHHHEHHHEHHH]f.@UHHH}HEHH H]f.fUHH H}H}HEH}HP1H}Hu H}HEF3H ]UHHH}HuHEHHuH$H]f.DUHH 1H}HuHMHuHHMHHMH;AAAH ]f.fUHH}HEH]f.fUHH H}HuHUHEHuHHMHHuHHHuH ]fUHHH}HuHEHHuHH]@UHHHN!4HHEHHHHHHhH`7HH1HH`3HHH7HpHHhHX]%HH`HXHp-H:H:H> 4HHMH9xHİ]H|CH|H%H|HpH0:H$:H& +$ f.DUHHH}HuUHEHHHuUHHEHEHHHEHHHEHHDEAH}A5HEHHH56HHuHEHH ԥHUHHuHHEHUWH}HuHEH}Hu H}HEWHEHH5HMHHEHMH}HuHEH5H}H H}*HE؉UH}HE؉UH} HĀ]H}[ f.UHH`H}@@uHEEHEsHEHH5HMHHEHM5H}HuHEH5-H}{ H}1aHEUH}RH5FHEHHEH}HuH}HEUH}H`]H}Z f.UHHPH}uHEuH}HEHEHH5,H}HE?HuH}HEH}Hu} H}HE:H}1HP]HE؉UHE؉UH}H}H} f.UHHH4HHEHHHHHx2HxHH2H5Q1HHHHxH-H5H5H>4HHMH9lHĐ]H7HHHH<5H05H2 7 f.UHHpH}HEHH5HMHHEHMH}HuHUH}HuDH}H}EH5HH}H}HuEEMCH5 H}EH}HuLEEEE$EE H}oH}fH}]E$Hp]HEЉUHEЉUH}3H}*NHEЉU9HEЉU$HEЉUE H}H}H}H}l f.fUHH HHHMHuHuHEHEH ]UHH H}HuHEHHUHHHEhHMHEHH ]DUHHH}uHE}HHHH E}5H5H HEȺHHHEHHHH5HH}H5H HEHH`HEHHH*H5HHHHHMHHH H}HUHHHuHXH}H}H}&H5H ̓HXHHHxHHHN H5ۃHHHHHHHHH HPHUHHHPHsHPHHHx8H5ɂH ߂H HHH@HHH` H5HHHHHH譺HHUHH HH1HHpHH[HOH@)HEUH}HEU%HEUHEUH}H}H}HEU+HEUHEUHPOHHCHxiHEUCHEU+HEUHEUHH_HSH@- HĀ]H}^ f.@UHH`H}HEH5H HUAHH(DH LHEHH(H H54HH}H5H HEHHHEHHH H5H@HH HHHH}EH HHLEE;E_H HuHuH EEHEȉUH}zHEȉUH}eHuHUHMH H5~H dHXHHHxHHHpH5YHHuHHH5'HHuHHH5~HHuHHH574HGHx0H5}H L~H0HHHPHHHXH5]~HHH54HHPH`]HEȉUHxHEȉUHPsH} fUHH H}HuHEH8HuHEHMHEHH ]f.UHHH}HuH}HuH}{HEHEHuH}HuH}H}Hu| /H}sHEЉUHEЉUH}RH}6 HEHEMH}EHuHUEEE}9H}HuHEH}HuHEH}HuH} H}HuH}k%HĀ]H}Y%H} f.@UHHH}HuH}DHuH}HEHEHuH}[HuH}1H}Hu /H}HEЉUHEЉUH}ҝH} HEHEMH}EHuHUEEE}CH}HuHEH}HuHEH}HuOH}H}HuFH}#HĀ]H}#H}t @UHH}HE ]fDUHH}@@uHEM ]f.@UHH`HH 4H HMHHHHHHHH;#HHH5\y6HT HzHJKH`DžWHxHHvZHHUƅHHl9HHHL4ƅDž(HH Dž Hh  HDžH$HW 4HHMH9*HH`]H$H  fDUHH HHHMHuHMHH}HHEeH}HCHEH ]fUHH@H}H}HEH}H0H}7HEHuH}aKEH}@E$H@]HEUH}"H} UHHpH. 4HHEHHHHHHHPHH 7HH1H*H/H8mH"H/4HHMH90Hp]HH]"H_ d  UHH H}H}HEH}H0H}Hu}H}HEV1H ]UHH`H}HuHEH8HEV zH}HEHuHUH}CHEUH} HMHr Ήr HE HEU^ HUHuH}H}HEHEHEFHEUH} HuH}HE< >HEU HEHMHH`]H} HHU fUHHpH}HuHuHC4HHMHHuHHMH}1Hu H}H}ȺHublH}Hu1‰6EH}EEЃ}H}HuH}HuEEEE]EHEKHE؉UH}WHE؉UBHE؉UH}-HE؉UH}H}H}Hp]H}H}N f.@UHHpH4HHEHHHHHHlHH!HDžHHHHHY4SHHHHHH,HH4HHMH9Hp]H  f.UHH H}HuHEHHHUHHHHEE1DEHEHHMHHH~1ҨUUHEHHMHHH1ҨU#HEHHMHHHnEE$H ]UHHH}HuHEHHMHHH$H]DUHH`H}HuHEHHEH}EM9 EHEHHUH;  EH}NHEH}AHEH}"HEH}Hu H}H}HEH}HTYH}H}HEH}H/H}H}HE}H}H EH}hH}HE[-EE$H`]@UHH`H}HuHEHHEjH}E^M9 EHEHHUH;  EH}*HEH}HEH}HEH}HuH}H}HEH}HtYH}H}HEH}H/H}lH}HE_H}H EH}DH}HE7-EE$H`]@UHH0H}HuHEHHHHEHMHHωE1DEA9UmHEHHHMHHωE1ҋu9ƈU5HEHHHMHHωEU9@@uE$H0]UHH}HEH@]f.fUHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]f.fUHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HmHMHcHEHMEGEHME4EHME!EHMEEHMEE]ÐUHH H}HuHEHMH H;HE#HuH}+H}HuH}uHEH ]f.UHHH}HuH}HucH]f.UHHH}HuH}HuH]f.UHHH}H}H]DUHHPH}HuHEHMH HHEHEHHMHRHEHHo1HEHHɉHEH}HuH}7HUHHEH8)HEHQQM1HEHHcxHEH}H路uH}HMHHEH8HEHQb1HMH9~1҉HMH9HE^1҉HMH9HEVH}HuHUHHEHD@HEHDAHP]ÐUHH uH}HUEEMOH ]f.DUHH H}HuHUHMHEHMHUHuH)HHHH.H ]f.fUHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}HuHEHMHHH]UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH H}HuHEHMHH}HEHMAH ]f.UHHH}HEH8p1ɉUH]HHUZf.UH1}}E }EE$]fDUH1}}E } EE$]fDUHH H}HuHEH}HE/H}H3H}HuH}mHEH ]UHH}HE]fUHHH}HuH}HuH]f.UHHH}HuHEHMH HHMHH]UHH@H}HuHEHHUH; HE EAHEHEHMHωE6U9 EHuH}$EE$H@]UHH@H}HuHEHHHEHEHEHHEHEHHEHEH;EYH}H}HEH}Hq E*HEHHEHEHHEEE$H@]UHH H}HuHEHHHUHHHHEE1DELHEHHMHHH1ҨUHEH HUr 9@@}E$H ]f.UHH}HuHEHE;€]f.UHH@H}HuHEHHUH; HE EAHEH%HMHωEU9 EHuH}$EE$H@]UHH@H}HuHEHHHEHEHEHHEHEHHEHEH;EQH}H}ЉMM; E*HEHHEHEHHEEE$H@]UHH H}HEHHHEHEH8oH ]HHUUHHH}HEHHEH*H}HHEHMHqHǺHEHH]f.@UHH}HEH@]f.@UHH H}HEHHHHEHEH HhH}}H ]fUHH H}HEHxHEH}H8HEHxH}HH ]f.UHH}HEH@]f.@UHH}HEH@]f.@UHH H}HEHHHEHEH8{H ]HHUUHHH}HEHHEH*H}H/HEHMHqHǺHEHH]f.@UHH}HEH@]f.@UHH H}HEHHHHEHEH HH}H ]fUHHH}H}蛔H]DUHH H}HEHxHEH}H6HEHxH}HH ]f.UHH}HEH@]f.@UHH}HEH@]f.@UHH H}HuHEHMH HHEHEHHMHoHMHHEHHxLHEHH@HMH1HHMHHBHHxHHH`HEHHH ]@UH]DUHH01E1H}HuHUH}HHII HULHEHEHMHHEH}؉HMHy6H}"HuHzHMHAHEHxHEH HEH@HEHx6H}HuH)HMHAHEHxHEH? HEH@HEH0]fUHH0H}HuHUHMADEHEHMDEAHǾ(E^HEHEHMPHEH HuH3HEH0]fUHH H}HuHEHMH HHEHEHHMHo HMHHEHHxLHEHH@HMH1HoHMHHBHHxHHHHEHHyH ]@UHU]DUHH01E1H}HuHUH}HHII HUL1HEHEHMHHEH}؉jHMHy6H}HuHzHMHAHEHxHEH0 HEH@HEHx6H}eHuH)HMHAHEHxHEH HEH@HEH0]fUHH`H}HuHUHMADEHEHMDMA(HEHEHEHEHMPHEH HuH! ]HEȉUH}7HEL{HEȉU#H} HuH}HE <HEȉU HEH`]H} HHU f.fUHHH}HuH}HuH]f.UHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}HuH}HuH]f.UHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}HEHHHE H}H]DUHH0H}HuH}7HEH}LH}HukHEH}+H}HEHH HEHE HEHEH0]f.UHH`H}HuHUHEHHENHEH8HEHEH8HEHEEH}ZHEHEHEHHuHOHEHEEH}HEEH}HEH}JH}HEHH,HuHEH HHuH}HE5HEH8HuHUHMDEAEHEHuH}aHEH`]UHH}HEHH ]fUHH H}HEHEHEHEHHy9HEHHIHuHHMHAHEHxHEHHzHEHH HEH8HEHMHHHH ]fUHH H}HuHEHEHEH}JHEHHuHgHEHEH}*HE H}$HEHEH ]ÐUHH}HEH]f.fUHH}HE]fUHH}HEH]f.UHH H}HuHEHMHHHEHEH HHEHMHHH ]f.UHH H}HEH81ɉFHEHEH ]HHUDUHHH}HuH}H]ÐUHHH}HEHH]fUHH H}HuHEH}HE/H}H+H}HuH}HEH ]UHH}HE]fUHH H}HuHEH}HE/H}H+H}HuH}-HEH ]UHH}HE]fUHHH}HEHHHE' H}H]DUHH H}HEHHEHHEHH HM H}HEHEH ]fUHH H}HEHEHEHEHHy9HEHHIHuHPHMHAHEHxHEHHHEHH HEH8HEHMHHHH ]fUHH}HEH]f.fUHHH}HEH>H]fUHHH}H}WH]DUHH0H}HuH}HEH}LH}HuHEH}+H}HEHH> HEHE HEHEH0]f.UHH`H}HuHUHEHHEHEH8HEHEH8 HEHEEH}ZHEHEHEHHuH菽HEHEEH}fHEEH}\HEH}JH}HEHH2,HuHEH H^HuH}HE5HEH8HuHUHMDEAE&HEHuH}HEH`]UHH}HEHH ]fUHH H}HuHEHEHEH}JHEHHuHWHEHEH}2HE H},HEHEH ]ÐUHH H}HuHEHMHHHE_HEH H#HEHMHHH ]f.UHH}HE]fUHH H}HEHHEHHEHH HM H}HEHEH ]fUHHH}HEHH]fUHH H}HuHEH}HE/H}HH}HuRH}HEH ]UHH}HE]fUHHH}HuHEHMHHcH]UHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHHH}HuHMEH}HEHMH}EH}u@H}HEHEHEH}zHEHEHEH}HuVEELH})HEH}HuH}HEUH}Ok$EE H}3kHEHĀ]H}蛸 f.UHH0H}HuHUHEH8HuHEH}HEHM HEM܋EH0]f.fUHHH}HuH}HuH]f.UHH H}uHEHQ;UHE>HEH84uH}HEuHH ]fDUHHH}HEH8.H}HHEH]fUHH}HuHEHHMH;€]f.UHHH}HEH8H}HH}5H}6HM3H V=6HHH!HP]HEU:HEU%HEUHEUH}H}H}H}g6H}L f.fUH]ÐUHH`H}HE1ɉHHE膻H4HHUHHHHUHEHHHE HEH HHEHEH(HHEHEH0HHEHEH8HHEHEH@HHE蕯H}H`]HEUHEUH}fH}CH}ZH}qH}H}_H}6HEHvH} f.DUHHH}H}SH]DUHHH}H}SH]DUHH@H}HEH53THMHHEHMH}HuH}H5SHEHHEsH}HuVH}H@]HEUH}rHEUH}]H} fUHHH}H}+TH]DUHHH}H}KGH]DUHHH}H}KRH]DUHHH}H}RH]DUHHH}H}+H]DUHHH4HH}HMHHH@HHMEHEH8HHEH0H'HEH(H5HEH HCHEHHHEHHHEHH]f.UHHH}H}+H]DUHHH}HEHHEHEHH]fUHHPH}HEHH@H}HHEHEH8HEEĉEHMH8uH}HMu0HUH}u轹H}ݐEH}E.EHP]HEUHEUH}詐H}H}u DUHHH}HuH}HuGH]f.UHH}HEH@]f.fUHH0H}uHUHE}HEEHMH;BH=j8H5_HRԦH}菸HcMHHH}HETH}HuHH0]f.UHHH}H}GH]DUHH@H}HuHEHH HuHHEFHEH HuHEjHEH HEEHMH HuHωEUԉHuHEHHHEHuH臰HHuEUUEH@]@UHH 1H}HuHMHuHHMHHMH;AAAH ]f.fUHH0H}HuHEHyHE%1HuH}$HHEHMH; E HEHMEH0]UHH}HEH@]f.fUHH@H}HuHEHHE萮HuH}HUHEHEHHMH;[HEH8HuUH}^HE؋uHUELEH}HMHHEHEHHHEHEH@]ÐUHHpH}HuHEHHE~HuH}HUcHEHEHHMH;HEH8=HuUH}(HE؋uHUHEHljuHUHE|LEH}uHUHM輭HEHEHHEH}&HEȉUH}oHEHHHEHEHp]H} @UHH1H}HMHHuHMSEHMH(HHu=HEH(HHuTHHuT EE1H}}(H}u@H}HESEE܉MH}Ⱥ BH}HUHuvHEHMHHHEHM~H}HE/H}&1H}UEHMH(HuHBEEuHEH(HuHPHxHxHu@3EEEqHEUHEUH}sHEH(HuH蜾wwH}HuuEH}#E ;H}4HEH(HHu]HHuMMEHĐ]H}\  f.UHH 1H}HuHMHuHHM̽HHMH;AAAH ]f.fUHH@H}HuHUMHEHH@H}HHE^HuHUMH}:H},H@]HEЉUH}H}苟 f.UHH`H}HuHUMHEHuHHEEHuHUHHUH}HuQEH}EEHMH8H;E#H}HEȉUH}@)HEH8uHְuUHH`]H}觞 UHH H}uHE}HEEHMH;BH=KH5=WHZJXH} HcMHHH ]f.@UHHPH}HuUHEHH@H}HHEHEH HuHEEǨHEH HuH躺EEEЋMHUH8H׉MFEEM9GHEH8uHuHEuH}耇HE؉UH}H}HP]H} fUHH H}uUHEEHEHEH0H}HHU葥HEH0HHu|H ]f.@UHH@HHHMHuHUHMHuH}HHUHEĦHEHuH}9`HEH@]f.DUHHH}HuH}Hu胦H]ÐUHH`H}HuHUHMHEHH@H}HHgEHuH}.1}%HEHHHHH˹!EH}/HEUH}臹HH}H}EwHEUHH HuH %EE&HEUH};EsH}H}EEH}.HuHEHHHHH}莻EE5HH(HuH袷*EEHEUH}&HuHpHHHHHpݺ|HH(H|HxHuHhHHHH,Hh[0HEUHpC HEUHh+H`*HuH@1X(H@HHHHH詶$EH@b,HEU5HH_HH8HfX$E H8FzHEUH8H4H`H4DžXyHEUH8̸*HHXXH@Q+0HH8HHHH(H(HH8HH覨HHHH9H(H H`HHU|H H趇H H(HH(MHEUH y8HH(HuHѠEEH`AH`0H}bE$H`]H}HH}轕 f.UHH1H}HMHHuHM#EHMH(HHu %HEH(H}HHUH}HuH}E菶E EE1H}9H}uH}Hx EẺMH} H}HUHu/HEHMHHHpHh1HhH`ܵH}ӵ1HpEHMH(HuH__HEH(H}HUHȱH}HuH}^W^3EEEdHEU{HEUH}fHEH(HuH1]]EH}ŴE H}袴EEEHİ]H}   f.@UHH H}HuHEHuHHE*HEH ]fUHH H}HuHEHH HuHHEƯHEH HuH藯EEEH ]UHHH}HEHHE:1ɉHEH8(H]f.@UHHH}HEHHE1ɉHEH8ܖH]f.@UHHH}HuH}Hu`H]f.UHHH}H}[H]DUHHPH}HuHEHHE  EH} 1HMH1FEHuHHEHEHHMH;E1HMH H HMHMHUH; EHEȋH HEH;H ˆUE$EHMH1H}PHMHUH HMHDBADBEHEH8LEHMH+BEEHP]DUHH@H}uHEHH@H}HHEVHEH0HuHEE4H}EE$H@]HEUH}kH} UHHH}HuH}Hu3H]f.UHHH}HuH}Hu$H]UHHH}H}3H]DUHH0H}HuHEHH@H}HHEUH}HEHHIH}HEH(H0H}HEH8H H}HEH0HEH}EۃgH}-$H0]HEUH}H}襎 DUHHH}HuH}HuWH]f.UHHH}HuH}HuH]f.UHHH}HuH}Hu٥H]f.UHHpH}uHEHH(UHωHE蜘H5.H DHEȺHHEHEHHuHEϦH52H}]HEHEH(HEH}uHH}Hp]HEUH}H}? f.DUHH H}uHEHHE迗HEH8EHMH}HHuw1+H}pH ]f.UHH}HEH@ ]f.fUHHH}HEH5H *HUAHHUDHE貮HEHHuHE肥H5H}HxHEH(HĩtHxtH}轚HEH(H跖H5CH HEHHhHEHHhH`ۤH5>H`fHXHEH(HTHXTEH}Hİ]HEȉUH}HEȉUH}H}$ @UHHH}H}H]UHHPH}HuHUfMHEHH@H}HHE]H}HEHHQH}HEH(H8H}HEH8HH}HEH0H H}HuHEH HAHuH}HEH}؈MMHP]HEЉUH}|H} UHHH}HuH}HuwH]f.UHHH}HuH}Hu#H]f.UHHH}HuH}HuH]f.UHH H}H}HEH}HpH}HuKH}HEH ]UHHH}HuH}HuH]f.UHH0H}HEHH@H}HHEYHEH H賒H}+H0]HEUH}H}芈 f.UHH@H}HuHEHH HHEdHEHH轥HEHEHH蕥HEH}Hu~eH}HEKHEH H}HE5H}HE"H}HuH趑HEH}?kH@]UHH}HEHx]fUHHH}HEH8H}H|HEH]fUHH}HuHEHHMH;€]f.UHHH}HEHH}H!HEH]UHH@H}HuHUHEHHE輐HuH}HUţHEHEHHMH;VHEH8)HuUH}芣HEЋuHUHMLEH}0H}Hr#HEHEHHHEHH}HJHEH@]UHHH}HEH8辐HH]f.fUHHH}HEH8莐H H]f.fUHHH}HEH8HE0HMHHH]@UHH0H}HEHH@H}HHEHEH8H#HEHH܏HEH HHEH(H貏HEHH豍HEH0H蜍H}2H}DH0]HEUH}.H}裄 UHH H}HEHyHE4H}EH}HE,H}HuHXHEHAH ]UHH H}H}HEH}HPH}HuH}HEVH ]UHHH}H}9H]DUHHH}HEH8HzH]f.fUHHHH}HuHUHMHMHH@HuHpHHHhH`cH`H HuHT\\EEH`HX1HpXcEEH`TPTP9UԋMH}H`3EHuH} 1}O)H}Hu NNOOEEH}HEȉUHEȉUvHEȉU"HEȉUH}袝H@HxH@=} EiH}Hx1蹢??(EE)HEȉUHxԢ>EHx貢H}EEH}4uEHpYH}]EEH}F:EEE HpH}HhH]HpH}H}臀 UHH@HILEHuUMHuII8MH}LHuЉHE uHkEUH}Huo HEH@]DUHH HHHMHuHMH}HHE^H}H^HEH ]UHHH}HuH}Hu%$H]UHHH}H}H]DUHH H}HEHHE誈HMHEHH ]UHHH}H}#H]DUHH H}uUHEEHEuH}E uH}@H ]fDUHHH}H}&H]DUHHHH}HuHUHMLEHMHH@HuH}HHHEHMxHEH HuHlEEEEH}iE1H}u荔EEH}E8EEM9ŰMH}HuouH}HE|H1ɨ{HuH}蟣{{ȃH}|ړH}ޞEEIHEUWHEUBHEUH}訞-EE H}LH}HEHĐ]H}-H}dH}| fUHHH}HuH}Hu轢4$H]fDUHHHH}HuHUMDEHUHH@LMH}LHEHU|HEH HuHpEEEEH}mE1H}u葒EEH}EH}HEH`]HEȉUH}H}s f.UHHPH}HuUHEHH@H}HHERHEH HuHFEEE܋u܋UH}ےEH}pEHP]HEЉUH}WH}r f.fUHHH}uUHEH8uH艔uH.^H]UHHH}uUHEH8uHIuH^$H]UHH HHHMHuHUHuHUHE赏HEH ]f.UHH@H}uH}H5HEH}HHE"UH}HubEH}1EH@]HEUH}H}q f.UHH`H}uUHEHH@H}HHEsHEH8UH}HHEHEHEH8UH}HHEHEH}Hu>`EH}-ZH}$ZH}[E$H`]HEЉU%HEЉUHEЉUH}YH}YH}H}p UHH0HHHMHuUHMUH1;VH}HEHMH}X'1HMH9.uHcMHHH}HS$HEH0]fUHHH}uHUHEHH@H}HHEH}voHEH8uH螑HEH}HuX\H}HuH}1}%HEHHHHH/H} #HE؉U)HE؉UH}iH}襎HpHpM}H}UHEHhHHuUMH}HuCHuHUHhZoH}H}EHE؉UKHE؉UHE؉UH}迏H}趏!H}]|EȃEH}H}yHĠ]H}gH}m f.fUHH HHHMHuHMH}HHEFRH}HJRHEH ]UHH}HuHEHHMH;€]f.UHHH}HEH8{H]fUHH}HEHHH]DUHHH}H};H]DUHHpH}uHUHMHEHH@H}HHEHuH}EEEH}UHMH}HHuUԋMH}Hu HuHUH}:mH}܍H}ӍH}Hp]HEȉU%HEȉUHEȉUH}蜍H}蓍H}H}l f.DUHHHH}HuHMHH@HuHHHHH@H8EHHH}H5H}ҌHuH84H}ٌ4Eԃ}H8H8HHEHEH8H8HH(H(H9oH}uV$$EH}HuHUsHEHHEHEUHEUH}H5H}ȋHuH8 EH}Ƌ}H8H8HۋHEHEH8H8HHHH9cH}uUEH}HuHUrHEHHEHEUH}H`Hu1x/HhHp,H`HEUHhӄHH\xwHH\HPH8HHPHjtHPDžxHEUHPۉ*HhqxxH`EH}^E4#H}FHHH}a%HHH}GH@H]H}g f.fUHH H}HEH81ɉHEHEH ]HHUuDUHH H}HEH81ɉ辀HEHEH ]HHU5DUHH HHHMHuHMH}HHELH}HLHEH ]UHHH}HuH}Hu$H]UHHH}H}H]DUHH H}HEHHEpHMHEHH ]UHHH}H}H]DUHHHH}HuHUHMHH@HuH}HHHEHM EH}3HuH}&EEE؃}HEH8HpHEHEHMH8HHE臇HMH9fH}u$QEEEH}HUHuGnHEHHEHEЉUH}舻H}2EE H}^H}HEHĀ]H} e f.UHHHH}HuHUHMEH}HEHMHUH}Hu\H}Hu{1})H}HuE~~2H}HEЉUHEЉUHEЉUH}HpHpM}_HEUH}HuHh/HuHhoH}EHEЉUH}!H}ClEEH}EH}菹EH}wH}IHEHĠ]H}3H}c UHHH}uHEHHHu~$H]UHH H}uUHEEHEHEHH}HHUakHEHHHuLkH ]f.@UHHH}H} H]DUHHH}H} H]DUHH H}HEHHHHEzHEH0H_lH ]HHUdžUHHHɃ3H}HuH}H%xH]UHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]f.fUHHH}H}!jH]DUHH}HE]fUHH H}HuHEHMHHHHHEH=H5"H@Y_H}@cH ]f.UHHH}HEH8HE?HEHHH"H}xHcHEHHHH]f.UHH}HEHH%]fUHHH}H}bH]HHUd@UHHH}HEH8HE>HEHHH!HEHHHH?wH7bH]f.@UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HmHMHcHEHMEGEHME4EHME!EHMEEHMEE]ÐUHH H}HuHEHMHHHHHEH=H5bH|\H}r_H ]f.UHHH}HEH8HE?HEHHH"H}uH;`HEHHHH]f.UHH}HEHH%]fUHHH}H}^H]HHU褀@UHHH}HEH8HE>HEHHH!HEHHHHOtHw_H]f.@UHHH}H} H]DUHHH}H} H]DUHHH}H} H]DUHHH}H} H]DUHH H}HEHHHHErHEH0HcH ]HHUWUHHH|3H}HuH}HpH]UHHH}H}mcH#H]f.UHH}HE]fUHHH}H} H]DUHHH}HEHH{H]f.fUHH H}uHEMHHEMQ~M9H=H5}[EH}UC[UHcT0DED ˆT0H ]fDUHH H}uHEMHHEM}M9H=FH5qZEЃH}UZUHcT0DED!ˆT0H ]UHH H}HEHHEpH}EpU)ʉH ]DUHHH}H}[H]DUHHH}HuH}HuG~$H]UHHH}H}H]DUHHH}H}H]DUHHH}H}ˈH]DUHHH}HEHEC\HMHH]f.UH5Y]DUHH H}HEHHHHE"oHEH0HaH ]HHU{UHHHx3H}HuH}HEmH]UHHH}H}qaHH]f.UHH}HE]fUHH H}HEHHHHERnHEH0HU`H ]HHU{UHHH x3H}HuH}HulH]UHHH}H}_HH]f.UHH}HE]fUHH H}HEHHHEmHEH0HgH ]HHUNzf.@UHH 1H}HuH}HUH}HH ZE1DH}HEYH}HuHgHEHYH ]UHH H}HuHUHEH;EHEHHHMH=H ]fUHHH}HuH}eYH]ÐUHH H}HuHEHHE>YHMHcQHHH ]f.UHHH}H}HHUH]f.UHHH}HEHUH]fUHH`H}HuHUHEHHuHEhuH=PH5YHjS1HMH9kXHuH[HEH}u!HEHQHq9-HEHQH}ؾU+UH}u e1HMH9W1҉HEHEHHEHEH8WHMHHHEHEH;EHEHHEHMHHMHHEH}HHEH;E5HEHHEHHMHHMHHhH}cH}HyhHEH}HEAH}H51HMHBBH9VHMHHH`]UHH}HE]fUHHP1H}HuHUD1V3DEH:HHUvVHEHEHHEH}HuHUE1ɨDM51HMH HMHMH98VHEH}HuHU4EE$HP]f.fUHH H}HuH}HuH ]f.UHHH}HEHH;v4$H]UHHUH}uHEMH8;OHEH=H5%RHEHHMH8uEHc}UU؋u9UHEHEHEH}Q HEЉU!HEHbuH}oH=3H5pQHEH"uH=BH5?QHEHQHMQH81҉XTHEHEHEHMH91҉+THEHEHEH}1ɉTHEHEHEE1HEH;EHEHHHMHMHHHUHHHEЉUH}uH}1ɉHESHxHUH}Hx`xu^HEH;EFHEHHHMHMHHHUHHpPHpHA>HEЉUtH}tH}HhRtHEЉUtHEHQHMq ։qHH;MH=)H5wOHEHHNeHEH0HI_HEHMHH9 RHH=H5NHEHQHq9H=H5xNHEHH`QH`H9H=yH58NHEHHXCQHXH9H=VH5\MHEHQ;UH=8H5&MHİ]H}L HHPp f.DUHHH}HuH}HuH]f.UHH H}HuHEHuHHEVHMHEHH ]f.UHH}HuHUHEHHMH;AAA]@UHH}HuHEHMH)H]UHH uH}HUEEMH}HuLH ]f.fUHHH}:#1NjuOH]UHHH}HuH}HuH]f.UHHH}HuH}HuH]f.UHH H}HuHEHMH HHHHHEbHMHDB(AA H}UH ]@UHHH}HEHHHHE0o H}TH]f.@UHH H}HEH8HEH}jTH5k3Hk3H}A_HEHEHHH?aHEH0HVTHEHMHH ]f.DUHH H}HuH}T1AHEHEHUH HuHH}OHHuHHUH ]@UHHH}H}SH]DUHHEEH}HuHH]DUHHHyj3H}HuH}H^H]UHH}HE]fUHH0H}HuHUMLEH}HuHUMLE H0]UHH}HuHUMLEHEHUHMHHU H HU H]@UHH0H}HuHEHHUH; HExHEHHEHEHHM_HMHHH׈E:_HEH0HQRHEHMHHP( H}QHEH0]fDUHH0H}HuHUHEEHy HE H}/H}HEHq$H ]UHH@H}HuHUHEHHEGHuH}HUYHEHEHHMH;VHEH8)SHuUH}YHEЋuHUHMLEH}rFH}HrlHEHH}HZlHEH@]UHHHuH}H}HusH]f.UHHH}HEHHHHE0a H}EH]f.@UHH0H}HuHUHEEHy HE H}1HE8HEHq$;EH} EHMHuUH}zXH0]f.@UHH0H}HuUHEHy HEHEHHIUH01v ҉HHHMHMH HuH;HEHH8H=OH5d-<1HMH HUH; EHEH8uHUf_4E׊EרHEHHEHEHEHEH0]fUHHPH}uHUHMLEHEH8HEH}DH}TPHuHUMH}LHHEXHEHEHUHuHHUH2NNHEHP]f.UHH H}HEH8HEH}CH5i[3HZ[3H}AOHEHEHHHQHEH0H|CHEHMHH ]f.DUHH H}HuH}=C1AHEHEHUH HuH}OHHuHHUAH ]f.UHHEEH}Hu8H]DUHH0H}HuHUMLEH}HuHUMLE H0]UHH}HuHUMLEHEHUHMHHU H ]f.UH1H}uHUHMu;qHMEHEHE;H ˆUߊE$]f.UHHuH}HEHMH]UHHPH}HuHEHHET EH}A1HMH1FEHuHaTHEHEHHMH;E1HMH H HMHMHUH; EHEȋH HEH;H ˆUE$EHMH1H}@HMHUH HMHDBADBEHEH8MEHMH+BEEHP]DUHH}HEHx]fUHH H}HuHEHMHHEB@HEH8HMHLH ]UHH}HE]fUHH H}HEH8HEMHEH0HCH ]HHUZUHHH}HuH}HEHHMHcIHHHMHHUHcR HHHHRCH}LH]f.DUHH}HuHU]f.@UHH`H}HuHEH8HEFZzH}BHEHuHUH}BCHEUH}q[HMHr Ήr HEw[HEUN[HUHuH}hBH}KHEHEHEFHEUH}ZHuH}HEBZ>HEUZHEHMHH`]H}3 HHUX fUHHpH}uUHEHHEXHEUHuH}4JHEH}XH}HEXHcMHHMH}HuAMHE؉UH} ZH}HEJHEHMH Z1HE؉UYH}/XHcMHHcMH4H}HuXHMHcUH H}HuH A}HE؉UH}tYH}HEWH}HEWHcMHH}Huy@H};IHEHMH@YhHE؉UY;H}J HuH}S@HEHEWHcMHHHp]H}1 HHUV UHH}HuHUHEHE]fUHH}Hu]fUHH0H}HuHUHMHEHEHEH;E?HEHMH)HH&HEHMHUHuH)HHHHOXH0]f.UHHPH}HuHEHMH HH8HEHHEHqHGH}HEVH}HEUH}HEUH}HuHUH>EHEUH}gWHMH9HEUGkW8HEUBW HP]H}<0 HHU U f.@UHH}HEHx]fUHH H}HuHEHMHHEf:HEH8HMH_FH ]UHH 1H}HuHMHuHHMLHHMH;AAAH ]f.fUHHPH}HuH}HEH}HLH}؉1H}HELHEH}LHEH}HuLJH}9H}HMH}HHEJL0H}u1H}HE8LH}HTHEHP]DUHH}HEH@]f.fUHHH}HEHH}H^HEH]UHHH}HEH8DH}Hl^HEH]fUHHH}HEH8HEDHMHHH]@UHH@H}HuH}HEH}HOH}ȉi0HMHMH}HEnOHEH}UOHEHEH;E(HEHEH}HuHHEHHEHEH@]f.UHH}HEH@]f.fUHH H}HEH81ɉrFHEHEH ]HHUQDUHH H}HEH81ɉ>FHEHEH ]HHUQDUHHH}HuH}EH]ÐUHHH}HEHDH]fUHH H}HuHEHHEEHMHcQHHH ]f.UHH@H}HuH}HEH}HGH}ȉ.HMHMHuH}HEGHuH}GH}HuG*H}GHEH}HEЋ0M.H}b4HEH@]f.UHHH}H}HH]DUHH@HH}HuHMH}HHEHHEHEHEHuH} HEH@]HHUPUHH@HH}HuHMH}HHEHHEHEHEHuH}HEH@]HHUOUHH}HEH@]f.fUHHH}HEH8 AH}HZHEH]fUHHH}HEHH}HqZHEH]UHHpH}HuHuH}cH}4H}Hu,EE;EH}?H}Hu,HEHuH}vPH}vBEE;H}14EJHE؉UHE؉UH}J|H}HuHU~+HEHEHEEH}JE ẼEHEEH}HEHEHp]H}H}(  DUHH@H}HuHUHEHHHEG3HEH8/?HMHuHHU܈EFHEHEȋuHUHMLEH2H}H{XHEH@]ÐUHHPH}HuHuH}sH}9H}Hu*H}u9EE;EH}&H}HuH}@EE;H}s9E:HE؉UHE؉UH}lH}Hu:9EH}eE ẼE2HEEH}HEHEHP]H}H}&  DUHH0H}uHEMHr9HE 1EH}EUH}u8H}#H6HEHHM>+HMH9HEHQQH}H;EH=H5)'H0]ÐUHH`H}HuHEHQHDAAD9AADMHHEdG EHuH}1MEH}؉EHEHQUHEHQUEM؉MЋUH}:7HEH81ɉ*HEH};H}H/H}!1HEȉUH} 21HMH9)HuHHEHQQH`]H}$ f.UHH}HEHH]@UHHPH}HuHuH}H}-H}Hu 'EE;E|H}Hu&H}<EEă(H},:HE؉UH}@H}Hu,ẼExHEH}HEHEHP]H}# f.@UHH H}HuHEHUH}HHE,HEH ]f.@UHH H}HuHEH}HE/H}HxH}Hu,H}myHEH ]UHH}HE]fUHHH}HuHEHMHH#H]UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH H}HuHEH}HE/H}HwH}Hu,H}]xHEH ]UHH}HE]fUHHH}HuHEHMHH"H]UHH H}H}HEH}HRH}Hu,H}HE6H ]UHH H}HuHEH}HE/H}HCvH}Hu+H}HEH ]UHH}HE]fUHHH}HuHEHMHH"H]UHH}HE]fUHHH}HuH}HuH]f.UHH0H}HuHEHuHHE\HEHH}HE!H}H!<HEHH}HE!H}H;HE@H0]DUHHH}HuH}HuH]f.UHH}HE]fUHH@HH}HuHMH}HHEG<HEHEHEHuH}HEH@]HHUDUHH@HH}HuHMH}HHE;HEHEHEHuH}+HEH@]HHU DUHHH}HuH}HuH]f.UHHH}HuH}HuH]f.UHH H}HuHEHMH HHHHHE6HMHDB(AA H}'H ]@UHHH}HEHHHHEC H}t'H]f.@UHH H}HEH8HEH}:'H5?3H?3H}Ak4HEHEHHH5HEH0H'HEHMHH ]f.DUHH H}HuH}&1AHEHEHUHHuH}OHHuHHUAH ]f.UHHEEH}HuH]DUHH0H}HuHUMLEH}HuHUMLE H0]UHH0H}HuHUMLEHEHUHMHHHuHCH0]f.fUHHH}HEH83H}H|LHEH]fUHHH}HEHH}HQLHEH]UHH}HuHEHHMH;€]f.UHHH}HEH8HE`2HMHHH]@UHHH}HEH8$HH]f.fUHH}HE]fUHHH}HuH}HuH]f.UHH0H}HuHEHuHHE,HEHH}HEH}H:HEHH}HElH}Hl:HE@H0]DUHH}HE]fUHH HHHMHuHMH}HHE?H}HJHEH ]UHH HHHMHuHMH}HHE?H}HjJHEH ]UHH}HE]fUHH}HE]fUHHH}HuH}HuH]f.UHH0H}HuHEHuHHE\HEHH}HEH}Ho5HEHH}HEH}H@5HE@H0]DUHHH}HuH}Hu#H]f.UHH}HE]fUHHH}HuH}HuH]f.UHHH}HuH}HuH]f.UHH H}HuHEHMH HHHHHE~0HMHDB(AA H}"H ]@UHH}HuHEHHMH;€]f.UHHH}HEH8HE.HMHHH]@UHHH}HEH8N"H H]ÐUHHH}H}HH]DUHHH}H}H]DUHH H}HEHHE"H}fH ]HEUH}PH}7<UHH H}H}HEH}HPHH}Hu?"H}HEH ]UHHH}H} H]DUHHH}H};H]DUHH H}uUH}EHuE!MH ]UHH@H}HuHEHHE!HuH}HUo4HEHEHHMH;[HEH8,HuUH}44HE؋uHUELEH}HM HHEHEHHHEHEH@]ÐUHHH}uH}Hu H]f.@UHHPH}HuHEHHE~3 EH}r 1HMH1FEHuHQ3HEHEHHMH;E1HMH H HMHMHUH; EHEȋH HEH;H ˆUE$EHMH1H}HMHUH HMHDBADBEHEH8L+EHMH+BEEHP]DUHHH}uH}EHuHUQ2H]UHH0H}HuHUHEHyHE%1HuH}&2HHEHMH;HEM HE؋HMEH0]ÐUHHH}uH}Hu1$H]fUHH 1H}HuHMHuHHM1HHMH;AAAH ]f.fUHH HHHMHuHuHE#1HEH ]UHHHH}HuHMEH}HEHMq^H}0EH}u4!H}0HEHEHEH}0HEHEHEH}Hux0EELH}?0HEH}Hu H}[HEUH}$EE H}cHEHĀ]H}  f.UHHH}HuHuH}7H]f.UHHH}HuH}Hu)H]f.UHHH}HuHuH}-8H]f.UHHH}HuH}Hu(H]f.UHHH}HuH}Hu#HEH]fUHHH}HuH}HuSHEH]fUHHH}HuH}Hu.$H]UHHH}HuHEHHUH; Hp EHpY.H}艅lJ.l9 EmHp-.HEHp .HEH}Hu-/HEHEH}-HEEH}MăMHp-HEH}Hu-1ɨkH}f-HE;ˆkkH}Hu4-HEHUHcEHMHMHMHMH}HuH`H`H9 EUHEHEHEHEHEHEHEHxH}HuHUHx^ E EE$HĠ]fUHH@H}UMHEHuHuH}HEHuH}H}Hu#.kH}.MH}Hu],5H}Huq;MEH}HuԉESMĉH}^{H@]f.UHH0HHHMHuHMH}HHEHMHEH2H}H=HEH0]UHH0HHHMHuHMH}HHEHMHEH2H}H=HEH0]UHH}HuHEHHMH;€]f.UHHH}HEH8:H]fUHH}HEHHH]DUHH H}HEHHHHE$HEH0HH ]HHUw1UHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]f.fUHH H}HuHEH}HE/H}Hs_H}Hu~H}mHEH ]UHH}HE]fUHHH}HuHEHMHH3 H]UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH0H}HuHUHEEHy HE H}1HE8HEHq$ EH} EHMHuUH}Z'H0]f.@UHH0H}HuUHEHy HEHEHHIUH01v ҉HHHMHMH HuH;HEHH8H=oH5M 1HMH HUH; EHEH8uHU-4E׊EרHEHHEHEHEHEH0]fUHHPH}uHUHMLEHEH8HEH}H}tHuHUMH}LHHE踿HEHEHUHuHHUH2NNHEHP]f.UH1H}uHUHMu;qHMEHEHE;H ˆUߊE$]f.UHH}HEHx]fUHH H}HuHEHMHHEHEH8HMHH ]UHH H}uHEHQ;UHE>HEH8$,uH}HEuH{H ]fDUHH}HEH@]f.fUHHH}HEH8H}Hl6HEH]fUHH}HuHEHHMH;€]f.UHHH}HEHH}H6HEH]UHHH}HEH8H H]f.fUHHH}HEH8HE HMHHH]@UHHPH}uHEHHE*HEuH} HEH}|*H}HEc*HMH}HuHoMHE؉UH}+H}HEHEHMH+QHE؉U+$H} HuH}HP]H} HHUq) f.DUHHPH}HuH}HEH}H8"H}؉H}HE8"HEH}!HEH}Hu!IH}H}HMH}HHE!0H}uH}HE!0H}]HEHP]fDUHHH}HEHH}H3HEH]UHHH}HEH8H}H3HEH]fUHHH}HEH8HEHMHHH]@UHHH}HEH8(HH]f.fUHHpH}HuHuH}#H} H}HuzEE;EH}HuUHEHuH}?H}?EE(H}` EHE؉UH}KH}HuHU`HEHEHEẼEWHEH}HEHEHp]H} f.UHH@H}HuHUHEHHHE HEH8?HMHuHHU܈EHEHEȋuHUHMLEHE H}H1HEH@]ÐUHHpH}HuHEHu1ɉHHE8HEHEHHMHuH}71HEHMH;1HMH HUH; EHEHH HE;ˆUEHEHHEH}0HEH} HEHEHEHuH}0H}HuHEHUHEHUHp]HHU %UHH0H}HuHEHEHEHEH}HuH0]f.UHH@H}HuHUHMHEHEHEHEHEHEHEHEH}{%$H@]@UHH H}HuHuHUH}HEHUH ]ÐUHH H}HuHUH}HuHU H ]DUHH}HuHUHEHMH HHMH HH]DUHH H}HuHEH}HuHEHHEH} HEH ]UHH H}HEHH HMHHH HMH@HHEH}HuHU$H ]@UHH@H}HuHUHEHEHEHEHEHEH}HuHU#$H@]UHHH}HuHUH}Hu\H}H}HpH}HpH#H}H}HhH}HuJ EdHEHEHEHEH}HuHEH} E/HEHEHuH}HEHEHEH}HuHEHEH}HuQH}H}H`H}H`HH}H}HuDPHEHEHEH}Hu ZH}H}HXH}HXH-HEHHEH}H} EHEHEHxHxWHEH}HupZH}NH}HP>H}HPH}HEHHEH}6HEH;E EH}EE$Hİ]f.UHH}HuHUHEHE;AAA]fDUHHH}HEH8HH]f.fUHH}HuHEHHMH;€]f.UHH H}HuHuH}HEHEHEH ]ÐUHH H}HuH}HuH ]f.UHH H}HuH}H}HEHHEH ]UHHH}HEH8HE H}H]UHHH}HEHqHTH]f.fUHH H}uHEHHHuHEx} }}1}'}}H}uH} iuH}辄uH}躄DH} iuH}躗uH}jqEuH}ryEuH}zEH}HuE! H ]f.UHH H}uUHEHHHEE}VHEuH;M)HEuH;MHEuHEEH ]f.DUHH0H}uUMH}E;EH}$E;EuUH}EEE$H0]ÐUHH H}uHE}HE.1HEHHuE}HEuHH ]fDUHH@H}HuHEHQHDAAD9AADMHHEd E1HMU@u@EH}]EHEHQUHEHQŰE̋MM؋UH}ЉH}e1ɉ΋HEH8M Mȉ1HMHMH9EUĉHEHQQH@]UHHPH}HuUHE}HE+EHMHBEEH}HuDDEEHMH;B1HMH9]1҉HcMHHHHEHEH8,HEHEHHEH;EBHEЋHE;+1HMHUH:HMHMH)HMEEHP]DUHH H}uHE}HEEHMH;BH= H5ͬH1HMH9X1҉HcMHHHMH9HE9HcMHHHH}HuHH ]fUH1}}E }EE$]fDUH}} }iE%1}E }EEEE$]ÐUHH1}}E"}1ɨM }F4EE$H]UHHHHHMHuUHMHuH}HHEHMH}H}EEH}|x|x9H}EuH}_HpHp8qElElxl.HEUHEUuH}H`H`8HXH}HXuH}HPHP0H} ^H5H}HU}H}HuH}HHSH}JWHEUH}50uH} H@H@8ZH8H}H80uH}H0H08//H}HuJwuH}hH H 8H}HuH}HuH}ẼEAH}mH}HuHUHuHUH}H}H}H}H}HEH]HEUH}H}|H}sH}jH} f.DUHH H}uHE}HEEHMH;BH=?H5H1HMH9HcMHHH ]UH}EHHR3HH]ÐUH}EHH)Y3HH]ÐUHHH}H}bH]DUHH0 H5AHEHHpH=X3HpHhHhH}H5HEHH`H=uX3H`HXHXH}H5HEHHP}H=&X3HP4HHHHH}xH5QHEHH@.H=W3H@H8H8H})H5HEHH0 H=W3H0H(H($H} H5xsHEHH H=|5H WHH51H}HuHHH5i1H}hHuHHH591H}.HuHHH51H}HuHoHH5܅1H}HuH5HH51H}HuHHH51H}FHuHHH5L1H} HuHHH51HxHxHGHH51HpHpHHH51HhOHhHHH5g1H`H`HHH5-1HXHXHGHH51HPHPHHH5Ѓ1HHOHHHHH51H@H@HHH51H8H8HGHH5e1H0H0HHH5B1H(OH(HHH51H H HHxH51HHHxGHpH5ق1HHHpHhH51HOHHhH`H5x1HHH`HXH5}x1HHHXGHPH5Yx1HHHPHHH5x1HOHHHH@H5w1HHH@H8H5w1HHH8GH0H5w1HHH0H(H5Uw1HOHH(H H5b1HHH HH5"1HHHGHH51HHHHH51HOHHHH51HHHHH5j1HHHGHH5u1HHHHH5u1HOHHHH5~1HHHHH5z~1HxHxHGHH5t1HpHpHHH5t1HhOHhHHH5}1H`H`HHH5}1HXHXHGHH5t1HPHPHHH5s1HHOHHHHH5s1H@H@HHH5s1H8H8HGHH5rs1H0H0HHH52s1H(OH(HHH5s1H H HHxH5r1HHHxGHpH5r1HHHpHhH5r1HOHHhH`H5gr1HHH`HXH5'r1HHHXGHPH5r1HHHPHHH5q1HOHHHH@H5q1HHH@H8H5yq1HHH8GH0H5aq1HHH0H(H5!q1HOHH(H H5 q1HHH HH5p1HHHGHH5p1HHHHH5up1HOHHHH5Pp1HHHHH5p1HHHGHH5o1HHHHH5o1HOHHHH5o1HHHHH5Jo1HxHxHGHH5#o1HpHpHHH5n1HhOHhHHH5n1H`H`HHH5{n1HXHXHGHH5Qn1HPHPHHH5n1HHOHHHHH5m1H@H@HHH5m1H8H8HGHH5m1H0H0HHH5Sm1H(OH(HHH59m1H H HHxH5l1HHHxGHpH5l1HHHpHhH5l1HOHHhH`H5tl1HHH`HXH54l1HHHXGHPH5l1HHHPHHH5k1HOHHHH@H5k1HHH@H8H5jk1HHH8GH0H5Ek1HHH0H(H5k1HOHH(H H5j1HHH HH5j1HHHGHH5wj1HHHHH57j1HOHHHH5j1HHHHH5i1HHHGHH5i1HHHHH5ki1HOHHHH5Hi1HHHHH5i1HxHxHGHH5h1HpHpHHH5h1HhOHhHHH5h1H`H`HHH5h1HXHXHGHH5oh1HPHPHHH5Mh1HHOHHHHH5+h1H@H@HHH5h1H8H8HGHH5g1H0H0HHH5g1H(OH(HHH5g1H H HHxH5g1HHHxGHpH5g1HHHpHhH5hg1HOHHhH`H5Ig1HHH`HXH5/g1HHHXGHPH5g1HHHPHHH5f1HOHHHH@H5f1HHH@H8H5f1HHH8GH0H5f1HHH0H(H5xf1HOHH(H H5Uf1HHH HH57f1HHHGHH5Xh1HHHHH5h1HOHHHH5g1HHHHH5g1HHHGHH5Xg1HHHHH5g1HOHHHH5d1HHHHH5]d1HxHxHGHH5if1HpHpHHH5)f1HhOHhHHH5f1H`H`HHH5c1HXHXHGHH5e1HPHPHHH5_e1HHOHHHHH5b1H@H@HHH5b1H8H8HGHH5jb1H0H0HHH5id1H(OH(HHH54d1H H HHxH5c1HHHxGHpH5c1HHHpHhH5c1HOHHhH`H5Jc1HHH`HXH5c1HHHXGHPH5b1HHHPHHH5LHHHHH@H5LHHH@H8H5LHHH8bH0H5JLHiHH0+H(H5LH2HH(H H5KHHH HH5KHHHHH5nKHHHOHH57KHVHHHH5KHHHHH5JHHHHH5JHHHsHH5[JHzHH<HH5$JHCHHHH5IHx HxHHH5IHpHpHHH5IHhHhH`HH5HIH`gH`H)HH5IHX0HXHHH5HHPHPHHH5HHHHHHHH5lHH@H@HMHH55HH8TH8HHH5GH0H0HHH5GH(H(HHH5GH H HqHxH5YGHxHHx:HpH5"GHAHHpHhH5FH HHhH`H5FHHH`HXH5}FHHHX^HPH5FFHeHHP'HHH5FH.HHHH@H5EHHH@H8H5EHHH8H0H5jEHHH0KH(H53EHRHH(H H5DHHH HH5DHHHHH5DHHHoHH5WDHvHH8HH5 DH?HHHH5CHHHʿHH5CHHH蓿HH5{CHHH\HH5DCHcHH%HH5X1HxmHxHHx*HHHHHHHHHHHHHHHvHjH^HRHFH:H .H("H0H8 H@HHHPHXH`HhHpHxHHHHzHnHbHVHJH>H2H&HHHHHHHHHH H(H0H8H@~HHrHPfHXZH`NHhBHp6Hx*HHHHHHHHHHHHHHHvHjH^HRHFH:H .H("H0H8 H@HHHPHXH`HhHpHxHHHHzHnHbHVHJH>H2H&HHHHHHHHHH H(H0H8H@~HHrHPfHXZH`NHhBHp6Hx*HHHHHHHHHHHHHHHvHjH^HRHFH:H .H("H0H8 H@HHHPHXH`HhHpHxHHHHzHnHbHVHJH>H2H&HHHHHHHHHH H(H0H8H@~HHrHPfHXZH`NHhBHp6Hx*H}!H}H}H}H}H}H}H}H}H0 ]HEUH}$HEUH}HEUH}HEUH}HEUH}lHEUHEUHEUHEU|HEUgHEURHEU=HEU(HEUHEUHEUHEUHEUHEUHEUHEUkHEUSHEU;HEU#HEU HEUHEUHEUHEUHEUHEU{HEUcHEUKHEU3HEUHEUHEUHEUHEUHEUHEUHEUsHEU[HEUCHEU+HEUHEUHEUHEUHEUHEUHEUHEUkHEUSHEU;HEU#HEU HEU HEU HEU HEU HEU HEU{ HEUc HEUK HEU3 HEU HEU HEU HEU HEU HEU HEU HEUs HEU[ HEUC HEU+ HEU HEU HEU HEU HEU HEU HEU HEUk HEUS HEU; HEU# HEU HEU HEU HEU HEU HEU HEU{ HEUc HEUK HEU3 HEU HEU HEU HEU HEU HEU HEU HEUs HEU[ HEUC HEU+ HEU HEUHEUHEUHEUHEUHEUHEUkHEUSHEU;HEU#HEU HEUHEUHEUHEUHEUHEU{HEUcHEUKHEU3HEUHEUHEUHEUHEUHEUHEUHEUsHEU[HEUCHEU+HEUHEUHEUHEUHEUHEUHEUHEUkHEUSHEU;HEU#HEU HEUHEUHEUHEUHEUHEU{HEUcHEUKHEU3HEUHEUHEUHEUHEUHEUHEUHEUsHEU[HEUCHEU+HEUHEUHEUHEUHEUHEUHEUHEUkHEUSHEU;HEU#HEU HEUHEUHEUHEUHEUHEU{HEUcHEUKHEU3HEUHEUHEUHEUHEUHEUHEUHEUsHEU[HEUCHEU+HEUHEUHxHHHHHHHHH|HpHdHXHLH@H4H(HHHHH H(H0H8H@HHHPHXH`HhHptHxhH\HPHDH8H,H HHHHHHHHHHHHHHxH lH(`H0TH8HH@H5=_HEHH蚩K}E#1HEH0HĢHEHHƕHEHMHH9ƕHH==H5'=ÒHEHQHq9H==H5<舒HEHHpEHpH9H==H5<HHEHHhHhH9H=f=H5l<HEHQ;UH=H=H56<ґHĠ]H} HH` f.DUHH}HE]fUHHH}:h1NjuTH]UHH`H}HuHUHEHHuHEȰH=,H5,Hi;gH}Hu芰H=t,H5,H+;)HEHMH)HHEH} HEHE1HMHUH:HMfHMH9H=u,H5:Z1HMHUH:HMHMH9H=H,H5|:HEH;EH=.,H5Q:1HMHUH:HM跒HMH)HHMHEHDAAAH}71HMH9sHMHHHEHEHMHHHEHuHUH}HEHMHUH2HcvH+uH+uHHHuHHU蠴HMHUH2DFA)DF1HMH9HMHHHEHEH`]f.DUHHP1H}HuHUD2DEH:HHU肑HEHEHHEH}HuHUE1ɨDM51HMH HMHMH9DHEH}HuHU4EE$HP]f.fUHH H}HEHHE螭\HEHQ輐HMH-1HEHQH}UdUH}uUH}1H= 9H57{H ]UHH}HuHUHEHHMH;AAA]@UHH H}HEHHHEiHEH8/H ]HHU1UHHH}HEHHE H*H} H1HEHMHqHǺlHEHZH]f.@UHH}HEH@]f.@UHH H}HEHHHHE*HEH HH}蝟H ]fUHH}]fDUHH H}HEHxHEH}ҭHHHEHxH}踭H(H ]f.UHH}HEH@]f.@UHH}HEH@]f.@UHHH}HEHHHE H}cH]DUHH0H}HuH}SHEH}LH}Hu]HEH}+H}HEHH\ HEHE HEHEH0]f.UHHPH}HuHUHEHHE誏HEH8謫HEHEH8fHEHEEH}ZHEHEHEHHuH譈HEHEEH}HEEH}HEH}=H}HEHHPHEHEȉH HuH}5HEH8HuHUHMDEAEHEHuH}޷HEHP]@UHH}HEHH ]fUHH H}HEHE3HEHEHHy9HEHHIHuHުHMHAHEHxHEHHHEHH HEH8ǚHEHMHHHIH ]fUH%]DUHH01E1H}HuHUH}HHII HULAHEHEHMHHEoH}؉:HMHy6H}HuHzHMHAHEHxHEH HEH@HEHx6H}襩HuH)HMHAHEHxHEH诉 HEH@HEH0]fUHH0H}HuHUHMADEHEHMDEAHǾ(EΈHEHEHHuH谬HEHMP HEH0]fUHH H}HuHEHEHEH}JHEHHuH5HEHEH}耨HE H}tHEHEH ]ÐUHH}HEH]f.fUHH}HE]fUHH}HE]fUHH=5PH2H 5HHHe]f.@UHH0H2HEH5 H>H2HEH5).HH2HEH5-HHl2HEH5-HHU2HEH5-H¤H>2HEH5-H裤H'2HEH5-H脤H2HEH5%H讓H2HEH5H芓H2HEH5/-HH2HEH5-HH2HEH5,HߣH2HEH5,HH|2HEH5eHH`2HEH5EHƒHD2HEH5%H袒H(2HEH5H~H 2HEH5HZH2HEH5HH2HEH5H΢H2HEH5H询H2HEH5rH萢H2HEH5XHqH}2HEH59HRHf2HEH5H3HO2HEH5HH82HEH5HH!2HEH5H֡H 2HEH5H跡H2HEH5H蘡H2HEH5HyH2HEH5HZH2HEH5H;H2HEH5HH2HEH5bHHi2HEH5CHޠHR2HEH5(HH62HEH5HH2HEH5HwH2HEH5HXH2HEH5H肏H2HEH5H^H2HEH5zHH2HEH5[HҟH2HEH5pH賟Ho2HEH5QH蔟HX2HEH56HuHA2HEH5HVH*2HEH52H7H2HEH5HH2HEH5HH2HEH5HڞH2HEH5H軞H2HEH5H蜞H2HEH5H}H2HEH5H^Hr2HEH5H?H[2HEH5H HD2HEH5HH-2HEH5HH2HEH5HÝH2HEH5H褝H2HEH5H腝H2HEH5uHfH2HEH5HGH2HEH5aH(H2HEH5lH Hu2HEH5MHH^2HEH5IH˜HG2HEH5*H謜H02HEH5*H荜H2HEH5 HnH2HEH5HOH2HEH5H0H2HEH5HH2HEH5HH2HEH5HӛH2HEH5H贛Hx2HEH5H蕛Ha2HEH5uHvHJ2HEH5tHWH32HEH5UH8H2HEH5ZHH2HEH5;HH2HEH5BHۚH2HEH5#H輚H2HEH5$H蝚H2HEH5H~H2HEH5H_H{2HEH5H@Hd2HEH5H!HM2HEH5HH62HEH5HH2HEH5HęH2HEH5H襙H2HEH5yH膙H2HEH5sHgH2HEH5THHH2HEH5NH)H2HEH5/H H~2HEH5*HHg2HEH5 H̘HP2HEH5H識H92HEH5 H莘H"2HEH5 HoH 2HEH5 HPH2HEH5 H1H2HEH5 HH2HEH5 HH2HEH5 HԗH2HEH5 H赗H2HEH5 H薗Hj2HEH5 HwHS2HEH5 HXH<2HEH5 H9H%2HEH5 HH2HEH5 HH2HEH5 HܖH2HEH5 H轖H2HEH5 H螖H2HEH5 HH2HEH5 H`H2HEH5HAHm2HEH5 H"HV2HEH5HH?2HEH5HH(2HEH5HŕH2HEH5 H覕H2HEH5 H臕H2HEH5 HhH2HEH5H蒄H2HEH5 HnH2HEH5 HJHx2HEH5 H&H\2HEH5 HH@2HEH5\ HރH$2HEH5< HqH 2HEH5 HRH2HEH5 H|H2HEH5 HXH2HEH5 H4H2HEH5 HǓH2HEH5 H訓Ht2HEH5 H艓H]2HEH5p HjHF2HEH5` HKH/2HEH5D H,H2HEH5' H H2HEH5 H7H2HEH5 HH2HEH5 H覒H2HEH5 H臒H2HEH5 HhH2HEH5u HIHm2HEH5Z H*HV2HE1ɉHHB2HE1ɉHH.2HE1ɉH֑H2HE1ɉH躑H2HE1ɉH螑H2HE1ɉH肑H2HE1ɉHfH2HE1ɉHJH2HE1ɉH.H2HE1ɉHH2HE1ɉHHz2HE1ɉHڐHf2HE1ɉH辐HR2HE1ɉH袐H>2HE1ɉH膐H*2HE1ɉHjH2HE1ɉHNH2HE1ɉH2H2HE1ɉHH2HE1ɉHH2HE1ɉHޏH2HE1ɉHH2HE1ɉH規H2HE1ɉH芏Hv2HE1ɉHnHb2HE1ɉHRHN2HE1ɉH6H:2HE1ɉHH&2HE1ɉHH2HE1ɉHH2HE1ɉHƎH2HE1ɉH誎H2HE1ɉH莎H2HE1ɉHrH2HE1ɉHVH2HE1ɉH:H2HE1ɉHHr2HE1ɉHH^2HE1ɉHHJ2HE1ɉHʍH62HE1ɉH讍H"2HE1ɉH蒍H2HE1ɉHvH2HE1ɉHZH2HE1ɉH>H2HE1ɉH"H2HEH5gH1H=sH,M葒H0]HEUHEH /2H9HE.HEHHHE܌H2HMH9HMH}Tk @UHH H2HPH}HEHEHHHE}H2HMH9HMH ]f.DUHH=2P{H2H 2HHH5L蚑]f.@UHH0H2HEH5H辋Hz2HEH5H蟋Hc2HEH5H耋HL2HEH5mHaH52HEH5THBH2HEH52H#H2HEH5HH2HEH5H.zH2HEH5H zH2HEH5H蝊H2HEH5H~H2HEH5~H_Hs2HEH5_H@H\2HEH5H!HE2HEH5HH.2HEH5HH2HEH5HĉH2HEH5xHxH2HEH5XH聉H2HEH5<HbH2HEH5 HCH2HEH5H$H2HEH5HHq2HEH5HHZ2HEH5HLjHC2HEH5H計H,2HEH5H艈H2HEH5qHjH2HEH5pHKH2HEH5QH,H2HEH5PH H2HEH51HH2HEH54HχH2HEH5H谇Ht2HEH5H葇H]2HEH5HrHF2HEH5'HSH/2HEH5H4H2HEH5HH2HEH5cHH2HEH5H׆H2HEH5H踆H2HEH5"H虆H2HEH5HzH2HEH5H[Hw2HEH5H<H`2HEH5HHI2HEH5HH22HEH5H߅H2HEH5HH2HEH5H衅H2HEH5H肅H2HEH5HcH2HEH5HDH2HEH5H%H2HEH5tHHz2HEH5|HHc2HEH5]HȄHL2HEH5gH詄H52HEH5HH芄H2HEH5RHkH2HEH53HLH2HEH5<H-H2HEH5HH2HEH5(HH2HEH5 HЃH2HEH5H豃H}2HEH5H蒃Hf2HEH5HsHO2HEH5HTH82HEH5H5H!2HEH5HH 2HEH5HH2HEH5H؂H2HEH5H蹂H2HEH5kH蚂H2HEH5dH{H2HEH5EH\H2HEH5<H=Hi2HEH5HHR2HEH5HH;2HEH5HH$2HEH5HH 2HEH5H袁H2HEH5H胁H2HEH5HdH2HEH5HEH2HEH5H&H2HEH5HH2HEH5HHl2HEH5HɀHU2HEH5gH誀H>2HEH5cH苀H'2HEH5DHlH2HEH5@HMH2HEH5!H.H2HEH5HH2HEH5HH2HEH5HH2HEH5HH2HEH5HHo2HEH5HtHX2HEH5HUHA2HEH5H6H*2HEH5HH2HEH5nH~H2HEH5lH~H2HEH5rH~H2HEH5xH~H2HEH5yH|~H2HEH5zH]~H2HEH5yH>~Hr2HEH5xH~H[2HEH5|H~HD2HEH5H}H-2HEH5H}H2HEH5H}H2HEH5H}H2HEH5He}H2HEH5HF}H2HEH5H'}H2HEH5H}H2HEH5H|Hu2HEH5H|H^2HEH5H|HG2HEH5H|H02HEH5Hm|H2HEH5HN|H2HEH5H/|H2HEH5H|H2HEH5H:kH2HEH5HkH2HEH5pHjH2HEH5LHjHd2HEH5(HjHH2HEH5HjH,2HEH5H{H2HEH5HzH2HEH5HzH2HEH5HzH2HEH5HzH2HEH5pH~zH2HEH5_H_zH2HEH5DH@zHt2HEH5'H!zH]2HEH5HzHF2HEH5HyH/2HEH5HyH2HEH5HhH2HEH5sHyH2HEH5HbyH2HEH5kHCyH2HEH5LH$yH2HEH51HyH2HEH5HxHr2HE1ɉHxH^2HE1ɉHxHJ2HE1ɉHxH62HE1ɉHvxH"2HE1ɉHZxH2HE1ɉH>xH2HE1ɉH"xH2HE1ɉHxH2HE1ɉHwH2HE1ɉHwH2HE1ɉHwH2HE1ɉHwH2HE1ɉHzwHn2HE1ɉH^wHZ2HE1ɉHBwHF2HE1ɉH&wH22HE1ɉH wH2HE1ɉHvH 2HE1ɉHvH2HE1ɉHvH2HE1ɉHvH2HE1ɉH~vH2HE1ɉHbvH2HE1ɉHFvH2HE1ɉH*vH~2HE1ɉHvHj2HE1ɉHuHV2HE1ɉHuHB2HE1ɉHuH.2HE1ɉHuH2HE1ɉHuH2HE1ɉHfuH2HE1ɉHJuH2HE1ɉH.uH2HE1ɉHuH2HE1ɉHtH2HE1ɉHtH2HE1ɉHtHz2HE1ɉHtHf2HE1ɉHtHR2HE1ɉHjtH>2HE1ɉHNtH*2HE1ɉH2tH2HE1ɉHtH2HE1ɉHsH2HE1ɉHsH2HEH5Hs1H=oH3MyH0]HEUHEH K2H9HE.HEHHHEsH!2HMH9HMH}R UHH H2HPH}HEHEHHHE=sHƼ2HMH9HMH ]f.DUH7r]ÐUHHH}H} H]DUHHH}uHUHMHE1HHE`H2HHMHHHHM HEH8HHE)gHEHMHA@HHHHM gHEHPHHEfUHEPXHhHHxfHEHpHHpՆHEHHHh`HEHHH``HEHHHX`HEHXHHHPHHPHcHHE؉U\HE؉U HEHH5H}HHqHuHH H}'qMHE؉UHE؉UH}qHEHH5H}H@pHuH@= H}pHE؉UH}p,HEHH5;H}H8VpHuH8 H}cpHE؉UH}NpHEHH5H}H0oHuH0 H}p-HE؉UH}otH=H54#PHuHEHH(uH}H(H}oH}WH]HE؉UH}yoHXH`1Hh%HpيHx=oH}4oH}+oH}"oH} HEH)]H}M f[UHHH}HEHHxHp/nHpHXHHHhwH;HhHcHH5T2Hx]vH5L2Hx]^H5,2Hx|]FH5$2Hxd].H}H5H nH}H5 eHxUSH%4H0HEHH`iHaH}H`rHl2H}HurH,H}HurH}HuHxwrHpH8HMHHHXHPr\HPHHmH}mH} mH}mHXTGG8H5(H}lH2H}HuqHLH}HuqH}HuHxqHpH8HHu[H}H8OlH}FlH}=lH}4lHEUHEU%HEUHEUH}kH}kH}kMHEU%HEUHEUH}kH}kH}kH}k*H}k%HpH8HHxZH]H}I UHHH}HExXHEHEHhHH5%EZHExXHEHhHH5Z]HExXHEHhHH5Y,HExXHEHhHH5YHEH8H}HH]f.UHHH}H}+H]DUHHH}H}+H]DUHHH}H}諳H]DUHH H}uHUHMH}uHUHMH ]f.DUHHH2HH}HMHHHHHM+HEHH9HEHH'HEHpHՄHEHhH3iHEHPH!iHEHHHiHEH8HhHEHHHEHVH]fUHHH}H} H]DUHHH}HEHHEHEHlH]fUHHpH}HuHEHuH}H#PH}EHHHH5HgWHHPH5HHWH} uH}OH}HuIH}t\EH}>_4 1H}Hu)IH}HEHHVHHDgMMƅwƅvH5FH}fH}Hu19UH}Hu1MfnH5HxfƅwH}Hx1TƅvH}Hu1ev H}tTw HxfH}MTH} fEHEȉUHEȉUHEȉUkHEȉUVHEȉU'HEȉUv H}Sw HxqeH}SH}ZeH5yH}e EnH5TH}d E4H5$H}d EH5H}Sd EH5H}d EH5HhcH5yH`cH}HhH`RH`cHhcH5,HXscH5HP[cH}HXHP|RHPYcHXMcH5HH cH5H@bH}HHH@RH@bHHbEȉHPHHHcHHEȉUHEȉUH`bHhb0HEȉUHEȉUHPgbHX[bHEȉUHEȉUH@7bHH+bH5H0aH(1(H8HuH0AaHEH8HHHHRCHHQH0aHH1HHLHH}ؾKHH}ؾKHxH}ؾKHpH}ؾKHhHHHHxLpLh/ggH5H (HuaUHuH`dHWHXHHutdHUWHPH51H`HXLPWHvHvHHEȉUH0_tHEȉUHEȉUH{vHovDHHHuH3OOH5RH H!`HuHVcH7VH@MHHu< cHVH0H51HH@H=2mHb^2H ӭ2HHHCcH=­2,OcH=2X++H5HJ]H=f2HEH H H=]H5mH\H=2H4EHHH\H51H\H=Ƭ2HDHHH\H5HZ\H=v2HDHHHM\H5H \H=&2HDDHHH[H5oH[H=֫2HCHH H[H53Hj[H=2HCHH H][H5H[H=62HTCHH H [H5HZH=2HCHH HZH5~HxzZH=2HxBHH HxmZH5EHp*ZH=F2HpdBHHHpZH5 HhYH=2HhBHHHhYH5H`YH=2H`AHHH`}YH5HX:YH=V2HXtAHHHX-YH5aHPXH=2HP$AHHHPXH5(HHXH=2HH@HHHHXH5H@JXH=f2H@@HHH@=XH5H8WH=2H84@HHH8WH5}H0WH=Ƨ2H0?HHH0WH5CH(ZWH=v2H(?HHH(MWH5 H WH=&2H D?HHH VH5HVH=֦2H>HxHxHVH5HjVH=2H>HpHpH]VH5RHVH=62HT>HhHhH VH5HUH=2H>H`H`HUH5HzUH=2H=HXHXHmUH5H*UH=F2Hd=HPHPHUH5kHTH=2H=HHHHHTH50HTH=2H<H@H@ H}TH5H:TH=V2Ht<H8H8!H-TH5HSH=2H$<H0H0"HSH5mHSH=2H;H(H(#HSH5+HJSH=f2H;H H $H=SH5HRH=2H4;HH%HRH5HRH=Ƣ2H:HH&HRH5hHZRH=v2H:HHHMRH5.H RH=&2HD:HHHQH5HQH=֡2H9HHHQH5HjQH=2H9HH'H]QHEȉUHEQHEȉUH-QHEȉUHQHEȉUHPHEȉUHPHEȉUHPrHEȉUHPZHEȉUHPBHEȉUHP*HEȉUHxmPHEȉUHpUPHEȉUHh=PHEȉUH`%PHEȉUHX PHEȉUHPOHEȉUHHOHEȉUH@OjHEȉUH8ORHEȉUH0O:HEȉUH(}O"HEȉUH eO HEȉUHMOHEȉUH5OHEȉUHOHEȉUHOHEȉUHNHEȉUHNzHEȉUHNbHEȉUHNJHEȉUHN2HEȉUHuNHEȉUH]NHEȉUHENHEȉUH-NHEȉUHNHEȉUHMHEȉUHMHEȉUHMrHEȉUHMZH=oH}1ҹLHHu1ҋsLH=Q2HHH= 2HFH|H`=ı`H}1ҹ-LHhHuKHX,mHP1PXHpHhAKHhXL|Hp16HHp6HHHHHp蒴>HEȉUCHEȉUHhK+HEȉUHpVH5H H0bLHuH(OH(xBHMH HuaOH BBHH551H0HLBH aH(a0HEȉUHEȉUH aH(taHJHJ'H5oH H>KHuHsNHTAHMHHu=NHAHH5L1HHLAH`H`HEȉUHEȉUH\`HP`%H}*H}dIH})+H}MIH}+H}H}1Hp]H}˱H}0H}' oUHHH}uH}uEH]f.DUHH H}HuHEHHUHHHE.3HMHEHH ]DUHH H}uHE}HE"EHMHωE/LU9H=_H5H[C&H}}2HEuHKHH2H ]UHHH}H}苞H]DUHHH}H}B$H]UHH@H}HuHEHHE/HuH}HUBHEHEHHMH;[HEH8<HuUH}BHE؋uHUELEH}HM/HHEHEHHHEHEH@]ÐUHH 1H}HuHMHuHHMBHHMH;AAAH ]f.fUHH0H}HuHEHyHE%1HuH}AHHEHMH; E HEHMEH0]UHHH}uHUHMHEHuHHHUHHuHHEHU+,HHu5HuHMHHHMHuHHE+HHu4H}H5HHMH}HHEHMXEH}HuEEH}eEE3HEHHHu+.HEЉUH}'E"HEHHHuf+HĀ]H}# DUHH0H=)4H+EH=4HuI+HH5I3EH=4HuHE+HH5+3EH=Ƴ4HuHE*HH5 3EH=4HuHE*HH5t3H y4HEHH0]@UHH H}H}HEH}H3H}Huq*H}HEH ]UHHpH}HuHEHHE2*HEH8HuEHEH}wHuHEHHuHEI8H}HuHU)HEHEHEH}<HEHEHEH}DC#HEȉUH}/CHEH HEHEHp]H}! UHHpHH D2H HMHHHHƅHHHe71HHH@ƅƅH1HyXH4H0HHHH BƅHHH9ƅH`E H6 HAHHpHH{YHrHHH@HHpHHhƉHhHpHHH`HHW1ɉHPH.H}HpHP?H@H`7H@!!HHHH.H@WH5NH?HHDžHHHa9HHHDHH HDH(H HHDHH0H(DHHDžHHH8H8H0HFDHH8V.H8H?H>H0>H(>H >H>H>H>HH>HP,H`YUHp,HZH H0H H2 H=HQH'H HH@vTHHHHsHUH7HHH =H06HPHHpuHHxX)HHpUHH1HtZHHpUHHHH1HDH}HH$HHHx=5HxX,HHpUH@H躜]HHpUHHpl=hH@HplDhH8HUHME1HH8H#H8\4HHpHcH`H`5\\4HHH5 H(HP3H(HP]O1ONJ1Hy`N14MHH\MMNNH(LT3LHHDžHH]H@HHDžHH+H8H H@H87H H"H 2xHEUHEUH8v2HEUH(^2lHEUH F2THHH5GHH01HH0/1/.)1Hy`.4..H-1-gHHDž H HH HH HEUH'15H%1HQXD‰}}HHpHH1AHAHƋibHHHH~0qHEUtHHpHH1AHAHaHHQHH0Hd/V }"444HHpuH*H =HHHb4HHH%/H/HEUHEUH.H. H@\@HHpuHE)H kHHH3HHHS.HG.HHH5MHH-HH1Hx`H- HHDžHHHHHDžHHHHHH@2HHhH,`HEUHEUH,H, HEUH, HEUH, H@\x`SHHDž HHHHHHDž HHSHH HDHHU1H*HHH+gHEUH+ HHDž HHHHHSHHDžHHZHHHHDž|H|HHHp apHx~DxHHU1H9)HHHD*gHEUH,*.HHDžlHlHCHHH<HHDžT'HTHHHƫHXH.HHDžP'HPHHH`HXHP.HX%)H5JHH(HHHH`HH(HH$Hx`HHDžD HDHHHHHEUHXR(THEUHEUHH.(HHDž@H@HEHHH>H}9' HHDž,H,H HxH0HUHx,HHDž(H(H HpH8H0Hp3,H8H[H8&H0&0HEUHEUH8&H0&H`&H`&HHH5H Hh8&H Hhg1gf)1Hy`f4ffH e%e&HHDžHH HXHHXHHpHVHHpH& WWgHHDžHHT HHHHHMHEUH $HHpHtHHH5HH@Z$HH@?1?>)1Hy`>4>>H= $=HHDžHH H0HHDžHH H(HH0H((HHHP#0HEUH8#:HEUH #"HuHeH}e"''H@\HH@HMAH0HHH"HHpH4y&&5H5]HHEUH&"(EEH "H@!H!H@!3H}!H}!H}!H}!EF5H}!H}!H}!H}!Hy!Hh!HH]H} f.UHHH}HEHHH]f.fUHH}HEH@]f.fUHH01H}HuHUH:HHUE1DHEHEH8HEH}HuHU讄H;EAAAH0]UHHpHH}HuHUHMDEHMEH@H8H0H}//EEsHEЉUE܃щ֍T6UċU܃|6}H0HEELH}H LƉfH}HUH =H5ơH}$H0HH5wH}HEH}HUHEH5OH}1H0x`E H}E H}gH}^H}U$EEEĉ EEH0HH5&H}HHuHi1$1H0y` E4H}H0HEHuHHH@H HEЉUbHEЉUMHEЉU$HEЉUE H}E H}H}H}EHEЉUH}0H0HHuHHHH0HHuHHHUHh HhHpDpHx1HHHxH@1 HxZHEЉUHx=H0HHuHHH@H H5nH@ H0HH5H`HH`H1>H0xXH0xXH`nHuHX1HXH@ HXNJHEЉUH`6HEЉUHXHuH@c H0HHuH(HH@H! H0HH5țHPHmHPH1$1H0y` E4HP"gH0HDžLHLH+HH@H$HEЉUHP<H0@\EEE H@|H8Hp]H@`H} DUHH}HE]f.UHHpH}HuHEHHEFHEH8HuHEH}wHuHEHHuHE H}HuHUHEHEHEH}HEHEHEH}#HEȉUH}HEH HEHEHp]H} UH}} E"} E EE]f.fUHHH}uHEHuHH]fDUHH@H}HuHEHHEHEH8Hu~HEH}+HuEH}HUHEH}HEHEHHEHEH@]f.@UHHH}@uH}ueH]f.UHH@uH}H}ueH]f.UHHH}uHEHuH|$H]ÐUHH@H}HuH}HuHEH}HHEH}Hu$HEH}`HEH@]HEUH}FH} f.UHH HHHMHuUHMEH}HEHx EHxHpHwwHxHpHQpp;EHxHH5H}Hh?HuHhgH}FggHxHEHuHUHXH}HXQ!HEUHEUH}H5H}AH}Hx}HuH}H}}HxHpH*jWW$EHEUH}?HxHpH PPBHxHpH HHH}HHٳH}HxHH5ȔH}H@pHuH@ ?H}w?gHxHEHuHH0H}H0!HEU>HEUH})EEH},,9HxHpuH}H THH01ɉH H}HxHuH}H}^EEZHEUH}@g1MEWHxHH5)H}HEHuHhE H}jHxHEHuHHH}H$HEUE H}0WHx@\HpHH 1H[H}H}yHxHpHAHxHpHb 4yEE H}ZHEH ]H}DH} fUHHH}uHEHuH,$H]ÐUHHH}uHEHuHlH]fDUHHH}HEHH貶H]f.fUHHH}HEHjH]fUHH H}uHE}HE"EHMHωE/U9H=_H5H[CH}uHEuHH:H ]UHH@HH}HuHMEHxHpHhxHhP`‰P`HH5ЏH}H`^ HuH`\\EE H}HuHPHPH}؉L- LMHhH`U)ENjP`‹u)EƋp` uHHuHljHD8CCiHhHHuHBB2E !HEЉUHEЉUH}_ EHhHHuHyH8HxH8rHhHMƃMHuH/H0HxH0(IHhHE HuHH(HxH(Hh@\H}1HBHuHxH}? EHhHpH''4#H}HhHuHx3H} HhHpHe 8EzEpHhHHuHHHxHE*HEЉUH}/ cHEЉUH} NHhHpHHH}HH}EEH}9HhHpuH}HHH01ɉHYH}Hh2HuHxgH}!HEЉUHEЉUH}jEEHh@\HpHH11HH}蔙H}膙HhHpH9EUEEBHhHHuHUHHxHNEHhHMƃMHuHHHxHHhHHuHHHxHIHhHE HuHlHHxHeHhH`H`EE HxHpH@]HxH}P UHH}HuHEHE; HEHEHEHEHE]UHHH}HuHEH8Hu"HH]f.UHHH}H}$H]UHHHH}HuHUHMHMEHH˜EHuLEH(HHH LHHEH}HUH H}HuHU HUH}Huz HHDždHhHdHH}HuHh/ HH}Hu HHDžTHXHTH2H}HuHX HUH}Hu HHDžDHHHDHH}HuHHj HHDž4H8H4HHuH8H( H8H}HHH}H}HXH}H}HhH}H}H}H}|EE|kHxtKHxt0HxtHxtHxtHxtHxtHxtHxtmHxtRHxt4HxtHxtH8xH}oHHcH}ZH}QHXEH}<H}3Hh'H}H}H} H}H(HH]Hxt @UHHpHH}HuHMEHHHHQH}HHEHHHHHOHEEbHE؉U|EEHHEEH5(H}HH}HUHxH5H}_yHHH5H}H+EH}HUHEH5H}E H}E H}H}H}$EEẺ EȉEHHH5H}H4HuHH};HHEH}HUHlHuHIH}HE؉UbHE؉UMHE؉U$HE؉UE H}E H}|H}nH}eHE؉UH}PHE؉UH};HHH5HxHHxHy1>HxXHxXHxHHH`HUHHXHHhH`HX1HHHPHUHZHpHhHPHpHHpHPHhHXH`zHE؉UHxbHE؉U[HE؉UCHE؉U+HE؉UHE؉UHpHPHhHXH`XHHH8HUH-H@H8HHHH0HUHHHH@H0|HHHHH9H0-H@!H8`HE؉UCHE؉U+HE؉UHE؉UHHH0H@H8#HHH5|H(H[H(HH(\HHDžH HHH H^H 0HE؉UH(IHE؉UH 1EEE HHHp]HH} fDUHHHH}HuHMEH@H8H0H0HpHUH(H}H(iE}UHcEH .2H4H}HcEH .2H4H}H}Hu(H H}HUH0H uHuH@H}bH}YH}PHcEH %.2H4H}H}HuH}EЃE HE؉U?HE؉U HE؉U%HE؉UHE؉UH}H}H}HE؉UH}H}HuH}HuH}HuH}Hu[HxHu<1}(HxHHHHH'DžtHxHE؉UH}HHhH}'DžtHh-HE؉UBH`HuHhƅWH`1H5a~H` 1 vH5E2HXQƅWH`HX1ɨ/H5Y~HhR W  HXD HHHhH`H0HHH@RHHZHE؉UrHE؉UZHE؉UW HX0HE؉UHHH`|EH`dHhX!H}wEEHx/EDžtH}JH}E(H})H}H@H8H]H@H}H UHHH}HuH}HucH]f.UHHpH}HuHEHHEHuH}HUHEHEHHMH;HEH8]HuUH}HE؋uHUHEHljuHUHELEH}uHUHMHEHEHHEH}&HEȉUH}HEHHHEHEHp]H} @UHHPH}HuHEHHE EH}v1HMH1FEHuHHEHEHHMH;E1HMH H HMHMHUH; E&HEHHMH HHH"EE$EHMH1H}HMHUH HMHDBADBEvHEH8EHMH+BEEHP]fDUHHHH}HuHMEH}HEHMH}dEH}uXH}HHEHEHEH}HEHEHEH}HuEELH}HEH}HuH}HEUH}$EE H}cHEHĀ]H} f.UHH0HEH}HHEHuH H}HuH}HuhH0]f.UHH0HHHMHuHMH}HHEHMHEH^H}H:HEH0]UHH0HHHMHuHMH}HHEHMHEHH}HHEH0]UHH HHHMHuHMH}HHE6H}H:HEH ]UHH@HHHMHuHUHMHzH}HEHM%1HuH}HHEHMH;H}+HEHH}HPHEH@]fDUHHH}H};>H]DUHHH}H}`H]DUHHHH}HuHMEHHHHHpHHH}HH5pH}TH}HuHH}ȺHkH}CH5uH}LH}HE؉UHE؉UHE؉UH}HE؉UwH5uH}H}HuHUH}HuH}HH}xHE؉UH}c EEH5nH}H}HuHH`H5~nH}EH5\nH}EH}Hu?HxHx fxH}DEH}Hu1HxG H}(E H}PE H}8H}/ƅ_ƅOH5mHhH}HhuHpHp%llH5CmH`ƅ_H5*mHPeƅOH}HPH`H@ @HH9DHHpH`1H` HpO HP_ H`HhHHDžHHHH5 lHRH}HHXHHHXaHHHUEHkHH H5kHH}H[HPHHHPH HHpH(H HUHHDžHHHH0H(HGH8eH8H0"H8HPH8H0HH(H HHHHHyHmHaƅƅH5iHH}HHHH5boHHGGH5iHƅH5jiHƅH}HH8H CH`DHH1H8 H H HHƅƅoH5hHH}H4H0H5mH0a//H5hH8ƅH5hHpƅoH}HpH H` `HhDhHH1H  Ho Hp HH{ƅGƅ7H5gHP*H}HPHH5|lHH5fHHƅGH5fH8ƅ7H}H86HH( ](H0zD0HXHH1H2 HX7 H82G HHHPHHHH HHXH &4H HHHDžHHHHHHHH1*HR4H zdHbGHEHHHHHHHHXHHDžHHHHHH/H ^HH HH8HHHHHHHHyHE؉UMHE؉U$HE؉UE H}=E H} H}HE؉UHE؉UYHE؉U*HE؉UO HP_ H`Hh0HE؉UHE؉UHE؉UHE؉UHE؉UHE؉UHE؉UHE؉UsHE؉U[HE؉UCHE؉U+HE؉UHE؉UH8H0HH(H HHHHH|HpHdHE؉UYHE؉U*HE؉U H" HHHE؉UjHE؉UYHE؉U*HE؉Uo Hp H}HlHE؉UHE؉UYHE؉U*HE؉U7 H8G HHHPfHE؉UNHE؉UHE؉UH HHE؉UHE؉UHE؉UsHE؉U[HE؉UCHE؉U+HE؉UHE؉UHBH6H*HHHHH^EHXHHHpH}H}H}zEaPHXHsHgHp[H}RH}IH} H/HH]HH}訹 UHHpHH}HuHUMHUEHHHH}HEHUH}HuVHUH}HuHuH}H}HUEH}HuHuH}HuH}HEHPHMHHHM"H}HuHuH}]EH}H}EYKHE؉URHE؉UH}=HE؉UHE؉UH}H}H}HEHp]H}rH} UHHH}HuHEH5\HMHHEHxH}1HxHH}HuH}1‰ttpH}HuH}HEȾHhHOH`H5d[H}H`HH[H}HuHEHH}ȾHXHPH}HXHPHuHUHhH}H}H}H}@HE؉UH}HE؉UHE؉U:HE؉U%HE؉UHE؉UH}H}H}wH}@HEHH5(ZH}HHHuHHUDH}!DE}<EH}B@@+EEE;EH}H5_HEH8HEMHuH8M44EH}|}/HE؉UH}]HE؉UH}HH}uHE H(Hlj$:MH($H}7 +EEH}H]H}H}L f.fUHHHH}HuHUHMEH}HEHM-HuHEHpHHEHH5WH}HEHuH}覷EH}E>HEHEHuH*HxH}Hx&HExXhH}HuHuH}H}}HE؉UHE؉UH}kHE؉UH}VH}HuHuH}H}$HE؉UH}gHEHEHuH/HpH}Hp+EE H}HEHĐ]H}H}/ f.DUHHHH}HuHUMHUEH@H8H0HuH0HpHgH0HpH,,EEGH0HpH^H H {EH0A`HpHH0HpHHH H0A\HEHuHωJHH@HCH0HE HuHHH@HH0HH5SH}HNHuHH}UjH0HEHuHdHH@H]!HE؉UHE؉UH}H0xX(H0HpH}1ҹHY8MH0HpHHH}1ҹHD̚HEHuHH;H}H0HTHuH@iH}H}UH}H0赺HuH@*H}H0HH5QH}HpHuH H}wH0HEHuH膵HH@H`HE؉UHE؉UH}H}HE؉UHE؉UH}lHE؉UH}WH0HE HuHݴHH@HֽH0HDž|H|H蓴HH@H茽H0HDždHdHIHH0HpH5VHPHHXHPHHhHXHH0HDžLHLH诳HHpHhHaHpH@艼HpHhHXHPH0Hpu1ɉHTEH}EziHE؉UCHE؉U+HE؉UHE؉UHpHh|HXpHPdH}[H@JH8HĀ]H@.H}ê UHHH>1HHEHHHHDžHHpHpHHHHHHhHpHh7HHYDžHd`d`9HIHXHXHHHHшWW HHHp&HH般HH1Hp HHpHH7HH5"MH4H(NHzHHHH>kddHP5LPL;$Hp۝HpHPHxHHH@$HpH@HHxӪHxHH`H1HHMH9HH]HHxHHH  f.UHH}HE@]f.DUHHH^1HHEHHHHHHhJHhxX9H=JɨHHHHgHhHHHHHH`HhH`HH1DžH DžHHHHω\HPHP\9HHHHHшOOHHHhHHOHH1HhHHhHHHH5HHH`HHHHHHokddHHHHHH@H8H@1ɉH8H||;$|Hh|HhHPHpHHH0HhH0RHHptHHH1HHplHHTH}1HHMH9HH]HHpHHH蕢  f.@UHH0H}HuHEHHE聤H}认HEH}pHEH0]HEUH}VH} f.UHHH}HuHUHEHuHMHHEHM 0EЋuH}EE4EHEȉUH}Hu袤HExXHExX8H=E詣HEH}HuY HEȉUsHUH}1HutH}Hu<H}TH}ˣH} EH}HĀ]HEȉUH}H}٣H}֩H}藠  DUHHpH}HuHUHEHuHMHHEHM莩EЋuH}dEE4EHEȉUH}Hu%HExXHExXAH=!D,HEH}HuܢHEȉUH}ԢCHUHuH}H}bH}袢EH}蘨Hp]H}艨H}J  UHHpH}HuHUHEHuHMHHEHM>cEЋuH}EE4EHEȉUH}HuաHExXHExXAH=BܠHEH}Hu茡HEȉUH}脡CHUHuH}`H}H}REH}HHp]H}9H}  UHHH}HuHUHEHuHMHHEHMEH}oEȋuH}谦4EEOHEU]H}HugHExXHExX>H=cAnHpH}HpVHEUH=A0HhHhHEH}HuH}ǟH551H}HUH}1HuH}Hu蜟H}贽H}+EEH}`HEUH}}H}BH}:E$HĠ]H} H} UHHH}HuHEH}H]UHHH}HuHUHEHuHMHHEHM軤EH}Ⱦ?EЋuH}耤EE4EHEUH}HuAHExXHExXAH==?HHEH}HuHEUH}[H5V1H}HUHuH}H}iH}詝EH}蟣HĀ]H}荣H}N  f.fUHH0H}uHUHMHEHHHHuHE譡H}H衪HMHHHuHE膡H}HzH0]fUHH H}HuUHEHHuMHk$H ]UHH H}HuUHEHHuUHT$H ]fUHH H}HuHUHEHHuHUH2$H ]UHHH}HuHEHHuHjH]@UHH HHHMHuHUHMHHUHHE˛HEH ]ÐUHHH}HuHEHHuHZ$H]f.DUHH HHHMHuHUHMHHUHHE[HEH ]ÐUHH HHHMHuHMHHHE賝HEH ]fUHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]f.fUHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HmHMHcHEHMEGEHME4EHME!EHMEEHMEE]ÐUHHH}HEHH HHEJHEHH8HEHH&HEHH4H} H]DUHHH}H}+H]DUHHH}H}H]DUHH H}HEHHHEHEH8?H ]HHUUHHH}HEHHEH*H}HHEHMHqHǺHEH H]f.@UHH}HEH@]f.@UHH H}HEHHHHEږHEH HȖH}胨H ]fUHH H}HEHxHEH}ζH>HEHxH}躶HH ]f.UHH}HEH@]f.@UHH}HEH@]f.@UHH H}HEHHHEIHEH8KH ]HHUUHHH}HEHHEH*H}H5HEHMHqHǺLHEH:H]f.@UHH}HEH@]f.@UHH H}HEHHHHE HEH H H}衦H ]fUHH}]fDUHH H}HEHxHEH}ܴHLHEHxH}´H,H ]f.UHH}HEH@]f.@UHH}HEH@]f.@UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH}uHEM]f.UHH H}HuHEH}HE/H}HcH}Hu膛H}mpHEH ]UHH}HE]fUHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH}uUHEMMH]ÐUHHH}HEHHpH@H]fUHH}@uHEM]fUHH @uH}HEH}HE蛧HMfH ]fUHH}HE]f.fUHHH}H}oH]DUHH H}HEHHHEIHEH8跢H ]HHUUHHH}HEHHEHH*H}5H}HEHMHqHǺLHEH:H]f.@UHH}HEH@]f.@UHH H}HEHHHHE(HEH HH}H ]fUHH}]fDUHH H}HEHxHEH}*H蔢HEHxH}HtH ]f.UHH}HEH@]f.@UHH}HEH@]f.@UHH H}HEHHHEiHEH8觠H ]HHU1UHHH}HEHHEPH*H}=HyHEHMHqHǺlHEHZH]f.@UHH}HEH@]f.@UHH H}HEHHHHEBHEH HH}H ]fUHH}]fDUHH H}HEHxHEH}&H萠HEHxH} HpH ]f.UHH}HEH@]f.@UHH}HEH@]f.@UHH H}HEHHHE艢HEH8ߞH ]HHUQUHHH}HEHHE|H*H}iH諟HEHMHqHǺ茍HEHzH]f.@UHH}HEH@]f.@UHH H}HEHHHHEbHEHH\H}H ]fUHH}]fDUHH}]fDUHHH}HEH8HE誮 H}讔H]UHHH}HEHqH|H]f.fUHHPH}uHEHHEHEuH}荟HEH}H}HEHMH}HuH腔MHE؉UH}YH}HEPHEHMHUQHE؉U,$H}+ HuH}HP]H}  HHU f.DUHH H}HEHHHHEŸHEH0H/H ]HHU臬UHHHQ1H}HuH}HH]UHHH}H}HS-H]f.UHH}HE]fUHH}HEHx]fUHHH}HEHHHHE@ H}.H]f.@UHH0H}HuHUHEEHy HE H}/H}HEHq$EH} EHMHuUH}آH0]UHH H}HEH;H HEHEHHlj苜EEE$H ]UHH0H}HuUHEHy HEHEHHIUH01v ҉HHHMHMH HuH;HEHH8H=*H54*1HMH HUH; EHEH8uHU$4E׊EרHEHHEHEHEHEH0]fUHHPH}uHUHMLEHEH8HEH}H}$HuHUMH}LHHExAHEHEHUHuHHUH2NNHEHP]f.UHH H}HEH8HEH}蔍H51H1H} A蛚HEHEHHHHEH0H\HEHMHH ]f.DUHH H}HuH}1AHEHEHUHHuHH}OHHuHHUZ@H ]@UHHEEH}HuŃH]DUHH01H}uHUHMu;qHMEH}HEHHҨEߊE$H0]f.UHH H}HuHEH}HE/H}H#H}Hu\H}0HEH ]UHH}HE]fUHHH}HuH}HuAH]f.UHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}HEHHHE H};H]DUHH0H}HuH}蛤HEH}LH}HuɖHEH}+H}HEHHh HEHE HEHEH0]f.UHH`H}HuHUHEHHE莈HEH8HEHEH8HEHEEH}ZHEHEHEHHuH蹀HEHEEH}lHEEH}\HEH}JH}HEHH\,HuHEH H莐HuH}HE 5HEH8HuHUHMDEAEHEHuH}ѯHEH`]UHH}HEHH ]fUHH H}HEHE˓HEHEHHy9HEHHIHuHFHMHAHEHxHEHHHEHH HEH8_HEHMHHH9H ]fUH]DUHH01E1H}HuHUH}HHII HULْHEHEHMHHE_H}؉*HMHy6H}XHuHzHMHAHEHxHEH HEH@HEHx6H} HuH)HMHAHEHxHEH蟁 HEH@HEH0]fUHH0H}HuHUHMADEHEHMDEAHǾ(E辀HEHEHMPHEH HuH蓤HEH0]fUHH H}HuHEHEHEH}JHEHHuH1}HEHEH}HE H}ܠHEHEH ]ÐUHH}HuHEHE;€]f.UHH}HEH]f.fUHH@HILEHuHUHMHMH HuH}HHEIHEH}HEH HEHEHEHEH}H=HEH@]UHH0H}HuH}HEH}LH}HuHEH}+H}HEHH{ HEHE HEHEH0]f.UHH H}HuHEHEHEH}JHEHHuHK{HEHEH}HE H}؞HEHEH ]ÐUHH}HuHEHE;€]f.UHH}HuHUHEH;E/HEHE;HEHHEHE]f.UHHH}HEHHHEw H}苁H]DUHH`H}HuHUHEHHEbHEH8HEHEH8HEHEEH}ZHEHEHEHHuHyHEHEEH}XHEEH}HHEH}JH}HEHHfy,HuHEH H螉HuH}HE5HEH8HuHUHMDEAEHEHuH}HEH`]UHH}HEHH ]fUHH H}HEHE諌HEHEHHy9HEHHIHuH2HMHAHEHxHEHH{HEHH HEH8?HEHMHHHI{H ]fUH%{]DUHH01E1H}HuHUH}HHII HUL蹋HEHEHMHHEoH}؉:{HMHy6H}DHuHzHMHAHEHxHEH{ HEH@HEHx6H}HuH)HMHAHEHxHEHz HEH@HEH0]fUHH0H}HuHUHMADEHEHMDEAHǾ(EyHEHEHMPHEH HuH裝HEH0]fUHH}HEH]f.fUHHH}HEHHHEW H}}H]DUHH0H}HuH}HEH}LH}HuHEH}+H}HEHHu HEHE HEHEH0]f.UHHPH}HuHUHEHHE|HEH8HHEHEH8VHEHEEH}ZHEHEHEHHuHuHEHEEH}躘HEEH}誘HEH}@H}HEHHt"HEHEȀHHuH}u5HEH8HuHUHMDEAElHEHuH};HEHP]ÐUHH}HEHH]fUHH H}HEHE#HEHEHHy9HEHHIHuH褗HMHAHEHxHEHHZwHEHHa HEH8跇HEHMHHHvH ]fUHv]DUHH01E1H}HuHUH}HHIIHUL1HEHEHMHHEϋH}؉vHMHy6H}趖HuHzHMHAHEHxHEH`v HEH@HEHx6H}kHuH)HMHAHEHxHEHv HEH@HEH0]fUHH0H}HuHUHMADEHEHMDEAHǾ E.uHEHEHMPHEHMD ADHHEH0]f.fUHH}HEH@]f.@UHH}HEH@]f.@UHH H}HuHEHEHEH}JHEHHuH[qHEHEH}HE H}HEHEH ]ÐUHH}HEH]f.fUHHH}HEH8HE H}}H]UHHH}HEHqH}H]f.fUHHPH}uHEHHEiHEuH}݆HEH}LH}HE3HMH}HuH}MHE؉UH}詖H}HE蠆HEHMH襖QHE؉U|$H}{ HuH}4}HP]H}]o HHUA f.DUHHH}HEHv$H]f.UHH H}HuHEHMH HHHHHEΆHMHDB(AA H}rxH ]@UHHH}HEHHHHE H}xH]f.@UHH H}HEH8HEH}wH5)1H1H} A諄HEHEHHHHEH0HwHEHMHH ]f.DUHH H}HuH}{w1AHEHEHUHHuHH}OHHuHHUH ]@UHHH}H}wH3H]f.UHHEEH}HumH]DUHHH1H}HuH}HeH]UHH}HE]fUHH0H}HuHUMLEH}HuHUMLE H0]UHH0H}HuHUMLEHEHUHMHHHHuHHE誓HEHHuH蔓H0]f.@UHHH}H} H]DUHHH}HEHHHHE:HEHH(H]fUHH H}HEHHHHE蒃HEH0HMuH ]HHUWUHH0H}HuHUHEEHy HE H}/H}HEHq$kEH} EHMHuUH}܇H0]UHH0H}HuUHEHy HEHEHHIUH01v ҉HHHMHMH HuH;HEHH8H=H54k1HMH HUH; EHEH8uHU*4E׊EרHEHHEHEHEHEH0]fUHHPH}uHUHMLEHEH8HEH}EsH}$HuHUMH}LHHEHEHEHUHuHHUH2NNHEHP]f.UHH01H}uHUHMu;qHMEH}HEHHEߊE$H0]f.UHH}HEHx]fUHH H}HuHEHMHHEFrHEH8HMH/H ]UHH@H}HEHP 9HEyHEHP9eHEHMHMH}HuhHEHEȋ0H}~HEUEH}HEݎH@]f.fUHH H}uHEHQ;UHE>HEH8uH}sHEuHk~H ]fDUHH}HEH@]f.fUHHH}HEH8}H}H\HEH]fUHH}HuHEHHMH;€]f.UHHH}HEHH}HHEH]UHHH}HEH8lpHH]f.fUHHH}HEH8HE}HMHHH]@UHH}HEHHMHHHMP U܋E܉M܃4HEHH;EHEHHEHEHHEHEHEHE]fUHH0HEH}HHEHuHM\H}Hu@\H}HuHUSH0]fUHHHUHEHHHEHHH[HHǃHcHMHMHHHH HHcHr H}HHHpHLHHx9HHxHs .H HHpHpH e H}HZH}HH"pH}HZHMH}HuHUۉ H}HZH}H葂H}H|HoH}HZZLEH}HuHUHMq H}H,ZH}H!H}H H}HH1oH}HYLMH}HuHUHMLE H}BHxHYHpHYHUHxHp胈J HhHSYH`H@YH`nH}HEHHHPHPHhTnHPHhHHHHPHHHXHPH@HH趀H8HhXHPH0Hh艀H(H`lXLMHHH@H8H0L(\HEHHHPHPHhcmH HH`WHHhWHH`WHMH HHHֆ\HHWHH`WH}HHXHFHhHP3HXHPHmHtlHH~HXlHHHH,lH}HH@HH8~HH0kH~H@H0HHHV~BH}HH(H$~HH ~H(H HKNH}HH}HH_\\H!kHk,HH}}iH}HHHA}HH.}HHHh4HyjH}HHH|HH6jH|HHHHH|NHe|HHR|HHg^\\HiHHzi5H}HHH{HhH{HHHBH{HH{HH]\\dHhHHHa{zH}HHH{HhH{HHH?HRhH}HHH"hHzHhHzHHH4HHlzH\\\HhHyHhHBgHHgHHhyH}HhHHyHHuyHHH=HFyHhH3yHHH[\\\HHQHHQHUHH $HHxHHPHUHH*fHHeo HeHHeBHH PHH xHHOHHw9]HHOHHOHUHHvHdHHdUHHhwHHKOHUHHHHkd!HĀ]}} dUHH}HEHHH)H]DUHH H}HuHUH}Huc~$H ]@UHH}HEHHH]DUHHH}HEH8cH]fUHHH}HuH}HugH]f.UHHHMEHEH}HHuHUHEuH}HEuH}HuHH}HEH}HuH}HEuH}HuH EEH}luH}HE_uH}HwWEH}HEH}H8uH}HE+uH}HuHk)H}uH}HEtH}HWEEE&H}HEH}HtH}HEtH}HuH:H}tH}HxtHxHVEMMH}YtH}HpItHpH^VEH}HEHhHtH}H` tHhH`HF/H}sH}HXsHXHUEEEEHİ]UHH HHHMHuHUHMH HUHHHHE(HEH ]f.@UHHLEHEH}HHEHuHHUHM>KH}Hu1KH}Hu$KHMH}HuHU9zEH}HMH}HrH}HErH}HuH H}rH}HErH}HTMMH}HEH}HorH}HEbrH}HuHH}H`1HXLPLHHh%HH[HP[HX[H`[H5H@?[H5 H8,[H5CH0[H5s1H(=H@1H8L0L(Hh$H(ZH0ZH8ZH@ZH5H |ZH5HiZH5HQZH51H =H HLLHh#HZHZHZH YH5RHYH5HYH5HYH51HF<HHLLHh8#HWYHKYH?YH3YH5HXH5HXH5HXH5w1H;HHLLHhr"HXHXHyXHmX!HEU:HEU%HEUHEUH}4XH}+XH}"XH}XT!HEU:HEU%HEUHEUH}WH}WH}WH}W!HEU:HEU%HEUHEUH}WH}WH}zWH}qW HEUCHEU+HEUHEUHh5WHp)WHxWH}WO HEUCHEU+HEUHEUHHVHPVHXVH`VHEUCHEU+HEUHEUH(xVH0lVH8`VH@TVHEUCHEU+HEUHEUHVH VHVH U/HEUCHEU+HEUHEUHUHUHUHUHEUCHEU+HEUHEUHXUHLUH@UH4UoHEUCHEU+HEUHEUHTHTHTHTHEUCHEU+HEUHEUHTHTHTHtTHEUCHEU+HEUHEUHh8THp,THx THTOHEUCHEU+HEUHEUHHSHPSHXSH`SHEUCHEU+HEUHEUH(xSH0lSH8`SH@TSHEUCHEU+HEUHEUHSH SHSH R/HEUCHEU+HEUHEUHRHRHRHRHEUCHEU+HEUHEUHXRHLRH@RH4RoHx3H8HpH`GH#HHHXQH`H0HHXHPHQHHHP?IHUOH5K1H#4OȃHHHhH@H@H+QHEHQHQHiHHH8PH33H0HH8H0HPHHH04HHS/H5Y1Hx3/ȃHHxHhH H Hx PHDHPHOHHpHHOH(3H0HXHHHOH`HXH)GH`RH5e1HP 2ȃHpHPHhHHHPOH`CHXNHpNH5HHNH5H@NH3H0HH(HHoNH0H(HF1H0QH5d1H 0HHH@L HhH NH0BH(MH@MHHMH5HMH5HMH3H0HHHHUMHHHD1HPH5]1H/HHLHhHLHAHLHLHLH5HzLH5HgLHۻ3H0HHHH;LHHHC1HOH5{1H.HHLHhtHKH@HKHKHKH5H`KH5HMKH3H0HHHH!KHHHBHHNH51H-HHLLHhHJHJHt?HJHJHzJH HHH-JH3H0H`HHHJHhH`HAHxHhoMH51HX,HHxHXHhHXIHxIHhe>H`IHwIH,HPHH*IH3H0H0HHHIH8H0H@HHH8lLH51H(+HPHHH(HhH(HHHHH8b=H0HHPtHHHH HH'HH3H0HHHHHHHH?HHiKH51H*H HHHhHGHGH_<H}GH qGH`HHH$GH3H0HHHHFHHH>HHfJH51H)HHHHhHFHFH\;HzFHnFHpHHH!FH3H0HHHxHEHHHx=HHcIH51H~(HHHHhHEHEHY:HwEHkEHHHHpEH3H0HxHpHhHDHHxHh<H[HgH51Hp|'gȃHHpHhHXHXEHpDHN9HxlDH`DHHhHHPDH3H0HPHPHHHCHXHPHH;HXPGGH51HHq&GȃHhHHHhH8H8:HHyCHXC8HPaCHhUCH5ZH@CH5H8BHs3H0H%H H0HBH(H H0t:1H(-F,H51HT%H@H8LHh, HkBH(57H SBH8GBH@;BHHHH AHg3H0HH HHAHHHh9HH0EH3H0H HHHdAHHH9HHDH51H#HHLLHh H@H@H5H@H@H5H@H@HHHHX@Hѯ3H0HHHH1@HHH7HHCHn3H0HHHH?HHHo7HH7CH5I1HxR"HHLLxHhD Hxc?HW?H!4H??H3?H3H?H?HX3HH4(HEUCHEU+HEUHEUH>H3H>H>HEUCHEU+HEUHEUHxa>H+3HI>H=>xHEUCHEU+HEUHEUHP>H`2HX=Hp=HEU[HEUCHEU+HEUHEUH =H0_2H(}=H@q=HHe=HEU[HEUCHEU+HEUHEUH=H1H=H1LELMH}HuHM EH}?1E$H`]HEЉUH}!1H} fDUHH@H}HuHUHMLELMHEHuHMHHuHHE1HMLELMH}Huȉ$H@]f.UHH H}HuH}H5<0 EH}H5]0 EhH}H5</ E?H}H5/ EEEH ]f.UHHpH}HuHEHHEHEH8HuV1HEH}wHuHEHHuHE)$H}HuHUpHEHEHEH}(HEHEHEH}$/#HEȉUH}/HEH HEHEHp]H}  UHH@H}HuHEHHEHEH8Huj0HEH}.HuEH}HUkHEH}'HEHEH HEHEH@]f.UHHH}HuHUHEHuHUHHEH5óH H}.HuHEHHE2H}$HEH51H}HU%H}DE=HEUH}jD9HuHEH}HuHHHuEE$HĀ]H}  UHH0H}HuHEHHEBEHEH8Hu.HEH}HEH8HuMMEH0]UHH0H}HuHEHHEEHEH8Huc.HEH}HEH8Hu&MMEH0]UHHpH}HuH}HuHE=H}HHu H}1ɉΉM=MUHEAHHuHE8+H}uHEH}HEH}HuHUEH}nE$Hp]HEЉUH}PH}5  DUHHH}HuHUHEH}HH}HuH$!EE7 HEȉUN HHHuH%HH}|豏H}1MUH}AH)H}HEHH; HH:HHHuHgHHHHHVHHHcHHHHuHDHHj)EEH}HuH}HuH}Hu&H}&HH}:>u1ҹH(vH}t&HH}:Hx1xUH}AH(H}1ƺ (tH}TH1ƺ H'pH}1H1ƺ H'lt;l7t;p%EEHEȉUH}衐(EH}茐EH}EHuH}غ1EEEExHHHuHr HH&EEHuH}غEEEEH}H5^&H}H5C0&aH}H5&3H}H5%EEEEH}H5H`HH%H`HH`%H}H5HXHxH?%HXHxHXF%H}H55HPHpH$HPHpiHP$H}H5ͫHHHhH$HHHhHH$H}H5ܳH@H`Ha$H@H`H@h$H}H5?H8HXH$H8HXH8$Huƅ'ƅ&H}кWWVH}H5H(HHH#ƅ'H0H(1ƅ&H0HH#GGVV&F H0f' H(#FEEHEȉUH`"HEȉUHX"HEȉUHP"HEȉUHH"HEȉUH@x"HEȉUH8`"HEȉU*HEȉU& H0d' H(">EE EEH}莊H}腊E$H]H}kH}bH}G Es@UHHH}HuUHEEHEfHuHHMHHuHHM!H}HuHUEE$EH}!{HEЉUH}!wHuHHMHHuHHM H}HuHU|EE$EH} HEЉUH} E$HĀ]H} f.UHHPH}HuUH}HuEHM H}HHuHMH}HuHUEH} E$HP]HE؉UH}H} UHH`H}HuHEHuHHEHUHEHHUHEWH}HuHUHM1H} EEEH}TH}K1HEЉUHEЉUH}*H}!EEH`]H} UHHH}HuHEH8Hu HH]f.UHH@HILEHuHUHMHMH HuH}HHEM HEH}HEH HEHEHEHEH}HM$HEH@]UHH`HHHMHuHUHMHuH}HHEHMTUHUHEHHUHEH}HuHUHMH}%HE؉UH}H}H5BhHEH`]H}# UHHPH}HuHuHUHEHHuHUHEH}HuHUHMH}-H5H}EEM(H5ӣH}EEEEH}EE$HP]HE؉UH}HE؉UH}H}0 UHHH}HEH8H]fUHH1H}HuH}HuH]f.DUHH`HH}HuHUHMH HUHuH}HHEHMHUHuH}HuHUHMH}HEH`]HE؉UH}H}E DUHH0HHHMHuHuHMH}HHEH}HuEH}HEH0]fUHHHH}HuHMEH}HEHM1EH}PEH}uxH}4HEHEHEH}HEHEHEH}HuEELH}HEH}HuH}yHEUH}$EE H}HEHĀ]H} f.UHHH}HuH}HuSH]f.UHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]f.fUHH}HE]fUHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH H}HuHEH}HEoH}HPH ]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HmHMHcHEHMEGEHME4EHME!EHMEEHMEE]ÐUHH H}HuHEH}HE/H}HC`H}HuH}-`HEH ]UHH}HE]fUHHH}HuH}Hu[H]f.UHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH H}HuHEH}HE/H}H#_H}HuH}-_HEH ]UHH}HE]fUHHH}HuH}Hu5H]f.UHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}HEHHHE H}H]DUHH0H}HuH}wHEH}LH}HuHEH}+H}HEHH\ HEHE HEHEH0]f.UHH`H}HuHUHEHHE.HEH8HEHEH8HEHEEH}ZHEHEHEHHuHHEHEEH}0HEEH}&HEH}JH}HEHHP,HuHEH HHuH}HE !5HEH8HuHUHMDEAEHEHuH} HEH`]UHH}HEHH ]fUHH H}HEHEHEHEHHy9HEHHIHuH HMHAHEHxHEHHHEHH HEH8HEHMHHH9H ]fUH]DUHH01E1H}HuHUH}HHII HULHEHEHMHHE_H}؉*HMHy6H}HuHzHMHAHEHxHEH HEH@HEHx6H}HuH)HMHAHEHxHEH HEH@HEH0]fUHH0H}HuHUHMADEHEHMDEAHǾ(EHEHEHHuHHEH HuHHEH0]UHH H}HuHEHEHEH}JHEHHuH%HEHEH}HE H}HEHEH ]ÐUHH}HEH]f.fUHHH}HEHHHE H}uH]DUHH0H}HuH};HEH}LH}HuQHEH}+H}HEHH, HEHE HEHEH0]f.UHHPH}HuHUHEHHEHEH8HEHEH8rHEHEEH}ZHEHEHEHHuH}HEHEEH}HEEH}HEH}=H}HEHH HEHEȉH HuH}5HEH8HuHUHMDEAEHEHuH}HEHP]@UHH}HEHH ]fUHH H}HEHE?HEHEHHy9HEHHIHuHHMHAHEHxHEHHHEHH HEH8HEHMHHHH ]fUH]DUHH01E1H}HuHUH}HHII HULGHEHEHMHHE?H}؉ HMHy6H} HuHzHMHAHEHxHEH HEH@HEHx6H} HuH)HMHAHEHxHEH HEH@HEH0]fUHH0H}HuHUHMADEHEHMDEAHǾ(EHEHEHHuHHEHMP HEH0]fUHH H}HuHEHEHEH}JHEHHuHHEHEH}z HE H}n HEHEH ]ÐUHH}HEH]f.fUHH H}HuHEHMHHHEHEH HHEHMHHH ]f.UHH H}HuHEHMHHHEuHEH HuHEHMHH H ]f.UHH}HEH@]f.fUHHH}HEH8H}HHEH]fUHH}HuHEHHMH;€]f.UHHH}HEH8(H}H,HEH]fUHH}HEHH]fUHHH}HEH8HE HMHHH]@UHH H}HEHHE HHEHH HM H}HEHEH ]fUHHH}HEHDH]ÐUHH H}uUMH}uUM H ]UHH0H}uUMHEMfUPu@pf8HE؈UH}(HEH}E׊E$HM؈AH0]fDUHH0H}HE0xHEuHEHM EEHMyEHEHM EEH}uU܉&HEH0]UHH0H}HEHHEHM1HMH9UHEHHMHMH9ˆUE$H0]UHHH}HuHEf@@HuHH]f.UHHH}HuHE@HuH}H H5H}QH}Huغ1H}ZH}Hu,H}H5LH}H}Hu1H}H}1ƉλDMH}HuHUD1H} fHf H}^H}1cDMH}HuHUA1H} UHAH}H}1DMH}HuHUADJ1H} HAH}HHHkHHHEH}5$HAH}>HEЉU!HEЉUH} HEЉUHEЉUH}HEЉU:HEЉUH}%HEЉUH}HEЉUH}wH}H5Hp&HxHp1kHp&HxHuH`.fHX1ƉDX`HhHu苍D1Hh HAHheHH.$fH@1VD@HHPHuAD1HP =HAHPH0.eH(1ϷD(0H8HuAD 1H8 ||fHf H8THxxwNH*HhHhH H ggww$HAHEЉUHpHEЉUHEЉUHhwHEЉUHPr_HEЉUH8ZGH5†HHH1WHHHuffH/cH1Ɖ`͵DHHu苍`D`1H \\HAHQH/cH1BDHHuAD1H )XXHAHH/bH1軴DHHuAD1H TTfHf H@HPPONHH@H@HH??OO$HAlHEЉUHHEЉUYHEЉUHvAHEЉUH^)HEЉUHFHoH^HxMHx<"H}.H}HH]H} H}H}^ f.@UHHH}HuH}HuH]f.UHH H}HuHE@H}HEIHMfH}?HMAH}#HMAH ]f.@UHHH}HuH}HuH]f.UHH HHHMH}HE{HEH}HuHEH ]fDUHH}HE]f.DUHH}HE@]f.@UHH}HE@]f.@UHHpHH}fUDMHuMDEHufUfUMLUH}LHuHELU0MDE؋uuDMH}HuHU^H}HEHp]HEUH}H}K f.UHH}HEH]fUHHHHHMHuHMf9H}HEHMH}H5؀ H5ҀHEHHxHEH}Ⱦ tuH}DMH}A HxtHEPH}0p]MH}HupHEPH}0lG]MH}HulH}HuHUHMNH}8H}/H}&H}H}HukH}THEU:HEU%HEUHEUH}H}H}H} HEHĠ]H}6 fDUHH0HILUfDMHufUMDEHuHUMDEfDMfDMDMHE&HEH0]UHHHLK0MLEIL@H8H0H(H8HHHHH H0H(HHHMHHMHHMHEHEHHxH@HEHuH`8HuHH(LEHxHMHHUHEHMH`HEHHHEHEHEHEHEHEHEHEHEHEHuHUHH0HHMH9HH]U fUHH`HILEfMHuU}H}HEH}H5@~1EEE NfEfEuH}cEuH} EHuHUH}u H}E H}E H}MHEU$HEUE H}E H}b HEH`]H} UHHHHHMHuUHMf9H}HEHMH}kH}E_HEH}о0UXMH}HuUH}HuH}Hx HEȉUHExH}HugEEH}wwH}.zHEPH}0pWMH}Hup=H}Hu%H}HEȉUH}HExH}Hu8fEEH}ooH}.HEPH}0hVMH}Huh[H}HuCH}HEȉUH}"H}HudeEH}H} HEHĠ]H} fUHH H}HuH}H}E1ɋU9ˆMEH}H}E1ɋU9ˆM H}H}EM9ˆUE$H ]UHH@H}HuH}H}E M9UH}H}E1ɋU9ˆMvH}H}EM9UKH}H}E1ɋU9ˆM H}H}EM9ˆUӊEӈEۊEۈEEEE$H@]f.fUHH@H}HuH}'H}EM9UH}H}E1ɋU9ˆMvH}H}EM9UKH}H}E1ɋU9ˆM H}H}EM9ˆUӊEӈEۊEۈEEEE$H@]f.fUHH H}HuH}HuEH}HuYEE$H ]UHH H}HuH}HuEH}Hu EE$H ]UHH H}HuH}H}EM9UEH}H}EM9U H}H}EM9ˆUE$H ]UHHHHHMHuHUHMH@HH8H0H}艅,D,A9HEغHH0H HtH}H QHuH}HuHUH@'H}H}H}HEЉU%HEЉUHEЉUH}H}H}H0 H}艅92H5%tH}@H0H} uH}.DMH}Hu1A H}H0HuH}HuHUHMH@H}H}H}H}xHEЉU:HEЉU%HEЉUHEЉUH}nH}eH}\H}S4H0H}艅9H5rHxH0VHh hHpDpH}Hx1A H0 HX DXH`aD`H}Hu1A HPH0HuHHHuHPHHH@HHHPH}H}HxHEЉUUHEЉU@HEЉU+HEЉUHEЉUHHqHPeH}\H}SHxG(H@H0H8H]H} f.DUHH0HILUfDMHuUMDEHuHcUMDEfDMfDMDMHEHEH0]f.UHHaI]UHHT$]UHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]f.fUHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HmHMHcHEHMEGEHME4EHME!EHMEEHMEE]ÐUHH0H}H}/HEH})EEHcH}Hu^HEHUH0]HHU_f.DUHH}HE]fUHHH}HEH8H]fUHH H}HuHUH}HuHU H ]DUHH H}HuHUHEH}HEH=kH5kjH} H}H=lH5k7HEHMHH}HMHAH ]UHH}HE]fUHH0HHuHMH}HHEHEHUHuHUH}HEH0]f.UHH HuHUH}H}HuHU H ]DUHHuHUH}HEHMHHHMHH]ÐUH1H=21'‰U]UH1H=21‰5]UH1H=21Ɖ‰]fDUH]ÐUHHpH}HEHHE5H%1HHMHHxHHMZHEHHHEHEHHHEHEHHHEHEHHHEHEHHHEHEHHHEHEHHHEHEHHHEBHEHHHEHEƀHHp]HEUH}^H}H}lH}H}*H}!H}H}H}H}YHEH5H}膿 fDUHHH}H}KH]DUHHH}H}kH]DUHHH}H}{xH]DUHH01H}HMHHxHHMHMƁƁH}HEHEHHHuWH}HEHEH@pHǀH0]UHHH}H}+xH]DUHHH}H}軏H]DUHHH}H}H]DUHHH}H}H]DUHH H}HEH !1HHHHEHEHH?HEHHHEHH;HEHHIHEHHHEHHHEHHHEHHHEHHHEHxHMWHEH2H ]HEUHEHHrHEHH HEHHnHEHH|HEHHHEHHHEHHHEHHHEHHHEHxHVHEH1H};f.UHH H}HEHEHEH"1H}|}HEHxHHHEHxHyHHQpHEHxHXHHE HEHHQ H}hH ]fUHHH}H}[H]DUHHH}HEHHEHEH H]fUHH0H}HuUHEHHxHHEHRHE@HuHH~HuH}HE[E$HM؈A`E EE$H0]fUHHH}H}!H]DUHH`H}HuHEHEHHHuHHMHUbHEHEH}~=HEHHE HEHHQ E\HE؉UH}UHEH}оHE3uHEHHQhHMHUHxHHΈEEE$H`]H}y fUHHH}H} H]DUHH H}HEHHH5cHUHHxHpHh>HxD@pAH}HpHhDDH}8H5{bH}gg4H}!HEUH}HEUH}5ffHxHH˹e1edSHxHxHHXHXHHHшWW4ddHxM1H} PPPƍD1H}к H}HEHHHHHH@HxHH51aH}H8.HxHpHuHUH8YH}+rHEUH}8H5 aH}H}Hu1H}H5`H}HxHH7176SHxHxHH(H(HHHш''466HxHH}HZiH `H}HuH}Hu9H}H}HxHEUH}HEUHEUHEUHEUH}iH}`H5d_H}H}Hu1fH}HuHHEHHH<H}H$H}H}1HTHxHH5a^H}H^H}HuHxHpHuHUHrH}DH};THEUHEUH}TH}AHEUHEUH}H}H}H} H}H}HxHHд1NHxHxHHHHHHш4HxMHx5H}H ]H}H}e DUHH H}HuHUfMHEH|(HuHUHM('$H ]f.UHHH}HuHEHT(HuHh"$H]f.UHHpHH}HuHUHuHMH}HHEHM H}HuH5[H}HB3H0H}fEfEfEUH}HuHuHUH}H}sH}jH}aH}jHEHp]HEЉU:HEЉU%HEЉUHEЉUH}H}H}H}H}蔰 @UHHPH}H-A3H0H_HMHHuHHMH}HuHU;H}EH}bH}E$HP]HE؉UHE؉UH}/H}PH} DUHHH}HuHUHMHEHHHHQx EdHUHEHHHH@H}H@蠸H}H}ƇuH}l??41EEHEUH}jHEUH}HulH}Hu袱H}Hu薱E=UEE0HEU2E=EEE%=EEH}HuuH}蟰HuHxHpHH0'Hh[H}H0H}HhH`HxHpH`H`//EEHEUHXHxFHhHX(..(EE:HEUHX_WHHHH}H误HHHH}HsHHWHHHH}HEHH#HHHH}H HHHHHHHH((OHHHǀHHMHHHH۾EEHHHH$$OHHHǀHHʽHHHHXEESH}HuHEE=UEEHHHUMHuHHRE-HMPHH 6H}HV?HEV=UnHHHH$HHHH蔼HHHH"HHHǀEE EEHX,Hh HpHx)HhHpHxH}H}H}胲H}uE$H]H}  UHHH}HuH}Hu˫H]f.UHH}uHEMH]fUHHH}HuH}Hu4$H]fDUHHH}HuH}Huk4$H]fDUHHH}HuH}Hu߿H]f.UHHH}HuH}Hu詿H]f.UHH}HEH@]f.fUHH H}HEHyHE4H}1H}HEH}HuHDHEHAH ]UHH H}HEHyHE4H}yH}HEZH}HuH茺HEHAH ]UHH}HEH@]f.fUHHH}HuHEHHH`Qx EHUHEHH`HXH}HXدH}H}~uH}褯WW41EEvHEȉUH}HEȉUcH}Hu褨fEfEUH}PPEuH}臨uH}{uH}XHuH} H}HuH}HuHpHuoHxHpEH}HxHx裻Hp藻H`HppH}ǧH`H}舧H`HH}HH`HH}HuH}RHuH`fDžnUnH}EEH}H}˺H}֦oHEȉUUHEȉU@HEȉU+HEȉUHEȉUHxnHpbH}SH}\H}gH}H}E$Hİ]H}褣 @UHH}HE@]f.DUHHH}fuH}uH]f.UHH HHHMHuHuHEHEH ]f.@UHHH}HuH}Hu軺H]f.UHHH}HuH}Hu腺H]f.UHH H}HEEHHHHHHHMHEVHEHHHpHǾcEHEHH}HHEHǾd˄EOHEH E6H}@$EEHEHH}HE$EE$H ]DUHH`H}HEHHxHHE<HHHEEHEHdHHEHEHEHEǀHHMHEHHHH}HEHxHHHEHEHH4EE HEH E,HEHxHUHH@H}6HEHEHcMH9H}H}HEHEȉEfHEHxHHHQxHMHHHE聸HcHUH)HUHMHcUH96HEȉEH}H}HEHHHuH}MHEHxHOHMHxHHE8HHHMHHHH}HEHH@HEHxHHH@HEH;E-HEHEHEHEHMHlj蘁HEHǾd肁HEHHKHEHHHEHHEE$H`]f.UHHH}H}H]DUHHPH}HEHEHHxHHEHHHEHEHHZt1HEHHHEUH}[1ɨM\1HEHHğHEЉUH}N~1ɨM#HEHxH HH4ENJEǨ-HEHxHHHQxHEH}rH}@HEHxHHHQxHMHHHE4HcHUH)HUH}HEHP]f.DUHH H}HEHHxHHE,1H}H HEHHHu肞H}HEyH ]UHH}HEH@]f.fUHHH}H}H]DUHH0H}HuHEHHpH;HEHE=F0 F0HEH**^YX,ʉMEHcEHMH$HEHHMHHljwHEHHMHHlj諭HE/HEHMHHUHrpHHEDHMH'HEHMHHUHrpHωEnuԉ0HEHHpHHHpH0]@UHHPH}HEHHH5DH}HHH@舻H5{DH}xHHHpHuHUH@H}uH}lHHHH5 DH}H8H5DH} HHHpHuHUH85H}H}HHHH5CHMHH0H(蠺H0H(f'H}褺'EE}LHHHH}[H'UHu菹E}EEHHHH} HUHu>E}FHHHH}"HMHuʹE}EEHHHH}"H9UHu衸E}HHHH}]HMHuʹUE}NEEHHHH}[HUuHEEM)H}H覷EM)HxH艷HuHxHH_HxNH}EHEUHEUH}$H}HEUHEUH}H}HEUH}ܷHEUHEUHx踷H}请gdHHHHp]HFUHp諶tt tEHHHUHhHƹHHHHHh#HhHڶHHHH-HHHH5w?H`HHH\1ҹHHԵEH`R}7HHHUHXH2HHHxHcHHHHHш[HHHHHXDžTlHEUH`蓵KHEUHX{3HHHHHHXHODžTHX.T N?HHHxHIHHHH}HHHH1ɨ)HHHxHַHH4HHHP]H}ؒ  fDUHH0H}HEHQHq9HE`HEHy(H}H}Hu'H}HEP1HEHQH}UjUH}uФHEHQHEHQQH0]UHH0H}HEHQHq9HE`HEHy(H}hH}HuH}HE>P1HEHQH}UjUH}u踤HEHQHEHQQH0]UHH H}HuHEHMHHHEHMHEHH ]UHHpH}HuHEHHEHEHH5d:HsH}HEHuH}GH}HuŒH}HEHE1ɉHuH}HEɟHEHEHMȿHM诶EuHMHHRhHHuHEHxHHE@`HHIhHшEH}$E$Hp]HE؉U%HE؉UH}HE؉UH}臵H}H}衏 UHH0H}HuH}HuHEH}HǺH}HuH}HE蹰HEH0]f.DUHH HHHMHuHuHEHEH ]UHH }uuH}fguH}輮EEH ]f.@UHH}HEH@p]f.@UHH HHHMHuHMHHHEHEH ]fUHHH}HEHHE4HEHH]fUHHH}HEHH肖H]f.fUHHH}uHUHEHHhH}HHE_HEHxH{HxHxHEHUH;JpEHE؉UH}螌HEHH蕟uH}fH}HEHH56H}HpTMH}HUHpH}ZHEHH56H}Hh MH}HUHhH}HuCH}H}EH5)6H}貭H}Hu1|ggfLH55H}hEH}Hu'eeffEd H}=H}4d$EH5l5H}ccH}EHuȉuHE؉UH}ˬHE؉UHE؉UHE؉UH}螬H}蕬HE؉U{HE؉U$HE؉UE H}YH}K=HuH}H}+H}"EH}HĠ]H}H}H}H}胊  UHHH}HuH}HuJH]f.UHH H}HEHyHE4H}IH}HE0H}HuHPHEHAH ]UHHH}uHEuHHE HEHEHxHgHuHHH5B3H ^3HEHHE身HEHHuHE芢H5Q3H}HEHuH} wHuH}HEH53H}җH}bH}诗*HEUHEUH}8H}腗H} HĀ]H}譈 f.UHH0H}HEHEHEHH1ɃM^1HEHH芊HEUH}[1ɨM#HEHxHѬHH4EߊEߨH}UdHEHHo1ɨM#HEHxHgHH4EފEިH}H}]H0]UHH HHHMHuHuHE HEH ]UHH H}HuHEHHE6H}HE蓧HUH}ƹA論AAAH ]@UHHPH}HuHEƀƀƀHHHHE蛖HEHH艖HEƀǀHEHuH} ,HuH}HEȃ Eh1HMERHEHxH谪HHEHEHHH5 EƊEƈENJEǨ9HEH}áHEHHFH}HEHHMH}HHHM豬H}HuH}茦HEHHHEƀHE؉UH}Z;H}w H} EE$HP]H}评 f.DUHHH}H}{EH]DUHHH0HHEHHHHHHH_HHHHHHیHHHHHN0HHMH96HĀ]HHvHx } UHH}HEH]f.fUHHH}uHUHEHHxHHxɧHEHxH;Jp EHxHhH}H]H}HxHHuHUHxHHHuHxHxHxHH5+H}Hp|MH}HUHpH}肣HxHH5+H}Hh0MH}HUHh H}HuhH}$H}EH5N+H}עH}Hu1衡ggfLH5 +H}荢EH}HuLeeffEd H}bH}Yd$EH5*H}ccH}EHu蚃HEЉU/HEЉUH}HEЉUHEЉUHEЉUH}跡H}计HEЉUHEЉU$HEЉUE H}rH}dHuHxHxb,H5q)H}aabb$EH}H}H} H}ΠH}ŠH}E$HĠ]H}; f.UHH H}HEHHxHHE輣HH)HEHHHEHHǎNHEHxHh1ɉH}HZHEHHHu輀H}HE賶H}ZH ]@UHH H}HEHHE#H}cH}Hu̎H}HE艟H ]UHH H}HuHEHuHHE~HEH ]fUHH H}HEHHxHHE|1H}HpHEHHHuH}HEɵH}H ]f.UHHH}HE@`HEHEHH}HEUUHEHHuHET1ɉH}Hu1H}Hu虢HEHHHu脍H}HEAH}8H}HEȉUHEȉUH}H}~HEHHMHHHM)H}HuHEHHHuH}HE讝H}襝HEȉUH}萝 HĀ]H}| UHH H}uHEHE!HEHuHHHEHEHuH褝HEHEH ]@UHH`H}HuHEH5%HMHHUHEHM蝜H}Hu_EH}誜EH5>%H}ZH51%H}JHuHUȹH}qH}QH}H?HEUH}3HEUHEUH}H} H}H5$谛-H}H5$蓛H}H5z$HEHHuHMHQpHHHEUHDEDH`]H}z UHH 1H}HuUH}HuM諚AAAH ]@UHHH}uH}u5<H]f.DUHHH}HuHEHHH}}HEHM1H}uE}HHEHHMHUHuHHuHHEH}HuH}HEƀH}H}HEH}HEHHMHxHHHp1ҹHxHpH}辙HEƀ*HEЉUH}HEЉUH}艙HEHH}H蒝HEHHHu莈H}HhHHEƀpH}HEHHMH`HHHX1H`HX@H}HEЉUH}͘HEHHMHHHP+EH}HP貗HMHHHu談H}HHeHEHHMHHU H׉DHDDH8DH09H0H8踆H}H}_HEЉUH}ڗ H]H}av UHHH}HuHEHMHHEHMUH}HuHE^H}HEHEHEHEH}HE׆HE1HMHUH9шEHEMEHuHUH}WHEHEHH5H}Hx萖HuȺHxTww4H}Ȉv脖v4H}h!HEU:HEUH}B%EHEHHEHEH}jHEHHH5H}HhH`蕕Hu1ҹHh \\H}H`荔HEHHHu蚄H}HPTH}KHEUH}6EH}Hİ]H}H}s  fUHHH}HEHH@H]f.fUHH0H}HuHEHMHHMHMHHHM#HMH9H}cEEEH0]f.UHHH}HEH8HEpxHMHHcRHHH]f.fUHH}HEHE 1E HEfME]DUHHpH}HuHEHHHHRHEEEEEE1E4HEHHHHHH9ˆ~ EEH}EM։ʃ}HxH HHcH}H}HHUMHuHHHxH HHxbH} EEEE%HEUH} = EEEEE}EEEEE؃ETE}HHUMHuHHpH 1HpfnfnfEH}莌1ɨm,fEfEH}.\fEufmmM},H}HuHEUH} EEEEEH}} E/EHuHp}zH}HHUMHxH`HHXH H`HX9Hx HEUHx EEEEEdHEff``HhHHP4HPLHhLtt:}H}HHUMHPH@HH8HH@H82HP0HEUHhIHEUHPEMʉƍDEH}HHˆEH@H0HH(H։H0H(~H@+EEE)HEUH@aHǀE}zH}HHUMH0H HHHkH H}H0wHEUH0_EEEEE}zH}HHUMH HHHHHH8}H HEUH H}HHMUAAT0HHHHHDHH|HPEEEEEHEUH$}zH}HHUMHHHHHHH|HHEUHH}HHMUAAT0HHHHH%HH{H1EEEEHEUH gEփHEffHHHzHpH9:}H}HHUMHHHHHHHzH)0HEUH衊oHEUHWEMʉƍDEH}HHˆEHHHHH։wHHyHEEE)HEUH[HǀHEHHE)}xH}HHUMHHHHHHH$yHHEUH Hp]H}g f++qq&RqUHHH}HEH84kH]fUHH H}HuH}HEH}HL`H}HlvH ]f.UHH H}HuUMH}HuUM'H ]ÐUHHH}H}'H]DUHH0H}uHEMHHEM}M9H=FH5qfHEH8MHτfEfEH0]ÐUHHH}HE8zm$H]f.UHH f}fufEfEfEfEfEu4$H ]UHHH}HuH}HuuH]f.UHH}}BeH]fUHHH}H}fH]DUHHH}HEHHEt1ɉHEH8gH]f.@UHHH}HEHHElt1ɉHEH8gH]f.@UHH0H}HuHUHEH}H`{H}1{fEH}-EMʃ{HXHHXHcHH}1>{fEuHMHHP%sHP LH}ՃLE܃}+H}uܺOHEUH}蜃D6H`ƀHH}H@~EH@HuqH`HHÃH`HHpE H}}E1H}utjH}?\H`ƁǁsH`HHTqH`ƀKH}yH}HuHEH0HH(y1ɉκ H(y$H0$MH}HEUH}H}H5 YyH}%MoH}H5 $yH}L5H}H5g xH}LH}H5 xH}|LoH}H5 {xH}GL5H}H5 FxH}LWH}H5 xH}K5H}H5V wH}KH}H5 wH} dK5H}H5cwH}/Ky1H}dH`ƀ[H}H5 w!H}cH`ƀH}H5)vH}H5 v!H}cH`ƀHuHEHMHHHHQvH`HH_H}~pHEUH}~dH}H5 v!H}bH`ƀHuHEHMHHHHuH`HH<_H},~HEUH}~H}H5fuH}2IHuHEHMHHHHuH`HH^H}}/HEUH}{}#EH}1tfppHxHHjlHNHx}E}.H}uCHHEUHx|pHuHEHhHHHHtH`HH]Hh~|HEUHhf|H0]H}Z -Cs66yUHHH}H}+(H]DUHH}HEx ]DUHHH}HuHEHuHjH]f.UHHH}HEHHpH]f.fUHH}HEHx]fUHH0H}HEHHHEyH=6H5@>YHEHjHMHHEyHcHUEHMHuHHMyH}؉iEH0]DUHHH}HEHHvoH]f.fUHH H}uHUHEHuHUH($H ]fUHH}HE@ ]f.DUHH H}HuHEHHEoH}HEmoHUH}ƹAkfAAAH ]@UHHH}HuHEH5 HMHHpHhH`wHpH`Wv_H}w_B1HhƀƀHpNfHEUH}EwlH5{HEHHPvHpHPuOH}vOB1HhƀƀHpeHEUH}vHpuHh#1HhNHh!H}襥H3wM?1HhLH}hHvLLMMNN$EEHuH}H@OpH}H@OpH}m4HEHH8ܤH}HH}jH}HuHUHMH8葒H}H}uH}|H}4Hi*HEUHEUH}GH}tH}H}HMH(Hω$YiH}HUHMH(Hp Hh H}H}@tHhHHsH}HhHHMHHHHyHh1HH#H}sHhHHJbHhƀ?HEUHEUH}H}xsHEUH}csHhƀ`H}HEHHgH}{HUHMHHpHhH}TH}rHhHH.rH}HhHHxHHHHxHh1HH軐HxZrHhHH`HhƀBHEUHEUH}H} r4HEUHxqHhƀH]H}iP fUHH HHHMHuHuHE`HEH ]UHH@HH}HuUEHuH}HEew}XfEuH}`EE#HEUH}#qH}qHEH@]H}O UHH HHHMHuHuHEk_HEH ]UHH0HHHMHuHMH}HHEgH}Pe=H}gH}HEgH}HElgH}ЉPH}Hu؉^HEH0]@UHH}HEH@]f.fUHH0H}uHE}HEH=7H57s0PH}PUH}HuyuHEUH0]f.fUHH H}@uHEHH9HE)SHMHcQDDME9@@@H ]fDUHH}}9}0E 1}E }VEEEE$H]f.@UHH H}HEHHH;J@@@@HE$HEHH9RRHMHcQ@4@u1ljeEEH ]UHH H}@uHEHH9HEQHMHcQDDME9@@@H ]fDUHH H}EEH}EeM99H}ueM EEEEE$H ]UHHH}HuH}HuH]f.UHHPH}HuH}HuHEH}HHuHEbH}HuHUK\HEH}-mHEHP]HEUH}mH}K UHH H}uHE}HEEHMH;BH=H5=HZXK1HMH9PHcMHHH ]UHH H}uHE}HEEHMH;BH=oH5HJ1HMH9PHcMHHH ]UHH}HE]fDUHH}@@uHEM]f.@UHH0H}uHEMH;JHEH}K]EHMHr9H}"l]1MHUH2~9OH}6"HUH:G%EH}Hu/J0MMUH}\EHMH;B6H}\HcMHHH}HEe\H}HuH\1H}G\H}HEL\HcMHHH}HuH\EHMHBH0]fDUHH0H}uHEMH;JHEH}S[EHMHr9H}j]1MHUH2~9OH} HUH:G%EH}HuH0MMUH}ZEHMH;B6H}ZHcMHHH}HEmZH}HuHZ1H}OZH}HETZHcMHHH}HuH!ZEHMHBH0]fDUHH H}uHE}HEEHMH;BH=H5MHjhGH}[ZHcMHHH ]f.@UHH H}uHE}HEEHMH;BH=H5HFH}3YHcMHHH ]f.@UHHH}HEHH]fUHHH}HEHEKHMHH]f.UH5H]DUHHH}HEHH]fUHH H}HEHHHE ^HEH0HLXH ]HHUjf.@UHH 1H}HuH}HUH}HHJE1DH}HEJH}HuHWHEHxJH ]UHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]f.fUHH}HuHU]f.@UHHH}HuH}HH]ÐUHH H}HuHEHHEZHHMHcQHHH ]f.UHHH}H}DH]f.UHHH}HEHDH]fUHHH}H} H]DUHH H}HEH8HECHEH8xH/HEHHHMH} HEHHH ]fUHHH}H}+H]DUHHH}H}gH]DUHHH}HEHHEh[H=LH5\lCHEHH0[H=}H5$4CH]UHH H}uHE MH}uH}EH ]UHHuH}H}uH]f.DUHH uH}HEH}HEV]HMH ]@UHH}HE]UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HmHMHcHEHMEGEHME4EHME!EHMEEHMEE]ÐUHH H}HuHEHMHHHEH=zH5Ho?HEHMHH}€HEH*NHEHHHH ]DUHHH}H}BH]DUHH H}HEHHHHE%HEHWHEH}MH ]HHUcUHH}HEHH%]fUHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH}uHEMf]UHH}HuUMHEHuH0MHMH ]DUHH}]fDUHH}HE@ ]f.DUHH0H}uHEMHHEM[]M9H=6H50a>HEH83BHcMH}4HfEH0]f.fUHHH}fuH}uH]f.UHH}fuHEfMf]UHH}}A(}z}aEH}ZE9}0}9E 1}E }DEEEE$H]f.fUHf}fuEM9€]f.DUHH }Hu}<.H\0HcMTH]fUHH}HE€]f.DUHH}HE€]f.DUHH HHHMHuUHMHUHHEHEH ]UHH H}HEHHEhR1ЃMH}TRȃEE$H ]UHHH}H}kH]DUHHH}H}H]DUHH}HE?]UHH}HE?]f.UHHH}HEHH]fUHHH}HEHE<HMHH]f.UHU9]DUHHH}HEHH]fUHH H}HEHHHE)OHEH0HvHH ]HHU[f.@UHH 1H}HuH}HUH}HHU;E1DH}HE6;H}HuHGHEH;H ]UHH}HuHU]f.@UHHH}HuH}:H]ÐUHH H}HuHEHHE:HMHcQHHH ]f.UHHH}H}7H]f.UHHH}HEH7H]fUHH@}EH}$fEH]f.UHHPHHMILEHuUHuH}H}HEHMHu}H}u\EEEEH} EHMHHEHEHuH}HEHP]f.DUHHH}HEH89H]fUHH}uEH}T1M;MEHEHHHM8ˆUEEEE]f.UHHH}HEH849H]fUHHH}HEH5H]fUHH H}HEHHHEWYHEHHy-HEHQHHωULEUH}u5H ]@UHH H}HEH}HEèHEHH}TBEH ]fUHH}uHEM ]UHH}}@r4H]fUHH H}uHEMHHEMOKM9H=FH5xq4HEH87HcMH ]fUHH0H}HuHEH}HEJH}HEJH}HEJH}؉3H}1BHMHH0]fUHH H}HEHHHEJHEH0HDH ]HHUVf.@UHH 1H}HuH}HUH}HH6E1DH}HE6H}HuH2DHEH6H ]UHH}HuHU]f.@UHHH}HuH}6H]ÐUHH H}HuHEHHEd6HMHcQHHH ]f.UHHH}H}2H]f.UHHH}HEH2H]fUHH H}HEHHHEHHEH0HAH ]HHUNUf.@UHH 1H}HuH}HUH}HH4E1DH}HEl4H}HuHAHEH>4H ]UHH}HuHU]f.@UHHH}HuH}4H]ÐUHH H}HuHEHHE3HMHcQHHH ]f.UHHH}H})1H]f.UHHH}HEH 1H]fUHHH}HEHE94HMHH]f.UH0]DUHHH}HEHE_4HMHH]f.UH0]DUHH H}HEHHHEyFHEH0HAH ]HHU>Sf.@UHH 1H}HuH}HUH}HH3E1DH}HE3H}HuH:AHEHx3H ]UHH}HuHU]f.@UHHH}HuH}Q3H]ÐUHH H}HuHEHHE*3HMHcQHHH ]f.UHHH}H}HH/H]f.UHHH}HEH.H]fUHHH}H}FH]DUHH H}HEH8HEHEHHH@F 1HM HEHHHMHEH ]UHHPH}HuHuH}H}?H}Hu/H}u?EE;E|H}Hu.H}DEE(H}?:HE؉UH}@H}Hu>ẼExHEH}HEHEHP]H}+ f.UHH0H}uHEMHr9HE 1EH}EUH}uh>H}SM6HEHHM0HMH9HEHQQH}+M;EH=H5e,H0]ÐUHHH}HuH}Hug-H]f.UHHPH}HuHEHQHDAAD9AADMHHEdL E1HMH HMUEH}؉mEHEHQUHEHQUċEċM؉MЋUH}ȉ<H}1ɉHH}H?HE8/HuH0"1HMH HUH:HM/HMHHEHQQHP]UHHUH}uHEMH8;OHEH=fH5*HEHHMH8ZNEHc}UU؋u.HEHEHEH};`*,HEЉUH}OH}HE).OHEHMH}(HH=H5D)HEHMH=H5)HEHQHMQH81҉-HEHEHEHMH91҉g-HEHEHEH}1ɉU-HEHEHEE1EGHEH;E/HEHHHMHMHHHUH H]HEH;EEHEHHHMHMHHHUHHxHHxHAHEHMHUHuH)HHHHMHEHMH)HHHEHEHEЉU\MHEHQHMq ։qHH;MH=H5/'HEHH>K}E#1HEH0H"9HEHHR+HEHMHH9R+HH=LH5/'HEHQHq9H=H5X&HEHHp*HpH9H=H5&HEHHh*HhH9H=H5t&HEHQ;UH=H5>&HĠ]H}|$ HH`]I f.UHHH}HEHHI4$H]UHHH}1Nju)H]UHH}HEHH]@UHH uH}HUEEMH}Hu%H ]f.fUHHH}H}=H]fUH1H}uHM#U;UHME$}EHE;MˆUEEE$]f.fUHHH}H}<H]fUHH}HE]fUHHPH}HuHuH}H} 5H}HuZ%H}u5EE;E|H}Hu$%H}$;EEă(H}4:HE؉UH}@H}Hu4ẼExHEH}HEHEHP]H}! f.UHH0H}uHEMHr9HE 1EH}EUH}u4H}QC6HEHHM&HMH9HEHQQH})C;EH=H5 "H0]ÐUHH@H}HuHEHQHDAAD9AADMHHEB E1HMU@u@EH}EHEHQUHEHQŰE̋MM؋UH}Љ2H} 1ɉ΋HEH8MD%Mȉ1HMHMH9E!%UĉHEHQQH@]UHHUH}uHEMH8;OHEH=H5%!HEHHMH8DEHc}UU؋u$HEHEHEH}; ,HEЉUH}EH}HE3$EHEHBDH}>H=H5P HEHDH="H5 HEHQHMQH81҉#HEHEHEHMH91҉q#HEHEHEH}1ɉ_#HEHEHEE1EEHEH;E-HEHHHMHMHHHU10[HEH;ECHEHHHMHMHHHUHHxF0Hx0AHEHMHUHuH)HHHH2DHEHMH)HHHEHEHEЉUCHEHQHMq ։qHH;MH=UH5?HEHHz4K}E#1HEH0H.HEHH`!HEHMHH9`!HH=H5HEHQHq9H=H5hHEHHp HpH9H=iH5(HEHHh HhH9H=FH5LHEHQ;UH=(H5HĠ]H} HH`? f.DUHHH}HEHH@4$H]UHHH}1NjuH]UHH}HEHH]@UHH uH}HUEEMH ]f.DUHH}HE]fUHHH}HEHHEf,1ɉHEH8H]f.@UHHH}HEHHE&,1ɉHEH8H]f.@UHH H}HEHHEL;\HEHQvHMH-1HEHQH}UUH}u+H}:H= H5{H ]UHHH}HEHHE+1ɉHEH8DH]f.@UHHH}HEHHE+1ɉHEH8H]f.@UHH H}HEHHEN:\HEHQHMH-1HEHQH}UDUH}u*H}9H=H5;H ]UHH@H}HuH}HEH}H9H}ȉHMHMH}HE~9HEH}e9HEHEH;E+HEHEH}HEH0HEHHEHEH@]UHH}HEH@]f.fUHH H}HEH81ɉ0HEHEH ]HHUu;DUHH H}HEH81ɉ/HEHEH ]HHU5;DUHHH}HuH}HuH]f.UHHH}HuH}o/H]ÐUHHH}HEH0.H]fUHHH}HExHEHEHxHEHxH=H5)C%HEHMHAH]DUHH H}HuHEHHE.HMHcQHHH ]f.UHH@H}HuH}HEH}H6H}ȉHMHMH}HE6HEH}6HEHEH;E*HEHEH}HEЋ0>HEHHEHEH@]fUHH}HEH@]f.fUHH H}HEH81ɉ-HEHEH ]HHU9DUHH H}HEH81ɉp-HEHEH ]HHU8DUHHH}HuH}--H]ÐUHHH}HEH,H]fUHH H}HuHEHHE,HMHcQHHH ]f.UHH H}HuHEH}HE/H}H3H}Hu%H}THEH ]UHH}HE]fUHHH}HuH}HuCH]f.UHHH}HuH}HuwH]f.UHHH}HuHEHMH HHMHH]UHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH H}HuHEH}HE/H}H3H}Hu$H}-SHEH ]UHH}HE]fUHHH}HuH}HuCH]f.UHHH}HuH}HuH]f.UHHH}HuHEHMH HHMHH]UHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH0H}HuH}HuHEH}HǺ3H}Hu H}HEIHEH0]f.DUHH H}HuUH}HuE$eH ]f.DUHH0H}HuHEH}HEH}HH}HutH}HEH0]UHH0H}HuUHEH}HEH}HE 1HMHEHMHHEHAH0]f.DUHH}HE]fUHHH}HuH}HucH]f.UHH H}HuHEHuHHEHEHHMHHHRH ]fDUHH}HuHEHMH HHMHIHHHEHHEH@]ÐUHHH}HuH}HuCH]f.UHHH}HuH}HusH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}HEHHE.1ɉHEH8H]f.@UHHH}HEHHE1ɉHEH8H]f.@UHH H}HEHHEJ.\HEHQ\HMH-1HEHQH}UUH}u[H}-H=H5 H ]UHHH}HEHH14$H]UHHH}1NjuH]UHHUH}uHEMH8;OHEH=H59 HEHHMH8z0EHc}UU؋u%HEHEHEH}; ,HEЉUH}1H}HE1HEH/H}H*H=öH5d HEH/H=ҶH53 HEHQHMQH81҉$HEHEHEHMH91҉HEHEHEH}1ɉHEHEHEE1EEHEH;E-HEHHHMHMHHHU10[HEH;ECHEHHHMHMHHHUHHx0Hx0AHEHMHUHuH)HHHH/HEHMH)HHHEHEHEЉU/HEHQHMq ։qHH;MH=H5S HEHH* K}E#1HEH0HJHEHH HEHMHH9 HH=pH5S HEHQHq9H=?H5| HEHHpe HpH9H=H5<HEHHh HhH9H=H5HEHQ;UH=سH5ƲbHĠ]H} HH`+ f.DUHH uH}HUEEM?H ]f.DUHH}HE]fUHH@H}HuHEHQHDAAD9AADMHHE' Ed1MEH}(EHEHQUHEHQUԋEԋMMUH}؉}1HMH9 H}HE"H}HFHEHQQH@]UHH}HE]fUHHH}HEHHk*4$H]UHHUH}uHEMH8;OHEH=H5UHEHHMH8)EHc}UU؋uHEHEHEH};,HEЉUH}$+H}HE++"HEHr)H}#H=CH5HEH2)H=RH5OHEHQHMQH81҉HEHEHEHMH91҉HEHEHEH}1ɉHEHEHEE1ELHEH;E4HEHHHMHMHHHUHH_HEH;EGHEHHHMHMHHHUHHxOHxHpAHEHMHUHuH)HHHHW)HEHMH)HHHEHEHEЉU(HEHQHMq ։qHH;MH=zH5ȭdHEHHK}E#1HEH0HHEHHHEHMHH9HH=H5,HEHQHq9H=H5HEHHp HpH9H=H5MHEHHhHhH9H=kH5q HEHQ;UH=MH5;HĠ]H} HH`$ @UHHH}HuH}HuH]f.UHH uH}HUEEMH ]f.DUHHH}1NjuH]UH5]DUHH}HuHEHMH HHMQPHMQ P ]UHHH}HuHEHQHDAAD9AADMHHE  EHuH}1MEH}ЉEHEHQUHEHQUEMЉMȋUH}]H}HMH91҉HEHEH}HuaH}HEژ9HEUH}Ř=1HMHUH:HM2HHuHEHQQHĀ]H} UHHH}HuH}HuH]f.UHH}HuHEHMH HHMQPHMQ P ]UHHH}HEHEuHMHH]f.UHH H}HEHHE(\HEHQ"HMH-1HEHQH}UUH}u H}H=H5o H ]UHH@H}HuHEHQHDAAD9AADMHHE E1HMU@u@EH}=EHEHQUHEHQŰE̋MM؋UH}Љ H};1ɉ΋HEH8MzMȉ1HMHMH9EWUĉHEHQQH@]UHHH}HEHHE> 1ɉHEH8H]f.@UHH}HEH@]f.fUHH0H}uHEMH;JHEH} EHMHr9H}>]1MHUH2~9OH}HUH:G%EH}Hu0MMUH}I EHMH;B6H} HcMHHH}HE H}HuH 1H} H}HE HcMHHH}HuH EHMHBH0]fDUHH}HuHEHE; HEHEHEHEHE]UHH 1H}HuHUHMHUHuH)HHHω! H ]UHH 1H}HuHUHMHUHuH)HHHωH ]UHH 1H}HuHUHMHUHuH)HHHωH ]UHHH}HEHHE~ 1ɉHEH8H]f.@UHHH}HEHHE 1ɉHEH8NH]ÐUHH}HE]f.UHH}HE8€]f.DUHH}HE]UHH0HH}uMIIH}HEHUXHmHMHcHH}H5l?H}H5GW*H}H5gBH}H5)(HEH0]ff.fUHHH5ՠHEH}HHEH}HuEH}E!EHEUH}H}1x|H}u> EH}ؾ0?|H}uغ ENH5HEHHEH}HuEH} E!EHEUH}H5ŸHEHHEH}HuZEH}E!EHEUH}sH5SHEHHE'H}HuH}1!EHEUH}EEHĐ]H} f.DUHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]f.fUHH0H}HuHE1ɉHHEHmP0HHUHHHuHjHEH HHEH0HHEH@HHE@PH0]HEUHEHwH} UHHH}HuH}HuCH]f.UHH0H}HEH O0HHHH HHEHEHEH HEHHQ HEH1ɉHQHEH@H`HEH0HNHEH H H} H}HEUH=BW0 HEUHEUH}H}H5H}H}H@ H}HuHU HMH}Hu HUH}Hu H}sH}jH}aH}XH=qV0Hu\#H@HUHpHHHHH5V0H}HUHHMHPHH H}HpyDžlHEU:HEU%HEUHEUH}`H}WH}NH}EHEU]HEUHEUH}Hp0DžlH}l H}HUHXHHHhHPH@HHHXLHEUHX4HHH]H}  f.fUHHPHHHMHuHMHHH}HHEHM6sH} HEHHHuH}HEHEHHEfEH}u6HMHHH5HEHEHH}Hb HEHP]UHHH}HEHHEZHMH9€H]f.@UHH H}HuHEHuHHEVHEH ]fUHH@H}HuH}HuHEH}HHEH}HuTHEH}HEH@]HEUH}vH}  f.UHH`HH}HuEH5q2HMH}HHEHMHH}Hu*H}HEHHEH}Hu7H}HuH}H}EEVHHE؉UH}FHE؉UHE؉UH}H}uH}lH}^HEH`]H} fUHH@HH}HuEH}HE]fEfEfEuH}H5^H}EE#HEUH}H}HEH@]H}9 fUHH`HH}HuH5o2HMH}HHE"fEfEfEUH}HuIHH}Hu6^fEfEfEUH}HuHrHuH}H}H}H}H}HEH`]HEU:HEU%HEUHEUH}vH}mH}dH}[H} UHH@HH}fUHuEHuH}HE$fMfMuH}]EE#HE؉UH}H}HEH@]H}d @UHHpHH}HuEH5m2HMH}HHE^fEfEfEUH}HuuHHuH}bH}@H}7H}EExH5H}H}Hu*H}HE?HEȉUHEȉUH}H}6HEȉUH}!EE H}HEHp]H} UHHpHH}HuEH5l2HMH}HHEfEfEfEUH}Hu%HHuH}H}H}H}EExH5mH}H}HuH}HE?HEȉUHEȉUH}vH}m6HEȉUH}X!EE H}ffEfEfEUH}Hu HHuH}H}H}H}H}H}H}HEHĀ]HEUdHEUOHEU:HEU%HEUHEUH}QH}HH}?H}6H}-H}$H} fUHHHH}HuHMHUؾH}HHEHMf~f~fEUH}HuHpH}HuH}H}|EHEH5GH}Hp-H}Hu H}HUHMHp(HuH}H}H}H}EEuHEȉUHEȉUH}H}sHEȉU^HEȉU%HEȉUHEȉUH}aH}XH}yH}kH}bHEHĐ]H}LH} UHH`HH}HuH5vf2HMH}HHEEOfEfEfEUH}HuH΃HuH}H}EE/!HEȉU1HEȉUH}H}H}zHEH`]H}gH} f.fUHH`HH}HuH5e2HMH}HHEE_fEfEfEUH}HuHHuH}H}EE/!HEȉU1HEȉUH}H}H}HEH`]H}wH}  f.fUHHH}HuH}HEH}HHUEH}Hu*1}%HEHHHHHH}0HEUH}HpHpM}YuH}XH}HuDH}>EHEU6HEUH}!H}QE؃EH}qdHuH}HEHhHHUH}HhXH}H}HĠ]HEUH}~H}oH}4 @UHH HHHMHuHMH}HHE覓H}H誓HEH ]UHH}HuHEHHMH;€]f.UHHH}HEH8DH]fUHHPH}HuHEH8HEzH}HEHuHUH}gCHEUH}HMHr Ήr HEHEU{pH}HEHuHUH}CHEUH}HMHr Ήr HE8HEU~ HP]H}x HHU\ f.UHH}HEHHH]DUHHH}H}苂H]DUHHpH}HuHUHEHHuHUHHEH}H5}E1EDE;HEHHuHE EH5f}H}EEEEEE H}Ev[HuHMHHEHMH}HuH}9HEЉUE H}dHEЉUH}OHp]H} fUHHH}H}H]DUHHH}HuHUMHuHUHEHH`HXHPH}H`HXHPH}HuH}eH}\}H}LH}MHLH;EFEEHEUHEUH}H}HEUH}HpHu1}G(HpHHHHHGG$EHpHEUHxH8H}H8}sH}1HMH0Ho,,lHlH0AEHEUHp=Hx^EEEEH}WH}IH}5E$H]H}H} UHHH}H}KH]DUHHH}HEHH]fUHHH}HEHH]fUHH HHHMHuHMH}HHE趓H}H躓HEH ]UHH}HuHEHHMH;€]f.UHHH}HEH8 H]fUHH`H}HuHEH8HE6zH}@HEHuHUH}%CHEUH}aHMHr Ήr HEgHEU>HUHuH}H}HEHEHEFHEUH}HuH}HEj>HEUHEHMHH`]H} HHU fUHH}HEHHH]DUHHH}H}k}H]DUHHPH}HuHUH}HuHEHMH}HHuHHM1H}HuHUH}<HP]HEЉUH}&H} DUHHHH}HuHUHuHUHMH}HHEHuHUHMH}HuH}HMHuHUHuH}H}H}H}uHEHĀ]HEU%HEUHEUH}FH}=H}.H} UHHH}H}{H]DUHHH}H}|H]DUHH`H}HuHUH}HEH}H HEHEH}ȾHEϟUHuH}HEHEH}Hu+HEHHEH}HEHHuHUH}H}H`]HEЉUHEЉUH}H}H} @UHHH}HuH}HuaH]f.UHHPH}HuHUHuHUH}{ HEHEH}ȾHE袞UHuH}HEHEH}HuHEHHEH}nHEHH}HP]HEЉUHEЉUH}H}H} f.UHHH}HuH}Hu H]f.UHHPHH}HuEHHH5sH}SH}@HuHUHHHHEH} H}.H52sH}H} HuHUHHHHEH}H}H5rH}H}pHuHUHKHHHxH}@H}aH5rHpH`HpH`HHHHXH`HpH5*rHPH@ HPH@H]HHH8H@OHPmH5qH0*H H0H HHHHH H0H5fqHH1HHHlHxHxHH^H|H5qH9HHHHHpHpHHHH5pHH1HHH{HhHhHHmHH5IpHHH5CpHHHHH`H`HHHH5oHH1HHHHXHXHxHzHH5oHpUH` ?HpH`HHPHPHXH`HpH5%oHPH@1HPH@HHHHHH8H@HPH5nH0dH HH0H HH@H@HH H0-H5anHHHHHH8H8HHHH5nHpHTHHH)H0H0HHH9H5mHH1HHHH(H(HHHH5>mHHiHHH8H H HH*HHH5lHHHHHHHHxHHH5lHpH5lH`IHpH`HBHHHXH`4HpRH5)lHPH5-lH@HPH@HHHH8H@HPH5kH0H5kH QH0H HJHHHH <H0ZH5qkHH5pkHHHHHHHHHH5kHH5 kHYHHHRHHHHDHbH5jHH5\jHHHHHHHHHH5GjHH1HHH_HHHHQHoH5iH,HHHHHHHxHHH5iHpH`HpH`HkHHHXH`]Hp{H5iHP8H5 iH@HPH@HHHH8H@HPH5hH0H5hH zH0H HsHHHH eH0H5khH@H5ihHHHHHHHHHH5 hHH5=HHHH{HHHHmHH5gHHH1/HHHHHHHHH5JgHH1HHH荼HHHHHH5fHZH1AHHHHHHxHH&H5fHpH5fH`HpH`H蚻HHHXH`HpH5+fHPgH@1NHPH@H#HHH8H@HP3H5eH0H 1H0H H謺HHHH H0H5qeHyH]HHH2HxHxHH$HBH5eHH1HHH軹HpHpHHHH5dHH5Q9HFHHH?HhHhHH1HOH5HdH HHHHŸH`H`HHHH5cHHvHHHKHXHXHxH=H[H5zcHpH`1HpH`HԷHPHPHXH`HpH5cHPH5 cH@_HPH@HXHHHHH8H@JHPhH5bH0%H56H H0H HܶH@H@HH H0H5@bHHHHHbH8H8HHTHrH5aH/H1HHHH0H0HHHH5maHH1HHHtH(H(HHfHH5aHAH(#+HHHH H HHH H5`HH1HHH胴HHHxHuHH52`HpPH54H`HpH`HHHHXH`HpH5_HPH53H@HPH@H苳HHH8H@}HPH5^_H0XH5!3H H0H HHHHH H0H5^HH52HHHH蓲HHHHHH5^H`HDHHHHHHH H)H5#^HHHHH蟱HHHHHH5]HlH1SHHH(HHHHH8H5Z]HH1ܿHHH豰HHHxH裿HH5\Hp~H`hHpH`H7HHHXH`)HpGH5\HPH@HPH@H软HHH8H@课HPH51\H0H 1wH0H HFHHHH 8H0VH5[HHHHḪHHHH辽HH5j[HH}HHHRHHHHDHbH5[HHHHHحHHHHʼHH5ZHH1茼HHHaHHHHSHqH5?ZH.H1HHHHHHxHܻHH5YHpH`衻HpH`HpHHHXH`bHpH5nYHP=H@x'HPH@HHHH8H@HPH5 YH0H5YH 聺H0H HzHHHH lH0H5XHGH1HHHHxHxHHHH5?XHH59XH苹HHH脪HpHpHHvHH5WHQHHHh虱HHhHHHH`H`HH߸HH5[WHHHHXHHXHHHVHPHPHxHHHfH5VHp#HP HHHkH`HHHpH`H迨H@H@HHH`豷HpH5TVH@H HH8ԯH0H8H@H0H(H0H0HH0H@8H5UHH HH(=HH(RHHH葧H H HH胶HH5PUH^H HH覮HH軿HHHHHHHH H5THHHHHH$HHHcHHHHUHsH5STH0H`AHljΉʋH5(HpHrHHpH豥HHHXHp裴HH5SHP~H0HHƬH@H۽HPH@HHHH(H@ HP*H50SH H HH/HHDH HH胤HHHHuH 蓾H5RHPHHH蘫HH譼HHHHHHH޲HH5%RH蹽HHHHHHHHUHHHHGHeH5QH"H5QHp%HHp肻HHHHHHhH賱HѼH5/QH`莼HP xH`HPHGHHHHHP9H`WH5PH@H01H@H0HСHHH(H0°H@H5sPH 蝻H1脰H HHYHHHHKH iH5PH&H HHHߠHHHHѯHH5OH謺H1蓯HHHhHxHxHHZHxH5SOH5H5HHHHHpHpHHޮHH5NH蹹H1覮HHHuHhHhHHgH腹H5NHBHp1)HHpHH`H`HhHpHH5,NH`˸HP1貭H`HPH臞HXHXHHHPyH`藸H5MH@TH5H0H@H0H HPHPH(H0H@H5cMH طH¬H HH葝HHHHHH胬H 衷H5LH^H1KHHHH@H@HH H*H5LHH ѫHHH蠜H8H8HH蒫H谶H5&LHmHWHHH&H0H0HHH6H5KHH1HHH诛H(H(HH衪H迵H5WKH|Hp1iHHpH8H H HhHp*HHH5JH`HPH`HPH辚HHHHHP谩H`δH5JH@苴H01rH@H0HGHHH(H09H@WH5$JH H1H HHЙHHHH¨H H5IH蝳H1脨HHHYHHHHKHiH5ZIH&HHHHHڧHHHǘHHHH蹧HH˲H5HH舲HrHHHAHHHH3HQH5tHHHHHHǗHHHH蹦HױH5HHx蔱Hh~HxHhHMHHH`Hh?Hx]H5GHXHHHXHHHӖHHH@HHťHXH5DGH8蠰H5iH(^H8H(HWHHH H(IH8gH5FH$H5HHHHەHHHHͤHH5mFH訯H5qHfHHH_HHHHQHoH5FH,HHHHHHHHףHEEwfHE؉UvHE؉UHE؉UH}萣H}豮LHE؉UHE؉UH}fH}臮"HE؉UHE؉UH}<H}]HE؉UHE؉UH`Hp-HE؉UHE؉UH@ߢHPHE؉UHE؉UH 询H0ͭhHE؉UHE؉UHH蝭8HE؉UHE؉UHOHmHE؉UHE؉UHH=HE؉UHE؉UHH HE؉UHE؉UH迡HݬxHE؉UHE؉UH`菡Hp譬HHE؉UHE؉UH@_HP}HE؉UHE؉UH /H0MHE؉UHE؉UHHHE؉UHE؉UHϠHHE؉UHE؉UH蟠H轫XHE؉UHE؉UHoH荫(HE؉UHE؉UH?H]HE؉UHE؉UH`Hp-HE؉UHE؉UH@ߟHPHE؉UHE؉UH 诟H0ͪhHE؉UHE؉UHH蝪8HE؉UHE؉UHOHmHE؉UHE؉UHH=HE؉UHE؉UHH HE؉UHE؉UH连HݩxHE؉UHE؉UH`菞Hp譩HHE؉UHE؉UH@_HP}HE؉UHE؉UH /H0MHE؉UHE؉UHHHE؉UHE؉UHϝHHE؉UHE؉UH蟝H轨XHE؉UHE؉UHoH荨(HE؉UHE؉UH?H]HE؉UHE؉UH`Hp-HE؉UHE؉UH@ߜHPHE؉UHE؉UH 诜H0ͧhHE؉UHE؉UHH蝧8HE؉UHE؉UHOHmHE؉UHE؉UHH= HE؉UHE؉UHH HE؉UHE؉UH进Hݦx HE؉UHE؉UH`菛Hp警H HE؉UHE؉UH@_HP} HE؉UHE؉UH /H0M HE؉UHE؉UHH HE؉UHE؉UHϚH HE؉UHE؉UH蟚H轥X HE؉UHE؉UHoH荥( HE؉UHE؉UH?H] HE؉UHE؉UH`Hp- HE؉UHE؉UH@ߙHP HE؉UHE؉UH 诙H0ͤh HE؉UHE؉UHH蝤8 HE؉UHE؉UHOHm HE؉UHE؉UHH= HE؉UHE؉UHH HE؉UHE؉UH还Hݣx HE؉UHE؉UH`菘Hp譣H HE؉UHE؉UH@_HP} HE؉UHE؉UH /H0M HE؉UHE؉UHH HE؉UHE؉UHϗH HE؉UHE؉UH蟗H轢X HE؉UHE؉UHoH荢( HE؉UHE؉UH?H]HE؉UHE؉UH`Hp-HE؉UHE؉UH@ߖHPHE؉UHE؉UH 诖H0͡hHE؉UHE؉UHH蝡8HE؉UHE؉UHOHmHE؉UHE؉UHH=HE؉UHE؉UHH HE؉UHE؉UH`迕HpݠxHE؉UHE؉UH0菕H@譠HHE؉UHE؉UH_H}HE؉UHE؉UH/HMHE؉UHE؉UHHHE؉UHE؉UHpϔHHE؉UHE؉UH@蟔HP轟XHE؉UHE؉UHoH 荟(HE؉UHE؉UH?H]HE؉UHE؉UHH-HE؉UHE؉UHߓHHE؉UHE؉UHP诓H`͞hHE؉UHE؉UH0H@蝞8HE؉UHE؉UHOH mHE؉UHE؉UHH=HE؉UHE؉UHH HE؉UHE؉UH迒HݝxHE؉UHE؉UH菒H譝HHE؉UHE؉UHp_H}HE؉UHE؉UHP/H`MHE؉UHE؉UH0H@HE؉UHE؉UHϑH HE؉UHE؉UH蟑H轜XHE؉UHE؉UHoH荜(HE؉UHE؉UH?H]HE؉UHE؉UHH-HE؉UHE؉UHpߐHHE؉UHE؉UHP诐H`͛hHE؉UHE؉UH0H@蝛8HE؉UHE؉UHOH mHE؉UHE؉UHH=HE؉UHE؉UHHHHE؉UHE؉UH賏HњlHE؉UHE؉UH胏H衚<HE؉UHE؉UHhSHxq HE؉UHE؉UHH#HXAHE؉UHE؉UH(H8HE؉UHE؉UHÎH|HE؉UHE؉UH蓎H豙LHE؉UHE؉UHcH聙H@HHP]H$H}w fUHH`H}HuHUHEHHE~HEH8踚HEHEH8~HEHEEH}ZHEHEHEHHuHwHEHEEH} HEEH}HEH}JH}HEHHPw,HuHEH H(HuH}HE 5HEH8HuHUHMDEAE芊HEHuH}ѦHEH`]UHH H}uUMDEH}uUMDEA+H ]f.UHH0H}HuH}HuHEH}Hh-uHUH}-H0]fUHHH}H}k.H]DUHHH}H}k.H]DUHHH}H}K5H]DUHHH}HuHEH8Hu螘HH]f.UHH@HILEHuHUHMHMH HuH}HHEEHEH}HEH HEHEHEHEH}H!HEH@]UHH@HH}HuHUEHuH}HE$HuH}qEE#HE؉UH}H}HEH@]H}lt f.fUHH H}HuHEHHEVH}HE賔HUH}ƹA˃AAAH ]@UHH@HILEHuHHHHH苔\zfEHu袃H5+H蕃H582H}H訐zfffEUH}Hu蹙HO+H}Hu覙yfffEUH}HunH}HuHaH}HuHHH} H}H}H}H}H5*H}HH}HuHH}输HEHH;HuHEuH}Hu3uHhHu^1}(HhHHHHHDždHEUOHEU:HEU%HEUHEUH}ӒH}ʒH}H}踒H}诒HEUHEUH}莒HEUkƅcHpDHHHK}DžduHEUHy.ƅcDžd)HEUHӑErc H褑d)Hp{EEHh dHh)H5'H@HHH@\vH5'H0ȐH8H0H(ƉGH G(D HPHHH8IHPLHHXHHHOHPH8H0+HHquH@H5&HHHXDždHXҏHEU[HEUCHEU+HEUHEUHP:H8.H0rHHtH@ZCHEUHXB+H}H}+H}"HH@]H}H}H}H}m f.fUHH}HEHx]fUHH@HH}HuHUEHuH}HE}HuH}}EE#HE؉UH}ZH}LHEH@]H}l UHH H}HuHEHHuHHEexHEH ]f.DUHH HHHMHuHMH}HHEvFH}HzFHEH ]UHH}HuHEHHMH;€]f.UHHH}HEH8wH]fUHH}HEHHH]DUHHH}H}%H]DUHHH}HuH}Hu%H]f.UHHH}H}߉H]DUHH@H}HuH}HuHEH}HHE{H}Hu{HEH}而HEH@]HEUH}fH}j f.UHHH}HuH}Hu%H]f.UHHHH}HuEHuHPHHHHH@.qH5"H}袋H}HuH}ƉHEUsHEHMHH`]H}ge HHUK fUHHHH}HuHuH 1LEH}LHuHHUHE@kf~f~fEUH}HuQHH}Hu>H}H}H5H}ӅH}]}}kfzfzfEuH}tH}HuNtH}HuH~H0cH(j~H5JHWmHH@DžLH@)~HEU[HEUCHEU+HEUHEUH8H H}H0cH(}:HEUH@}"H};H}}HH@]H}H}`}H}[ DUHHHH}HuHuH 1HUH}HHuHHExUbfEfEfEUH}HuHH}HubfEfEfEUH}Hu趁HlH}Hu裁H}|H}x|H}o|H}f|H}HuYH5)H}|HUHMH}HuH}!|H}|H}|HEHĀ]HEU:HEU%HEUHEUH}{H}{H}{H}{.HEUHEUH}{H}{H}{H}Z DUHHpHH}HuEH51HMH}HHEw`fEfEfEUH}Hu%HHuH}H}zH}zH}bEExH5H}zH}HuiH}HEz?HEȉUHEȉUH}vzH}mz6HEȉUH}Xz!EE H}H}Huw5H}HEvH ]UHHH}HuH}Hu0H]f.UHHPH}HuHUHEHHHE5HEH8AHEHEH8PHEEH}[HEHHuH-4$EHMHMEH}DQHE H}8QHEHEHEHEH8HuHUHMDEAEAHEHuH}Z]HEHP]UHHH}H}H]DUHH H}HuHEHMHH}HEEHMAHHzHEHHyQ HEH8 /H ]fUHH H}HuHEH}HE/H}HH}Hub3H}}HEH ]UHH}HE]fUHHH}HuH}Hu,H]f.UHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]fUHHH}HEHHHEP H};2H]DUHHH}HuH}HuWQ$H]UHH`H}HuHUHMADEHEHMDMA0HEHE.HEHEHHuHQHEH HuH@mHEȉUH}PQHMHHHEKUQ{HEȉU,QH}QHuH}HE-Q<HEȉUP HEH`]H}) HHUN DUHH H}HEHE=HEHEHHy9HEHHIHuHFMHMHAHEHxHEHHJ-HEHHQA HEH85=HEHMHHH,H ]fUHu,]DUHH01E1H}HuHUH}HHII HUL<HEHEHMHHEAH}؉,HMHy6H}XLHuHzHMHAHEHxHEHP, HEH@HEHx6H} LHuH)HMHAHEHxHEH+ HEH@HEH0]fUHH}HuHEHHHUH H]f.UHH}uHE}HEHEHHHHEHHH]f.UHH}HEHH%]fUHH H}HExHE*HEH8)HEH8p)H ]HHUKfDUHH0H}HuH}IHEH}LH}Hu;HEH}+H}HEHH& HEHE HEHEH0]f.UHH H}HuHEHEHEH}JHEHHuHu&HEHEH}IHE H}IHEHEH ]ÐUHH}HE]fUHHH}HuH}HuH]f.UHH0H}HuHEHuHHE\HEHH}HE&H}HCHEHH}HE&H}HCHE@H0]DUHHH}HuH}HuH]f.UHH}HE]fUHH HHHMHuHMH}HHEJH}HTHEH ]UHH HHHMHuHMH}HHEIH}HTHEH ]UHHH}HuHEHMHH H]UHHPH}HuHEHMH HH8HE<HEHqH:H}HE7IH}HEIH}HEIH}HuHUH/EHEUH}JHMH9HEu:J8HEUbJ HP]H}\# HHU@H f.@UHH}HE]fUHHH}HEHHE~AH=H5k$1H}*AH]f.@UHHH}HEHH$H]f.UHH H}uHE}HE"EHMHωEGU9H=-H53H;N"HEuHeGH-H ]ÐUHH}HEHQ H;P@@@]f.UHH}uHEHHHHc@HHHcEHHH]fUHH`H}HuHEH}HE?HC/HMH9HuH}d-HEH8F"H}?H}о,HEHEHMHH7HEHEHEHuH}Hu2FH}HE1FH}HuHUH,WHEUH}GH}HEEHMH)HHMHr )Ɖr GAHEUdGHEH`]H}U  HHU9E UHH H}HuHEHHUH; HE#HuH}KH}Hu+H}HEH ]f.UHHH}HEH EH]fUHHH}HuH}HucH]f.UHHH}HuHEHMHH H]UHHH}H}H]DUHHH}HuH}HuH]f.UHH H}HuH}7HHEH}'HHMHH}HHMHH ]@UHH}HE]ÐUHH0H}uUHM}lHEHEMɉMEԃ6H}HEH@0#H}HEH@c} HEHHEHEH@HH@HH9@H@HAD@ @HE[HEH@HH@HH9@H@HAD@ @HE H0]f.UHH@H?/HHEH}؉uHEHEH}HE1HMHEHEHH5zt/H?/HHMH9H@]C fUHH@HQ?/HHEH}@@uHEHEH}HEHMHEHEHH5s/aH>/HHMH9H@]]C UHH H}HEHHHHEZ5Hx(#HEHH=5H4HEHms/HEHEH ]fUHH H}HuHEH}HE HE:H}H5]|/B HEHEHEHuH*HEHEH ]f.fUHH0H}uUHMHEHuUH}H}HHMHE*E} EEm}.}HEЋuUHMH3EE/}  } HEHEEEEEH0]UHH}HE]fUHH}HE]fUH1H}$]f.DUHH}@@u]f.@UH1H}HuHU]ÐUHH0H}uUHM}\HEHEMɉMEԃ&H}HEH@0H}c} HEHHEHEH@HH@HH9@H@HAD@ @HE[HEH@HH@HH9@H@HAD@ @HE H0]f.UHH@HA;/HHEH}؉uHEHEH}HE:1HMHEHEHH5q/YH:/HHMH9H@]U? fUHH1H}HUHH52q/H]fUHH H}HEHHHHE1Hx(#HEHH0H0HEHp/HEHEH ]fUHH H}HuHEH}HE HE:H}H5x/> HEHEHEHuH(HEHEH ]f.fUHH0H}uUHMHEHuUH}H}HHMHE'E} EEm}.}HEЋuUHMHEE/}  } HEHEEEEEH0]UHH}HE]ÐUHHH8/HHEHH$HHɉHHHHHpHHHlj|HpNHHpHHHh<|HHpHhsH6HR@HHh6HQH HHHHH@HH@HH9@H@HAD@ @HaHH@HH@HH9@H@HAD@ @H H6/HHMH9HĠ]H : UHH`HQ6/HHEH}@@uHEHEH}HMHUHEMHEH}PHEH}S1HMHEHEHH5+m/BH5/HHMH9H`]>: fUHH1H}HUHH5l/H]fUHH H}HEHHHHE ,Hx(#HEHH+H+HEHul/HEHEH ]fUHH H}HuHEH}HE HE:H}H5t/~9 HEHEHEHuH!HEHEH ]f.fUHH0H}uUHMHEHuUH}H}HHMHE9!E} EEm}.}HEЋuUHMHSEE/}  } HEHEEEEEH0]UHH}HE]fUHH}HE]fUHH}HE]fUHHH}uHEuHH]f.fUHH}uHEMʃHEM$E!HEMHEM HEME]f.UHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HmHMHcHEHMEGEHME4EHME!EHMEEHMEE]ÐUHHH}H}H]UHHH}uUHEuUH H]fDUHH}uUHEMUUɉσHEH}HyHMHcHEHMEOEHME:EHME%EHMEEHMEE]UHH0H}uUHM}:HEHEMH}HEH@0p} aHEHHEHEH@HH@HKH9@H@HAD@ @HE H0]UHH@H//HHEH}؉uHEHEH}HE 1HMHEHEHH5g/H//HHMH9H@]3 fUHH H}HEHHHHE%Hx(#HEHH%Hm%HEHf/HEHEH ]fUHH H}HuHEH}HE HE:H}H5]n/N3 HEHEHEHuHdHEHEH ]f.fUHH0H}uUHMHEHuUH}H}HHMHE E} EEm}.}HEЋuUHMHCEE/}  } HEHEEEEEH0]UHH}HE]ÐUHH0H}uUHM}:HEHEMH}HEH@0p} aHEHHEHEH@HH@HKH9@H@HAD@ @HE H0]UHH@H,/HHEH}؉uHEHEH}HE*1HMHEHEHH5"e/ Hf,/HHMH9H@]0 fUHH H}HEHHHHE"Hx(#HEHH"HM"HEHd/HEHEH ]fUHH}HEH]f.DUHH H}HuHEH}HE HE:H}H5}k/0 HEHEHEHuH$HEHEH ]f.fUHH0H}uUHMHEHuUH}H}HHMHEE} EEm}.}HEЋuUHMH#EE/}  } HEHEEEEEH0]UHH}HE]ÐUHH}uUHM]f.fUHH H}HEHHHHE Hx(#HEHH H= HEH=c/HEHEH ]fUHH H}HuHEH}HE HE:H}H5i/. HEHEHEHuHHEHEH ]f.fUHH H}uUHMHEuUHMH$EEH ]UHH0H}uUHM}:HEHEMH}HEH@0p} aHEHHEHEH@HH@HKH9@H@HAD@ @HE H0]UHH@H!(/HHEH}؉uHEHEH}HE 1HMHEHEHH5b/9H'/HHMH9H@]5, fUHH H}HEHHHHE*Hx(#HEHH HHEH]b/HEHEH ]fUHH H}HuHEH}HE HE:H}H5g/+ HEHEHEHuHHEHEH ]f.fUHH0H}uUHMHEHuUH}H}HHMHEYE} EEm}.}HEЋuUHMHCEE/}  } HEHEEEEEH0]UHH}HE]fUHH}uUHM]f.fUHH H}HEHHHHE:Hx(#HEHHHHEH`/HEHEH ]fUHH H}HuHEH}HE HE:H}H5e/) HEHEHEHuHHEHEH ]f.fUHH H}uUHMHEuUHMHEEH ]UHH}Hu]fUHHH}H};H]DUHHH}HEHHEHEHz'H]fUHHH}HEHH]ÐUHH}uUHM]f.fUHH H}HEHHHHEjHx(#HEHHMHHEH-`/HEHEH ]fUHH H}HuHEH}HE HE:H}H5-d/' HEHEHEHuHHEHEH ]f.fUHH H}uUHMHEuUHMHFEEH ]UH1H}Hu$]f.UHH}Hu]%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%"/%#/%#/%#/%#/%#/% #/% #/%#/%#/%#/%#/%#/%#/%#/%#/%#/% #/%"#/%$#/%&#/%(#/%*#/%,#/%.#/%0#/%2#/%4#/%6#/%8#/%:#/%<#/%>#/%@#/%B#/%D#/%F#/%H#/%J#/%L#/%N#/%P#/%R#/%T#/%V#/%X#/%Z#/%\#/%^#/%`#/%b#/%d#/%f#/%h#/%j#/%l#/%n#/%p#/%r#/%t#/%v#/%x#/%z#/%|#/%~#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%#/%$/%$/%$/%$/%$/% $/% $/%$/%$/%$/%$/%$/%$/%$/%$/%$/% $/%"$/%$$/%&$/%($/%*$/%,$/%.$/%0$/%2$/%4$/%6$/%8$/%:$/%<$/%>$/%@$/%B$/%D$/%F$/%H$/%J$/%L$/%N$/%P$/%R$/%T$/%V$/%X$/%Z$/%\$/%^$/%`$/%b$/%d$/%f$/%h$/%j$/%l$/%n$/%p$/%r$/%t$/%v$/%x$/%z$/%|$/%~$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%$/%%/%%/%%/%%/%%/% %/% %/%%/%%/%%/%%/%%/%%/%%/%%/%%/% %/%"%/%$%/%&%/%(%/%*%/%,%/%.%/%0%/%2%/%4%/%6%/%8%/%:%/%<%/%>%/%@%/%B%/%D%/%F%/%H%/%J%/%L%/%N%/%P%/%R%/%T%/%V%/%X%/%Z%/%\%/%^%/%`%/%b%/%d%/%f%/%h%/%j%/%l%/%n%/%p%/%r%/%t%/%v%/%x%/%z%/%|%/%~%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%%/%&/%&/%&/%&/%&/% &/% &/%&/%&/%&/%&/%&/%&/%&/%&/%&/% &/%"&/%$&/%&&/%(&/%*&/%,&/%.&/%0&/%2&/%4&/%6&/%8&/%:&/%<&/%>&/%@&/%B&/%D&/%F&/%H&/%J&/%L&/%N&/%P&/%R&/%T&/%V&/%X&/%Z&/%\&/%^&/%`&/%b&/%d&/%f&/%h&/%j&/%l&/%n&/%p&/%r&/%t&/%v&/%x&/%z&/%|&/%~&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%&/%'/%'/%'/%'/%'/% '/% '/%'/%'/%'/%'/%'/%'/%'/%'/%'/% '/%"'/%$'/%&'/%('/%*'/%,'/%.'/%0'/%2'/%4'/%6'/%8'/%:'/%<'/%>'/%@'/%B'/%D'/%F'/%H'/%J'/%L'/%N'/%P'/%R'/%T'/%V'/%X'/%Z'/%\'/%^'/%`'/%b'/%d'/%f'/%h'/%j'/%l'/%n'/%p'/%r'/%t'/%v'/%x'/%z'/%|'/%~'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%'/%(/%(/%(/%(/%(/% (/% (/%(/%(/%(/%(/%(/%(/%(/%(/%(/% (/%"(/%$(/%&(/%((/%*(/%,(/%.(/%0(/%2(/%4(/%6(/%8(/%:(/%<(/%>(/%@(/%B(/%D(/%F(/%H(/%J(/%L(/%N(/%P(/%R(/%T(/%V(/%X(/%Z(/%\(/%^(/%`(/%b(/%d(/%f(/%h(/%j(/%l(/%n(/%p(/%r(/%t(/%v(/%x(/%z(/%|(/%~(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%(/%)/%)/%)/%)/%)/% )/% )/%)/%)/%)/%)/%)/%)/%)/%)/%)/% )/%")/%$)/%&)/%()/%*)/%,)/%.)/%0)/%2)/%4)/%6)/%8)/%:)/%<)/%>)/%@)/%B)/%D)/%F)/%H)/%J)/%L)/%N)/%P)/%R)/%T)/%V)/%X)/%Z)/%\)/%^)/%`)/%b)/%d)/%f)/%h)/%j)/%l)/%n)/%p)/%r)/%t)/%v)/%x)/%z)/%|)/%~)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%)/%*/%*/%*/%*/%*/% */% */%*/%*/%*/%*/%*/%*/%*/%*/%*/% */%"*/%$*/%&*/%(*/%**/%,*/%.*/%0*/%2*/%4*/%6*/%8*/%:*/%<*/%>*/%@*/%B*/%D*/%F*/%H*/%J*/%L*/%N*/%P*/%R*/%T*/%V*/%X*/%Z*/%\*/%^*/%`*/%b*/%d*/%f*/%h*/%j*/%l*/%n*/%p*/%r*/%t*/%v*/%x*/%z*/%|*/%~*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%*/%+/%+/%+/%+/%+/% +/% +/%+/%+/%+/%+/%+/%+/%+/%+/%+/% +/%"+/%$+/%&+/%(+/%*+/%,+/%.+/%0+/%2+/%4+/%6+/%8+/%:+/%<+/%>+/%@+/%B+/%D+/%F+/%H+/%J+/%L+/%N+/%P+/%R+/%T+/%V+/%X+/%Z+/%\+/%^+/%`+/%b+/%d+/%f+/%h+/%j+/%l+/%n+/%p+/%r+/%t+/%v+/%x+/%z+/%|+/%~+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%+/%,/%,/%,/%,/%,/% ,/% ,/%,/%,/%,/%,/%,/%,/%,/%,/%,/% ,/%",/%$,/%&,/%(,/%*,/%,,/%.,/%0,/%2,/%4,/%6,/%8,/%:,/%<,/%>,/%@,/%B,/%D,/%F,/%H,/%J,/%L,/%N,/%P,/%R,/%T,/%V,/%X,/%Z,/%\,/%^,/%`,/%b,/%d,/%f,/%h,/%j,/%l,/%n,/%p,/%r,/%t,/%v,/%x,/%z,/%|,/%~,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%,/%-/%-/%-/%-/%-/% -/% -/%-/%-/%-/%-/%-/%-/%-/%-/%-/% -/%"-/%$-/%&-/%(-/%*-/%,-/%.-/%0-/%2-/%4-/%6-/%8-/%:-/%<-/%>-/%@-/%B-/%D-/%F-/%H-/%J-/%L-/%N-/%P-/%R-/%T-/%V-/%X-/%Z-/%\-/%^-/%`-/%b-/%d-/%f-/%h-/%j-/%l-/%n-/%p-/%r-/%t-/%v-/%x-/%z-/%|-/%~-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%-/%./%./%./%./%./% ./% ./%./%./%./%./%./%./%./%./%./% ./%"./%$./%&./%(./%*./%,./%../%0./%2./%4./%6./%8./%:./%<./%>./%@./%B./%D./%F./%H./%J./%L./%N./%P./%R./%T./%V./%X./%Z./%\./%^./%`./%b./%d./%f./%h./%j./%l./%n./%p./%r./%t./%v./%x./%z./%|./%~./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%./%//%//%//%//%//% //% //%//%//%//%//%//%//%//%//%//% //%"//%$//%&//%(//%*//%,//%.//%0//%2//%4//%6//%8//%://%//%@//%B//%D//%F//%H//%J//%L//%N//%P//%R//%T//%V//%X//%Z//%\//%^//%`//%b//%d//%f//%h//%j//%l//%n//%p//%r//%t//%v//%x//%z//%|//%~//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//%//L).AS%Q.h h h# hh hh9hVhhhhxhnh(dhlZhPhFh hl 4h *h h h h2 hV hu h h h: hT hp h h h h h+ hj h vh lh bhXhNhdDh|:h0h&hh9hbhhhhh2h^hhhhhh>h\hz|hrhhh^h$ThOJh@h6h,h"hh?hdhhhhh h%hKhrhhhhhhxh;nhVdhpZhPhFhh4h*hQ hh hh h: h] h h h h h/!h!h!h!h"h("hQ"vh"lh"bh"Xh+#Nhd#Dh#:h#0h#&h#h $h($hI$h{$h$h$h$h %h<%h[%h%h%h%h &h2&hL&|hp&rh&hh%^h&Th&Jh'@h,'6hH',hd'"hh&h&hz'h'h'h'h'h'h'h'h(h(^OO s  V  0qC }Pi 88 bE8 .C +   // T<3 (b#''<Qf{#''<Qf{%*?Ti~ %*?Ti~  */s:ee{????2**9 F22>**;>!]288F&l #  !  hYYLO      < '9**N#qS9pp[ i   \ umzR   B  !!WW+W!UU  > .C9.ggyo - A)KWW.9/_`11.d/z 5M)kk!.%. z8) +C%MMg]w"G$$`!!>A8LL _U)~ $ ) .=4\\ si"<0^UU./x"<c$$` .C66%l R\66 vQ ^HC    h'7:i=4ZZs{& -  /h{p/tt%u !? jj}r;{{ .F1(l&H ++t P // }|,BBkO^^ aasrWW+W-``$!$== c C eLL`QIORM   !yy$%++ B T7 Sw w 6   Q;;7%00 B$k }%00 B$k }LAgg$( 8Mf}O q       7  88Bz/KK$t KK Wp[Ghh^!II$r:==+mh< !@@ NiX==RjXM@ K WYYT" R'``$!1 aasrYYT@   ^'``$!1cc$IIE 29! X&y,T@/==$f--Oxf fWW+W==$f==$f7<<Rb7<<Rb9mm$5]]v o o p.+;  ` SSdE!yy$88 d qX<iAA    =     `u 22 e>B77n6ee=/RRI^LG??D //K7////3\\KG }TT95!PP95UMMbw3?GAJJ;3 ddx3 II)r3 ::%y_5 11 X>588 \ }v+553m E G662s k9^^s}q  /  /QQx!7 I zu 5M     5M 5M 5M .FE:l 7   +C=3LL _U)~  &4=4\\ si"<0^)kk!.  /  / .T .T!!]!!Issu>e!!> .T .T  0 /N 5M%MMg]w"G!!E*Tl 000 %%w8<tw<w<w<w<8x5x5x5x5x5x5x5x8x;x;y;y ;y ;y ;y ;y ;y ;y ;y ;y ;y ;z;z;z;z;z;z;z;z;z;z;z;{;{;{;{;{;{;{;{;{;{;|;|;|;|;|;|;|;|;|;|;|;};};};};} ;} ;}!;}!;}";}";}#;~#;~$;~$;~%;~%;~&;~&;~';~';~(;(;););*;*;+;+;,;,;-;-;.;.;/;/;0;0;̀1;ـ1;2;2;3;3;4;4;5;5;Ł6;с6;݁7;7;8;8;9;9;:;:;;;ɂ;;Ղ<;<;=;=;>;>;?;?;@;@;̓A;كA;B;B;C;C;D;D;E;E;ńF;фF;݄G;G;H;H;I;I;J;J;K;ɅK;ՅL;L;M;M;N;N;O;O;P2P2͆P2نQ2Q2R2R2S2S2S2T2T2ŇU2чU2݇V2V2V2W2W2X2X2Y2Y2ɈY2ՈZ2Z2[2[2\2\2\2]2]2^2͉^2ى_2_2_2`2`2a2a2b2b2Ŋb2ъc2݊c;dd9 0000Q1(l&H  .CQBB  ; : FFxD          (A^1A..../////0000001 1  1!!1!!1""2##2##2$$2$%2%%3&&3&&3''3((3((3))4)*4**4++4++4,,5--5--55369798_9949:1;:A;<4<1= >kWW+Wf    t  7 0         ?lT3w         \g.*g!!"#5%#%$%$%'5((()),*-/.g//0k01191_H{X{{  r{  {  x{ .{uWW+W 11 Z>7VGz    / SIKg8B  0  [Wpp  ?X            fC$  4   F   !   ` /NC$l.OUUd 6    6        `d `  d !`!!d!"" """"""#### "=#e I55^6;8F%G-?)m H   (BbQ       5  (vv-CW+0F-C_H %% J.7HHHwK  VEEHt`:EEHt`:!YYR  jYYHu= .C .C .C .C .C%MMg]w"G 5M%MMg]w"G 5MN%}s1л. x  999*E-H-H    - H    - H    - H   -!H!!!-!H"""-"H###*#H###*$H$$$-$H%%%-%H&&&-& 'M'M'3M(6M(\)M)N)3N*6N*\+N+N+3N,6N,H-O-O-O.7O.'O.T/P/P0P07P0'P1T1Q2Q2Q27Q3'Q3T4R4R4R4R4R5-R5t6S6S6S7S7!S7h8T8T9T9T9!T9h:U:U;U;U;!U;h<V<V=V=V=!V=h>W>W?W?W?!W?h@X@XA3XA6XA\BXBXC3YC6YDHDYDYEYE7YE'YFhFZGZGZGZHZHZH[H-[IJ\J\J\J\K\K\K\K-\L1LIIiX2ZlO JJ`:WW+Wgg(pdd=:f8rr  r  r  r  rrUrMM|^UO ==mN:IIcuj [[pM0S=`CpX3 /N//DfbZ         ` aar3#!tt,x r p]||Ra^ 2U  ,,<jPPx } S    +33 E(r'44{J SX*^^g :VVg_ "Y88Ym9E  Y  $JJ X s 7d?99} EX+&chh<kAww ETTj w _33E1v4 E+A}u s       t  tv sBW 7     d G\??W      < ]EK0]A7 .F 3S .F .F .F .F!!>1(l&H !!>1(l&H   /  /  /  /1(l&H 1(l&H  -.&&e8YYf >>Fj% 1,] 22 D \#++ 8.f|   MM aV2PXkn !K 11 Z>766h z  $$8t\K..'Zs'8 YAK22'^122'^1..'Zs'+11']v'',77-i  22'^rr22'^rr(+ 3 DA8LL _U)~ $ ) .oo^ ]"Cf h=3LL _U)~  &4 ;;`L/B Tn {r( T vBD%% Q sxk-oBoUooppoppoppoqqoqqoqrorrorross o s s o s s o t t o t t o t uouuouuovvovvovvowwowwowxoxxoxxoyyoyyoyyozzozzoz{o{{o{{o|| o | |!o!|!|"o"}"}#o#}#}$o$}$~$o%~%~%o&~&~&o'''o(((o())o)**o*Ȁ+Ԁ+o+,,o,,-o-؁-.o../o//Ă0o001o112o2ȃ2ԃ3o334o445o5؄56o667o77ą7o888o999o:Ȇ:Ԇ:o;;;o;<<o<؇==o=>>o>>Ĉ?o??@o@@AoAȉAԉBoBBCoCCDoD؊DEoEFFoGGċGoHHIoIIJoJȌJԌKoKLLoMMMoN؍NOoOOPoPPĎQoQRRoR+SSoTȏTԏToUUUoUVVoVؐWWoWWXoXXđYoYYZoZZ[o[Ȓ[Ԓ\o\\]o]]^o^ؓ^_o__`o``ĔaoaabobbbocȕcԕcodddoeeeoeؖffogggohėhЗhoiiiojjjojԘkkokllolmmomnnonno+0 Q9Kw--7       55 V>K 11 Z>7J>>S  I=3LL _U)~  &4%@@-rtl>>-p-- 6         ,<<'h'22'^1&(A c q'.?8M    i'''Sgr +C .C 'd +C$ 8-)=4\\ si"<0^ +C .C)kk!.=4\\ si"<0^ ((N81) . L Y))kk!.=4\\ si"<0^$$p9/nnv.- %N)kk!.)!A7%pgn-convert.settings.processed.pgnmain.cppint main(int, char **)Processinggames in fileDone&other != this/Users/jens/Qt/5.15.2/clang_64/lib/QtCore.framework/Headers/qstring.hdefaultsize == 0 || offset < 0 || size_t(offset) >= sizeof(QArrayData)/Users/jens/Qt/5.15.2/clang_64/lib/QtCore.framework/Headers/qarraydata.hKQRB♔♕♖♗♘%1...O-OO-O-Ofrom < 64../../src/database/bitboard.cpps < 64isValidPiece(p) || p == Emptywp == m_pawnCount[White]bp == m_pawnCount[Black]wp + wk + wo == m_pieceCount[White]bp + bk + bo == m_pieceCount[Black]%1/pppppppp/8/8/8/8/PPPPPPPP/%2 w KQkq - 0 1o-o-o0-0-0o-o0-0000000K0QZ0nullQRBN w b - BitBoardw%1 b%2 %3 to move (%1+%2).rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 10 <= type && type < PieceTypeCount../../src/database/bitboard.h KQRBNPkqrbnp KQRBNPKQRBNP:\[%(egt|emt|clk)\s*(\d?\d:\d?\d:\d\d(\.\d)?)\]\[%(emt)\s*(\d?\d:\d?\d:\d\d(\.\d)?)\]\[%(clk)\s*(\d?\d:\d?\d:\d\d(\.\d)?)\]\[%(egt)\s*(\d?\d:\d?\d:\d\d(\.\d)?)\]\[%(csl|cal)\s*([^\]]*)\]\[%(csl)\s*([^\]]*)\]\[%(cal)\s*([^\]]*)\]\[%(eval)\s*((-?\d?\d(\.\d\d?)?)|#\d\d?)\]MoveData[end]QVector::QVectorSize must be greater than or equal to 0.variations().contains(moveId)../../src/database/gamecursor.cppvoid GameCursor::dumpMoveNode(MoveId) constMove Id : Next node : Prev node : Parent node : Deleted : # Variations: Variations : Move : ()--xxXKQRBNPKQRBNPm_ply<0x7FFF../../src/database/gamecursor.htrueQList::swapvoid QList::removeAt(int) [T = int]QList::removeAt(): Index out of range.QList::eraseThe specified iterator argument 'afirst' is invalidThe specified iterator argument 'alast' is invalidCopy gameAdd move([%emt 0:%1:%2]noneW%1-%2 %3Merge game.??Replace moveAdd lineAdd variationPromote variationRemove variationSetupTruncate variationRemove variationsRemove commentsRemove time commentsSet annotationEdit annotationAppend annotation[%csl %1]%1%2,.%1,%2%3 ,,,'Colorize square%1%2%3%1,%2%3%4Paint arrow[%cal %1]Add nagSet nagsMove variation^.\)%1) %2Enumerate variationsSet resultChess960../../src/database/gamex.cppvoid GameX::dumpAnnotations(MoveId) const Annotations Text : Start : Nags : void GameX::dumpAllMoveNodes() constCurrent Node: Moves: Comments: Nags: ----------------------------------../../src/database/index.cppvoid IndexX::reserve(quint32)Index space void IndexX::squeeze()\-\(\)QWriteLockerQReadWriteLock pointer is misaligned/Users/jens/Qt/5.15.2/clang_64/lib/QtCore.framework/Headers/qreadwritelock.hQReadLocker/Users/jens/Qt/5.15.2/clang_64/lib/QtCore.framework/Headers/qbitarray.hQVector::insertQVector::insertThe specified iterator argument 'before' is invalid $□∞⩲⩱±∓+--+++----++⊙With slight space advantageWith moderate space advantageWith decisive space advantageWith slight development advantage↻→With lasting initiative↑With insufficient compensation for material deficit≌With more than adequate compensation for material deficitWith slight center control advantageWith moderate center control advantageWith decisive center control advantageWith slight kingside control advantageWith moderate kingside control advantageWith decisive kingside control advantageWith slight queenside control advantageWith moderate queenside control advantageWith decisive queenside control advantageWith vulnerable first rankWith well protected first rankWith poorly protected kingWith well protected kingWith poorly placed kingWith well placed kingWith very weak pawn structureWith moderately weak pawn structureWith moderately strong pawn structureWith very strong pawn structureWith poor knight placementWith good knight placementWith poor bishop placementWith good bishop placementWith poor rook placementWith good rook placementWith poor queen placementWith good queen placementWith poor piece coordinationWith good piece coordinationWhite played the opening very poorlyBlack played the opening very poorlyWhite played the opening poorlyBlack played the opening poorlyWhite played the opening wellBlack played the opening wellWhite played the opening very wellBlack played the opening very wellWhite played the middlegame very poorlyBlack played the middlegame very poorlyWhite played the middlegame poorlyBlack played the middlegame poorlyWhite played the middlegame wellBlack played the middlegame wellWhite played the middlegame very wellBlack played the middlegame very wellWhite played the ending very poorlyBlack played the ending very poorlyWhite played the ending poorlyBlack played the ending poorlyWhite played the ending wellBlack played the ending wellWhite played the ending very wellBlack played the ending very well⇄Moderate time control pressure⊕△Aimed against≥<Equivalent wasRRNx⊥⇔⇗⧉◨▞->Good MovePoor MoveVery good MoveBlunderSpeculative MoveDubious MoveOnly MoveWorst MoveEqualUnclearWhite has slight advantageBlack has slight advantageWhite has moderate advantageBlack has moderate advantageWhite has decisive advantageBlack has decisive advantageWhite has crushing advantageBlack has crushing advantageZugzwangWith moderate development advantageWith decisive development advantageWith initiativeWith attackWith compensationWith counterplaySevere time control pressureWith the ideaBetter wasWorse wasWeak pointEndgameLineDiagonalPair of bishopsBishops of opposite colorBishops of the same colorDiagram∝±→↑⊕Δ⇔%1 (%2)NagSetQVector::removeQVector::eraseThe specified iterator argument 'abegin' is invalidThe specified iterator argument 'aend' is invalidabegin >= d->begin()aend <= d->end()abegin <= aendtemplateshtml-default.templatenotation-default.templatelatex-default.templatepgn-default.templatefalse../../src/database/output.cpp
^\s*$^\s*#[OPTIONSDEFINITIONS][OPTIONS][OUTPUTHEADER][OUTPUTFOOTER][MARKUPTAGS]\\n\\^\n,void Output::readTemplateFile(const QString &)Could not create option. Ignoring line %d in file %s : %sInvalid option or value in file %s line %d. Ignoring : %sMarkupHeaderBlockMarkupNotationBlockMarkupResultMarkupDiagramMarkupMainLineMoveMarkupVariationMoveMarkupMainLineMarkupVariationInlineMarkupVariationResumeMarkupVariationResume1MarkupVariationResume2MarkupVariationResume3MarkupVariationResume4MarkupVariationResume5MarkupVariationResume6MarkupVariationResume7MarkupVariationResume8MarkupVariationResume9MarkupVariationIndentMarkupVariationIndent1MarkupNagMarkupAnnotationInlineMarkupAnnotationIndentMarkupPreAnnotationInlineMarkupPreAnnotationIndentMarkupHeaderLineMarkupHeaderTagNameMarkupHeaderTagValueMarkupWhiteTagMarkupBlackTagMarkupEventTagMarkupDateTagMarkupSiteTagMarkupResultTagMarkupRoundTagMarkupColumnStyleMoveMarkupColumnStyleRowMarkupColumnStyleMainlineMarkupMateUnknown Markup Tag found in file %s line %d. Ignoring : %sUnknown Section in Template File %s line %d : %sHtml OutputPgn OutputLatex OutputNotation Widget OutputPNGDiagram SymbolicNagDiagramSizeColumnStyle. ... #***VariationIndentLevelCommentIndentAlwaysOnlyMainlineHTMLCommentsECOWhiteElo (%1)BlackEloWhite - BlackEvent%1SiteRound, ShowHeader@(\w+)@@TextWidth ISO 8859-1utf8void Output::setTemplateFile(QString)Could not decide which template file to use. Maybe strange OutputType:/Date*node == e || (*node)->next/Users/jens/Qt/5.15.2/clang_64/lib/QtCore.framework/Headers/qhash.hNotation in Column StyleAllow HTML in commentsShow symbolic Nags0:20080Text width1:2004Indent variations from LevelVariationIndentSize1:103Variation IndentationAlways|OnlyMainline|NeverComment indentationMainLineMoveColorMain Line ColorVariationColorVariation ColorCommentColorComment ColorNagColorNAG ColorHeaderColorHeader ColorShow HeaderShowDiagramsShow Diagrams0:500200Diagram SizeFontBrowserTextFont for textFontBrowserMoveFont for movesComment Indentation../../src/database/outputoptions.cppbool OutputOptions::createOption(const QString &, OutputOptions::OutputOptionType, const QString &, const QString &, const QString &)Option '%s' could not be createdbool OutputOptions::setOption(const QString &, const QString &)Option '%s' could not be set1whitepurple^#[0-9a-fA-F]{6}StringIntegerBooleanColorOutputOptions^[\?0-9]{4}([\./]([\?0-9]){1,2}){,2}$[\./]^(([\?0-9]){1,2}\.){,2}[\?0-9]{4}$^(([\?0-9]){1,2}/){,2}[\?0-9]{4}$????.??.??%1.%2.%3-%1.%2-%3%1.%2.%3-%4len >= 0/Users/jens/Qt/5.15.2/clang_64/lib/QtCore.framework/Headers/qstringview.hstr || !len.cxiInternal.pgnFENVariantfischer960?../../src/database/pgndatabase.cppvoid PgnDatabase::seekGame(GameId)Seeking offset failed!\""Result1/21/2-1/2Length0*[{!!!!????!+=+/-==+1-00-1-/+PlyCount\s(\d+)\s*\. \([^\(\)]*\)!weakref.loadRelaxed()/Users/jens/Qt/5.15.2/clang_64/lib/QtCore.framework/Headers/qsharedpointer_impl.hstrongref.loadRelaxed() <= 0QMutexLockerQMutex pointer is misaligned/Users/jens/Qt/5.15.2/clang_64/lib/QtCore.framework/Headers/qmutex.huint(i) < uint(size())QList::operator[]....i >= 0/Users/jens/Qt/5.15.2/clang_64/lib/QtCore.framework/Headers/qbytearray.hcapacity() >= asize/Users/jens/Qt/5.15.2/clang_64/lib/QtCore.framework/Headers/qvector.haalloc >= d->sizex->ref.isSharable() || options.testFlag(QArrayData::Unsharable)!x->ref.isStatic()d != xd->data()uint(d->size) <= d->allocd != Data::unsharableEmpty()d != Data::sharedNull()d->alloc >= uint(aalloc)isDetached()!this->isEmpty()/Users/jens/Qt/5.15.2/clang_64/lib/QtCore.framework/Headers/qstack.hQVector::atQVector::operator[]chessxGameTextPieceStringdata/log/engines-macucichessx.eco:chessx.ecochessx.gtm:chessx.gtmwinboardtimesealmacchessdata/General/DefaultDataPathindexshotsColumnCount/General/EditLimit/General/automaticECO/General/useIndexFile/General/ListFontSize/General/onlineTablebases/General/tablebaseSource/General/onlineVersionCheck/General/autoCommitDB/General/languageDefault/General/BuiltinDbInstalled/GameText/FontSize/GameText/ColumnStyle/GameText/HTMLComments/GameText/HideSpecAnnotations/GameText/SymbolicNag/GameText/TextWidth/GameText/VariationIndentLevel/GameText/VariationIndentSize/GameText/CommentIndentNever/GameText/MainLineMoveColorblack/GameText/VariationColorblue/GameText/CommentColorgreen/GameText/NagColorred/GameText/HeaderColor/GameText/ShowHeader/GameText/ShowDiagrams/GameText/DiagramSize/GameText/FontBrowserTextArial Unicode MS/GameText/FontBrowserMove/GameText/PieceString KQRBN/GameList/AdditionalTags/MainWindow/GameToolBar/MainWindow/VerticalTabs/MainWindow/DarkTheme/MainWindow/Themeplastique/MainWindow/StayOnTop/MainWindow/FilterFollowsGame/MainWindow/ShowMenuIcons/MainWindow/AutoRaise/Mail/LastRecipient/History/MaxEntries/FICS/useTimeseal/FICS/guestLogin/FICS/userNameguest/FICS/passWord/FICS/minutes/FICS/increment/FICS/eloLow/FICS/eloHigh/FICS/commandline/Lichess/userName/Lichess/passWord/Chesscom/userName/Chesscom/passWord/Board/showFrame/Board/showCoordinates/Board/colorCopy/Board/fixedImageSize/Board/copyImageSize/Board/showCurrentMove/Board/showMoveIndicator/Board/guessMove/Board/showThreat/Board/showVariationArrows/Board/showTargets/Board/noHints/Board/nextGuess/Board/minWheelCount/Board/pieceThememerida/Board/pieceEffect/Board/boardThemebrazilwood/Board/lightColor/Board/darkColor/Board/highlightColor/Board/frameColor/Board/currentMoveColor/Board/storedMoveColor/Board/variationMoveColor/Board/threatColor/Board/targetColor/Board/checkColor/Board/wallColor/Board/underprotectedColor/Board/engineColororange/Board/AutoPlayerInterval/Board/AutoSaveAndContinue/Board/BackwardAnalysis/Board/AnalyseOnlyMainline/Board/AnnotateScore/Board/AddAnnotation/Board/BlunderCheck/Board/AutoPromoteToQueen/Board/AlwaysScale/Board/PlayerTurnBoard/Board/ReadAhead/Match/Mode/Match/TotalTime/Match/UserBonus/Match/Increment/Match/MoveCount/Match/AnnotateEgt/Match/AllowBook/Match/BookMove/Match/EngineStarts/PlayerListWidget/FilterEditCompleter/Sound/Move/Sound/ScreenReader/Sound/PlyReadAhead/Sound/DelayReadAhead/Tools/Path1/Tools/CommandLine1/Web/Favorite1/Web/AutoNumber1/.pngthemes:/themes/:/themes*.pngboards:/themes/boards:/themes/boards/images:/data/images:i18nlang*.qmchessx.ini!isEmpty()/Users/jens/Qt/5.15.2/clang_64/lib/QtCore.framework/Headers/qlist.hQList::atindex out of range  JvGbC?tr2r4 -r-Gr(-Gr-r|-[r-r~d-r}-rz-@rz-r2-rR- r{-rxB-ݝr-Vrx$-r| -Qr~p-ry-r{-rJjr0r0,`r%!rJ)&r0(r$*r(w&rB+ir$ rJr0|r @rr*fr-r\y r Xr*r#*SrJ2rl ry!r$Fr!ary#frrr6rcuEQX>r^,rv,r--r-dhr @rX JrC rC" rn rO* Zrd ,LTrlJ hr# O:r QrE ;rMwr8  r* JrH 'ri x׀;- 0rm^Br5h j r]{rorwUrpn r6l rC r x.x> =rl 7rC\ ' r26 ru Flr\2tuT JrRkr SDr%drg r4 jrf 'rt"r+ RrD Srb *ra ars mrex'r, rsrq  rj r0 ?rN6 rl #or] a*u7 t/ ArE }r2@ b rC rJ ~crJ hrK NrQ< ro%5r^ :xك\ frG bVvuA~ , r[ zfr; MrT DRrqr<< r.^ + r/@rC *r-  rC 2r: Fr9 trhru )rHyg ڡrV rh DYrA xr`, rK frRB rW ~rt Zrf$ IrQ DHura r$er_h rY CrX  Nrv J+rY pqr7 }rn r j$rc(fu6)%g^ rSr' }r= Yr& rO6r)r: rZGr_ vrV _r K=r1 rB 0 rr Z_rP-wr-ky}~X-u-&-yr8T(rPVnr#lVrrrrjr!/r%wX.hLrrp s-chessx.gtm vchessx.eco Dtextedit rCtemplatesijsoundsthemes0helpstyles}images Oreplay.png /hgame_engine.pngbrush_yellow.png Ynext.png'show_variations.pngH'brush_erase.pngYprev.png {gaccept.png jchessx.png folder_grey.png ;Wtraining.pngGcircle_orange.svgOpin.ico Çfind_tag.png 4folder_favorite2.png`black_wall.png :%white_wall.png edit_mail.png 'filter.png circle_red.svgsquare_yellow.png 'arrow_red.pngGfolder_new.png setup_board.png egchesscom.png8Zhome.png list_add.pngZGback.png Çfind_pos.pngcFlagFrance.pngcircle_blue.svgYplus.png XGredo.pngXsquare_none.png H'arrow_green.png computer.png IF'rating.png marrow_none.png \'filter_reset.pngfilter_rev.png 5folder_favorite1.png Wbug.png['threat_black.png #'decline.pngWZhint.png'circle_yellow.svgfolder_web.png g'camera.png time_clear.pngjcircle_black.svgWpen.pngC'filter-list.png !fileopen.png folder.png@black_chess.pngGFlagPoland.png go_in.png+show_threat.pngZ'draw.png 'new_board.png 'folder_closed.png ;Orename.png Gmatch.pngL'brush_green.png =game_down.png çrespond.png ]forward.png Clichess.pnggarrow_yellow.png Wgprint.pngXgsave.pngZfics.png j'brush_red.png Hsquare_green.png Cedit_cut.png "FlagGermany.pngc%'swap-color.pngZgchip.pngWquery_move.pngM'close_board.pngflip_board.png edit_paste.png 6gstartup.pngKfilter-plus.png Ëgo_up.png3vformat_indent_less.png !rnd_game.png spray.pngYlast.png new_game.png ʝgo_out.pnggtraining_both.png ̢'active.png YgreadAhead.png P'game_up.pngfolder_open.png 3Zhelp.png;Gshow_targets.pngWZ'insert_move.png ecircle_green.svgRgflip-vertical.png Mއengine.png Gfirst.png 7folder_favorite3.pngGflip-horizontal.png edit_copy.png FlagUK.png ginternet.png2threat_white.png annotate.png 'circle_grey.svgWnew.png ='go_down.pngqtext_clear.png- replace_move.pngXundo.png edit_after.png _'square_red.pngdown_arrow.png -handle.png V#gcheckbox.png ڛorange.css  ּabout1.html #about1a.html ּabout4.html ּabout0.html ּabout3.html Džabout.css [ּabout6.html ּabout2.html Vabout-dark.css ּabout5.html{gshadow .Gmerida.pngboards0outline 'alpha.png  Ngberlin.png Gleipzig.png 7mahogony.png 'cumaru.png Glapis.png spurpleheart.png Glanta.png.silverwood.pngWXwood.png Galuminium.pnguIgbrazilwood.pngGXgsand.pnggsandlewood.png slate.png jcherry.png (Gmaple.png *&Gmarble.png u\fantasy.png x@fritzSWS.png spatial.png ding1.wavSmove.wav aTfanfare.wav )woodthunk.wavEhtml-default.templateWpgn-default.template )latex-default.template =Enotation-default.template Z.'textunder.png)'textjustify.png @Geditredo.pngSgeditresize.png textleft.png h'Gtextright.png @editundo.png ;editpaste.png 6editcut.png Beditcopy.png hgfilesave.png0yGtextcenter.png ~gtextbold.png {zoomin.png ]textitalic.png Rfileprint.png Gexportpdf.png Rfilenew.png śzoomout.png2\LUK* !}OV jH #lJO M٣i֢&e@ I9{J j"e$)0م#E.%9#vh^<>[B>/l(; [%B<>5{C 4,ϙceL*!2"L^  1^6vPN>ͥVHڧ2:\-N fH,T99 gmW32"c*ZeH% sWz2*V$~x# }#䓢 u: 6&l2"k3Kl81#cL Zi-;#c k\ׇ3"2"SKş*S$8="S>6 S`*$>$}Hp;2=n[-7=@ө93<5k7Sr$7cA7.91*40BH /2D2*%HN3#!156. P"=r9*t@* g#4֤g -1)bU,0 ĥa1!#mbHm'IЈj&Hhp#)K 썏=<[\QpD Ep cAG4,\-紩zzѫ0(/[2gQ3*WA-j?|#:-mXA,4$L-_:̐wu,>+#x>-ꡗA>-9P=4s~93" ۝3+TJܾ5M\̴Z<.M$x#Nti^1#2]dU=6ZW՟x\P J.&-Hw[Y^6.}1{C|CS zSk2z>x=xqD w#Ov_h4$obȭ eZH D_ <Ԗ=4ZBdTS;\E$L5c&}#+KFVIJDW@4$JllHeJ = X936m]Ad<<>6V2*.&X;f7/(h[c"& >ܪ0[0(%,}Z "]Tԑ93,%&R@9 mHN@$i 3+9ko" [g\ Oɀ2" . #sSM L 3_w_?W3I .UŁ LA[1!|3";h@X9*F+y=/-掘(Q7ML dߍ2"Uw ha1)XLOtʺ!G#=-=r3#/ԨrCڅ,#Zwzz}P>-}ު {2*xys4,v B*'$nkU &kׁ$-e{;C<>dc =`w5#\_ -1)X0`b V<@*Q>z Q0uE"Mc`*4,Kqr:HVtO3#D zA6.4$=  :%H ZUd#1܄2*AK SFZ*"90 Z<>K K|'i x9*\2(93狺-' W1oMg#` g5B"]v<;4ٿ:k!2*Qdu սQ(*0(:ò4$ΠT5҈1)̿܆`1!ĵr X*і, %S^5%4Bj6.n: 6&?q3Fn*"po _8;)Ϙ%7s9*}4 _E_;=n 6fE -fuʯ\Tz \$+86.ZҞG>-Z(PXY 4$Su93Q͔ #Nʞ>Vw{2*DUZ]$$>/Ӕi4,66?^.:3 T0GU7!'R '`.5,룮;4Nr0m?Q Mc0(,%++;4ۡ4$ tH~b-# UYc;6.GGs&^e#5$hd9(5g-ZM$AP- 2"W7v44쾕l!&콕eV^ `R&\e $6-՝A C&0 &vI2*퟈>ѥ7/ʸLi&4$ȴ%c;4XR |AɊʸ&},9*Dq-|JTkX fP#p@4$';"$?C3i- @%@. ⎫a$9*,gJ.&b/*rt4=PA3"bk$Lv;;)v-#*";O %<93͉T |w &-|hy wwwvq',v&m=OagP>4gIG1BF f,f6.cF~a'`6.`1`=ي\Z:Uk*@2 SP͑P\4 M4M?W$K28 E(- 9Xa-9*6 *P09*47|33.Η0(0w2fy /7;z0>-,4C:,9߃>-*: (R?u(<>`3# OX3#*< zV"ceyң%a>/hD؉'-8$ +G+1!>:,L?5z犼!u# #lן 3dْ[e.>/F{Qc ׋3bspdw;)ʂ-J xtEá_xS2&V-3P$:1R l&w7f͠ I뮀&ؽZ193r^ #;لJ>-F* F8d7/Ak_>-crX4"hzn; & [h93@")I*R!%V*2*֣j J SK ~;L0b4,} a44y`c332*^SG:3[U<>J3D$[BweB*"8YuD 1K6&4//ACw9*.-3J1+ET}b5'E9*t[vYe Zwݝ5: [ɑ:," 4FF 6wF8Éݍ>4H]#C<>p7[8 ;)Lgp#6j $Q:C }O$E> !𮋢,5Cӟ4<>ܱRO| ,!ψτ($)?8=6|/*|xTc'OYZg\0('v%/..7 FRГ4$A ,@*8N9*-ybStaR3nߞ93n@߽&h!dEb^>4diʟ7 cciW(//$Sr(:%Mp7%DHgሰ B] ; >;r&>ȧQ;2>,L>4=lЮ3qx 0T-LS0(-q!|&*бIvS1!$F=|x*_;$0a $ hL#g# d[!9`2*OtU2*iZ${yhEGc]5-܌xγTKr19*#:1zy0(\iQ@тyؾ70b غF ySt (K$ԥ%y> m.+4$l=4$>S%;#̺Ն\E6; ,;>-ʩ!%_V0(&SZl#3+&WmxKf=: Qvg9*y;3#.-_u "ClN'I:.tT2"l>)4$|/ Kuc r\#qW3+pP7 u>-l f(2jP?0 g,U\ [:˚ZZ*yZsV* UJ UaA-T% kr&S3O1)Q.Y\~$P&<>OI]=Nkk:NpT -Nkο4"Hv-s F8h AfTr">1W=<<6&9p=p+%7k즷6 5RG0(4RL4,.N0 +9?Т]=6*naY5%yWJ&ʪADyф 0e9Š R;m9*T7`93J-yRI p7+o ͪ0  >1?h-}9 Ή?`IA& fb2*[)VCf  ܜT1-6ۼذB>>-.]/7/' B Dvֈ9*HWe>F 9:%'n;-Ǻ,z?6&IEz B"<{P$GDc:1<#d9* Gtr>- 9(SU!2I PV U81S 蘲%!+;-. oxefuZ93|Ҕ<4vZjrLwXѤ l"xs2"h% g2w3#eFDe" a)Śz`2-^{DY[`knY82"Ok$Z9*Mwm!F4,L $92"KyF_@f3*:/5%6yd 5d-/, Lh4,,(_`0($X2@<>#KT] W+8 4i f;)$ !_tjo3-sl+,# H~ yH  U  O˜K1)Fprg^h.6$:3+ *[9*R & BF-űX4@S R>+1&i']2""|%^:ulvI,aԩL=]e ;2q :2"S Cp0 ?br 6O 6|^@; |\4ؓ9*'1)o}x=#!y ]( HZo0(A'k[ |[i3+r2  T1)] 1 f)YD0-<$^-3?7/F5s-!=A9*Fd93(R*uu1xN>-txn q=U9*nMh7lV~Nu2"l:LSnc93jΆG&eVd4$b To:1G+YP!Cِl>-;>43R)-#*iMk *;px05d,#':% @{9*iH] \{2# Hk_u dr0(1aۀF T)9*In". ѳ h#UK\9(>I,?P-<]T9W  Daϡ J93Ԫtyl*I "P3€4C$ŵU *3k3+±kA3+6wo3#$9*Ҙ E|c>-5h*#3U#S#9|$ ֧b4,Y]xE#7%=+%T\wC6.y8:Ljzy<v쑶4 qjk ?"p_>-nr n%`Dj<>mpU[>-m3rK$i} e"y=6^ѧ e^S|% I剤ܶ4,Hњ7$H-yF#E1 EDj ó 0 A?k=䥷  =yEs;7 9Jk 6χf-9*3>?:3/3i5%.VO4=.D̰?s+R:'+*WE4$$ġ:j n֊ ֭5@1!hX4, bsGJQG-3W i;y~WvQfLN f3+hRͼ՜#\2*%no#kqץ >-Qfʜ"n=6X˱<>SV?m.rPg:r33++_'$H0(%9*C"v$?0 Ɩ6.xwF  b37󠢲L6=ܑJؖ@(o .Gg2*2p& [W/ Ag:UF? ~]P1)w0 ,$s3(s.B?p9:g|Fa*$fV0|G>-f7R #d崻޳<>bLx Pb9ٞ75%b ~#a i\5$3#W(G)@WB"Z93Wfl #Ps *S~ӾM5HE_ 4$̘,I1!=W9=q7=3#xM{o m C}z ֞)33=*e/$T .|2*& 7Ap9** 89ֈ[r ?E=6Q0:;23s5-[X^ 2"K&=c6.MQQ؁ ~ TË<>#Ib&_B  ^\b4F<>E4VYt<>Rt?SCQ{xG`>E ?93+9kx80>-6%X0>-0A*7&/6b#.m=Z#,+ ,D~w^;-AEu @ȋj}|:19'na41uY4m 㔣m3#@#ν#$  `(S S|S7ٙf%+fk`L4-qH{? Þ=B ZS4HH Gҽe4V03#Wש*89.ь#ڼ%e cGuN:,}b$@6.l <%FQI;4$??+"-$C4,d<> =ڒ c-%eunM3+Oq* .!N?f@VQn>?ՄB)2k<><63+=s I>4w;N 9*vgHu@"{o A)"3+m]0 e dPU=4ak<>`D=6_y@A5%_Q]!U @\5I4,T-Mx_K^V~EyJMD#@-|2*>z)iu4&;i&$:':m23  3Hp 1%+:,.&u;+4%*!9**H$}:%'*$r8C $VvZ "uǺ  f2"#]u% xPo x``T2":%m i%C<>udq=:S+;+Ѓh?&NS0 ]z6.1z<BrB0(<1g2"T1?"'gQ4%u1ۣM^ c=+𪺈AK380WY5:T,Y=6؀R63#D2"@y3sU𒩹ׁIֲ&-F-'W_ Qy=<~%{=v. _=+uIzK>-r:1p?X[҈!:(dn92d1%ݙaa}apF˼l=+_@jUH IսB6.F~ DBq93CtA5-B:Q +#5z& -#4  4m .o]r*#+Z &(kXѽv>-&ؔVF0(&RHZ #~jFwy T*&( xݭ$06 31q5 EJ bތ  ˝4$Gbv=Z֗k=4WO 9[5%a ";2UKt}4,J!%$#T~!%-1>0<݀9*8684@3#!t>-5L g|͆5-͗Ei Qv'h ʴtĘhJĔ2*.b`3#ﯱ[g3$Seigh_ eOL%9*_ k]s0([sۛ2"U7S09*QP93O&N;EL処ѝ2*K=j~ 2 H%2"GY0Yw2"EOneA9*D'$?g9*Ags]%@j~ =1)@:X9e7;/&1>f#* /f6_;93.(Bh o&%5@6."hEl3- pb !&1)?ck,$a|3#($'A`4$gC+: HZ Hz$3+ 䝦O =4:d<>~2 o*ʇ59*ؐ Vky=4[ xr $^L7`93t*,h *O=:%93֫89ܱR+f1!؎1 d,$+ʚW#G#&m3+|p9*(:%5Ft<>2*@=4CaL `ܴ9*yMm5)#,];Gau<>@!::P2G1; \! ͆B#bpl#Y?kqP^"VRY T4C/ JM="B;i#-::,?`;pP )!+:/Ɵ :(wc 9G 6;:1,ơe(]A=$@3=#\:#XX_:3#74,"n>-" "b !b=kӒ  ~1#K6 I՟  g7 Z2"`ki)<'93{3#iE,OR py#)bD  ݹ6'H9*nqW3+ԖTz /-,#2O$ߴ ێ ݉1w#E/ȅ(!^MZ+l-&їד#"BQjW<>8/ϳWGǑ;%]0v$ !ť$Q2"i-,$:=4ܣYޔ oC4$rj\ 6 vS$,0hG]',$yTN$^y[,-=6(Ϊ3+膮Ϩ;)EZ9*퇑:1dw /%$}ڭX;|73#z>Oc9="q_>::;4m ^w0(lx5|\$-ky3hew3+ b)M ^2hiZ7l3(QW-lfM6.PR9PZfȡ1!GpU#F>-E)^=,@{G9 =;h@ /Qhq3+q$MiUZ.ֈ(?g$[+2.3#r*  /SJYYu|?*#ҭP{I. ͚҄@/q;)e=PD V~=4dz22*Ǔ b-%tPFK1,v3#Ti 칥͂=6쵵{I-#oH93:R\>-|ckB:졪`{&܍윱.N ljA"ku1)8=g >j9*~BL!쏓tQ[nq *$b2"$7z  쁦vv|jt {}!q*1!h:5w=4h(:ށ1)_tF#] ևܘD9*S]BFX`"&EX撼6.BgV^ AtWV @{/J1)?h7];0 >A,4ް2 =,aT=4;i.B&9敪<>7S<!5a90(3pO#)/b3+$Dk\U"-"מ9^ <>dv; ;1&ǔ:=4 ^{  rW  菿 ʞ'͇ gi,+k<>%FQNh2*8ް8OȴJC ob$d5% DŽ$sVD@9*9Bw lfD$8iU4,$(*#Ρ9N;)J|!+lu;|=6D:Tݑ m6.鼩rR6&fJ 3eb9* { h2"Eg 5 $=6#yNj6&R`8 #mҧ 뤹Jo9*ji;ɤ[$v <>AW5%>#67 #>[" {ABp9p&zp>-mr#m{g.$lH3+`׫11*_ph>-]ŽMX?6.T\}1)SU2"N JlAl<>Kf)t ?|)M >B5ᐃ0 =4,:/9`4"֋3+0mu++\7*w>-(g'93&.H %?V4,{ ?p}1)g3+WG0(u  W( U;'<6. {O S|#+:^beWEJ;)%al,3!8 4$…p5-|Zq9*Y-y{>0( $N3#]M]E-;kRc >-㿖t yF[3#5!FT ߱?rJz=4dz*=4\^ :j63d3+MN]c$W P(l'0(# D9 7/s"8K 귘5? ꮈK 9*Oc$>4Y@1;)Ꞃ.>#2C=4gMR &x4,Yȣ[. 'fꑧlYq $ؽV&)#;ꅍaI"#ώp9*{Jp@=z0-;y~%y>-x]IJ&t|1K#qsuc3#qAmlcn 3#jN0(i駃hψgy̩<>e9'6.bu,6.`=9ƅ :1]8LQ. W*֌ +3#Vi%.JbHϮ~^&F a@#5dƤ2?L`g$/t>-.P;Љ93";Es-#!gfZ3+"/}4,QY W$I"l Ag9(D"88_A&Lp#7L!{``ol/>4M_P ᦦd<>2k@JK0(\brs߹{'0(јUe(m ˶YpnM *eW܊}3#~wN1)D{;2m_]="魌( 3#ꙻHC2*Ighb3+k*ҶA1#ο($:[g93,6 [M2"VZw#%鑱j$ֽ8; P7R%Bo93邬;2. <>y:J2"w+vK  utrs-K&q^Zrw-#pOki2*nQ%.bՎe?:3bBAP`60(TIK+ OFE#M%c9*J5-^0(GRs8!BI*;2@ n!-%=\)ob6m.@"-*"t=+-S  n[O&֯= c֞x ^Aaz#Ps%&Ca9* 2"# E3]pBu]=6p?(` #nž^c3#gP3#g6'NW^t-R<;Xx1),=6W"|MWR\U|~MSvj R^O354,RNR00 Hgvb93@X$ H:")=fUj==X09DU<>6`M,#(QLC9*%Dni_K؎ Bt]5FA=+=f >4c^> M. zS>- $c 4D6X&-KI2"=*A8ǀ>-u:MR<kh1W=6Y:%筪@$窎ȱ3+t. s *B )="砌TՈj$]皌o=6瓰7q3=瓨 px $/&un 8z4q`3#Hkվ :[$~6" vY#t˟}-t+%ۏ5%o6&jI>fB cmDF* bK~;>-[>}y~~@2"[(2"SoQ>=;Nn1::,IS&?!ICInD{Ido-?4,IO<>=w+K6=-OaJ#=(&2#:S2"/F/q;), S1!*Ơ&6&'zij &ͤ 93%ޚ.nk"!7~5j9 tC]u9* &c8b Bt:3Sy   ]RFk#UӸ9*AXB/ԡ93Ek#By:d@X%2*,^|Xth446Q{4,P:26rs2 [怇3#݆3-3 n ڵG$< K{-ҴDt0(\FOZ93O4$Ɖw #M '1!LIR SXī 歋ԩ+<>樆CWI槾5Y 桃QB:1gD]/h0 -vza&掔daP=-惕#MD<>怳} }Ѝ@O |fB&{z<5kbui T- aw#_\bl Zw=ď3+Xs0(W p<@e;Q}Jf1*Oʳ Gd漶D"35E:'?>-1/H S Rl=4 Џk#|9^?cr+$\ v "24܍$<㞠"5cgq7/-ƒ YS hF}9* @KV `&,t xD%ޅOƕ:31!A| _pbIU@ =#'+LM4,!㫰S93Ø }V޾lL +>-峻[C?|+$`h֠ V(uqB<>%S!2*厇&I  E?H:,偹V&|Zl+A3#r>,Ngo,#h".!B8d@W c=a2S!_7?_I>BJXMj. $WJ Sj*=3+O1)?`&->' =t$, =^h4$;r^;? ;4Hk7r>-; _J}45J1A3#1zx5,$'aKp%4;# >Eq1X &l/ |h$+Ƨy&-Qj *n ޗ;2̶>-Oʥ:0= d  5K0(!@ h\On2Ր 93z2";_ iRlC a6 15<>ݢjM:,VD9*6d 3+Q1!ѤFF2*SY q侞T̈́]"伫f:伥~%&䷕3c.!g?4,rcD˦?p7v4,ͨ4,䧝_Rf4,䢧:%#ov&eTQj 䋾k693!꼍>4\C-٦y_4,>6.4;q#'t R)V1!Stl }C!0 wS.8`, vlA9*pp,soHq oY l͕dƴ="jD4=4c cY֠%h2*Wu T^2"PWa~DLL7ѵ.1!JқD̬b=6C gAV▂L>ӣI<>0cޟ:(/+rkv .DX4,.5=4,ݲ)!*ǢaN+*u]h=6(=q  !KRv4a Y93,ZT ̄[3+=ߺ  jI7/']N1)l3k.="  -$D06#mc$߮tS gk="ܢ]>4Lݢ`#Ԫ1Of;:Ԝl3#+ Y )t Lc TODÇ-5;:Ȼ=[O˨O=aq| Ʈ"09*<><('2#)OdX="K~7/$g &Жצ;)ܺ胴&tO#GbD6.T2GN + T)#"i<>㘦MBj:& x#N)!\aN÷_!0 [<}B,#tARun`}8];2k}E2*hOF? fDF$d}-5%^o;)XD;2V׊j$=6RJ\;OփuMhSb)*K%)KH&I `Ggy? FCOEdIDrn0(B4H+H1!=zzŇ 75pTc6 JT2G.{3>=<.m8s2".i׵%B '(2\FX!xZ^mH=4!z7$ y H14,Ih41)*b3+Do . \1!>Tnm6&ߓڴ9=+ի`]B2*ȝNy:v?'6.⾁w2*~( _|Ԏ=4lO ⵨L&GG#Q RY!>-l3#V0G:3⨱+⧞O 6: -3⥙ Z|,;)AJNU7. Z-⠝O4,a (o|O %@'⋸۪I&bZk=4#&*#⁉7N;,~iEIA=4}C{}P |^@ e=6|O@)> s7-<>j;gi#k&gvoHn`LB`!V [G5%Xyǘ%W0) ~7.Rh3>-Q|T \0(H0u3#Gfn{ƷD+$#C]K ?!AO]T =+@k>e1 > txU+#2EE̼/7<>+M"'#G&]m8<> 91ta:yӃb \`su BՖ9*U I 0 BpTE93K H")$1)"s)#UV{QA 4$R  P sgD@ f#&VU2*MN93+ϱM ]`G6.<"2"#G|#&T11!E=4#4,᷋qBQD4$Vt933+$M9*ᦰvW`7/MLtᜉ [Y75%>-ᙟ'{0(\[73+uE&t3+haD6.y ?<>3+ᆺ < ~CaG3+zo50(wpW t`r^<>pĢ h6F>/^P_J9(W@I4bT#S7 Q,1|AK I1n?=?h`l&7b3o *3$ȁxm.7/f&4$/_n*Tx..#Z8H#y =$"*yNI2" L9*Jm*&:,#BX4,ni!G #5L3#O. }P`+# tȐ<~-3 <oS:3kSOީ3+v-UH#%&-<-nb$p*;}3S+lmrܳn%Ni'mvf3Y4$d[Q& #^2.q#\-f4,\AcW ő1="V#MT 6.IW2*IL(}lH1GSU;)DvtF=C2q) C7ֵ @Q)! > =#-ո\ 9BF SJ{=4AP iQr1![lᰈ $2qD-3%{KFQ! 1 ả/4 C*2*jD" 1!:9*l.a9*ߔ{*:1ssu$g ?Vcwm:3߿3cH-߾dw˚߽aY=߽%S ߺeb߸*߷E~6.ߵaw6P߳,a$߲gY7/߮Pjj4$ߪBFlX ߧzttn94$ߣ9 ߟq ߚ-I;4ߓI* ߒ6 1)ߐc{_}ߌE~񉁋2*ߋǛDz2*߇Θ ߇^}R_%:߅Q [߅"k߅a ߃8Ћ ߂Ty89*xS wEE"tjnf˯2*n&9*mz!rp lFS; j;H4&-c1_*"aT8 Tsi[_Sr鹨sS-Ch=OiQaaL3B}a/=4B/J%Ƙ")84,7Rqel7^0(6`9(5f3#/X#)ChZ '4TG$%QZ$wj dG4,"K^(|ġBd93{&o:k>&Ҳ-  c n3-##H÷93}(;2;{9 B5 m@0(u؁8<3+[ {w 1nZ@94=I.! >-l6>-8da4,7Dfk2_:d+,#=E =&=S~1!RW )V y}"ƥ!lۘ' y $޾SB ޼2+ 2"޻Z@:޹.c(3+޷f(޳t%G ެ!IxZ ޫ!җ ިpSr4$ޤBIr2*ޝP(oV9*ޗ2GޏˉHޏ\C  ލKox ފgB`=N ފv>-ކ#?ށ@{SyZ"|‘HXL=6yY{-6uA_|!rX  mPXR>-l` q$kbՑ1!i*ѐ kFe읭y*9c*aQ 0o3+\1 1)TӏvSI< R>!1!PW!4,PID;4MFh(0(Lc3=6H0(D2">Oғ9>CHu5-:OHk'4PRV2McV3#1gp -;u>-'EDlP'❧6.!ؑΉ w1\'9* g* ^7:a;$xy3+Gh 6&E<#-~ Tv4$~4 ̩rE 8l!4$C鬤2)3$+~B"=:K=4Yk1)u{{cMٞh7b>-ԇ˂2"=6.D}ML 53)fܥq1!68b>*$;4$ݾYN'ݹW٧ݳU+> qݯybId93ݯr@"ݪ5yݪ4a;:(ݥWH#ݢ8< ݝK &>4ݛzPDݖ^>; ݖ TݏFn?!݄c"<>݀0 ݀$ ~If|Ch[9(yR%hx8ϰ=4uʏ|t4$s9adZ!pJZV:,n;C$mO, h a^-#e[ c-P;)a]֢0(aA@a,W}:,a#9E$-\>y VvJM VciqVؔ`;#R?F3+Pey΋L74,K4:1I]金4IX>-G3h>-?B=4I].aͱ띚4mxvt0(PvkI9#e>-ܶ#9*ܰL]b9*ܰ70 hܧ#D3b2"ܦ˰#ܤv3#ܢ^NL(q%!ܡ8"ܟr5-6ܝOd3 ܝM=6ܔ6=-܌ *܈"Pߊ>4܄1Y&܂S~w5%܁!$*|b&" zΣA~* y*>BN2"yx]k-%olez5#a#級:]BG[ QY;bGG Vg4,U?Ot!MR^r<>?n A5:?]*#:.]>-:#-̉=68N29*6NSr3T}o!2o-!c3F'?'X=<"&O 5W9 };#*$m9[C󑿨6.}+ljay#j;O4, s h!k&  V;22  e(`7'Y'@ɦ3+y4-;v1)<܋4,nga-#R]o9*Iy9*{Dؙ"G*Ii&6/H2*_L!93՗V:d˷sH  l+v}?c$ `:"RuӮ ۸>~9P:1۲\>-ۮ> ^<>۩LۥL : $+ۥҬ.ۥBo ۚ>>^ ۖݴ ۖҢv-#ۑY#!ېRs ې3%hiۆ]쎟j69*ۄD_ ۂv졬;4ۂ]9lu=4x׹Rt3+x/F+02*wUgn:U#uZ?F t3 n(o<>n?m;'4,l̰F} iⲿ"i)Zë&-fCcWq; e(+$#bx2"YSxd5%XP X7 ,#T4=b LG8_ Da7'='&9uu=8C ]=460ô"3qwR; 2p<>1[=+-e>-&Sƍ6<>$7J[P|3#CKFKXL?*ԄS d)"C:{*#11AD %5# F>sVS:1Y‘;=5=4[`Q#*b,jAt"1!ٚ69x93ZI-81ч%.1Lýp[ s<>ڽP$T 3$ڼ V4,ں"ڸ% ڶ_ƍr1!ڴWإ>ڱ",;)ڱEF+uY$گՔgl=<ګ,zP ڡ,1;)ڜoo$ڕ>٨ ڒWD ڏy޻ڌ™;o! ڃք涥!ځUU3$}pg-0}F~ #Z#yf@ t΍Wt'r؏2"knQߌjG3#i0(gY\I9(dUP]3c6.ZEQٖI2"WZc+5-Tv> S]Y/ Qh7MFE_ϑ E\@L2*E5\A D\*=6=`2*<-(d9UK,-939)X2 77"6]>-49_r2+ 1)1v-*S١9=i#)'~v!4"&uS! !-ٮT]8="ٮdᤅ٬Q2*٬/w83+٤lGĆe7/ٝցٜOe٘tSD2"٘1V 1)ٗԵZt2*ٖzٔPF<9*ُ ٌO#Qa6.و PD!4$ـU< zJK x qt1#qn&p$=6n@zbA<>j g43"gQV9t 0,$Yp !Y8cY$MX}Oi VN-#SGT3RM6@f!*PE2"PM6.O  MJPM=6KmgpKK",;4IE>ňKo4,9X:6+`gKW2*5Pz; 1O=*80,a>-(%uh(zD&9*&>k%D|c;2m<4,>7  ; `Vp#9aO& vcXs1! __-# m. uK%ג`#2׃93Yay yW-#*֌3+HV0(IG-0=64W3+ަw` ۳!:ᇶ։Ԕ,K=4LV!'  euE93*i; 6- /nˆ3*ظ7/جb>n3+تh\1"ة)"Ӭx ب4 (أ&} ء ؝P  ؚ?C^1!ؚ2Y4+ؘsؘE᭚"4$؂5a ؁XBR/3+{=L ydtE|:u%'qZ#tsYypS_-oFa4,f %7cD7ccXu-cU2$_[,%>>-Z+7/Z1e XqWb>+#Os=-LۚH Lr X H ^G=kFPm:%Ee9*Cp% @g0(A ; >un=47S/D-6x53Ň=45M23#4eC2"2*` -7/0Pg-$d"My3"#x'-##>w?# j"~/p# e8x4,)9/"}}$' >N"#ó5  d%W<>s2Xc4fQL]#h0{^ ^K֚6.U 4$3, s$8[\-׏H'")׊hׄIEׄB^3 ׄzqū9>-ׄp~%ׁۏ0 ׀4~z28A >9(vkv A;-s9l9*o$&*gip h6.fT#)d} 2:d5,9*U!@ PP2"Eky#D|ߛ4$:S;6.94r7/8"\6T 5 aj{2$pWD1l930Όe =++eLO *rI&D4-w?^)!*A&! IJ'*J_ uj7wIcS2*ܛ*=4Cߠ=6VV$ Ų˭, 0l&lܰ=+ݒg+; 1)?u>yD:%%$hJ;)󄡘9*Mڼ #*/(}xF<>x9+m54$gqC@";2[Xq>-ͱ:ha+:ЌOg; ֿ 54$ּtַ}%ֱíb ְ:d#֬bU1*֪< 3#֨ȳD2 ֦լ8 $+֤YYM1!֣֝p*֢8@w#=6֠jF0֠A ֟}~՚9(֟aBѴ=6֞o=RC;#֛>2*֚ N0.N3#։2jU=4ֆ$1wyօ*$譩ց,=4~66-xbʈ-3+t-m$";4lŇA 83+c=3bp=4\IL9[;4$[ R&!! X+-WlЖ#V࿡,.Sx#S#!Q, QqE[;^ OҾ>&O)>1 Np)NP;T3=M$ϟ9*Mx6.AD]Ձ6.@Gi>#??Ζ4,;Yp  7pK934lu7/.i[-#.9*,8AĹ'<>"2* Ɉ1!F ѱ2*r۵ Al[3%] oUy AW&e#ǑG-#*Y3#T~vz@[3+ |!>-e;2ьb!/Qm1; qP2**b@T)#* L175%ԇN}82*{}bpj}4H:b+Y DQ0(ƯgH2 ë^%ƒUt0(3F#սCH73Q յ_ۇ`*յ~+p7|#հiZbG>-ծ-\A2"ի\·_=6ե:""բ9V`I ա`.+ ՟ZDX >-՜9; ՛ +5 1)ՓP26.Տ'=4ՍtՋpũ}'6Մ%}\&Ձ7&&#Ձӈ#(=Ձ?ш7/Ձin$b&ՀO?$|"nS#{h(2zF1)u\$`$t v1)rFToKzl͘bx3+i^͖Eg^ Q:;4dȯT&71)W,0 `C93V9\qBD V?·*Kn"J.e Gٖ2G#CP=@3`?$A;"6 Ln 5sN<=4320(3?&2"3\NǬ*.|Q[+$.p^k$, k8:%x* G~`Z2*.&h C%h<>?@e#λ3+ 9t$Q.u'>/ V+9*7~?4"<M` R%p>-~)7B r Hp Ek*4,鯚<D3d2"\+U 4+Y=1#f= .EƏ$,y 'i׸#[[.x6.!Njc=Eԯ0=4Ԯomr0Ԧ]#Ԣ7C$Ԟ _IUwzԕ&y$93Ԓ(b<ԑꑹԋe$ԉϚ0EԆ$Gc-ԃkԃ/A2*Ԃ F93H2"x~@7/wuD1;q*\d#)pl)Y0(lè0(d#ykbg`ē0Q_@y[@" )F2"Y~,9*Uq賓Sn#L;RM RY *#RI)14,L4; L3x.Kd F9*C2=4@"83+;$\ 8xR{{~./} )F 0 )<>q`6-<>$"o ! Zt79[3+-Ӯ xӭX'ӫ"z8:Ө"mӧV 1!Ӧ#:>"ӤHY2"ӤyjBu0 ӝ@֓9(ӑm"a<>ӐM32"ӏx%t. ӎj")ӍGK ӊx3 1!ӊJX':3ӈ=4Ӈ89ӆ{VksӀ/( rdG@,$r?U=6pH!$pKmb:. lHۂ`K3+g~@2"Z}%p=4U+z RBؼ]QlQ I8 PpRX9*Ex8OCo54T;!ADk;+{2aO̓; 1P 1t2p82"/ޓG .a #,Hq&(N ,%$(f2*$2"#F=ø<> m<=<eS W@ko  \u8U! ֟[ i!3u-vv; vu^>-7Da}9* CkOk0(l {&?S`2"_&Kl=6ԭN9 3/R4,Η]#4¢,2"lgK1)Ȃ14+<>Ʊ`>>-Ķ3<*MQ-;ÿhV >-’H M ҾcAy2"ҽ"V ҷ_[ Ҵ - !+Ҵ-o҂\ ҁGN=ҁU^ p|*STB,$zʛ393ys:i3#x}>ݮk u7*MtQ0(sF²G-#r=~?,,#pE^ \43+p.r:l*#h}7uk9*c.̖2*bОB:1VA7-Uh=4T=c+'S}؁<>Q͢LwQYAb3#O3N6XF09*KΨc [$@D"?U^>H( 4<>68\*4093,N,m5)J~p|-'o}%*#ʼn*8:™   v%a>4(D;4A靗L<>9~a'=4)2~즯|#)Wh[#="x;T <)Q 2^zߤ#•$,$ױv0>-ځYfMԿq ґup&կ3+Р^$U.32"Ğ8O@#jP-'Ѹ0̝$ѱz2Ѱ09+ѮҪi93Ѯa!-Ѫp͎ ѧ@Ѧ'==<Ѥd ѣkH|ѣ<=6ѝM b, ћWv]ћ(;: њRј(.Q<>єV߼Z;<є }:%ѓHmJ=6ъnDK9*ъ}@ K3+шn|193чMei*3+фu#>-уC9z"у8*="~W  }/* rCn]&pЃR#n/ڿ&c "_Fy"uq5%P}MOP8a$U<>Mv( L'DL:3C2ozF-#16{s2*1;@ɀ (v>f& 2 ZQ$Z0:5%#EF޸ !4"Ya:%VB7@:%o q>-H]O', ; ZyD>4 b$kh)G [H  (`/=*QU=1!1ڋ$&Qq.?es6. ff=$ 8 0(gZ!灁!0(6i<>x~eǫ L= 2*=A*7/<x-#7`Q}K&I=;he&a#$Ѯ.й镸2"зɾ1{,жV.еI!;)в789Я@] Э6aP-ЧKNh4Р>cy  О?K" 0(МjxS#И7r*4,Џ%Cx ЎtЍIb̧#Ќ?^.!ЌAn2"Ћ:r=J<>Ї(2 0 ЅAZ,%ЂQ:Ёl&o zSh #yDR v;/~"u؄x mcq2"hzf8#3#cJ#9*`:b8=4Zar=X dlgR]A&"PY~ﳨ1)Nw#4=M,Ȥ?+%MAL9;2Lk3,s9*K0^ s JpNW#I| ׍b<>F t1#EAJU C5"!#0 8V)T3#4V 1)D32"0+#rN4$-kS~93,bs+K'D_4,"AB*y3#盌a 0(8C`1)hԥ<:zc 2D1 t% aE6=<""^; dp5#.} >J(=*w2"lH$īo$P -[W1i+P,#P)9|"NaNoLz?p- E;3En%:pA^tIU@] =0(?&5<R73#:Ԃ~75f{ &7T$%qUF:$R_h7'!#6nkw62*Up2dؗP  c4cW*DR;  9y>-Ew<>aqu9*TSٝ =':16>-3RP4S1U <8;_ٖ G:"+4,磃J ~Ph':3(%J,$VGFJw4$n߇ ζ:YÊ#έ" )6&Ϋс6ΥTl"_ Υ!Τki*Ο5[&Ζn1i"ΖGf#4,Ε00!Ώgg ΏYp,<>Ώ0fY!΍s Ό^  ΌX)>Ό-VsW~:Ή%Q3#·蒪_#΃wD#z_Bdr ,\9*k+@Z!gpu<>eeѢ2"dt˼Z7m#UZ2\d7/Uv:"O#:;2M#AJ ҭ9V-#HAh4{93F($5E3#Bk:V@=Z@4$? eJ<>>y<7Ѵ,#640T:%3#v:31|.*#1QGm4<>0N:\=.<Š2*'Xh'Q#6. Ս8"ir -0(ԕY vo4z+$ =,VR=4 42{# ^O1:?z&YR e\L3#XK؇t#4"9}4s>89*ܴ8} Si_*#T9*9S3+v_t0(M@ڛ}[  P_]6.єfv)f Ʃ4 34$2Pi( %k!3$͹6BD9*ʹ-3ͭgE4,ͫVV$ͧ|F|1)ͦlÓ  ͢*5-͞i"͞E=6͘G:1͗[9:%͕Q']>1!͑ȔU ͋  ͋nz1)̈́+"(͂^4<>͂C 4z-sz?_=x2"p'I- pQ%b:1lܔ3#e =6d脵p|j abeM2*^?2*[#93Ycߢ?1)V*9 Ur> M;\Mȯ.;:ILE+N74$<#9E#4N7g6e6'&82*3duK2/gp<>"!_ &2K̆F7/?r>*^ZB*/<> k `ؿ2"hs ou MhF~3+eWC3+-%`.d$ܚbШ۫NU3]&ѢX;2jo;-'@2*u=-[,#W ̿?:,̿@$#̽Bx"̵pO1D: ̵yE-̰3֪LL9*̭0-$1)̪퀒v-̦ ụ|y9*̡K7 ̠m6GF ̞I̚":%̕mġ̍:G64,̌.:,̉mVc!̈"~P:' ")~02I! }7|C i x&5xx? xcIb*w0ծT+$w 7X=-`'}Q ^G-\ap3#Y&RV3#W̧Sf QV!PZLMͰ#L2x< FTWWxES ?3%>uw<>=.1K=y:P[ j*8F`ab:6Ԫ2*5-jQ 0jHV^0] /Yc=6+ ŖL(L9$;2'm6V1!%FO2"!z?* P bZ7/%nf=J;319*6.{$S_ ; vӛj#͂"1mV-#81!U0(c"6 {*ft!3dG1)+fޮߢ#guBFzy\n#8Ҝ53#9> ˿>H[9˽۹gN;˻1_9*˸}dq ˷g3~=˶]A&˶ ~#˳,"8*˲:S"}>-ˮB2˩nyxb&˨uT0(˧"KT˧i:QJi˦Ιdˡb89*˝,z$/˜c{93˖iX ;)˕gtr~ˑmvf%ˎpJ׷#ˉY]Ĩb#ˆ ; ˅<^0(ˀj7sѢ |}Q3+u=NEu9*t\;AsC o!~ _V>-k8W-#gp < fkejR*4e2#  b,uZ{EXh9*RLCOa$OGP2"FP B敞< LYd#97>-7S ; 3$,,#3 Ml0Ia.0h*Hpr<>$N/S3##Pv- &U3& ٸO:(Ņ!N r<;/ Q1*^w=4 $[&n ܙF"-#Ve1*`:()ıN5%vu9t+/[q=6|Ka&|U.'uqOq0(q37/&'i$ZQT"ݳ<>C  U4 K9,ɭiӟ *<>Ifc0 6ȇ^ ä埳+3#ҮI1p1!ʽU3#ʼq\=2*ʻpDtʻZ2"ʹr,#ʶ tXʵ6p<3$ʴ(.ɰ+#ʰ_ʮkC;ʥ k p:1ʢ:ks-<ʢymQʛ)ʙV: ʘ.('B ʒw9*ʑ[%a!9 ʏmʋX(oOOʆ/ƈ#}*ʆ͝ʃqpc0(ʂ<%s ʁ~1# z:1nLTn iv" i}Š<>c!Az#"_e8?3+[dU,,>-ZmFYsQd6.X-C$W[w&U7*P,S2\Hc43+GN< :ɖ#-9_F1pײ<:6 cI 5L[)&4XED:%3p  3mrn-.7>K9*-*-V=66Z%DsT!2=>-bP}\9*K, -w5%'“0( v93a& 2(6 @6=""'#8dLE;^)@?)Dk S=HE 2Ry0DfJ2"cxn aT*ߍMB'ܶu:AY9*tF׀%;H$), vnFH56.G!2"\93i4$X-3kO@5p& ɻɸ^#ɸCɫg}9*ɫx| ;-ɫOO06ɨab[ɧsG%<>ɤSಬr4$ɤQ\#&ɝz43 ɚRG:1ɗ'="ɏ]3Ɏ6[PLɌEMԂ ɋa"9  ɉ!ҐihɈ9Ɉ#f6.ɈI8_ ɈZ${KG mle4,ek.3+c J<bP4>-`6d,#_GZwM>4\KǤ \3膜_1!T̲6.Q{xOzFLW:1D^@9*C:p3+=6-#8;26j+#2i 0au Θ ,OBi93(+D2*#*[;)pUy(O`'~!--o0(493 9Ahf 1ؒTz6$sp A1 i|3#s!c Y*##}493OG  ]3ulR$]=4R%Mc Vl2*4 5|2"̽m+5̧z͕<>ʺrg1>ߴC,#ÉA1!=?=6ȽzB5a*9Ȼް>](ȫJ Ȫ(D#;4ȧ/׹9*ȦnRn> ȣ6!3+Ȣx,dȟv~#Ț W,:#Ț;̓E93șꮀ|*ȗ( =ȖzPW4,ȓͿ#ȓdɕ? ȏȌ1SI:"ȉȁ1aHȀ+H9*|Qsx|SF=4w !m 2"u"2*tsxB93qVgܘ(3#przim$ɒHl6 c|\7'cO&&Y2"a*/Hz_e#*Zd1|8:XKЊi X]H* Qi> P0n9*NBIH{J,GuFJ%<,Bį+LBWT>3#A"I?9axZ3#>5> 6S~]1!.#R,t *'ϔ$=4$+y)w2#Dd#n:6 <>mf>-};4 !YS _@"+R0I3#tY"+Nm --fL!G_->Ζwf>-#55v"]<>櫯*| Y+V9;&`>@)6.|MJ߿n=4>-б{<4z2"%w:>r_!#I%ϾUݼB`2*| @>!Ǻef O ǺdEe ǹm'Ƿ:w!#6&ǭY'<>ǤPmM Ǟl<>ǖ˺ڢ93Ǖ9H:ǔAǏ=0 Nj)bv&Lj#Y2*ǀ'}2*{+)#voy1)v~~-tY5s t{GK< sTosl^c= mi"0(l;z<|dTQL$cp 6.V,eKcQ90 E<2q ? +y6&>f >16.<{7/6R9*.-{=6,d1),] :&ۘ^ "M594+$W= 4,@o""Hnc n,$!2*54&A@؃;4$ծdv Me`2",z!9* n 933K8;xj9 㖓BF<>`6;3Fpt#B#TKN;&Pm="ب=?~cRhy=4͞4wh&2"ǁAx#iXB ħՃĄ;2(DHe oƿ*[-#ƹ}`#ƹQJйƷ9c+$Ƶר3#ƳKƲƱ' W="ưiK:3ƯmƮF;)Ʈ$o( ƭq.t<>ƪTءsv9*Ƨ7K^ƥ|w1)Ƥ .®<>Ɲ j:=4ƗX(>#Ɩzg69*ƒft8CƐ(p?g0(ƌ2?1 ƋEW-$Ƅg@ƀaly4,u~,8<9*tP9*p(w!h pʯ<lݙ :1dЯh&bC ]}!(9([~zWDV6Bg S=4SFS OS+YOTҭ+2Lд f4,LP2c93Ir$,1QI 6.EDb6.DjϹ^2">ӳ-=jϟG;2:jLd83?և <;2J5_O-2/`.u`,:R#,;#O +*'/s5%)[~24,#yEt#H;3w|:1S-o)br,ûH$H4, i  ɀ }9*Tec5-uX\ X3 ,E0:,DT  N2*]:VOz>-žJ{q h^,#Hf) 翓ƙL)&!]t"BܘŌ#Bc_ :-=}ź.deH=4Ÿ~g ŷdJO<>Ŷ1Ŷ=$yŵ[n5K ŴbJ}#Ų5}J1)Ű5K]#Ű Ů=Ũ2-ŧsW ťև݇^ť+Ts_"ţ tb=+Ţ3ŢdŸ$ŝl& ŝZ)E];2ś^@ śm~2"Ř`z(=+ŗM2v6.Ő+7/ŃNh3"vZY#vźuͬ!t`A5%r2*qvɿ93lE62*h7;C1!g--d{1AA0(]n-[#f| Y Y=+X•  C @ǵ>-?Vw 2Ѡi.3;<+KFn$'+g$]KPg=6X:36[ rA o q:#)+$-364& `3hz2*i~N )GW  Z≐Q@' ڥ#hs 8&]d9j6.Л>:1r 3+4F2*@wKd)T<>RUh%tu1!-iE;#o;$-* 2*SvT&0A (xɗĽ]$Ľf1(Aļ\SD̸>-ļ6;93ļ5Y:]~:,ĨsWy <>ĤH [tĤ$ܸ ģZ>9;2Ģt,4,Ě]܈mqĖpdz:ĕ_a@f:,ĔbMI93Ĕ1H ēr1DĒgrѓĐS^>-ĆKX02"ăOHăG0D^JĂ@Ăl~G_:,zlcA$xp2?r9(xBҧ 1!xe]!39*2j2`Tӓ/*(o'-&o+o(j_+0(bO |q]>-`43  T2tW4,YȦx3#j _]3+τȬmd3+`|~I NsE'Z :Wd6. <2"dtH qP42*0R00 L;v:ɯ>^0(ܕ4݀0 NE$-Æa 7/Ã]@ ÃZb >-uJd9*qЏ q͟q/2&n.j)K]hRWRe= dי>-bq^ ^'><߳{'.Tx wH9(=°93;TX&80R9*5E2%x 3*00()u,9*'"_X[*$$84"#.0oo3+"G86y93"/$x)g "Gf| _K# !eu  z\#$#DK]t*#Eۨ<:HŢr0(,E4,>0(7HHΧjfULv93=do ůg 5bDPM @¾[zU ·9|I&²,U3#°r=!1)®q ®)K=-#­y׿ «F#©tc  ¢6 HS b<;œ)!$!œAl-&›W>61)šؑE_7/šN ”X%qpŠ0:U=6‡x<>…B7"$xǛ%jJ7/w>3#r(%; 9(qJC2"q EW)=6pZ o.eoLp;2o n j"J/5-ed((:3b3TQ9(\\aV5{Q1ti>-IPy- EY%D}; <`!R7L6O3#4 t7>-1L|2*0Ƿ /{1Ss+k(-3)>)Ϗd:1"93]URS g>v>'a',7/ KF+  C^}1)m':%+\nT93ΦZ$+z4/ pD|-'^*$keT=+15P$MU1#8 fB;47bm-#͹o ̷s  HEz33#ö>:1¿Q,mץ0(`B>-aql99*C֏ 6~ oO4$* lw~'2O-q u*$J ?;)|,$:B$\ |SnUO0(QI9aztu .NXa4, J9*dA ||PT80{}M:%sKh$mfXL4$j8bz=4j?e v0(cXध  ]Fv\ [0=WKFSpP*[&>-N3!L2+M^\}2"ERER:,DvTY>>-DC<$3+?o| 0(>޼ޠs<>3k 2wwr(20sY319*)@y %1/N Xk:%>7>-h1TZ:3b3'= 圷u5% DOr=4L6.u2" DsY"FL9**N{[H G&&7uBx 0ʏP5D4 Q Vy3#.ޠB$*>-{KS ⍊+n%D9*^f1)ݲs!U"{O~ ډ _θs(Kd0(=<ʤ]X"F   :&Aj1!Q@qk 2+$åi=4Nx;1! Đ:3US3&6*J0ga +6 Ì" b_  ˷EG0}V]* Y%JNYzfoZ t"e#t _3sUx< rGi6;n eSVq9>-cX "9*bmy`eв%_r5493^ na=<\y [<;]7!3+TS8A]yRgVl9*O65LT"M`0 I0C$8[f3+8w+6y/^0(3Qˊ .+c:%(TS{ 'b=(71)#:j;@ x +J"E# $ ѵ3# Wok  UP3+ `<&&5 ^+#-sV>ɇ#9B8W@*=4 *Ï&Ll WAF:G5w-GT:1ߵK TWRY6.a2uu_ީ U0>-Տo`3*Ս)9mW,- 6 ] };)fxWd מJO=6zw\6.íв6/ìN]]3+B C2"$;E4Wz9(9>4 ={*"+uPׯ_@W Bs"5?P g;2d_})<2*'Y#Liƍ;4,}`;2io{6H4,x?S w8j/=KtٌׄA%qnT@D&g~3#eƥH*)2"c9\U:%E/-#[Я*1*UqdG; T/d: ShڿBO>J=+NbUNly M۞: MWr-M,ha Jm# ğ>4FN C5 N]#@̴W&$7:  5*:ɟ?%=i-#Cw%$ GS ,W60(#3+4p`(4%N(3+ވ2n߲2* zZ 7t,t@  qs^ .ۄ 4o&'D !=6idYi93 THmW* c*U 0 U9*/3#h`&1)Ԡ5y*&= B}Ӝ d#?.#㖁[ Zua X )+A_cʈð 㴛8IGBcc<>!=~mMbzW0(7kW Ѵ_Kw NsL<!KcN c5 I> tp#,ulwb?41)Ί:3~m&}#]~&{ F;2y#ά#v) t# b r5L8pHv2*hf?_fjT_M܆W xiS/%P &:Ma É"HhH >Au>-=w1lr6.= Q#Y ; kT: KAi9(6ᩉ+0(6"-;x>-66I)-#4rxis"2H2"20`1~KXx/.w= O'':<>e8er:3m٧I4| 2 C vp,$ i- Uh#1)aIX޵qR-@f899"! 2"C:1F*#D -Z<2" ܟ<>y4Q,څWql0<>J'2"րl1)!(؇9384$g>w=6ǠՇ(1 :¾5,##\l#O0(X5ώ;:O(G4,v c-; yY@(:,M'&:4"Q&΢37"Ji6.h om hlp<>d@;4/nE.2"%γ32"2HyZ>-=+wzA>;3=43Um]jaH~3#<2>-fJ$HO<6. 93 6.~'Ix'Z;:3v>sY-* t(n r_V<>kd1(i ^= hRB & dOdc7"\lnf93Z5쎊U6/P7" H1 Du;2D_N-pGV 0( Ƣ=:Ҧx= Iݎ7~p(sBy 4$4V>-?L=B;'A{|åKX ȽRuUN2*=ɗJ 3$:d 8-'ݴ;A93.SFN2j1)pR-g#`:(x33+]Lp 2"\ߎ9*;zC=4<:Y2w0(QZ".S=6~+jApj  }g=93{o3#xXw;=4sG,&pϴe&oL&$nv&mf#3"m6mS'h4{H҉ e`4]Oa((Iu7U: %:3N2fM;Mkn#)K_? 93Ke J"`ybd#DCT?XF=4;+{0 ;Lˆ 5 9*5Dof3yA<:1O܎7//h /pe&* ՛4,*:3*_i&*oHȃ '~ <>'@?#$֋xP9*4'>!ב`<>< 6.w,#6.ڞp#VMm:1iY93%u-3=6v+k>-e:ܩxx0(֥HiF#6,1!£F="x0(n%t 4$v9*sA9*,A63$*g<'y9usf-ã#?93Yեb#qrSU=<̟#; |ƵmFX6.aI4,}u,h{F#zbbTsnU5xfi E,bi03+bL`75%_~4$]õ![g#Z3,!%R闉-RhQL!w Kڱ Qo<>CWdM0A-rN ?P:} 5%=O=6=\$9HMݭ4,9(3Y%-7 l@9*7"7<`Ey*#4T!%U>-%',:t "ma>.6._i~g}6.3%O&k>Ήc;2 XK}w4,* &4$ސ٥0(Zzo>=+٤ mUw _*`/{:%f*$Q>=(I% iO:zH߹o,$n;7u5#,c d]`W3&*9WЕc9U93T%rqf@$[ٵ81)rE0 g&&~#$-;pz#y݊=6}~e % E2*\-3[* Zx]4$ #|K' 5@,%]2=4"-u ($̀Jr;!ˡ1);ri&#K7,$hQ]jҏ&BC?3#C&Pz *}HK |1  wV7/u㊢`t\T6=t-:7/hF3<3#g֡JL1!gT%z&bǺ{qS `7W /_W X0 T2`C4,T~$j=QWOt7 $LdC Kc !*AJ4,@Om^+2"<\pðy6.;*ZT'M<>pL:1Ԅn=4= #=lD  W3<> M5l9*ogT1!21wPۋv)ۋ`@!ѥ|ln+#V_9t0(C'KCn6-nbW<>쀻ya)24,s81rnvE JHJ.v$BPS0^O";-#hľo; .Ճq;2,v* !OO9*]rU2"2|88X1"5-1Ɵ綁<>ոǍ4-7`B !}6.-q 2L(0 q 70(gr7!lX#2*a|wo `&g<>`#:Q.c ^ɕh#Z =OA R;F*4)Q\Yd,N*䉻 20 MB<56 !IFZ Er !%.?OA #>gZ;d(7,h2"6W5_7} .Kɗ)%nK (W939@m0?Ox:>-R>-zcEyq$bF.a 7/ׯ޹q_ V| :.JV;2$,Q"+' Rak*! f,F0(^'s(=bcmT3+5@ ֣e2"U<ё0\ ޴qb4,x,8:O&WS ÊLyh#r4 XM5%ht!/u} GH9*aq;)ά=6Op.!I84m7ʉ9(.!`s] P=4/<cjh&{c=+@坛;)v~G*N$-s@=+mcm;2m *l [z<>^ WS<2*R ; )MZ~QL^i4B#J eUD,:%B=Ed ='g-L;<5q  3 *] 2i}*4,⯠21)+" wP*(TY%3+'FI2*:c3+я5{^Ǣ83+5B~ Y,#}3! 9* ,К" >%VULvٻ+0(̀ ]SD0 W3+w܎5,w}GĚi,$|`cJ&C%,+$'4`" &xW3#ct4,ѓw1!㕕쒺DᏃߍ;#dkE0(߹<;֕o>-Iū:?j|6.Ҋ}O#< 2"˒+|Ќ_ %<;4Th  'l; 敹; e L{Eo;;-YsBl7/F~m$ 9`];2 ).9*ժ g> x WJ |;u 9(aɺA<;؋+Pi @ zK7 >9*T>6.w>-:pl- zdi1!umk mYagQ7Q `0_|-3_.Qo> ̬3+O~N&=6H% \CT#F1!A v<y0 7dB0(6?-:|2"2}V 8:12%N:1!1 1i׽.|93, '(k>-$ۜ59*"A|O>F<>! <}"6. O>a#Z  Ȗ?1!݊ZABne$Wkv d-&4,=+V9*t-3*6  chR:ɗňR,> \0g;& *5Ww<>{2*sBYNs݁3 Z^$`:tj0(͘n6*ψ&c擨ƐB1.-#QwC 4,=+k"Ԕ>-l"|¬3#Դ+#'%l Ov$c-ݰ~)3+F=T>-"=3#1)쁭p :x*"K^,0(  }O|ur0T3-yi+x*/hf4$x:wxZ$twt;> n#tG>Fs+G% o׏ud?;2nUW bYh;2]y=6\烣4,\ q86Eb\2*DCԟ/ A]`@<1n Uy93(;Tiw9*' c-1W"XvB,$! WAđ;)G; X:lB+9*kgBe86.1*h-<:g  u5?,$ o"=uw̒@$c*u֗93B؈g 9[b4,ώS=5%NTT4,)fi G⊊=6.(B!2"b Hz1) uY89B H%P!Ҕn4=6 g6;+Ŋ5r>-b;;ylv ?,srσ~r%! ě4,}kq@=4]- x:s2*=$t-# uWхp; 4}=<% 3# ,$k &;)6ʗ:,,*4~y-x^N ~a,[!/7/j%'<>hF҉4,_ٝ_ ]rKD$ZNm;#YhW Ydq!#Y7j2"Vx:1K\E`mP>-DbW;)Aar93?~oz=>D2 < 1Z <(fGh< <#;(' &:Е\::4̀%9*:f =47תPB&-2#T=:-KK7:( 9-&o t Dӈ-sdG0h##iJ1J)ry <>ƓG4$Q1 3=Z(1;I+;{ s>-^Ǡ:1PUv{>-#_Z T5>4 h4,X!,w֛qC'E=,O#L- 0vi:\Ys ̃#5tMYc2*T?QJ5,ju9(B #0xnJ$#u`RGī5|of3+WO] ~1)|3JkC%xؒs {#)sӱRq:1o*t*j"H3#hGZ gre=6c1)a9B? `SX^jis=<]-YYV,#\20(YG%./'U2oZ:S׷0~;2QY@H824$Gp;)-"E :?%I3+IiEo ez7ת="2"Up>-ߴi^#ܞՖ-# B>-ֹn 7>4i05OΠ 7RX&A[_XL=4NZ3+P=` lT; :0("ú: ei5%h8=+=𵗫4[ n6.'g 393^81?9*mܡֺ2X93Sw7zR ؜u3#yEIq7/3+}SYE _*$huF ܨy=za Pc;2F3#}B榉<>{8 { {BR$x9(3+xZyt1=+uA S92*s(P9-q75e9*lSe63=ji%1gJ11*dst{#_s*^I^f{[:a S=Xa6.O^g>N Nzym4$N$*NNjR<>MUt" IS F"I=`;3G}sC4$B܇}N$AZ[ g93>8'sn';ץq=7ܤI1!6 3H2".հxh ->ǟ 'tS&%%-#.VR=6!I A펤֛6&3Lyd9*?`0(Fi2"pe ,=4IZam9*@N;)6 d:1Gz t;2~ k-&oHR}; 1c^NmGY#s|>Un4*1!bT0@M։2*" 3+#Fcӭ0(0E6^9*X"YswG:oy3(*=<&e}N)n vN#gRS1:,|Ί 4,m!  \i  OZl&:wu 5f'`/^EC0(ؗ<! f~;X !n%-w #w=u/H,$s,V!p( hO“D g ʑ_4,gi{.7/`q!)`lB_[ ^D@߈3#XkI}}L O -#NC<%4,MCLE=Ks:å}@#_Q=4@oa^3}>/?yVat]>-<,vd ;؂,6-:6&3Ђ?8<-I;!+HU6.'!qd*# [3# A;m<>2"q2*5=ZX)~7/yɭ=6ss#{CW!1` lEHeJ zS_?! )=23+ؔr3q,Soy#B:,ۘMuh<3#3n>- ZGwQ$jna_*C̀&ɰ-Q_mI3*:IM p[G&mȸG4,h7 c /Xi3#lc+}1e :1aY)vR)=7'[>93 bָE .n3+N< C ~h3+^l0(w2  QǨȿ3#t:3'r81![m!!ep K ѳ&2*~$:N+5-{<>z+xrސ#w>5h3+no ,x;3j=i£M>-c7131)b[ u-#bg-dZ2"_3J _ ^SR^[%Lz<>\W:w=UTwFR+;) JAN{:GÉg0(F89\3EP (?r7EI6.;T932Y,R5/A4}+%HL:('ik=6%Z2E&#"#" dS4$cka4$ N 2K %.KpLxKX$פ5L5%DX\ppW5%{nW:%93+ "=`2*Eɷ@4,h0^6.K*#ުPX{q j/  wOܰ˭93ؾӑ l\Ia3+S7 :,XqWPzH>6.^cpJ=&"y& 2%7=J/ ; G4-,\>-qaKq8.d" ܑ6A<>cQ =>u1> :1R"XyI ="")xk8>* |γ y>wG<>n6g1, b5#C$a-24,_HRvd0\2+rhJ3#Y ®MX "ځS}q Q;4,P꯳ M5.ʏ LB~RK0_L\2*J GƯa9*Ab0 **a#*# E'j;%6P'#!H>9*.YJ ^Op`j o 9(TU#) Ҋi=ǃv| ! \I[x0|E2# 8*40<=G 0 "85&3+w4,MOt=|+ y;$vX* <>qXhK"d-k c'mO•F!\l`Ug]L7/V3$Sc&U?JS-1>:Rv`Q !nr P=WGwC`J2"Dh_<(#Tz/';Ȏ/4$9S(u6.7<7c* 4 -7v&+. Gg19**WG&3P0(é[[iEƌ<> b- 3( -F!qO<> v# ldj3 Rfg#ڴ;3# ;2*ۢ }a>-ڜh-ʤ^1)_Wk:1V? D#,4,  a:%qs*&q1!B.6U#]5}!*ܥU-#=ȐASAwr Ĉ?  CLo g H#Kun6.+/=~!JZ_qn =6T?L47/Hg!>-fݡ3#`{2*N'*1< `{v168 Ol6.3O6.<; ~ 2)(1~G,ٞ:1g-'>/\tL V)3qJ:=-IvO*_ I*d$F`11>-Dћ4%bCst*?Mcx%4GV*3LL-H:3/&& ~q9WImt*$h3}#sf  L~)ey0ڡ+t_ns u>-^$ A4,#_Vb9* ﴴ="xjK+W'>ۉ0<e~>-ٝz#r!^Uѷ[9*uO4-·_ُ5%Z{v{pE5&`ONW/ E 9*[o13#ţ=4B)*&-KRE<> 9*2*N ;2PP?&(k*K,#!f.-N Ĝ9*=4<#f/#eKI4$݉'$yf Ǧ>-{vfF gH="Jɷ$}\%f{KԐ vm!4r*s3Kg$nv Ӂ:4kҟ#j+N!j;3+j;Y1!i ':,`f]oxĖ(#)[I \$,ZUX&c3+X~YJ}UR|& T$`1!SJE St Jˌ]G93Ju<4,J@W#Y DN<4B8xaA%9vI1);#Qs )S )"Aa Svf׏ #5)eK $ʼnd @W:,h(# c9*LqDw.^ *d!  B.0 akP5%?B6.>89A6.٪9*0&aq;)'S<"H2"mPM22"'4K nW ^P<> "@ـvp0(~#=49z[!hIB=4;0=Z!%W=6 ^3{]:3ƹ 5  n4oATt|0(ډ@A13& 6&p)) Ɗ_6.ˠ}%<>~Z:jxIR0rl]9*u?\— uwMGsFK  rejRSrmHG qnl:3l܋hU*"i2]sb=b.Krx3+`EM=:Te~-;4M«Fu2<>Ed،=\\7/=k *;-9e95*77\;7|F<2*0ψ[7/0)xJL/C+&옴z)6.% /c2*#G -!Lg؎z6.7)  K2*9ndVwK=6'aO2*11X>- n[W") 3{ g/VX# WKp]2"js-@a ـL;44c^Z RAx0(0(ǏS`>-NjZqc4$f6ދd[-ʹ߲3 z4,Ȭ2"+%<>3u%ŧiL! f0(% <'dJ0)#{nߎz 4,܅#SP4,Xdx935 Ҡ* \#:%vy poV}2 2~oÈ=ѹ ~7g`4,zߨzm2vƱd#sYͨ(2*sPul->p2"g*0d$*'d-8 UO"bF*4_$~:,Yw1!X[(Jd*1)UTh4&U;R(=6O2<>$:3:J, 8pL~6.8Զ2"4ҟT($b5Mhu"G8o2*8*\d/*mF8 ꧘`<> ;4$:1 s*l o"کp3P7>9*{*9ŚZ9(~h_a{#Xxu:1;So0(Vx6 ~)i %=/.'4$n[3+d~ >-k 0y^=6~4"l |?6( |n2QXv(Wt#qnE=$-nGÆ =k>)"#*0  .ۙY%.(xS[c&_?H&$E` [j%5%I'.37M?0 !@2":mnʢ BY/,(> [X D29*ajV9*;:p;2"o-v$3=ur}#lj93hMz1 epB=73!=44y9*33R<>2##&0(0Lq1!$PI5|0(!Ekr="Z:@T!*8VЕ2" xz';-^R;Иﮜ ~9{l:18rr+ [hбlNj&N58Ư{~1!cG"@ K W[lJ=(7 Uq22-~*DYCl һ?U{6.G'M>ΈcjFoW%:5,$g%So'mc>°j (>-bsҳ0(g۶V\ ;D=&z['&7u(<>|P-N #Kp%>J)3+dq*,$O#)/B6!jUoz:1z1)G︧z6.g\d A9*EIP -~4,}$@=6xpMS< we;)q5[m|b;3j25="i I55%c-_f!bp]&Qk#Inc+#H`fx0(E$p9*Cٷ-%Euo-(;)Afu `->4?%Vb=R3Ax :, T2"(o\gyj#(J:1nx*!$-#됐>b 2A  SG +1)x-n8;™y%i3+‚#A4j miX@<>VACx1!X=6{3$pY` 9ypP9(Mxw2"{c $c |2*eXY26>ڟ=4}V]Ҽ4,u;Q?;93b5i{*"ajV'ë]Zf>Y ]jA4,Z&;S9*YvBW93PBF5((1O/n^4,Lc*н4,G #R2"C3%A}מ@;9;de3+:"H :}ٙ>-8,Ϸ1;#2⋩-r,#.&D2*-s% *JKgH3+"R"Mvl3+ʮ5$2O[-q3#Y* e7/ ?c Y|'&-~ޑk!1ǎIG@HbN=#E  >-|>lx<>zm :Uܨ q!<>^:v= Ss2"X}&-G?s3#IR=6%+R+-3^ =+x*+$5u7'9*Iٸ~1/ u$ vB.#)̗?="yv 3#uf0w}=4tK1H`27*G_N!C̲ ?jN; =Ɂ:=<4j QG 2 G+-0Zsn+.5*jbT! )('ʔ#*@ŭ$hiQ93g}?6.L+4,B%;)  - ;Y43# zt=,# ?ef%m8t!z&Å N%F` tVjs=6ב. mUA.7QpA: :6.=¨44, hx2"؋5 ؀rn}#JR+[^#Ψ s:+#Q ~E3J ÍCJ$]7+$N5}$CfV4,:"X6E<:߲jAu $ N! BׅH?.8#2" 'iNY1!̐0 z%Vc"$(Y'2" CS$r ck1W5X#xӳ=+|o8Z4<yzY$y$' qq07qja`E=g.L0(W{v)TZCJ.Pv=6K8\U4,I* HB FXZ}9*D1b4$@c@ .d?޺-hac1)*^Ɣ[()*' y!&x4$$bfK;)#@=ր K  %:1P=g_ y M5# S  rL>1)UM[3+ Ny"+~,ß$} \#F Ro~: Huy>/v+eqEj:v$Q)k  ڠ@F ǡ@ -&εď0?%WphgzU6~}ܵ(w#$|1O Ҧar#^Oԩ*"_% 9 ? MBN\n~ 3+$1#DfKS"άFVE5S-35؀ 4$@{;3[{:V dm\ >Q z# T.m6je:,vA]RY]\2*l[<>}@$zh#J;ydxm$uVm u kok{1!hVC=`:1hS -3eE-m7c"j(1baea֚5(!0(X:  SXz\A2*M+q=L68z0(E+DXN#>lM~[>O|O93;.86.2l 7/- sD&-(+̼4$&h0d6.&*NfuM3#&a="%}t^"M2G2*_W#bk c XP#`}*"93o )4,$\-t4 t?`#noqG,W0(h93/&SE}zVL-6@7'jv HT~2*YH !1)%rti0DI&@9:r 4+G鰆(*{`y^dz^6;4d% ַ6/s  k "չ&934 [/q3#uwhV'-vEۀz-b3#Uڛi93nD +[3*6.j!>- 1|S "If!Dv(,d~u<> p4,V] , ?S>- !8}{U"Z{%kn_3!Ӿu/hqnV=6oG &mi§#aשFT-3_9w#Z5>E WX^6.S(3tLRAOm3 <;O.:w#Iԙ B0?t!5 Y/#.ᦱP"->g *u^:3)ܪ9 $-&"=4"8'ۑ "X~o04,=]3#wy>-zX2*DZ y͊l[ek);2 Km"iH X .Nj=4:#`%#)-4pX3+'3#R-PO(!O~R\_l5%֛in;ϐ $u/m$t{.@-3]m23"ȥŨ2"3S<>E:%tnй1!%\h"M-6 2"?#*#Hm v ><>/, 13+RZ M&*z&5-%U0(Ө43+8x"Ly:3G&[)>-46_G#q{֮Z2*z/ k#sG[!U &-z4]~6.wB`н !poXc#h iV0([ 04,Wv<3V9դ$TC\]P\. J~#cj="H[18MPi2"3Sq{/ɐx6./$AX3.Be,~)e̫ͫ (f{('OLcSc,$!i=" ΄>--.:+~-#  ֲ3-/+=<0=4x+M8Z' !*Di]Z4$ѕ-:3S4qvd c[6.cb* (–&1!k)B`K |7D1yctH&r(i:q]*e3 =e#R=4a2̅ __3)_3j?>-_!> ]e-F \ Ҡ:1ZĨW9*ZL+gVaNH7/U[R7/R"N LeaDuLp*D &C_:2"A=C -]-{ nx\P=4e|93!>-+K66<>'Ii 䛉{ H%k{,#Ȝ^{|,#ǤߦrL>4[5\N0 |939*xkOD[&-ԜjRѤE">V ̏wXrzm Wzp : P`$Ą]DnmsMà}6 vF3+T9l tCF!@-.N U%`r4ܗ!Fؚ  $H93 A8)3+qutlR$ڲ`DY$,(+# ik +$E&j<>{ƺj ,#z;Af:,sTh؋{=6q0 pF͢71!fq<3+e :<>dVfba==R5%]:>[wƔZ?aeV?24QLJMg_s!*JeSz] 6.D:ж =A٧ >N+":1Y21*8"6o0!6 13珗=4/Rï:%':v<>T܊6.B˷ $Lg>/s!?7/ i*#R7\3#n\ )a  plS^t+*$Z3+tf gV`{<>$"$h/  /;9*Ύ4$*g1렶%Z.4, =6laN ^A~X.-#̹:3 #ˍ Mz3#ų/ԚHi4*Dni{1!wa Ӎz xt<>R,3+ ORq7>-I0b&_e=W 9*zYlƚ:zO y;z; vk{rs q9ȍk- q$o1~ jF8Zhdf?7Vefĵ'-3dFwϻ E8<>BR2"B :p<>Bo =c3#-4Ḙ-qUm ,+>. =2*hK-Д?.#$yÆ Q4$[ %Y:TI$彜r8T+S 9*מvy`t2"A/ 82Ge/KL=4O(>  Odm*TZ ;ʳAt+*4EmF~k2*FEeb # |Z;#8B<>Vr8v9*`[r uǟ&Xd=4{ק>-Zދ2*oR;6.C<>3S+< 0(iGG_Pqo$,:Z?{J<hC!q|ڧ1!qE̱Hp}F`&o#[ ; k[s7/hsB7/[2bKZ$5T'vQϮVi P.4"E&_;&@JgE:"@$$mR$>PR[ ;?.w1)7CY4$/Q.>c{3++q[+-o&)Gn+#'#k4׺$jd ÿ ^V<> KHTr$ȨA#B*p<&O_kqX'2*U\yLI6.VN UoE#w;Zn0(L*~ 3+s`HH6t2B=-PH Rݣ=":j+!d8@$ ?j |QB {$ }#*{KLWj2"{b0 v<.q2"thqUk*#s>ˤ*n\fR؞n;=#l&q%iXBhV2"fYCmy>4`O"=n4$L LArlTbL> F0(KS$3O"IS%  A*QC :Z._,8DE 3,\s=61.X1)-ݸ#(sP$' :J"$JB k1)m<'Lhq g3+/: h8}>- 9* +"M# rɨ(>4=Vژ4+7 T>bdC'g_1U<>[V&[B eӮv#&V:3w="ᷗԹM*ثLj&-eY{| s ėkz6@|7BtbV\˜o5%}s&T ,(} qm? 芶#)k,86.I-q.4u7/ 2"K3+%29>-mЧ]DnJ:3.fq93;`F[,1Ug=&mI1=)T= K(8#h =4=U@@ 5? H; >-8ϭ0>-%޳}R6&ݮOu/b }%d#D32"ю ?nh"ϫE2"[5& Fy}r 3<1;a :&?] }:A_=+: ;sS17/  :xW S;`/Ό0S+,#ڳ>/Fݔ<2~=6OC<>Xi&n$ AIS/jZP yw552*uwE ȑuc1)tcё^>-pª0>2*ls:'f.@4fN-c94$bq<aꡨ+<'aAZXF&KYcz =6YBXM3+Q N L26.E `D 2"D-3!;|0(7p/`9*6۱W3+4|ZT 3Zd4,1`wI4$. mJ`$,,ju>Km ,˟tr=<&Dg XR$a3/4dx#"w$jd: Y1 [7/rgeq , Pk;3 } ; `K0(fi $:u h 9hvKw+1aPP9= Ѡ,LG0(v>e .$7[=4粻*"-~Vg4$ڽ,R-0(`)%3#x=6܄"%3"u%LbR1!DY*pm׳j:3_EK@o :&=-lU6.6+|.$|5GX $-zr| m:2;MkqKjPJ<>bwb_59*b.IxAaŠe>3+^7=6\(5t X+T:џs3$T:Ou5%T\9%:$R·>-Q*VE>-Oi s|m KE'糡*"Igf&4,@aM%X,#5bg08p:3/RK-TF~3")&fsw>-'@ a:&$є1 $ӟ~ǯ;) iLը W%wFr CX+$"f xN;+ VI(2" `Jh2"C9"_fl9*֡3$2Wr2A Q!T,#z~!3Pil$m D )̉@^%O6.5-'O#äpt 3#KjW12*/#$3"obk* A,.n ۙj_$ݔA#̔Ǵ=.DБ )6 f-(GX} #-'Q?i &jd=6$"9="S[.1p$} VDrw<2*z_8& m Îqh3+u>` p93%$ ͝T.644Kv ! gg` Q~_C S.&r #v]72*ۛz[ ID6ؾ;4K驆az:=66.ƾrhg đ';4wkgn r^Z#\3Y93_I |CWV3`*$<Z j/g8(q{d *#Q_-!o($ }{_ ENJ”,3#8YH;3#z;2/ wJA"q4\(=4V&P!}N©4$Kh#52*I, sl+9*HyiQ!ED1ג(!Cu }2*Bf 3#7#}TVl:35P5 "3_1)*>9_#4$%Fih !t_q  `! t^f&H#&:٧ _\s3+,# t_<>&GYF2*F%@ϋ3+(ygv"ާcr9**]'0<>S9*5ȭPn/q ;C4$; hTԪ0(tnK1)ީŋ4$ݓk[!y;9*Н.g"*, 5֒0(!Z3 b$ Brec9(>p&L<3=!;4$>2*4ԛ6.K4$pv11)?o>-A.?&^CU6.bE{=6,.3P3+&ځ JX(;)@ #I'3#ٶ nY1!$ + + }5N6&wH3+G;W0(~ד}|{ ǟ[1!yҳT_>-oܧYp3m|n<>cx >?`c>4_ޭO \ 3=6X|=Wx7T0\7/UPUoCT֙> ;4Lcڢū!*G~觳CMU0V$;bO(:u* :3d߅>47l?:,2xظ7=40-A4$/ḣ .q .Y-:J0(+V7I#+@ 0((gT;0 ',G%>-%ff70M9r!Cemx9**:1uy6.! 4MG9*I|ѣepz_5,#϶ڙ#)Ȏz :%I%{68 e/Yw)2",+6!s*=6rX N/cl-˩˙q<> f0:w|&U!a-2*w+#|/mѝ 6_K +)5ӯ GK&~@9_.=6y[StK!sND 49*qIw=+U&hU3+e-Z>-c2HK ` C2>-`Dհ^b=4\`w;_\̮:?>-X%P T(h!R?Xs<>MpY6.K< L#K- RE4$Jbu3+Jw ( ?q3v#>Kw~2":N.<>8,Q+/U2*6ػ2Nv:1m=.klz .6yI"!*-W )51v$(D $30c4,$zTz#9c%m"N\z<>-P#ܥz-#ZK3+7 :1%NT꫻n1!Y3x ޾Q:,|[&:<>}4}_D}7/D=Ru߯;2`&3#(v=2"{'"l2"P۠%:1! c!6.8;2"uR;2ܜ`Q Xnq怾l7/г 7X (U=#r&8; pO km=6G:m"؊)=me#t`o"ƻVԭ14, o)) Dy|#?{0w*Fx*dz6.v ;;#pOIp)7?pJ/+&4p%M n/D  mKH2 ;4h$[K01!c7}{:1`:zOt:1V侗2SH-MyCII9+5%CoT 0=4?:K;#9N b>43.N_v3#1*j9*.gEVS93$ά1)#;~s\2*!$!% >۬V] v^,`9*gc;)>Բ,P$&#Wh4,M&_6.2r1T:X=>- ^ˬG#= /2*R70(IB:H+$_^PDYB u؁9* .Ҩ eZ>~R#ތ0(8;1M6.G( q-MTm!L7ȏ| @NM ?2t/2*>37#6gR4$0Q;+.;Y 7/."r_3+)gYs)1_KQ9*( (:'e{pT &#Q|1)"E>!G_=4 r]s4,Nm_cd6+R7/y&$# :-# ?1) ڍV28: 7dUX2*\e=6E-N7h""Ȓj D 7/#c03+I8C$%*_*"}F= ΍T6.˃z13 J;v#| fv řɋu݌93Rʎ$E2"kRIy E"<!Jc C}v =;JkM *$3+`gϔf +JBh'1!Ls &-NI4p KS ` W- H=8:r Q(9*Ub$(=+)>"NH1!|ѧE wd*z0(v2Rz"j! <>gN [7/frے$5bC_&aX3_ 1)^Y t QK4,I2jE˩ Fw"i@ۣ| ? 4$-9d 8ez 0(Tzy0%ZsE93-f3,a ,u2(|j-#ȿGTp7<>՝'I$>S/<>\dM3+ >-u=+z3٦# ǰi1!1 K7/a;%,q?4,-Mc2")\ a O3#VIG1!vC$ 4:u6.dp%ڭN4ؚ& #aN6=6↙ 7tP<>#'  2Ԟ1)[tU:%U=e9* ȹ3#" /;-B J \ .:3+>-N &XGWY2"pS%\pCQ3#vQE=40xf9*85>-T&:0(wIC9 aq[ Z\?Y,$Vc2B&6-VGzV#3U% Q93S)9*#R#iH JZ7I@1)FKgk=4Bn>R M 3#;  8F6-4._K<>&U^‡ %#ᐑ=6݀6 [9MpN VuB4, T' 鈦 0Yo9(^.m9#z@72"=F4&5QU#CZKҫZ#̢ٜ6.ܦ䊲\ t+2"G\!gK ށUlã5%.\nK4$GkD(2&^ xunM6.rEoeY`1=Dh0=6b=#t]m<>`=<&#$ 8pRx2I u  tM\ qH)2"gb-a#`@T#:%`)np4-]>B Z9_OJ!Pq~2u K(G!Klmp*$IrdH;O H(GH: A)݊P!@h3*=YKPÑ6.:ȃ:#.( =9=zӖ9&v*;)1Ǡv>-/w /)TzsK=(Ms 'q >-%Q,]*4"Ճᬿ,$o?")X  I*9* 4 iN vxJ3#"Хf;Ԭb& 9*(M3g=4l* FP/5.e Z(_P $qȒvX=<&1!郼PO9*'>1!sި(=4ͅ K*$Yc*ډY݃*Okt:%Ч`|Z BQ1)F~%u^3#;#üD2>+#_BЉ2*v dAf|`#%Q8t >-wA93Qr(ϕ=6Y␩<>;21^q;%/"2"%2"R_] nɑ2+6,9*r,aX5`/b}{NK؋93 !>}7g,F-|t"x)¿wׅ2/ ojlma* gdjcix&Ԩ5%b9:;_F+҅#^l "F93] >FZ<ɖ&VtX=4NSE?H6.Gk2*@R5.1)@i`\2*?WJR;)?;<4w%z#*19*!Dq!:;I=6/'VZC'9*!|ɐ$Ն6._{c0=40eWph 83#"h*ZmlC*4 Xl  $B ?ЭY^Oc_-Pgns#omV6& IT3qG=;Rǒl1!o;:37/X,_v Y*ϒ 28:] >-<ص1Q47/v:wܹ:/ ʆՑS P9s.}j,#9*3>-LV]=.82?R3#2"4XM@.&3+|̻;I4,tiI }uɑE2"`O?m=6^zўjj 32"ώw-1yͦHy RAr;D]f 6ﳀy;Rm\:r2iT o[i2*l骇\jՁzK g9E)2"e_+q c@ݺ1!bאl0$ao.(~%;2a#*x\`VyZY-.)=6X64:=m4,J4~#JZ P;G'] F7e4,FpC Cwj@yL4,:Ŝ^0(5fg`5$3)%9*2(1393.$p;-|@{0(&dU  %l<2"")-!*@T#,GAA#!ێ"Z0(i&|l=9(W΢֏ Bʯ ȣ  |C<> 25% qw/1! t.>ih1)Ӗ}K2"_1u3+wiB:tYoHG>-^'2"$2@<ca&G2UD=9*n9vܨ[=6/ S:%WSPHu; υ4^?IY7]rbv"â5A1*V>1-Sb«V5u="卦"93a 2#V .}?$Ls  [SkXJ0(Z^T-] :3>9^b* J="%Ǹ9*/s$Ey-`PS5%63|ׇ % [b R6.&U935bD Rl1!tx3,*fQӱJBw4$9=qYR>--ĺu2"4N?Ok"|C|EI{essD qt͠Xp`Anz7P}*e@4 e'Jrbݹ9*\@y \744*SOѢDM&i#H[KD)F=l0 Dn%=-vz<>Mָ 3OmȅES:3L# %-Y[ɧ0(¨H`L`T:,34M }E10 -_E*_Ο,P?b[0(W$9k>-K9>/CQ"&Sv KҢktw ~1)|S 8=x*}3=4uu{ZVB7/swaTr-A kߕ2%!j=,=4d~`c_ d5#qbHF5=6[adr*4Ud"RxxB"4$QxMuY=4E#A8p3+@j[:,<~-::wZ)":+g,9kغy!8/Ocq7q&2*6`J2*/ + 3#.2"-Eq $'U)D $€BA"_HS7/"\3"<;!nR$jN65%8"%*$1F>- RJ4, uxO~ 1F:3g=!snr5%%0&^]-# OHL"!u=-ʡA;[fP;C Ǚm{w&{2"(RW0 k6io 豏+2*h7V:h?6.D?c3&7  E"6d#:ك&2"c/. UU9(y}iEB} k4 |CÁM :"z cod0x0@,#v./6&v<>sex#oK:a6.n7m օ#)l -1=6f?da㪝6<>bx> bnT~ az@>-W I Un93Ub ?n="SQsw&Ol Jv9*J[U:%H'(;-FrU3#D1ak]BkA?f.d >ê(g=">C% =[/ <<*:4,;*x?&8f::U*"7X 3F6&1ۧ 0XbuQ2-qP& (&Og4$'W>KH-#ߣrJ5#"Pʫ'2" y"1MRK2"~g(=484n2*:h=X D[W93y   i-%YߚF.Bj=4R(q(M*B4,(r$GR{)2*L=eWH. x% %V .^< yuӌMd9*=.1!EW ߫4|T/ܐOr5Z- 61!պ=h0F>4' O .i!HIa4`fqp $ξK)*By*$Ǭ~i3+G@m#EX9*A5E [YT4+ Z89@ N B1EL F5]9j&U9K!-3vZ:%C5&~Hw FHS HE~U  h=ß׵3+8@$/rx u{ +n`廨*mí#[~-*> 5%+0dj2*)P:32Ǐ=;2~ڠ~i {s =w|1 Ug:,tlű1!s4 pAKBjB1)fXZ#bLU1!_хy.=4\@!M]f Jǩ=6H^6.>x)=;R3+3p @2h 1N+;93/*s/fD,06r8,m'+ՖaJ l3#%>Ⱥ=4 Ye<=4 +k$ AC%r=+ HNL3+!u&y3+ocn iL+¹=;dQ JCPq2*G&93x<>r\-3ӝ$,Q|63#?=<˝k31!ɅK{{4I}uhZG"8<>na # $p,1!mh+<>H *4@[9(=+) 7' 3+v 59*o5%٧ QL89kc$$Qe*'"$R6.VR;+$yy[M xc} :w3cp;)p.r۾#)ot#t' h29#gGgWf2*fXi c7Z3#bGܲ<>b^vp4ZK9*^E(d:3\\~NAR2*[&vI9(Xy=!X={/>-QE ^=4Iv3+AP#-A;6=<>Z=+<'4 4;N%-7/2@ۉ  0Ƿ9*/_ʒ; )^aR $3##t(=XM3#,`~ O$<CLL&#M fI wW7/ wp>#_}#;L''^>->t="U3#A`8:ؿɸ$s yܥU,E \e\.=6KT,EGPŶB_'ߊ4${2"8M3[: Ґ*8Q9*Қ[$%bԕ VfiܦIܖo7/-`#Gb+2x %KK$|Ȳ0(`)t="#K/,$+з<;:l}-<@*xћ""v2=t,E%o_WVz9(n@ j%6hi\Tfj"֠B f` WC:%P#NI}w-HkZž *ECG)L7/A)1!8#|6J6 . 42Y#4Jz&.Zo93.ROwI +^W=4(7.b*&!h1)&Mx7/"UDZŦ@e0 x 1>?ʇM1) .[U {(E&# d c R # J~ t#f9(] : *Q!?q#OiٌG 2H%V #<- >0p9*Gg>4,[4,<;=4y'xu2*Zi6&W@9(ӇR&тƩiG& K{04t93sYJ  FDdsw<>hܮ1?:1T/u}#%X5]݆>-œ6.VTIΫ-'2@=+&"/V%2%3#jؘ@:,*(PMQ6&)57;2㼑 &*g>4/<>$Hٓ7J^K1-3I;.I "S:1!\[S*ӽ#I Ů$|Q« xJ}2*u?<>uhj8s JqQuR*#msMtlaeO6.kdTG1!iz ؙfD |%3+cXb>Euz-`9!@x#]-k8`8 ] :*$\Tm=X|Җ S0#R*˽RE:3)R|U[ !*OҹC]&O$!*M9*J?L'7/I)7/Fe@>-Eᚗ8N AY6&ʆ}%5F1d /.w#.!& -xC,+@ؙ )ŀ E&:K0:3"@i{3$QH3+gP OjG꺱F4$xD#"ՒH?.ƍ}=6Ylw'z x93+3;i  vo#+X?!dU>-hd2*=>-(^:,ਠ7+D0$0l lOPk 1!ް2* c7U[v<>Ү#щoD="Mp+fa$ɑRaW !1O@ V1 !*>#Z5 7 ߔ6.5rf>-(S<7o="6l *}昉v.&aG#rU:,ߤ!R6.y-'#bdA5:1gxO"{\3&j˭mԇ1 nH&=4%;5j7/J :,XP P~1)/* *4P$p ;*4G"#;%'b4,9Ӆ"(9M\w-RL (a:3&oh4,$3 t9* $X]P r&$>-4,&&˜S?8}p /8FA %1 EZ$ l۹RM&c{**RҎ>-gMp WD^ 䶧,~1!+uPD|2*ݏ˕="_`. ~NLn* p`yU="~5s3 2$F Wb"g#>_X'Z5%kש6=6+P&|)F="Uo[.0(\Y Aa$P ;3S>-^ks!#d+2b F:35 B  -lů LP93ɂV<:1[}; }̒|#zPC3+yA#4*wGTwEL" sT.$mwGB0(k8bK@!)k{y3+jl&e -ea S=+b^ʂ3+aSSG9*[u =v Y }4,Tua?>RbA R=LhOO,#O2/>*N$LHNsȌ4I p^6.GD,@LF,  DhQ;2Bl7aY ?:<9H<#  ;C0;):f!:-+;3+6Gb6u{2"46K"4,49*2&K;2*0}S7/-j24--QQ+5tB;)"|X*~V< ")zjf2*HH&r2(9* Aʦf ÒZ^;4c ? ." B`/R[(2P4,hf߼wO^2"i&;4cz2<>G@W 7S#?:,.Uԓ=<َ.$M80f1)!6.y>B=4Mw1)?;xE9(P5AD͸M($ܞ4B_ XPW:(l:1X\pǩa&>-Ų{ +Vց :z#=4I6N|=;  e=<%I#<7&ͨM^h c. =4<>Z=;2r + _f_{ oJE23#e,8x -Ȇ=6R~%zPH 2"|**[>6.qU5byPlHW9*doKd7 .#a3T$anU6_`i#_,{LS+&[J̕_P RR->i+!J}[<>I&+;4H5d_ g2*GJ!jEGwC/ 7ZbNA93614_D3+5l23[Et -Z"+@&*Q3+$='>- Qfn>-ݚ$k3+vR2*wrD6.{  LT'|9* 5ܻ 1)d:oE_&.U4%c( 9*,)qUDt:Ud&*#󇚚OH93KO^٧@2*Tp 3;S x6.ۀK1!كSz  KY64,Չ l<>Ѫrņ^SSÌ<>aq129&4hMq ü.zԺ mTD 3+rҏ{6.+ٯ%*Z3=RАt !@5% QkX=+3v~;2`8*p;4Xg=6PnB6.ܹ׹>-{,x7 -#{ie  zb|}O4,wlFXCvd2"jsЯDC iK޻1!gj>c'-:1ao7 _Y_*&_:<1)\1^Y<4,V$ȓ#Sʶk:%FMjX12":vJX#92*8<ߋ9*3X=z>-1`/pK'u23#JY4W0H>-ٯ'B~'G9*~A*$~T E h# y.ՙJ6` u52sS9*T)"yo*<4$/¼3#0<),*vE;) 3)>R;f=4㯤puwE>-g6m O9*ݻTގ*ݦ! s=X:3#:X!*ӍP=ҁ`ЈM2"10Z&σb}D=4iMbqKi ʃf6.P[}-ĘZ ).n9*W9KKiM1=<|З,"~2"!Vr] qz&Ql93-d]&װ2* p"5>%ZH fܻ ^l$} 3$!g SO?1*tuØ*:1 ,Z1!36O)蟽!UBrJ+8!ڰcr}#,=+x  IS oo &kIx2qR f5**V$9gK RѝUa R-Oo9DF yiOBˎG:pt6tjh4_6B'/ELQQ**O): (J{9*r}ݱ []&#!36 bY\ RJn9*̨u=6%^i/,$6-.cJi:,ud4,0W2*ye! bFDDhq* W0OH;g 2"u.~6.K>=4ګE /8%B 6b;N Ď&9q$ʗ#` 1)W=#7ى tA16ۮ _>)=6@& 4,rs"߃$X%{ 5ϐ}:1ʬ3#32D`93|~>=4T VlitJS գ:,KO&1)0_-Ņ:%+5%"v3# #r7/|&\2"zNl t:Aq\b۠-q_?F=6p̜m7/m?19*hh |3+c3!bq09*asQˡ _eD9"],h&[EWk Ut1=4TIJ T*h*93S0J\PnR :,NA, $JXX=4CYsR4v-3B(f* ATZ9*@ݕђ1!?T5XV 9*-5 i! V?73+;1Hy#VZ*&  X\ WH <;`2i<8W:3&zO\dzb a8dEφ2淃=27 à~ d휮ي1ؿb4,Ħ-TNv 9%CQJ\4,ӝF0(F PB4,uQFJ6."ג%; C2"tZ 6?]wcs7/ \3#F g:1~ TPx>-|} s4$npK lr+k,l/-j&i߫r;2f5߬ cع;XŏB:Xf_:*3+U()O: Uμ-+-SZ+|,$SLL<->S>?&; R-Mg)9*Kٯ1JH- Hg\;4E9|3+D ҷC} xG93B#b('2=69t26.5Mo:11T})^7/1Wq-R{ &(!ʡ:3!(ؑ wA od)8XEM  4 !w< *]{0(W⧖2* G~ 83# 0(O M<>L *"k-#l"!-k=6z23+k%x:Ww{׏B.U wVѝ!k k(:cN?=6znHy4-w1XI>-- #6.˖}4,[ ;-d5%$_7/du#ۃ=!ʸ^-L}0 3)BJ}4$0634,\;) O+-il E'KP"}9 x;*>"uA֑f m;w@"lrCkq6 kO0 df^[-_46J1)W&ΪT#UC/}sS-CQ3_{$MQé~;)IQG IOE>-Iμ6 D، <>C9*AOH_2*;#;-RM3 6!Xl0('6i02*&&P4$=:$ 2 IGg ~WI2j2*~%ZO~TLxs:(~`q9*~!gx~6{2"~2 WD#~pܚh1~k`c*2*~׊,TA2"~ր;c~\[{~XpC3#~R X9*~4-:%~m ~VM9=~6 %~:#-%~'(^\=6~V)'s= ~? (2~ٷ3+~3 ~go ~y'$#~4F",%~O*5~ i,#~P{2*~ <~%f91p4,~|3a5-~x6.~tb$~s$鰌3+~s9 c ~pf;=~n ,y<>~i8}Q[~ei]$7/~aP5P=4~_@ ~_΍_#~Wd7,7n~T:ť;2~N<7=4~L4a~LzƤ+>/~HY:saT:1~A&~=}Oi$~1C$*w~1C3h=4~.s~,D$~*7)!~'(o ~#[0;2~"4-~an~ of6.~,SB1!~ژ*"~ln[00 ~ TZ5h"~u1)~N].7/}i.}!3Ry}$k }萸;4}(  }ƙ&51!}A]ڷ}COkt%!}>B}mp}$##}+ qc*}̇'}W, }ɖ): }ŋ| },(2*}uj,$}(AD6.}ņZ0-}fh,}˛W:,}Xb~:3}l2"}; } <'}G4}9*}CgWt>4}x!d5} 6E}:<}$#}/"7/}㔭c }zC$}z_/}xVck(!}wX#S>-}olh}lvZ 僥>-}_yV}_4N5j-}YuC=<}Xń*o=}T}RvMZ=6}Ri|ЇO9*}P~v})8 }dq8(}W }7H=;} }_m}dd#}742"|*%~:1|\~r|QV:|h42"|@n;*$|z |Pk~4$|50(|^^_4,|Ôr-#|䝅-^6&|ufaE=4|b= |DS% |g-|rZy2"|pXo=4|]:|X7j |Weؚ |V*`3+|Uh]# |S5_ |PrJI=4|L`߮= |I8]kz<>|H$|@zS|<͘#|< *3BC|:~8XQ=6|8vO&|6TP||6A;#|4 hbD>-|1gZ4,|0u|* p |*+)\H |)`[D<>|(]0$*|$r1)|Ţ=R0(| 93|`vށ0&|o9~'"#| $Go2*| )4,{~ }${Mbܲ {I>-{^Ԅ9*{/55%{+n1){==+93{ n6 "{Mp%{ C K9*{B={ڲXC:3{̠*#{זZ{SӤd{"d81!{}Pp'>/{κ*h{y;${Ƚ:3{if7S1){#75:"{ۡ}>{5ɔ${!섿89{K {7c8{t%b{芅g{3K+;2{Ӥ-3{ڋչ#{39*{?/1K  {KЬq${Հ {MkW( {}S.4${|+7̐6-{z,:%{yCE"){w͡! {t~*"!{rvF11!{qbX2P&-{n.>r{n'dsv3+{lX4,{f$<®{_ idy]6.{^4]3+{WYKC!{UF={T8? {S,9 {R- q:1{Q°6"){QIz*>-{P;@ {L'=6{K%@1!{HLa=4{Dִ<>{B^4,{Ajz  {@|t@{@S;#{?K c{=ݙ|{/Q19*{-uPR${)3)1!{!x4{bWq&{`1*{I\9*{9Wqؘ>-{ Ib3#{K,4,{FNu_zAX9'z% zkc:$2"zFg z޻lן=zX-#zؽSf2F;)z)kzB9*z|0(zǍZ:lz=3#z@ ;#z|u"zelͪ' zqz8u(A z_fL$zU\",#z`zU~@4$zU2;)z6.z{pl"zf?岷#z@36.z3α,&z7JzZEzȹ"r!zw= 1!zx  93zzU-G zzZzxzB6-zu]3lY zqnv$zqhn"w;#zn{Km$zm8-'ze{s"i#)zcAh@o.&z_k"$z\@93zXS6&zXL?`kzPzLd;C# zIPa[i><>zE*zD3Wz?Nc9*z<=@7/z-z4^yJtT#z+q6yqyR)ZG5%yQy\y64$y.h7T y8R2"yPR[ y1{ y&oB yy|;4yBj9uy/ܽ"yؤyJM99*y㳈$;2yEJ ykC>-y]^y18Gh0y+>2"yMA#Ii y%>-y3X/yʋs;:y1sAw$#ys?N:yy y-kxyJ!9*yD^:yߗ9+nyF%W4$y԰pyf8 y)}0(yZ5y* yqxI>-yB7/y@ &)!yv;y 9Fb3+yNx:%y| }y{70MQ ywUAP ys?}s6&ynW%m09*yhkh.F2*ygFUBydG#e\:3ycT ycFљ ya5By^Er`F yZ9 yYzBH> yR$=) yQ:LVyL79=yK'8yCs 6.y@^y@'45^ y?4y!y>w:@y3;&"1y0Ǖ y `S+yY<=yX(NTw yWO'D yF6.yUλ#y o=4y AFyaCW| y\` y8]@U4,x@`3#xA Cx0:69#xZD!4,xmms3+x;L!:%x Nz# xPԿMxNN3+xѸ1x xdL=xī<x xxѐ. xhq.3#x[_. xv?xp8-xf ֲx#H%:1x\W x*s"2"xw)xosפ x*#-<>xV,,e#x?F6 t]Hxx0 w 0(x.()&x+䂊i4$x+] | x*xҷMx!'>ܻ!x m1xp~!xpCP0(xM( x ~} x} x'nk> x 23<>wJ<>wz0 w9*w4wÝ o wuVm7 w_ Xa wyMȜ:1w+֖w"4ywԞ}Y!YE w$4&-w9X="w#w ʋwj! =4wSVVm\=6wTO{Ka="wGU")w)N$,w7zIwt 3#wF w1!wqȮwTS#Kd93w$*s#w7bY$-wR:(wMzg3#w~93wyO#/<6.ws׹:=>-wrA&$wnWXwkwhI)  wg8̏"waǃw`yHu!w_ȇw^5hq|y wY聣#t wH8I4,wDR1)wD;8 w@Il6.w6s:3w4=6Sp9*w0d mTt3#w) R <>w&4E"w&agw T>w䚕9*wߵ̬wtיwTcw?W9*w Ŗ_w .! w UN&w fJNp:1w@k!wDlH; w|Lw g* w d  v%vCvV 'vvmU3v A*vnث9&-v4!v"v:3vΊyvSqbKž&vQ  vӁK9*vΓ(vP?3*vYrcvUv3"nVv㤀Q v4=+v9*v";W2"v F7k v(En<>v_ 93vuE v,۽3+viNC7v {2 4$v&s. vyw^3#vt*$v'ɄQ&3#vM~|E=+vЮi<>v$€2"v䗸U v< %v|am>-v-ov0vϟ v{N8J#v{c{)=4vwP'4vsl>-vrY<vqg'-vj`t:.89vfk װ<>veŵ̸C"vd+vVd1!vU evSڄ#vP.W<_4,vO`4=+vMB-3+#vM=zGv vKXՊ1)vG1d.lvAy3;v@5 >-v<_GpRv<<>v4 1!v3 P _7/v1jU4,v-6E 2"v, 1 v$r:9*v#/R]v*j vȯ&vhw4ݙ vfsAh vwuv j9*vhb2"vFZvPu`Z=4u="ud.uWb[U uBJ0P3#u%}" u,uuu4M6.uyG6D+$u=6ubOB7/uesD&uxuR펇i<>u &,&u>ֻE;)uUx7<>uѫfuU+wOudg&"uYpDu.̞˞6.uh|> u}&!9 u&uou,##,uIJuL3[ uIs]1*u^ \="uK{-u ͖!u>-u8Upu z)$4-utP%.u5x6.u=3#u6 uxUo}uw K=uwAqz0(ut4^&un(9*umX.6.umd7`n uh͕b#uf8uai+59*u][tx$uX4IuXji&#uX-uWAb" uVNE-uOa 1)uMe2"uMjIg uM(^J9*uJ,Z8M u? u> u9\19*u7[|3+u0]&u/yén$u&>z]`u sTN u 8=:!u~q u@|T uQ"( >-u2K%uq+u64 t>Բ t4t8 $ta-2IJ,#tk9(t0?bU tӋcL6.tdƅIt@ŚtR"LY=t/|t_814,tƑa8tw{"tQ  tϚ 9;2t/P3tA  t͘ԭut) t1QHHt4?q$t^Xg;2tP%! tK&2*t#h#2*t|~0 t6=6tKm tiOm<3+t>#MLt R!+to]i tHQ4t~J"Jo)s$ty+8gC'StxL:3to(%(4,tm!➠:1tc2N>-t\<#"tX$Hi3tUM>' tQiq!>-tPVLf tF4e\d$tF+8u2*tCjVON tA69*t@$I3#t;6.yt5c4,t/P t- jt,rٙj"t+sHY:t+,j t*#l st${7/'t# a1:t"(1z0tѫ#)t^{-U2*ts0 tgt` tZ3Ȳ"t 36*tҰ4{| tsrMY2*s'e#s9~;=sp42*s0ls] sm4pt9*sкs:1sڄס +9(sՃn8Vy=6sF:$sϓgsο`os# syW sA2"s?"se {Zs*=M!sH×6.so s=]s9a<>sLm)*s-ra0 sca<>s+bZ2s';2"s sw(f-s`[sg`E  sW"~$s8lsK%O s|?~ sx)]C swN?msum[V0(smt8:1 si[ shKqsX꺯_sFumB+: sEi|>-sE(D-4,sAt9*s@aG=s?*)$s>l;~"skrͥ{u=6r=#)rC I rğ3#rP8r:"! r-46:r5&nzrޛ:%r '1)r5Әrᙑ rtKh&r[2f;r·X+#r݉} r}WE0(r8q^6.rV&ϊ3#r|fTryWZ">-rsV븖&<>rpR|5%rn],rj9R/ri h#r_F'\B&-r[himaW-#rU܉~~=4rU<~ rR.&rO1A <>rO)pk rO@i6,rN @K$rMJrJ^_crIg!rG?Gp r?7!r&r#rj  rEBri?">-qy"q5> qNH< qM[Dj"qqp墎0(qOyKw3#qA?qRx:3qғ^ qϺy@q)nwTt4,qˮw/#qa"qt0e&q 7P4=j&q)Bϫz3+qti q } qr93q~{*q~5Ըj"q}nVqz&ʮqu=X qppGd=P@;2qm9*ql,J#qji=#qh 5893qe1 q\kj6.qZ4#qY{2_<>qW-p=* pX# púز-3phO81)p p e2*pAt p=*]A3-p ck pE09nIj3+pFcp6hi pD40(p_ ۍ pwhRFp؍>2*pE`;#pVh.>-p|D p,&-=4pCp~ԫ'I:%p~QGx#p|WP?$' p{VY,#pyf#pwʻ7/pv+:pu-ptM3#pr:qi@ pr 4Y`"pohZJ pmkpfD2H-pe-t` pbux~2"p`tQS9*pV+`䑠 pOeK:pO1- pI5e p4^:1p.n.\ p-0@Hdgpw\Q:7/p CD)&-p1x9*pq!JL=6ppkSnppRo$puO8$,pop8R<>p *i,2"pDbPp I3#p ș=6pRKxSUp3>-p+q-o5n, oU!o`a&V;4o> a>-o$oj=4oTM"o[=gXf&o߁og6.oӉ: o+SH 3+o{Y!Fol#-oJ4,oZ%t#o8 ,$o]QUE; ok:oIY‘<>oyo^ŗ$Lo}4v# o|o$ * oz"YoxV7-93ovKV4$ov  osT*#or2!J>-or#͠$oo)  oa޿oa%+Œ>-oa>K9\;4o_p o^Ԡ*&EoZMn^1!oRT2"oO&oNݠbM oM?4$#lc oFa:o@BD_|o>"LsKR,#o>_"D o=8ʥa93o4/o/j H}V3+o,+'`3+o*/#o&m0Fo%*J4$o >o293+o]ʖ9*o\F>-oP:o l)к9*oZ)X=o Jn n4_,$n)69*ni^n犕K4$n޼e2"nGM`5G4$n,c#n M[|nؕismR=4nMiF:,nо0n׹żUY nӇ+[n-$$nЖ,0(nZHv n}]([:3n\"mC nǒJMn䱮܀'n\Z#npZn3/e>-n8 R>-n^9*n-4nf$c;=4nc(MU"6&nax3k5%nak]* )nah$rn_m4,nZ CT nXIGn=6nT̙qnQ(8*:1nP>n;d9*n9MyQR4&n4`EG~ n/{:A2"n,TrHfn&(] n%~n /XDnZz<;4n!M=n$)#nIB#nQß n I'-3mP  m}U]u mr_I; mٴ(9(mH+ۓm(h&mϵj#m; {FEmfYP m߯iP$mFiG#m29>mmLYO2"m|m܎K$-m;=p/mԨm;:m2m5?"m %b;m*%mϪbFK,$m))V;4mV8>/mS3Oym=½n mŵZ,ƒ mI;m:Ot mѽ mܶ).mS5%mT mX"ԫV<>m=>-mƝn%mH=p9*mHD1)m*m|ئC[ mxgV-3msta^( mp.ԕ-3moA͉#mnh9*mmV'; mj~c =mbʽPfmbVo)m[Hv2*mZ$ވ-3mXZ^5>-mWb|P=mF-r2"mA*m:y͡-m8l<\)/ m-$m(LApN#"m&gЗm%U  m$2>-m!־'m=lr+p  lXb$lsKlb'M3)lP;&l/E78la֬6-l$j="l=)PlR:Ĉ 0(l+:A3#lζl l@p tb)lp7p-#lH7B  le1E1!lo,$-3lZ2(lZ4w-lY lV X4,3+lUL4>lS =()3#lNclMΞo.= lDp6 lDH:(l>M9(l<ޜl:Sd<'l811 9(l7B=4l3=l2͓>-l14+&l/Pi l+&VXl"퇅>-ldѸ#l@_lF7/l t>-llO:%l63'2"kW52*kdGM; kOw jk2:yE>-kcD)Vks6#kP: k߫6\y  kXiU1!k2wꈂE kgJk$kPw'Kk+-kjGʇk:dХk)0[:,k "2L>-kb4,k~r/k I{3+kV j kz92o4$k4=r:k3$1)k,?93kUKD.-#kzF2=kpfdkl>'Ekx:kr@˲2*kxk[i[6.kYOK&4,kU_kP{<"0kO^f)&kN1ZjE&kM%rkEuG="kAAߴ&4,k=:XSk:Qɦk8#2k2x:c >-k.OP'eg="k,%& k&vs93k HkQ(.kN%0(kLV0$k[ pek^*4$k 5 jT[K(2j($jɚ:jW3#jhts=6j1 j@ܔ23#j'R"̾4,j 2Nj c=rj饘f9*j89j<"jӬj5K&j O j̤jZ/i0(jO jᄍj6!hl9,#jCtG4$j+3#jSۅ1!j,~?3#j:p6.j  j]1JȒ;2jQE6.j<9(jJgIM>4jvm#jP6kj9*jp0QM0(j3]$jsrjr9bR]jl9 j`ͱFi|j` DӋ4,j_gE-'j[*(jUV7/jR\P$jOFdjML78.>-jM#djK}J@2*jG(ljAQ۞Oj>m?93j=zH7/j7d E j,)N j)Yj'&с>-j%w?>Fjt{ j9 d-j +"ji)j qbRjrp"j|b i$iwJ]/. ih:i19*ib|Ǧ0(i8],#icYBig5*2*i٭" i]T=ik iknX;ix̒9*i8 iiH: iF-! iU=iӜYihy| ii)L#iK93i}R̕4iS<>i i 493i~$52*i}'>Jiwx is{Uũ=4iqb2"iq"& ^h$ic zd2"ib֥;Mi^w&i\="/iX#iX@i+iL.y"v0(iGt^H4+iGiH6.iBջiAF:G/'i@;0i98n i-+c$i,qoi+_ 2"i)V*8$i(`7  *i$:$i"g]8ZiO &iHgc=4iX <&i^Mv=6iHi).N& iXF<6.i 65N i[Er=hvyb]3+hKq G:1h+EBKh'ThpG@h -] hsWˬZ/hCm.7Y h<L*4hާ1ZY#hA巼Rh)n*j4,h8Vh>JN h!j h8y hɛ|n  h+bA93hY6h2 h+;mW1)h #=5%hױX=4"hrl3#hQ2"h-pJ0 hf\`1!h=A>-he3#hsx3"hR#)hEJK9*h+a7'hRGgh +%hvо@t˔hs[R-!hrZ$hlq8YSheKhds00 hb@i`1)hWcǎ`^ hO{JT~!hIv>-hEop hDny/6.hAE`1x h>>93h;Ȧ1Q$h9yQUPh6-S@Ch5Ueh3 옜<>h3Ij;)h2p5 h2N/$h.;C4,h.n$?q3+h-2+ph(2"h'eb=+h"pqh![5 7hl۷R4$hujhxm h!+hABv hC0ih!?ht%.h ~0(hKp h $B h}_՛ ^ hyK[h58YQ9*hqng!gWCF4-g:y[qVg2tLgѠg8>-gfȚag|]9(g1U5nE=;-gg+. gk gp4$g]vg;C0 g C<\9*gಡ{<>gkwg  gsg:1gW*Pgk}4S2"gӞ#R83+gӗp8̙ gFH#*4gɏϙ<>g =4gĆlgĆVg-Vs<>g/.:gqD@:gc +$gGEWgNOLh3+g~)X=4g( 0(g? 3+gwn=-gt g*zgJ{Sg1}l  gx;4gM/gZ ;)g}#0k;6.gqngn!aczglB捾 giR=gg2͌gg'#ggDi$-#gg'ߒ1)gf<r6 geʀyu>-gag^lK!g^l1d2"g]6A gYoR>-gXwe8 2*gV  gQ ;2gO/A,#gL^/jh0(gK-\gIЧğ=gFu=FZ$gDe2H:gDIڑ6.gC23+gC o(4j2"g5]4,g4/fų,g/*Jjjg.{0 g.<^* g)L>Ng&L0-; g%䯌9*gҧ;)gkdg_):,g @c g A gpU=-g f"t=fΛqM2*f0F#,fg1f_mȰ93f,Wh=6fЛM->f^flSfD. fO>:%fjz 0(fԓ B f5ӒfΜ fG%>Q?&-fn .f{lz fk)@N3+fhzqpf!N<;)fbB f L#fd8:fގ; fQ|<>fA=f{!R1)f`f)Yz f1 xL4,fP+- f J#fW f/t9*f{RA& fuU "fq{%E:-%fqmhfm@4"fm:3#fkE fi7fihP fh"!e#1!fUpFfT0!-fRK5Ƙ7>-fMc܆x:1fG9J4^4$fF_E.;f i}?*$f tGT2"fO1^Gh f(fzF4ee~G3#e|4ʏF&e}ݷYeacxF2"e1e~\0"e|w/eztu}exlu#!eqC@2*eo8+.enf#S="ekЏC0(ejϺ\#ei9:)6.egtmֆ0(eZ]x58:eZHƮ#eX&WPPeTfveRf;eQ"4$eNn@:1eL=Otz1)eL  _3+eJPH?.7eI5>eHa"-=-e-.K(n;2e ܅O~e SKl;2exМ=6eյ5JW&e~eシ,$eI%hj2"e ea&!2*e:4{H="eXl!93egO5d纰kdL5 Q93#dsv:,d.O`ٜ-3dM h4,d[j d_Ӵ'K6.dA7dܰyVdJ8X< d>+4,d {ĕd֜w֟GA4,dHU4,d=Î>4d?  dͷ#!kdAlx&ddҶ#dJ`KCn4,d&\_zd1,R dN-/dío| d1"d`\%Qd 1"dDB{3+d|@e#d8d)doė da:Cn0dYd e<>-dX2"d ;#d`/12"d4]c&dCJ.dhA7,W<>do{FYdJ+")d#ydx!NK7$,duZooq8 dp>G<>dpeUc` dmt.2*dmbYMS dg^ $d` Ad]joyv d]XR 5%dRf:dR|+dRC,R4,dO4"0(dNkHdK@m:1dGgV7/dBtG$d=:ud;a[,>4d9F!d5C+^J*d/CSx$d.^΁%;d-Ɨg2R5%d*Ad&r=+d#S\}7/dAʾ=+d d-Fd`uߖdT$/dsL.9*dLl[B"dq ddpR,<>d] Gd^U1!dWSd'dE`2"cLYQ7c&Tcvq<>c)Q#c* +c,~2y c cqN~¯Gc$ ˆcʆ cA>p?W=-c8ae c}LIc{acycV}CcU _8 cM[IL:%cE/9*cAh3}rc<>}c,a&c,ۧ0K"c+њDvsc&n"-bkդ( b6HSx93b.O+0bIWo-#bi^2ȕ89bqY6.beZ$b m bq͗4-bQ=4b{r7 bzCIgby;@Q=4bp텤sboֺ=!b\qa%bSF>-bQhhF"#2*bF| x,#bC@<e bBZx>4b>~w6eb:۠]b8'^ .b7f b11a*bb0^DѼ::b-.kCϘb-X(b*O`*b u+0(bkj>4bGZYbZIb׷93b% b\kb#bm~/ by9*b!7E b3Iac i2"a{Wba_t(md auRJ aAγw)0=a6#CW3#al8'32"aHZ(2"agM9*atnb!aZI' a޾ո9*awwX aسVP:3a֗rW3+aԴO' *a{`oikaӺB<>aI$ܛ4,aT.%=a9\aiv aYO~=6a9 %aύl6.apó a|a aʑ$ aAHLaLN#a!oc a{>-a'H1)aW2nY:1ajbaZj1!ao̕#-aӨ7Ca09*azJPas7hj>4ald"{ral] ai,Eo4,adm7!ac}a^1S#a]7=4a[+aXU6.aQ^$LaP*p  aNc#d3*aLzW^ aI193aI. {2"a@-Sa@ Eʽg$a9dzk<:,a8Ma7 c>-a6m+";)a1KOa){X::(a(F<a jHʕb=-`g@3#`$`?w `4`KS<>`c`t>*0(`7ppI#)93`|#k=X`{$_52;2`v ֱ. `s`>-`s&|; <>`rQ};+`r `o`1`-V3-`$d?c|3"`#f1 ` %` *zw4,`3o7/`* `FT `ۭ&5`T2 `T$d9*`ס{Q)4$` RF{{ <>` ?`kG:%_))F3#_!:_<9*_Ы8,=_줋݇S$_ص&=4_~ j; _䝩9*_!o=_mTBў4$_ݓ;Y _O}H:_-"5,#_kY?2=4_0DC$_X_23 _46Q[2*_ęZ <4"_׬h1s#_=RpW _I;_T lZ9s#_[:Fp3#_•8$-_vg->_@g _r +?0_ݓ^5x _Dsv7/_i2*_X["_G  _{_:Y9*__j>4_*ip-_=zh _yLUZ6?&_} g=>4_|H=4_|1E˳B _{@ľ'2"_{  X; _zR>-_vޟU_mm7/_ca_`1"tf_] ns|_[moH_XSp4,_MF-#_Dvs)4,_CMwCq9 _2*Dc_0+| _0OT_//$Qi(2_,G3$_,kGs_*L_&Ӏ` _% ̷&-_!3ogc;3_ NIt>-_A.*9_`Qj >-_h_91u93_ &]_4`|_ߚoZ&-^Op@>4^A 0z-^)J0(^jt"&^#``4&^jZ="^5%^&Rn#^f:^ߩ2^޳z ^3э-^ݬr2D:3^9!F^̓%U ^_ذ>-^{ #^ Eo&^1"^zéW^:&7= ^~1!^$=yO3+^-^ێ!s2*^&_ ^4  ^%="^⻕ ^}&ˉ3+^xiMwY1)^xF.$W^vrQ^j$s ^h`Zp1)^g$ >-^b2 GoY2*^aMt"&^[o`M^[cI },#^[(9Qж^V~ 8%^Tڎ>-^Saj9^RM_u ^Pβ^OgZ ^NlL>q1!^Kv^>쵈<>^=G1!^<*0(^;ǫ<>^7I ^.I\R ^-o*H*$^, 4,^+|KJ^+,w^)4_^)A=<^"{صn>-^ ul_/^%|J"^Sqj&^ޢ )nA^9a6&^#//^N]*s93^,86 ]19*]3* ]]-|h ]O 83+]U:L<>] ]#Y 2*]f5$]ێk]Qff<>]ݼF-]D}+J2"]я(_v]ޱgu]SLϠmO ]82]tL 1)]}3]NYVp ]l#*#]t&3+]C ]2e]O]s>yk1)]'593]{|Xǚ"]cj,3+]:{ ]:]s]5KްO!]5'9;)]3on?9*]2D o3+]0;m04,]+X O>6.]*q_?>-](0wW<>]%na@;2]##N"3-]#`A ]!o]jJU>-]_X@]P]-F1)]12E3#]tLna ] A9*] `.9*] _vT] @vR5`:] l]]uU}&]I90(]bG* \5qN5 \G4[\[~Sc\,$\c%MP \֛w1*$\P'.;4\բ8E=4\m׈R6.\NG8":\͕"r$ \Ҥ5o{ \eҟu:%\il1)\R|.\v= \\7/\ d5\\ c,!$\ּ>-\8_<\}Bӭ&4$\12"\ c \Acq't\GȲb4$\r26.\(N=4\E \70 \F\sM\~؝ \zһ^ \w-5:\t1<} \sp6<'\s;$c4$\r,j[@f\q}|X{W\qVq :3\q @4-\n-\YgԾ+9*\Yb ak2"\V'93\UdO22*\P<B{#\O ݷ>^-\H y2\GJYi\A. \=K6.\=,Z\8?b9*\6=B-B#\0X(:1\.STTs \-BT2"\* sP4,\$}#N+#\#a|bh=6\ 7c:3\*B(^=4\Qw#\eq\}\Մ3#\?jV7/[i&-[[fmM=4[;#[kƈ [.-[mTG>4[Xx`|C [:yޑ93[ax& L7/[D [ *#[L0([ݨ-[43#[ξW2"[юS%[1|8 J[gFb[ʜ|%[ő3/>-[9->-[u_U [W`a[o[)~>4[2#[>`χ[D8?_[2[?@p [9!=<[gp[3M H4,[뀉L#[~ 27/[{Ȕh6:%[xWM=6[w7hry[v.;4[u* (3+[j 2*[g:M<{>-[gi :,[^sЄ![V[0([T/?' [Q+\p5-[K;w=6[K!:2e9*[BNچ0([[9UV$[0ѯ;"[0)=6[-cp9*[*E! @9([*'7Z[%0[[!σ+[&[l2"[ml; [$_;-[8K4,[;|'[ÿ  [ i! [ B|=+[ |3 [OU( [y2`5%[Mq#OcZ#op+Z\Qk/<2*Z B]$Zf0Zk.6&ZE;FUZ,{ Zo ZETZ_Ԛկ>-ZR^Zc Ӧ4,Z;>8:ZI‚&Zm Z_' Z Zý Z<>Z4" Z_Zv7/Zշ,Ё:%ZFg:3Z֒_U Zf&-ZLgOT Zi H9(Z{E"ZzH*NX4$Zzl 'E6.Zxm@Zs]%W $ZmOw@^,\Zm^]V$Zk -Zj7XM#+ZgXͱ,$ZfZI1)Ze֥6 ZaoH=ZXkbJ{:(ZOΏvj<>ZJ( 0<1!ZH0魀 ZF)ݝZB|]Z7fw>-Z7ve)EZ5 z#Z4Y{c=+Z4V&Z3UJe4<:Z.U.Z**6.Z'9*Z"!ZßS * ZS\5%ZH$9Z+ Z+K#ZyU*3#Z b Z :3ZU YrhY<Ynl=6Y^ݙx>-Y+ m1)Y ~1)Y07=4Yji YOL Yޗ~yg2*YuF;4 Y*Cqp"0Yל-YRٮ Y{ZS#YPW+'X*$YҊ Y;nwjda>-YK2 Ye/^ YPo=YyrY^fY.Y|D Y)̵Vw&Y3<>Yǃ$_ YewO:Y^`YOam#Y- F3+Y,`.7j*Y3:Yv>-Y~a-#Y{tՊYw{ YvA 3!YvW;#Yul2J4$Yt+䞟;YS ף3*YRӣ;DYRq=4YK^ΧYH22"YBf?4,Y? ʫI>-Y?3CJ4$Y>~8 Y>kιY5n3+Y5 +7 Y3רz2"Y2($4$Y+v6!Y%@ڑ>-Y"nL1)Y4-2"Y- yw<>Y~/2*Y:u 3#Y4va4-YHjY=Y,9Ua2*Y:a,$Y ] Y6Z` YzowRXezeXY'X5_YX_P93X@2*XL)2f9*X߼0d,mXaGi&X}P" 2>-X=qD9*XnW1)XP֢qXѸ,̩ XB$9*XCkXuHiIXL*^XfXZXcm7X}L,$Xxrr9*XPeX3ϊX 6(XY#X/jX⇆/Xl#XN_+&{9*XPCY,$X/$@X13#X`vxXic,eNXh?f"74,Xfı<j Xe~c3#Xb<ĎuX_lB:=4XYKϭh3$XY"1!XW[-qa XTrK:,XR02"XKkZpX?&l<>X95׮H=4X6[STd#X2InϸX-(6.X+ZPnq X*_[й7 X"]H*#X5s/=6XwgOXNz93X80FX 8|޽XtV4,WV W0> $W2"W#\L;)WUħ}1)WKp93W*U[q0(WzZzUWGs 8=6W끼d]Sq WrU=> Wpu*W/,=4W(#Wwb L$W?7&Ws 34-WgO"Wf_$Wh% Wɪ§8>-Wo);2WAUݸWޚW~m4$W3&WWkdrWU8}$Wߑ#; W )l4$W6*3#Wlw7/Wd2"WlʕWål>-W=0#k\1)WJFW{J WV2"WZ0(W'ͺ\ W D#Wy62"Wt(WPb* W{"WXqTQ15%WGժSZ$WÂF WM= ~/&W}}{zk7/Wz3+Wx(=#Wx'oVsWuGe Wt Wqf3+WltJO3+Wk t2"Wiݢ48 Wi@GFWY(S=4WYkui2"WK3LWF=WCI,$W:9DXtXW: >[W8ī4,W8X3+W0*p8C6.W)2{^:w W!h.93WnlI6,$Wg;)W @:1WJ)FW~zBIWJ66N$Wxkq Ww6&W7@ WٽWŞ"U=Vd V;(Vl*"VaZS$-VT0A60(V|IVA =V l]V=t3"VO~$Vl;ho VI8$Vϊa V\yVA>z%V0 V93V$!=V@&j4V5D>-V& 4,Vh<>VxρVvn2"VL1j*"V,Vs_?SVٴA$V| V̧ <>Vyh93Vv$DVyw=4V%Oi V/C<>V%߬^2"V.D0 Vt Sr6.VyV)~NVwn4^6.Vt/hVnfVm JYkVll>-VgGubE#Ve,7E:3Vc[u?&-VaH~#V_qD< V_,^Eo V^/(y V\X{3+VX?$VTM:VR/'t VP30>[#VN I~^2"VKƋB%&VJa54JVIB2"VCK4,VBILJəVB1HV>۩?n-#V90=93V8_V2+xa V'=OZ,Vt*L:3V~MK=6V;C V˿p V:r_3+Vlk3VZ*3#V J43#Va">4VB7E6.V N-#Un]z Uh>QMU тUꎢ>Uަx~&U1E-Uʼn593U),;3UDkWs Uԁof3#UkфƓ UϙV6ޚ,*#U>&Uh=>"U5sn3=U46;#U!ĕ UɗU>-UƯ(\eUĵb`>-Uod3#U`2=4UG  UA.. UiA-UUAJUgU b"U= E89Un1!UJUzt~+!US Uyx UNb%&+1)UzN*3 Ud2"U!%7'Ut3sLU}&ka4$U|:gDQ0(UzL]z#UypP̍ Uqx2z3#UkXt0(Ug8UfSQ Uc7=+UbL0A U`Z)Ho:3U^Z UXz8UU蕽 %UTa+0 UK=r=UJJ`0(UH o3#UE$U96m@ U7d|J-U6|̰2U5 J U1l U0PVDHU,S;)U+z}zU)_];3U$Ln+ U"N U!B93U nem82"UboG3#U:}vJUWlLz;-U &{ZD UH|>#U8 C TR@*TQM Tbz<<Teo-fP3+T8j7 Tߎ T3}2$T*g_:1T< 3? T&TsieTqNz3 T TE"T=6Tܘ _$T=@ T2 ;T+*F"Tmr5 T,`.=4TԗT+MTG Tyr T8c3#T5:nTk>T³G2t$Teȸ&K-3Tnu>-T1/LtTV}K6( Tv#$-TSǭ2"T/NQ:1T.hޤT;ZV>=6TCN T;ù Tè2Tz}-T>ː93T!+TY85%TG=6T28UT93TZ4,TT'<>Tڿ-89Tߴc02*T`kбT3qüSTz:G>-Ttᨖ Tn "0 Tleʦ2"Te?~ * TdC2T`7cX93T]F9 TWW> TVLQS9*TUɧ:<>TNiTCe{ۢ<>TC5>-T5tg T0{լJ9*T..ks64,T-4ڍ#T,u,iT+u2H,T+IT -$T%V\ T \^T$ڒ=ThD)*"T-B$ T>-T!ǽ-#T /H T p=q2"T cW#)T ^P{<>TuLTUC!TeUj%:TQ0 e~1!SBwV!=SK\D}6.S˜KYSgSƒ1YSz Ӿ#SpSJ7<>SƃS`s3[6-Sס JSְ7:2"S1' S2x75-Sl=6S=_;=SčSL"SLj">50(S;f>-S٦{?:3SfkuSfK-Sl+P'S4SZSN''W6.Sc?2*ST.f0SGJ,$S/SPYE;#SKFS%,49*S.k!S|V) # SxGff;)Ssd 3#Ssږ#Sq13Sl\2"SjuhJ#Si`<_(*Sh|$%, Se Sd~>3#Sb|! SZ.#SX(Y;SW^k;4SV?AD#SURj>-STb SSUJpSLE5~W-SI<.U\9*SC&+5%SCZ \2*SCq걈j?;#SCDg<{SAdU%I1!S@`B&S3Yb| S30LNS2zU S1KS1\ viS+(*7/S*j D3+S%&S3eceS~fSwZ Sz3+S fc "1)S -#KKJ;)S S=䇎T;&S{3+RK Hr2*R$ Re1 RmUp|89Rַ( R!f6;4R[4:%Ri6.R*l2$R wʉR1)J5 Rȭ^ R㸊]&R6XRA) R80"17'R5%#R1eg R05 f;9R0^k "+R- ,*#R,ED=;R*80:,R$Nn7q=4R"t`@93RpaRb ?RE1)RF%R3+R MBð RC%?R`mI;&Rj^C QS* Q_ԕ QxV|G Qc#Q!qU_y3"Q QӮ'QTSQs`@̡>-QЬ4\9(Q?=4Qɾފ[=+QLjNN Q3k4$Qؖw>6.Q8uQ&I>-Qǽ -3Q)W&Q]CVi9*QG#w>-QU;7nlQ潩 Qp% QM/, QE=/ QU:Q_# >-Q 15Qo&93Q6dQ~dQ}40o_ Q}3O")Q{FQtsmj1)Qo;abQ4$QkFe%QgF =4Qa~B]Q_Ki8Q^qZh=4Q]dQp Q[ɨj`:3QZCpVQYyDU=4QWbYj`g=+QVU QU(wF-QKkHO7/QKieQIQA0|=Q@tIOa$Q@^3VBZ1!Q>ͨcZ Q8I3^MQ,Y$^Q*xH0-#Q)Jol"Q(ov^Y ,#Q&s7= Q%5 &<>Q%&q}F Q OR7/Q)7>-Q/=NQR^4"Q Q8:Q"?.9B QvQb)#*Q 򜃯3=Q 7i,Q0ްQyK P-I PJKK^ P,>?Pb7 PtA/c:1P@7DY--PE0p4,P P_҆ _P3DP]q P9z g PZL4$Pm@(1PW M&"P6UB&PJL>-Pvd&-P-SQ P%gr3#P >-P#}P%P)WOۀ P P5 a3#PRiPb? &=+Pb~OV!$PLD$Pua|i7/P+Z,3#PGKP Wf:3P4ȑP-3-PaRP_ 4$P|P|W, PvRa W4Pu B*PsS1)PoŚ-4$Pm J{$Pl9)4 PkC od/2*Pg3pPfxs'!Pe¾J:Pa Y[7/P\=I:P[f4h4,PZ7ϯ&PX<;'PWBb~PR/3+PL饯 :3PLPr4 PJ!㾠9*PHv(PEF莂4$PEOȩ*9PD;$B'>4PC RPBö-}MP>P P4O7bP/A`:(3+P*/^\ 3#P&(u,P$(&P$RG) P OS3#PT P,Pt>/P(6ZP-=P i?PzzP<* O~g#Odr? OpemdS<>Oޖm93O#;<>ONS ONy2*OmcM^j]9*O덬f 7O.L!3=O B1!O꜈nO?x6:Ows#Oxg`#OdVx#O6s8'Omu Ob]SOIBz` O֤Km>-OOh|4$O_V =6O ?S+$OH'KcOp9\O :1OhL7O%0.gOg C&O&ȧ+>4O4յ!1)O39*OɆO-|kƪ9*ONa8:O>Oێ4,OZXy#)O5] ObS2"OyO іO^( OUdV3->OJO2(#)OP[RZ OWWO-82*Ok[02"OqM7-3O|I#O@8<>OW OBI4$Ov^ZhOuz-Os l LOr{u2"Oq[?0#Onh sp^Ol3İq:Of|Ҧ #Odw9Odr#}=4Ocʄҗ: Oaq-O\Q5OX5oFF1!OW'>4OWMu0(OS:OP⺼:,OP,P ON3~^ OKZYc'+#OIIu>瘹>-OBwJlO>SF!93O=S93O<޹5~"O;c*A7D9*O9QL==6O9MPB O7tU!3+O6!84$O2ꛫo O, 'FY O(DP O%(V  O$+ :O$6J/OMO(>-OXQۀA OAv!*O Sh O l)g Oc)%N!dN{X}1)NA4,Nƫܙ*Nr'4$N9LN_e 1>-NT Q)5%NU?&P=N$!N/^]=6NRU!NnAv4%N?]0(NS=4Nqew~ N-]>1!N?l>-NPK&7Ns<NeP>?N17-4$NZ;kf4,NUH4,N?P N" Nbb-N,N~U5[2"N| 3-Nw73#NvHy/p"Nu F*2*Nr{B6!Np`=4Nj؟#Nj~I;)Nf͙*{#Nbmz&=#l NaSڒ;4N_Pz NYXf3NWC~q3)NU63+NU-NPaޟE{;2NF6nb: NFjϡ4$ND~D0< N9 N7@P#N-eZ&6o*N$!NhPNӜ_ N'0 =4NxȎNru>4N U߯Nw?Neτ=4N֖ NdzQ4c4-NYJ;)N*Kh9*N%ONgmVM~:Mݧh M`e2"MtOF7'MQ =6MLMMtM Mxэ(V<'M\( M==54,M3M:p_M M髺dM'Mn_K9*MW*0(M3M:'O۳M >1M RM߃,#MlWMA<M=j=4M|pR M =MC& MnSMjw+0(M9]!M64=6M*7/Mdrg 89M d; 89M $9*MX- M_\+-3M="M09:1MG±R=4M~C%iV<>M||q_0(Mz\'! 0(Mx-nn=-Ml;w="Ml|3+Mi_ p#MhP 5MgǂMd-,$Md(;;#M_p7-MVTՓ&-MV{cpMU_Q=4MSUi3#MMQ>-MH."#MFQ{ԥMD=m,,M?-EM>ZM;1.ڃM8oM,1t M/aX5-z6.M.\0(M-0-q-M& :#M"X7Q&MɰȊqMZIa>1)M8 M A-7=MEos<;MǶu4$MbK  M ;Z$[>2*M u="M@ꚥ3+MZL`͢"LR*L(=74,L^xŠ*&Lt@7A&-L~LjQH.#'L`%! L`w<>L$C\ L&QfL6.Lu`4$L]@+ L.5 L UV:,Lj0*i,$LQs=>-LJo-Lz q L=LoK3+L~=-L}* Lw #93Lt\GLrbg Ll3O eLk,xw Li$n >-Lh\?/Lg2uGS-#L]@v3-L[ Ry?<>LZ+i!LVNH3{$4$LUkvLN ̛4$LAإ3`; L>T>/L=M·L9"x6.L3c[L3NL0F0%L-@*L+P* L+1~ͽ%L(7jT>-L&Lp'&L#ͩL#|h8 L" :1L!שF6893L l<+/L /Vgl&Lس}" L]BWX L&HLU`L2 k!L!HLKYtLʘ=b#L.>9*LQeC4:,KߠZ#K3=K E*K n=K~cN4-K}<u-#KzIO 6&Kj3s4$Ki:%Ki-:7/Kf52((2KeO45=Kdm`=;*KbF?z!KZF|m1!KRN*V<:KQ;T KPgy KN ;2( KK˜| KKz;"0 KA./ K7Ԇl+K4\z˙;K3kt4K2%K.v/J K-b.; x_pK cC"KR1K}P{<>K ߝN=6K'tKJ!5ѐK̓vHBKԾu7/J3\x>-Jd< J YJ:B>>-J!1!J]2 JZn:1J|| JNz<>JTˊb  JgVwJ׏6vl Jq_%59*J4qGJV_; JIVJāHtJ[J) Jx-:P7/JQ:{5%Jv7'JGft!JfW; J% J^Y J%2"JwzJp,$#JtQ 5,J JPC=6J>~JE]E93J~>-JQ/J~5E6.J}.0bnJ|ġ JxEi0JsC"Jo^U3#JhV\$Je%Ye^0#Jbf6L.; Jajr-V, Ja93J\xjy}B2"J\Ն{*J\LK%JY>M JWr`,$JU:C=3-JO|{Z[ JC߭)*7/JA\J:`0 J9aܚ=[0(J.\6.J-l:#J- ֮ $J'8ژ* J'6dY J&Wd'J%fB/J!ܾיS J.3+J [Jk@SS J\s Jt0zI+UIL>FISv7a9(Iv8%IC,-3I5&쾪I녹f/5%Ib,093Im2W I<֦tj IH$Iᠢzz I_~W2*Iާ~2 zY:%IILj IՔb۟O1!I>AIݺS6.Iť$IͽL#Iŋ ICO-Iy2"Inja_t$ Iul_-#I}S>-ISͲD3+I9+*ILN:,Iu I,6yI!IWz&I=IT I|U I+X] '>-Iߝߴ= I3 I#IT#JIc:<ؒ3#I&l4IFoIk˂z Iˌ# I${bIx5Ä*IwU^' Iv81 ItEC:3It~?IfBM-3I\/" $IU]eIODM+$IL3z(6 IK IJ\2x2"IC\|>-I<{I6&I;=*$I0N I*ӜUI&h0(I$%@0.#I y #"M IS#K,cI$I8JL ;IR)ѡ#IψC$4,I=uOI &7/Hƅ5J HiR3+Hjރ\#Hٖ/  HN?o-#HPE-l<>Hd<*$H7A&H `4,HV<-H Ā@ H㛻grO"H(mh=6Hd60(Hj`>/H{;Hٍ c"-Hf3#H Pe(<>HE|>4H'hHгIɃ^ HЉ`:HvrL H )<>HƆt6rf H@,&>-Hsl0(HOZ{ HֶHq]K<>HJ0 Y$HRo;:H:nHa#0(H<Hr;S9*HJHA&H}H8|EHDHJ H 6 ΣQ Hܘ-Hb3#H_ HjX3+HR"HQH=4Hg-H&_:1H8XhH3Ha ߋ HxJ76're%HrHjHkGcU=6Hgd1m He9 o>-HcW #,H_] HS#=QHRض\3+HP:!HLXH@ H?mKH9AY19*H0p%!3#H)T #2H)6l6.H(6$H$d0V HHdd&H}!u#H Xڡ=4H VI=H fv+ H H4xk9*H4$HD}$H,,a` G%Օ~GӢc:G)5 GXl l GSi GB6vQGAZGшS[2"GϠ{hGͮ G̃+G롉G>t=ʽ$G(O3#GD0(G*h*Gi2*Gk G2*G)E>~G~M-#G}p.:G?u)Gyo/jGΛ`Gx#,Gٌ-G5̋=6G~q7Gy; Gt`X[4Gc{w-4$GaPM:4,Ga8J<>G`UQ-93GVH! GVk>4GSK BGR P&GKYY(^GC5Ņ93GAS|nG=M29 G=ȹG8AfG40*O|D6.G2X"gGG.N];(>-G'ң:,G'nxG sc($G唋GfD820(G KG?OE@gGh4v>4G u(=6G C'GB5#<>F{92*F 듭%-#Fkp#4,F/&/Fӻ9*F5NE Fwi) FyTc$FF#,"FC$"#FZ(ܦ_9*FtF 1!F,>-FlK!0(FKљ~[`#F!8 F  F=1!F>2*F=635F9>$FMݜ!FdߘtFV=F_-;)FP F(S#EFD0+@'6FEi<;Fr F`lɅ*#F]}x>-FJ,{*Fbg4F9*F|F8(3+F7kSF F Ym7/F\R|  F_OT>-FwĒi F22*F lWFthu6.FC+j,#F31r; F}Ta9*Fwx4Fs4Y6.Fq"LFpy~FpVb\Q3#FnGS!:FlPf4,Fk:/2>Fhol5Fc= - FaX ۡ:3F^V٬U5 F\`/.&F[k 3#FXzFR FVԗ FUyB4,FS!GA1!FR0"FP7*0!FK+EFJیFJ@/9~ FIع3YFEg΍"IHFEN:]L1!FAU~Y.$F:t^=F8ss=4F8AF3D%.F0f 93F05GPQ4,F-ܩPF-1N7/F& F&cWF%z  F!$!5FP?9*Fq*n FW(FW9(FFA+`9*FFFB<>F>p FB6.FUF>-Fu$ FYOh! E4|SETy_1!EI; 3#Ev,Tr#E(GEGƺ=;Epu2*EۣV^D5%E+AEҫGP3+E#E;ȯEǺ҃9*Eyh|<>EܸJ5|7/EZE }$Eq)Etbe;)Eb]93EO'n-דEvE ES/b1!EĐH(Ew"|=6Ese=A\#ErN3<2"EqzG3En!Em5ܴEm\xB$Eaf EY(493ERP&gI(EO!A7/EBG  EBq5=a!E?1f5%E=\  E8',#E6;4$E4/V,#E/Bֈ4$E$-E",MkE"hJ c|*E!O3+E=E&)0K E=2d:%ES EӴE q%.EGNbd E}),ZsD=W4DW D*viD%Wޘ$$DGhu3+D҅D*]p&D I( Du=6D޹s4,DDٔ>@>4DҾasDJуQ=Dvp5DnI;2DӇwlDؤ:EA"D4n`F#D"^zzD._&D&ϡDw12"D4 DZ<JG:3D㰄#DQّ|>-D!4 !DF&"Dmv D*k0?DlS<>D D{|s}9(Dz5$-DzeDx-p:3DxGAA:DuP%xEA6-DpKن1!Dh\T<=Dg*e`DeF.'4,Dch݇d D^wQ|D[ʐA$ D[." DZGzHDT\7^ DT/؊= DR:uxg#DO7MdPa DNJ-DM6 ۮDF$DB2*D;%2"D;,iB|[;4D6N bD2kR:&-D(!O#D! D"3+D [O/4,Dj{ CZDR4WD -C\C_/m=4CKbT+$C钀΂CN"m=+Cy)C}ß3#CBHX C3EJ>4CC';<>Cʘ <>C&*9*CO,2"C> 0 C)ݿC'6.CmiCLjC=y:9*CJ-4 Cӣ8#CpϳC[F} Ce>iC}b$o! C}0y+ C{RItV-3Cw]B޶=+Cv ,CvTD( CvXAG;)Cl;k)5-Ck`@#CaEj"C`eNQ C`3צ!=+C_L C]PC[w/2*CZ^ CP xm:1COőQi:CL-~3<>CKݪ CK*2*CJyjk+C;t.$#C9LXw C8ى 4C5 HƷC(QZ\{9*C!@~Ǒ1)C89CUػ'CV#CҾ$5=4C@?' C/g$Co]a‹ C ECbg{!CQuBB-3BZp2"B霏` B~K"B6&B햱30(B䕋  Bި@bB*o\{&BBABj X+"Bti<>Bߵl<ٍB_.,#B0f1!Bdnm0(Bi 6&BiHܣBx~*Bt31;<:BQ.BnfG;oXBd[:XB"a0(B554,B7 K#B2 0 B~oB!n:B8Bū5MWV<>BMaBSUǺ>/B~D4Z>=6B~I3+By#D\=Bu8FT*$BpPiu Bg\<>BewqFZ'-Bc 5%Ba'K`B`AB\#3+B[O" ^-&BRυVEG1!BPYr?A4BEujl>-BEo@Q2BBi)` B:T1!B4"js&>-B3eB+Ć B*f󶜹2"B)C}⌕ B)?حmB$B(+ 3+B%M 3*;B$2.>-B/29*B R]$ѡ:Br Bjo^!ǭ BK BSj*B+-BF|B7@=A =89A' AT#A:(V4,AdRMA } A]m\RAm`B5-A"ŋ>-A A}gAB=4Aǜd>-A.VI?A5Cf$,A|ib Al4(Ov7/ANk53+A-?-AԶs*$AY96.A/>-AzLP3#A%ix#A/)#A03+A[͆AmG73+AӐ AnY#AbP$Al}}m Aj7URAjp]>(90(AekAdWLNAc{UÈ=-A&eZkd$A&%Sk A$^09*A"/Ll>-AhƤ2*Ar/9*A2C Ha!AXN@g:,A I:aW A BOx1)AdbZ܉93AW,0 @9ɤ$@Sl$@#,%@;(V@UF<>@O_@wa_@X&@׷nxu3#@#LQ=6@~l *#@j&@]B=<@l"@24@D=4@̗8W3#@Bn,@B @4Y@m#V;@RW(7/@W86v")@xwy&@%l+=4@zh;@k;4$@$|&@X8 =4@OR @8Y;2@K&-@~= ]$@|m4}<>@y2#@wY*e2"@l1)@j>ȗ @ibx2"@hw0_(1@hvL @`WA'.@\6ȱ @U]U9פ<2*@QHpvu0(@O׀#@Mh)G@L(3p@H75Ȕ<>@H>8 @H3> d~2"@G_.* @E:@>W1)@=-Vfؚ=6@<\ih- @-@G#C2"?*184,??uVk3+?3Ӏ:3+??n՜ 4,?pTW?K*$?&}wŸ??s ?hYm2"?bn,$?Ր{ӧ ? m+)r*?Mw&-?ç1l ?rO<>?NMQ ? ŘC?i?T44禢<>?D³2*?7d@=?@ ա?K%^?eqz>4?);2?yD{q9*?x@yQ&?ug/d}$ %?o!=?k{M?frN#?`a?\^Xn ?[t[:?[@23.7?T]9*?S0C3*?Ob*?]} :%?Pu2*? '^5>8d >Ѭ'*!>$3=>;-6:>mX5->x'E> 4vc>+73#>az&,$>什FS >ߴ.J\ >/$  >6H+&&>& ׺ >1P")>I+EV #>][y01!>IƋ7/>Ķ;!6&>Ão|->ic>6 &Q;)>V:%>$n4.* >>I=?!>ΏQ"6.>yd$>\~ 9*>8R>VL 3+>C^9(>G>-; 6.>$+>3wxc >1&S8> #>}E$ >wf<}>uǀ >sY">sl Jr",<>>m6A$>->h#Hs2">c +g>^9U">Z"Ҷ0 >W&ɹ >Ln5>3#>K~>&>EMD5$">Bz>->@b:1>@?66>;4w|3#>99KY2*>2LbH>1N>->/")c>,ܒ*4>*[8Q1<>>"4-9*>!i; >bD!>Wa:>>4>P;f>X9*> JYh.'>d@'T >Tr%%$ >Xpge >^7=4= QA=%f"=Ve:3=/=nk z=<=3mC=oVT =O93+=eB>4=?+u =K=-=# f4$= Px==&-=kA6h$=lR 2*=G4$=i\h^0(=ap i5-=}.ʀ=53#=y+Q1:==y5%=pG=lKsg2"=f[%6=cxF64$=]rq =ZRB#=Y3 U:1=XXREjN3+=M0ni =JBԱ6=H1 9*=EB%3+=@$=<~-< $r<ɍy+<)WS93<߰q_ <[ 2"<2==XY-<ߑ9*< }L <:Nl&5-"<9i_:1<7B׍6.<6|)\"m=6<4|r;)m <Z@ <S`b1)<K!X"<gf <1WH+$<S  <)" <3+;8t;Hf=4,;$^ 0(;WZ{;ȡ$Da#;&p 8;w}`=#:;^T6.;@Z%v ;܇{=| ;|?;խ~B.2";j.rِ;2;ЄcA>-;B`*93;ƽQ%;[z3+;JY!;7E~;pi ;˦ҙ6.; ;ϓ; A:;s1&;)O;'H w#;,Fa#;Bo,#;&; ;1I.;9o6~k<>;,l)b ;&pٷ;+xX>-;2vMf; ;'3y ;w) ;q @4,;nȄk;mt]T<>;mU\;h92";aT3#;\Y2";W,;<;Q𙛓=";NQ ;KܜdД2*;Hk>`$;E94,;C[XW:3;Czkޛ<>;A,KV4;:TVH>P=";:El:1;6f*J;5y2*;0Fn!;.r\۫#;,&KUZ5%;)! #;(֋?;(eGP=;$!ŝy ;#yVMz ;(3+;r.`:3;B֖ ;$;}E@ ;v_6&;pY#1 ;EzV$;|_-#; {oP9*;sO;::;P :}t :NeD:tVRny :,;'u::I:ށ)%=4:ڈ ":c{93:ؑQ?:S@"S>-:.J3+:}9C>-:Cx :MQA:B^]Q0(:j?3#:De[E=+:"{ݬ:K%FM :2y :X Z8*<>:Hts:3+:31C}:1:[{&:F߅#:o`0 :g"-`,#: Z&: 4 :?!{I3#:ܣ:ad2*:w!#:~aX9*:~+: :sA]7#:s]C1":i/oȧ:dSk :b1'+:[QFz,@ :XK+:&4$:WVTE/<>:U_ :QVĹD :OD-3#:H׫ռ3+:E2>P 2":EO $:BYv\:A^e.&:@@kC :=4,:5.u :+j_wH0(:*{I:(d=+:(F:t4,:$Qpcu[5%:",L :~7 :Ѽ\:dS^|q:}o:&:]t,!Q#:{ci :1: :͓1#: (: O2: LH93:b ::!1)9F3+9"yu<939)#9w0ֽ1)9H_:19'=49hr 97og"9#䓋o3#9qR$9*Z9e )A$P9*9꣹"r=<9qե#)9>IG|T9O=k|2"9j*9(9@7}8#)9НApd<>9M+  9|WR 9(3l9ũK|,#9Qb19o9!' 9 d9*95x 92=9oC48a=<9i#-9"Uu49n,%9C*) 91s4,9 ֳQZ$,9v%Ҭ&9qi 9mq  9e2;29ealk 9b\%n 9a[9Z+X 9Yʱ9SC9RH5.M939PAge4.9LC~:9GCϻ;)9GƏM9F)A¤2"9E %27/9B/^(-9;x{ 993fr93BLz<>93(`~ 9)Om4-9'T%IG9#>9"2ydA 9!s(1)9!tގg!9+UZ9l}G=+9E}*f:9_?i2"9$:޺ 9Jm#9[<ǿ=4912*9jSj9 )&9 k/H9bI9_:O0(8ax[= 8V-8;ed#8::38vi 8Ph'8j 9(8~+G'8G 8֌8&xb #8C8% ՟6.8c8vA8VL 40868883ќT"8mNH9*8SrZ8Dv]ߔ9*8_*F!*8-98v84,8N' 8$Ia88tx+ 4$8[PRA&78-8xi=48x>-8wSUf+-#8ryP8nyIw8XI$>48U܄ 8Pnbw$5N8L?[r5<>8IBxz 8Eq~;48Bt944*8BiаH8?m`d"8=|=68 7#B~;27vPf7ޫx 7c[r\-#7 D,1J7dw,K7ܭFf.3+7q1$7 H͈7n[0 7#΄);#7l%b=67@b &79C+7!u7TʲFE&7 ;)7 .=I&7M 73o>A 7P{n74:17_Wz5-7Q|p$7hŽO7I#T=47|a^>-7G-7[9*7!94,70 7?Fq?#+7eTNR7t7AA#,2*73ۓ 77?<>7J"7p`N 7[j 3+7}D^6.7|. }^="7z^]4,7z'!E 7ynoI9*7vwC!$7sY#7oe,#7nGo&.7l_<47lF>-7h]A1 7gΣ6.7dU#0(7aG}L1*7^.Ѫ7Ywl&7X싖;9(7R`G 7JE"lC]6-7I C7G'V},#7FKR=7;UxI3$7;S 79A77?^1)74XVP9*746߰^D;272rdp2$7+5YΏ>-7*.I7/7*cA2"7*gA3L$7'}.M- 7%39*7#V;D#7 *D4$7 +Sщ7߲uHX4+7(#;7rt 7{="7^!9>?7 p~7 ^vy7n7c|]7S3+7l[5%6̸=<6et3+6i^#dA9*6Ŵsi01)60 `go"6br6-6fO#6qvhӮ 6}3#6Szۜ&-6,t 6l?3D 2"6'S#,6#>16ڪZ%M:,6x 66 6))6Vyv-=4686 Vky6C7C%6áJ$6՟6.6acr2*6BB/69:6H 6<a(6Mĕ6Q-$i3+6p~\3+6!6U 6t+3+6V6B6<>6S&6Y:%6S6H@ 6m_-6=`<6 "6w626s{6sL$1=+6pEGe+ 6h$s/ 6e\:16`!qW 6UU<;26T)6RN&r6N8aGm<>6J'J'3+6F~+$6<>m]0(66,`0jk2*64>EW-62~ɠ3+6'b)!6 <!6:N6: 6#8'6P6x#6#Q5Vs6>45-5 Ăi=5|#+$5RD)2"5p-($5cfjg5^>}935&~%-5jO۾ZQ*5琏RP2"5exH5~ֶ. )5 ڰ9t1!5q>3+54RFa>-5XF 5 \3e<>5գ'F5Jθ8a8 5A55%A!5m=2*5 n 58¨SN5:ٺ[2*5y4,5{8=9*52ï 5Q>45%?BV#!*5.|)5W#3"57/55 5 FF>-50\7\-#5-&5PK5 }#24,5_5 75A<>5}›ˣ4,5; 9*5+NfS5ot5fm‰n5a} 5D !5~d%] 5|\eS35vV1*#5t]F 5rad 5iL* 5dw;25d#p{Z45dl$L5^$L6`$+5Z>&5Vc q#5VSoy5U+@3 5EXS :35C{E%2"5@n5-4Wa$V_4ߵpYO4$4j4ސ8%4ƞR1)4hH"=<4n4$4{Z4,4ȸFCy$4-cJ~; 4EJ:,4qY 4{ YK934|! L4"˯_>=+4)1)46c52*4R:P<:4˴3 !4(0^}4&}g 4A7k5%4NV~p&-4^E-4& x4$4d4S$4,4 M4,4\-4}24wp;#4u%2"4rȄ3#4oW&9*4l`}k<>4i(ig=44h|u ؿ934_a>/4^\'9*4^k)4\۱uE2"4Y-ll8;34Xԁne 4Vc0 4FGq0=<4:s >  48ն:45n!44C/+6&4(nVg:Kd4&Hќk 4(]TY 4t1!4wK$4Nk4Ǧ~4,4S*"4o9&4 K<>4 ˉyS#4 YM0(4 Dx-4 y` 4237<A@2"3 o>-3HPY| 32530̧33_73#3m\P3-3ܗu90 3aD4#39\T=63t23 [ 933dnc8z"3o$ 3'43GG7  3 oϷ 3f ϥ4,3´Sd 0(3Q!>-3pUГ2"3T-g6.3ͪnq%3xD;3S <>3 , 3]|3C@4&3{x+-33aIBR3#3Uh35*43yhi@f=63cM0(3-#-3H\;!3M`&3j1;23,v]38Pg?0(3hW5-3ok<-32J3xn  3w~YVg$3v:oC 3p}F 3o1GJD&-3lV/WY3k]iZ 3Z723Zb.933Y舆$3YnyB6x#3RU<>3Qesҳ3Q礈S 3O]3I A<>3Fnv 3A!(r7/3?U-#3?s\ 3>6.3;6^5-3:2XI39*3/d"3/5S$p 3/3Hv$3.Wc% 3-byF3'3+3#`}1!3#mPN33{a=3d9*3#3Ӗ=3Pɧ3#3Mf 38k*#3 ~5]30b8A:%22"n2v:At2IM6.23:32 H9*2CVC 20V0 2ޠq<>2nֵ=<21LW 2/n2%K7,2۶J 932[vZ]-#2o 2Nb$2`˫# 2ZAˎܴ>-2OM 2ŗ? T.3"2^cEr9*2~(-#29Xd#2a`Y2Ao} *299*23e,H#2H(a0(2_ z2cב452}9e 0(2 O12b#2z}oG*2yܗ89*2xZw9*2tÕqEQ"2gpVm?-2g?[$3+2fD9,#2f?%e@X2f6Uik2e2d12*2\tF6.2\$2"2[p#2Z7V 2Vfw:2Tl/-2R}r2P,U&-2LN; 2E5L2;_'t4,25xj Y5 24J' 21A0(207U3#2-=>-2'`S&2%vz9 2 sG0(2`2ﶗ -2 Cvm-:%2b6&2-0+94 2hڣ-2SQ|4$2CQy9*14K+1A1><>1fӱ3=1.ڪ0(1bL\ 5<>19༏$11+$1Rc1V*>-1i%:1ٮ\)+#1U'TA>41נ/?<>1c%"1 ap">-1Vzr>-1n9I(Y1!1=}È0(1\He2*1 m;41%hyU&1@:æw 1'b1 (J6/1_ 1s5[B&1ln4$1mD1$3#1v"&1[1~ѽ 1)1|0qn4$1z?5>$1nF:13+1k:'N=+1hѬ/E2"1b)b1X5PwrX*$1Q 1PBsH(!1OOim 1M3t931KQ4$1E!I 1Ag i91>$0;21;v v0(1;J $$176!H,12;4,10478/%1* SC!1)r1(:%1#&SS1#QC>41#w>-1 jJ- 1 ~Oʋ1 /4,1sX$1|/ 1]6BE931 x_;41z0EOH2*0)HB#0 o<890uQd2"0R 3#0)4w'_ 0tِ5&0蟢a0@ >O#0zA>-0 1#0h!(Β$0D=60@p4,0B¾)j0>Li,$02 0&?3&=+0M2Ay1=40Q&01<{.9*0YOKYk0hXn0NTm;30bT6{")0ԨS>409 3+0m6^ 0"32ko:,0sR y5-0 'g#0W/Z\h 0*BL0p|d 0n-sbIy:30lAL݋ 0f|=T;0`J?iĢ#0Z0W[ށ 0N bk 0Mu'9*0J@d0(0J-t)B0GYe"l 0Es30E+h6.0D\ǂn#0CG?T=<0AD.0?/Ti9*0;'{ 0,<=0$<<>0$/6.0"7z 0(h}1!0^Q2*0XS"0lB!*0 #{!0 @Qq 0 HF0 9 gU;40 ]01)/!Z=/z}9*/~WM]9*/Lk/X $ /I9c /Lt /s/椃7B:%/X2*/}j>-/s1 /'ER /݄OwH*4/܁wct&/ U /_4]&/(&Mi/YՊ /o` / j$:/i /qW/u<9I;4/ˌ,%/?eXH"/r`=/Ol0 /M[<>/[2VK:3/op4//"_-#/40(/TH/×w4,/eD   /::3/qI&uC-/)1;1)/Yrƃ//%1-5-/7y/3u -#/ /\b:1/5{29*/[ʞX7//` /{E  /x<F:1/u!Wk /sMuZ1!/r'j2"/oY.;2/nؕeI:3/kـ'/d݉<>/cNpF/a/]ӅlRu2"/T$Ta⍲:3/Pi]][/Ps{VK/M#Q<>/F3B~#/FVG=6/BߖaE/Als/?Rѡ!Q2"/>9N%-/= )%m>-/6//o 2*/.C9$/-Ca4,/*`=/#t/1*/#oYP/"l Q/B4,/y!/Vܹ"/ ڬ] / M3/}#./Gq@3#.?0(.K~=6.\ zq2".::1."c#.Y6&.:(.&u{  .Be .8Й.ݏiZ' .8  .K4,.pC93.(#)4,. 1!.؜ ^a:3.UC.ϒޅH<>.%諈.Qo9a .RyH;2.(z1).ȼޗ=4.ǭ4,.Z.꘽8.E .R C&.b"s.qZ=tz.@\k/2".o0,#.)B*&.MC1/dr#.ø>l.`H+6&.Dt5T .r@.pΰ3f6..Fa2".x=.S .>.~x':1.~w  .tCZ$3.pf[k .kQ-3.jer .j >^*#.gMI] $.d  .Y<>e n$.Yj td]2*.Xl .XBl '".Pb\ .LHy3+.JF.n .B"0(.A^F#).@x f$.:63#.55)L2".4xt&.2YE1-3.0f,$.-$ 4;).+4"05%.*I}<>.)AvT.'Jw93.& #.%V.%b߿.$x%2".!7S.g$.46t;-3.$wԾ.2*.\õ$-.2Lé. [fA* .Ϛ .W:C2*.@Q0 .Wc*-A (2"-A3=-jIB-/j\>--/|̫;1*-NSc")-Bxh - ax-٫T}^4-O`yW-Wk`-Ȧ>5ui-ѣ漮#-$G56-ۈsn-ʶk -Hʿ9*-6F|-$v4,-9BcR-Od1)-!{둷"-P~0(-*B0-Y~4j2"-LC9*-MHu-Xi%-v@3f1!-&5B- 3#-zUFf=<-bc>--D--  -}sj -}ܛA0J0(-xj&v&--p&2-hk35-3-f,\, d1:,` ,U.,}Bn%.,CF>==+,^tR4,ܸe=",we[,s<h#,̳B,!0lc=,Mfj6.,ǼGGct82*,D?I!;4,u ,{%-,8KS0(,t.;*,[=",52!=6, n|?d",ċV$, Of3+,o2",K6.,E?#,LZi&G ,sŜ>-,,F4,, \kP, Ez*4,T<>,x~gܬ ,xQ4:,w ~,lZ\=",jU.",j$^y<>,i#2*,hМ ,huQ 3#,dx.0(,c@C^89,\A;2,Yk:K*,Xn+ ",WF<;<,V4;* ,Vfח2",U9Y>-,Qw;, ,Nhz,Nwn ,M ,M&= ,L_rhE,IGy9*,I<j6.,IrW'%,HQ :,,Ds'e ,CU,CR +",C^U͓ ,AQ܁<>,>s3#,8y,6#rL4,,36.,0ɏ1!,gOGv:,p,~ ,~׆ѭ ,R,#,ӿ{=4,Qk#,A.( >-, [c,fJ=",?v$+;AB9$*+S_p 5%+u;$+SvU3#+=SZ=#+[p_82 +b+Ka~6.+Ee9*+󻽏h0(+Y:#a +藺G%9*+ xo-+֦ q +ԠXvO#+LqqZM-#+ʽE <>+]+ɶؙ+AW̓+3; ,L3=+V| |`+}r`+{{.5-+z˙6.+kl+nz;.>-+_ [1)+|+*rP+q 3++-+N:3+ީP<9*+vHK:>-+Aqik1)+䍶9r$+x:+w/Pl0 +vBv&_} +ua4+usu~+tR +s\as +kNO:%+dxKmN+b7 K9*+b_Hо3#+^gF +]<+[xH#+Y%h&+HOg +AqJ[3#+9-+83Eq:3+50 M+3`W{3#+1 qxp;4+/UN5+.$1f+%Ҡo +%)1&?!+!zOXX+t;2+ׅ1!+Wvitv +>|p;4+{,\&85-+(!u-#+t *Q=T>-*&7*o55'z1!*j[&*=;*<*DZ49**G:*[d] *ѠkX"T$*8ټ !4,*`M13#*|E|4,*ƃAx| *,a!l; *Vdѭ&*Uk-t 2"*-=-. *ӆqA<>*~ 24,*; *Z3T *zxU *<{ *EHн#*! Q *V2 **{ *|q m*+E$*"Բ;9**+FŮ:3*K{,#*D#*y|]>-*9w"*ggx4$*.40*}<1)*{j4,*z&u76; *zAآ#*rL=*nWxd*i&Iy}*9*cL$*aOO^-*_, $*^ ɻ/*]0U0;)*[ cNh$*[o`U *[HPv*X;y*Sx1)*RC*Rv? b*>X牘5*9kO6 ;2*1Ed>-*0W/*,;R9***\ *)h7*'͇2"*#n *#$~*4*q:,*=&=*M3+*Rd0 *W73:%*:{(X*OX"0* ** S~3^b$*`4,*ec&X):=4)Pbd2")筛P]w2)'?~1!)[ ) );3)ZP8:)8$#))NL0)˵6|{4")ʠT87)ʇ}2")ɧ5 )Łg )Sz. ))-* )ã/D? )Tdr=<);xdp $-)cɓ-)P>l,!=+)h5`2*)@đ)@Ck)^!չE#)?Q)-.#3+)A}; )YJv )|*)Y1Rd)iÔ,:,)8å)_;2)ke<>)3#)y^C=2")p&A-#)c,&م7/)`#$)RvV)QV>4)Q,K&)P)fQ)Nu5;)N128)JG|T)G?zW93)F01!)Et+-m2")B\mm2")>!+;2)=g1 )-) (}=4);M]O0() 5u ) 3n\d6_>-) v8$)}MK>4)t|b\ ) )1A$3(<,b/ (N %$(I9*(,(](86J (cѷ93(meb0((a'="(\'A (sSl41!(,s;<(><c:,(mv͕׺ (QY4$(͍)(ѩQ>-(Zv`y (8T4$(k%5ۭ6.(r+Im(;Z+4,(ŸF73>-('v  (d9*(mT&(kV9*(~c-V!(pd[1!(XDS(W$>-(xi5-(!w(  (\:O2"(.]rs-(Dj&(0(XX$-#(rŧ~(4\ * (2)="(|ղO (~yZh"(~p!(}&1!({&c0((z&4-(vऺ=<(n%"(]Ҭ7f(]I\;4(S:o (R5mL>-(N36X(M'(D\ (CLgKB(C1Di (?rdb,2"(?1u_ (<@[Ѡ (5Ǻ""(4F]9*(.ab($a("hn(!h($( F:3(cXs(RXC(2( ba4.(br'K<=(6%(z|']D}'BӢ#'Kʴc@<>';4'팇"jZ'݃ '.L:3'ˣ\2 '>qa2"'y<<#1)'h>=;'ՠ_;<'ԛ4="'ks~>-'%I2"'ǹǽ="'gX93':p="'cF4:'i!['!'G-w1 '9"'MV="')2+'Խ#-'o#'#̧;2'p;sa,$'0:3' B=4'd嶉'WD_7=4'.x6-3'z3F* 'Ed'ėJ'ͮ  'o23+'t]g!'־b; ']0('yD<6.'ro(-0('ft[n2 'eo>' 'd>o'c<~ 'c@6&'^-'\K\9*'Y{yR 'X]:%@=4'S2}A 'PUY1T'B`x! 'AAS0('=H9'7  '3'AJ '0<y}z *'+x`r=<'#| u '"3Is#;';;'N'>D4"'*5'k'I 'Y5Y#'!dzZn'  7 ' 8="'p>-'4񺒹4,'jʅhL&FZ/t"&A&N^9*&7ɯ&}d!2"&WOj:&Z _ "&0w &{= &j/y:&㓺?RZT &rH&ٯD5%&Fu텣 &daL 1)&Tһ ;-&4qV &̊}ݗ93&DՎ"5-&{Z6.&>o\ &ôg\w93&T9n1&#*"&ftU3+&U2*&Tki9-#&m $V 3+&8~B^;2&v &&&ܼɬɻ=&f&X &}r;-&X5>4&b &;C9* &`4$&©j5%&#h&xO$L2*&tJ420&pSHSw:&my.SJ&h!&e*X&dӨo9*&b9%`NQ**"&`{&\3+:&[R4 eI3+&R}w&RVb&L&W%~&Jս#;&H.lJ0(&BR49*&>xU?3&;(g=4&5ݺf>-&3uHW:%&34.4,&34 A &2 &GM&~oU&g8:& V*#&4/&s>T0(&zLQ&)4,%2"z % =8:%V %Y~$g; %pv?%M}zB>-%y>>@ %$EW4$% N1 %=l@-. %?kͿ%ۄ %Ra%J03#%p$y:%x}5-%z<,0(%MX %p˦ %$C>%(.H`T"%ۼ%c9832*%w\x%Ge]>4,%lyq=<%&G%Oӷ%%fb#,%cc=%K=>B%Qd9*%he;2%}S;&%{ce %y5r%wxq0(%wJ0%m ]%jQm %f[4,%f%Xķ$ %R;)%>Db%=B`0 %;%t?:3%:U>-%2i %1i)?9*%.91^%)׻Ǒ;)%&J %%HśJ6&%#ƚ$% ]{%{T<>%kܬ2% wJG,7*4% M3+% 4A-% {l<>%Ji$e#%Bį $|)+ $Z< $5Ym3#$  $mR.c $=w $ؕ 1$ٶ $.s`$KY$$Duj7/$唄* $݀}27'$gj@3+$%q/$e1)$x,#$ʗ $շq2*$Y,d $ɩVs-#$&4,$MH#$m0$GN $ī]{$nMO?:$2"$b'`$u6$Y'<>$ :$G!\}#$'€ #2$O5$ܕD4,$NO$AvՊ=<$27#&_$kK%:%$#~<<>$*Q2*$O|2ڟ$2gVT93$*u@@$ ) !$~iѷ2*$}#$vU3#$rc`;+$q $psi8$oS ~'9*$e&o  $`j982*$WED$P</-$P)$m $MPθ $Jx $Ici:%$Iy%-$(n$& ;2$ᮐ-h#$HD>$>0 $$Enza&$ @CK$ ;#2"$ :$[)$h$$\^u#y3$#*'%.2*#2;b#Z!j3+#C_5:,#J6 ##g2*#A<3+#,F6F#GBU2*#0(#ܲ S3d #ց # ##/<>#jgK2"#X:֤;2#RBp:#4 h|#O,=E:#T;O#6.#ZYd!#M.;##4G7#7)e#bP892*#UiC4$#[l:93#`@&V #qV5u'#B#S7'#P;%0 #$4ܞxr7# ##ϝ$#tг#9*#~U:M#} ]4,#|Q7$4$#zɟn#z6"3##x4$#sa6 #jdn;2#iZ)! #h9*#gi<7/#ak$0(#\G 2ɏ=6#Z<(;3#TJY-'#L&7l#K 9",$#GcCq=#E:3-#>8j^#=B2*#:66.#8)#8jX>-#1tؗa1)#0,$%WP=<#0O!##-5R2"#'[dT/2*#"Y$ *#!?nGy #^ѓM4#@:,#fIw#%~fi5%#98$#.04m4$"#9*"7v/6."* X1"𚴥 ) "퓗t 1!" "1O"&S[%"ʫ$9W>4"<"|5 w "//=4"׵W 9 "֩i*͒4,"ք+y4$"'L93"Fk#*"^ Ņa\3+""&)  "ck:%"g_@+#"'^"j'q$"_";W3+"iVu "X@/=4"3 y93"$ͦ$"6ֹ¸>-"|m];"ּx3#"hK5,$"|g~W\=4"|8yo#)"|#߸ut "y`^5#="u8<1z93"mIyx"l+p "k0&-"j8+;&"d9=ށ "`ZZ4,"`Ds S"]p}#-"[Lp "Ykw,n<>"XF/6."W-#"W ժ=$"N[  "LV5L=4"FLDa%"A|+.oV#"AUu!*"A.'^9*"7p}-#"7=p"6ɣ۞4$"4H_b:%"3D :%"3$烢"2U["0pZ,o2*"/c?#".8Ӎ<>")M~#"#J^;4""vA9*""wP`<>"gB` "Y^i"$@[" &l3#"7"EG$!v$#!E'U*#!ԄH!!"&;2!V$-! ?B !@V>SQ>-! 22"!湥f^ 3=4!v}D!uG+$!ûğv1 !äU;S;!T9&!5\L<>!@[b 9(!4V--#!}o;3!}OE !}KŮh:!|4m&K_!tTd*!o3*6#!k[(!j-h="!gV8x=v R,#!6;2"!3V3f !0/X7"!.q*j4$!,e<:!'Ӛj&4,!"AKS"!!\~j93!!!j֣_=6!m3- ! oŜ,#! I4,z>4!qᝦ=+! =" d1b>- j-# jx~*`# %/9* ts؃t *4;4 k  xS ?{/ ^$d& ՜O-3 ]2 o˫;2 ҳ E   96( ;) `>- nR CxVo# Lf knG  }hEv-# gFfU=6 ;[X  ń Bh a֌ M wp%j  (w\%l  # F%.7 '~uE93 bqHC3+ t} `j0( = p)NA2* ky.y  iHcd4, e d ^ _}74, [Z&,# Z& Y[r_>- XMo' U6t =9* Tͅ RTIWmB NK5G>4 J{E9* HjL}8 F*p" EǶscx3+ E@#[2* DJXUI0( Aoo6. @4!1! ?7gI>- ;ƒ  ;ܢ#: ;u3:5% 84: /+$ +Dy5% +k1) + )P|^< 6. U+;) 5B. >t~ac& ՜bU0 6OM d@&Ф<4faa6-hVz &^\S9*[hV  !1Aʱ~93AgP/1·m6^3#x$ ."dςX93Z1!9ކ09*li0pg?ۀd03+\8 n3#3@G:9*-ֱ*0Ql3#a-V@i9($t63+"26+1!qf]z ӣ$a~v啄h>-~XOO|="zn !z yF y;q#xn6.rF3#jֺl!93iǙy<>`|F^1)_^cVi ^p93^" $]p[2T7'XJ-Q!*WPz%.V.6MT|ł_P'%?PGC~:3E!*Bt_-&-B9k2*9t9-.Mc'7!p %}C=6$mjb2*#u} .uIO VQU G]|=" X^i X +- P"h6D RÞT|&r2` ֐t<>hj%5%+M49v-5Zc/9 C? hp=4$UK. },$BBg9#) &+u9*1#+@r8>/ޥih[:B-"$;4P!*f3<2"&2*~Ω,93ZK1yi"fӮv:d y ǔX^84,? D&*'>4A9*jl>-4px!+F R v9 L?3=N&Ņ|>-uDN:1Kl R%~n rZwl 03+vuLO] s2(+St9*nf4,lDN4"k Ρjc 6.i7=6gK>-cMl ^r#[$j9Z㲓!R WUp{>-Q!@ r3+MtO f!+$L)b;2KB3-JF6q% E#*g <꫙T&:Dl&-5w0(1 k:/ +5\A1))#;#"F "Έ }W7<>-0 >-!x=4|s,`CY/   4 ! ]D &e,l&9h=6Iw$$[яa5PK * g4g P%kcO 3٥:%레ӥ dzVp #=l)m֝eea7/,; <>Zx#} ȝ4}:%ƣ@2*‚3(l7/}20(o\3(=<21]; H6( ( Ϝ{= j/o)=+ji FX#/ r>- F)cd93(I+ P#|)ƒ;#Z-$Qu_,#2  F |vHT,3+wl  sT_s˭>-s"tv6TʈĝYPX>-/o>-& |>2"'q"-μ=4ްXN ha  h t)x:3  %nw"K|#nӎ$&?9*z7'9729*p P"<3۠ל1)}Gq{JHU=6t߸ ].lSid5-iś~0 iIhy&gvifŎ=fPV>-c{_c%@:1`Z>>-^r8Wz%V Xo VXA/'TnUR2"J3u|HPV3f3+CF^OR$A@t )2*@2*?xk=uK#>)|793r*9!;'ւЯ $ [cG9*G@w* j){Y E̠Z'r/t  2^\T.ӕ ¶=4#B>-j;=6+\89ۭ. 0Br Qݍ ߳.&3+_{Q(|ʄ3+Z a93ۅ@="_@_qMd˶93ѶA9]9*4g'q7/V9o4 %ڕP:Û>{7'tǗ,=8$CǪ&-V '̷7/?3 *4﯑$$="T+# \&:F`T-=6nO0(I p:bW74; G&- y#} WFv֟&1!-WT5% Y(9*r$~Ym)Qb }'9#{{hx4$zCrt(ftY.1Ԉ'=4iFw09*hEq3+hJRpV4,gZ0(f7:e,e:6.eMט!c,"ы!b\b6t1O7/`*z _9*WNbwU6.PgvR LJ'`|&J񩑻;<>IdE9*H.k^c9*DiBiDfr%C?<><}/{0 1&(d3#*+bw1v%)`/ %})M;&#- 3 <> .Rf3)r !.Z19*D  ]zi: <& K%=+M:3ڢNlqy932W_gұ,w3+r2tkd9.t9*ϬU :1&md 2"(A2"gUe0(rjKhJ-jgP9*]!&"%$wg?%$8I.A Q$̴4r }#2"j Z=4*rzK1!b/*0(+V#u$-  ;>-ܱeFCp ~%T-|܉:1pu<>p\y Do:p8:ngY>C#0 gA*>g犝Yɕb%{aЁ/#^7M2"VN9V •[2"Q,#OH]4,Nsk$M6Ӝ($5-EeK C?.<>CEs]}:34ez` 4EH\0(/L1!#yo1UF})zm;)6 5rf&o00 ,<>BF;%>3#,1)mJ:([$b-/63.Dė :11>-+r3#onWL9*B>qږ4&Ȇs]T=4ս똇3+ѽ`1 n0v ǩ>0廒ܢ2"ٰ᭔->-")Ȍ; ed  _X0({sL:KAĀ/&>46.OPC#FgZLs~ Zu93!A Tnt03Ws|)0(L{w.)^9*p>-7hOy$x sߑvr #oTuž>-k}vjÝ,=6gն"fBq:d$g# `kyZ2"`9O9(\|VjXe2=6FL6.F=B<>E:m]?zM > #kg9b<>8:2V 7n5%6$5`|94,3G:39;)3&ѻ{#1^U T}#0k]7/,&2>-+2jůeq2**1Hy @F cg6y89NNk;  mF=pD4=`6=΃ 7̵$HfؤWCX  71j쀰 4,  \VC^ڭox`$_# *"۲LL0(-P6>-ٞV*ّ[z/ dM=<NO{ ҳuuyd3%U%A,#vJe!(2T k2Cn>-г F- T#Xt0(D5q?j5%+=4"+PE=>/Ećp/dWjGV3"p6b4]O9*z?@% M[rgpʋKM+gj"0s,{"Y>/'Q`f4=$~0/"Q5|@ {Յ*bNm0(` _FRle^w ]GS ZD[LJ&Y8XX<>Xh XNˆ XUYiU&Xlt<>Q<8E@9*N#="K'qB CC#,Aw.LJ ==!=<9.> 5Ԅ;X$5*Dv 3=S=60lɬp*/Ps%mD2="kOZmj=61!u7'MU 5[73#-2w  ezFn -9->tf?[) -z:K*;g+i\^-5-zy*4z)>=6u˄a  Os:1!Ԭ2߳63+܂r=6ƭ:3 $49* 6.Іn6.ˊ#c}=4H%)^b4==w"1П#,=z8&}9)#QC.-6.7@ ,#J 0 CrH0b*$C( *L"f4S ¶&3b5<>D"^"89[%89yRMsvD!sB 0o v;W3+nL"lFQE)Skz:2*iUѰk=4fI#ԥ6.ey2*^7%+$UyT:1N/b>> J\THIw5>-Hӵ Uj4$C 0 B003#>V-U >5*q3+=Ѫs<>-Y-::;  5W3+*:(E cf<>2UWメ-0 E+$vҏ0x*1! -|ߚ :#  _d# Si-#cbp? m;ΫRvq]|L 90<>Z2""wv>-k=6Z15~Λ6+0(6 WhD ܧ*! Z] o;3G,& hSZ* ƞ=+Ҡ¼,#'(R!Q/ ?54$  sM5%,r}\!=\FGD}z=1!,=6;^::(}^}ي]93} ̷|;vxw>-p Th3#o r*]; nN*)=<gON f)ພ _1[Z$2c R4JO"{| Li FA !"E3F2*AYP6&Ag&65OY4=4>A%`2*0--+fPV6$(U!*' 3e]#z12"#:"ݢ KJ_ċ=4KL%.+̛p aˀ-r>-a= &  r4_&HPC-39*-u<:̺6.dXngA<>jo\j#o9 j6,+5p"6&iOkhQC{gm7b>3=<_Uؕ^9R"^a{ȼ [#X]4@T4,Uש@eQ" L0aN DƗc AYW"0(@Ek:3> /{:1m 9Qf\,#&Ba/=.2*LN,#LW%$ 6@  gK  ũ b\=  K98y "ͼ"?f /:De"4,Φ̢S>- w0$~q_?6-kC%z:N2"$>&ް0q QB/#K[ fuLZ_="ao}&!f;4e^$ >4i24,i;T|=<bwC>-^@;X [n Xљv93Mr6=4$J&=v)=6I=g0<>C\K5bωg=<.^E=4'DG8 ;M;=6ҴxJc%43+a%Y4$rC3:K+30(RIUr )d! =+H6&-_=J2"Ui b93ͅ 3蘲3+ ޢ8~G];2ᗩ3-/鑈6Ɠe>-I,&C<>ټY #m>-=48#נ0M1!WxŒ ԻShk?  ªi<>%>4G1:1X2` }w<=W5{$cSآ=<& `XV>-FeF=4PlX cM L{ !<*$I~7 *9 ^0AKC1M2"8H^=6CDap#_u42*N‹&>2 Q<>4HZ'-#2Wd2*~1r/ { ȶyI(6.xa@*:1x`rjB u wǖp]o%?$ kW& h74=J:p$e2_s;<anϳgu<>`,:D\х4,Qanv_3+:-* 8uc-a 935of#1l\Ʈ3+%L4"3YCJ1'u kIR>-~9*y7e9*90ݧP  :3q*u21!O)gf ;$-7­e#Gg!L+<<>IxFUR Rlw,#pW$*6_(zZ _&-Z|2"֞).2"[zn>#Ϳ0Vyʴ[ &2"ՔҎ bR-<ƠG`4$ő~*"UU"X_I3#`.'1)mș=4Eiz]!x]193B=<Ʊ/CArT7/m]3!Ԑ,_1=~ZԌ*|4E:qɐoiC%oX=4j֐F>-gÿ>-cG1!^803pg Zʧ"(W1!R+I/ Hk oE0(GGnT4$@S>J5 ?z'B"9q$4B ? /vLbA-4,+&[!}k@dȄ$]t` !=4 2+!ziU YW  ){( ̸U3#sF7H#k ;hQX=<sJu,1)DR11!!,WLd( ɣ9\0=6L9*7O0 10 pDkU;)hE⿎2*ٱ8Qv5H#Ҭ~20(Џ<;<> |j 3*gGwi>--EuL6.k?' riNR-ʥyi W%?lc8:̆ F$+9J*:+1)$3 t[0(_ֹ[[eH]d "$W S;)'n" =6eh4,q6TWa!|59&vnS3)o 2"k4,ff}uo5-`V o>-_a/?$_Vc_#SsWwFRWDGW|0(CB%> -<#7Qe-#6鐥6Ge|}d +xU=*g *ޫ4$'I5:]-& W?"#RQٍ# Z?*b ^;2"`Y1!IRv9H.. 13#6wkIl!4$J7BKW 2*U:7.e6&w31$0( \)]d <>9*y $> 8N r~40(& 4-m?}-#}=6|v[Nh6"'ﵾ;-<>i#m V5-~Ơ `$-`>6=4\'h0(&ˆ)!R 15^M^W0 TD5%fF1)2*:1a$č i0C1@Wh"+\mI 4:%#|ߖE; z\9*lCH<>ja\a>-i) 7 d,vZ_޲c]`#^BJF#ViT% Oz6.M'EQQIc0?׭:3Gb>#=G) mG ?hy=;<.>-7b!65-$2 4ʠ#1Բ9:,,!F="%6!F2" ITi:,?ea /QZ aë&82H& 7ʫ  +) !a  Ӫ qN@5uȳ1!=<տ:~l,#tb$=<󮲲d GRN4SK1)H[3+0(p%c;9*$-6cc#50@%93o4|]!ЀpDfaWb<>J(2"ei*$ h>-123+q \v7/n)ʖ B͓<>| v=Yֆz7/;kS LF6& H#;sy U3+n/;  ?[)9#:3Xd9*詃zAj7"qSJ3+ZRZ=4,k89&}9~SQ }zUg |NQW6.sHkZi>8 k/N<>jiA8gR=3#g݊ eܛR5wdCL)X+apBgQ `K1B>-] ʏZ#%@3#X\NwO WvSW#WR7M2*U*¥2"GoIyL$GElVT4G.LT2 DE:B|E$=U0(:Zgz9[{5ԓ:3-3yjZ-Aձ>4)PfJS (Bp ػ &6<>!f*s0(n~c-' ͪ HQ 8:=6  x.   x-&{~vY '  /sg|18<˩}2*  HHme x'JZ9 -fx=6HTe"-˺%-3A`*"⁝4C L?Zp ?d>-߷~:A# =+4,ڌ9;2ڊkf#DbQk?n vB93Y-<>t(=6hXj; f:1épz:X4 n 9*\u:%L8ct2*h/7r5O 9*7qڲ _M0(\3+^Ֆ^0(-?O* N]#L32dv<(d89ӱ *U*[<>{+"{9H$,#w  w)ebJp?]AnM6.g YcvV->-b#M (0(_hiG™2*]=F$\ =q3#Yy=<WQ}|#VCRϼ)x QtYPd L}d K~5%Js/ Hþra GD FU!*EwQ5893EudU2*C#H<~B{4,;г :U49*:ڋGR4,5Vތ5k%9*/k$*,O(Fđ ;(:Ou^$3NJMZ4, =b   L r& 6Zn&  o>- pS F   Qjqh4$ ]]ڭ14 H2|o; ֜@  cأK qR 3y\ \F=4 % G"0 ÁX XB  @82* T!/* 3<B  .У {* K8 sw/ qg1%*; ЯYe]>/ 9`,v ն 2<> yZR:1 7* Hh.* _Qm 3LK  o`&p   YE e{ PcL& 46OF2 QC; ,dl2* ;Q! 7yq_/& | \h fj] =  f=!C* eĚJy<> _h9M  ]8?r >- Wמ$  U# S;L<1) McZ>- Fd*4 A;bqc*$ @2&p$ ?"R-   /6)2f3+ ')á2" &|SO>- $Q(=4$ #Ks9* ! !`Lt4 p3# ؒ?٨   A9* 1 Y=4 Goqh$3- ܒ!dm ]^A<>  :Z ϧIV-" 4&/ n\ 7[1! ?;) _0( \6Snm=4 +7-3 lnZ Rְc=4 |ֽm}S  Ŧ*i<> ܍qأ3" ܇ ~ ٧| ٖ;$M HD_;2 >hW:3 @TT$ /'3# 6c: Rl{<; v"4<> 㜅 HB)  %x[=< OJ ooG4, ~2" aM5 n K y4-4, ?$ ش# Q-in YD=4 \ 2" Z윝@#-# :9* $& }&Ny  #;9;) <"č l8ģ1) c \3# ai:3 U v0C9* vf&T<> s4}P=4 p*.~ p#:4, kж$ iÖS]x ev 5% afc) [}\ Y:'=+ U]H1) Rr#ѷ93 R&PV  Rӓn: Nuv L`v3+ H<1v  AXɼ!v>4 AQcE& 7Tx; 5xа!# 4u[N ݘ= 15YDu: .;M=: ,q ,om[K   (x2Am:3 (/R& I^u>4 o5 _?  :, TV<> Wͪ6(#) Kd93 fm1) 13Hw  I^ H8Ii3# X o X Lr*2" >1  I"* ϖC4  1) p3# <&׊4 l`$+ `2ػU9* UI>f "P`2" ݃Ǝk=4 dҵ[4 y`-0( ʃGR޶>- L"%a2" Sd&5$ 6L ßO v{lF<> Eѥh K&#0( KЙ \+-0( ij8ty  !* -D h J4$ k+2* 3l\ ʽ(0c>- jg n=6 .P/ ~t% 3# 2E=+ < N0)>- [z  xgI  C&  ~l=G:% v7 uqҰ" udPC`=6 t0;2" sS0!=4 oi, kΏ%m gMTf~ er>=+ a,!=6. `@C$ Tj!?P4, S4N]R6. P2gV: Me@ M:H#0( L0( I/$ EAslS @ps 4, @3 :3 >f` 8* *" 0fA -Ix  $"-3 #ݜ>`+2; "ml6 "+>- Z63>- a  eY9*  =6 uX;  ") tǟ G<> q@& "F7 >- ]J"] O^4$ =\ܸ*  +M=: t>- /  lڗ; yD  yB > 4 "}T>- mb_( LhNה  sV  ;H &У HHD!1) _ᦜf;) b( d [J-3 m3 >4 KJ  "u$ *n   u24, y |#R; xV|ݚ]$5 nr-  mFo;2 iw5% f.8_3# ew@Z>4 dQDxB[ aIJ/rx Xڼ-.$ Uqp=6 TX63# QPH.3# PT:,FJ  I8FX GjS-93 GF;# Di/%^4$ 72>d:1 3!O42* 01J* .ap& .[f0b* (oL64 ' &( "Ƴ: ;2" =_j3# 9r =6 Zj Kߟn<> Kv_  .];* MZ-3 $=y:c4$ OѺG  I>q?l  (d$ `1M\9* D{!g * ?ZO<> ck 8k3+ QdL$ NZ:, ^@=+ ANDc&- 8-v$ |JD- LA*4 H^':1 ڥ  {Nf  Ι i% ֐mc ՙW492* hoڱ:, ΚU+^Tu<> VI\# 8\ =: +X3+ $6:, Ĵyqz2* ht$ P:1 чq + 8 ڐ0( Q & 0t6. [Oj93 ]y;& #͹ 3# خq-# |=) =< R1H73+ md  0 zPt  w,"Ξ93 wTXUe>- u޵u7J! g  f m d1_ cG awry:3 ^eS; ]܄  [>5- Y!- YQ3%1! Y;K VB# U8f3+ OyA O?َA N}-Z`# M"Wu M-iU K$mF$ KeLvՍ J/1) E,!噧 CZX# Bp gm:1 B6. ?6P{R5;3 =3- :O= -\MV +j (# (D,S]3+ &Ƞ %*}0( c# 5>3& Qi C2* WX:, xCp; Q'&- \f>-cJA u 2";k{\n Ӳe  <>MR89*93ϊi=:3BA>-\f1!Jr!߷[2q.!*ޜ6GY 5 ک(WD"3KPpQ:3 =\:%ҩ|XW}yR fk:ӯ *EXNV7/(u =[0#Fuv>-3Ru611)+ɠ4$_|;+,$p,u{ S 35:,4f!Iv  w v:1h`&-s+i2"o+83!j(D{;9g))T1)gu%"gj4 bso|1)ars]8=]2*] ]J3#[#J"Y(3 U6X&-T%CۼL K$,IBy^j3#I`P2N1!Af`c2"6>sǠN(3#4^WJ->-)1)]̂'V1v&N_A0 %9>֓2*##y !Pe|:3!: 9' UC9(wuc8: "  G؂  Hu* * v5`G!D1!6:3D u'1OxBlO*#zJY%*)#7/4P ѣ >q,%Z7/i@_S|A&҄$-[1!ʃ.!{ ƍ.SwZ93eйi6.IJ9_c; o6.ǻCD ]v#QT/!9*wQm#ڶ #2lTb M ) =B{>-މ @$O6.u?Y1:R:^0(N4,\4, 7ev ~Dbn|eVLc ~p# ~7B6r! 9*4 , `Kp<>+sew*ҰLD*/?p y;-* g^ $ف:-'sPZi9(=k ~MQ 6|W&vg<;Ak!@(eO 2Y[1!G5.| _ݯI'ړ!<9$+ 73H-&΋3+.D4$X5BFz-#F;c<>؀A=:Ԭ 9*pD?&8~:or]<01y"y}f<>q)+G3+|NMJ~3+Ѳcx3#(;q3$U, /4,_$$=<cvbK!/Ւ1>-$/N_.>-=<>~5"S.&}2ڹA {%[4${#txV1 q7->-k<1)kdq4,dZJA^cJX="Zqhˑ_4,Z@3 #5%Z^:U&`- (KDuv!If#>-H+VU0(Gm"WU4,G25#Ej8D B_t<AC= A) cv>-@-q@<>@5,?1~Q@;2>fI >af6=e45\~#=Y :1=TQF:w6b**"5OA7="1| @+ 1z40B6H$0=/0(-0 *YT&($sf=; &9YD~ $(g ^>C ($&̯j>-X&4G- O '\=4 `:% 7.1)$@!4YO4$~Vr&<6.iDKrH=6 xCQM-":%~ ¹ >-'ܙe6._7"gt7)*sscqڹĕ=4|(;-}qr=6r-Q2c>-/thf: NT sk &}X&&#{$k>:1{Jߓ 9*r/J "q|DW*o~Cn+$m-qP1!j*5T=4fba&^Ej`Z!i;Oհ${"N7-8P5%Io-Nr-#HB;4,Do.<3+@]at>v m; ;Ԅ;--;`- &xёݕ&M 9*% $4,$l;#8xY0(ǼP0( 7'tYY#8u$ m'c"9N_  h  4̞3LY ˷"9Q#) *jcT40 |B'ѥ15#~YdA3"B$ tPb=6 z0UZIҔom=t2FX> 8 ؊!T 97% 4,M)<>yK#~z/d' zLO t+=6t!pw r)mHk0 m5=r&3"i1>-f- 0(eh`l"`fJ@&_3[ [3 [[>K0(XD3+UȗZ Qh/ -5-My[93LY* J69n HG+2*>\<> <;9V &-6A,>n;26.<|#1*#"fdu:;ϝ1)zXD L7a3#62V> ^ K CZBQ XA 1!t* 0 `V[")HZ'$__="32>3M:(t 59*=s:@Īg  *0s5%׼Y"  ͞y%ʺevNʊ~W=<_5T 2h5%T%yb Lۯ)4,)[ 9*Df=4"s:a 0(b="72"\Y(k:8ųck+b4:+L*60_V(z2*-_4ݞW xL(ї1)1&~ ݾ-}I/6.zO zse Er!x&K*4&t šv3+rP<=4qqZ"n/v9nb4A#lMIlk.i7i{;4b#$ "Sx2*>`ni<>7kA#627>-0 -#.ާF/- %4'E6Y3+%4,%mhS*#$ւ<: n, w ${Xp9*;$|g O!#OM0(fSU7/ .1 '$ ^xXu4$& x4,} Ef ¿2"uyǚE^  ob}uȨ ͊)j#vHY*\99*9ej2==6cQBf=6C{2"4$Bj+3"o=4ç>*? );)B^ Jw;4R_ pC-#$.nWKړ9*^~遢&M}1)<S?Z4$ &|6$ :3T*,$}uAz!V6&qdsp.Ep"5-oQ mgrS_#)k5@ ftgw#b3:^8V5%Z9-8=4XLUR=4X6;3+W0^7 QX `X7'NU(*MCUKҝƹr2"CǟW^9*@n`;4+255,?#T>X &(:gDd;4V}K SK_:%ivHr!R'j2"1{r"{93x2֠߻wy9* 77/<;Jj|:,R+a6zvQL,1)E/8p8="U$ :,ն|< w:"lU&$ !_=4,X"r4h5%ɬ%'1K6.<>zp +*ǐB">-Ruyr Wu[E a\7/vd-3lccb Ե!2" Up;|GKAX;= BY ָ߱S4,7o9*~[ }7zp9*{zG_(2z_I:1r nwGO=+mšrr2*h!\Ifv( [|.)Xrji3+WP0:Qrݣc LS63+G5)!G~,) E-ӧED7Aa+>-As- !@;8?7/<7GUT;<;ل38r4@0(60(58*d;,3+4NNe37+Q/'2TF0k>-,U<4,,]Y@9*("&=6% "f :Ma=4x _v=6 f\09* ۅ>- ; K,#QJW s3Qz:0P"hX r*L3+cF=6/f*U * Lt3+ceȆD%,84,zEU4,d] "^)v zǷL XfRPm2"Qz̭}4N[ѸV<#7&J/9*Wـ"'PM ^6Ӟ ˶ 25%43#d)ۣK 2*\Ŏ @WKV ]\#S/0 خ&&-_>-<:1ʒo!)9tT7nQ:y;2-c#|NK3$zhȭg#s =0o jAUS<>ix$D*i+12gtT]J$-]&Pz\$E`:3WdqW{? OyezD N'iO2"K.6.J'eH~'3#Eng <J(!#:EHs)9*841'>/*pH< &c49{8:2a:3b ud OuY1!/Q,3c33-3"7Y :p:Y-A$ vR zť  U,$TDS/ֵ$,to"jx}xTE (""EzdK$^l:iF@(iHER MT( o̽sw>)̜9=9 vRi֍LhrGnHD D( uDP8 Ho(v߉Ɵ;: җfFm9S!ZK|5|šXB/oN%C¿?y dWlzW37b{ɢ@|_$'SG3|<; FnrpOႼwo*@dsŸu*1ُNo_)%+7p H|p7p1ty*x]تݯk㌯NQ>YB1?*\ZI𵮏2&kӑ]+Pw Mo OM׺#w#? +޷NﰰZ.L7 ]^";&{awxسm7 K>YN[؍H| _ӎ|Wt?wg$k +w V[Wz;Hd%֠ ~J@ =)NLZο d֋I+_-;۸|]# MU$rxW~o>Xu!'~bY[;~8,Y^A.,>OW.SNm_GNM<W{ ,eL ?  FO(yvr> Q_'x?2쁿 !)knJ=̶۽;MMk? 8}1x&K ;gM]Wzzm c`: Id#maD{A"r_k!B.Zh 5j};x^Xv}i;1GxR+z%7you f:|xӴ&zFL83jK3ϤT:~L;ݭ;wʺO#u]Y탋Ү|>MTlx&$=M?(P-6NxU]<ޙk DF?'B/ܽyz=.6C(G{Lvd@&Zzﺯu/E)l\aVtYB7<%\1JhdחZckOn}xO9J[u͉%U&q먃Ȏ/F+bJ&\<@WratjcKb0f!6>jUКx*΄9!G,JE0ʒg6+k,zӖ31!.业_[FO[^ZԹN@URzjs_:/ CJ䃇དྷ}ӁYpx pNBIWأ왚|ꄕ#&Feҗi&=o0 ؕ0 ~ UT${Έ͏u+4é$Ϝr5D WFߏ߿JS!y@UQ6J+ݦ96ޭ uot+p6HNbY8qâ&K*h}6k'|?(8#[wL~ k? 7kT|.[ A%Ϛf x;:&GjD'=QO4IwSSdC=5;M<Y>G2k/aWp`1/*t9zAWy!9e\ĩgWY;܇')ĬRҗt8uϭoGzBqx5D | ,@ aDVCbM͝zr Qdr_w.v`%FGW<{tAc <~4H~I<}%B`g]Y 0IO;%d[>!šM?rߧ_߇q,4a׆Jщ#z9q+]!NiEc/]Md(Dۆ*3׿[=lM@MOƒ?_4ӂP]_}?9\bY?"`@ hTB?yCOB|z1r휃*e/5zy|%pmWWRSh1a29 wb b=q}o,>wBƑ}U^bݮ;S+(8BߋPqF7%/Om?i"WOt)y<6sg+wL-ᴑ7n_#[GG<.ȹ8 $8)!X|+%](9g 3:M 7\x@|ϒ _ɺݜ9dXbǾgY%LZy =SqUgrՄǠu'1J2 1;u;, KHP }d.ю,% `Zh(nZ[ ҞH_=&-QppB,w08v@J7"pرmJx:734ҿB\Ci{g,ްa~ݫ]koU3!-_)P@uT\%Z|JDSV_5*ECvp%w|5*Y2wLunrE9/~b77W`S:>^(XbA;j5Rq-|ȌB5Dѓ?n>)+".vjSc+ ,1=Ί=a:E?hqKuY/E2FZE so`4e;\YǤwuyTɚb5==c\$3ǣgPTKK]X4E%Jsm+de"V]C_M[0?z]n\@JLԢd0x\KA-s؏DW]guJ4-YdWt6UufjdmefV鋎n+M/:Z|7tg^Uz249?r$N)"cT GE;zO1 2OCOByCM֛rdG[i7tpTӛiS@ P`WhW;{yɘ,3Lb/+Й=]_]4ڡk9~8rE  'hLoqU /<ԧ_jbp{U=DV=ʞ+QS.㘯p][р  J"LZ3TL W2ٗg|G-=lyWٔޜd zcC@,@TR' hO[ܱyɇ5"56=]o$Wag+쏑'u`j4`&@,hegvA: E#j>^P[fz[HVF*8KD kujL^73c* *;U\yU:j܎o֤; Q2nYK.feQ!%nGXW)tj:f9K92:CD Ӛ|WB)Vh:zTǦۈyguNEǪ0xΣSmgwNb?&)ۯcLRP:4vȞխqo /^n}bbu5Fn=sϯ)3a p W{/h7L%-ęX.E- @( /?ѱ^EbO%N Kӕٜӱ`gUzוx={3&2=ØGj|^;>GsYY/Dp,ˍ#679))=aVG"`#T˭x3c`:zvyĘGtR0hMâ+P1]VijDrx ofhs~( 9]hP_fEQb0ѳ ]}2 -Y2RT0b^X4w!qZп|W3D* 3V671F2=7TG8}3Ǫ~ ^Oh[[VAP, hYB{ .#V!L]a1 (,yG"ԮSmaMZf\cdB]޿2Ϗj_4x:FLY sۺwTK3;Kg^ه~R4/{"v[H =Zh RU啕B_ݹډ[N7dd/X BzfoY?.0K9eͰ?5 ^,Ўx`X'r;,[9oe?7;xS4v\-K;МHMD)Vw?HzCj'5zn|e9#Y8w$C߶/q|U^g, {H ?W7+<(E=CSX^gF;\hG|7rNsZLf&2f%isά۪Z >$p?=\}\D:E8 }Kk< NSO<&bOKrQs{&S71+}VW'D:/Ol,h+c.g6ُWIo}"גݢ؃7\ ɃNH` $2 /hVC?hڋۋ L]z8j 4[ u\Dd{,ZHjGekO.[Xs@hOkzVy){rÕsbs]o5nwycV}lR z,}]=zOJ0`d&nT:9%ճrE}E1h։W1׶*XWwt3ElhrDG~yʗ̶(Un$)ɻXnxƪq0c$bQ^("?@d;n#^G'u l9sZ/w[rbz5 <߮k[5G֑MBnFV.o˭ 5 +_֗Bފ:\쪄:!QS· gyҡzPSIY/HcU-3yB$" Z,_DŽu]72BGRmX^zr34U$7S%2NUڗyr=&t*yr30rܾUxoF /s7_}ydlNN"Wɽ~x^n?Jb0CmM=dۍOB7brcw*ETF{aC_gL]8}{!V aB#CD~Z>a%y 9Hsk :J=1{q-ç*S$soi*x¸4[e/[_g;W"M'VY)ʰ 2jxfV7 07퇺2KD?X0w%wK6h-9dW5pPi z\} ș%S-t-,趧'}"A9Vݵ'K_ȞD ޭ~s5j ~RՑigYs/kZ.Q^ W3[t(FڃՂː枕iYjY-7ׇ+AXnUG^nn|3W5z`b`@+Cl`R{-/Е2/t:K :)`0Ȝ=$ZyS}wo#}x2'dT?]Za٦.IxI!%DeoݎZ'=4؞";܏V̫ރ~̯N6}UKPxHXի{X쫤xv4hX̑`sJE\lEu7A '{pAaFo׳2"#[{#-J=K6eOh=G-w)}׬kM0U-[5%sce[qHGpJk8w%tm+fX#eM q-^L\+ks%Q'V@tjF."$:Ĺ/_FYYUcMy 1@cgd#~TG)'xJ@nՃ. f"\? 8&]V9Eo9'YsNɥkA||!.5ϤXvא&?fpٮ86˄Jr@{9W}XΈ]dO4'#eBzuQ͋0'`{}뇬VT$u7)K@n;Zg? Jϼ;6BdDd[/lrn6zqM$;ˈDYyw, -reM`Y,g {vdOћn=iySOdt:[7P*kqL̥9. ]LL :׽=ѧeWWS![q"ZB-w4Y4 s3x(_!Z_9:#Sv,6 ]o{y%CΉ7z9y:6QF$ *2wXYMFr͍wH)`*c;ө?TxYz`n(ZK5/!޶uoYEc{lK.Qys$HN.Z"9u=`8YehssyP{W3]0ǯFcyȨ#2;rI"xhu E.+&r=W6g&9vj{eS3ĭ1R]Nй{! 83Sz5-^L_=dс?F1Sf؄cü+y<+3i2ѺZNMNߘ-˂CN!Z!Bv7Dmn‡oΐ㺶&n~:;%y4$,y:As*2eGKF'g#_9M.֢eݕ; / \~QeqZKn]stw8w-i 3 9Nvxg@>Y+ڗ9K,Ūؼ~s1) ~wcFTHXx9_ݠUmЎq(v;Xy{y_@A)Aʕ+#ӗ!e:~06=ضZ\T9 "GS~c2+ó&q4;"Ơ=Z3D%}k>=#ܙte\;FC ]ǀTS3c/vByM[ $ k9 B+u2/=H"|yiM)x3NkhSy TY7Ӟz.\l AS5#ENRFEP;D*3^'eL6Gp w u-[5,\U^DXT:l %:xqҞيH6ZҩwgnK^#&W!n3m&}l H>6QeY6nCX8?Ӕ/Cof]ɥ{wvȝ&!:1Tlf£swDF0 ] uwO\1폤cF&'ѽDgd `ȨrʥI`;痪h>3MBuo{MyuہLN%st'C]Wp;_ArG'!KV/#xC$ *{sh|8e{~/ط}Js)bW2$T~-ĉ$B^I~Ǒ}V*ə"9@%cH]r5 Iw71CV,k9{W%n<Pydo8VċuW]3k6 r,%VW//^L~ӥCAy^_hUG]}pU\E̫fO];" ư7*^c<;YDsOCsc?&{c\LE"9Z%h?{FohDFv jN9h5lWs93A\< *%-hxgGd 2_HB4>硰g":L;"qJ= vlI]m̧gƏag)no%^zyDkʼnSyz-4UE#;r"Hqj<ˇ Za76/m{:.Gs ٓeŊvO qUU~(ٕ+6I>I՜Jm0hJO%TYEk&DkoRݷvĦ3RovwtG8cNH/iyWr' ͬ{JvzsjO5[@ޠ1OwB8x|,B=N˜Oy}h7 ;\={统Z3jD;^kxewĹΤ9Q)&mTeoݻRBNG!J'Z!>| )*d_5z, '2۫PWUd^o|'\ R-DVkY Kwھ}5r\=x4l4[#sTNù^9>7FvNFe]]|jО[\Au(^>y1^~: Ac-gƒo-` 2Ƨ}CCKR^Ynj8=YP{^pp8Qk6n|CӮ}~}֤y ӞyѬ A_*zr){:H'x(=cV*"+X囟K L.hEC325HH]?xMhb'%b "WTɹg}I›֚?Z'њs,DVbSg{7f$;=iETY$4iwd~a۝ε$anΌ͢= NgdE2Nbڱq\Ojt%3'skV~w ~hDz9!4o=6: wC257o`^jqgӖSu?-Tk52T`ĠJdWO}C@< ^Qeb*<<"mWeUO>}~ K9zvssfxX7X|@Tgn9];3> Xͼ3C'5xD+څGD||NhW,)s-}ktOfNd^ZiPDZ7U,4@l3#;̺;% t!|x1ǡYߌm,aF3QfJ!Cro蛝bYo77S " A=lh^ݒ JALs#61!t3G߬VͣW}!+KY=:8K6l!5 vEB++@ե>mk_?q֦@JL'o.c<+nndE+v;:%n|i DkI>Z%ǕRDy>׹WkgqY57Rh2wEJjdYFϬ.f9~WZ0kxSoXXYs)fONv{xWXyHꛀTefhȷA~EGj_{&$uqsίG>Cqs{Eg<= v^g_z^uPOő cIv&V$R;q]7;Ȑ; aYs]!{\4&#yE ,j1GF8Tq%w`WS-2 ih@4 ޱD%"" R,"%pZWmCs=|GBn[7~}970?faBdn t*rο?اE+ ?rf1cuޜ/=ݡ$#ыy>#2Q"|3},k *_Yܡ]۶YPg|vo>cjVQfkuʖBd+猱np`2 2OD0=h&|Oav㙖zam 鴰TY[5gr__PrOE ľlƠ6 ѹ:jIs;w^2B)h)gCx3=1^ke]Q9F;/ߺ;hā}YGuKvbȰO{>qZPϘA0X_ٽj*}xBE^ȳ7B}LJLԥ3ƍ LazF; G#[^X>H!άOT=hkOɩ k̤gkmiw{!'g.l"%gz pg^^E7}|lψˑCtFēue>FdO?pCmVݑ6 ![<Ţy[pL?) wxu{}dwVRCAƒpA!Kt{8UE]XcOcꞄZ{+̤/돪DϐH_;3K_p0EQ,f$2^%mt_>94k֨LAr*xeE3<$c{Ǽhβ3r4C[${3l:3&8d/k@Ԙ3}7Pap# krh_=9dL/ \ңݸV)Vr0O_/U E瘕 B} +7@@̺Y;r_DsfCS>v^MWOdx0l{G3:쀈3.}#b3#d1רa5hlyuG0V t 5tbT"871ᣗj1E?nsʲ<Mݵ,)HϭSc[>:Ѯceۊ\1eځC1>&kJX=v`l`G ^eVNۓ,fDD{ڕcu]Q1AigrWz1Tbǐ`ǤMy^vAֻy[jԊ]jDckLC9H8Zo EbM[0O|fOۚ3]e+{-$GԖ1'l+5Pt2I=?~Eyw+zu1_gK{#kE8WӺ:laKĹ n  yR4nD5TvH{;ٱvM8ړ,렔+oL'eoR,tD_])Ӈt"zX)Xim|6gLR*\uT+Tڄz Btn3O@gwO쵤׭Y,c?( ].d~;s4I<Kbv'ro@iŚ*KܟVĊio68ს\ 9VTӖÌه>#<kDxZ|aS.L '~ƎξȄVNpJ)xgi L,'lDy.jD󟀽Vws}'d{f9x=V誣nFkNq)!a3g~"7Ŗ Ş&!t+X- ߵijxpЫy~g)P=%lr} 23{ٮWg v@Yj] V嘚0}i7:l+q|_ٽWhmcH'*g[O0`ʼn^MC'QȾj^PDDBq_?/C+gZ^'^Iю9DF#`ߐz>h;kM=Wmŕ~쫷5I.sL={gJ'^SS}K,e g'u)}{Fj^oY 3qPG6iL_ۼ̢M5jaeFl{ƿb8yCPyg7 G0;Rם:ro(D9fTle;+I1 G}x*k.RWퟶocYվ5ޛy21+2+tʦX]yJ2vnyON,CdH A; Lz ZiȧS֡§|KnIeuRMgPrZ~}'ݔ/7 Zmc~,ҬsLZy-;#ځ ~*zrR`VeS@2ѐ#k1d Dj[s_&D7sQWk@DdôXg-nnx"3ԐOB @hZ uAR+, i@,Ѓ xG*ʢ4:NHb/^ٴ-i;R[KOsMYkH0%u :}{: e8~rc֡,/-jEy~R{7o5 a{/C"sSG+SA{WqFJu@R-jjzYgj{oc4iy^`12d0ĢfGxjUЩ c2jULDv5S]91BsSt6xxy3\TЊ@LI~0gϽ1I9O婼Z9DNNIfj̒w@ϥ@1PgYȔ_sktxr'B(\q؏Uµ9_Gї8ayUz"(z8D-E;ɤTȟ,u)rt筦^heUCD&XIaΎy%!_7D9pȈ< ̈rl((o{mq|ZI9Fgb#ae82gaž*>c1KFeoyP\ޠ?J?}}2'ֵ/U2ֲo)l?j0MJ{;{@ GJv4֛ EQWqCL*VSzҳ~T ;NGM#S}n )C8oy QcM?#$nLYxo+va]KQ.(=͕S}}j+`f/ItʃOTu㶼h}1Y!*DWͻOFjЉ?H-85:J4qg=B)c@ 9kfy&vO]` )cߎ 6,cCN M7cEX&V ^b -nUId1ΘVw=뜱 :^C܂s.2^ǔp+ 0ͭhUK);褈-@~6碈 qj^IgĹzi&!etJq;E[x'5CpZَ].U|"DۧhطE]RqzJŢybW)(gs+URN_ ũndL8]G]3”"]K p̻:rb`z<*wyLfΫjV`1YJ) 5n~9ި8}]Q&g )+Ơ I~zgHSt 3z-8p`{('uY2q`@eeQ|6^Y];vAth(灂,'kʙrWwVV]ٓo8?Bjho_mDv4>w^˽ga`u23qO$Վ*?8yB9VCs׽Jf'>Zo`ݤE䋟;3x>.Vl*~e H>J"p;+5?Fɧmo)_ޚG- AO>ijS p{z.Y&LTɒ&λ_F"ۼNGc~Mޯ.D\iHp&MK>g疔ZCЁ36!K$7UyN,{u4\dDZ]*o3[ZF֮X')n™2"i%n杒ͥܝslu A_O|΄ama R+؝I,5*|biVArOؘe#~gibLvA0.3fÄIAc_ƧO~ib;k%0>¯NEtN8Y2Z ĮZ>e4 ŒўJ߯{%h 9{Cutg g FUZ7eϪ#>݁U:W4S e2XmqdJHY_6 ʤ%Q&w|#"><,BG!}o=V~+e4,Z{zo~1s:ҧ=/߬3h ,RtC~ |3Y'D[wۻQ:31l)l@pMn.-\9[)H9"A-xvO{jy:ʾEB$ۄWnnїggZkGLy78Q=5O 'ݎL!~:9a߈!ʩ3hys>8S` Do0앮?VQf+ȄКטeɼpqNR]蔫NG;CQ}{$ oiDMCgɿցb~ o͢,īN{Eb$D:p揋?1LW]ni<(7#%SmNN?)%ot Dg<%= W3]>)=DGN%ڹwȀ[!)UۋhZ8?vb`e,W-:\c$!riofrWJ] GB4N~IJ|^4_Fl h9S30!eg{Ľpz=gyb{Kk)f #W`[\e}毅"YϪ`/"QUM1DBzZx9j$`KUgDEƣdT|7^ =߈*eG\I-_Gu A&p9.'baTHmКA4ڊ.()iՑu~tUf8>3M%v#4ml"GR4"l|h}"a(Np}tԊmf#>ʁ~A|*цe%q6999h_8C:CڡmJ"0 SʢU,OچwP [QƙRj$(r)g%Pܥ$0$&mcoshcJ_igGS^vM(Wh$Ey=m4*P9'ː!o‹3=lR921)|sS7օXR,3P< (y헌 BWޤȡfR f[lL(>w<~p̞_SoB"i噊dgCs[L2Ðuf$ Ef$U2iOj4Ӿ!vj_sEĮgvx?q){%>)q洟#!I/eJޫֽa7o!Svbfc@R$7Q!)A"jLYʭE'uiiijbiO"rͪ]tEq8UO\ZVљvZH<ݘzEozZp(4jU42rtʥV"ٓںL}8<Hm`&x eork3:^ĬufE-5b\ clgV`ۮ(DqS@Hχap(OV扊ja7^;ƀ`J-YN&Wl` H<{+rby둢IQ(8P_o{4%DdOi<~66u9jT-(m(yE˙C"emI)ϔ+}ƌC-%?W:+vѤΘN+g}ڭE%ןuXbܣ>ꟐE b!~'ڃ ُLu|nW ׶x#ӟ7n +I g&i0gS']ӭ* H_ת"$iCZmS"YgPkڙϖ!ۈ` je^PZGdqJ'suޯNu RL=$_cħPiZ8AS5U-ͱLlOn{# [QY~!: Á a[]OI3HƔo=P,kḲSi=O-,FT  Vw 9\U&;APB::g 'v~3u@tGc_&tDƉP AH;m4f2֌s@ZO쯧s4&zkNeK"7d浭 `-4~,$џ>_>XyVL3ɇM|qWA놲ג O uK;^j-><+(]!7Ornߞt4es:WO;vYGd^3GNO?ݛu#]4ޒފ`ؤj',{L`>4ÙU*V-2L›M'0>푳r8R{&)+>>{b&2A r3O l/Ʒ.{b+Z5'g!qjeͽٞ%O\W/gu0ONܚ0S H|bդ^o[*{c`mdU ]h]ݞۓ)M|oގ3΅%95eSt<% p0Y2htVtOy/=b3uGDb'}q%g^ Pi=Z5r]~2O QбZN|Dj}FB <{[Ks&dʫ1:̙A/I+1%>aE/j'!Of AU.},Q#ɛ|2֕}~teXe}9 =L|m!:ԠiX2v6Gm8'A\xcrAVl[31Z<޿}e :.\"k'C?7oy@۰V'Wh}xUGPJ➛+IH-C<PHP{[+Z^)ߙsΜ{ι{^ɽGfk >y˫攥5CLG`D4x0Lf^Uz/ yg{-FxHJ,N0<ߦ#yg|k|M#;>j}^M=[;bNɯ/yvD^~Ks] ȴNLo &9vHu4ԗo1JVnp{FȻ&K:ljO}E.#bNdw geѪu4TMH+D6[uUjb7h]贛?JQOS.SbP Zzz?aO+U1_fQ>Q0WR}衭k@튤JqB5j\ɹy_hcCG4qfʏDJ0Lvwn!8Ȩq}82 cIo7{\o|yJ P5̂FkӾCI>ɿv^i,qiE c3O ȑI3T2 zPv~/},XY[zB\twqۛ:3atŽ`\y5NtoubZt/Z:|Ǐ喟{쬸؅Lcj?r]ÛDFi͡IBDc$jh-N5HמtVy+S:Q@c·&7oq\ υq{~|5m\9bF/QDR %ZS8O& }yʚp9|4z x6( ߧcXQYxG+Msrc\[5"Q__TGqe Aޜ&4.%X3cWS=s=wS?nV3&esbK6"C ̫g.]j ĶfdJIk4'1✊Z yxKv霳JPvH@Sy {ٿWDT~ ƨN WrW,M0WRd zNH Fl;XFH+zZf7!d5g #|Đ6D"s~? 68=q/g}'`e܁WU\*+%X33b_": 닯x? CNҍ<,>u4 QzD_('`̖ ts"ǖI"_ܴ03 ի` DwE,C2yiRhk@IvN*7Ӏq_ Bϯ>+uj=e H3%%oNB srEv\xXIJI2qy Dc\&δ[{Π]u1G_AmRX 'ETQX}8lG;E%kOӜ= #vePiXYEkpSC,`9m9d25t[\)EU4lȣ1=8yBC$.3ui|ѡ ‣ʞF"?zJgr>U23HBc}.Z(aNY-wQwc{7π^AmSR}xj5̡BS1k)9"\O"kUʎ\-w2LYל (GT(jj_' ̪}XBřwGJՑRXiw;@X,z2>팁W.`󷖙&RO"^f+CT9׫JGvYVLL@b+BQO2́G) L;T}a +1!fu8oh0SD}cմZf6y p|zg!ɼwe󁷲®ږ>PuPO*:\S l[GbVJ#bA}o1뽜O~>gia?g}#jٝ8R=b+?`Te^9ܯPjM5!:';rIxD'񄆭*mRJf-I@G|*EZ+y輾uBU#{ P{g6/ܖDbdz;6Ef^av&X7{Z+xۖM3dEaBGX3oM@8eчwy/ETږ)L9{{;JS,;Ml_RE QeƜ!C\L0z4:gw p({"!*`ZPu71/LQWdw1Y]_Ce*$x#D r9L>F(ew8i ':\ʽEĕ9rRAB5QY/ϝ]qMyzfrqd ;=s2j@dvv!HuUFk[>Zӭ=z@r~mᲮu<"(|ZUjv[:hv}0sv7Ϳ8Wq\in$rqHpp'>-â $ 6p{Ydw~S +-!c?# WMXĦkzMeWzua.[Zuqpv zBǖWI":7Ww].%o3~ 5Y/rԔuH#,]Y$eW&DJr:p0f>zY!YQUDL)jVVzFtv[,5\xޫkoCEO5R2[A-O=RQBrEV3-Y|;W8fVj>ʨs^Yub"+- ] H6F-"LW‰WLRڴ';!Av^3$B;jq L?dMQ־=~1`uȂu@9fs{ 0;Yοt~:܄?RK٭VchDX5qRg{U'A ?YccJ|&Y~lD m Kyj=Xbjgc?7" D4 R` x-msBeꡟ+LD{TI&Q'.}UqkzRϙJLTl֜.7gzٶ=LgG#@詙|wC&Gt&t|UZiFuJ$B/#͏b:YZd^Ƌ҈=+꽋;BI8kpWqM۠%?ߩUocwfQeT?kzXos${3Gy']WUcO|˜8iɮ9~NJSj; 88_j+k~и7gވstjTnX}^aX<5 :~tNoVm&wN>LYLz)]YUDv;:$ ܮXv z[YUǭ;1P;gԏS:$ضB?Il?uLMD)oU2酽fؘC").;8G`<Ul%tzK]唯X[*r2=k2VYJ9v<,꾢ʜ*FԠn7UNZlF,Whjum{g$Rm 3;kku$UfwuVM5 QoR ([椆\ޓG32e5BƼ9yVZL+n1[[-H+g&/LJD.,- "ŪnTp6 :;ĵ@b'ó3Wm sEt +(9M*Js59*7%ɳSH\$dy &3n6ɣޝ$f3$VK2 O;z=A/sd~ 3fOX;[N:#e.*aqd}gxvZ*^!$T,25.Ov F *%EAʾ}TF|Zϙ[zχsmӁ8I؂ևJqlfyd_"kP.7e:ve~=&M7Dg0%m,eh?JBV/h1%T Jrȉ:% 6<.~w\qxՄƹ?,eOR}<"7Ƭk^k@|V&:jàJk]g"Qw[GwvѬNi:19Gä3P҉wQOx;fP"4lf1ڣzEeF.#},bc :scU K8>cQ?SRs9 ׹M|܉t@h)yKSY\>V)ʑ bJVݛF*>uV(+t벽YZT,5љBt'9cV,W Y ~[UW(ເoXtk+ ;l5xbc=^s՘e^:FCֲr}mSDD}5鱄 $z<Qth>9aF/)ۢ=!'LF2T%{.\&s tsj+\玥$4M2z+1J[y}5hh.Vd[iʖ~ZltBF$?*dgէ4gx%vrZgt|査KHsFz86d2&\ $@Ǿ`&Z =gO03sj]UAS!C(HWlU kmIuF 5Ju]rykSTorΞ)Aaf|Yk{,== ̶M* u\p_Z`)G@Bf,rՃWHЕdSnk͎5읊foxZnlĠA,~37 hyT=c82ЛKAzW~*5e ߏ"rnwo',!pG-o=܅ %Ay+;j x+][ە4!}8}zf'=-Gl CreUke{IAt7vqc>=UPMwnfS/asZa&u9|;b13Qd׍o5N] #oFTm:!Q0CTXs+I<үO1?v1Ƀ}h G;B9I:ͤCBmFt1'(3ϥIBN~rW"ы;ÿ/ÝタD%GGtyZ\i"xzj"<}?*lj22|HJ32YbgT,suVjR3(\kVKWԮ4_4ɛQGRGY>[PuaodG)S8ofT1,:ֆ[A>}Щc!nl{zb^c?mZԲϒVQ3ԖQՖDO7[ $:G8y_W 8g{J߆ۦw'P(Iz >2x[5Q(*+)ʼ4Ӈt+;UL=ZG@k<CT)P4Ӈ̫x{3H5fwcDhEOeJ(fc7K祾S̫tՖl2ZqTmȠ𯔘d@lO8M;J>KI܅dIj>N.b_OwoodWfCF[Xza)%QSsࢆ*S% %u%bnzjO\:s{[~@TR'XJQBÍ׍8e6^YS)SRU,'Õ*:T-1ViWOiOS,(bΞ$͸=d i6qyN8y3qfQ5]맥w|‰JgϽ+x'P)iiW"tZ }|A eRL¤`9 zrfz+#Nj/N')-fBS#řQ*tMiS|_'3SGʼ<: )9<5F6{uZnoEO݈[C5w^Du'^TQ' i;?g]Hjتu,,8KҶnsfCs!pʖA1]xQb{GڶXHxD^i5ѭ…4g`i b5yO^\iXfbǎ.M۩2lא#mz3_}8R}lN->=ӳ Nc 5F)φ4ۿi_F\pb0@`1oD)? BSf!dti3&7ÜzO)dw{9%ޥSXuI4E]Lg87Ӥ]RKIX6i@#߭Dt5_yQ:KS[ۓM1ZYi>U.LAϾ33Zis#\Hٙ]g񏊗{h%js8Ӣ8E~2-cШퟑ#:Q>t0vMN ڒy} "Uw'ۧi\5p)bEŎYFt^PaA 1;q8CefOZH;͆d=w5PuV>/]Ў wW{̾޹87?vYZo?9gZ}Dtfx6C9VLIqɧNZVJ  pe^F7zp c ~2~+PSGoLi-<;'7ޯOwdTX[_Hq]M`f;zI F3j'_iiK<,Jdsi~t۱9N+7&ߛ)[X8G#'9N]~A+Ŭqd,=f|Zo׹*8EM - uk3A*eoTw-@2wI_¿Ikpt= ]JW(q@'jXnY1[K}$ٖ՟B+2՚.tJ)ׅST# ,MWQrٜvR5V!ITyo[S&}E+ҬԴՊou2HRm^ڱoh g{drxi(sј_ 7)z9lV1SSIBr+%- kRZvmWPF&z!,/Dn?qu;Rw)wXlSX8˱9 a(߲]*#:H lX/ ?3 gW=t*2|2I= 6nR3IVJ]ֹ,L=qp}p*KƓC1fAX kDܗʼJT 9G.qB4 8_yVԍc*E̿!RgUqb'{8Upe!ƪ=uˈǧ]T%Q 4G5թST\GLNgh.M|xUHa>`@az[3h>s!~`Ska|z9kK e}:0uqwӚvG3STxBOI՟˻q-uSv̙pmPN]Bi$%a3F* dOc=/I:t%pS{]xk#-Ms={Nnn]&jkͩt'W( ru5e+#7U/F8#M<ߕ]hLEsڶSs!huBԓ\#txnS}| W;;n[0Rk>aՄWkkcƓA@վ8܆LD ɩ/u~Fwi~[~=~،l5ZHT9JluLCf 3EUfRˇ~EX|ʝ.g xADďY$Tޜ_ra\PA'pjEZ*\%WUʋm~9\؅GNQdʐҷA AǮh`{e:;&|ndRI4,wiagqݧLyX9VS*n2):qE9c2t8>uա>SE$R~N#iK1*~Gi%γqx?Is^BLNQ啟CR#hZ5HjwM0+^B# )nYx)E֌7EOF/| `i)Q>I`d㕤rȺs!>wHY_Yۨo:N4[&>ƞסnh4fϖ f%ne!U#Bw=A[jGSHYgq\XT*XT)5O[aJv%,/wNJPѫҮ!|gē8O'=m~F]2tŔX0 )<Rm5\B{DxTTSJ-c3DgtPg5RfKx Z)gRyfVU 7۟tUq y ߻oaf2У?;AvpE驤"\[[ 庝ΐz[uZ51}5BtISw./OhGtNقx00R1U.݊TDn( LMQ]!%=~cAo݀$>7vZE:Ngrt:2gGE=Xp2'31FcxvBJ58 RpQ&y@Je],M>Q+:]J U1YU)ӪKu+F"6'/}xj,C}~XiȊ_>,?Hg  $\SA6N9'X,pJbYD%t?~y\S^(Q-G3r#) W[W4]5NGW6+Rf\xr ؔe̓7=)$g$98f^9 CN^1ě>s*1i.q٘$/hSӘsS0 Xpx΍H P%#9SXgot2JCΧb(^l|d6iWsA|'ɝ:ngj^'p]wy/%.9d]9vTM/HncrUs}FrPƸRJ͚C%3+2┞ՃZfm:<5K /" dRo$Ys\Ȱ?dX YL?jm[^K-tYv͛'Ү瑷Jpz9j΃Vܘ.=@YіZp87iΙ1MYܙ +E^Qk0'3OpJ}NUaĴs!lɪ9FWI#nMOҕ˺_r̐ARm$e6#:"%]Ү|A)Ka>J1Rfg.n%\1L`-]*r3PDLe[hNkw-1W/'QEW2EsK@D}XoB|J-7 ^^Tr6HAVyT 㫣xMP]xT4)8Zg:xD1~'|FwZp2M2{ڭP<ܝI,L(Gzq<4 ;ɕ:I.d_΂W5>(\;z1cO/.QE!'@n,Q a6!iA5FT[*WrR!S\1IgrdUu%8W#.;HM]BgIޭnCVSqK'Hw!iW " 8lU7IO/[{[Qg_BMJ 01&7-dRJ1q$@S&$ AXM0(&bА~}ELx9NDEeiA)ʌ9-wۡҖRCi_kN8S-^:\V6iX^͡c$S$< 7uݰbXRM.\AG 7TyԌUصH1'E r6x1b6%KVsP `fDT̎.z}m dܕ{cߡ_{ٴC{x { M!I9j*PzSTH:w,Ū!Q Iz#B{m;1%yni;VIS< 4Q)Y%i\aEaƳ0գF|B21:O~:'YODok[lmy>i 'ɬL㤆;hydRװV]noUx,J,$h]ǷWCW ^$/UJTNU""W&N{iE&5~2pgɽl3l,;ىxH8,]uQ!_hSSIvté#O(a#'Jۃt>soKT &[mpsQ](sgTK=x V$_{P9?la6R&N4$6i2H[&t@6˖4ETwB H|CUK!8Bu?hF\3GR֒qܐ^JGTcaZCvҟ59G-Uf}  KHfߕ hEI c .uGeCMWA"NMkEҬWb=Z5 `z5/O{#Ī߷yku8jkA*\>2]g?Z+Aq*ΣimCy('bXy4~*S;@Ţ)5B4?(z'oLY}7DJlE jhFIwX ^3>ܿv љ8W(!sbȨ#p")UVl !1kj NoHiYnۭyKE,J0Y $D9PbGոa(m{.VP]~Y@bOIC}#f>ӧܓԣ!$?oazy@W~>SrMBUG}7+\z$CmŽ1]w ѹ$0DsK^BTt [*Hz~>u-Fqid:Qc:Yjxp2XN^9 kv}+͆ Qq+LjQ Z~DvFKœ+'u uzfA=>;V஘|Wn@ OUr)6i]Pd =bʊp>~hߦi74K(M~wZATթɸӒ1[v.ctVA_ 5'I~f&B_Db~FP1Z{!yOq+7&apeQ˺&iB Y'|ƄKizAkMNu!pgE|m]G/ӡ4\ jk?o^ gɝhu,mBb* 9@ VJ¢R ",6񯪯\a_υ|Z?FqaOqC q#.%?}E5ʕ~O/Dh/oybA nbت!ϏMHIQtМZ)_E9ɴR#O>'@ Skë/p/_&~:d+_Ϳ~14ӺxATeҀj7;eyGNr³C_Iw{Ct,yF?6/: A]8'/.buWşh˅ fAoߜy)q"R盙2p37mҴ N㧇Ulv;L8r,ixSw=MP+ KxO@y_yfRO$TI7ߞ2\ym \Z)2fj_Zn6n+ͺxD}YM$z{!e9$7{t-N-c'6T&4⹷pbNS,S,+1POc6v߶'TO> yZ_{`b~h2D]7b0tㇵd9@]C~F%.Ji&:ͩu4X7Yrx,+F,Vh~F7DW&5ȿBB(fLef")=_}xUcǖqwQ,z8י Վw [벮ʇt|˞=Z%:q6L+G]+vTthƒK 09b Z&YZ#Oy J|Me:ߪ6,}G4992deаdx_־{={ō☾)_)8JNG9e8C%/_h:.k, Қ|D["<ʋK}w{㒛։r*)ʾ A+<C\!ޔ؏N:uL5ҍ ; auqwst,0[blN\T,g D$-߯A9j\|O]7@KIM\NO=/I췔묮d.i=JV{cmw*?YOΛ`FyCeۇ[OĽy GuE\̆DױQᏢFԷ:qaUdK$͑f 9yjt6/aJ~ ϝfLWm߷u?xv.ɏT~y~lnJui4}_E5iOz)afJ>??*gp-劦Zጊ!7IЉV|,wE?M5'uL+D$_%C0>Sa =-gV)sr7~K CT+~!1Q9#k713a'l[_ә @?&I[nbnCAܻ&Y4[܊L mɚ ?qZ-?s%Kܢ 1'!@78ºkƉ Xu30dz I$gdܬ|D>1B!Tr_tw;:nRvXJR0>PD..Y67cu8y/l2۫83 \lObIcۄ=ktZ}K.s^L7X\jLg==L' 3e[5٪"D-?ڧI"8J0~ w[2!3_/DXˆMy0\;D *@U*vGvWxڲUܼ5!6'Opv\[no;&+Zՙqr.$1JƫF? Snf'Y1;ЪO5d=⧯ٛ $ʴoEVUC|NjC ;=y;=1}' -G׼"qwrxd=Fϊ*f*u0>ό6o$fto@W߯~Lz@:^)9b vL9L9?=`viH'mhdHF?Kt غk~ 15-2P̉KbtYU$f|t3Z*,µ֓uʳR2qa4 l'9=L+͛?a3LaRLS\Ir-cQ+7BtBD#觛2ߩ.|E/ys8WWWCTlIgY'䙃?yrqCxRш*[xT=H0 ˔_S`:+e}마zLfKژ`&b/rP^4Mr:v2/u{lB/WWO̷HLa(#NC}NeY6"Viژ]K]N<9)QX鋔9@mb=_\OszS{7"ʪ`.۲!&jZ!+^ g({{rs!wçMDd ީR̵oaQKs NAT -U]vbܮM%_B9缡g\ qsMڱ-A&\rk%svDHf0ejS˟IjccOZ51=:C&Q\tZK-*`2L*iit:Ij]J8"wa Rҕrdg}\t9 H9cO>98fVkgCLY`œχuߩ9{$ΪY-=sOOO&NP>;K7aO`c>:ť[=SrL c>'̷wrOJ]k aYLg U:U3۬g}D`6N]IY%.tq 81eG>9,/bȇȅb~Hf#?%٠+hɯQe*_{܊T4 5 'k;#4D0Qs>Rm͇p02 ˨{vL^@}i@)+W Vo{nYr șddJ׀LPoۇ;)ZO zZIb&[#{"{e1dG{W13~<=U4m&YȤ|X=/,qRuT\L"$lwd&76= =a+ _8wskڕ*L?QTѲZ*'?ϝ(}鍑 zfYY6$|i75R4u. 製4)2aF UbdN/I-+*27N]׈G?qATߎ3*kW9fh2՝ddMWU ^<]qVX|ݪ ryW[ur[1L~p2ER#x—vPi$s47l7㿵}'NNI+Y||7*=F*e7UsjJtEen{-F ]{P4s tf Q>e>QgE96厦{F%4 1\ YUH^Q1#+TrMs$' OLpރtGAƤgs<$bm< TL GG-ut<\IȉId:3/#Į;TֻPϕPR4Xv*ON9%lCoٮ/=" $61pF;&QHڕ6䫽z꿈 uuN~tJY''>]섰:]TW) eE !GmcԢ\Gq [Cŵ&jK1CTec~gU;"bO.LʚG`?qΣ}W"q]>C1B}1OO+|j$ Z<Ϸj"re+ce_9jŕeǃNF'N-UDrϪHK&ʢV|~Y 1sֲu+9doY;@qpi֧Z6V䚘9eSQAeVdQ;'uWa4޷7PFMq{7LP'['~ԐT2#G6EC}i WT1xTaYwo?cFTg#J]̩X' BaEgP=.֞8ߧTR)T(MnxHS-w9:"u? u'3Q%~Z'-K;Ȩɹ)n(تztvT3UgoNfhN'e2UwTõoh,;?/7ǹi".ۍ]wvG kMX~"}2ky=KD5W03E{ơT<ۈ"Go2,DC5*Hugt‚oT^l5EߧErQ-Wc+Hh>st1#_)k9JfKtUF>pA̳m |_$(Ta=Dl@NρdZCc,-oH[y2<4yygAx\7;D}rl-*8G gX^ť>aZ Ӊ2rC* (;i|Il}ge/3,#QrWE"7i41i \7 1JbZz;^0mhR$ Do_p҉ةqw&M!DI|MsG:Tw% (F.~?Uj Nf8Ұ[)}ܠȁ57|P6MjrO#af[rӐr?YagG FT_[C|ߌ%eJa)DHGbGԵ;P簉*k0 |/9bx|՟ӁǴyc!k!1O/̎xx(y9ZPBOZOI2]ă-_n!t<*gh`/8(uuXg)"7&Tj"¬D0:Mdܿ W=I[On]Gk|zBǏֈ{qw+ڥ:ƽq?}\!{X|xcd޾лסGu;')Ӽ8 kVt ؟f|lң8x7Yx߷UPu!Eٖ 7L@Vu7RKg֔̍ bӫmH%B-Gl |1Q[*v%ZVC~+ioxq"6T8\ŽhLX.O=$&=n]lգ5$DIB9əu>|gfg0j`\9D4ߵi j#Qg 4>ѽUV"C[SS5[|Ey6C+.fN캀f!:!|f?~-w9|w YԢ w/#BKI;##J5nP.U$3EUMbY47vO)`ußz< Oa:GæWuncR-(ſ](Քc-+̱,lլ[Auk.G2NtX_ cg % _?ëm~3xf*b/QiO>1@~[l}HraŌGC}z.9}+ʶ>jNOKJWrBb<Q=ov7##Ͽw3Ôv$: cm&O>T љ{F&Vx!sn4#3Q|p4xٝ1O_m/>'h.뙀Oπ>cB)!L w>{uSjeiښ%!v]w+ᛵw=CL MGF/t)}z͙Lڙr nibS t,]CD< pTmszdsj3GgB~f Y,IkLg=:7 zP\Clي;m:_#0,&yMzp{|\r[.{\%> }xn^ČDdf:*s.#{[`H=}xŧ -ūO[;???GAC { jęgRܑ/C6 ~ثC~6)b%Ϗ \ꑵ(?zȴcIՕNGa(Ѿ\FTOU e MYN^MS[N 1r^f3r}? aYg Vz MɄǵ&T.%q),E ΧfӐ<ژgkXjf++E`o^`GDu"ޑHv;iz{&YIan VG<)٤0]ecp,wД8#{Ivτ7h._8b>,\w'Ux/?>vJAVĊM4w~S-i~yÙfrFYDQdy`\>ǡ+ ѹ0{yS>y׈g|c n7LBR8e̓uԐTMTIWDYlZtC7vL0üօ>oh2ޛi<1dg"Q7-WK#=k(ܷL@Ͳ΄%B7@T :\hPe0oVTp`D]/~V*bԝZ\_dd[nޙerJƳ~sԳ]\aC>xeЛ* 6 +[A UVdؤT)ew=Mȷ[fZ7 Va}5zi<3kkJ0=]w|EH%. =!t)wH:"]"RJ{H^*ogٽ+I|^Żٙg-b@{Pxd́ZZ|'?H_;O oTNvțe#w EhZ)$+qo+x'LԙTvԫ9p=Hu`>0z8➈F5>{' )\0/z֝EENcT\})KTv|JfܮFNwyu҅/cb͒ݞ5D_ R:a ߷k7;5,+ia%_%/>n 8vY.du>i%{'_yN# L8t6/ Z!LD5oͿh67#o "+yg 9Ϳէ!|k-D|OӵYUv8]zĔ߄O?zHr9wba}Tߑ`& _;$I3}~~sH|LDk9HQSg˩T,Xk )!Yn=7Ոܬ!×9q){:88AXy 0z b|Uk+ 17Uuo=j|#4<'X4+5U٪審k[ާ1mMU;dw s{))n%ft/jƙ#I~P}}iZLS:'8?R9#W˘ ː<Ϟ=طD mabU8f|kϥ͹ nW39C&މ̕g=Iy roD>ks(fŽUB]Ū;qYG[.kIe^'ǺfjDd%' $ i=6廎83PhWܾc|'R}~cG^ߓ9y}籛jnX) IytqS+qY}~KnQ0AC[f$9 D< ?\8JV苠⯆Pd%z+ImfL+xyyd'Tn=ݕCɔt@IAg_w7"֚µ8U/$;N7GG^4JleTyǦ[QlpQ14bAͬbn%d2ܿ4K;,Fya5Z;*#jqjO9t& >p_CQhF^h=DZ#|&/RBTiV Q?rpHLu$sHLmY׾2tOI &;[A³H<[#rΔ׿ eO=&E>/ۧG ęTFmDN2|to-?D6h)Ozm[S;~ϩVP}B^V #Z4F1y S55U(ɣQ}\-كN bS@y|֗{ZbP8oT5msx~ PbUgжN 7!-Yi|#][]D+ qwĝ#aW2M++-V,nP"0(kQXq.MWWBʱ_xt⃇L&inҭNɸ:XH喨j玩xr.H-e3&7GTOQGޤ5+SN`D7<;֊ZLpf+Bf:Lɽ<=]p@TO@oQPˍUg<6Jyvv펨-fD0˼s0L剴f󂚜GqŪ?}{'ʹj<ɽqdwݽ'=\ZiekU.%/b^榦8A)ói̇ޝ/>q|JĔY kh_UY'.7:ۛkfXY/l+Dh(1>QaB3 :Ą ɱ;'?SQ?o|/:F V֣&j}ʄV |ՠ@X>1޸pI"1t7̽!Zː88j{ݦCs蹿]X5.ơ8Wk$NG5p'ӆ;+JXB"7sbg n-ꨯ7-d':;Q=QRd$90J>fsG{v):0QIaҭc{C!4EJZWSrep7ۂAư{<΄q~tyjHQ$y#mkCLŕBno-i2\\FXU*N@/묙I8V]| 9JV*)>ȑB.;CFn_Kt-FM[BI9lV\9j*nWb4&Y~`S~]&uݗ ]9ښRጤ eVk:YU![`^&11ů1E˗9 BWSRHnw8Ο n~g{Xx7%bd61رRnshfW$ 0g_VCJ\ GjnVcX˴Vɂhܥ\_~\YB/ermtzВ48"^[-Cs;!ɍMiu<(>p?C>G24r;-~$tm)W0sw󚒃;QcD&x 3\#fzҷQެh̀i IWn mU.^Z! q'M^ LuwS-)+Bׁfo*9,|.Zr-ga78 BInf _-pRŃ[ΛuxU~n٥ǼR~$eN喸t#ɶ :CB|'$6%2?˳!FyNj?EnD[Fy=jcO.@8'ÑhtfT+|ɹv6GT Q*gan~nFSf Y9GfThۗul?L$py#^ΙN y35 ؋9t%rj#";jWUJ]g n6`C S#Ă$_TZa ͛cΎw_5Q1L 97hՍOso.N]9g[ɴg ٽi?NZ *YJlw7q4 %xʖFqĉ\r6,lUQ_#o$5aڻYiٺ-g"tD~e%YY/݃{y``KtNSVG8S{v/~TSQs~Pvt&r?6!3ʐ0q,4RR̍Xa)WAP}qnY.!msIn#U,uQE>ծ }V ꀁ^=$Q{iogr?z ׇa;__rr }5sUGߋ{GEw15DR]}0*93?gI~$x4y,{ _XB3SgԪ4ڕLy7>(DOI|[!ya4)kf"lkR(lwLC%kW c.b-imQP(!=fzSni_bU r+z6 &f;$0/a. έNxC4_uSvqa3>O\Z;}K 1E212I/uM!۩rPY_ dN]3n[7 sV+UB1(b?M*6>Uhs(ciٟg~s LmJ;u;CLJxIsbG{^>qt[aL+Mo&:g9T:Cfטʉ_}K1ehx~C}37kl4f]@HMZ5ia?;LڔXelGdf$sꋈrm0gfji5Ҩ'~S V 3o;͠Qy{B\V qS|S. e q`60`!{(Xzj5g'VZCw=uȣ[cČ3 VYO[:itTo9N*{VT5-R[xX ]#:dV;{{Hm2%&D}ׄܦz5Ұ9 7f=y q[ɚvK!a'ʴ&տ8b:)v3w~J"U_STOZ=KxmO)'2@gН.6;q1Ym/%:'3^țj7@Z~r"\ 6\b/GX+IV0`ı0s2'H0y>8j<~Nrπ+s-ZȅEz&! zn{`͠gz>jd':kABytVu"!-MˢpF#~h )%݁Eˡ}OdhbT#F稖cnysmU9~ERnd~Fs1#"b837~=wjdĠGfP\*o!q2F2=c{ԛ8[nb)󩫏wPybM@60qﵴyIe3}4nQ$|b=;61;[#{;O ꓇1A<~>=u4k&W^;םט+u񎻒8u\@yECOX;* E3b[#5~翪7'K/o$7rf輝 dB&dZ>}/7,:F ao]y9y}#b6TRkkډOo3S69iOnnoH:t権RmXxP~|\tf}P!gdt> R:U%MpHy6o[=ѯ_+_bSIc+~;V1u34rb=jkyIRОΈ+9dƓx;T:dI O"-eObϤ=qu,~{RdD͟" 神-Y.3ª ^AN;y՜ bho#z%O58Y?OdPCD4mWo kOvL0!3j웄o <%BL]`X_florHg9LMEOF:LjE_H8 rR7O*+1r)UFT k0OR 3V'CFn`Hʭ}%d"E%xv^$&8&wif Vel/6ct7212׫ 5 {G]F߹wopFI l-,9v+&ђ"CkZPբ؄(YUPdC-Ys"'S{@b.WqGX Ǽki0M ߝôtoh;,Cwf {K^ ĈGzi$veԈƌ]FCn#(óP2IgSzG,X a :GHG֕pL!dFݶ<8+DԹiX͹S_+sR]mgw4o=K*AAL>?L@srDL[QNZ@V@a ~Su dBb M߁Pa:oMnzwjǡW "}HsiŹiUӚx3N-ōD-a8lB9ln4Y@bjwMŏ?P&ODbPQ܇j'f{[vu@;S_Q޸ߥD5ĕ9K|ulgeȸcKgz?lF1t($dzjO|߼ޕ#evyNU.'Vud *Ч(4Mo0&JS^똈 ?laP,yqić=E *BdYFzC3F,ߝ#=Sҙ3%{ۜ?ZE|k>L[]an/̱dg9'u=G#G7fEqfHɈTjsMCXu=b*aʹA;mO2~§7"M1qwQbt|QTU5d(4U^X.a ꔤ!(^$aUp{/>v'SɯeqN,ywpz76Gq dw+g󯝰7Q⁴gg\{I³m'p@ $W}De!ܩP7ؤL(ηR9L[#8Dzv.kZޝ{Td['1-@{:ս<¬.-bUq~"mAwQ_|抡r;޿lā:R_c|#b7vߧbG[Gx7]>w/^J]iY*l=7DI=DLoQq:b2;nsIOӅ[jn4A$JUT7x[mޭq6N똶䖠V=//DWen. 9DU^m${1斉5G'?Qc3A. U;̟ jL-'L4lVN.f)u, O^W:U=xU_S̻pؖLJ>}<& 1P$##3=$4ʰ&3F-? ZN1F+kAs/֗Q`H-IZP;ti9@3?O^osx蚝;rݧH}2 Iaei_V=u.eɢLpd]C@hFKDyF zziN OH]. 0VJLrSۑOo5]ѥ/`^f!j l=ĝƘLtZvQX@ڛ`¨M\xh{-#$#]ͻ-m)6o3l'PDi ˞j9`JZsVfp9}`oI<KJ`oO^?Khaԩ{G+p@#ܘV>80آdtZLky+rS_44p8v^B-A]{L >8R(G٦uGIg{q 9Yȩ3[E ǔiG ZHGj^W-_FΆԃ;Jtn +m@Zf}ދ{f㩾:G)~x01w;2^u#'bM\QEe:Q_wr"Եk׀*<^oה mJwk_Ӡj{Gf<ߜ,wQg\Q($u[>cg=h:7!(ԙlܭ"G)~#8ݑ?G\6="1Ru{剃ti*2#}mħΐd &mM1UP@jWϝ =SG-6PB6]2UCHٕ>uЃ#Y:2@]+sCcUe.p~ë1&3·xܰ_+͒EL'яk4|S{g7_v7D5Q-DĦ~'5巑RZ}~n~GPqgL1ITuÌZ!'rD-W'ĻqX.=8ԍT&dR;ojDY}m uG/, S0mU7KͰ{GG0XjyEۗ_~"Ȳ3qw uیNߠ~ %8TϪSFS9!8N&f.1:&SfK1_Ao@ܻe'8\ڥ Jha-G$ZZ߱F7*VS/XmژINn͊y™D&#u5"y(JE)6^ZJ{`o:lƕ$eȳ"d:͞aoC9{u[Fb95hȔ &u.]RVJ_, c3sx|"hJj1}ntZ46U:-)'^ҡZ}ab,cM97`ƖTaL4|8-˸3}KmM"Qh).>%TBe ьgԳ'En7iO x"SWT0Ąn8 nx;w# tU=ZUQS;}dJ$_s=dOI~WLGC**Az|i6KqRCNϺN:m4|?j Yj7ބgPJ/NgkyBEwD;1eXw \'t)Z3zXwbZS[X)NAbڂR,?v6ozVө_\^I 7Ȓ#:A)͆!5pqD]saVxV+euL`rfpc;AX }2ٟHHrޜQ󩫤JD4poB1?j3k8bqEsZ x+'ygGWk$@vs$Z#糁$K,'?DL;,d :|cʄ7JO̠.Fa7;?}~۶[ ޅ ŗ6 f-8I38䋾o&< # Ba1c1 1ZbrNs4_1uW"7M}u6Cqx42։)I>J__TyOtd Ǣ3G0m 7 ;q9 E' ;}5y3¼nV+e)*{6i^Olyd3D{ά.Ōx}ށc)}jae*{Þ~knu!;ؓ𐦓stդ/#IOA4bw7aw܅x&۳ 35ߝ oJC:ybVW!/^r_)%yBz(CA^xoT[?$/A'sQ JsêH35֤d <̾; (˧>VnhO*(ڋK|l=`H`ƣڀ#fMbor?uZqamndcMbܡq,d\ěMu](߅|E X @.Tg}IEM*{w눤p'7|xJ5 V0? ld)]R'!2""2?p$1;]>{'W?ƴ0%pWSЉHZ3NOnڒ^qf!0~]&}tk;/vme/Sb0ݘO2Wy"KueK d43t)O{2l.z7P M̴ոj+ HBOJ6)~usfia _IkCgKQNe ˮU93T 쓎mԩVƈ /p|jMq:4tׂx<3QER/-NER>Mc.;\w^vh$p!H H [PGqrDO8B(5݌bp|F3I$7<, 2A{5I't0[ }:  5I>xty,t7ln}%t )> ݉^B4Z'ALuzn$.qwMPgFInpR0<}2ɩ󻌎@ۂ5"P{q}͗sc?"xB\\p Q= ʵ)p*ڝ6c5 -1n->~m_QpIۛkVnqO/U芌\I/#>'%Lڋ]f Cr$gMyjx~b 5Qտy.CvM{E0+h Хga*$C>O7fodD)#RٶF(QQ'}UZ!HU2rpO.i^uKQԨ+dG .@2`/]~_^o8LrJ~])Ab[ǎݸzY}43M&-r}j#9tz5<=©*s9czկn0[PS,H|O4l؂Cd 0#c%'Ig"`'ӡߣO$ƒruLD5 VOnfrg\=0L}I9 1HSp{iG܆]VBp9nFT?LdJk.sJ.;siD5u@\L .k$qT< iͼ34kIVʢ:!7㬐anսr_Jodp!3ڴ FR?mWl+LC?܄SGS֭ &;+D(L®=;sUx!d^(dyOHX{6j*zk32WރRR1@KXK!)5(X gِCSXw%y>˳>B/-Uni%ek/o#IEw'g1:j\f2&d|A"ÐWk1έSfAm\mA{ $u bZ6Na\M&T(K+8TGi&-* edX4 1N{QW]sT Rju_}聱Z1xZu%%C[l[ڌ1b}\Od(|xRۍ awuoJp}dcNbWҏf°;:$l;Qܕ'r/nEJf~tDKǕqXC膰U 5Ojzp7Gvx|ٺ0yazS!91OL*K::BQPo^Ӫ9 `] 'cE 5 2s5v_錂eX()=!ެ w1VU 2vcq?Ɵ4{hؾƃL>x}mP_ =IWLWHQ /~υ#JLBT zoi=9hEmE*;L ဟw[S.0 0,q8&I 8~k3Zݠkָ+L8Gh7a)!o O!!/2J4ћH1>*Ŀz?B_C<`uM] Ld\QW8[+<[Ge7"dWrh&}-|&(2q+y^o[DZDF+q\={+cF@d7 q*]ߐ˧؜.M5HR?o*Y|Qv/侶WIf, o $Y E݇/lM:~wE|EWmb*[<ȫ ~SJhgp/.&i~F*޻qy&2]:lM dW$.VϿ_b{Z>;.V}<Q/; 9סNٚ>>m%aR\*77ߙ7ߍem(q՟\5z?lh,[̻fӀзw$U2Fz)o@l/qozP3xH4=IJם#MT,΋N˱Ϗxp"ޘB]yX=,,Yٍ犩v#5>- Y_s|NխMbrҳ̟npsjA!x)oͻOoYfo oh] l_z&Ns SǞ?ؓdBIjFȳ[ ~)&&wt8˶vW:@YT!iyͻmWKH23tL)6MG cY6^ jsWy-}~6u[+rBTby,{8Zb.:R*}[O>ގd@9Ch_n#Z-- 8% kq~){|OO1Os3{kJg b:׼3}D51ټ65;-v lyzK=j\|w|`]Dsq_F`{[ ~?T9ES&vJޫs4}줉M1NYZ`g8Zd4L?vRT՗ +Xw5i!؉_6[?1l{+>.=ARepA͌QҼe8XRިj'pG}7_g g=Eml3κ.<7)DJHk_b G9{H'qI uf 7O#!.d:`G!#V Fhn.ϣX~#D 'E_#fTm8*5IՅ59nW?}@`tQ#* !ΘWWQ?Bi2AѡQhUZ̫2ܮj~V>d6:MDhie 1%SJX&ĘK嫲v?ksnEV"bz!1 4zv®I] O6 Ix.\-x ]霌ACoAj]quV09gu^N57U7/$Ջ0r" &1lE"ʘw1n'h72͘5KFgpSO; o$nx%>?bvl/X_H4noy۱OL@q}Lأ8HDgD7"k;+Y;A9xn[qenOw9b{\c'DŮ9#4)S [[ Co > Lɹ=ߵ/A;+fŜ+q{`Ψ=ĊU5~+r˘9wZ5"uk\\ށpiR:s`3)dvzۀQy 17we#!j+n' K)}s9ιZw<,'wBm֝? {ǝm"C!b={\m6瘾S!_.XBLO6T7심itD\Av9@wc\~2e3jKeutR=Aj#9q)Xdb[ sC v'N%AifÞ~3U:$葊.ḨZ{:!%|'IbzO;r6T on;z)"<Ǫ-g V<2&qTۂtg%.a.41zO߾7yr iR9$›}1EMaIhxKr+VwɻzBKѯnbI^+WR&_G*c@r-E{|mAޒbܗOCE6>s}R9#UCW|ӈr0k*Xu:g;scOBuu{*3BJ8Ns}ּ^2ZlbCE+P7}_ P{=qdL~yV8ؗӿQO6n[CIiVS> ÔgAï8گI>QߥYDWWCdK '"?LW5y5,@dc "o sr 87ǢI=N=g!k<ϕZkle:/_A#:$F|}#:ИPVu$4⇱_ ߡCCNX/oؿDf!lz731 hSg)nOzsڲԉs[: 6iuj&>!geiȼzQtW~fjOJ99|EqbDpЍrwNڹjn.Z-`w$};'Dm~ןnx A&ψb]KkD5mMOҚy{ J"VL+vE[ZgTq rLa=]ܙ%|2+zvFr>ZhZP~{cˬ"* ~LJd7$Y.4W]rXǡ bbK]U;kR{Dxu"ڜRn!?]{C/MB"CEǣFl†{d1dwQXT>UϏ:${zz +ٽr H=Н0Ɣk^{{ЈTWW^H'BUu'{łtԋԟ$N '$1#+)qC>1 = pˢ٣ǭ#8AgPD xNzcU(%yi.<Z! Qq͌;n"ǜj']w5~UĜ(7|p*T2 z7Yr]UKUԔ>UQӷN<%ZҪH1aȔb>u7B|2>QsYpۃaԴȡ>v5o>{6p~K-%l6ڹ%ݸ*يy q+jIEm>[`0$BEa7!cYM$tQ9ʽϷ~`n|f=_jB΀8ϐ&ŢƧ,|nM[4O@ڳ«Q lS3ŻH.65zvz_2w%)]3i+W)LPjгT\'J\ڦunz$QVΪ(Nu]{nk-E5xx)hV\Y7ӎ|6p3t#7+s]j(0to)9?IKaj\F{mge\c|=Uq!Kpӡr [ҙB*GDۑX[^#knzWOEJUuQe&{bO~?b:BTqν bR/'H7Gg@Ի& ]=x֐=UEԍĉ-qRzIl~!G^,aׯe^Fs9s䯻n*nsxiGfo9aUuU5dcS9悰"}Qp*SyOU!u&.o0̱]B_͂3=! a EkiO,ZSہr,>@/3|MC"-lݐK8!k̊@̅ T<.$3֪,'F|#W9W<_R]]~Hm#e _{¿0/X/rspD՜afku>v!>:jq2^Dyj\u$da%=INWE6߈*Hbe m}aS.n]k?`)v@R)U,cHh}.8-p5ǽ7ݷLܺL ?a_pOjp!4-*=3Sw$@^ MLu<s%=u|7$vHOX4k%Xa}?l:0RFڴe̖l,C+QcZ F]|3/9]dFgؒ~uGr,kݲ 寮͋돨ΒrvC"}(ªj'UkUfjq&(ăf&T~ ,!)w qn:eEQ}]:2WįFTb7w5<$ }ȯyxNm챽|S~69$xmMt`,xOz c{/"˳*~ ѡ9vvrſ 0۾Q`YT?xUv1\Rܓ jO;n6/Jt/D+Ԛ]oU>[#/~ܞOTf˾ORx:x {$)r}u['.M$OQ˽y{mWpL(OzWx_~SGms7H{M3E%I/sّGZ޷#đ ؙLH-ǖNK2v -ͷfCcuX%3uc1G̼np[!+u澤[:*n`QaIf{4W@4dTWiUQ/Dz6H T%我q'әCu.'TwI\SsJکA$?솞E3}VLtY8F><^=#-X@u%p:qCaƋQeZ*>¤K.!DuolAm"Q0{tzVOr;$)g 4+z*tm{VկwC׀;EqbM7} 6mvtY,yQs$ӇZ9hD}:oފ's޴7e -';, G,xma{}>Ho;v'WW!vm@P샞d#V>?xao2|a toȴs`+^eDKF7T.$[ o(~:.-X:SQ&g7 7P5C7<,u"N9ӡ8V7 sI3*! u68`>g,3%’:#%k Is0sP\U?Ŭ.<ƥ{6# X>™9vCL(qg`>QCʭ[>'r_vq&i !;oYy&J9v}G~ 5JL½T=1L;7:kN.7_|aB 7Pv~DmO\G, >| ꑌ)zCSU>ٴ֢;r8Sޓ\㤾w;9K%MӵtZW-2~Ciw_w @ԂYKUذgc"_x~:GCGj%Jct\9݀|壇5_/?eb\,@^D7l4AR- R-xFNwf!ɛRm#TS63$_tO;]&wV|Qx?,΅=׈%?b;R ƪpٷݟqD珈oqhxcHu>pB(i}5U1uv嬊3l2Ui Uʎr|x%!MDKb@5޾edVVuvt8h'@kjk%C 9Q6+]B:ZXeFL,MRciaJ>խ3MQզّ<TtaGjVZǷ͸;Yqٟ[;׾ꉰC:s7QO(?](QUvR;5#wI-aF݅xWAKl ڟŸ~\G [N{5HE$-S4RȩƎR;k_>|2EB"}5{WGj݁T9 sQ̜|F UjC?yGU~o,Xf4F՟WXoaO|T/aOk(dx}O [`!DeX]<9l#y8S)/d. sfߓ@7 Z^v:Yi̢;mNǯllp"L3]7ͼr&1I^rϞH&6ZD=tw\hTyG_0{Zvq"Жw 㡦i0&9t&y3WR[$S /]N>eV޹erU v,SV,@ I4xX0|COL'?Wט$`+ñwL͓~Z24u%Q2l҄zCԛƉd?EaTl ndB3_`=)D+cz#5(˂{ӑVJ}Yʭ4R rUsgŎQ ͛z%UöډR3sXHVL?UgjByrʡ?2rx8 6;2 nߦVOly8z3;Żj& ET;yI;oYjaωWр\ eC+V ;DŮGi蹵,+f+φf'`!5sEKc=U"rh„DOOKcA7f99֥x5Wrq|6)ԪY||dOUd2K&4etkr/>I\EA__9D}tS+e|́izO⟗FL[=P\ &qa"pk&ݗ6{n =IK+h*GC/Z`RbvI6g~ Iid琬{37TN*;pcHBɹ' j۵FW!ʢpI6$K/-$9_~ZǽqrɶDǁUF $ЅKxls\)ḳ_ʟp뷯|($hiG ɬaq֡wn?g_h}^~D-X<fGR0x9hkJW2[TQ4"я9{Ӎ䤔dٴRƓm[dS1݁Q](ҋ MA@@:$ -zGjz ^ Ho=4 EDP@:Avfܙ{&Μ<+j8&_mފEMW 5&G7<;1.+TQ)3mj$#hkfmDU򄁢 zRVt5KlGbZ5O\K·צFf9gv$ʵufX _9M+֐tמ7iinZ̘ jyDw˴}o)Ҭ48*7h>u]wc12ǰB5J۫/΍Fz#wE;;w_̲=|~ Dq26}G6}vXυbnl*uec"L=;"ZO/3Pq'USb";X[|NYrv0}qV+/gpqԴT0~ 8}j u-t6l.BC2}&ù?sĔߚ)>6oiR;#ny37V¤+ȟ~MKb>Öjjf;Uۡ=f+..4C;Щ L=kBCv?Pu}o.9ڿ[=}peD5ն/N:o]c佶%;wn"pg7_9}OлQ`5MkkƳȳRyJo<YmOߵXqՓER=:jY[3wˏ;Va"U#\5{*8 c)#L]˕#k#iU?qE(N:q|[Bhm*T_ܦ:zC*߲v?/>9Uu̟nЅu-iex<[m;mbضa'wضH` F*Bw~؋4t$Ȉ'Cbyb7nGZk7yK&a$Br'|P=8a]vou|7$?Q8J~ -OK<>éo+d,Ftse>lcIʒO^awIFZ؝Y Qw[>uu+UĎ!@*~,{ f|;%V n]zfϢegu*ӛOi> vO>xPl e:nMnLD9m n/?8Wr? `b{g>\hhmDrpGxZq/1^pO/O3*`1D!;Ck% ]޳i *Lf򻩪. w%i?ZӫxM[y3թ?~SbPoacpSk?epYF5iyܧ/=hX)z9J#̷Yte+=B7{ݥ8L 5Znw["[M l7XND/C;75?93޽- ;{ [HL*(osrL^#`>\ÌjEyO'wrնd=q"2e2}I[ĝꁘ%*tJPˋ|Һ:N*W5v(b]jm8E î"eXu]wgj[d fya u,Q=p: YQCT |<tpRmc/./rMu|7g8y}j8kp!]2kUy^*cӟX){yChaZ=y 'Uv檈1e365tNɞwhSC+L`[maW灗g i3;L' r U1|Zʫ\$P5dy#?\YDs5J ϞFf,qlI*ԻH¸|O666$9_Y12gZ=S`斮`y%7(<3Zj''8*m)R&}VƩ1buH)~(]"aK?5=qf9r0Ս6!l\]YAHY t@z nۃsv)AAA}ݳؤ1) ˽}[wTDQݜ6 "sT?΀'C2fl+glRy~%R#ƐH iI*mk<=^oGL&)]05 KyR0bJ35en l2U<L)pnشc'P/ҧh )c%H"[r?Q< V3ړoLJTsQ)gܜv aaWlMT=Z1 't=P&Gxk[+iI+|">=ob:7 V|w~ ֊'ꞓY^:%EnxC7ͳ`_9I^_$is艨V@D/iFi&]qn@j}k͖z'ս@uL%܁ɖnYuc->߀8˂1Jb^Lw+jܞ;zZm R`1Xfb EL@۳Cz ~pC\ T[u%jn-@ak)> tbs[߯:97ၥmF [Ĕrk:xM٫: i KoVQUnٸ="O6lC^d;W)M:ضdI]E r#*0Lpn[1\V Q:kPV աRaH?w[yZ=5. >19\r,?K>6\~B^w3ʱž+Eb6ϔRJ-=2GK有Vg7`ORALiL+q8H.v^ C ?/z=ޜ]SuQ%w=eF_whkWjX&I*+*&e|&'N-OѺYLϢM ؓ)T9zl"QC_9ӷ1Bij`}3D؜}ܭGL{ts-uB1-&N5|Ur:u{,D0%{9bڑwsbnΑ_}<<[YwMv_ٜSf޻1'M~ g}]kc@G~bv|鱮g_}{mbf:fPC5O7(@' fۮ˘yub?TZA߇1#rݭzUD!`Q]k"U7?)y駱vm,ؑJ"~B'ƾ"!/ۇ/NVNF74FFGmœ>Cn8VZ9M(N`15)mSϠxw2|vI!֐ٌ%+X}ָ]wf[)/Q`'~Á|CEdRI_Bؔ˘xAT#*SCI#sDT^H Sc #G<yhK89#5FKvG*L Et,2ODQOvwkr. 0-k=f)P+^x)T$f)TUon}DLy`(տQgc@/yyv_;-ᤢ #WDNvn(:30[YP7?e!lrO$&9'{}WfnR}ܥn4Ekꟓ;I*cffI Kٟ_kuȅd'© V1/V-;|Pomw#_0Y:g^/q[7~ummF۰h*e|qޔp,= TFMDrzǼ M>>af C;HE-{Lr~)Uz4d{}|5IZ_SS囐Rč u(-B9??ezT_V1ݔitg#qE4Qy8_W#SQho`{dw%O‡|;-szy]!,lwYW9j>Ȉv-Vk36荕\G5+kl -B =f71(@41a +x"QT1ؿzMSJfn;xKTvSD RhɕV}f[2 ߎd!7evDwTeۉWY;ϟޛ0E h|JةΉ:6#Ss OOT6^}*ͬ?϶6 |!4fX00[džsQrU(;I(yK絈NGΝ۩ԛpR1̱$s_Lo)2fxSGff\݆V)Β"˻Fv/U3B~OORn+5 ;[[NL{3f} w|?Dz|7s<ļZ)?U_?=CBW%7F"D8sLJZrcVo6dܬ'[^5>v648G b8$Ӭ'q+uѭf;8ᴇ`JN oJpqшRb7֗6>:g_lәXް.iw:X΄\YC2Z˪S{o Ô'QnC6ɞ}UӋ{RPHM}]y*t^%OuNQ21?;޴W\D7`ަX"[v݆Tz|15W<%xە;Q܆:" ]1=T5NjhiͰ QST|j?3}nx>9lO57oę+3AEԅO ev+wo/e9sn`Y=3CpXBT[l3#/o:}=:UT/cC2cAݞ)\H͵OCDgsd(0UƩdKXqwx^B&m)9e7iN'{rM']&NA$I&~O_NjJyyV3gL^EJ]'G\Eʌއ}zxEK̰2|7\gVVv6>J g, SkEt19XF݅k,!ӳt?}F+E{sKt]9וr$M2hjZXwj" ؼVq>u/M5"m1$lK:'42/<j 0< .';5K\ N&YLuf a8؝Å3~n1[f5Ů*,!"eйSm#?nU"0D<܍B'R~^s+ 8N|Yd`i}Yq X)*U!䌄Qժ`Xs6LyM`O*b$cs3!ݨGt,! .'e,op:κ5QPU 0X,ifC˅(XgCʻ3J_:+}O/>˘Wrt'Z ů#l '!.M M\y5%7Ft>ۚ((ݨbCB{\<RAIQT3z>p'񆝚jǮwYeo؏ 2O?;v/^etͻ 酛d3ֿbJ`dyVTQỷRe3W 5#k,(ۉӓy5e4=~٪YE#ab+kDS>AQU꧂ۘd/+YV+V:Qqv *ޞ"i)Bܑ8@5ȍˌT_PQ]0;CgiuoNbyBV!ꃤ=\-97`R&pW tڍV sj,ĮpGWOR*&A1:1a;\?sv g<ٵ]ϖ [k~M O!I?OFcؓUƳd?t DCyLG ħ?z S ;e!3PDfşx??|L%wqmr4/E'[dp7־J:gg2;|3b;=yl^$@Dmxw2TL(¹GtWMޞi$}tb Z2jke ?u/ uEԑb-ӋTGxeϫGbT!z5y1kck45EЍ^IN#N|f'7=4DA;YNl–σָbpCrdOJx @NHS2MbQ]3|ғ~,b7 G|<]9^5>]t>Qibe96=$<䭽U|Bӄpp$fp1o!4r㛪vO~ܧ6 ̾1K@I?4b mw=5[2MHb !L"!/LW n3  Mݬiau`ٕ\ Ķn um[ů;c|& _r[t/@]3FuېgkNo{Ӊ-҂%)<!6b ]3HEkI:$3[{ԥWs[ 2Mq,xW锜5l='푺j~Wa1r({Ob[?Г AmI̶]Kl>0(E/ռٱ+3y4y8\􏛏TfL-I\H.i!_͙W%R̿6-{'{aXR1v_(s3ԘVr3.p(R3JxQ]hc&'HKނT]ޘF8 m;&AMQkL??-;]+VRW(ԧ|V"Yj/͇}U$x׸BoMd 4V] <63[_] ىȚ=*fYkѿ ʢw^W: I)mf93!%H?vK(qR܅X(iK7Ϻ޻RZVScωy?mh fF#l՛mRb51IЦ̀7!b(d?$gpb16);0~~h\;|2뵁im.rE~f?2+Z]3s 3p\6HkXb csب}߾@NҪ^S+!: YЧk 1Pz:mAO4q%ه?۶9.d`6ܒ 9~[ iOyD'LJX,g zI%O+w=$4J&SG\U&eQVP{KqG:UiϬ]|d]Љ9Ҋr:Žo4Y[j(? D5,+/\ss>M#n缂 ʂ'Å7b{Rl?l6x9x\U ?/<{gj˳g3'?iBw6Mv$V?yI5n|\f[ |7Ҽ%YݥNӅs#wt[jcN|3q̽KL1DZ YHټ 3; 1n $q3JJ@jB9Ƙn~SVW8WQ%'j!gmWOK&m :Z1qW͵nd%H,UXvM78e}N5+|;uwRNn͎R@#n*zdw`h .\%:p.7=~JġQ|6!3 (]A`*P&oVrn ~?YgȻgk -4<gǹӻ=< ĴUb#C\D 8ky-1ܷzo^@ jgcuUDqAjǂ\MicigbZ~ct8$W:7Amwm ^zdC\Ǫd Kcz)+^9Zp-"!ߵOt@y1Ao:6!tǴZM&]y7ܨkW6SI9p34݄Ҥ9&v<5hʦ)v&8hSWUVAȲHT}SH`RۺJl4˵W}jj]QQS\wBMzŭ%>FDNxHsM oXa/cwRXsMh5Upj[7"w ٷ>ҧ\?Ct'Uiٹ>61"ԣU\R6%Nw3їJ=aP̟=B:m9Q||42s_ߒz5ב餺;hVc'}Hp>2=Vn=jC[WF{vΝVwǡ خa(]:Vxo @T7+hJxj:0BګDR!DuBk׉V*!J:iaRXp~jNK픵dAdP'87 acnݪP밼_`/$nv%b#%w-~౾z ڱ3-2v6Ww!SJ徘{d8ꚹO+uwvwUQ`6g]ͧ5'ԥdYZFQ6sM?'} ]?>z"9V!Fon[.NeK@TiIыTOt0B@7Lt/nKv'I OX8~R]Fے>.zx af C(u>P'M*: ӨgQTC]?eV ش9WpĊ ?Mx+}>i5ae90B =%G/S@Ĕ푒ZXrC՗`~B"РED}GE[@bij޿ty],Fܞ-镉Obexo+Rf4J1MC_¨oI齖\'H^JXsm\OG*`$&Z\B'u4vU5ZGiO<8#dT XBTBSK ixaCy5aShA'S6]>x:bT9M{|O]jޥy^>j؝ h( j @t)"_] S^]<^UkUnx:vL͟D\El$̲HBܽQ[C^vSSypFLMk|vM9ldzg Qm\MW43SWEJZ1Z< w5Vhs+ᷤ\noʵw߰}c=y"*oi?6Y,W:TRN}mz9"hyBLAyZ>6T)Vg bNpMهs=w)U2z󮍞H_QO/̠XCݕ8E?@TŌ3|NعUr/".:r`o拱!oav܏D,?[c}OG38+>$BFV; ţT/L7}L2"S}2W-bZ =ɛrz?ͭ;Q`;&1>-ß_M˕RЮ] E'w SJ;=bzz}"F$z[*m&{}b9D`N\F꒯zϧwL-Õ&s店)j/.iTP[U\Ȓ1?ZmZm$,%խwblf2aט<|;cv}SM^O L{#'~ pFˋ>1mdYmdvo7|1(C֭#c- pג˾ƽtʇC6eԜj Vnn`I$/Wo՛?DZ$Od ReрM觖}~@Q9Rcmg>pH1|Cp¸mK,kdvψ_t QOQ<'WJLsQRT :ٻ^k[֏%Ue))}WϿ (ٳ}vne61j³2G&<t-Ww'1sөt2jK2FAX <ش: 0a{iҒf"W]Xtq02UJ0zp~cH3.@L[ 1Ǵ&c QD1Jiؽb=tzsǣy*}gɦ$;r]Ow:r_沁032}faN'cs*$d%1vt6" Y-bɄJ'ָJ#pt2ɍ;8$:'0?WB­In8KWkՀowDUJK;g$$Wq]Z(Iz`7zSI)HXvnMJOd$?_y?#5]zyXan\yA =Iw_SbOzg _Qj:0Vf O̭c$7ZD[@{ҕHx5h;R4|K_kW-IˤKyeWg%QŪID<); 'RU*|ҔZ(aaU[UY'IJzn2m-$6H~uv_"n/./ΜD_NRK:Qt*Fcms7p^i08P0y. Οg*}EJ #hYp/ YҮ,>kW׮\Aqړ6Ux<7DwqjIJUe[ 6V$E3rf7 ]IkpD c%7Ik~:#b^U͹̒`lamtb ;(\i3t\G\{É^Z{Q!m=V`U JOZϟ9%d F(o8W Q ić%>-Wԝ6Sf]iF&[7Bp0{Fbdˤ mt['J^e4E]Y]Hk\JQof'N.8CoێTWfEHso,5eb:i;Om7`W ?#9u55kRI7~˧AD1M$9Nptb-({ C d`̼n]em5>mѩ6V#s7rUb̃WPLjńDd;+@642m~L',;Ly16\YboR6l1YnŵtJW[Q(yPTŧU>IfImv)16{{[BHtހϜTDTXOՆJ8uvbx%cj`JnߑXau$^j侪)@0cGi1t ;})qX&YV'sRg"' p8N .I|"ri,^\,!!qok1N HOxv{gԲ` G2r:gfBTS2m[hv3|?6f_%9+ɤ/<{j]?;O38%yɫmT;AMovN!;iR?!'hne|)igFr}5^ 9&}}x'zZ'4#;zct3r<_hx?U3I~b鏟ދ d{ [F#z[f [f R_&nIIph^ J"WVܵի yy6CTgZ7E+A4pbB?|baIu!bn*i)ޥ":XV:fӝTL\}ބ [u]OiMi TΉ} : ih LWpo Q}@Af_y&`1Ĝ$S{2=H NꗱHA&q?&P/0rdWM}3_CI8 }sfDZ7V;]prKwHf*,ujp,W)5x/&舺w&WM?O'8; dx;t)S^]dTa>dIp '"Yү7s-lsZ3D5o M^2}%,7C.NgG&vILtN"ܗ|<6uyvGT]A5ILNJaݒeCKS#T}GN&n$z#zryq}v,kjcg@YLj*?IyHr_;V1 *eV1F6si#5|'r/ޟ|yU'!欪?g\Q+# X1}ڄǮhJ '~҄XAv hI(1!Ol{_P /2'<>Vr 7\_T#hf.f 1/`RF[D]OTp+VCIK_+}IW N$:_Uq#3QE*01)aINgn"vl&pĎ5z=BLUcMƟs"'@6Xt}ϧ§wӖ0}-V$/n"G|{!iv^۴KպJ|C!]|BOj.6yTYg2LUA/aiKغspV ߒ:#:$l3ᒟprR􆰞T@Ҫ>i urėzHvD O6wU&ľ"1;!;rѥň@8vg҄D],!bmx J",bC1֍_AMU׭6;d}lx[D pMmwQrI`Šm .S-G ,nӌfKZJE;ZbmEf>Hc }\"ZIy&¶xpxɸBʦO}; QP e"^?ȧJݦ ~*^ڪJ6aٱ%F{EmO)~yf麑-<,V1__>56.7 |v>*5 W:15~ 5'?iJg 18 öώ8x?3Q!>{JwjS>5À{VDgũ(sLT uN7Ȫئ? <Э0oJnQ lS3˫-eMZdMRdp$x n#Cso8#> d.g׉/=d!5afSlj!\ QDZ+ț,vֽXbfrSǢ)pz{_4X2 pB#`pwl;kHҮ[B7n_(X!hD'|sɿ)MYE}33r/Dw)f`=vVBY8 0cxWzކP)티!"zޥ)!j. 1\}C' =y.MP<݅i)UV{LZ;Qgc 3Þ2z􃷡%kيJ}x]Z[/o< ApûẢ%O {3z9 w[&Ct_Xei}'R|@TK6Gu3[,5qQް)'^'QG;aUaEBlF̔?lkLnR|jI}J!D3[VáYz*7;ձysv?֙ԗLjI]l42&V`v&'W#%̇H(g⯾}-oI^k߶|ɬT2=t~9;׾t jt R:=Rvnoxl jbA=~K{CpS.yIS>WMiEO%}Ἑ)M`&0j ޺뷏K!h~~S1.ߨ`4aRfoл6 k{պSmZ){$O˝p[5멌34i-n뛏0Sjɬ-,c񴦪[3uiMwi[p{%=paO{z4ܢ}6N?R>.0+>ByՏQ/>Te hk|ߜY37'PT(쎸%n33_)̒>+˞=iwa|1Gun*S#^BkG~ ձm؆>@}?$^yo\~klDwzT){ =rg*ۨ{d7;/淿+ԐNk<'@1Mv2|{:{y=+=m9+ыxg c@?" 2RLS{ڇpےo8/JY q;r}ǎT["ۥLAƬF%8k IǯUs~|ar3y9YfΉǸ~kr~ -g访:,%]ukq"Rr2&At*T'{W:# +K^Bϟ:J N{%Uҫ<^ҝj Kž)wձFvNQ=kqV xetp}O;z#kXB&Si=8a(]2.yJE@ԫѝs}\/>q7%uªpmLG@9M\rk\.V)j!Μ1Ҹۭ/'Hȝf\ m\1}sB!ƾ0"C+?jBqfr]~q[eƦRmSt>8wpz@KےGncU@V}6{aʨOfA]wNW+reE76{angj\SRG=4Eאޖ,ި Bw$+6{ؤ ɲ#gmiy {6+C-\ȴ8jwDo{X Z'/dZ|q7Zo~٪_<]4w$ ؔiŵL2!%^0ebStOGN{2^clT۪WǨ-_Ľxem.U͚"D5,e}I|¹W0t۲}9]p=p!Յ0y|!Mc_;-.JQ3swGcL,jBT8=|X$-0S4 9wm|ۡx(;ba68+)YlJn9(RݒGN42CTl4=\WvSVȟ|;ē3v55*`c5$PaԐd!>?bDwapF^!RO{˯RTA/,ĶდwS4r;85cpo6p %CkF37Ͷ}Ss6OҼ0p<ظ^ܮΊC w0١mm=*әF~^@nc\[ƻ#e7R9Z[BdӃVϺm#s27mᛪ沈MD' klËm]"ĸ5z5{u_NWa^kmf5rcݹ${v\rek\)k"^pT@ƒ unIq!t(Qlo-{M:z+FXjaM0H+ZOiY'J|{@׏4"T? 4/gB?~ ϱ-zz4Bl Nə*YĻKN41'*6dA-oAtmkg؏/m6/jySG-}nb1o/ަ\`d[}39+Wz4cbZ~5nM\ƛ!s;" 1movuR6e'!`ƍḎ#CmsdIӍkGaReY{&| Sgxo-UW:6;ƪ<'s^+sY#LӘmS_NkߣH~jӘK>{%+~ỏWaA2IBtcT OIJg̦^0ݾBU{Ij߻Üڝgu!ʒ9J51 v@T^RPMY)2rLZY1ӅG~sPf1w~j_mrGgI&I=YTCMD Y߯u{pLt>#:YY׹(ds=#وssޖdݯ?OTrI|p(uK94rb刪T#`oҟLT$ŵ՘Q,˓pXdg,pšsql&C̏a5G; \%E$GQ$='%3u'|3s|Bd2ǎvlG#zXmR+֘ѳu65Ҍliг-|ba./ǎ aH)FKpʝld{DՎ1vn1KWA_ߛ7M( QtF :N\T;l|gn7>-Zӥۧ/"Hc c f$Gc:9DݚctH2dp }sQxJleZxM!֩yoGT6 >8F. Mc^p;5iZDx1oOt^-d|sXLǽ7| QGtL7" Mn~\<Z`M3 ԝ~Ww?SsV?N]y׀OFM1goVFc)9N1EV DGbݔ9!/1"g{#M^Ƴ b'2EO~"thn NjB/r+sy4[O$?(-%DE)ա$IƓ}KH>,+RDkEgeF̼0gjBk}&:oz]WX6E_xo/u(֒ɽ^c5>2>_j z :I`K@S4>7NO =cqG$uQ[2[d7GzӐԷ>|{psl7#C-~}ٌ[.cZ;ĂYAn(dtz>v&T ވH;AQmoxs-T ꊩs]xNћwцI# E'ePTL蜰-\E" ].>)g}W"ȇ+gbE>S{]H*2iD=5?q\L(ZUз`^F Ǻ'c-Pd]Hϰd赽]W*a ( Q ot ϻbT_ibNa(%=3jUӼ#"h#"#i-'JX>Ȕ%4e'Mu:% [seԦE~t~.lNݔ? $SP={B%[Q&^+9*toW;gόxވH* wV:n:?̂\HܰQWRElŢ} n-ln8r | FJy\LQQu%-rBLt RUPo=-xLZivNHԲOl؍UUrqTc2}ex7^q(zfQ<[_MlC5o`zjo4*U|WAM^B%os^r88@aywV_Z9bzNiyS3 d5jʎ#ja `E ĹO>H5{''ݹ )pSݹD5ܡk Kf+*J4ʯl&W\CbzcҊؾ,mD]}A^xӽWO#η#ցj涤vt˰A(Sؙ|ꑀW hTzXKW)'L9>w?Ur'03ޕ7p*}Q8 L`ג# )2 X`#jf߇'=By?~ne}^9¹ ^$J*}2ǚ-άIp7 ?D}ҷ3 9`@ &fZ(3[A*'Jib+]%cǟ405LW"b8fUy:4o;TDLϩ?z:.#LԆNk 1 g2SR /=]yn-(v)~hyu`х ^@tϘ)GK;/`>zlG<ȿW<2EOԉ}2a:s;tu-|-h`e`1VCxrP{e?]xc "V#%=KYNk)Bx ٳ+DYT,;6+\=Q LXD彥r2æB6rR3> vUy$rV%,fl;9A_;𔉌ok5jV"~] )$;#lGƝ5kRZxFY%} CxPq?F0 bck/ ,z7K0H><u^RڻG!73:ޛ/Cʼn"э\ZHͯw"mǸ}ۇsh)G0\N}@ff,:Xde=L ?pVO*fWn~즛ol2;E>e&]w~'c6^03o]}1%<<ȹeF׃Ɍ'2;UmC]u6#,*Q>PZa7!r̥_'dQtK jc{9O*J6i:Z9aC5/``FO!ȑ_Mj{8bN~kl7exsM뫢 ԍ=%^mOAd)C?_O[ |UXuF9rsT"Y,]dL\mdokH=8{ 5n[c_{AbRaF9͗TkQ]M{7Dq>',\j~R_jFHS]OR.$+漧!^ɺMgj}z4# &zvINV5Y՝OaD68⣟j NRQSD֜D;u!?_ Z_O@g ?)˦ fNW2p g*dMkC] S`5wS'houܕ2Y,r‹ uܣ SA#n 9 ~Yb/;OZlvg'9K&}ZnX~VdYNin;̅cS3y鵑EU)9-m) \쀑"Y8`8#{攩 w%T!譾#5d6&'9Dŕ"TX@S dڿ=3xG92bN PM:SSSaFaԓ/-9NwuDxȀg"#NrS7!sUC\-Z |G9ܰgI@Cy|PG\StwDm-E QSG}rEDt oGtЮ'E)Gv?~,(G5-_zވ>" WjP'^?m$ 67NĺO8l."Z<='q4[t 0CFh6zR>DXVVd9V.٫ @0T eQuϷ'l_OpE筭*a@ *lqw#7E\E~Åyj-]6y2\MoɺlRWš >0ej G }1QRT4Pn MDE@Zz )4HAiҋH￝3ν{}}[ٽ{g9y<@T^gRAMCkGɮ]he˝4dxvi+/[sZtA ?zQ ]w(jC`7y!6S@?A+ޱ@?t!wbmWkg>#U+RT ypV䊖^a+w6T-ג\𛅚Oȉ:!ʛ+^̭NV{4flq7=% 5t&$J7>)zzODհ!S٢~MsV4DgKX Nr-{o31B'g79{Qŵt#Ƞ r;/D.K] nsQîxJݷY|}7S)o< %QVC'68g:e:k%_$pUu)zЍcMb |Xr%[rBmjnu @ -EJ7IƿбWE]y~w#N~'-iԭtt)S:A}GuWo#;YWUҐj $1ߗ 4.!! ?$n}by~sGǦUd㢻3eU/FͺHaVoHF_lW{/%@&6NxG;g"llӀbn)-Wv =#V ]1g]ٳt͝Cp[CCN$=ijFZ7/y72qqEBϾ&]Ccj\U\~vbGiWr3#0T*+׬BmQ]<}h.T>jEӯ/ߴQE26-"wcfAocNhZ<'n OR\c*_*#=K}vE;]ѥ7'MOBtu~+LptE1QE'q"H$Ql-:pۡiεڀE9S1=qdSޏ+^p2Ju' /9"çdÉaْ}mT~_paP LiU urPѢI?Q] JyFt ~}ze Ss8/`p&1/-C"]j'JWQo>ڊ%Φ qQ]_CĔ.be E<&Lm{1yZ#5kP5]Vl!doBh'sVzZ;؃O?--í-=`gE@h宁uC/TyE!YT&oO{#Fr;*{GS.rXܯj/YcDtK> >X =2Q- N6UK ﯹtȆmdg.MgsI>シ'P:؃SkxLUtS(q$o٢N]oKVG,jcaÔ6 O䤘veCjko1 FٔXogZ\QR1&jʲpiۦ|=5D›^GV.p8㬗՜=Ip거€y{N,njحd "]܅9V(w8SD1yiΉWݓ1n4bqb-(pD'΀jtZA\ Q9^s.}^]D,ƕ >lq 'cZ[/̃_OϠ:JÂr}uS_g i *@v\]1AxOlRUz7˿dǫꭗv3/BnNp '+ M n3@LXʆilVi?DL TyDpN} 1g-̛& ~{6Bڹjp0>:埲 xJm_ V)h-'0sDgF4ϛZpPxG޶SJVnI|?R5C֗5Q^3dWsO8w|1T0~/fS}L_X"GF{l}!>RMwqJNLO:緍ɶ<2Y Nm2r{GkIFr0k6͏Qlկ: VdOeGӒ}oXܠgh:v91Ws 1}[rcbWu}׫~uJВ IhjE%4<&N9NKmz?{i/ZWѝdOV2Xw~B~.O^Ա>eoe-4 rhEV8A#G.U{rs`2&|g-;jDr'6y"9Rʦ|twgۏ!OtbFy/B@Ͷh7yvkEŒM+wB$BtsV.+Uj6s8hޓMFLk2[ijw3m^ɯgm4Mɀ.yGXȍdoHҼkS}\ >Ƕ&'@nW\{`R& _y]txS7(eY|Ew7GCI#eF!ϻRи±$rt>y"G|~q-3~\=`İ:T>|d2q&vݫpttUE>m;vI'=K%og*t(3bʞUbF !<[޹yp >:9P'3¯=xJH7{y)nN6n ݋̃4M}K~db!~CKk=u}3bSTQƔ_HYTй2N5Ѥba++3:C~=˽`b#Z50~+q^}z@@)uWo&<֫}Vg,aR%$+AGbo :i-Nvsb-|;Tr=v?[XFVa17Yic!X1?bqs3eo> 璨5nQ2[meN- !f$b?w:~ŕD_&US,OC [Gb5I 37bJMIʩx?I s&ޘZ#Rfh< =% rv!O0trq'3}v89{dLq )NC=zSLhSb뷅ʃT7v,b:syNfY=Lq׸RibI]]%9סfǽ1c wOPw97$Rh8wy})ej\?zB@λ#4 䌮dQ9JQ>[Sǥ 9ZF/ Iz+޽e۰O$D@5K,-8~r'r~9tөt} Z^yIsJ5 dY6ܫīO~:Q-?[@k[[}njZQn2 ujﰊ T.H*?rw7Z7WkXOogT9e$G=`D{+o"uUQyxuo{/uk*# gp9up]k9|Fټ+? (MV?dGZr]qKkGa1/@jgB)oCeE EC]gtKAr@xzQPvai t5i ߕL2#y|ñgY~RD̋\YB9VoWq7a}5\w.v2l"n^޿ZDߗSeNҨ9Q??9M"R4HuVyMySo6)r&s[Oug2*#t۠;O.(?'E:GE#N')s 3~ <vzIs>jEH#[Q#Zb@\ē i[U4#*>}NāQ;b ֈ͍ ل e\$4'曓{#de>{|K=9:D9L6gts6t-/lTO&s>eLMSY3 GUǀ S>R>Eަ,rFV&uF&^ :@!qKN9!3WCKo\89VcW ,M˗q=m6 DY#J 2UFuCՁnΨ'3L#EI+ƳI=k?CaYtJGi+ɩ>|>tu$S95|m"(5B͞u;C$<ӥd[?ӜW/u9X+b%URE"B-fRuƴ#%L:-;${Ɛ F}$ș $G3=νћ אʦ-ioyw$ \= Dzt_?;,ĉJy>-70^>+yZRK <%}.ck65 l!Zf;v~ fvP_AdkvRxa;xmSѹU? I~JGxnwiG?--sXFjnzdBDђsfoMZ}4Y\"V:><{+?BmསxMC).7.{W>z nLaq_R/ʮpZh1 Ɓ*j eWH)eT(e2eWˋ}]ɉJ8bGǞ5TSER51wʮS"b.P 5ϏN8p3_I^ r!Sy rGagy10TS),P$j>gy1?7E̱NX-2!DF.g˚:fs]#|+,Ix@UODlT+: 9 (;v\ QLFxV!prh4tgng-9SNHyæV_k.=6ui.g^aշΰ&]_Μ JKv/L2$ӕ=/f׶mj9Q0Gj/ɐ(ucyHa:ymso_@6;HݯG@J2\Jk<¬Q. (e^qS~y$:{+b[7kMRcE晷;zETGzϓ(ף5^D]%k^+bJbȘ"r{!z׸BbRgn\uOB0*t$]=a/s}Ň^!~!8de6_.u8Y&]i+ ˯ 2&.1wJG-\lf 1[&wVj(ymqy_8b 5̜~\[%ļp*e%Ɠl-:P}Ht L'$DTF|Um:eOO%2W5[p( C3o 9nƔcq]n!YNT.ㄇo+W\&o'8Cj"ꔀit>H3> }nZfjs\عV2;-so%e};W,dՐ#"S S#Is*[w铻  oH{ū>bo;+$UD+žގ`$n- %c􍵆":[caF3%:ܞ9AܼCV'*a!4`7?>;q0lưdpm9|1e4o_yg~H91q_ļ\ue~J9OHFΙ tK2fN׈j;L{S}*g$jk3>l)Xý` z2o6>`n✙%7Θ_PQ@I*?dHW973G݊:6v2E )z+6Cj{dfΘt‘e3_w:/Z)q~c'Ԡ>?7a\Ρ uԴ 0ֲ٠a;ͭ =Q &;1hØΚ?-Q2w#s+ޅoH\#ƩAAxf(C3^>uVyi}aHȓ7CLD3= Ev䆨vd"/>qj$@[kb7DֲD.x0͆j˝ZQENjA>mS3jJ$QN7W?V\mJ0̌6K:c"EY"sH,UjKOߓQ>+ND)3Hd*N|sK:g_BRBDzwzKR~=R-=PIwvQ-/ GT Fo}؛~G ''yʕ$p,{\i# Q}J~ho8'ĄrV\ƴ Oz] b%ဤ<8>[GĴ:{PEs4$sݦ-PkU+Dv >>*8qVx>7)L;\j؃Ϣ7"rUk!9#v%b7#e \ly6KKC+yh"+5kޡfצ)WuLI;lRZρS6Q̘ { qT/nA!;!e˯_t;@7Wr˄#KkDl$ қu! =3uk5<JқᄒBeMj_g0F;%5zX2o򘂨S|-2m:rW5}/fӹged3aPkUb׸î} (-rK)+0ˮ78E943,N1 >L9졈*f*=O}MKUgM΀WӅjuAtvwCRd q G]mQ `]ݛM)m'm't%3&rAn2Q,@BHCӾwo<+㘡TYIUD?~WOV^H)e^;H3Vmڊs6m--Ռ!t.m_|UN%g4 iN־>`6D ^6-L+UA;8mMQG’>͜A- -Qvw?9B)&O\pU k@f~ݹuܽ _%soDLef,p^ٕJ112>AuojOSsdڤօ[َ:2y =NtJཕ$lך#*$OKLN 4>9)8c Jz$KO϶oZ>Q|e\N;?gщiC=D9 O2En2Ԭi*/?UĔe)J,%*yz? 6|{[!]I؃ӑFM.pH~BR*))rl ;(C;J׮p(SimEm|NڝB|UIkmשFv幁 皜oN!>NzY7vZcl= եY:ka#`.9#tOWKWi# 8l񔎫拼Z3A~luZƍ,Dku2*N S߄_뜳j%}9^ӯg.Y>SEIPSV CԱ4:mcRj\|MHOOd%޿ 0Y(3o2^5GToQ=g)o R>*F`b-eoc|+jX<[`ֈg)R/jh`͠!Oc`t`YJml!tq]ui/4HXs:B0u=^ k`Ƙt^n=kRYk.aEꊢ ^7/ _L$V25&5`冣+Ә#+KW%gZM} Qm Om/;`]~zlX4KJSu! 5*#MԎ#010 H,B3vOm٪%]jcbK]@;##mV[)uѭ= =a.y)n{Fﶜ*8WZC "tLJu"0h3}B? n)gke ApDv(æV'Ӹ{5XAn&܋[Ny53,5.BHy+kuøT1cEB٦ j?'jk,R쮂<\)yɹvB()TyK^K\;ዺPsi0fjO/2/sFgҠDt4>y$ƆIN0+eaF+@5.)Ru}:>JuXuDD8BSz(/Qz)cǴB-p< 4So>|%^:0_yDZ]SZZ2 3X0*֊d4y4$ zfDjC=,)Շ­S4:> ߄̸qs'$:1KĿ5*gXB_t:wқp%Leo̿4^uxA%߿:o:Jg|OkK 1#6}S :r&5I9] 3z>K5z?e9arɓ:&;Ǖ >h%?8n|zEeὮGLr]D>߽*1'/H &_jS{`jM޵,Ʉ[!­3@LvZ,Y'_>&d֚^}Iޙ^sQdDL'MD # M^mj(4GUkilz~-IjZM^!"lN&Å<ӗ.Y7yџ.-%YQLNV%io/ 3[E={[VgJӸ9λ m"YGWlVS&9}ݮVZGIF"VyA_!&QLxSZj|uĦ;lA0ϳ@H{rbr=GCT.3Z߸ɧSF^@Ԝ]|&9OEg/2QA;!<tiP[&䙯Q6 eoGxD1`r _?֕)T)^y ;CTD5ʴ&U$'$)yeMήPs,M c?XȩM֏sN&LefCr;վ1'8kRCR8T {u{Ȫ5~@p}HY":o a8iF]./zGvwjpew1Nμs`F%hsJ[Kky l$&wҸS#fKKu9@9_$!<BWe8iyqddsvmn^9f!0z1+HPCc׿Vg=Y~AۅC=2uDv HpHL+$ϩ*QPRxA׫O׻!TH8v99 ~Qܯ8?k.O{^lkѰj6n% 5Y]B ppin )WBO@Β{Pzv]vW |D&JD{vI|:o3q[ʅ$tjǾ+UAǦU˲Wrew@/v"1ҕx* u&g_KIj(;do~v"v\+Sw$β1iGǝ2r6I[JR섘/N0CHǓ)CФraa=5 M g7wr$YIӑy -0%O>IAɧ/wĦw r&y^LuQu;X jXAz]oG7s<᜸IMs)~Y*TSCธw|n@FYi; /tE{ZLbF+f <{tm:3>c]n:/tl'*$c4y"TțBԭY;W4ڔP+?ы|V[ ڌ16$6C-N`$ Eq-vHؤ.p?b.a2/6ȗ]zsM$v< ք! (g%]Stv57:P s]M@ ?7?YyQt GbkuJ6ŗ SDxA4:<ǣBݐ!wTWDT GON߉ 9q ]O/`6dy7oETU2%esNyf,ށDo@d:r䣉wuӤ".t0!fZ_9hGY#b(p{'ޚsͥәcRND3oWDhb  :Vnk+g# QYeo9_u$^^ퟗs#I&ߔz% ĢGYxiOD#Zys9SD0/UCv9CLEP'i}j3g3YD-N7DzʮUR^#eغ9/~SljtV56&&(RP+W,0pG`DT5TO@PGLMa>XΓ3LtE^os^@nSI; HOd$mbGڋk;":-i):'պZr*∜0 b/9YsjzPΤbQT&L-:YZ:q;^-)=^q}k8$鈄nhv=OX_n b2*Hʲ;ẙOGηpd*Ms&W-pomgcE3QQ+YC"uV1 lܓm4^+IMBݦXKݦ(A*մ%|/>|} N"WՖ$o.-pY‘fcB g}颣 id*b>dvb}K&e#a_d2pMxdzr*21?b:l1Ѥn=ĺOf%\8ٰǵdTVé`$\_я tKu̾%ؓ?7+9by߂!k=Oy"`鵋6%n*j&%;kP5YNN|Gς3^ j *aI: iJ>cH?zAe PpK] kѼ+ :Dz*~%>zL&^'QA ׆(JDfNoP= zJ)y$u._iTN^aZ:fy\0l|zיг^ojzRyA7-aG1!a1> Ӣ ][ZTAFP%&tUR'N:U?(i}FS|*_Z:p55]Ie9YŸZtit,{ ޏR68_?Uh,RM&=[h* #?I܎9Lu=˔eUгCa`TMPBXf5B}Dm OuLȷ={ N'؄f ن^>uy}o>]#dw 3FtLcgRNz YK cΖŲY&r|L}~}ùj?YPq'Ÿ1Ӄvp o P>ΤOBoa1wADL&-QUkƗmL Qzw0F|a::,3} iɹ TUlDrՐJd  &|hL*W +]{,BT,zėG]/LN~;R@M"`Ac$@L>hB+맟{In3ȗG3UlQy"m19CFat:ye~9i)\v>/? =n{r g~ڳ.w9Bέ /DTkw Y7/~u`c)vO+7~aڭGLsC!H֛A1/Te/yNmkSGw9J>0Ԇ= hX*N 7?oxi=HJ{ӸQ'!C3$7go0z>|0*jKrҡRGQE9'_?5>ws4FFs\OuēveqΔAy}=?&3>{9񪹢B/[1v_0>DvYHԫY<$׆S|oj!V`1Ϛ^|an#:)\p'_Wxj{) ?Ϭx{w_N{ףf\J.b8Z9~ HՃnwSTqb:KGA?džW~E2 ?g3VՂC|MbE)I"g? 14Z3]tn]|2%j]$Zr!LRǻ,uL謚 *cKҤu}ݮewH|-#ndn)^tBn^b]~ŠVmPw#@y R:6!j`;Љ0)`N^;_. ݬ2dq${Y_c;t*,fƓOo?4Ԍ:ʮ"aG>2-?tz~7J^<v߰{!lЇd©{O %5/ x*(TXJ?ux4Zy5FיS9o6BnLa׾fRD#a:(X\gauC*Xxzic|xf$7*Y̪aGH5B d\P>%0Y."-+K5uq?4Ξ!;M+p\{guI^= hU*au/bܬv7'UҪ*eJgXbsH;dߣ%Pt"wh^)ehHD18jDMˏ:bs[D5$"ZظkaXIX?P еB&tKy@ }mSTCunL g5NW63}WZ6udM"]\&[N}#Gn,Өϣp]ؗEʝ|) 1}>Ob>FDNPϋ1>|5uHQg݈6'c#H'ulL>lgsbOoFK<%i3xӱ?4w'Dma|un _tg=EJs1:kβR;{8t[`)E[D(3iI<-ɳ<~c8}g4x!q5~lwAicRļYKMz=Z̀cYW豉>AD֜udӿ<.T.]xMۡnMϋU~4t4P:kM L~z z޶loWQPjÒݢDj?pbWlx}6ǍSm:T}zZm8qv+ r ĺ5>qf"3jjfvSS::ԈYDuteGs7"Ij=RiKZ$_9m q4#M #aX˭|bq1#+sg4Wӄ.5Mң՘3/ ʙ}Z3ĄUD'`: oY3.֠&'-X5(sILvYmG΄ހfEE2yp!fMj:XR)"[Ep =~e!H)ua b"wPDtnT-O~7~D(zVY;‰@,1\ܘ8Έ6>N &,Xs#? \qKxxs ȍe{o[0/ڏDJovP"ٛ,u_'켏zWR\|4ga'n iUD>_'s}`NEonQD;XӲs2`E\8iP.c3䓓@s]D_{SzL_DDC\L&!f#+0 sW5pw7r$șG. )C;Erw'zr';@|KM?WHٙ@y7֟1?CD&#cbtb=)SkW|tr_H8]!"N3: jzfhifkKSW,t4D-&]wV wc dS{b&^ԠpmfxDUl`O4sH3 t,m!Z}1:q@j.BoA;θ`T4ѱgv/np'%'K[GrGuYH@{7=5A{jNΩ浹#[s]h?U@t6p|Gi=೨85>bv$rλ5=H]=Ζ>Wj'jbJcXTF]n52|F3C~i=ZcÀgؒg8R&jMkSɬjD 39/F#-/[ѵ7O1.6k83]Ct൮kUdPP^Ye9m$0mp$:'l"W ٫HMwWFԋ%+ݟw ~{LJwoרgao;`05'A|tuc$zڼN_9#0TIgTIhENlf|ط)փFm[2d[`xQITO Q~n_"GnRrgͨ yUqo!k!>o`b:cV[n#*JQ{kW@Y48ꆒ8=8JgJˌ=_ߏUݦԗӌFw3Yɤ"w`ݸQG\;x>QKT}ū/'Q۵mj{|0'M!J20B]C_ 'Q7qaϪ֦Fo iji^*7"B>kAs\ Y,ZU_W!Q2LB+XG-}2EZDmɮ;E0*c2@"MiDH;\s\/ReRűܽ34i3}r\1k0@J_U$*+jZa11oM<%'̎B諾0?37,ٵ`f$yVbX2f Sw>+)UUu?dg9/jD)ɟ,I<č.}{!ꐇI`.Mm0wY1bYE\8:߫nWiʆ4@`Eot-U$3 3E1Qo%5\Y87Q}2\2;#6Q=YDyYgmbP$jXJ.Iw)2v3-ΑH.G_W=$fѼ'.ATєbռͬu4-#uiɵK"Hm9EV]M,nŊxhr⟟) ,(ڬm& R(қnUz'Fr8fA'uȀeG.E~a>T^qb.+XemO]D?xCU%cxNk{Vx+HLhhʎKDth3M@J%c*GAJ^lK PBo6d{&*QDҔjAD̜w{w7z^{̙s򬡯xQS$-*o?;vvԝ.{3̮ (~.#Ksh.\갥%a/1ꚞq|=J[L9_TOo}r_l[܁ZN 'mrDQ'HVt"t9S6and]vb(:YőW9WFsU٩/Cq?(>]q&p*5ӟUɔiXCHczˏ/$GsY GK9j}uz3jcjk逜`t QKYΝﳠe6wԚi&?{w^+(T) JH𾦾fsע E:lΣ{G܉T[zo8)rJ B;6ꙕK+0X)y-6ܜwBTmoQ[:5d~Sʡ;{TBYrI]n=c-7x >0xsܤi3ost5b1rvU;7 2憷Y3lǙ # %Ca+q7w="c=`1e4k2}~۪YHR w*gtraöf')>t@sW1I5n0 j"E LJpnuΎIQd'[>Yg&Pl*=\v9( iFNY˭׿mZub yPonv>9pPLd8Sρ$I0{rk D7c85vT. ?'WVŽ <гD F;( !Ur@dњ^P(ka}XuCO=OyJ{Ҕ,aƆ'_9ϖ=;;yeIނ$XZ; $]'0,%FYj9we{3D'JQw u"@w+MȦrLY6mS,h%&&SK9׿Zs^Sv__[4(#sȹqFs+!k=G[pRWY.?$ Dmۜs +Bgx/dۧB=ҒM>c}6' wѴ"RV wM}sp-u> f[kGgXRr}%=ƭ]s~jy1nXzoko?1bW.d/s,s6PaUDIkUJqF9{:#gD@yQ[+ ~xQu5օ$}55S&Ic9O70?@؃Hr/r}N)aQyUs87Iv }fQYߵ{|1u_:j\k((Lwẕ#QMR.u:٪MtEQ rE>yWUdZ9˽]|ثY?rF]B 23̺lږO7:gʽPY N-0b=zR 1GYcØqwßR::DhqE">}>;ݐS99Wz6*Vk)o9᝺nx jӏGj}"h'JO0)g:QKdw4RikS6I`Nfcr}?FԯZۻ@8Os'_2lYPI8qHR bO9HqlVNcN; ;Xv߯a(7 Bѵ WQHBĎKǚv57׶{m<-2|q`]^[5./.+؄T턃7Ep.3Ӡ/8+Rهz^B E q#& \rǤ4n5EfpSSei@ ӕ8(R.AVg-mbX QTU H _;97qtQt&P=ȅ1 5g|Oۖ$''xړ۸YՈIH QqJ9>ysDgXu#F==Pj@M'=gD"QnVIÎ _(aʒ*Gʒ/G?tU(So+O}9, JQ@;b&`gz;үQӞ#O>;Qd5ld-.c+F-B.@?g~*D環ϴ'v\} a!`yg'n\zuLPJVcٟ+Q!Eԃ $!ۺ7\)Vi3i {q "ǜ(l!6;¦{>SPOyG 1#s08n8{؈O6\Q8WBIҨ:tR O^9be@a%n#l7@ʂs(ۧC}F@Tut"8R:>/kCPF Y3]Et.Î4>d7ڽ9mx;@Q=ja>LW M3$yƪƒEZ,頋! Ai%finC{!:MW٢]ȳ]*%ʜ{ pY U3޲[]#GC,H{j !͎>i֫Aol We/Żë(P zn$يS-CnDZ ܾP37PǐbV<ʺ 2`oTi9-l_C g $8I!C#7-{Z5j'/ₑ>ۯëi(Gڍr!ErWI=>b=mľ"6%Ck 5%ZC _a![^DN{"Z_4ړ̎ oyE#yZ:&J~?99fMhQsoI`,b~](輨ޕkr}nD:>+HgftWCҚa&BE^ &zD MҢ2, 鏺<%g#D,vɇ^]%߼Bq@a%e ua'b $S DnY}(Y=߾Vv-(sVFzAY=y׫bӱy"]e^H!nY?_a]$פUyi*@Xh_fuv[QIBl2YW@s)C J"k6jOh_O_KFK}JFw>:a `*x<$vJ%z<k+W=<;ysTn&!:ۃONW733̹?Wz&e:Ho[("lfY̙ ו<ڡ<"spƌ8~Uew ~+)mmYNgss ׃">WmDڜgvyfQvJ;AMO]ZUW3/;ҁф1ۑT8b0 S<_dHDu̿>4;g caWY/<"5‘c]ጟ8ղ>LIs* 7ج?#Ԋ16 ? 3j%YS-^c4mnA"\dH4ҜWYD/Ű<0q(RS(SdHQ?YֻE7Lޡ}=*O` )ӵqFqwCO̫1'sCG@wjU#r'tz"wjG_6'Q*_˕H>I+}+Cs7S;#Uԁ){Jb*HU2^>ɂ'5{EuQr""3~ryT G9X77Z?kD/j]|mHqo\uu1/rUKI?BXG*T=q̱[2e]MI:uӎ:mƾ%Ͼ}T-'ՍLR{>q D/WͨhKD|D >c[r4A._RadlYUd-ٌ'^=?Q|{pj uC>L)Ov{5cgXDiy LS%CH9cѦ]S ) : O{3׌[|}6J0Fq3/^4o?H'"8WBI-ˌGǭM*fL :)ݿ4 ($SחxX #X&ĵV*Wed|ulnȞ@wjcȿWͅ7NElfОS6;Dv\FΨ[~-Y~UI\A \FR!Dʻw<>Ӳ:*q/3?!ۧ~3..ZQ/Z1:Ǚ̆2= $W˰^=A tw!o)I}FPNFwO~iaEt6 z؋;U,2#0P!|DopzL-F-g/,A5 ?=bo_ޭED=SeK{ obk zP?nuFT{+dq2-GH]g3T$Ny923:{Vaw 4ՙMZ+2)WLU"dBZ JvqC>ov:էAr}zj!V۫V?pbje+8dxx6zvl~Bɻhx;>6̉زդeTз R<E++ NFRU_,L+,"#OF~'FԒVcj݌^Z6vEްtF]fBo8q(8,9K ib_7eBd!DQ~1›IԹeU(ܑd z(([hf$}~0\u-"^GRZ~QҎKV֋.جүWSHB9øx-%}I+,)'[֭4LW/zu`䳢M{FX4d v)V5ȑVVV+GÐ6ӏٸ vȩb&I)+Ͳr:AU=K iPu9Nr䕑yeǺeI!{%ū\!a|'>X?0h'8<W/D&!˖.2|j*aƁ:M?yFѺɑ^0 D=gqCt*3I89{"0GMNjsyQ=PspȔ?ECuq՘=mXiT{۞Pa{ rzB%n[ 5IH,1 oDm\HXu"'j ORniyM[9͒?_^0tzB [b=L{C]o6cvlb)mA/u0%1BI7hp3 2[N+d4)M~2$4XcʟiQk,WБc7BF6~>4SBbcgE݊O-mlD{I> n"\~Bw&և61b}G19)'I-hys2coEs1XW[2FG Ћ 5fҬ{~>< ,EѮة^U*,#4jSN!%ˑ=#7KuMZExٗd^e^t5Iem\2ꓽI_ً4s[]>_+a;!%쩴?7q}YQeNl^)^aUOyoݕ >4߅t.JPR3w#\4&LOEP2Y`m6|Q닡P+s6_J#:נQCz|?N)h wُDQL-{[nѹףbyz4|js[ iqOհ[Mir>ƻ7 }CL&#?ky'MArg۪ !iƌM3D/9eJ}v ^]sö-Fymud^ݼS夠‘zW[>gN%@R7k`uVjb3<х(R}\: -rgveg*$vܰRo C HLgZB $6|6"BtOO[<Nj B:A @{Ρ 0A?tz{(f>2':zqh/ +O$^lRrZGm8|! |ůR;Xo"I< ꫠ]ٝitvnb brgfMmhB#h;t},񹎖p\Etk3u RCgQfٽ˙[jez_l(I*yxZS^xUq!l؞,dGù-%S-^mѲuΝUoO06**R,Z}n߁MfڬBss.cSnQV쇈:+sʹ_Ǭ}v"rvj)a+tlx+ K\=[]ʩScS# O&d>.`. &ONlog'3h=#6OU 14~М:m 9s]T\YĔmW?>Zvڝ2|;n,@ O9ժ*;CrdOF`Х7v’+4ϣ>.Q/Fr[|_ '@nZdI^!MsQ:OYN~SW! !'yiy,ф!Cʜ}EUDZ% |C(kӉU2ݯܪ:o9ְkTsY!n+d=:*9>d^4IujZ|j 0.Y_n(4/l؁ f! #|.3sAl',a_$lzn-$B^n2PۘmM?S uBSiOTj^(P$55bkwtCՖNF*gBE?mr#t0zqMco} Ր+뫳r#9 bc4##št$F+PNxB9>ʧW,H,77ɣ,Nú˸)zmhX ݗ +qk2~M:Uqʷ.UB#NfvݮLqo0Ȏc7yí2Gr<BSZN*yg7qJ?^~)(.lM{ͱqLԉk۳x~u.{YU":wyqyՒ%|nS7IN]͘CZCRliLt޼81o븹`qDdR~=Uv(SRAT@pNk|5D+_V ݇܁<p*!UaxEs=Vuv1;CY՞_cW:9iVa$}?V>p7cഋGL[gWJ/=s*1e bH[o/'WKW+W*`ҩzj}\^"=o{J/5zr^O&qMZҚx|.Ӈ/$$7_=o\˘wB(ޤƣt;ldTX=yoSGiW`:Wb5w9%яdaӃ?}z=mjD iԲ߽uB==yφs$=i!o*zBIܧp SGlٰ>y]˟l7=yV֕ H$ӏ77Ɯ+wM=1DL\oBI{?N uu$s*9Kf<]e"nءF[?;էͱ>c ^?>i j+vn$Q*~Uu(;&:'`mQe51癭NF/e5QJ5D7M2DVz4;JMqb0E+HBmrEjI_RE&M>gp/a[5cPB/\"ڌQψ8wiNiY'ov?2CL,d3"!Y e+/<{GmBk[I٭R{&w|m";}Op &Mrp #ٔP$>"hY0^*Ȧ"*tO/6uoNޕY>I_dž;h*o蒰~}pkt1%p eH}T>9`qsOػg<[c*tn$m;%Y:䏭uI-߸nuࣜE* e篖?kI~hAD0%E%ζO$ؘTvz"#QiQGHHԇLZå{ԄW1OSɗu?8Ծ$\<\ J+l6o *I OoOu8\˸AeIvȘ%Dg(M$^n؃J,Fm'!: ~\W\IfQ>\#jM%}# Ӫz8st$Io#v";apZnbiG;yhR3t48;U♓I ZOX1혂 p'R0rHq{)o+f^×cgHRpڅo7 Ó'p962|H37#힅sJb]I6[UD6uqˉYRz!+G ! |ߤW&$U {~ l['Ct>} Izq>/݁eN> p޹~jS%ޫp#nɗUNɳu$^R02hx0x`Jl0LNdʏSE5Q[LVDpJs$jþ湓S0Yե >~3Nq C"bRZ\3Hɮ⳥H'eKGby#?3s3W?H ={uoYO$ɩMXFq7῿=iw:Ns*j|<ͳ%NRwG&F|'xmGiV$wOSsƉ^~E=ҍ2h+x^ٽCW#ʳǸw:wN\2GO3,f:#M=}%9VP (3WL脩0G:ğ3ts{B{H a6'= gi$>7|N)}GYۈ9ҙD@%321ݢ~HrpR4=>i%(Yu}& ܮ΋D[]aE<Өiuz7\*fa<\4&E&2UsiYe5N C'3Ba/d^+%1F@ȕq/QmZֱj$\_2EIG**pN pIn\FN^㝱,.{yCZר.QCFt̤#zX=J$1@ [a8jN&gDdα=d._ u3㶽&9O y<4Q_y2INIX9qHP e$M*D7è!z+˧lOÞzZL_)F ӕKlr:MCSnh%P\SI7|V| ZҬ1Z՞~:K,H /E7uw\\_>d^<%{XfD o^ld^zyzu->uOQ{Br?a=yX<["R/sONxCߧGL/M-LGq()2_>$uOHU%qV,W7&_hkۖ$4#u/ {\v)%m'+N n'c&F_a*0> 'c9"Jy<ߞO߶}SZU"7{b>;*;#apAԕ\ cW\ ?W-UȴYtp$l\nݤ_,*D.]=I +ǔWxX9Pide\DB4}]0 ۷ uQ:XZ)aӍٔK7f8 ‘lAE2#3.E>.<.@fF"G'2tmrvGڮn{wo-MS\SAg|L(4Mz>K 0kdj~ӑҋTK9&1ժ܎wI{xcp,v+ډ53D6WǙ0{*40Ѫ/?:02VU*Yd&$4|Zc OZģ7\ YA0!|`~CT(_ ^LkڥTŚW8+Or,U,z{4fQEPґm.&c'Amn =c1b yGMɳ&\mG6?-$#͹ /.ޯ+cx ƍ̾s ~nSgs[ غ)y?AZ7J.8lә Ɉγ,L5iLٺ(]ܤǀ6 ˬk1}!"!vg,-rZmUq*VZlu0-zs-Q=>k1yLVNh![w#B&d+=sZ쫎?!=7+[0Ժd?0c*~~P$hB@ՑMv7h5hϨ+)V5_9R<. "tZWIܸc?;a}Hh9NyU֟SOVuUa ?>ׯ"ՙSQv`R*a6\\ݼUs ʟ>~bS#wM>ـ JO˪+S2nvɪ9Y4 " 鐳Y9?ƺ-;ZfW5ٙA38po$a{g;xj D^_G*NC[ΖX{ޭ1޺SJ</,T6?fJOX A7Vlx:>n!űBh>cUKƛ7A䕂}fa wԕ8Z~r6#~8fUj4r\ӷ3b."Wk$v+Ul\bx)#^:?]7HԀƸO,S|?f@)sji޻ؠ_| MO)Tq=ZDcsH= I \DeΫiQpi&ӎ2uQ571vT5mu1ʢ}ATP:HY\[Q(Vv&gH9S;tA݈;e bҔĤߏ.[Qf6f03cCtև+fN{U%'oY)(i'yWgy&sa@y^dƒCmxJs8;#3xߥ384uᱦH7Mi E;}1m.֔$5=#1xCgK诬[;IE.90w.N3%eyG{WNNK=C:-2{&ElԕxNI.|5Қ!9X,Xkc [Ԛ^JN)l+9ub:AtfkZ-_pb_-|7pZKX a[u,tLea 9EVY~8ejVIVpu5Wy w{.'f^h$睷)F"G%/xwr3?0;ڬ>3. y5?Ev>\{v[D[I"u#<^;!XaZ%2U_7@Feߜvs ;h}e_z0a yIgn-ׯՃKKaDz SMcQ_{bjT75ӽ(jiFT WaZrg͡syYKl>iI!#)&-{BFj(E_K=W_LZkw6;Ƶ I=xgn"C^ӔNz+j>칬=zӁS\M<%̩ٵ&݆שVO%+ d]љ Uu[UWɃ )e=bןVl+pŰ "XS!vwo.WuUz ڷ#wDNoۻ:hӻ9; MӰd'w/cOQ﯒4vLCVgayxSQDRbsM̔\`_9D 0RRP&\Zt=bJ-z= Z3*6i2߉1 ΛL ŗS~ɪW}yo_Q8Ô}}cXaK ~C!C*XDߍ׬|Tfx.FQsyۣ9Χ8bÛ<ۇds^lsheHK}ݛ:c{:_OJם 䍤s ǎ\ЩdUP5K[mӎWBT\<[J@ |Nivv]uuOr< vK|Dֱ: S r"+),)Xv9b ߶DʏkJ cjoY]HV܅J,Aww^CS/63> Q>x8,q~Ee_8hqbz4}+c-cI\[ډ|XuRT15 \;R{>d9el3:1<1c]8/Si;s 3Gfqwߘ8c9Ӹw̉/[*K<{.MƘ'53Da A(q*o^ހM@ÖBx8mα?z&InB3b4omr!{Y^fɹU6Feo{#?ޞ$ۋ,6J `BRvqT1*|48NIhAfT}O1so b}Wv< U)xìIsMń\3^ L+WgVw:)D犌"IUǢ%'Id4C^fYb<Z~QJ] 8~9nVxڍwCu~1 &9qgwŹЄy.уIد@w}Wm<Ҝ :9C5%XMzUlu#R|(WLEz;xx0xA0g{aE8QT>0>Ըn ˢ %BE5iyh[cBXF%tL2T(xQy7r 2~uuӋj'~ƫ_hgS԰k_mSW+FkcJ\:eBSE(?&gvkQM98U2&J!ؕV,m\A|eDU LN-={q81|nAc'Y~GFr@ɱbFݥS}~&דT\P-_2>vio/np5WGt>km$زElE\Xr7t'hYx.t?ʺ}|[͝Q$,ǃźD7f{D.|p쟧 وeSXʉ+x3B ӄW8Z}rq x̩QޅGYu0`PD5 09bӲ_{q/jYtyӧy:l"eOn. >/b t^Y`TMc)A GoHBCuv-c'ZY##H%ɔᗧ=x]q<.&Rr+*hKyWWɷMl_} 4yhFZ;w;KepQ͆v܈5Q!AʻRa[ )QMDWQ-_z*Z 0e@<#,怯f@xs0+oAwDw n Ʌ_BdS$ћ?.'}D9׼sI^煓;m~d;ͻAV*YhTDiHs{lQ~uDD,f {,rLJ)ُ[ |IxKW?§? C%<Ùf~z{ ElbHPGg["KUnh&wjeU k/Vz9X6^2O xZ$R,UU+| iQޣ#k9L<=bNo8`q/cO77 #c H 'ٚǥK5unI}B8C R< Kz 5~g=5K'J]B;rSZ-[\'L6|2 ˇ:3ͧ~IPbIR R!ӬÈ*TtkArKٯ|I5$N}և}@3{3T 8YGYTSpjaԫS.R Bx,UdUR}vGܻGc\Ak3g)cAw|,UPC%x&'i.mqt$ُn*EUȞIw@pl{G63zǸ?2]ԑ""`mEɄiǡ.3"S]ߗ) օN~g΅eLJz쎤Qg;r&UMHas&o<:ڜUKks)*-@|E>|g]wMO;"fq4ͺzй$QEm_DJNteHAd?b؈ݢ'3Qp6QMU6".:Ӭ|.GȩcP:2gx荺9O w/sz-D V+%:Ő}̀hǝ_B}U(~=Fh\ 5u 3#n;rjDĔ =m3^V{D'0{?^e}#'9 nTrqbfco[ua#%Ú??'!`}`Pc HDKǵtJz81˫R)\DՅt1&DĨWAGOp .wvvq)øw`Jz-յj\\,7P(gZ0iԴ%YI2$nkeJEuNf~3L[cO =>bzr1'LWpFݞs什iB Ɲk_GؔPq3D \5F](%?L~^U p>HY>)&bQrkT,{U7q\N>+)c's; uG{'6aym"]x_s䃮UxTmt|;!=Z/q'rVw~br]y~~& } zH,RF.Fx?f߸hp"=?z OJxQSvn_[E9WCIՌzE[\|OLQ~8ګawz!WeBdJi/d[]?To"8y)?zT=Q Ub%^#шNx!ʦ>g{O DZ\asT\F]t(@d_**;t~[ : GY^P[8l=bu,E,_ݐ/Vͣ XWFUP1 7Eu~dVH@R,:YxD=Idzi(m{|<1fWĜ2o>#|ɸ+'rNbmwrLD  Fq;՗ :F ?- 09L3:xܗ Ұr>JE׈7|:b#M]֢ztޙћCi1e$G5[Ycs\*ES:}2Ub؅V t?wDNk;RPbUEtqn)uqCךkL+Lb">׭?4GtݨTpODJr~tT1M/QM腩={Ʃmpl9Q+بP:-TJ5`T&]%DpyB**l#.jk4a;'W,#nc_'ܫ;6L̿oy8DI/- ;y&Y?NkM`4&HW̷njEN5Sٱ_۵N,l'\&^!a10/xdAQZ2Q~YJ4v$w}3:zy^SuQzuQbg7@XonUxVd= ֩Z]Hy\Ej2ZH(Vj=`;|(]1NOZ=P Sc-) ؝)kOUfsʔUF@x6K4q9M0 a}Z^fG{Z7J%r$wd^z,u˖?W3\Benoٕf;0KHll!㼉u}c LTNZʌ$} ?qn36xUJ`I6JtRM䆤4,tzeך_ё{cs:s?OՆ+HQ\a~1mJT&sN*8wcy֧Ho20Z*f\8rOnWɋ̖hVȪ''uVN*w0^+B:B:ۏޭ̷*ۉ9˳~%j~, LߧU6ݍ f]kN*o̗_]4|t2s M=[RFqV-n"_\$gH!2"z}w%S50c( gC\LzPQW)=01r@(r:=K9AoWgpצb 4>wVӅGjqKFP1E}\5!:8yew'W%3V|Ů}riފ]a=Ey/2!#oG>FΕp㸵bcƯyΡ#Ԡ[ag\I*>aJꘓ4s /!W{1G=9Jtvk6=iΨd #avFODFe]E6;֒uE矒@jx. ;1;GJ^!ST]_ugU`M^ 4sax$k;HƌI+]4ȩ*$ǥn8 $wl~{q+d9f.W.њ/(`+5{NA"3{Rc+n|U$AO`Dz=|i<lg幤5k? +H>4% ӂj)AuT>ardW8<͸S!:-' ϧ.Dٻk#4D8 KhlzU.YYYĠuIk۶|r(sE_:Ezd7 ( {ۖlH wDz)t" iA;sgwfK?Ivgn9}}t([)ݾ>):ؑXDK܅d/~Ji>5'fxI\F)%gQ~Xfdc<.|OBX[Z!ħx5Zx]9 ܩk,~X[;ë aK7fl9VzFx!6}OF5ibm9o)ǟ WuERHo $ػl &kGs&!"ru) ۈj=sv%ԖSSZ 6R /H\XG£&&YqC/{~P+tB(;8R/̬]}#NׁHRԧylϕSOhy S:~HF@pw \)fnWȉ'={ǜ3Zl$WsG]utv~3u{;M~4A(] ͑Jr )[ƽX^HgȞ}p4;[?c$اޔSΪu[N t~oeT!4/Ͻe}nԮ7w:p7H<NfU##tt|xPY"9*#-BwSy=jOkxƃs[&,n}(^֕T[Y;fr Xϸ^}9kԢpaԭ Jqkވ·/"h] Ç\fw݉=b/ˑћU'ȧb1ZEe9F{t}a;>+J8ϲDƳżG{efkoP( HqU q40wkm$E9SD|)t[zqA-{\C۾؀cYŸ4yK5Ǝ?y*?j@ HwjhM›Pߔ2`*,(xf)Ixֈ>%l)*pt#j],P()dU9<^P=>un*}CkޑavK@lG}JkR!ZQmCδYvP_Z{% 2r{puDU_򄈦[}ܙ1nsd¾JR5}E G}ʄ҃k}]u)EۧxN%'&ī8޲|8smkn-Zqy^bl@/fg]{7: :o[>6Q2#2][ȓ!gtmBݟdIXm#掂oyٱ͐Q,cu,U#u;ׅ'n[CjUSC0ϖ-R6'!~V:یMK?맴ʕt.`mz6ZnAmbk];@ |k%e5r6lAm#o8}^*UNieƟo؏ץ_j4wޜU掐,=snM aӐ;=GMVdzj[eQNZPƾS?ܖ}-r/o@S>Kz/fu-D6[u9_OLĸifGeN fKѵ> -Lnrvw)Yc@9%!kdֆe Ѣ;H_7jВ? *l]ώjh`isr}ٺLzTz>|ֲru8'>678Surm_%|+Vy9(KM[tg8lk ^rM+3qFӎi6m#&n$qij4 N+'eH;UkRo5/XW)A rfDqfoKӧbK[Mѝ9λD$. c!9RBzS6>g]hכWw>eBlα6e<'q|Zu QNʗwQb.Uzt,XHNBt)_}c/͸ q3Oq렬zI߆ PFM7Z! PKlû Eg~Gnyz +WwASb7nfҳgdYނgCgO?u;(氬&߱H Y)i_iUAoRo+/|0Ө7y{.LI8_k!VgyLMANMc}n؝fm?ˆcL[L[I buF!ٗ<-CWRZV!ɿو@qԑv6Or'+ȶ_„䕺;=TkAu+ om*U="Ǚž͠ɕ?C\w5HȸdLܞKSZ8ѹXwϫ,ED|@RDIPYws^V}QQra݉d u2swW[T7BI#YA+{q(W%wOl`mAauXEIW%ߥJ͝r§EGV]:˵ 2QI`8qG|}w^Gv `Jo%RsO-$Gʰ" 9TǘI$1}rZ?D{(J R?.9|#GUрev榦h+YaCJ1a$a-"5k-f#I"i%7,Vn@?Z{[Z8FY}Y$vyIպ%)˦muǔwAJ)nT6`q^˲ϧy`iӮVKt#wWlץ)y*>SP~\oz-K)W8ɠX穷yE^9tMR_ﺩy(vhn+^0#]:IiͿE <,!vmX}|ESLQ>>m؉pWUBC@e7zʲgFPgihĜM'cNS]?gH ֛^˴m3RZ&Xo?]剼=TJs C' j@ʢ9O@z;;xW|w՟͢[O5tFTyq^<+<{rJP(J/ƫ~YQ3WYZ-[5")PƯr{K+ܚ`#=TyȾv0fgXEhZw?W~?OH Q}yUvßZ)79tL;ԋ?V9Vo޿czHD{+UܱL( P`cE8bZ4*sϺ |2SJX 9ైx2-aYHHj'9y%+ۮ%bH,I\oқ=CcoLh񝷀⫀IV9<DqeL2mVgE rheP UBOvV[*5 _0kv:g +vҷiVsCD''igOՉY_S䊱4 \Jր+z_Kfa7-Y zº?a_?, 2wȞ-ɳgu6Șu.@rloW-. ?Q~b%9/zm^zmw6}U"ﴶ2$n%"&"Sk#u0P15WUR·1K{'nuԠ7#%D`&&gsyӹԢ5M5 5@%0?w ?MG;/X0ͭ "%qKXR޿~+z Faq)b qM;m;~BEeCؽZɺU{w&z; f)7ŞU< pղ@\Ngu>y-mXZ1Nʐn~"xɄOCLᶛYl~Ukgv'wOOMn%\fb'w^w>=Dؾ&G7ʔ;^ sV7g |Bʣ3G* +HV1+t_|crbZf)4kHUKFy俙Hf&L%i"(ӚV_@l}n>sf-XE7:q$pȣe)h{k2e*37W{}\=Mn4-)0Z&.>T&RC}sK&ERϵ \].?5 7 m4On5vg% BSJj=6rn }ݰ Ѿg=;*@Vٞ|SjoPW={{Қ5u9ͽ7Go scRQ[ gg{j;Ow8!N׽~j ?d>p]!c=<~Weѓ5_(9n-7=B`\z̅ҙJZ ]oxK~ļo0=2ZZ+KWEB@X:طdMΆOǴUH'L}9;vBi?E}>ZԼ=WRWֺ↉/#NI+*#.`w*H.|([1G3mitu߹fZ1G3t. Z R?,;A|Gc9T4VO71 HkӳC[<d3=v1s? ҙѰY!ga\ {LvJ>FE9Ild: =abMVr3/~K?P'j}1@Agnt"|ns, 4Z8MJ Lgd:zPOY*)l:LpXz)|G;V{#"{"$%E|=w ޲Ɠ)aVI&V _ipUU BcnSƿieo-جbnOnZ{EށL* nr8yZ[/k+25c̓}FN+H'W)oZx6OY=;ň^',X0Mq섶iUHdL~Sijk&gWg2ްfLuY$F+|؀1{ K;˱Lh8ThMߖNZ״,5i,̋ޚ` l-7,s7e1APl&֔i[3` S/Ssw z=ަt9I3.l!5&o }kc? A%¼+XW zС+#䐦%OgxYB ]V[*3:&m>\P8'8TTqm`!6I_E4@/urg/[;Ln4"H\Ny4[tZ9 8+~J"YǼ-ANNPJ5}\pmfז!-2s1{< kd>S=̈=Ef qu*zM" ĕjYxg)!{B{/$u[qgJԚ[baojBd#:3*Vܹ9h9)&sl 2.\ M3ٛ]!:YTB#c1*5mur1dMHtq?kFC5ZVg䛨s7ϺdסڕѮ!\P<|2Xp^Yя+ fP[W/5>xU&NDdp[ݭ(at ̢4};A7c}x_ذ=4wrӕ}e"kpc֟Z cnƱ\/T'5޲T uuR$&p +|h yj: OMRUQM")P7Sx}`ln.x$eRw.Mt 2Xi=EҳhSfTҟsփ8nmΛdZBm6ξCGv_l]a3@}ɻWQkpMӤ64ߜ +*Rmt__Xs݈ΒymÙ*MV|v&qG az,$m9o  VoZ+Q[Mqda,D 8#;_N 6]*DWql|Z`NGD5a]2)f6v3g9 60}rTEf/ʅ1JfCy)eDNd4o`P9:fXDyZ}`7 +&'w-7!l$#gTBc|}Q1 ]"ރEI \xo{/"嘻›1-}Lj9ϙ[5+H&fDl[$JYWFN>4] KsyjSeLۤ{s8I 5!Ku&mASpvcΡg6@JÕJ^XZGS}jV>IW5 dqABU)QXߋC/-ns 8@zOnU+KN|AoC>Cޟźä!Y_v=Q=(~TAt1J"6FKl,8tCN:c~eE񫚨BN?My|Td2ol2Gi1II%@kJE_&Ћ%gaCv8!Y˸")=|~+>tu=\ٍ̈Q;VqBNÕm+yvJ_ Ig${W-qEΠz澈ol 6 \9fDHIcժψNW?9Ioiv}y/Qk5 YiM;hsE(w6b3 ¦vc|zN{Z WkΫ]٘k"Ms+{t8$xqs̒VOV.i3q'ZLM3He8$^!_IF Ohtn,{̲DI_[Γmǜt{^Ѥ ?>hشe?D':Z&lN[Q^Lیؒ,RhCx0uX9"֤𢺩*":5 Bۑ7@nvO7w*6LjdVQ kQ 3K\5$$5EՏS,DQI-=}@6H 6:z <l`|R[aS?Fl^S(O/b,DQs:W?"#)F{O$ 7(g;F-YI'~Wߣ$ٵRܣ]Nm7శ\gT =C %'eqI]9~`5dGvgMeRU;N,ʏNI3(xd`K$&c^מ0**~06 5O#N~D̴i{AD*b^}wk_y|uD{򨁇XN}9Ld^R~R&M_$? WtrIkQ^Y_^z8?:XS6}=6ҊuJ<;C;"ׅy rX ݥ7b(Oksy(Z狜>V?ȍ`)eRn/x7 = ю:nw%(?)QUi\ձ!I9D24=`nWY!wM<^δ~iYl ﲦw,X+ktxk{NB W8{z3r% ~nq3V_f?4Wx~},2Ix/]*p~᩾w +Sߵ ӳ0!rP8O>~<qFLZ H,~WƏ\RR1ӂ.Nq'BzT6r!Ú "4Br^gVXٲ2Jitߏn %o%dFĩte:=XhP%NXV*$O}/Nv,]E1l- ]/YkIΞמSYvzHwd9[R;jeTDx/ZLm}>eh$蹈:* 9ImDZg&FFzYf*j~ӹd?RsuĐ&$b:MbEzvyeA'vR7Ҩ^5ʶؐl^+B-gxbĊxbIJVL@&INah#>׏T-{R2D +c"sbe,FOo?So+D*Uɹ~nJfڠ V:z$N,6 ʾ/Ч`мƭ_Bb7h+u~2ϨcgU 6d8T7u䪿R$ܽ@y$5hʖ΀ V"Nuhia$#w oBP7%ܸUl+Mpis?k54n1F{'5{q\-q~zlRhC#wN^ٟfmgUyՏ&]9/((YC1VNƟ8ªЏ 85bS䬵dܟ۲75LUW>@J,#)LGt^2=tV*m~lonQbq;3ΔTuv<0b=~*LNv.^ʢ:qO&1 seTbͫ'!78rM qZ㚾0ΦRܻ5Gn]>G$״uc1]VI "IǬA \~h(w$\`Ț&; Q+!~YJa)a_~kGT]PKꛜׄW[HTQ82vZ'7va\[X#Ɉ]| i_@1 I#?o9$H}{ʺoŜl{y٥f֣Pl9%owH:Waͪ+]{jUɋ/sUNÜ uDV館U)˄ pبBT=I#ȬE> e2c{GlI%d`gKR/ʿ7P03"A#Lz4Mi4)LKx l_|^|$ݳ|{2݅Ƿ#"lm{n|_-fGp1ҪڙNvkf؀U-G+۵Uq+&tgxVӈ+|2ށ-u0 =Đ837$:ZF$RW_Qn9´7}cLp[z`(oHѝ^%9?7?&4~T)yh!ܥbc{sg詏0!jeUVQ֋vOF"g =)[yw =)u#/Y-|B2",RbnݚcTzމ]/|fc[:F+?^^ m_U9d^VqZrW,;r#w%7]{ Ï*,C+/H]st?xPU`l">}0,fԥ˥ щj1}l[;PEBRE?uNgY{T{9_܍hyzD;z ^N q 9-ɭ*a2rJ( JhRjˍ>\K?s& z+IGfVRSZYħX$m idQ=Eo4B⭗6z]+ug ໬#UaowQ;Y2%*mRo2h\rD47I_sߑ[ӼTD5/s]v$b l^j(>Tq9NKTݧ`F>I@A8P=|8U8 XEY+LܛS1?:m5 % Q@=sO禑H%>` rT)'E`sgoldGr;=_iJ O1ğЋ{WHʹrcw􂺪^uR|'1y?,'-|>SnYΖ<.Sn3Iq+M$"oC+ G3(auN]'{頓F#؏ XhWE^L5".<1mVi*$kA~[+Vbh51&2Cˢ'k3 V |\1w> T0F=иfϮd-QQ/P_QHuQo$㻕T`_Sԥ0'ru*:.6IW٪1}NH^i&uU}c+rbzoBp+N*Pؚµ:k]y@.P±4AC9>S[,`O.ӣ Q}הd\& ӆ[ -~~!S 1<4bYO_J̩uf?`c}qϩ/Ƚ|,oCV6DXXRWώ%^ۂ퐆pM2M!7I߄hNWxD5S>q] Fh%8v#ʋEN<9jT|.ߩr%l)=';؂Kget6pcOQy̫Y㛡69R=ѰQIg^?r6CUXg\.3gĦ0RrٱǪ,0*+BL %w' ;P"Q@1|DDأu?| 0WJG2ƬU,$!t|p|Uvyn7Ef{gKD<\sbw)61YJ'x OΚ Xg u1z+vʼ^" < $v1ivӷEL{>JǮJ UTMK#Z8LBxUuC5_3:淼[yHm*fgl"dbj{ b3)JL>}i0YέΊ۳q:ͫZ1m^ nF荝e7= ,*ցp9G|ׇ×Q-~~<:ڈը"Χ4VJ|ȫ`P>PQ)wSB )?f+2D'vsǦ~*BJ\!훵E.[Щt&C)<N؞W?R =xC_1z(Q*x%3NZ_aO싏UsP!:r*_'36vُ|Zdu4 (2Dۺv8"V|^ I5Ep @<[YXS*7]7s+k6j\*d~4^4QND{G,$'^+J|*W+.FWA8ܓ !:{J)2t>[&A8RD3,Wxz]" Ε CI? Rʽs#ApalE>.0^QlǽY>$j7c{<}zduL"MOwMzrW̋JL +wws\Cꜝiߏ#dP1L_PD&b@sB1j nS@\raP ˇēPd>L4~0!s9=i1@ \0-U@FVVnZ̯kH=w!?-C;5Z{䁺MFki @Ew m՘ .~=NEϨH>e)HţC9Pc'vWP9 f-MlW̆߇}r@q_?.fE? q /]WO,pH/CŇr~GփL Ř)9gkAVͰ c|4@Q28*=D\o9o&n&}F,un<{7N+َ{UEhhA \^-{ΨrIH%9c1+ ^.#/7%N1=+r(עW,lb=N+#HӚY]TbOj~{ecϡyqٰcpkK`!;Ȳ hIEHlA9/j| @ijnԦVSTFh'T>XdT¨9]ӀV؍ӷO?=SoP"k 0 F=)B<*uƣkGwݹ1%jd5pw=7XgqmvְjgjLrs9dLFwUvHYX~6e=U=bzn$64q̌հuEPqq9Y3D+kU gd'O. oљJ,AvƤ7: +&2Zl#w9JbEokEF:T 7ht&9?{2fd\7U|,Sf``)G/:P {j[{1'y=$l9OܶTX?(üMG:4V5Yh@ ٬asGl'¢THT$\b PբGPĺZNК䚣vik//GrcjhH)Ol gHjmR@\> ^SCมHŅN9;>ooC쭚1QNtQ(>e|=ȩS#D*ܩΖOۅGPE#D_\t&b .#(gc oN?}D9WzP<NktPb5.wVS*P4:Q3<5G^:@<~bcC6} s}Ys[ADTCJGO9&Q:>_W'HL"Kᙕ"sMmje?]tC ~n nl.aK4!O꯬Tعz1~ J#DQR:_5lyLs#:owj`sfTYwsftJ OM0\\LWtd*K:KѤ}2}t=#N?l0ѮhzJtxg8Nt魧:Y|$;ܳf9 .[ܲtqDR|[XK!~"[5s,'˒ax\w @zI]Tx2y5Dt>=j7<, ]:'}Կ!pSN>nW W;f9&Ţ>3X-DR Tric#g,"]}G``=7E]:b!I }20^mx{JIwFĴɼ#+Yd~[ZQ/v11!lyru[R:Zo %yRhךxVIw+2{ G-ܱوu, W+|_ vr&Q?ZgtOQ ؐ،΋|S[DgnP*l>.DzjšZ=zo.o}'psV02Ǝw(݇[oEV R(>37U*);ZoV_|;ݚɟLZÐcBu (xMS6)¿m<ٮwq u9;JF#^W]? Q|_sPO|\750)Ո6Ww6pEi?&!ß0{:傈EG8/k;j곮- ή䯙b8X,b'F߲MmUQA?3鬻U<9iGz8G>R|1{O>ȣz9qd QJvYeDOb~@$U$6$]ⲈȻݞvWZ9T("W.>M{hN 9#șʾ=sųij pP58gP fütUOׅX33դo JUxk]-r18?|Yxʤ:,fv⺛MHj_V1 ~Ef&v4*!zF$R[y>hו NtϦ<]`M?"Rn0$ qY|?nH=MGt֖7pѕ# ,gOYen},4Y_"!E7zJ떊gu\+FJcXAܳG\RFBt-`{J{C'"ZF7JDjoj ¿'(Ϫꓗ Xd>(Oc89uhS>U{x =H #Cǥ 鐎46jalr=\]k[]b񚤎 Бs#FEہ,ŚI1b1ځS"c|ցY@Ly!#>, ϝod;t!qޝ[ #|PlQ$ d~k^g&Tg#zY ͺ-IDw"qJ1u:B.ǰŁ}gV?w&Wg <1g<۟BWAҢq{U@-xzXc=B +qF ˉ 8L;^j܋gE>dy!Mp"s+BJv;,Ԧf[h$1!uӈ%iw^f,$a";^ťZQU6_ԹJbnFL;aF{41n)a 7l!0Vj b6|õ%Ԃ͋j>bDf9wJyM$F>cۚw 誯 b1tGES h:_gKҌfY¿MtFضLj%<RIg/")#gyݿE32N)0:?8 y?d"Z*W_I^4D2Jy6T}. 1+^7(.:`XCAy@+E^Y5 j,NY$l.8Ŗ]"",ΡNXa#i*Xqyҝ-ypW/xOixٱ~:΂ 5qYzGw +ď-;[U<)Y8$-4QjCr}N*Rv9/_ ~sܸuSsWr)>VۆS6 ʙ-c&{RUyeßwpҊ $iDJL_Ά' yFu:P>LFX[{nD]Wv[:(DZuB%SdKۖ4{2Z Om9[ Ƒaxwa{|Q{c ^.&?Ӣ->#7Gb7÷5ayk8GN-p4\i.%lV1~Ld?Uz"W s/)Ґ빗+?#Nq;^o>ОדOs:Si"9k|7Zf)K]( CcPgЇuFFg92j|8|nۋ,uQwT]Յys`϶ 1{|C!qk!UX>6gBވMR\EI}y?TLjt dóxަc_Dtx]?:*:hs"b [6 6 |ּ2EE znK^,wW,)p*_Ew\'wJ&w8WՈt8Hc'9.us7|~fӵ0?&K{Rw_ 3~!u5J@G`~ܛZdVV_v浙3|; ǙF^< ""|/ٱ]N8ՔgIdPqqn7|t=9|;xN<盧pHI4i k]jY[2gOえN*||6?{hJuQ? 7{4GLev SA:D lfXU,Ӓ'1g= JrX5 }lOa Z{ݲ5NT*RUϱ.W+63-S)%~r=p)`t#b֢U{ ]s@f}Q5Dֆca9qZfpM',9_N.:ú+XR^R}7eW-ݤpcY>VΦ3D,>RU ,b6!aYu#epstb6B a{{_$m5HßB&1?4`d>SqgO_djX>E$'٫H^X \Ӌ؊gS! y>@2yJ]9&Bq=d؛vß)ODyOdkw_d7%,d1WMC!j}X5ͦ<%ͪQSupzwOUXS C%H|_> ?kH$iD " F%e՜UWyd k[kZxrn[nO'Y% lw؃6D4 )!ɼW.yg_n*uYi .Xa^2[|o,?פFBF]!5 ֊fVWyDJJ:ztϧߚtt)\x$j0L#xo]*YjYdoa m?6Nkr]\kQ~ ~B ;[a=i;Vf_U%^ P xUC@7֑VbQc8|6tqmopCr>k}Љ4(j|[GDG;gb2۫u 5^K8 W&WlbhKR 5ӗA[1~}nXFVLhFկ򌓅7]>`aEd2KL,ZJmXԯ"HUM ٖU%uVwWYY֟1ud3=Ciy$kN|JC 4p& 52NP/h՛CWB[=MxJ,X~1V3]b>!՚3ij3ZVZ_c)l6VjXo$`L$~&oݕ Şv$DAOQSqWc2=ùy΄ܻS>Qn~ TGHMFF/Q[ȥV%dTy>n"vPx5n5S[(B^rnẨCiMiA}!o,bB?ϳ7Dnԅ&u'Y$CT@*1yUR!ER.*߆Pav Q5dsA߯lZJPFF YQ'Ulw޹zx4!kB*5r#paYjT=L:>~N 1^Q!rh#JN{饪X-fͱmO'#2~`ܝtom6CD\9dȣ_M|g ]Ŏw(کljᬇrȗjIzq?S!ͯ.g$Nt]/J+t i~nbN !~HiB"K:]96q>0@`D'Yz$XH|^˽a,b),Z[iBT]EKT\X~&'p{յ *ƣ$R=:9ĦӸ^.ɗڒ/Son`?6?rAaDƳ׸֎|3ax?,SfpÁQ#2|!b#e[f6`sQO.vj b=Zى2!{}K{ɺ '5˾5f>u_5T iP~|rY\:x_$NC[8?Yw>[h Mq xEr$^\WAt5~;eg~Ħ6ybvng \DyВ2lnHWEw kUӄ]vzK$f3o?wepgh=͙Axp}ǿ*듀ѲE\b'xi˃+}oiF=8A/R~Z#wRՙMࢿ5ED-xn XSyddG)Jlz@eOnZ/bJM@XgV8&(nG?7o S?d6xi/sN7oÔ1z>m*}q QlyRoϼUN)›̺?&C_ԑ}8Lӡ]-Xk#'smDr7ڔU?I&okSW-Tyߴ#C=17ܔֈU ߼gqAus4#Cy] AǞ"`6ab ov{F Qwo2abɴHU@mȺ3ވ폺mF &pҨR#dЃyJ1D38izC#6NCRg(m+Cl;+Zs(E'Nf}+ =yfqOMEb&6ld]-V^ŏCT{R5LSQ\wWyJ.%Vşx XS⥪~ߌ\C1:Q_xr^/PvJXıg·nOmx=?2-.u1^}V%ID/;J -bQ"2F4g?Ⱥ])⁔.?j U%]w wWGFiJƩ=s_~7ufVLR&prh)^$u{ 4N|S%tyOt!7P*gj"zu3~!heXNг UP%743$]$(f zv%b VLr!7V>a2~ÓR >AvҨY &s̢#9^<[?n]:+7NY?]4aV]BxDKϏԼKф+%'ʞoCHd%-Js;)bl 1M0~oW??SR '#~n愋gRԒ;nN_àC [w蕫>;: S;|zС>%{SW:xlDOMLEA ߾/CzL~YSAv^kXr~>Q D&nw\ P`3h٪!?v1FtZ^Y9b4gGQ2q72$ Q^]umA,w=Y==C'p~qwBЄ$! Ꙟݙ>#pLwuիW٣o$zIŮOɤTO|ˆpƥT4=T FZ.4x7-A/+浑ηaߚ7o\%W/C:tN(ʝ9!HU'j!6cSx0_aE#zYr== =Y.<If 5PiBڵ]WTznyURU$i:5\DۤX[#!"U">ro?Ga%p%"{i!TKTstrγapuђdy-]LM5ק5'}Ƚ1C• a<کq෥U״f z%ϥ.)ĪTʃbps7u/Fԭ3q6lPVSD8ESrݺSj}&쒏cѕnPD} !=Bt-y$0- Wi*9c7(|Ӏ*^zU-*z49{SAk g敬ԇ2KԻq5{cuW,?s >uF1=sȑTG9 YOx QMFݝk5`@.ij9)>2gHpE/@87uԵAz{yi?5l ekÌlbR*xf^mt<|KtυMbB|ʈJgUΟ:StM~iՓSxjo[X<I2ŨF_g#bG%s~Q[ _Ώ8OB:tac6!rOjƚ60;ٰT'Oiv3V7ؾha>o:sB˂|[Q.T6߹>^Z75 ;{B5DKbB? .s}:e6+LtzTՏ]Qm;~w.akJ!N`XvxSݪ!_u/T%X1kh*N%5~;g"5%u1çx͈zHc4EYb8F%XLOJ}'keAԠ; Z8u7=+ ?f|\f4peND?'*1ZS!0Ceӥ]TU; Q{ds$Qod+H͖)?3QTТI9~#/F<\A{L 6`uȳb"w\͝^P=9r3#'%qz; XŽ~2gBW&*x۾g!6H},~[T+aӹ 9b,TyOՍȲbw&Lt%1D`vs4Rtfwim`hc~_פ[>R-%L<<-9R> EhꈞN: !_T[Va ߭}UO4g c ^0x*QG6SPٷZN>/!Qekqg d3l#5>󽕽n9SYO\KgLəflDM!O9\"_ڜ._(wx0 q09UƛbGqWn+I!/D^o[C|3 ;lغۛJ&P?k}>?3sEyetBt![qռN{T?)"D\)0O=Q&l;}z``Er[$BD6<ׯ/ui u3]wv;.J rb鑒6b2 m,y?5"s#ڡaήfJ)M̞6tKkr/2D])Sk&WFz}~Ws^`|lHdWU̳ñ˿,% 6]3ϕHqtĴ(f-07qfIWd'XE7I|~[C{ctě-otGԚϤة!x&M̛GT{TqM|"T!*{߯Z<rܯ+PbogC~9i禊sv4a=W5t#[ f$XԴwQ/5|(*g|>v5i97GnCR{W_pքAXv'Ϫ{Z T}.z6f# ,ܘmPϖx!3į>⠏g߱ %bjg?ݫ϶72ŋkkF]>ة.~ Ē5s3k2@xL۽Gj%%_vX'PI^@˩څ{f8%U)bK{uڐ+#:DA$_\opdљtk)wfNJ:UUssd'HB*9VͷzU^6W+V1aۯzBZuGyKYkF7 :~Ed^/UeSȴ^Dz+cV]Vy 3u7Іx^5•+[cuΙ!緮8E ,&t6wSWq,ߥ# -[2>I\a"W)*E#uE<ٚ, =KخIrٚ bU֚oݿM`θ^rn0VY5Qsu~@~3>7l-ڷ5[o g`JѵFYTۄv [N WNWKu:9։KV+(ފNzU ]Dո WP{wauvNJ!|B?p1Dj/0G$s@9睯5,#w!f0;k4~}W:j:RG7S=g6ۯa̰W1ٺ>d#Ȍ?A)Y&\~땗yy\dWӈHxDn!v0Ÿ~9B3Έc{zZk /ޮη'BL9> 1lgRFO"J;Uxg|F\>CϚtuGdjKzU§M#R\wYAD90؇U$KeɔJXI=v( 75}lOroT pRS{|d}X{(ĊMo^CTYC}{It:"G>]S݆FCHzE̶oIc &˜s搮`k ]i"ߜ w E^94t,ۧcż&up]j_=%Z G>5;ώ!Rt1p7 =ʵӈ⹒;{#*5l7 sC'3R턆suICuqDyɜYΨXư)lϭ// Q|1v~كSe*k!_U^< a=޷jni7VՒOI;GOaӴUL[bBMZRbZB Mzڿ-z)bJF0Yw& º- Q-ԫdzI:"qGix~ԪK!ĦF?*:aSjнB5 򟰖?K'ԥ@iqaQG5/g_Rs0Ɔ;i>tv€fP̖U: כ΅D\1g l1Ϯg%rK藒  SzLk^\=?xLeo|FD ~/aǦM*:)Wrs h^a : WoY-/JR :ȿ2MN()e xWBԹT j0,ύ3NR|ۻupwYJ*{lJOu6 s'čj16NF ,&fLЪ3T%+X*D!4|[grRg6:V,dИ3>ݍ=sob Ԫn۶g8{pE5{v%IZ4)kݚ`9VJC|(r'>\}D'ę=hknT 5]}%rr^Tr1Ҕ;gO|o 8P[-D3_wRXᖊםO I3 ٧ ^%_/E"9RJ'a|yqi5|yƥ&[Pb*(Fr21ϻVJ-Kt^-8@B:Rl#HRʴc%*bVm6eۧD_>B#UͰd~N:|L Orm 4%858eמBC/8s%i"ybCE.dLgvkn 6B7'œn6+nx,{TrYϝ!k}mS<0i՟D5ew uZȂ7t"ؔ+:8W`ɟyVlD u"jD+~T!t֌xtW\j:ӡ  z7MdT VĮyH=T ujd$DяH29YC#s҅Ŀ)rOIDӛ _}ӽ=thmsZɾft!Pz%gtT WB9QLYOko_21UpuV2qZ]y§@NUI2XD7gs ;gĭ@To;o(#a͹Y!mi< g#ܷFI04_R~ڵ=LO̽ס'Ϛc~,]W#5*&oq+S?Z8$!v3mWB~pFT6a@7`7H,,ȶsJǻ?wxp!Oɪxʱ>Zk`~Bggb93!9({j3Yb@TW3ۛX1-|^bI'm~Y7Y+:ԕ>xZ'"Tr.e#O 5[]zw4L O۠U#W [ L Dqe-x*o5up>2UohB]{:" Էyg ɾsQ O%xU]Z).\ Sj*xeHVǒnՐ7(|%dBTDWN9 )xf#IAŶ"ttRYUtT7܅7SXDu1)F$m2RGݟv&Q!Ew˲3(RpMDtA@戛&*eqEmَn~3૱Sܴfg Bp52r:.;yw-ܝSQ(df4cgϟgv,t"{nה~Ӹ y:TQ8Mƅ n\Aß@q#Ddc.x1Mp]aL0O-=U$J:Aj5+ZohqUǟ DIX]׈{2Vޑz/ۏ7'o;uekgw89rkAG"iqQ|ݞs-.=Z."9FeպSPL$+U뀰ڌT/:_xt˺̑Aλ<8Ϥ_707pTr@-CouWAUƖ=՚~d.z?ݻS!ʿǚF1!V&Y˭o-K0g5sGRb1Ѭj>~$޺e?Wp=qϯ3bnsXJW~`:Ϥ}cQ>$;*hwjIq|OCV, ^+ N\kRY}RMBtHAT!$/Mݣ #b?";lTˊF_G]YTHiRFjqG3J 1-kzaѓDiz,hfs%՚Ҥ>s)hf#:񆕵rc^zGД}K[O*Jc3Fv0}n{%չׅ $_$(414=+Dury !ΌC#fʱIy6^Q?wԠA=/98݋dF+5*)aJgnoĪjHbׇ J>wxck<A͌ ɶ,5}J b8 %m }8*w$:tCTy[]=ԁCDnVڠgv1pyAS m"vH>N%M1. R͠VYzO!#CNXylo}ɔS4N F.bM7sycICrh||'dM\k1j]CMZ߾;+<=SAcJ:=jeAAD *~9 Jw OvE)ʃ^Ikq1poO16ƟIA$+Y4;#'?ĮLXnAUE" ִdx; *SNG oJIcSc3 n@P*H9dORߠ" ~d, c"1dJ{\ڼ,OpT"WY4롟D+FsZ|nZ;2PGlf_37!WZ\πXaz᪩Btl7ā:6vC;At [e?X(N2x}pT'UU+炸m^/~TE;澲M{?}$KN:ܶMW•_%P$Jfcgvz9.g]RzEnNmq;(nb.b+)hLW>ݤxD5qIk e-ZS!&+솀3x9 ߃cX/CMmUG܇> _;?INڃ:N?Mi"n~;fͫߤQ61Ʀ.ƾ"]Gg[T8̍I8= ' b;`|yќqR!gEIݎ"{ݎ+i_2%~&\bpAjۊ-]X=ȏ,Vp48d#'@Ņ'V8J?)CPgk~&q|"w#:1Q #VS^l͝@ՔHAM9`ft,@2#lGvDM;}W"::h?W;VEۮ6-r\P w4+8xO.ׯ5 |}7O 1SU17vm6QKޛ'3HA0gz62k2??(եs&l^F&=9Td")גLIj~ROxk}kDzj&WacdOZ|L#]vہuƇom5b:|{e 2qxŽۿB5֐L5ʽ⩠ ַӔ~R+Д0=SD6O00mGV h}歳uHSȾPIiZ8 Q  vyme~=CqD[h[2D]i{J|đ&'CEU~'S h͏:j"=gEnU@y =g;%cTAK@utasMṆT_NܛrDN++_1Fz,"CkNHB$2ƭ[TU_( (}qFtvmFI &W=YzQ.mg*qj,rۥeFnG)U@(]\IM+{tKu{\V̽+EL+*S (_Ͻ>ֻ4M'OUVdc>֏^ rw9Rdo_{ S=Ld;9|x*PMXFl.hVo9䛑_ JՃʱ緾w2۶0`Zy.v 4*&xw^b)m +Xu}CN]{z;?t?Wǧfy`jXJ94\ҿu%.!iWI#w} k?;mooE,4v[q" En4"tqWZ'"^1~FX]OFVOmpDg1?'L\iҝD7nT!ֶK{sY*`RmVΔοÈk9 sh_rWp<ؽ78;9?ݍ= ,,rrʬ{{zJҙt{bVϛBq:ϪdW1)%s!c Ѿ'RwevspA#KMۼ܁!gP MY3jY^եgꙈW g1WʓY_?%O9;l:]S 1~>e\9tk7t_.oBrSv_ĢɽFMM:1TW?-V.t.>Y}:?c|s}0 <1'liآ,w-YY\VO#E:!l E%?QR'}+sNj;Q>NHiDQ y%cvp\o^Q8!g06\8'(X9C?4@,bz"aXҵAOd6PlU y/i#kInK+ޥ?yӍ<ծVtq:wt#L/iRs!ӹofe' ^'H-W#oYVH8Q~jC5M5#fruEȑt'cֱ_1g)Eo+s1M~3'DLǑl^ɞ r\K*8T4*ĵtəFyEdi'qrlc srI%%:^_l8 7 8mYoDp#:YLu8dbs~Zr411= ԛztRVDž O /˷:M) gSJgŹAS9k{eB]OzI:\'1dCC]e{MYvp^3oȥpB gh ?By:Ǹ$5z> Rz()+}8yij5a_w lֱD]\Q;1L'xs, +pN{ew-+2`wkP*Ue jkvWRkd7x_2֗q͂'>8uѸPvG!:uѺ#$%-x"aN*rjWgXDLe %ޣe5?Nfv' S?׾l$Ȩq~ܭ~%1'-ъJqjG ETc 5 \9$rRsx=>.ƱѓZW^v 1o^V7z}jR q2ޟ:n2:-?GﱱO-38EN%X,f 8݇Rv'g>͢OPeq` ʑWoܦtpxK~3P+7_DvW8sI.>o)Q5W2;/cH?Jmq;qQ"ۓ*URf93o.k7QǓM疱J~@mN*2֋u ycB= IY1y'I1vbo`%TǺ)`#y>Ǝi^X2щ'<E\]YeHSW(׺S<9T}C]K.PJ !J5G7\(DqHO):0 v1(ZdF=azr-3vVUK N*TSq>cua@tECDuEQ q+Xuo|C䅸Ph'c!.*=JeInźƞZXM-gN&Fǻ,./ac9̓IbXj,Rcl#6+IU $Oz\T#TlQ $G/0\#i?֌&Hh@8|/mdH`?tݕ֢ }^Ư$\eΣjkQ,I@K=*렳iATgh6_O,s)Ϭ4tZ|x>jD9DʖZʾ/λ`'nYn?y4]w=0FaIY!VLsWA9Zw< (ZFc"ޫXɓӯŨWu3RuS-wy+Xw#ԋ qwi= M|oykwݡak>H;8Snw_M-튨V2YgMu]ի%!N9-hѯKcd;`j9Dc;Ϸq9c>ӍWyj^8rLHF'SF|3' M칰;¿úN ?aqʯ&$Z&oy[ɦEjpɧ97}j tsk^[hîj0DI` roѧj_YXʮ*tu4ZyJ q۷IA,ҪK}vo惔#*] Udzr~͓y$]dU +ʷooR5EZ'{9cr?Due6J۬㦁}.5C&}!ѣ}Jܻ"5._<_<SBjjSBVz "膯iH:\zvY- TtA)f﬇):gl^c2لf}5zXL0uړOA<&ݠq9ibC7xj14JxOaNc<4o.GbTD B[}wj΋l f% 5}? ҤjD t+ IqŹam_G/M;Ԅsc9|l>nXv(VZRE(SoDy\{[{ O?Y׼4*'2|8T&,'KtI75VN:^{G̨ x\a6uMX[b¯|TR-s"UΦ<Dp -!m܉VC d /ȗ{.AT'tYۣT㠿!Ik6ϚfM X#ggy(*<8qˬe1V`VZoľYlq4 ,tئur,ū}V/Ac a!m~#j{ [S&Y's"]a¯&O6FTYUN$ E0'8T$[U! *&8wIDz]Nj`h(R'% M8roF] zkNATdJ:":nk~y!N$\O1Gbo"?FA>]2}4Z pRh%S…E||گs3)Vi,Ue5x}X2V( ܾ8z:aھ?KD'XfOĜ8xV[)M,S{fr!uuP,Fui 9|b8s>wK51Y ZMJ?⤍I~rkM6 ~o6kF;4ϱ-γOKeg|#s1[0~}zkN~82]+„ʧT$=N~ޤƣ®+V >1q ͧ_"'Oպ^rrxg;8G RsvR:iTȃvgflsYFP=xoZ.fe|nNUfp~Գ0tQ/2U bT`++| 8Wo0Z@sX!s޻էblbHmIfJW;ˬ*0 1'E-]m"OHJk/dI $ޘeIc&w=R 4C j+MyJ\,<% +ﹶ=Ae U4Sg`$YESsrD7dajd&Ejx$"^8xcNy_Ifv4sT=G|+zi]*g{QO6'+Q~?/X \:aT\w[zō &P ͮp\qxXZd١+_{}R9#jHB ':1,\ lSyC?3-z&;e=l+F! FDT?1qPɈ}vP3 :H!+!H$5RKATGKu\ռly$ҪJ+]1ZxV8R.6勨Oꔾ]Kưݻou Z3sK,v ى]5\߄. ]z"6AK~Rk|̡d'[R '"[&,"dڄu MxwlU]?H1e]³]DO40C Dp]I SWK'8*5]gwp .*M5?=zng;;z;Ao_1LBr|O뼝֞z1tu0 J]2|6uBHWeٜ"WZj= S:*]}Fؑ͜7Tޠ2 -RSG<{e; ߊ贸3=!9g2:m83A&z{1sQJ-c  3wHo?h:5ZDXcEDGֿכǿ]ܮ:(4"E[$W:9; |HCM\EӢ[O|L)ޒW2<^ws_K( ۊKTMfM#?BL,W9znÐ S_=zE&[Z)PWRFŸa.UWrMwD爺xFT4-e~>fTM VZ.^'8Ϩ>րTiBD;:5uTpϗX:-2 Y*2nLtE0jXbkZ]Aܧt1qv_~;uZFX4%ȚѾocrAH!1,6tsǽ!E kgj ^ mM|kx?3QdrהH y܍GU2J"3kB \d{5[2t!NGJF .z',dWͩJ;gS$l1g1D}X7N{' "az pŁ9qH%*YaaQ&i- Uf`}3!{>švuGX_σͫS}{%jB(EVWwF|NߑV,?$>y{s~^m-;T/_(eARI|]њ|tktY{%ssZyuHD'plst!˷ϝU{I: xmG։j/Ϸ< (O*"2O[x}G,Si8v#gpJ3QK5~[x5EE )(ێ\j1RἷφgLBKܝ:DmbWbz 2NҼx}zøAī].Y*& U_=^5j;To+-<OH|O.Z1'^CԓUmO)q5/XYXBwXjA{9ˁhO̸UD eS}tc|+|*2>;|.X؜;cf֫ uj! Q@z"Ϙ)==gyiV}M"gEn5-@g^#]HG'B#f3{Z^?Cet&u TjpRrHgQU]k|,3,{,ii1wa,g|oS]V"꞉,N g]~z nY9K kΞ<1g+U}rr-f/,$ s ns/Qcгٜ&;X :jncyɚk@8y(*O3;U#Ʈv[fPʃ=d_{4_[> fOy_7LKOy*iʃ]Ɲ3t.>Uj'^7݅v91- US`{oiDսcm.M+=k)G8Yv=/a"/=o'I`j0}J.0cT֪3:K q"l{V04WI7$9i6n4! 8x>}ӳiVS }5"R{,q;ɛ3,1yz\١(s| tgq~FIw\g=< .UHw@QԹIdkggؼPxpWr/QӾSn͕+0w?C{V l$}uq< [>" 1O ~rL0Sx|SpӟhUEӅqs=M }aGY0=n}ΰ;TxF$)Os ݯ)Z3^3wϟ7 3=9,-y Y$(F?^ْ5Q}Q7';ZHUpyPࡲUf.Jg%sJ[x&C{nr^e״6,ԒeS4>A~/{\aۑ-{%5ոK,:h=NCȾ5Rlen:ʷQ:a􈱻zHw#\-T@2r[Ö5D\1Lt>)t=9NtGEi &C.LrqAc6q~HmI0{.LHŒG 7/V^ mלd1]2AƂ,גYu?&s䄤L{N?Zma%ױSUmĒ3aQ?ܠ!`Z7юuX%_ Kl /~Os(20BDHl w&!Q}F붮c=e=9g#o>˺JWVF Ms+X<{FQl)#2j~|֍>HA{xECһ, >Z!q# S_CrMD']6WxԬ8Wm_;Iq.1JВY/ypAě1uw {n%WDܻtXu-tV\dw!9(8޹}DlfỶ W/ӗT`dn2i24;t!߆T oMNZb%DS^% U{O?z<ȟrC ^i"/ŚHsxyջ9))T=!r[wƟA޵S W*Wk$ x toX;vq RGZ 5f";.^jx4jlf꺋vk;P0ԇ^|[{DkKIQkjg+ZbŚ(Qʚ/<]olYQwTwAj%൰sOB̯ROCnGR^@! 1\2ljkutwX*HJPʆ7`UT}"Gad~?爪bnhؿFyG#a S}QR/g7Gq]OT Ddp9>l&_BkWBJxՆ 7T{rE?U^Q ag!#BnB$y\,2Vװ\f?g3HJZRڋÞO|P1N-ޔuWoxT /ܸQWJWQQ.y>kNѩ6BUk&Z='eg6u2@E9dIfҢ5ةFqNu H@sVE~db3Ndw4OfBq\z8TbyuE 6W5uj%;4N˞6󞫒o@cOqrM(v;•UFS4!<}NW;o8uo7|PWťۋSӅ_)Mz ҆KըLN!$Kz9Xx-λElZ887x3l?רy=Hlް1x.1^-!(jn3&`.-z ǙRyYFJℷvry-G̃@ͅĚ!\n%>k΅;8:]Grmh3f !:75d;.~m^- 7P9p C̑Hi-HŠ/yazu9`A4].{İN] ffpIgh~t'|wft\%L&2 dˊX(s1_\A(y׻a>RޡKuo5}wB֨,TĒ;gFTisbLyi)3vD8M=^G#uc5'pg jߓ\OeҴf#듳N7 bU,cji&tQh'ՕCjETbg)0ŵ$ju}7*\qVg}f˫HUa erγQ[`x_ ƣB +N/bt&K΅n"vpKFhXU֝ԙ BM/ґ^xA$,r-Oo "1 3tV(΀y' gMLFjӐ([fy ^6:~е8gbAs~/0pMi} DwC}Yf]84f~s,kВوi1]MGn MAR঵?M?hlk豮K!FKs^qÏM:P59yuȺ#I N8;PtTw|37JǺMDZ[ ?'#E}2oZ_)"#j5lwKwK/][]_DLV/Kf)+ğs[мoM(~"Զ$72`^W`aUS/bOEJyG l\Q"3CROh qM;X0QU8yasZT[!#o'1;ᇘ&UMWv H™<&M}=9}cy"~Lv~8ꐰ)8ZڎQHR#ydo+vCAI'Q`!OլԵ0rԉ i+Qbj&NsFmn^~P^w[~~p?a9Eh/SID#TWć'7cn"[Hs`|?~m镛Z#;zsvGfO}ϬN6f&׬ްñ/{Gu"!UIS u<̭&gG!{1*aY{`[Qꠒc=!걢CsaYR 8鑓Z0ETs.wWn}=1^(8lMj5d2#9eRG9Đ*.QLdz9tӔU$7C!s-s ~T``R5&<Jd"dH-? NrGSHRb뺒LS7l /7 Ԓjkכ Z/IEg.F}3~ˢ:.4ӳEY1QF8FmBJcH">ڈ $G_+hOjh`kS*B^`3m蒋B<+5Eert0,p )RJe"m1]aӡMod_\c 4'ө //2)vlkm1^#`k DlO["ԵT+r`ubϚ^)Q> 2 74e3G6#S tە+g*yQˆ\Oϻ %|4vׯ/.a,JV/rAnD^>tM ]V.q8s]ҽ8&_ȴlΗ3؈ sc#j̬1g/ Đ]BPΈ&HiyחFt* j{lc& giߤ/FT,;Ri򥰛u~¤|}mYgn֞[$c[³&<:OM oSSOz_ny!9qQOg=qGb3^nXKi6 ;SՎ{2H'9$_c$3l EoSJӟOo:HސM @8+&yV!dh-P4P658~oU |6{1q[e6C ռp7t'$θI; &;igYHyV,;oMtQp'-pgLa?1Ō$jX]CAX'!Ȋ)deD I=$L6S%!V/.&>:fy$9'#dxAϝ$4U|6b7#{5Rӱ@]38!陛y/.S:b]tY.{2F)z뒷LNx*CU{0狳g)vXaCg|C%:j\E<'Qy?iu~(_=g+ GO\PC3;,llxϼrLd8硬Tx df_F/ [vg&ϔ}>0ߣes{jBIEX+^ s P& onen*"bw>ά"FQ]'աfL?GEL)J-_nto'k,$Sk}gsūKJ!fiNpt.>Bڽ[c$|2,Myh Z:ՑCϧVdv70rE;#gʂüc|3fArW|o$F> ŨWDndEߌ|11o ׸lMK*ORX{ TFT >j,ciz#C -f'wnV.9^GTӯxN!8$yAnEGt$RptbΞ]dq >n1lA,Jo0*^!^[QF87l&:Qɶ7ixt #HŠD#ip?yt̚ՒT[#U܃-xQOI,dwRL㤕D.>DT2+E2T1TW ׁ jШnB̝&܁:_ބ؍^ŷVmvꩋ֩n$b (!~yT(2YV\+GYރx_W:j? }Mz<=9v7##Ǟ4XNӅIv.RLxZ *vҐ -MQ>O$ijʿ_-Ir,{*r?F+wYGPIb9RL%fiˡ\ߍP EY|4<]xDVMxjvDiC3翾Ѕ l j*]Z6RH'k}e$VC8:58NҁwYI@f~.~V,sYQ4t.6ݰODkәgo'7/Xl}rx V' &gaQf|Kף >3uqѼ.,-r \m6CtĿD8}Uӣ %&~FgO߇rQrq@_TyWc 1VWy^Pݸ:!N )תf;ޮZ6oom8OG{b I:5i}*~;+2ry*y=6^)vE]K9'=dPp_Ela-M'S䵧pXs/ P8,0p]ʚu>P Q+¹?qiC&kLZw<:8m;wѪ_!U6V6ΕݼشtX8\MIMF#B5 ti$9kQQ:]=bUgI9$lWs}OAS :ҩ֗Qp D`U xLC\0AlKrB{jX?~w#yO1#d5_krΟk:;ޔ^sm]ieI{ :pn/8*SJQ-}M@{ެSKz9Iy:ˋuϛL56tqXx*1E{?ꖦsu1F-iL:)WIMvI,$-޿uT_x2n<>c t_ӱ&\wcnp9A*M,9GġrsN.y7DQwDgRÖ2NIw>h;t%:fV])1f94-g\_YFCyQK5<=c9ZJM&c#Bw~ O3R zBj }7cNu<rke=xtmunlp26铬rba#k&HjRsj۵- eFw"F4bIf]#jrLQDq׈eG v8˔x oYꢯ|zr'4jjV1{5M 9|l3(#KN'eOw}>[T@ !>~GO/t5_9FZ>K"BȳZaݴ.IɕX %Ʈ(? UG*Gǖ,'be &d6ӳy_zUhSD]=k()b|7r!qdk ڂd}-R}3}ztУHqF)1I(d JBgV~4V rk✊Vp YجIQNZuw0Q1]amwyVnjQ6G0)0wqCQxZ$"t@q9[~+u E* kݦ/ݧQgt͎ěbb igʝ%5xƟC@k]S ]^e;Xz(4cODLUA[CJ \yEBۇǕpD wRIƨڷQu֓q! hLB.!cLBYjY|jВ-j1EgǗ QgW3+4Df/b ߔq'[6UDDŽ;=;U~Z]E@N-vlo-l!ZƙaI'ۿuF*+s եIm#w5tkd:N>F;!@!|jkT(c^eB7^Gɯ~?u=P4f+~[` Ss$y tG'I {L[<ޮ} YA:=e1IrĔ"I5Y#mlPyI;]65c=)&Ӆ]жles1r9lJa_\_Mё i<_k̴7E6)RXDFcmxBw3> y-k2>+ "TcƷ,BLS0Μ;NK6} xBlv2Ocv׆|4"tҕNf,5MҐk[1~yf|hکmsKwƦ ~p\۫Zqoz{F(j enIbLAP ygnEo#`\$H4MЩ&'*ܜ"ekXyyL*E^崁\s1gA+oB-WCeMi$!}7L 53cum^M߼uxL0Mh'I}pu|} 9Ƒ\ ۼ+Y{ 1C9(]Wq=ޥ U|{hdO׶pt6YLS=#:3VBx j!7{ Z= R-iAvp6i| MO]79FZ=TܲI nil퇈zֱb8=/]у7CX8@)n)ћk OMBt|Hm@QucV@wn"xDu"`9.:r(VCL[}+3*8Z\-S9.V+sF&dA:rD Gj!=[A l=pR5';kUQ%7#K.VJF NK׆Ui(|sUEqb» n7:v\ +Zț\'d M6192)h1óDJwWtFfZ̓R仦Y"ȢRdKc2]*ߎ6GEX"yoۀaHY$/92 .ѻ ·Gr˒pA TQA7z:͍6M³]9Zy*;0<L&tՃ@Eյx([-$wHЙ?Y]ԅJMW%S" g_v uX,vw7 Q'hSS5}KL)ݡiкUwNEw@tr>ِ 7TĶ+gx""fͶb5E2ƥ휵(؝TSn~oؼWzHǶOI\Qrw e =&q.ڗ|j?8i&!zы-sRc[oVS:AWH]2T/̈ ePWhqq b$cUѓ^f|k on!3#1ה]!]G#M{ɼidL@psƑ$YuLV"1 ~iS^UV: BNNk!ᬃN32<]U_L*z2b:YsA.Ay%w5ϴj"RV2l$$Wg2-lhϓvK-{e8]K v~?ʪHKCaX <@~Dnܖkٷtf1>IOMlyWA )z3T-&BT[#K!)onDVID>Sr}6}+1sI5L?;ã]k1F]C9Zg<쇥&eYmJҊB⩔ռJv5nu7l/W%a3}:0QETrGQbzju\7$+֕|^FHemU_Mr{(H8d=]۩X/A\3)6EQU҆)ŀ3$'K'b;gUpDՓW֌=} ٣ ;J=-αt|^* Sdf;9$vNZnЍ4隱)b=>;iph3$~]l5 .}>TnY3U Gff :"=pԷB^GjtWZ1a^[3nheBmuswNHvw,v8$DOxmjyzLN/.E6r`rI7&a=ʫ5${"0R_Ae&Ѽg*9bGb+xcYzڞw-^U5yrU ؝fd_#}ߕE) 3_J5D2TY!ܚ!ϞBDjvU'FReu EqL](րw6ylQβO{V +yj҂] \]zBL }S/E$ u{ =u)9 =o&~VXE;haӤg5b=$`PUڪiZ%4Qi #{m!Íhoq8{_udսY\/\RwZ_ExRdy,EcIl8V9*Ms%we`Lo0I^3<{^Q}խ1A3nX,Ilj S9h<*,W uU iFtG]LPRJBZHO5u3D~9_ͳSECAN4:~IO[ϓ>;PƧ ZKkA惫 N(NjlwU/g;곆y5FGэ!=ҀtY69b#E7߁G܈m_VN:D 0J$R|6I^$)Vf,cŘDoCO+ߨ ̳3.V#*f j GI|bH)b| kWM1 F+1 =q'# XR޺!Y8c?/F楊{~KbBo!`vާǵQW8Y{|iѸ. 3RbrlVM5<[),l w_S+-FT30x#ݦ^ӝ9'IGzVRnyu9KmGdUs05D!&_Dd qﰲ'j(LTMU͏Y~F9>_,Dp-Ẍ́zzN$7 HY;UI8ȭnmt!ūeMFLK@it;[ bL$E.9L4xVqf#_Bw TmeLfQ?6y泋>c^C3 bW~ Gl /iz!M; +nCjVDU"Eyљ|=<5t'QX7(Ne,W?~-FT#iJN$ a*,:aҡ-g{A5 hV[|+VT&UK+rfIJ]?{^Q Re7⇘{n8e)oW~Fe"(^b>y:Usjh?hr#1oR()z ^:gw ]k?1M"*oշ_IGfdz˵z\ƎݩtwR}_Ďۗj;#vOL]"v>4} V9;(@]O|~]F:Xm/,}l0RR#K!:MwO(jXjaEŒ`nu,b"ۧAߨcWwU&9')cAkޜ֘^8t9q[M #f%#{8? JOsΜ43p_Α3UjzI{H"TCHMއ.b'nV˶S߱#fȕx/R /nn8|D4+e.87_/ڴj8u{Ṋ2GνSfny:sIb# VW2vO̫~T& D5|@rL9){p9f CPk y׆?k%"]*OA' XfO AT]I1P[9|CrjPf'OC$Hd!@]Ody*R"/ŜMqofZyOeųtwUp@IĿW楾Baw뛖^`cL*S%raoPI_^B(hIn3j% PGƟl1R4Zc8"R9ۛ~v?&ό'zL4.1n!F{_oBgy[~]2œ\47`zsAhm$RJ[?%GE\?U hUQ7GUQ?߬j=^e~H\)EyDPK /ffruJI3˲V7ۜ!ޅtP۝:oPK?"2^ nf'j1ѿwJ2 UNi(~,/_[TM7h,1v7b{YF7fzcꊨz.rhq]z y'Y$Ko4DuOG:xRsy97΋V4fxj"5 _PڼLwia=UQ[BfBcM!WJ2ǣ . Dא|>I18mĿe8=hBEF8O}i\L11V~K_-=2f✪GN=Y3NߜwZқ!5)vF[:;<{S8vvԯ臈 u=5#ˇ/$'u/=-w3Si$d~+EM`/Iަ\O7vj{;̝6t3*ti$jOL6f}ۜ8RjzQ-Was,tE?Q{.}ַ1;_{.|5 8Ȫ*QoQueu["o&(=Hk͑s c޸32 8aS~ўYCޖT*ͯq]v^&9Aju^#ulѯMa*.Z=+θhIEx=@86~U/zv,ʙL)DF1 iVΒ")OdO9Iݪ]ϜJ-7~R*ZSYI#.yMDtzO$\6sַ|K-~}?jxx*uƞ}/o8VHd#*X8sOX=VH^Xn'K: &߳j^5m4QL\ůe{lxgA~#\k/n;ᱸϦmMI3&uxU 9]A[_Ұ.}W_z!awn!jwM7,z͙ 9S_]xPƫH·N_]I-,_3/}zov,ÌVss?:oy\v{ ;La]~Iw<@ onaČ-8}³ xU@O$൵p|9LSvf~\AlRQ:$;st?Q<*ܻkpey'#kl86X[q/Dbߑ=z5#D0PmboT")1oe*龃<3$`B/t>gvѦwͽ~\fٹ·s-Zޤ#^ 3JFݟ.h67:ĜB Ⱦ&:U͕.DZ6s@ zlkĔִl yHs}P9b餇C3LDp/#b/kFm!kt8Bs(Sajv3J'HGlsּB71d*&9QZ ipB8,$.Wj>,u t|6~B*dc8g~Gko#Ʒ` ҌPk!UEQ^*aOzR/jD/ki/Q)/܎?>Id+(2<\;z/?,v=U_j^>Cw]I:\߻ jhu3"#)@Z? V,[>+BW߆%*wGl2]`;-]ĸ[$S+uof'eI=Ӡŀ`p1q=_uKwNө7ҡ߄sw#H uTP O./yDIeש :IFYYf֧7]<#D 8S|ZdUa"+0y~C$ ŧQՕW'ꂨTOl-] }9X1ԑ;N9)S/}W_faP! >9aO\I-4D|KM)R4\ u`Q njbלNndh<^!E`{_J%vdP$yo:*!/Vg.rZS"PM kxZlp 3YI'ƕ~~.D.v^1Jc~׿C5~윯'1z:Ac>XZJ[oBm"=bϳCi z Y/<ڣ:wj3ǿmZ.9E_\wnU/7D_'̵VX͒bKCAyPy`z@Ԧin&4~k s{b<_ȓ-q&5 /jl=wHʵ$杼9%A$)=]ӌZUĺFƃ?:#s<0=J>##I+"F&_0SF JG?cK?U.#ɻͲѽ4R8,{7pDl3iqbr IfWJ~ytyK3]1E<,Nww?P#f#{螹Nh'ޔessD=npmovTCR2x>5oXZ$ ˖#/8Hys :XYqtwư5kIɝ}&-T9d#l! S] oϗzBb3eCg6X&%Pѝ\xf ݍ1uA]C`AeIWWjUV q=Q%k5t6uCw>2)*wDVwיwN#Mnd΢OX´!CѐDdz._[V S]6MX YHiҼwԸVӔ }bPg/& Yma~VוUx(ʲbٯgGS=wwUZհ>bPSښ~ !3{Z ǧ+|4m$9*o|7`MR2ʋ.BYrT.98~t(CM'Ԧ355üosϫ͐䓪'Js_&IR !6ړcfXcjiTJw0vDZM^']/xuގΑJU"顀Oߎ* B1@rz`;Wlǰh8EŠx}p*fKSiu% -1elFF-bK|^e&cZMc]RZ#[]2e?vwc5S ,fnƅc}IL_VYP>1HL3{}yKXIPsԋQ.&uzdJr;AF%oiTbة 6ϻnm@J.Q:V?-Lo[s 8N֢'Ӓl7U+aPy? ieBjpTYjD#\x)7+ǩKvĂrl[Zs".JwWۯ}=I~"9@WKu%SyVl_b@+g7wY$9{]Ao63 w!y1WICNx8.n T'(gWD^$ !v&ehXLy)Oyv3ZCٙ'?{8zK*#UrH3"E(au7%r=Yt=$+=RLVn@8]ô7oy,V++KyNdz*q)p;M}GǤ9K~^/|xDڞbfĘR_$UgTDRK}#~MƳo"ܜG[t|]|D "`9˒y T{uLY׺>b(-n<[y?`/vM^$i1:rskx;S6k(isS/e[ ]R1"IyR,Q} 2t,-2^h[G{`1&zjj ( ] E[}wbt,.(|ȉ& gNYPZ= Ti 헻ҳ.y<d`w/WlF pHn]=  a/?vdr]K;|pE0p.{ĭqY/}U=1D'dpf$a |:lZ9SXPѨռrAmDV+z޸<7fr[~v1}gdmuD*T튣`m] Q-| &ԞG|6PcsLiZӳq9 ~ENϾkOY(8ʝfAPG=޹ju {GLwb evAZ e@e+$ٮ :=:?ÅgYc*2 =.ފfu5g&8bOj>xcf:MʧfŸ$hJqؑL#Ԃ}+]jl$Zq}TOcmG>JXjk ?"bޖIM s~e>'LNtr6|LvQ8 G K|h+sVD/sxX`$33g\#h^4[&HŚL.FԧjCJ7P]x}a_ۘ,0[|SF&UVfdjovT"=ߛRk: /{;|zev~kZ+qڜu6Sψ Iׯ{ ScXAUO۵o1ǵp^,[H?$W˟k#Jq4g6xSI<{Ɨ΁,0Zs܄_I1M^e{㷭 k.x K<(wZ,HONٔǎ%7O/QWU8o{́c'oCNeaHUZilU[x8.N6X`v3+Bzj̚+h$՝ {Oc^ꀫ3DdhAzݔ9-ʀ#ڍmf!kcp bR ٛʲ_:`$WGIWiB~0?BŬ I3loPz4cf"H&a_g%#g =K41v^5J/kGݢ':$39p?٣ w/ uf#ؾd{?3 8z0} ilXA;ï'=-_c<Ss)B {G`KsmMڊٱόam^Q&/i2[;+~n:nʼni?l^#}8)y$f#a7;S* QZxѹ*!W3zRD͢Y¿ (~b]/aUU x{1(@&[Kn+qAX'[Cڔe69 vq᭼!zZ~Yj)v$+ᄍWFT-ʌl8QO4n[AxQ?jSE=ᒝM~ygU+߁]FRgv#ռ`uܿ[Y̛ b'࿎R7ZKAz%S~R DJ7f?%o->m]f E!Q.UcpX/pYDŧE{D {+ːXSn.)vєң vRe!vu 8w N7]Fx/zӝ'zXq%Dg+IspM5*0Fv b^]:HKS:ļ"@7}:e%yg a̤>Ek{F]3trH,smDA{tV0O:hһY=?!9nن9pNL$)nY9)y#ޠe/U D{CEԋwsiW#۱8k4j9q-CO fDsu:l9,> YBlw԰^ uw)ֶꍨJvKA+OM~2Bh:R'i*tnG tpCڹ~FTz/zv3d(!5_rMs,ayn_w[<%OP:݁8Ԅ#e}e}VW>})Wm٥GD1X%'xu=嚻98X&nʭ󍌸~ͬ-P݆?L:~Ti?O[ZvpλHJRQWѭۅ;V|A GIY9SC#nM%'YHBzU,5SrL-t0(AlƝ/ƐJuEZ/ o-uȢvC=Cw뛫t|Jk y[o.4 <:Z">}~1Е[ZϷ)cn޻Uh,s@MWsk[iK&M4rwTaX՜"MY֬٣ZN8茫irmC_AL̄r3i]S\"a\{+R6g;8~{>N>OE?/CГYG'&}ဌPgfDLhZ \9Ґ|1?Ĝ7vz%UMcN}q^usz39QXQo.b,ު+S]oP ,0KpG;X-7cU4BtַY퉆ۓ84U]O4b/Zo4~`Ȯ'O/0> ZᙲS- w=|W_K0 6h/UB IERu&TE_lܩKC'q\{= bj6b.>]'MC!ߧK@Ld,ɺ{.< n[L@p4r&>)]>[fr swB 34q4k*|Zw05g#:#m6[9j=;\w *rx5V# Ct`w"ߔy=!0%!IRkȎI$EqNpvVkr ![Y1)wR(]:=z^F=u>ֲ E) ΃vtL1Mݣ&@᭧q}׶?-6Ef"ts4=Đ*`d~f&Է H1\[|YoPiH>?\u'r9و肆XMCkJsaJ֡|*~d͓#ex&%U'tah)垳|lS0s5&|5t%M@+HZ{#>fP:Ը_O=G1!ĦĨ.D>ثj,𴧥/WnES.O]!N>-E^E]i̔fz',]8t1ۨkûgOdrߣ&/(rnN/7J\y">*{yBguՉWr"D 9O{Rvy7g\2Ո@^*H'yR#\^|ШW܇f+.OtV!1Wf:Eo՚^H蠐8vMyFrkd²;!Gl氭s-mO)̝͗R١WzBtH&+p8F9sn>%(Ne@r#I(].' _m7&y\"^9U`캔ZM0VL!hX"zVbw&!c+˶Ǯ3H8P e@cJ7 H{s=.^m3u։ΚHweӗGKg>bڥ:UF0Dˆn'؜buUGblH%&TvLa !\7Wh.$}_x bκ"9A5rr*Ǟ`;P\5\՟U^wxE;oM?zZ8b3ёW/fpYuQl.Ko1+ wxe#gxO8uU2]+'|y/-D8Xጁ02s~*3L{ܧNRD sc)5"},D=\FUCSYl tOYǫYaA|WRsq,;Y9.YMg@˾._~tE#^߇ƛp]*ߊd BDDAH>(:&\z )͗;Bʈg=V~hKoRF+q^i@]GgVwDʾj`|xB5\:>u¤sӐ#@Wf2).-0hdX7i#mrk~I <.'tL$#6ՕS"S35Aջ/(<pd&B[-\TSnaU3Hs' :fgw{Y˯:s(x#LM$iNuSi0ďE=Wj<D`b:F@V;YRu#b^&I='HEr\Ո$5N[OV_ `2j\DoۥA)cZ8:S8/ QՒO_3&pLH~"ׂ c;w =ӿ{qN͵[`̄Q0m1uh$% j|ѳt0_v[k 'l!syjUޤTׄG$'ǚj㽪U^NX?6 Jl)x,u $5?^xxD'srin!AU의yzDyuvQ[xM ,CHp] VJnHX);3g{ݍ~{e9Fw hGI@Dw~Sf#cH55n|D,?ʎ>Cֹ}gHBVGCdh.tF}]f&ӊ)̣]Eԓ$ UqS#@4KOC~ Ée|^4d'N  r](jFp^Y lIL%gR).;4 1Oonm]or2%<ɷ=SO+/95\>W] T̆*$ -D#GrQ98;C#58hʓb&@іߧ67Ӽ>N翷Q`Ȅ@%N#X%x#SݣOY:U)P)"rޙ?o)n5KӼ;T%E{M1 ( E$M] W}v10ĊiCӲ<ijW{4SuEXR_e< H{DA"4N(Ua67_<A\Ü/-r.nq>35~=YXP sw%Dsw1/sμ9H Ej.-_cg;m1Vxb?:ڸ.| e\O'>׮&'#/_0rr0$Gp *w'aWUxɜy_qUIJp:HX8-#9+A>eYZA5Xީg@b߭Eri7%6vx JH%f &B'yR 9g-AÇ>_2T%]=[ |'kG왺W.gς2]XQVͻ#dmp5k+N2MGպ;0㵜l ~A)_\bڕ詅=Q21,d3.Z8V|QwYkBjq.p[+KTmGc6\'^IAkWߍgHب?& !QhXͤ2wfS֊)㓝yRF.dE jp|XhiDg#/\R6"1鬠F ӵ,1`De5L)4't2P'6Gv+ QGFYVw5)j$~gMS陵u7z&p?Y֛gws܉.]0dֽ^НIL+a[\}8AaA'i31MP$Ձ شC)Br'OFT9jcBbv$~ӵ@$x]Q6<#[ꫴ Ud_P|HXӜ:>g]jHN$:sTcWk2y|2\CR]RوJ!MNxTdoor+A_݃'GR.ZM۾ #U_FOMm_3ǓU,V%qXa>Y"*sZ?q'&58帆Yi5I=:ʆ^('SӦX|=Xm :9qʫX {ʧ1]PPO UVCNZ,ٚ" nY{@1XoGL{^4ٱz PٞuITxw{{Z*-(GhqU $?%g*9cf3ūsp6n5GsȐȪ*IHۉ_;+q<ܿTx杘_&s׶pGg8={SV:T3^|Hj4Ӛ7e`, >K'K:'"+wPIdwC[bP8É#ډ$'Pq`Ng=K#}cּsPc?)F%*8Ϋp)׎-JFA^F1(#D]mR pJzk.xsVIx,ª_PWnp/[zNb6Flq f.Ț>gN}Y Ȳ*SQ40J#_fz$"@҄Cj7 "wLN ȍe~>ڭ^j·LNpr~/15 d%k6FjFI? YPda|ny}ȿ ZMB?CIK|pW.S Y tRF.9k_FliD*]N-"<&ȘԬ7اLֹ}j 4:Q5u!'{>N u 5Q܁~[L%!u3+⩮$m:1oZ~Fij^ udyk 0*œhl+6jQUE鯺v] I5?Cg$}kQ?oVkUxX m7Q?0wC"eX w6O8 "RCc:c pctʷ"Ig5šMzڽ!+&?dN ؂{JU9M+pn7B!pڪ11հtW>NCRBЮDNu!gM>ag qHŋ b$n;<%݇S[/piUh9ǡ'2o&ȺSm?9d9AvyH)EߔJ#if9^D)3:M8 \:F ;\1ف}Fz,ÿ*~˹)FDϺ\ȍ %1¼om&YT - OBf6ے"dkӼt|҈KFGFI| lWw&` x{"mSt$UQ(l'rY=ÌʜF*J&~`-ᅨYҌjilݳK"G4wb|%@b?fmNMeH'4T㍄s^7.qBX֕ǑWo+i2GkGQ  tAˏ*q-HFR_\FuUQKPE;U1p`؛rF`x=D󼳝"zWꟵ0O+M2p-Ì(WjLϢ'#6Ә@1ݍhY쐉A'Wv}br^4\ = w:/*29OUUحjx=SNIګ"1A TEL3L}YV"cy[QM0ͩ~+1B3{ATRݭiIH?$`2:\s8g]"]D5: k4"0ioa2dXo U Qz꧅)oRdYG#ZŸ~|ߒY:Ipַ_oi,$81vGXvv i'obę"[V|'%fH &gSr}d`vYlmSRŒڲiV Wgcu;gױvGGRu`*qèA5.H['|&`on9s@YYG<81+=|kqvX9GJww P1:=*hIp"a<8f!Kz~T4"dSNi1;iMpkD1`JŷsnL&E呀QA{bKqzuB, 5ULWJP>qO/:^.}fta6dZ8 A~IX@NO)\P=y@b&R{;7Y@a>}rCk*%みJ Tǩ5/»H8 }u!Fl^=T:i.܏.N魧XJ4/9ҫhѫ9CEyP-xzK;O7K\.MS,=QH`,GCcHOD1st I} c=~Q-D5MDMjJ OQ 0q|XW;B 7C~!ٙ L!|7T( ] }pfۢ!eڴ߂xRݴ r/r1YR)DOCN)BmJAT s, |`jPoF]#D;8D{h2`꽳")S[zjOqEt:G0KDi2FYWW1afP3s|k2%3VĘ"a![&+ Q`&C HD:&:9nPɕwwߤ)UDVh"֗ ><KCLGC65Mt(& 3YؾSi/?{!NMS~>ӓGu7%ka̲9C}S# Z*=+=՞]1zulTX))B὿c/O"(89~6t4xNdSOoT% D7hr}߀@b%k~`+b:$?5=/펡bҀHEnͱ8JT3L|CmdHAw-F?T9'4˝ܕ7 pr툪15rnKح~/L2zI!-}qޚ~ oΔ?Qe03[SWMO{'vu{zI(*Zįu3]g=!XI@9 bwתCE5/*tp=TQǯζuUQSm |EMs|XG*ڑNß\SҎ1}rH9?BL 0P`VĽzD{Fydm2piZ2f;dGk#r+ܯ}C$WCP¹?Ax[mW1DVQ%J< NL弗X6| (K|w+TJZh/H/މ*'!<}LtDBS,/jl6W z~nZjwFdiZP 9R@ 咔aj $ZBuɵtwVm*;p(JRZ*՗{ ЌH@ۉxTf$!遼q\QAkNrّǘu[o!:Sg&M<=d#7S n&yk(K޴I(<'dׯ6siH}yo!Cn(;&mfi^8odYDFUNc߻tUӤV]dSwMwD%4Gdg &ۥl؛[.mpff#e Lf1NxkKffb-%8Qcq<}5qlѾ' 0OI=}Jgt懣 _c⍓b)^ IO"oa#Fs ?<\w}9ЙrXm=-!m2oq퍥UħVOqPͩ|ZeO{gĮo0Nȗ|;\Y.wˏO톤< 1ڀqSwa* ȞBC0RB=CT=|Wo~ͬߎ'c +J>błvM*qf^V2Ř~b%g߸?V4qIƠg"[u8n yS?:ԋoU>UUlZGg [xWX K$S:3̀D_· > %\j9_-ԧ1j`Xµ<_e$!'uأ$#YV.xE/N3b$=;!/4ϕAHoLx>]ڧrj*<;}=?tCH^i<|q9yĮU'VjlETCa''M>7|eU5%Ec'1~ySPһL{4|luouЗ\֓]?II*yn|2yvodZ1OV])pħ'mNj۝1"g+5$v<ԉ^<:Y:i{jEVHԺsZ=`|ZU7L Ӱ{s1H\>V]3U">Dl:2/MT!NV4ֹ|ѭj|n ԥ8#K3nkkX0{nB4לo >UջBD"NM.r1!f:ak*;Wyu/rN[1'M\?:TQsyw)W}'LOOK1Al݊ۧĊS썂)2d5)kbvQoP<4=7axoLOn*'\on׷TL[ۜ:>Bc;}:7ZƊ\h-"2FG:7{s9+qG#X:Qƽ6Tua𾬌u/x lӁF)-kmg8Ы G2x?kRĒsXt%<%HE) QSi7s'L'/@~53[L\[ I3\ɩ9_hPEγ"[錇s$hO m&w`;!3Xn}AGAOMDx{Q7`LX)WS{WwDs43"}ȇClE9Eφ.)] 1!л>=iܞ4֒ۓpNyw e 5& ꮝXK(AL7=>xA_ 6( QZ"}g9m&|rDxᒣ=Dt#s ~K?߱ _$!GdLWZ޾cAsOeLrQ<ź }CNǞ5`i9MMtN k"J0R䅆 Bn"{͞c  (Y<.{{V5WElMMS_ ke#Օ(D+9 jNuMR,LtK|szAGCX#lGY#n6 љmkV5~/r; Ԩ`N)>o #[ l_{{T{3Ϳ=^Q9.竲F=kx1!yNR8ԉm؉޿nB9 ҰeǸY)QgB'r$[i9Iy_ĨQ%S+>> h]TR<־o]G샐TaI|p})DugجfSHHػ3'A,CێD+g_ ۼA*i惂+)ƾ*AKT[/ZNZfQz#&5 -5S-Dp^ ^wީo}2yP/w8uuf-HDͤnvoޏ(YIc'uT[Sm_=Dt+:yնx (Oz];d׏z#:aՑ>5 +퇿[/#q faU 跺*(EHrӓי1G.$u##YuDs c<-u2yϷF]m7?Ӫb5i,oezKEHa4#H uOB:N\\>2Mޠ$׎S>Hސu%hK_G dsl$4y8h~яT+/yIMu]}Z%b!c'yK= {k7ڗ i&UuJL~Nnskx~";sW5?2ԉヌjj*48zY\+ k^b h7\_92WU3C`iMxil~XkÿΜ%42s*Q[슔5[t_L8"=IC^ワi&3 1g^Y=&(&(ja#.5baHs,P8^hXiad/>v%S`nAJ R5|#+\!3euW6+kuqkaؗG:TlcȞ $ӷߵwkVאhH^.]~xe_ޕNfS'yFΏz4zݵ(g5K. tP+jϲct'BŪV -Gb^mOr*(Kr 4e;UaզO֡YTWs+<__(̱ϵW+f'>P"3EZSӫA|£!~yi4=_$fd^zg{qH)b~/ 1^&q^3g6ycN+Ym1Cʶ؟+gD">jlCس-*4_T"֫)[~IG^iwɳ.|lX5ҹQ+71pr2s%ZeJVT.r7oxЅ)TWAO4-8]g ̫ķNo O4sT%ëî"6Kt/܏-5DS|'!k4Ubr5X~$U)ONQx$JqMxdQS{NuCTc'<育$䍞/]GXaP%0@֨An33{ѺLUt ȳ~w飇ΠH>I\/BTBinCUV>iZoM7?QL6QԔDm} Y<:&q ^OMsGl>ךӔ֝e'yn̹5kuΫ;ߛxoKcMSsD+1e8~I)AkjsM59 aX2c,Ѻ72ֳ{?'槏\`U$4=H4RxMZ`~ňMV@ʧ#+owSVd@>ZH=礱W(VdX`=AQ ]L]z{}x^n5՚"|lY눲SUlkOנ^_a8eq)A*RvF,cy:OX%@O' ~h݉= =V㨞vg!|(@[ vjƕ:]8Z\a{}E$ ~:jOzsfW\Af /[J-.='ȭ<K}]]E!ǿF\]Ī(Rv.⧚ 3iz=)dŅ"e ?׫M_,D*:A#Bj<7S>- QOD;{XfD'X2`s?qy6`ɽ'Z,mʭ''6jZm5(OPdeYvu2A%%Yǡ~B:<m_i =}gy/i|̺] d;Kšq7<&(u5BNj>Tiw\[,p*3̌HV7TiЂjwFK*]9c[C)"s+pj}dU}DuOp%&*}vC8=F 9Tu>䌈!xHAS,a5P^B:V4wP ? rbbm6NPвYb;idW?ߪ!BveYĊ}P/|iC`wri1 ti!Ucؽ_@T ׵J12UuDD &d=)j 9֝)<Q=wަf#%{=S'@xe^V>y!һ|3S-QX!rIUU+WJ3b֤ͽ^l65 n9s&{y@hfĮꪹj4*iXq*R}G\-$;Y,swsŃ'9g$O<Y 0YTy?~u܏:T mHXnGuFk͟^4&^`վKhνRkzi%Dmq;4nh}$!ȟv+LzSn|葾N2:Kmhi\oNsbjbd &J#-=\/v?0,I=t^Bz6gaD$yX Az*SSEUX[ׯLq) c\T+DgeYbyJ@ץ.#a.9-zZ28Gs ~ DI#&dzЉtrmfDt_OfIFiu-$( eC+%[J%]jE<+ O*7nBTeWNZ _&].>Yn˭FX`v9E/W jUe}W^LDe5ʧ#ixHvޓD&ތXsD5*Id/l}iCzFxZjZjz|Y2lgdJ3Q9!.k/!V]lE7Zi Ri)/#I{-r^"s'Thv:Vz VuRd@4E`uŰI693 RC<}Im2A«|gTOC섺 x͑X-+9e)њSVzYlIَ۠X2dk'! o! NB.UwУϹle̟v삘E/֚w#^쾇;J<ɪ4 ]kiclGؾzVX ؗK .kANߠK5W7 v]2Z֝!9D"K}^jtR:AB\R.?n 4Ω{n8jgi#z. ?{ab.n:<̭^vCTB!KHا. 2g#隯_g&}|R`TdGD"sBBkzwZ]peMzQ'œ<+ ȴLr.+8qHEJϙȵ5[.| o,tk{/r7)2hb缡Zc!# U▹h˿ }? ĊVT^Iiy4%'p6y㥗:sJ)o<[[s S2=<䟕1m[4AT} Ɖyާ2OsۙtU]y@o{uK+޷/Nro [;/82֩s!޿=j&V[zs;Z5m"3(WךgʔYLbjrϩBTW\:^;\ vN׳RIA*c/)ceے] R\S9͹^V6gߓgHٹc1oB59;]+NoV s']B#{,F9?+{䊜;YUٻPAb; e'G186TY*m<CX:=9м#Z5^~%땾S57L_'D- 3}HZy8QhIWDFtD rN'9Wk[`ϭSjpZ?4S+_ڹ+!aE QD?2͸q0b[3jMu>"'` |ep.ke 370AStAA1'X\Ѯ1N"@ܻͅ9{= 82vJ'8ECiTR`!t8J^nDλ٣ʪ%=Gc=G`"#=̯v#H4 M0>Zu-d:}r#HdE ^ UE_; @ՔW(dzgҀ&p+l$):]x& ÉHJ~I›s:*t"IYJ9A yܴ\a8uYsl5q"n&IBPJl;~}ET;gZS'TN:|}QD" օ)!ޅ& S[G94P=KsD^uxvXV=H(?jj_#ƹǻwtN_.xt$#v)MO t N[W~eM!释 ;4rrJ*ޅ89W 7#O~ mEH['Ɵ`lPA4`=ȧ)]ZuκE<$dnNSU'"=x֥pNS|BcNĕy pp6͡KtbȻjSTu3a?5վo;$@ $ب3!#&ËwN}fܤ b*R(A>SSoCYKoLI.Ү}uM&ӴZ>j|cBysR3rS%P:F<_4Fp}PzzWا éN\?t5u.L麗1,e}Kq}_踻D"D擥<; Q^S%Io;A8 yI'izښx~iH`wSs9;y9]K8.'P#Hb Q2"H RQxxXq:QBg~לKX4YqZ-}r)y螕.9횒)a|6#U}4Գ;[tfF5Ƚ_+t9O}Ծ] \& I2 %N^ܬZ,/z"(3|ֽ뽏~{it50F:Qj0N'p:>|[ٞ :2 T; d*7 x7e>ŵfY 2tV 5+OUg9'WM~-˲E6xL Q%O:f,VDNZq3m#:Aփ{w>Z43cՕPRY{aQku5 EXW4/7a X4ԛIWkS-_^}efcfBбj/.2h$grw :x* `O/.}#JzrYG|Wv~ '1}>s:_\<ɦ1PuT Iɺr/3P&2k ,*wt߲a Ty= S򳦐KkPs4 LL@<Z#uɩNvzOeȾe pak$w6a d%pXs/>mz@0g:{E )cLH'|p$vfNuqPp W!?cRÑ5r0c:uCIcλ }HĘ_-_`;OU֟:ITf\RɮQg]H\8d~3uq(|MA־板sBťyS2+A(Hm] >FTa2 pK26݅nCfsFf Pa&A ryZ} U5OH,:w'2 n:.xM̡K9 #i$~jM$o5k{i&`af0@pCAO/165n%!s_wc2DUq=iO)e ৏ *5ZϘzD4r*}\C=τ#o%ZTȟ9pQ䱨j$reUC Skb&G9(dV-,|yT۰w|'U4b~CT,^'DzJyP4Db4O>/.5JzƮ"CwoG!٦ݩ>g!|C9pr0?r ͟A!{`e!s=R:ЯM;%q*+#7@yLgQ,)ExZ>N1RtJ|Nǟθm xB"^*-顈1N?ws8_8tybIX_6EG" p`W}+7]Kו}{*2ؿ~Cz>4 MDC(<`ʱ-`OR ?1{BI`z3>,V5r1I,O8}cPB&Œ sO%Sa>7ATǛw4o){T-e|eNU_wy('t-_ D3z4]gW]IDU "֦hR$B K<Cxg^l#DUc"m=.ҬMk|2U7NE(+'QލDЧ?0Vz7:}+XvE赙C&~oAA.!{n9}fĴI ̈́2phAIlH7*=u-{OXf+U/v%N`M3 VWwx:CGpm_F{ZHsS^OtfT\MNC{{5QY7Igd.Lbbw۬V=scZ26iGX>'E%ٹ= \WcI-Y,G%T@@sMej ɝÞ4O5}]O hjW*&~=GEz >JȄenoz2asFs޴_|:̖=͔ՕU[tjԤ BQxС=6X?wtTe vj95kqCb'ިMr-Mx*/i%hZT\VRE dHVJBa/  [ҿ9TtNдT{mۼjjIQ2mpܨӉ.Wx͂diF j{z165=\Hof cA54ﶿ<~yhU;R._{Kr):䂡l7)kAvKMgZ2s\9Nvm\^2PNUOѕqTɄEKviz_$t}r՝Ct@9dVe}=f"HT)b[Wb"Qvy.QTP#RlT>,L⧗**Q%0 #eY<\uULry~2D]nyG+31xbs jy?tHVt9NE|vŒ3'ߗ"]<|JSJEvőS JoL:F!Sfu)`=T賒R=PaYj_S6{v`W4P B&!01 mf.䌨Ǻ]olkV(5N zOlM2|cwd.Ɉ5=aJ`! lw^xoD|+*捺g ضz}o)!854pnm0K,03Zmiʞ a(Y/Jo[?/vnQ5P=k6]xU 26:bS2A5X "m zȚB-ji SnXG=_~ɔi"ynJ3 ?ۀyC l@FЉy&z#jA)[ (VOu1cD ќꃤKNDEsC[Tz #H7pl"=Y ;%sS8z[W{ޭNlu*ߜ-Vϔs]ӷZnТSkC+CMCRH-nU9[E>tCy#$Z._ZsLd]:cADzWTs>l헜4w QI1PӐS+Zޗ)|ldb=Saڼnax\zNxH_X'+qq|J3jVU6tn4W83шeBmsq_#sZMtȩe/bWV>uEr$>,NVGfȫg] f̪.+"˞Gʏws}~trJAكLʼ}K`kpY($tqN{j3>`#l c. <-6'Yf͘Vɳ<ʑ)I=dS6G4aP?bFp7d\[Ū5d&}m=FL::wɒMSM⎇˓;D#:M:6 zq/>9IK=ܖ] @$~t`7e2HUHOBU`ӱa|kË9Cϧ%9 ٴ׷"iyRkf&Icñ6|;piUSgH#-ZYfj@}:Ǽ<8D{1y1yG"곮+ȉ);Gz c+KW}z LS c:b_Ϧ1ރٌd(Uͽ#sԛaY%72fYb99ơ?Iee_L써$r@\[ c%m]b-$ʍPqx|:fR U'ķ)XpヨU j]Mx&9UδBOY0ѩ9ΥS/zvs?Q~S+ fOPﯦ3V!Q I]ˌM Яo_l|c]jZP|E.e3 rYl*d}$e 9WߣȌPNd^>߫ol]ͣhHo`gmk^>gۅ-0=¾4T,Z{b4dZL#ek9 jP;vGհ_M62qv)bεȺ&A5*eHћ*b#Lle+!Q'0dG8P O#1ZH'ğBx*Ur`doO/wpDTf%.B m>H![kjrU MoMwK! V>i(>\p9]+v3Yd#ZSDz>wTSj"J/^ukA\E):urջ_Gͦf.R8lMU?e:+bfcjHE=g)M]iXT>&& `lnUAa`0XeRU X> ` XѤ$*QӸs{;=y_f-U4ۜ.▽ kt|k6VCl}/OL9LFi@W!*16Fts] ܔO=7*]Gsh[wf2N8yx.,4p^nj ڡ1`a)p=6;/<$jqpug]f<9>ExBB;ĄP 34ߓk 3KRٙ'2]Yܢ?@cSu=Z\0Ŷn~2>Z,w[_i{U)*(0ptnW'H煨u(zBesU: 3ߨT z!3BtdߕBJrS^tL\ k9Kڟ[b?'08d;{ʜMEtFZdM/6E=~?#wM'fMr/sEyK>>TrLL_H]$b'=5c"\UU AW)順C,Wvf0(0-\/p>TȔЁsz@(STu◼Q Klߟ2q+OWiOJ66g;f޽^+=4yMz,6❺'c)WћN2J1M2LAzHww_1f| Hw8Co|&͐|i/H]?\=H[ZV>c՝qǃ{L:Mځ.M=ԜIOY `iht R{v ͝ q 0r:V>#p0 =]q WK궄zQt+r!9ۊR 3,d=2}&k ø˸Af=LlO?7ES*iwUuI;XTֹFʯPfly >0vƨ>_*:yO[F,b_"ΰ ][o3pfu15:jl GnӀ3YgN:χvf:ºyL_~gƮK I.L^@we>9,2a Ev R}><4 B厗ܞ:=M`}U Ǥ^;OEH;U+X?.&DgZS*y82Ͳ+axk剸Y:™pg{v'McUVxSvzW9պZvwE{/ݙ%q(p#n(Ɍ;t+y7cQAt9:S:)ɂs0Mqu/~㨀3h=yyHygܪaGJi-j#kYqڕCN1gZfLG{/?3-Ne=q[tQs7BofQLM֔hq߭rh ˶4&ڿУ_nsVURʻc'qư\sW`'[85{b&&CWR>2ked\"/Yֈ;õ21bѷfϭ[{n@[::WDp١) nB3 9q8[w;y-׋24BeAT3]ќ8&[N*%)wC@Zcڪkv/@\> ueuS' 1K8MOxs#>5]{/٨#T6:%wN~.9#GT|J8|OEѓˢD_`\rވfάӈvVZKi _3qTCç"^~bJfW}?c)FzqDLnKD^BKmcK):cK@jܤK ©{O hĶ%Q%A8 y Y|PV_;ړU3+jRYf|2dJ} wr #"2K i NxZ)3`{Ҵ[]@T헱=~\8v<hť7֙<)p[%ΟdO{kTSptiSv? ?-#EWpR"6.r Mb+'APP[#\xָ̖z&͢bscnuk׆\g%8ژ¶ e!Se(9cȫev \+D Q kYzcδ1> T8q8"~0ˆy﹊Ź_~&>`1eWڛ$Gk/Wq6FTYg;sGcq#Bٺ#<䞊v4IIRk 1GOlXhLp0Z ^%'i听?ޛ d&/)ߺPP/82j +%˯5"|P蛈9 {$) 8 nA-,vtA@жM]FpsHCzYikգQnD;;;Y`HK4'Gں頧UL94}qu -˗7 M/S W$x'^[Ϥ&HO*-9'bP3PyU%D׶(h *Ii$̥&Q%K̬--(NGZ6.A(kX{ڳsD@:M7K$@Vu2R&ȧR/5ޏ=ޭ"u7&)7Ҳ?,U5CVd1 p$rrn=!0ed^D1֘Ӂ_wCRx<@$o=HsSjqF#S,Υ )cX>y i{#W'Үs"D!(>Csmm|XZdKŔv5ɿ),(/ghEQA޽ .=矞*I': Q8Zԙhbc֏֟~@f| s5l{dP?wQc)d B"zS?StsP^ 5Uq^CnI/SRlв?PNG  IHDR@@iqiCCPsRGB IEC61966-2.1(u+Q? 3Mͅbi\mbJ(F-i 7k?6oﻥVU낿[Z)"%W.\7ڒ=<=y:9`dnl.\t ;Mt)::=}QgYy)+P("@Vq8@ 91qCXsײy),' \nJD99E3\# F|iGR;Ov;n_s8D\pBhB{I gЀb!#޽ll/;o:E 7\\K%Hnゕa[C$ZEB"F"+xP{.gپ [%$R4A\ TL0 )$q$NHRHFu1@T6{`lC EZOR`jY|8&&/UH %ZRR: 5@ f@-pK{OذpOWH2qKH49*Gr[iVy%$IB6kP$ \4w*'?'rD\DAM[Wr@h%@@rs q IZch΁<6Lb4'iZ Tj[b$ GCdKfp_3YH*)IFHyџ߾(ԃY8x^5քEm;|!C0 0kSʓ1=.T֧j@AdMk}dW ]K4\sŌ8o?|eF_O* HY S%OsX%&S{Wj,}kt̤%C)7/L{z7z#|̭I%d>1i4"| =Z wFn`q{s/Z:/pȞiZoYT{!54&cӕeΖqϛys~{]%rP"|{ ZKElB,: Pe;~Z}mڊةK.|{S5}\v"? Cpы)#XFF ({Xw~ۥlF &3A?>Βzs0Nه=G֧}FAeBS@VDj}ב95#q!]sOzHµrľ#3JP%d1Q{hOdBjnP:=H`]yꄋ?{fX%,šjWOlԬr zB_ҩoGJ\G:έ xB k]5j]Mosgρ m)!#bKcm`&ۊNO2s.R*Q4(*tIڞ!3B]V W\j*|t&9RA(XBhƨ7jpZ|\G6d< pQ 6T I>,0Ś!ueFS^ϱ//U 6pNVl,/PUPũb:ZVnMt37Rz>!`c))ʂkw Ag/M|]x!-HǡnOf- S _65^}Rw4GEbyA}to&x̶ a/ok֞ ፫~:j[,Ool*rT.GyϞ+Nk}Sy7*kvfÖ޿zKSI~]m|ĸB4dOqe6 g2,d]  Y'xJ53hs*"J[>y0H%.;'l#=~l=1LVո1zz-w~..!|5ݞ1DWقBe318jg)<ƛek_6a ٷ>o/+}G+TVU<,`t{ά2")()$yT'76ٰOza][#Ч3T]7ejc,+gTP-IȲJ}Lx>1gcfUZ'zfky9ZU'd S0/.`uZ"!6!$mX82$kj,aSLzL띿U@Y[Y~I/f]Н.<#}V0)- a*Sژk_xP->Y 4_ e3玑7H\c+bIRCb=[mӺ'hZ>3y[fko|;.a$¥u\Œy Dw 9֋eV!ϟiWN~{gO~l'4x4k$MSYZL۹)bڣ>gAoiCCPsRGB IEC61966-2.1(u+Q? 3Mͅbi\mbJ(F-i 7k?6oﻥVU낿[Z)"%W.\7ڒ=<=y:9`dnl.\t ;Mt)::=}QgYy)+P(kVʌpƷmwCC\Db 0hAjFjzPep9-3w< \ b\q8C@3PT."8(2"DfD@bx{ٻYq +nXmcDq|=0S0ˮG7 -G\"s"@`#1(xva\xu`mO/3du35,!:8w"8\Ţ-A)^>r\w5o;ېU⢶u@5l̷s'E1 ڋPb(P]E|3l xo-O,3cB[HgEDAN l4 Zެ-ޓ&IR i:ڍV_&e6nF=Sn~/.ŹG˔okNf,,Q~i P U@qD6 r`,1r?htG[L._$KY~ϝVs`-FZ'ȡToyp:7h+ՃWE}c$Ć4d oJ&'uf-D<;8gɭ+q!?=)21- cw35 A4Q)ˌ$ #*3"GW{6̙PlE  ?;ʌ]sygu|{#QZ{ˊCfS^_{Q=k(߽Cp~<|_^NYc#4CChW`ij*,C$:(B"q\bڗz_4|9B7/sS;Ņc8BΈHj1ffC^fS.rRQ`A\&UtpgDDW3׻}JR.36PoD!bsdt_^ y T5#+xtfFZ#j US.12 eo8ȁ֯=x0+Lm d TJ=b8"OͲ3얈/s0ixV;34'ISJ)c!T9s';ze.* qJTqU?bH֡% fDpB߮2z;,yξ (ikocv- Cl;0дޔpܵ?v54K}C򜜛hY§jPv^Ge@ˏ␅y*>UXCfzHoBȼc q'yqҹM };Yc$ .ԻO\~fu㆟m啡rV` ^=I9\rDq5=ڞfӊijKUS[Y4-w\6~ur~U_qs5T|l*XfV$&Trks)0!HJj"y0᯿h{iGR6]\>)w6^Ь8P)IB }ʢ0z+-mxU01I>P?# ;q^]-4PӪ'Mtަ8 ߋkVcGvO}vL>(yIiVQԲ2+굧ƤAPM5 @GGtA :b[ ھ’Ӭm~o7eou=Ctve3/aXURy*jB2&iДXas[)_nEjOuR L~(K& Y?XGU4Ƥ.`fݹi]=D-q? րmfsSǩK{!jzm@fB-)󏿰JvZeGwBxA9Y<ҷ1? >|B/> :[:ӏ؏{~dU4y ҘV8>E\9bS:yn(Om湭#t.,`+˞,EPƿהgVvwNتD'K)㊭D\Tc f743}SMeƼo=1PٵyWFZ3/RFnn{W+&hI$>׉r8gS9-{>YʣaRkɼI|fOWL'f;ٳv9ǞfYPef^Uvf'^knl+?:bͻJ\x|3;شscZ_֫xV,LyWΚt49漟v1QB/L)=8MVKCܰDm-eիVl^ՎV,ѯ}*|k/y.UѤ&chy4)VzG28ͻ2{m(545p#/u`Z)`iWdګ>+D~~M$.Wv>P$OGd^n5m՚snʍ]ځJ֕4 =< c77(iI!\iGfsH\@\LLTv.XC;Ts6[sK_;9^U(?_cGչf$s&maGެL4qQfQ4O0f'Pma'o`Yz7M;. /s1b$ ˎІbIט9-\s,݉ȥ_G'2fBe7v'ssqv8 q>5yl(Ln^K|_@.ED*M1y8pQV;T7[?˄4!7.=7t#fn¹fr !e# 9U!OYc&wnuKnl8ҠǠnjaL ~1v$3Ҕb{edNyvs3'9IN"guO4ϯXvY6$ͨO^=5Qۘ{beϋ`}rPKj kB^$P@R KFoyDJs.;0CF[Ǜ80h߬)JrL7krs/?x}gǚM 2{B^=Bfؕqm*$nOx}a'gq9oTG8xclߙgk rӼK70.kY鮾QKvzȺt9 ,s[6~qMqKN >/Ā7lB~n4'3zF[/,ՀgjsZ{yv~~ ɈS&-~ω] |$._WνzkjYX/9=qpBOD(ivf3?:eGgpSqb)܍^0ѱg%>q8tcֽʰQ7 J(Pcd -}]B1g\.M Ĩ21@$Ps4#0w%x/M?z*ly!Pa8e@ćeHh@kLހRI$r+!^;Y=<Ԥ!(*ãP|(91GPQ%Y1fG&bߍ vȞwrN: l~s@I*")$&CS Nj—T܍HcwzVW{N3Dy;\63&1Dcpi;>΁8c/P&jpDwA_) zAƝ|Zn}O+S(8sA|kDl6ek"C$$0=l?pτz1IiNIht݁7!' R 8!Fn8#bxA\ܤ+π\R9l̦ZZh!t}=ʤgJ}%r_7M "cڋbo`m"Gf@$wWE..IB ')D1\_c83Adb6AP(p]6X."ȩ_;̽poě/m[q;02hyT 5C`؄(h^Sw7ځ/"l۞Gt|&YVFV:5P܋ mqJx-@ Y&x1ʆ%#ņ^o!Frڵ*gDdMXaY-]wW:AUq7O!Y%mLel E)&N޲QZ !rYDVRۿv|ڎUxMTZ~o"SAaHfJ*7 .f{Bp=khY*"S% -LrfiΡnr>"yA,V1D=HE(8:aKyj1IZ>Fd)p}V̾d=^u~LYfz4D)  OHX Ta{IDATx 67`tٳX( ލLlmk[ڶmϦ=ʛ󫸫V[U=n^sDf9<7k-|k maberҺ2һeŸ3'6`_Sh+p=gl}c#?1 T0Y)ѨYGV3qc)?s7vh#ײ^W>7ǐ!4WƥF eAy#а1s_Cװba4,Od_~8RBrlBs%l\BzW\2Yz7&0Ŗzk 3q`Wm {KD)s7W/vb6ısoJ&4gi$du}a`':<`g-%o p4ri@!4gsj$[BAӟXf> b% )4"p._pW+%(sF1La֓u5`8xcc{saW ͑y\oDBcw`vt>?z;0rV,dCh!EuKA%Tz Qձ:Yꋶ&~fn}7AU)A!ƔIA aLĻ2_^aI)`c"4{{|Uy^ގjY@2%b1alr=>+i*cQ̎:0FBu_ e>mˎZ b+*񑩚2UJ}81fB5w]{eL5oҼb^7 wl{T>'7Ym;84cpqd@Q>%,Cr|LB@ ̀ q9+13B3C\H-`ڏxxϛg5{$g8cmol{m8\۶yڶm[+y=uWnU:N߾?'WoN_#j,tHR#`Cȃkbr}ÃAdz_EA kVk(#Z4a8vxi y&… Ê5-QS+hͬc S?s^f8~x Q|gsraifT2'lfsjSD\߷#BD)39.Mu-TɃ;VB:j>kgQ;L=Kot $sr/\L+B??]FWW'b!ǔ"^wj .fceɫٮ4kY}ǜ?)~gEcq"\vì5SA6ew63"}qk;5ΊƊApFyꀇ~GLZWe,S}\e>! If=,6]^\̴HZfT i?I^T>8! YǾ{ӉßNItάyΊ}d晼P ,hL+~ 01k[9Ϗ]">晼P ,hl~9+39+)HElm7NB8 Zu_G$3kUM+>o3[x1h6} \-I;e/}jtάqo9]cajIjD2KA Ei쬩+5gl+gAcu;[2"Df'藳$M4ZsueW]:?8nhExiީ΂Ƥl/0URg]b$P ,hLj~[7PLy*ڋ}A{,bgu0^|Zx;5YfN!|PAѕ۸8^|ĀP ,hzKŁvΙ}IEYyo#x<3ΊLFڑ "'+o3( 1j YuW$Ӌ'GTX"^4q/]{j}IJd~U렇~Z HFxю1Jv VĄ'{ &HEGw+ۋWNM$*ɻ h-7^4gnaEw A)ΰBf%w-OfBU\V<&Xys mBF%vMǿwa8vӼjɹph6N͈٬k'mgg;`vxi^ &)s[YLJuq$a1WrL&҆ﲨ6 t:+ nFOc(o/xi5\ M4rM} 0]Lw3Y?= cbawFik"x9cǭ+A( @'W A!  C` A! CPX| M3#ұ0ea6y(ߪ?7n)T˛d)\h :[a(*ޱ04a~`P8x,0ec.P-Z&FtI”Qe@j I{C -^_ ^.q@0$u8s A7ν4Ѹ45pmg_da)L}VQX´Uw'lQv ;ӯaocA]{,´"7s^46=ٙ݅i3FGL2'fȮt[ &;)ڶ ;0]$M yfv0GOoOGxzd1 >K47gx"br1y =x/aKڥcAYG!     @?w"GIENDB`ʉPNG  IHDR@@iq zTXtRaw profile type exifxY D /AA.|_PʬlؕRjwu/X]RK+/BCv^KO|{8yW~|yP{mf>/>U 4_K^ֳ]/QZb;xz yّx1</z"ȯO?}ПX'F|>u< '/xo3<˔Yg}2ʒUW[}{QveˮpM&ZTjFAoAΓ7ju"!I6@,$b@`]է 9jȁEf-oa>do>%\[rΠ+s@-nAmY; -W$}BV}@JQ7WjhHSđVNlUg>dĦ1J2㲓kFhC aKgrspv+Cm.sEic0,qY_ ksMّuZuz %H/]Y2wu$WEVeY;59v6l{ 9告ƊiMFM* _RZ#:CHjIg}uRkv~86ځz@s-'Q#kB{m &x6%&ZSPӸH |)(fmiTV>+`ɑ!P` k20eٻl]C WB4;R "NK^N(mva1T.%"h5 =_E #$gdhJ>eGj^N1p =S92+zzw??1Jl{Җv2'aڔzq2OF:سkgVIXx5gOm{PUcW(h*{B4*]Hs8jjB ZϕuMpler쩠>61͙UJcf,9aF3A-cJ#q,Iˇ}|7Wo]`Dba¸|o^}k# jDX8J+w7VJ= s ![~ܒJ^M4T*"ѭ&'ojZX2GcΪD'E2Ų03'թ/a}ɨ菰`DUlHO΋M82{e,-<ߩ [P^ؒms8CpCwvY\fb?jH2I=vs}ILR5jgC1!{:K>{"1onbޝ \pk+(fdQ$uRhN1q0Lxj%h)ٔeW;k u5cb ?×}]s>'vaQ8Cp^cq(7bFM(A:$Gg< ijnjBjKVoX+$6;"gي/12{ebjl,䱸9Ҽ[Hdand:-\e90i D1 gBmp s ZȜX{,4KNcEl;'p"z# e[_F 1r4N2UZI9$i6o~|e5N !%Tc{^"tg̈́bEly{gL$]Erؿ(Z"lLRG oԁ*&s=Zd !/{~$Kn.S')m忳x:E=2tZ[1= fgZySZE7ޱR96ȓ. [7c.ݯB^Rh-0 vYņI,~ސ[!#F2j_XêQg[sݜr05eRocPL[;inBb,r?|-Qz|1 麜ݗUҥu+[hzW`b\7 3z>cFc&5 IKlʖμry+5qLC~Pi okh Vc}eN\->L DP K*-1u|Wn\j5ֈi`9zh2i0ݖ{wҕR)M'MYa 4 ֚A<:EOEM۬*,z\}Lr-vntPa31VCi7bݿra kUd'ꁕxj)iCCPICC profilex}=H@_V,"␡:Yq*BZu0 4$).kŪ "%/-=B4+0hmq1]^уBb@f1'IIx{zYjbO$eioOo}+*9I$~71өyX`YԈSiyV= 9}e4" A*J(FV )ڏ{\D.\%0r, ZɉfR8_c5>v Rf>Iз \\5e ٔ]OS3, ֚q pp({ݝ{rqpEbKGD pHYs  tIME   IDATxylU?eU 5(111 5P4GP1DJ 1@(VpQh*Hu(-`M[ҝvgge-qKo2y9~ߙ;r!r!PRx`60ONT`6ˣ ~@ [ 6.y\ɹn9Kt1MZC n#sEfpv<{x~<viQ`Ld=󝪰cǎ'%8f##_rNe=CFN8iх."8(C;gk]`!ð*+/tpMYq0 x:Y@3e X%L O =P7uon= \ńl nC5[ʨ F+$`ExoAi+-/dTf\?PUU([eRfpLAN !h Ɠs[ ^0(//?YYot`}36s Pw0@u=nhqgg B% S\QQhO(ǭgBV +% @ On 0YgS=`;ps~hE ^Ur6}xzϗWp˘8-= %eQZ!e *%tr6U_S_q$:w(?6"∆Pzx[LIIX YiAs2~}1@o7F-6`gq{>z{{]Ԕ? a3٫j~zHdPSVfFdἋlY]uh1FP((~=fQu*o?vr9^FN*`,fBXLss؈<4McΜ9YOx _>аsN3~WBs=#@!Y.]Ǻ 2N@2| ̬SU30 ͂ lCCCogg' @ӴxUQC@xX5҂@27D.7<$>@P|8Vc}J @YёI2_-2j4sƏU ñ0Tpa30cCBnѣGcV$Iߏ |wB1̒(ׯ n>eϞ=1UU1!d`7$jN #Bt]GUU͛7QZ V0[S(fSMOtt7`F,)**05oI\L"NK H rRG?ٱמWvqСs8̞=;->9YXq̭xWfZXZrH[P,c8Fz>`PnƘ`^^%%%iʒoo?f'g o,=RQ##+7(ρ k11cFZ PRp(Uۃ|"Hُ;9ܸ׋a\.`Jt3 vz{{ioołp8SImY% ͭ?K -YYFlX$7[7yPiiiƔ!r!\Ǫ|2IENDB` PNG  IHDR@@iq IDATxZsd!}sHә%奏L;CdYڋ,YcJH 5IƉ C`BB1&Z@Xe߬v~~>S...UvGӦ՟j湆 ,wC3쯖t[}͛w4n|^~ b$cq2FF =KkZ毂x֦?򭳱otQv9*gy Z֤XE6o+𤧥 R1rr5k[7x?4o9YIjAjT]SZ4,(mnMAwj[[KiQ jz7w- }67'%x hQf)7 '[}Sou~ksE> &LhlnZ =K9Eڣ'r~'mwWԹ0Ԝݧ{?9$@{< >U-Ɩcxr^C`<y  FD%hϹDcyNLX wz "IA5;ط|ɸt 0o> nA0 %Yl^xe[=5!?pn//ˏ@osF1t1X@'//z n/*Q)C D ^Лު؝NVNt}7PaO chQʨRXVx!wݚ̟{h}=OOBgELq"Cba g_ g!X6'J)90y@p_p Dϧg]^Dޏ#y*).'`ߺQz'nLo]'kIY? G֏Pr/45Hy 'ӳY1~$p3y?BI-O PbQtcbÏ!i4xXL&eI>ORޱdV 2߄6;Si/qE&O/Pׄ8K B$gThwV[Pm-E>_v*i Z^IL^e"ХzA0/e]jj9K=ye>+V> H൐9*{qV\g>ɇ[^$y"wF%w YW.$: eg?AޏYGaT=ɗq/b KqOH;d]P4PҨؾml]9x2C}ADb]hzlgP&SvE×''+X^Oz3w |Ut{WDS"O|A A1O'3y#Sr}"ϸ9w*{ *˹w"% [N}! #ۇM_CW/'ݸ51HV5ZkLC<ؐsgǥ s <=Eog^UHsFUN]ci.z3=usܣW#%&y31<>0d:SVd!684r EY^/0y>-O'<%0cl}:r9? w'wVC]zz/5,(iwptM}r{>nWӼnG2U&oLuq:Mu 6\`ggCԭΞНsK/<;{ (po+5:\ƩNK%&((|`&%t"v"OT鲤{D<`msj ӉcO30s*L ]vy,{5:&y5GĄ̞EK OQo0r,SN/C#TW Y\\xqȓNOg4ƁHrg8 crOx τJ@0 'O!@)ș3u<ٛ-*ɺT"+f!T̡&q'%d:i5L]x}Iu-"yslxBɬ"^DASƓ{SJ(ЕeY}=p㻹J-,=@!wFF)2!Dr-X\L|q=YbW@ˉ3_^W'Fĝp߶6og`:V@JNp(eJw^i;UHxH^/_>LDV֋TFęP7$ ,ɎIqxKW/=+K]g)$7#cC7&v#$k=Y.ytQzpQvv% @1ޙo0SS<8v5w@@;{陕ͩ}C|.560uYuYUD_.}IENDB`PNG  IHDR>aIDATx ph$dCHyB y{=^ttC|J[`lޭۧn -{kim˂#e;h+h7Qƕ-:qSRw}׉WV]8Osπc?G%u7f˹g؁d4X _3dZxl Jn.\QI6NL $~4>MǞg#u26a0Rd+v}ZW `49GoC |ee̠n]1oikV\6}=s68Mxgogp7x =*Lw1k϶#5_*%@5+ BJ׭-FCyK^d$rBCh MUXN"'/2^AjUiAzD+=QW8Qf8=:jDw8 TVn+ ,y~m&0ؠzTХlKr3WxuF@wbNpu*!?m?l^@t\k[Š)jW~>m\2ŠڕW?`]qΞi{Ʋ" Bb<34ŏ+ `8ZMS8dj}fH'@t͓t3s{VK $]B^ɟIHhq5 +/Sp2JLF>KW@fexH^YmO>]e/2~C[1s%TMyyOa.J< 33Bfyqs.J#3,?92f h ;@ V2'YĢ*% 1K4{@1@,V87H9;7b1 x>GyfPfDё `(;.jxFt1@,g.A/ IrN^y$ *RoЈ% BmS2S^j&  ^byK0qV7 2pH$Ar>,y: V7Amx`8 i`\y< 9 7Am(@J_p[v~'WU6? qPfg:.$d5ћ$$&LK N&HنUЄ.`?`.I/cxJ,<2pp3Q@ȓ &'`l@t'qPfd҅0dJrFX3XIt8( W@.Pdeɲ}hʐfDw2ppWd"w\ b@X1߈eBl 0|%Fb=.q" Mf'>% x=4. `Uk.6V@WjIpz9 0 !1{> Jci8"! ,+{lGXHd>ajKOrK7q,AG~"db|('8N2 ne3hFo"XJj^QާұOtS$H$t" Hˁ?8'w*{qx ͕],9DFlZ6&Awo϶x+͕,eh/8 (cw?ܘxEWh ,yb FNۉq\E+W o" O/BchhCq 4a(5m _m=]-iÍs.H pcf; z|x -iKJA )UvLsLOdkc#V%ÌL ށ<*T,o3x@tPXWB(80?D' BK6:u"4x UOːO"h'+?d͑Ȉ=5!:A3h9RŐAj,$5>.4SCI 2RbC2 |jaNOL: MvǍ&_ @8!4p2L F9oŢDJMd HD'$τ@91Gz!8C`tsWڔWq1Q؄(x_s\1grutGuGB߹`n5vDv2 !s/: tD:Ft5D %osQbvF]i T" s慸v>:AKgdN|bt7͸bã"N3d͝0|䵮aQx#_KK6aîB&73"tiצM6mڴiӦMڃA_#PnT#x?;IENDB`{[PNG  IHDR\rf{"IDATxQ 10-Oe2"<+@ @ @ @ @ @WJһ;?cIEz6ֶm{7Zk#vڎ׶ݱy'z=5OVUsuvݮtL`0x?8}IjW^gAh{ujZ&5FcIT*jRY75k fH$rP"" NDSCQniض= `̵l6˭Vk3u\P.j6؄-؆QDAޯ 0HIE2X ~xم@  }_ tk kD*x594J!~ >嵝; :3hjx*)kwr~n(~njl& 3 A\y 1AN0&S,;vgwި\SkMebq F3 ŷ%d`T*us"C1DB5 ɀ1 O1y s b:a!3X9󰱟?#>Yr$07Hh=;6ށoAr D?@l_%:ff:9^g,MoEGwp=$w#Fra`o #0&:#sm {"P'hܹS}#b3 lt{C |O'LYvAcǎRbTxWP 0`w#^r/b(|ssJ IbOpLg}f ̀MRCH) i|DnA"h ZG؂<+IS뮻gJ&+-t󾮓7u<q{c2/i@k'xw`aזw|A; ัgJCpef333333̼̼XbÌtJhQݧ[WjJw@f9 pzh/Qxeû/vl`:nE ͚eFW>@]FFfZ*" |S C@yl `.)h<]E@c B͡RT!*O%5w L F?3X:;e22vԬ&o[uC@_1~a 5>>r3sHmW6 GÀ?_)@6}ݷ͗փ˙c@Pߊk$oGa!T@H"OA$xLj;$3 cxcǎM"V5U-_5z g1Ew@?*:h0q4mAgQVg ՝P@$!a(~  g=4fM2#;pN3 B!R2DPV,q#_fX58vi'Ic+>ιҭ^&Ct_G;#oQqqIkkBeQ P4Q>S!),e /+hUW|Nt!tĈ2p.ل~DiJQ{$m$p5qr[->uyRv̧%GoEt5$qHyTφ$6? PIiCKsLj+qrPo-h9[_#U&Xw.%$SQFP7Rϕ.Y-gx&oٽ{0.2S%|%y)<7ʼngaa$Nq0p9ҺSzqjW  3OO.2tun F.2|1q4 Qj@nld+fHNxdoQ? ?kJe#~X |]Dg},?{Jgx85HjG+Gδu=hd30:,*Vdj#!VMxZTBag  c7ϭjy_H&prI=AcD r{C#,5#p%4L O{"0h+". }0xUfzk6%*EWS~1?ݽPE#$q 8a}oPW"!{}[KhѰ0=x5DC=08g힣35JV.Dd; PE$xaW`Je_l~qNzn]w]bﴴ$_b_ 1"y'>j,IG]#Am>V0 E0HS!ȱ>89X8wӨ<"Uz-:mDg\)7q F*4ccÓf_1'^fv~7F5'H0r2+C @(p|OD?];LBxӘ_u% INGeH]R`~bqM|5{Eil `w~aCW}I~Vy_,LHvd_ MrRPEʷ4t))JD{QPS$qR 80ث1%z.s'ա PيHq^|)k& ߰EXDVk[MK>q{K>ʛp2x. 4XaRp+Du  Giuɡj믿޽_h/&I~ȟOK tq2}䛴i3; {i%Ē.WBs:Z 5|(5aѬ&$ Ŕ?T Hvݕ0oI2ˬ}䊈 z9U +gT*Oצi6ln,SoY-s7" tsi]5éXwe_)S^~ {))Ze0? %GJ[: 0DWV@j*Vjg ~UdR)+-7?aa_aypqe8GkeO='4-n4 rtOW Ke 0+irkf>V̩z}L]SNPgJEaJ?K&Z3x74,~qO7_̒H@@.0"i`J.8B83%'D(tJ֧Uaer$T2 1YGFi* ^6RYvR ظUFo-RV&rv-D 'kl;=OD`;z^~qN0 OQZ"dQ ;A3(NJD5џV%),~Byа(XiW EaJ{@$ٽ/; ̴ ܷ;+f{Ÿ23uĒ=1JZƞi.ʌyWEXsz 6kdgFf?NovHe|{9co[\ͅX7{eM;z1 >ϴKXOfɫ**> F!9/B:?P-csބM+0Fuߩ4Si~ڀaҨ'r-uzO<ވӗƀnF|u..YEKi_z;8sR{e4ՓWVžLs?l뇶gA4 -K~4x)L] NRM>`p=sju }T]f@S"GBp=o)⏀\ŘB鮽~:pXb8f`7uva7`=P\oxBH_s0D]cafFo*0NCo]>.Vb@8 :F5 4z1=˲+]#,˾@Uwq+ʗ873 u<R_!٤fd@=g@=էSxX`i_Csò`HZ{n@P7^BҧޅiO,/bCu{9+? Phgh@ABuzY;bk1+!|c׻n"kHy# H|i-۷!! @iSotu1`wIפ`:;VF'HQ2G0k4KpzVkX2rG#19@Z̋7;>OU3cw` Y_zxa^P)U@2B-Lj(jQ Ue7_S߁4Pi+Z=mW6֣@ jLPo \y'~8K)"3Ћk˲ONIK@:};~KUГ[ȟzY?"?@i]@Oݒ:``R?9vOoMICRknOp(7(gC jJ (y~S׽#q'S(9Ro[> ļWG2s_"k{ń_ۈ9jlCE!̳xaV=Ʊ9KA-[(ym\3glL^ k?+}Fq#BHAohNC,L(SODA+Y|X>y( EQbE׽G^-:+H8Y6f6 !4ÔM &O z-:\IصO<&YՐ ĤKPnD!Cтsϟ՟=td8Jn' \#p)8s": 88È  zHv6!*iRB/=ߩm Hr/h{ m-!-ϜO&̹Bɾrs{;f^Mdr:K^x;TuLDOqw2}v _9M,U:B6Jڡy0k}le?_7+I R1? $Aar`S _1%쩽Μ3-XǗOq4baF_ueۯ1?)떺lb 举gvBjbZ5}(kY%:M+T1zDsh w/% Rk-PO"|Q?bo9b}p1 5@:ǚs8&\ h+E䵪*ιnolu8{>TVb]Ʀ @sKZ1)ğ1-'ЖǥZ`T:* yCu(H,bJK&O.nz_x;J<̎ew3\-{QtٝEQDȤv9EV(#sus NGn/gJJ2%v]kkO_#jKdM=IKh{t4 ~z]IMd}aRQ#,B'漆K eټ$9( %ѳx]\)+uM{ X6Qd,>(]veJK}Ht3,>c>oPb>oFIQ`$U$Ӯ$qJ -U>Jз #VAjF@*b\ HmyveX1'?:GC(CuQ_Ѩ.8{)c/?~G^+?-眒Zǜ1~RZ06$1xp-iIJ}:,O@v_/rs.];V( \,5<0^F3SAo[woys VB*tӻd~*Q;$< ڀ)3BK' ${u ^簾jUMFeX*̃-؏j(i{86n1-g7#G!h-ͿG<|@4KJW n4p`BBˁ6Me\}\VֲF$ %!QJMMJpF07HCm[, v0f+R hBHVZJD/(sZԇf'pk'뻽ph^9}5T.iX@< $6)$֖a*ئϖ/5) &EG_I*`"𛽸 H~ގ~8Bnb DH* g1g(5(8gRd8y~ %ܶD`:D/UjW!M]eYĴZX0c,x1]7}YRe(8ҌĽ7UR/l 4J*+mV (-yCʍŧ4T{xoaU*嬉bB2١X% LD %g?rX1eٵEQ.n.{Y}zѦ6\X9/r*yPĵ,+ F0i h5 =P/\S7 =r=(#0trx8#4ɱ]vG<Uvx!鴜ENC|wa3#3 ~ ͼ3X_@2j OW% %Ow!:˃dP?zͻen-qɔAO<^p1Jܕ .!xk'~զꖐk0 `0zЛ^UFwpG w\V`icUN}~@Wϟe 2X6wq>~˿=I.G= o˜Jɫ333522~<|^0 h@К,^yac]K)#I|nD 4,qkE Z5';6fmѩFM'p-7wJ 6bē8RYh4w4(Ϳ*e>di%0=tb`|{n P/}WNF/x;(<EH&\ G QdۇaXf,}nmqMEQNHJZγ\UrQ4 )/ ƽfus X{* Z $|w ^U>g1|n$nڠB`VDh&.z9w[#[Y s$ P>^O4Ƀ2Cॏ}ʭr+uݜk758q䟻~]$ˬ?sL;887M%M+V9`7ĸ6[z@'C>K>V_z?XՌ:N7Յ̹CCgg(mcZu(?C^N{_~kL@ueʒm*`sK/rAKe3-]EVx,q,v#n}O7v I5E(!pG֘ŧTKxP(QTVf_UXp& B&] &?ګJ@"Uڽ~HnDw_}ѶBcGgÆp!YRa`UWPHf/08#8VJ@[[[4 oYL e?Qz8ISwѺq?gakً`d}id08lei?{o{_Cm-b)3w1˓3[~#SS|S!/¿< ?X?4  ^@[גN`c? Z4s:{eYvW\߭Upv뭷+0; ЂPzQ2I汅z`2`kgY:30*Q;7?muDQcGp{geنe,6 *L~qwdIJq0(*vVV ޘ2Io!s#\1ɕNЁ#R'k{σ.NC?os#0-g^BXCeFk. ݵ >e/ #+Og)ޮIbRKaQY˩fE[tO'@0wG[+ԄQ޿foCbGd~XAT~!C,"p5A}3~8%hHE.^G+zKɿ!xlؘ9wA1;din,*X$IɶT"xIUpa- h t Ls]ڲn.0er u֣Zf94"Չ>a3 &Qh~}JEQs#,%?30ȡ{@](&Fm!~.znñj@5m?/?Oom@atӧƹB1S[u-? }oH5ob9S/?t'c?1&ځ ~߳tFBh%7_-eR dJ|_֫E v^F?ozA`ȲP ]';T 8]D@/J:f 8Yt&{L @ʲ&  -i|\oL HdOM4\: aw]hG3kǙ?N+ %*S_yޤ258̿bi~Vu+5)6eXUQTI{.*~ >B?LM=;͙ ^~@2E" F`/8jJi]V?YM)Uod&h@^]v5z_U FPtY{4j`Z<*IbP6DAg`u>߰|6ZҋXc_lXɉ@ H5Z 􇁽''ڰ`05NZ/@ú)Z{NP۟8Dc3S}Kgr-an*0իGT50Z$aC~CH?ۜ8ՕN`r"㈲}5p;).c(r+'9OK%Zm|RX]<8?7Z a=?xaåt>o)w+?HQހN "o2 e1B(3'y T$ IZ,[߹s็;d~"QZC7@(XMrRؠℜ@O@Ǩ"rT!v!AUl|n+`V5V;eM̟g \:0Fcoz{ߢ~ߴ\@լ䓌 #bc\Sp{j9G|'>u yk0C|H'lH}*,,U?tmrKcwaakmYPP.3kWzʵ`74 "z=5?arIe-g^6*"f/y`ѿbtdj-pS)[d` 9Ho<qPEX'P[~9Kw~@`g%W`\BŶiHWA$%!LtY7}+#TKlIs:%4f_0U#_R #,x5Y8tm* @+fy·>N5,-q'!3@/KU kֿ-sXy溙-ʁbi(4 B{}RIڶ)]1h˧yj9 3us/3+.Sp|ƹ_ } Rؙ֨SQedTJ n>?Bɪ7(8%|VqoenN(\]I *hړ }h-DتIR<)7]ܭ vYvVBYg$G\EML+aNU^Dɰ՘gOR1*!7D#C~+Y*`݃{@߀|w_vJ= bK~aO|VAi5NC@Pꆉ3:`ȎÁ` O|gKC+5$u O' @=UfޣD)'}ױ3=5I`lV&\0fs񶿗ȇ3n8a/qoHe߇^3}uMm\Bij(&Oxf8Ɓd &YR^U~"[D&b`\O 3NH9qKգլ})sSE.xs sonR7(0V+uUD Vby)v{rP{;RkKΚSUOC^/`{.I:hCH`klת ';dy /YL93dJFX>س2ߙKIUfPkv:n/zfﱰJFTJ(*_ R>&LZ!Z쵶v<=Tpo3["8E"I=hqD%rg+׬SV(UPg )4!+9}+!{}zY Ds ֗aL여IIsӸqeg|M ` \5K`fcJNob齹g" p)Zz;.~7U&%4S$cWk#Wh0~!Ζq7 hd.Ŏ% N =CyX ڡY)BiEzƘaW$8ͦK .%җyMf^7+QZ{~qiNoxMIi(#ǛLRD9g4 0 n:`7‡GqaN?6iRe Qs'RK>7+(:k@m#$m(&>$mk#ŗYiK^yoSϰg2d'L@ l3Y~嗰ub3@Jƺ g+&r@@<\cxlO)Z H1BzT(+J` "\jA(@#4 T)]k"5ϟF:)X (]V3:?eoV1?zysLf}lS/Q iBWp-$i Re!("Α P<"u=._v`$"Kەdcm E4m"?Tʄk x%XbudeRw0[3݅lSdd9pG' }zQ&Q:\>~U(J`(w@Jܥ|F4(po#MOON/y;k#b]AģxI*K !ziaECsxV׷>&&ѻeT$5+1K0""G[.?*4{횉/O6T|_!7vX=F5i7+;~ %`ӂӯR^׼_ "!]7nT8g\ @K `gm]DΧoG$ 9YF"}0Ӽq–̱%ʧ7*'_ͬe} g!G,Gck !TnbrWٕ{+ l!H?_E7GLD~0 ӋO6B^@M n'x/ٝ4MJ@SiM@-:(c|v >#,=%?R]!u}E=ġMVN K,Y-Miv|i;)kT[h5bKk Ӫeo- s5Ć3,?evO*5Kw_zf@wM? Eӆ59jfE< fH߻-IuN_J 4я1sהۦt_Rw=z "Y +E8 OL s3xDY A"V>f[ 5 :B13w9J/5գzRQX '46"gq{'#h"ͫϴnry6^@V!߇_rP=,^E7Bo@y;ko qXţ}l`-%%zW)Lj7 c7 {,-Z%XU _I T Q$˳Sn޳b:?EobG;h̞`7Ƈ֦Ovm/Az*hsi֥և"$³zKľGէL^̈́oL2OW|#qRf,uoca~Zژ{~2H D !3߳ :T aO8_Cli\|W|:%& B %FNj́6e{Ύ.o۹٣FP~ID^lqA[Ucq9>XGiI>iA5 d?#+pg6k^UYwoʿf~  [g| kot-?'AVh+*Hύ zc#?QeePRDV h p$3I10*YMa/:#؍Ȝsu1ЊXYwv\7P\FIY1HCl{یHUPf`m.9zr/r g?[?E܄B\p9.)Y R}/{`zFɈ}~iL@r_ [zQq־-)m+n`+LgUaIE꾾f,G0aI\2$8# ,|a|is6YB=KcTpSG쐵S671P^ (gB$ d);x=9LLLl}(׬r{&},א0]zg[Y,3zUOK8i:}oѿӉib,̽R+4U2 {G?K,IR\s'K{lo-'"6H;ac:BHhNꮛqn>233s9tZE˯a.-0Im9'!w'@6SSczP9̆ZE "@ hj9u۫{]k)ρlA{c]hm< {Vdp艟c˖IA`WO~?c~͌Yfl?d6 k8L]u*5m8?}tnDnl_UESeY֍.V'ˆR'c},S[cg3T#0 ϰ˃`i.ZMqչ/Lp|_Oo`́eYRϠ YcwS}z=0{&c?YZ;&VVYcO{dLS18Zծ=׳~ߦ1is[ym-rW',:O~e>JЕ-e٣Q[]4 BLz(*0uF}_6>%S ?Κ5Sf:0!fI%Z3U2;% <=,Kzg埆?}y((=E8s?z 2׃`b>db(6{N)̜IV&X[?$P͆8RReoY'tPg11J9@w~HZbu8r&TDCkck٬;p:e٥M8qU7O1bX:NVN3IKGVfƜ$l cNUr/l{cN=KzQDM1h0 #`z=sb/72`%U?_ >u mJrlrYgY]PLǭ8$s[Z\p$yg`B 3Ai4x|溅y\>} vqm{.⑲,oVD:(C?wWp9$CkB9mWо9 @z,B#RE0@0S' ,1ʊuU@rmJ;$J؊s &ʖm}򶚒`ԩ_.3L>hebˊtI$o[G#̻ލW)eı]K\H;v,[ڮݨ1Ly0~]X4 ,k"Y1=U5yԶ9פrP=KQP1GƼZ.3Wu*Wy߶Hj<TVּ~tC鸚~r,ŸvPac|&%@3m 8IΞoGedPז_D>gŇd& bmۧ <q}Jd&+sS(e-3'`U]' Hm<<™DW,,[vj5TT56锛OTo/ HZ;7I?I&Vʳ`Ua_c 1EȍC HC7 9,cxnFV .mXygs.=؛P{6 Y7g3GAAqjLpiFPEhc70d77UgXy(HUiGg0#$K0썯$>;wOƤnFnnqy0y0=1^O5)7^3瘦 #@P01ͭ BF8B-Xf@}-nH6c̉g\ QƧ'0a??ԡDԮGuBtc)>̈ 4]g9տM8Γӻ:zWS)!S$㰾w4ove]D/M!@<&o[\U O0y=,<4+c21ڱ4OA.bFę{)ϐ> pe$JBzLAv=eC-g2(di(f6T:gKZ*v  ֋@EG[xxo-  >C\B5!g7$Y -[KJ:iVβX:qPۚɌ^I?iH~fugi,Ϫ[^D7+YȆ3>WG ugo[@fc-!˲>tЋ1:D.\ OD>zY-%qC\^(dž6[=MRjObjgdjBo>Srh")5Ԡ^h0f$)~DFЭRHY@eaE< SLG^M uè>ww,xÀH_H60Kd^i1RA#eu,I؍CRJ"3G*\PDDU ޒ$ӔJ3vɋ{i?WC#0m+S~-︁7?4[$cP/͘z(HikQJ >B! }LjϱH`PI2AOvlRkK+D؛[~fZ6ivo` ,FD ,!~\ӛۏbI<Hҁ9n $UᏖw2NWEL? K Ӗm@}:KoM[o}ւCtBI qgB*cR&!P e!AhR& 3H޳j1b&zљI5uw @kKcιE00.)۷xԴo !k⛧cڧ1kX3ơ"P&Rj8ɻlA^rC*Dk^L b9*wq{2^kaøfotafn(8!ci1S׏zI|Z D7Y7nF}dW|7'KSPM"^PD4. {V=MMJ"P=[iY(MxVɹ%V}\3XO@K9n^zUi)"TF' X:xˑ|ca"t, )􍟆~=g(8TMVSJwC5.M`#V!4 z}Yq>~oK+m|,#j+uk~_Ua}37~A n"O@:cNUWh .9wA P;7ŘCLi,>|C&Zui&Ҹ@"H+@DB; h/sؔk)QҒՠ1O}LrE?m;)𑹹7fYɱ+1yr6$lIn,Qn~QCFѥ7W[סv4uD@[ "}'7BsrL~BEpn"s+C\-Z.qyǗ]vOV.D/-Pu ն&q Cs'zh jkS29n-[aD[!*`4#W! Is.(u>e )xeFgҰ9-tA&ؿ1iE \Rܶzȑ,?iO{a#LZ3G.2y*6!0$P3%0BMs\> U_J3Bz> '5oP4rT@oQ Zzp/g2Cg c.ߏo B,F%y_v@*inң=i|W@W ZaEp[,Uֺƪ3OVDAM4 mTVbr6P|mw|n&ۋC`$JF[?NIi\K oF |2~+p6 j4(l2Qt+^󞍸q) 4&N ;3Hh%MthtZL#mƋHk{jcTn{^)D$"c%|{~Lo^}/$d{u]vܟeYty !s|G,c[^Oy筼STn%%¸6&۾PamKmf%[#wNvN lvbiJM_Àpm9||jwb _\uUe\-q799q߽חeyMHHf!dB9:1y簴'∮0$ t(8.,V8ct_CIKb7|)XϣYU5sI4D$i٥JK,q2 Yzf<09}Y/zxDL͸s"oo,O"Dt |{kz:d-8RТ>L jr;MTRlC$!@ "FRUc`?Կ5hQ pbϦ]n?j7tUާ^RdZp8i?V4h x>bp?2s+{eG8U X;*(8t`# @TS\kW[ۧ"P4( ONQ6;f⥐Xk)Sax(pCExDU>GV\qU.q/)qF.XTxMM $@ìg=C VKJX԰ K-170KUqxڽ t)\ "e%ba>\qJ;|+%{7DQ7z|_s"i>r/)V{?eY.Eq;jOsSWыJ̡&: Bj!7U*+UgsZ*|4fFvS`{'d gOEcBbJG~=.$I:؜DP7OC_D?tג|cb{}~/˱wY.:!h__~G1Q#,o H&#i˲ `ýBLj)|ò9(dF:Y"].2$WA(nUt3˄eIqSz%% c8tT_aApS8?6Oc:d\ѣGG_|cW/M v$??=:~jYw6M j tXdH6HL}ʗvB¡PT\3ֈتLa pK[GvE_!]~Yjk1r=dջogSfܰ&m+ֽ.睑,E_8w1VԩSrEQ\UhK =6!Bpl"d^+&XGy}̃hX&xpv,㈐\y:^׎Պ1}W] ULm @ X+BWa+z~s~rnmm8 jH'{Ox_({n Dey;ޡ?3?Sb@Q?0p7[2lti_>N>~VYc\yЛlAO@JlT)J~n?$I^:F K-6oL.^~WTf'c~{c=QqjT ?Gm5S7+js>sEQxUܿʲl&SRnd5\X8O;}œ}`ܐ{1$aӐHc;B+1ר]IzOQ}0.ddFJwuSe6˿T_#??T\0ws/.".__+#P .7㢡TuziV`'(rZ!:MO2C,μO>ʩ-o H-ܪ[B 2E{fe7BҬ^iC,65aw ~5!09SX8E=A6ؑ'U+|FQQHwW Mw~kF7c~\9x ;4 7D`NOhrc)s= ̺=ȜZEDkn~k&{uDniIUM/p" r-X9{2 yjjB__gy__]{{:&8q bRI|>(1I(K9_y5Q]O'@j\NW"җӬ<d \q)" Srbv#bMM9Oc{:mcgenk?)tH!6od R_ ,//#<\7~ h_?o~i?cygYFD[P5@C0HN#Yހ>8gϳ׏,UVOI5)S"o互 >RX.Ӆ=snaOهiDz8O:-񯅟(t?߿Eww%}_u۬q$vgK3d(E#x;9{/PDrBG3r\P^~ 32\9fB 5 "fڝM@-~]CE#N"Jq^s'gex+Ĉ}57#|:[ϖЇpk.3 [<Znan|_#r+^Ee_Ã{/u8KZ7`:jɏ xL9㌎>efq?fʍEk BH)XQSm' 5eSBLM#^CD~ ?D\{5/cȾZ~ʾh\21K'7>vرCQh;{nV;mޗ8+qc,n7b-Wx3LH`v^.0JʈtrS=ps̹MEs">אUa$9{m\ Z HKe<=V/W];\O(dq(9eu:;0E?+G-oy˓1?ؿX\\ lԉ~roGI 8=Nyuޏ^'민; .Uu"e`V!Z+E2Ρ/vcϐ;Ō3E/%e z$~ZДK})EfODƂ)8:&`/Lm>!ԭ7Nf2LV= /rxʥ%־b1'@cn%лJs Dӄ>:ÁC1s 7gY6]+ Ѳ}2X-EPd2Yyǟ_&?sY7f%C)Ƚ2p>UѥgGD3U{B(#X2cUtx,r2#3*ӄخ;DHdz~7K1/Ν; ~*Vp{nO`)=Owp߂^|$!}w|gp h0\뜓h&Vf1JPFP@E.~SVV6<\ 8@4 o"7-H=P }&^^Iou?K):2?2EHs-9͗ڳ1gcZ/Ϝ9SϗMB!]q@|onߡw`A9-x%&g ;^,4GM }ĹZ"Hz90BX&tc̋S?G/wdػ{gtGwֽJcѹ)dng!{PEdzl{@lJJ,g1EhDRVQ] >77A̲5qJUlڼ4QED1>bcD"4 RlJcaPon=J2As Y4qQ3̸227aff w^W)Tz tJRӧ{ZfM8x_ =wzw;pSo f"5&VF$@|㳇O ` ޽{ڜ9svh/ kgAO/ d.!صN䠹vzzѰ}0#t[`c3oHwwe|ś'du>; QV{u~zq޽C ,Je3p?9@~!"4(< dS+ZuZ<p`B%MT4{ӦM`}E[6ze2@blvOޱs71iz_P]ϙ!/2PU' g-geɣ]p{ֽf@j۵kE-0`,%JC <0%ްb:u?=5!{&@]Qd5 b`iѷov;v6cƌ%z@; $&7}֣_e}}:p!8DDU@ )OVqט 193cu "Q@"!H5'8_<}fߩ"yR\ԀHP>g McGYfZjd0%"RQ@ի{L?O?}o_c'`C#'H^4VHK[N4i„64Wޛx?=שNe H`^d@ \j3p{o%`N `nzj0\{ &Qyح)5 c5)LP^@eԜcza`iOP}N( Àx .{8r琠(p zhaFj7!5@(Uw ^=ob% PR`OvT  ɺtZH:ϝ;wh=Bf,1$1 0?jq^ZqGd״EmwpX~)%w4ަ)J`ED2L}-ԔFGQ*1*2=8'МAڵkJv5t(=~s@ &'M2L80a}⾦4 ۖ6@eCF=Dd0HWdz6Uv…QUl>{);σ@L9 XR$1x h^E!UΠ_+Y`ӊO+?Q'Jݓ/>}`''C4X @dEMJR=Bep}E޼g DU@1Z׍7&~Au)wVcU1c 9?>6!Eszx k@ָn@2;+R D ]t֭;D 6zmV2Tfe}<=|L jy]~EqrYQ# '{g* ћ%ww}]֔Q `_ OA%  lzrwE074elsp \e@a{=Q8 ؟ ȳѭ?qqX (/[Mc?kciFMKuOlyM>3XS<ص8|/kٶqC 76=J&7e]v=hP9qi\G }遠:>)O\|X! HKM@:"ߗ mͿ.l_}!uf `ٻ1 ' vD1}, w'䢯2b p>>, J`L=6IX6ov5 0=1]|%:#?i3<%cPgAq=|@= څ7kH٦0zIao%>bˀ.@SPlZ>5(=ZkG*'nxfXQ_$(~,j }~#$'@[~3^Y-h,(=AUՇ>9Wow_ƹJ0/][o"bзSP}+Yο/=^ف z}ߺGIT}&~tC\d ):}hgvN0taJk j߫N/SA .Ǩд3 `fg+__mGv ERs_CrT}̱4@fbK;) }8Lǿ4{~{.n)nEq:?;Azy93a&1m;8ڋC zW-xȡFiB Z@hG E:((@ϨȸOs  ȹm(p5:HLp 7_*\p_\PH}{/NSf#:Á("A>|p1 :X\ \}^RRWjPP"Y[]b|]GH؈@QH~}z"q Ov-`!?@+ ޫGRIENDB`BPNG  IHDR>aBeIDATx  ?.>$˒a,46Ckcm۶m۶mڶm?qE\WǕp9\6LQ"qI8GP!D7q3 }^wq_V8`34Y];O%YL 颦,츈XL-^.z)2W2^ǀ&/ZplX;4wƱH͚QY*^YI^d$]Gm VV,l_PNW\/v%| _;a7<?(}ћ`/)bskU1yExs&Զ6tMkקNQQUײe)b/ۏ4;',z lc~ٷp9<=E|$;Χlwe,ק$}jJ.'Fg:J)mU oUMy[dEaW7=!jn˾Gu/K0XO}O=N ז+u_V亾W91Y! VhZ􆺔yiaaQHmib&fQ㑵g䠯}З_a̓^i\oSoW?{_*G H:Ÿ(e)!SU3}iF Ae1b4yTuM&#Yɲh:ض}.RJ%h!q +cC=:p8"- z/t9^/]2L|u~?Š!fva+ֵY$dLWW!k5?$%Y۲eh2E, mB0 I 麮b1w>?=~_~2c{?n;%p>=Ή{}G"\QQm/Rچz!{E R׊!F׶$Y:APc .l%bf}u]m#(dQ V1*>I)BppOݿspb'^o|Rdd4 O5)RFFx$IY}(Ų0N!)eْ-#EuضYm۶m[lYyRwS}sz.\;"Man`YF@[CDvdg]JtN.)' A etyn qs_oِ Ex(YG|?}h9]["@A#8͊ * 7}_ z79]7eYZ,+ IwmF<ً r,9xi1ҧkZLQ 8<(m#霱q5UU)ʇ@^V0YZFSZEkiK@ZDk0" 8xGGwp!bk6AՏDPO&M]-<8rpC*s:,RHttqǍLͯg∏4p&!B`3c߆f 6"`n. !aH2sCG'A'] ઘNﯱZ4Ie\}*aYN%PwDL c2m:Wp(5c}Q?=tu0bREnR [)yt&B#*ʉ,lUL ,Gf#.apl2 QA<}wbc?"rdbAp1쀾$y)<o5q 1zf hV 7[;` xȶ?ooF7U&%pA bxzII M Ǖ,3wG2EADqF8)%y#+@G1(*_QdbnLd#~/ .c](yޓ2!SxȂ]IxLS܃66i;h_2E薖/~3& Q/;&4hp3FRc(Jn4@'>?)%RG8JőS~7bq\ Wn=Kfa@d]SSO1ѬT k0ImTTB&9#dLPg;zo$0 OH)# r"KRQmG0IN@dJ]|dc?qe3lʘ ڮgC⌆.㒥z1(&{m;Ɍ8;m:XyX/c~9tkA-ڞ}k,E& àz6S KyD 18̳~r"StNCkhYp`r֚ .~`'aߨ{<?fl}1 ;S٘V/bGڗY,[Rp5J}V 7?ǚ)^Z1@R "5iq%nw[/|:^'E./|?/|g='Kڷ%FQ%%lt>z/!8 fͯD 8aaGd.n6yMtE"xyꢜ +r|'?=կkk<.(ւJbW>nёw@VVkZObXZz|u\BQdao)Dz6:xLwϙLp=Xf6c)5>횿pM`Kun1k8Q|)R5Rad>q5.[4}e/C۵FɜƜqxEA%L뒡M]G.z\&La:Ft("_;?>طj9@L%\=G%#09* 3a žlց%ل#Sj_Ʒk+~E*j񱻮yMη)cW6afakixU_:t'6hK m,{0G´[Z82s4?8oYT3qk͑) v(J n,cñsfw e7N `yA`SD9^qk1 EgrwㇰW4/mV8oPTҞ bi(]IIom4X2?;Lb`c1/c (p,gc.[D ɸ "_n‹/?S0Jއ.DP1 JϏ+j͏m@r[ /*/v({+ - 1)` 9%=noZ@+EPN觡 ]Ȭ;WRq,yvu9 l@suU[=zz=ߟ;OgzzҫW/s`Gq΃{PӉUZ)ö+Hg|R{9#ESFTfv.7^!ΈjѺu H{wKp$ }ۯTnkG_GC5%f=c(39qJ$׹(iS-fjI'ñR{S{Sk4 ssG\@C0 ]`ێTm6%?(`3(2PR0\f?F QGw~"__?WJ\||ūx+5stDKx٥11{kktv A `O-oCyo(r-(eӭ8r,ŴωfgE[eki\KG4).u5H " nKNqAƷX~E)߅ -O8c痓\ӕUoQUJ(ReL(<-ab"H%N^VZot~<[2dmVsϏ^pE ]V݅LDrA> %|5 )XDE%*NAKrpqmҷ>ϾNprCfDG $oVܮLVqX!XE.ɖzTdʫJ\\ހ6X_0(’5"mtc8p\ɫOl ٨$]RcҚ{bBnH{өeyED!b751- k37Z³72!{] ]Khۈpp$R6F3phx OMjHy^(~{㟼0'GhHEf /Ֆa%K:pYɊ8t*i$yz9J=+"A+>r1@֗o_յ_";^")$chk+ѧ<|P5$@.)`ڶlEy/U l~ }.sr[1;>-݈.ξ׶)+y=Flu4F,ݦ \؏q\; +"~_f BEJ d1JtVmVfZ 3+_#^xy#̼k Y@ zFl0;#UIrX9u%T-cpYYF, x4,MN j/C\Iޠ<%ɫ"IK]зV$2ZJ!hj/T 7tWJt=b&>!SjS Leto L\]Agkn\mw_:}30<+45WTԪ_fR`g&UY5rze1Hx\I{51kuQ_~Z ٴT'u?kޅh ߣ9[jU>s-$}oulYAeLBJzR~1yxu>|`<`:ק}%vѫ\e™\^SƽBQ_3nCȽR240+`ISڵ7QTozа]KZba/Fϻq? X> Jt)PLtjWFk/5:5i/+˯pvܾW\! 4EvG~F^èWj_ꪝuv2P4R``BXJi}$&`@@+2ȪnJf5#ȑA6 D$ lۖ>\ R̋E ,PJLJr=xlz4:wĐЩv2b_uŰ2P=tG#UN?ר_D vs1L,TI2qFD 4X ҵ~MNJ?(<) `q utNjg-֟0ЁgclG۳%ꂠD+Ӱ_%ymfT$[Y7+}; ObŠbMb|a nvqY L;JWMT9`\DETJA (`8 :xƿ[/Q-@9VuШ|hDl6*`(40S\df-"E2Pi$N5I=Bfm޶G9QN`R~Jg&}jPocL\>z]!V}x2I 4L<'كU9 &Ql=#roHx:$Gχ؊͚@o@Qfec[W|2ԼJ#H94HbEH$id&(QWض~}AtN|>v7IZtۦj 8_/I !H*##Ӽt8X~|SJRgz*XɈNL{5~@%htTet1b Vx L!8LLePCuizx/J"1Pa]OR&}n(5Qkx'Ԩu~{Wvu0f,d9 zD!O_ å" W牖IZȒH:42p4 Qp(_+{BC&w/Q;5@gbP% (T+ƀ)L"Fm1 j%V1S06ۖf 57G`nYNZ`j;l3]A .;0XVE[͂FQo:XV#satW, 1+Yۿ]'?B՛@Vh Ȏ2!KŒ1=uLN pDRAd\=8cmZGbCTݛN`%)n}2{B }b6АdH9/r>@gH̩|m@E8 8e!Fjwۇpу\ :~WS#gz*Clp42 ٫wN~yFٛMԱ%l 8Ꝺ)r9B]g|'FJ1|Xд" d쟣8ΈƷ Z0<Cljl ˺ FX2 ',0|@K:@IjqKV` |FhRR˥G䕯XC?C(yύo$s/鋾YzS뽻;wtaou?z4<٠nj(ܸ:R_"MDΈ^EKwZ99Zv0gۼ5?Ѣ+jHmZ@%#5Qi$gTV9{LĤp2SXn.I3\ ~.D}??=䆫u˃ .7_1ӝߛRCy[C/%/10FV07qNvVo<$Xo Ϙǣ{39e~XG_~'g-Qy`t_*#z@,ER*)~P ?PS.!;HoO LlVbkN /^k+eRA rJS+iW͖ڽ+dS$twrh2=qތ@7|Ƶ~տD;g~YCkD%gZS)$lJ;MۿT <rsma_*CƣJt3dےP\oXgy<@mjÑ6^(8v{ʽe,pY.OƙG<իˏ=sf4b"IϸI/;Z/caӚH6j6EѮ N(f b-[N<amEߞl e+Uq\N4m"HɊkt) !F5޵U*h?Fiv]Pzd+LR:`+1~V0Rsͷx16Uf] z뺦_[UZXAC>Ibv(Nxl{O^GV1?IE4>󫾋;\Am6 \=^> .TNSri{&$&#ҽXjM甤ͷiBG?@¿^w=o_e֮(:8}] T2WeXB lx1-}n^-#^*߰ʡY CP20йZ@>4I3&:qBle7twOg.~%H.?]o%H0כ5&i>lDi]/G "yQx*'}su&1t ݂a/pXڜeX@+ȥ2hvν)3E_ jT(GӉ(+ @bJa.; HͳR ޠF6锺N&a+OŒ;u82VjKR$Z]ùHH<gE?g<}?Q? ô U>ޢ_)+*e5-c2Ϝu. "pon\N^Q .%8|)%'o@e\Nb` F]5?EhT&zFKT!b4=Q߽ttBRV_>/Vr\ٓ-cR>tPZɆ&ce$J0NF~)+a^aQ0Q`L U6s` trPr/`~Jk94?f@ko2FY{iQRݬ:9zOQ h>XfTX\ѨvaLb_zÝߪSUOq`B9iˁUv԰_1YT(W[ M'iZ|Pwck wFOFz{G!RY 5fcyvVTK7TG7BXoނNo'ˣ+-d45l ېl! \:hD騥WAxU< oHy ]JIُ~nD֠#@D(M5*#įX; 5Q̽~E/GM|x3 O+ToLʡa3 }9j29I*{FʷslƁf&f85= `Se`& "=>4y,++>vQk$-0g[qRxX`|`+^h l]й˜VIQ)'I-BsCo#%E^I@FB,V.nB ㆘"R/e]h;.O)'HҔ"FGnO92.tSBu=IVo1$ǿ' 0vzK7wgoy_.CV ut*x,`X"[Э<-W}Դ-mbKfY"sDEy̘4[Ϻm1 A8. t7*GC;RcP '쭏0fӷlt5?A/QRsqK~/w wdd L^T|LVU&tk4t+L0PsPM-%fIOlHh68u(io`m;lRmX1f[p#gDO; NB1.ߜ@,V0&sLLRD&B ~8R\7&A <@S|]}Xc%@4ԍIy\wmqS0"QK,)WLfCF m;#Yc6D&5ifr8b:ӫ0t8kXNY /h]8/aWq.Mz!_,=q: ntA"9h"kTgE9yoD+AqÐd 5h8RtrN#^&`CHkb\Y)KA.=uୖ[>c+7৾tX?6CG( wP=F?Y0de\sz]wYhDM_.~[_ٳk휾k`5 |@oߧz7$Ru)q[𳎲n.Ty""9WcAʼn /weױ\c>qxn!~܃}rZZQRoƑ&& W #K'pjY/9uƫC4nPs^L^j?f^[[ޒ|<"7wdE߹(DOY UT>v&'Ժ\1zhXrIד۟8M}Wy#6 'oMbauwދǩoڽ_U q̵̛9n7t W˅C :{ON}5ںKzIۅim]h}ٹ{9[k5@^Ytšy ||O\3*ƧQK4p463pte]C#_Lz^TPxť"36X & Y:} Yf P}/B= Hd@*WX =C=f̹XҘDXGg_k$*= BC8DGlbÇ{:z$2 ::uvdgWȣnE?ˊSuZڠwCS vVqsBز-Z TӜ_E%J*.,* A|8H 9y3rg썍M277ѩi2rA6408%*6JDt\" rH<*6 HC]ؘ2Pd kɃԑ\c=fA|8)0&8eϚIENDB`ˉPNG  IHDR@@iqiCCPsRGB IEC61966-2.1(u+Q? 3Mͅbi\mbJ(F-i 7k?6oﻥVU낿[Z)"%W.\7ڒ=<=y:9`dnl.\t ;Mt)::=}QgYy)+P(gZ~\vmw=n|\%"}&tNlÊHNNYjlQrIHY"`  &bBc񽯼Ue|Kfn89q s ł0 30Q"~qN9}UlاDWAzpù( #rA @+xU̸KՊ?5N',7;wQ xdJ"!ssgᾚoF+j"\r_{3rO ' nqGC .&"\!!a9ȔEF-X 5H >_blűKw7?!v-!eVpi&fhP2Dq(vh Ey’n|3Qܫ2nt8稵3:  $"κ}v*k6Օ&nV`"RQ"hf`vrҔ3ǁKwפ9@,ޝDx.f(ۏJ^s/뫪*iR7q 7MpXbjn!A"#eg{XuUnZ[Io6(ZdrDW|@MCf᜵oUAENP?x<fdfS 'M&C!-F@`|V|}p$^^Yb5yݴY4IzF{LMl0*25e1&iW+?O}KY}\8i'i64dȁk^|8)ƾ-?Է11qKOU|cӴYueE⽧QOe3O)?bf-#;4,+u >|:ܷۮԵKV76s#%|ޓ$ &0ϩSԖA^!@)Ƈ.w0z-l~]ռv۷JZ3i6Xv/7ib-yg6k.]Kaf~LvR7]tdxG1$uPUf `ڻLmqt),_m؅m#ıhyuըc=[#H2mbO 2?$W Z*S)v׮u/`c>?gZ4sNЖV-i1MITYvPվP/guVi} bl1|{fޡ'}^r|}dR _NjsJ/-`($r0e͌2* 4 {,}n-yH\`p;zy-|ݿ ki3ڳJ"@U{U=;4>D@&TR F%Yvklm,97X{w@}KQY3 oA]'ѿƗJf/dbf;@M R*t7%}.A2inHsk?wGy[g~TF׭bx3{޿* 9a`;cs>t{.C-L&MU`5"Z<29dpS1n+.t[c*5qhcj,W͜ك똅Q.wxClvr5QdSNSDA\J25Ƕs6KM]DmN/Mkw2"-7cvf/kf#CC2 O|QHc gGifyçރlfk>x 搼:0kC~ϑw/6{q\\g7" fCl&h}g~MO B(j{Om~<3"߶hN_Iwf OQ1k1A"Q%5p(&}p*xaꢧiE8ż#f/2㡒A*k"ك ݶ׽R˖}n}T[v42^0U N)=IR_.^8c#ZzBW@T3ٽo+9&?맊zm/wE 4hnY_F9gVoƌJȋIcBW8C%{SbL!^vz$4[};ZOw5}tY 4zLl<z?{= ~?>d~.Sc"w3df741a>\XϸT4.5UHdxa.3Y4ḒK=kd(M>EՆ1}"v/`\i'! 2{'=-[qqvW/P>)CWq"&9_t|WRuZ ?4R7W,X;=$zOc`8.af\k_Ē  'Q Go7!x-L^J^S`_I*[u9uHM4i&i MPj"* _(?6O qO| 7SJˎt&@a?g{ax`l4 >"I}({Qث;kJ$^pCATPkCv "E: ^.z5*UU8g7L)?hDp~-nCpb$E|<4XZny" 3.k\{;PhS>$]ofOG4i:ڬu|A!²XL)˖bOS4'!={b1;1dsϿP3@"!Q8FS\lcbd׌3kȐ4pz-`gl;4mH8:fEeSo.j<]TtxGe{?s Sly.c5<]ӠT^T67ԇ7>Ͳxi!ןu׮?-ubu姝ňDXgdnN:"W8臭waGgONL_e?IoZCy4Lx 7󛝈bdy7f|\$?[~`+\UOjx}}ؐKy'koozν&6#1ܐKp,kccq+7~rtjl\#l&-2ό>Y뀵 Y:"o:oqwv߿ôB"IENDB``aB>xWWWG.1Ţ|EGG9<%qq7S%zw `v["KhZV֟cjޝ ࠟ7~AW!u\ WUTQ˻ ܊sDӔ*>m?}1eagۇy;y#xrCOChu҇?0Ty? %ce6$=.>ONg1;ӱjkZw e,{cШ; c%GګHGcfm']%IhVpǮK!ӨhKlG)m%*^89;Kn7.*8_NtjPwZW>$-_sRj#zT&]wJ-j &}ʧwtPj-y^[KQE[o1I Q??. !'ߢ~>HH o)ߢ~|yǷ7볏>[3Q oA//ϋau>/n#0 ۭKO@c{Y,9gq s@yQcPb&Bƨ/>2o``wibXK,5QZ+"ϓx4r]jOZkh`Kx?l_HOvNaTC>v]ɭ`rojFT?gf ;*w ce!3Ɓ{o:>U,iĬᴢ3ehN)υ:HW3ДJ mAb%ДFD[i1@u>K>( 3^<::) fyɛ=xCي0VL?ɧ7DH+TkD, | Cd6{&¹ !}K'|V1++MG?ml8(OhWL])ݨV_فNi/O{Д)wN}8WPm- _Ey> c|V[0++M;injt(Cј~SɧC4lYUTQEUefנKAnWCT@AnQ|؟hW9i6فwCfvmTV,84(^xŕ}ŕf>zuSP-Kj 5}tՑXJs4MeJ)=uI .yPNG  IHDR>a.@IDATxTRAs ē<ݝzpw99?!m1q(MpC=?gt^4Ӟ%AHL-Ozowv[`BSRh,$IXq0Z1X+`q֯3@\FlLKQi{!*0Ae$2yN<88-ݥp<1|WV{8Nx:^|rcLCZ4Rbwui||0,\頻zjmZ[[_^{ y5@~֍8 Ż1񤼳ohdN !q23333s i_ I 8ǎC鿟}n^u?t$;3{bBɀEka,BQ"trСm pP_3nv׿m0L12hv 36گ 0rs" C@ǎHw (Ak.{gsĴA"$ڭBh; 8i;zGT\\,>d2N H8u-7](3Af@" #hpay39.V|f @ҳgO=z1 0 4RPH7%L$. Պ9?°I41$yBX)|@nj#֭cqĿm+( s0t.@ VJ|lp{@*CJ:u{+C:LZ%.s@Q.&WzӼHA C,'k=造n1ijjB[a91!"\#Rp sN7`>7Pwx2'ͻw^5ij\ZZ*T& =F*1h(ijC۷Sm]}nN~_BV@ fAرC6n(۶mC3]aℑ2d Fe߫Wt郩1( iRkpK.W_}U6l`bӦMرceҤIRQQ=N*ac,] uBCsfYbfS/˖- ri:t ROVbb 3e0aBv> _ aۆ z+,YBy-t>sL9H |!'0`U`7~{˖-g-^x3`6lZv8Y\y2n8}x 0yg-M /`U__/O>,\Pn933U`iXNӟ$ZB.S 4TSNm|?|Ll_"ytvLYu_Kbu6x ,/V CϷjlW_}\z/KC-|3u-tѮny6w44 OSP%wuHDRWz1Ux}b&k}%ͪaBwA]P}GJ)(%=JHR3/m|?$MXA9v^֖D|嗳4_wurWkhHqC 6(^%|taUkz!v=k'7ߤaNaop)S $[ȑguMh< MKk1wjkdr`F9x@8s'[خs7>uB-$?]fBQS a݋>S_w)x>я:KL^` |6^z]iTE첏<؆q0@0~îjٽiعAbmv8W*؄ɜ 38 l2lSw_z%O~":_DCwkz2jR>`yP=$HY!tcj ~@ljUٷmaW|A={vBǘ'> n-oy IV!%Hky-]DQk!зm;X_u M>dYWKEV(&϶ia&}4l~F¾Qo%=cX1pQ3Rn?M'pѢE9]BzhQ#ts eڥKR3Q1[tX@>(slyQ;zɕ]#E}m|Ć.rNK~cJUfX#~qfO"L zǬG\УLN=2biң0sZO``g1#E+< ݳDz?\g,Ao9e9JIA$yfq{G?UqXRUI񃀠E-@:]}!yD=N_^rM$H700)̍HAH9W`[Hkyc)aA(h,  L?8JU5ved]"gOw=>@:C ;9h,DaIo9wJ*4>x+\Om11~ĀD|6Ꙗm1q4 XA4{ qe6rq_^;BCPEh5['ɥ_v/]һ_/4(RZ<V8fHD ^!o2TSл_\3o(gxTb-28C߯D)R 3􊇥wyÓVݚ"lz Gw_o; \ A,i̒._Zg *Ui6v\d<(|z}{]2`S/ f4h  p};p\к*# X' ;گ]@Oy"È2xL:[ {% K4*R`V;,Kh  rBCj-ǎ~*,Jv?(a9d6uTQI~DD D1AdK%LEc\gܱ]a_تjޅ]AҵmA!y3D,ǥgB:}SeD^{>KKnYԉj%g]rAϔbtv޽ Şea2w,G?(-H /N :T/<7л Ϙ,SGWʍW'5۷V7q<}(O7k:*ڞ5ͺtHyNflqe$##g^$F]xۧ'?WW5WYwmYOq&;vT k2e\cZI>aBh|+v keղfr7±~'>uWO@hh!GO$[w > " HD-H0 QiRأOViH$X-&]`΢GIGc嵗ц} +LdZ F-۝gk Qҥ_|Qcg#x 1~~7>a dqX9C.C:\;"Xm}J5Z_c(,6 ׇnS~0qCaÇIQY?[w|rw@"$ݎv+8ʴumvQ\nhLHƿt[*ի k<HLe54k,qHk Fč?BGωӳAP}ӪIlW u?K]I8o7)ʺz0N%ҿ.iπ~_A~'(xQkNOXMqCS{F**$'@t %P"p\#~0  ф {W2=mQNC?/KM{I=*>V .m_$m[6,x=F]#dwXUι7BH)Ȯ?D3y*xݒ픀pw[k8i|_0zχ>iL{knUцu]d JkyJR %͚bS:L{" (,fBpK6<gJM)a4hȰPl8=x\P9:hgpp%YM\@*}$$EK[8qz4//5S?\.^]"KyflCE҇aD:s常~<&Oi?d^T5pP0prT@k[N{dngwt=|zoU2+IQyE;%j6cr떙@Lk\lq4ʺ.]p%?1 5gy˔}c8|D.J)y_xE6ۅjfB 6_ 1 'Vp\*rﰬ%bֳ}ƤwFOPjaau@k$/aN& <8<<3ɠG"~;fQ q']޿ZGu.,v]đim>.1_h #RF#ZèvW ,l?FUԴ9"d\u$Mn(BL @m0:$|ie]$O664JM]rN{MZ$\FKȡ54!tnk3Ly8mpcvJT>ɟG1,#T$]\= ;1wTk7K #nS _1w +pea@͸VT6PwRîez'*&&{hū~N_spfiE !pkASZAd\Z Ծ7f\ G/֠C_e.yƍTHf$X<J`B:SA{W {A+`VMwIgmw?뀛}#4՗[Ǐ};.◬/dlIHxU|B2K.)L+*3tI伛E?"CqYs_O1=2۶}Z!uH>< 췋B=dC? W\scӬm5֑{g0|,1MN$#6s4J* (S.F^G@ %{+|eZ2@WqϰhkL3ǃ΢m:R!cEoUp޿v3+Y_!&>V ǏsRGəPkbX7tS`L`;4 -ׇ cA#;& Zo#yUgLxa\tʸ#w4 ~=/M}u@=9n^//;vH >P_a> 09!<×MYa Wȇ"raj%+þa&U?y1LJ= H#غIlY)_"S2A[s^/#ڃ5lEjebo ]d40~7>᫧O VejtpK.(x @p4>7Yzg) 1DR6o(kVfp͹|F"8 *b*"4co+XsLZ%haWƩ5j+|K z &3jZydR_[-XQ S};>zUd*9 Ye%T $Ϛ KgsP؇`J M׳%Q|(nW!l \\tEA[Zwr ڢdW/*tU <]umW_~^6.^m_#-ǏZ?o§ƟHg{W{:J{֮Dˇ|U ZӪƓ1mƦղ|YeٲEb{#&vJx33(;; p^BiV4Z—*[fSWK|\_P~@&q6No[4_ IPSOŋmKq$'-=K<@dk~\3Cȍ>h~v[T8(YL*\|w^ GWhCQMd}~_NrGt.\iMgӂX8m;x0$h\Ce}1maPS"fF)T3aiu] 1DH=8);<*{+O B4wc 4Pf+Ӭ(Xg%T oFE𑅪I=]\#=a‘~żgӝٞImcK!r >)F@7,*d"+j' ȢUw>{M8Nyl ]5'0#k@7@!)l1Jy7?II\@/iנzwq};dohTeyn}U"@vDα[~|":v?Z]Uow> #y;>ZPahu, L)ff\,p&wqΈf3Hi&5&oENyYrsڄo5xYr8ji<,{Dbk#ޓ69dXN\YX+B̀a\lk@v 'o޼ykPt²ZumE}~Ǐ8 o *}ٟe4?N dT Z;/`l%vkR{jit(3h7d A chl%C &EGZc4+XpR׷CzɃ}GEb6!{'Vf@Bڦ@91Z̲I$@Ì*a $ J@U'LN,|-3 s%A!`s -wV Й9Gfs i аly #Y. ~FB?N ?ED ֶXdf,dt۞(7dNf$vև,X&:ק*6Lw#0vGM- 5ԛ<6ۖ'os   x` 03(0>]$i&y2X].,{K $ڰ^떄k xXj {-\t"-ѣym e.Ww*KmgJ>J^ b~ m rkv3' s$r@`9ck, r'PKRyVz4J/h'jM Yi>"|ԭM6Fp\aa:,@ZDH|.kB0j9~X~9PJA+,Okz % !vTNy/ 摒]ŭK|S Ov)͕&>hP#ᆇj9*UB 8\Ph w5Hdm+~ikb#F{W6TR kt5?!A| L.7; P#a!xfHEZHo.FA0 OHoJUUy [[#`ٹ_L^ےZ(eALmjiUC#8 1bZGNCLݨ#{qJºYs3|!ç/{6 TֳH.Eog5q7aSx&|w_W-o5tؽGX|!AT%`0s V kap!>at@ۭ tՓBTS<~ܔ 0u95ʊi⸧c= 0ATgW͙3SfY% NZ?Asϱ œn;"Qefӧ3>a-I1F$WR#|ܹs3'1G<ɜ27 +k̈́Yꞁ0~be՘OYvQ0nw} 䗱 8Z{ڽN,~_XF۞njOM5(=]ś=Ym@~ة38𡟄RIU2qbwXVmƩ$ $p}/q$\\֪m4ʄu =D빖бV%"nلea>sRd2XݳT93K>νy2`dh9a}Ϩϕ9LN4v2WT0"9E8GV<>׳H-XF5^1ͭs _5+9GS&Ʌ0; ~3^=: fBg)l~NM]78N|ZX@˯pDl飧׮`ʏjFi`u@g31a,73πAe&kd`d IENDB`PNG  IHDR@@M PLTE$""7tRNS͘;7IDATxc`0B@&d o `zSBkLc&}bIENDB`PNG  IHDR@?-s&Y PLTENytRNS͘;7IDATxc`0B@&d o `zSBkLc&`}&!IENDB`/'PNG  IHDR>a.IDATx5A@_8nGsqbr"hG6]4W`}#Fhhhhhhhh9㇜sG{;zx.}qd%Wܴrer?5krX+֯N8r,<Ȱ ;'!I "AS [5S42眔#7AiF尀sSƱJ+&%18N(yhIzWCl l?i9221~?Z-KVxb(dT$MBaQӱu tO; jbG |XG -3Kٓǂ-33SE no^˞8{H{H}fךA(j%x]m} V:Rf_n]\_s1O/6ń_ń#Q68w*B`ޔ1X›#f勐/aD"KTPj(4 xƄdnppgz;`&P;gIơH;8z~S}ONNn6] /Ou .^+"]374rR3tդlt۶GOE]Ioh吞ϊ!­8d .v0WIYX(3M=og5r)޹gEUc.-߂X5+pc&4͌k4n j֪^(o.Y̌ Vv9axų&ؾ7^3_ j 3 h^i @R~e&؆R JIM5,~ʿx={V N#v:~;w#;3uBy<:uz_W@\\0?Av^>k?*vd[_u4\=_,scٖPt2T hg sS# q(ߜ\x^?/^I%|秿ơDT  ^9X_bOSF!*t]ڣA:_I/]IՁ8zL zҶnw9 @? xv-[p}c+06HXA;S!1 ~HIkQ~@O?UjDr!e& 2n•t$:Wx@6, M~3(D-dp# .w=Ǽsi Kww.|/p@$w^ti&ЪUkϞAݠp 7_>n@e#[.hҤ ;ݻSh,&l(รiUSB367Xj Wrssc( tc@R$tݻ`츱x0uT$&&FA;vkip-[eKTDz͙:=uU?'ukעK."bAqnvSg4 פU tW< Ku@! |^;` )S;SSaT8qԋC;oJGxx8R ,@3224t#G,m7\m_6Sѽ63ٔ 1~ @ fwpvj*Uzd$ʀE غu+jK<-y8ydt]ңYܹ3|M,X@٠o߾|w"1\,>G} (Pa#׼03vA{L:uL.H+xY"\woݾ^:tP-ƒnذA;͛ ؽ966V9r[/ϠT/OHH`GQ|T0(y5DGG[nZwzz+X u+qsޯ@N^fyr UYc![J.=S;$ˠ\)6@k%UV33tVdT$c>=Oـ0S`&+v`ĉ%hLڵSfjKa+h[!zkNyY?gc-E zM/մՌ,쨧r52e >׮]`( x-CEuŚETnJ h/"Ej ./ͅ$ߊ t6wӿGw V\Wbd;[ظq# W^y#F Uʒ?#Q0^ 8nƌꭿ/,TO[n=FIu~[ѴiQ2 CYL@pUC+xjD ĘSƦ$|a1 0Y<(}{W_vf}?Oϧg~_UAV>"2B ([/V 8wp\JgPzP:\FreÇ[+`-`x[YWcfH>dg30εW`UVĢŋw R! ?ccz _o3}{%oAŮ;dP]׼tUOJ* QQچK˜\趰I/'*l,Ѫ XM,s{y6GxAZ/)p/Fk%9WBpPC7} <ܳXd c2˽ tj5{?&Mʟ> =M6`ֵkWWE#qlXՍB@O]0ZfH8!s!]6DC3YeеFlEg݋ B`l0Z N:41gYcϢOxX8)L'F)naNAיƵBge[/s gJGbE^ c20e jL-+UZ}Ya# BӦM1|H`/-,ڄ =Ԫax'l2 X`! s1o߹s'fϞm˵ ZLs95,bf =#p97l&G^n)ʌ0[,Rb nf`P?S0o^./Cry=:.}i1gPO>K!7 r?*Ĥ˗[Yc07lP9@Geo$Fuc۶mֳm۶<ضg'VuVT*]{۷R}>ƉLKP8j ỊK~?aU5O],\c89~Pd4U`ၿ5)!3wnse#,{[qmGB%z8dMRLBAB1nvΈ4( uNnD E8} f?}^DiS&3.S*e֐_7vjժtq__d2V-Ag>3f_1SN)6tO֙ bTha^y-L^0 Ѡ)5_CE?46EzT@QC1_%E/]&Rj#C }#K/\a9 [^[hFx6^; N*?anw!1y 1T+_h*Pg*"ڰߏs؍cs׬aoks(hfw&uXS@0#F{TFEMFW97Gb}y.aXê>ݸ)ux=Ց3?g=o߶ѭ#h 5;L\q;P'G=j))(舛1tTk||_BNߣ{1U{VEXn$VVǜ+ 9DQF ;F PใGhh x^!z;q׳.X\BE VI6] ; O  ^KFg[i7 | VxmU7Ns'6m>Gj=| vR&߲.Bq@#8Fw b~+ !NY'CR-5{0kVߵ .HWüd ^ߢg;\^m~{/*jNino嚁%jUYS7z$okyA0(yl8eX fęo043r)y0Fj W{GqUpəL=nu`M3Gc}N-HJW{N0rc>+-''y̡FD ?Z1|~=}MmFxJ( ,_ϋWoI$eʸqߋo+ `Vwbs7ThzHM\"M." DFO^ ]tzw,ZʻkEwč+7yGMc Kֽ ?O]~Swp!*08$|4@jA@ύ絬hzrEǪc^?8aW+ŀ=wTmX)yX׬z,u1 Fw>R ëy՝NWoRyALj\)$i+s]x0b.$f{@B8 aJa<|O>sC <'.,ji^4^.i`SV4z\qY(0WPcU95Wy)RMo:@&"߃vBh#!6ԉ;g̜Q/[&O§8f1 "NTQJkaLA>L!%<7^ȯ %ߞpgFX_s[QiU*5AҠ=˩aK)\KR#U>a'̪{ T8~3ԧZjUA(5du];cܐgv +7KU g! }xq  )@n=2?\ |%$i< \}UG BY4H~ǣgj1, !fD wcTz 1Qܾ^r+C09C1b#Fclf`4v/be%b*ڥ~WgՆ|j9bAm+Nߠ-M j5~L͙U^s;T S[`̷c* @F nݴPc10Czpo'8zHu #XYˑŚ;"os-p)eAQ'.\h}HCCҷ3V jБTobwR4DbsLDZ'.rV x?&u=W㎯ ?bx}!-*Z7q`p [MΏ !CѮxr<~z @s;{zzzcWH gdmAM4^}5 ()ũ ^V79P@ov.UskG ܄ S3)a;裏>h\Tbf[59r[lҭRf/&li %䛨1BI4UG)ޣQj3Pm2m^ofsbkهgM!5\;3n޾PZ! īfՉYtxz˺t!V,5'u1`'G ya&ڒ@t氢F8jjڦůB+=n@rqXَfHt~6! wQ(bLث}Yf^4N^%ўj1mɤ7FL}mD6'ao?Y䭃ײK.8 {zN;4Lupu޻腮Q5+Lڕ>G ksC9R;ӛU mH=)T$_+^EOyȆ@/*iDH*%{sd~39SqC_}wCMgjkq# */K ensA|'8v7}̌B9ҹg}Pb}آ jP[f7M4\ʰϧϚŋGZ dHx@{$ڂOHApCFs9Wqg8G/ḋZO`Xu3? OE,Q?;_8oX|~⋟7H`Jac'{ Co&ul=C* tPJ[ǤoL3ߘs9s=cTr e0[ R6?^:R`C^~7 ,uLc~'DbAG#g.M^ő“qmH R0PH8L.$9;* CV2"[nxgp+zW3\8k@ GXO9r1:x4qx4O*ddLΟWE0?t9stg28z-Ưoph;;$|I,.]ci9̆u,0k4xg=ίq 6-]`)1sJH#Q3Ӫ CGEDF- HPZ<_:x\~Rj `^Q|M8]r!mXrwywwq}{Yua>zǐɩ5fZ+[!{ ~oDMFsr JhvmbV&q|;sa>XAƷKۆ_P jV@ih_D']`?.}ޣ!Muw`R<7o .{)1]*2{Π\bx@]t{N:0//cUDm7(c:a 'Wa{ "uM;9!e%cAccW#`NSq?.9&'Q8(`>O_gz1}aKP5ʵ:Ey\OϬY@@>!m -k`l /sysޜ `Scox("E)[(2鬳~|4co]wOE'?ɋHЬTe/+ȗeܛ66MmhS[6?s)kMIENDB`PNG  IHDR>a}IDATxҁb     c׊aJ|Õ%Z¤G]"%EFDd,ywj͟X,MェkP;_ k w&G>D0;$7_c^l?pCax#")gEfMJ :_Gs1#lؚcpEy\ΞˮSɥ4}^6Yn+&ċ˂a!TqfDb,9ՙ]:Gջװrq˳Zե|y6ܵdԭMk, ~9z95y3{&?~Gjr ǟ?nWcUVbC_+#=.W{ՙKq+ym]nh75p~}f?? s- `Vp0GAqӎd[3xCU<6Nu}cjx {9tM/SǦ\=:JEfp f.7T" j /jknPp2p|Dk<kvoзym?˵O]ObJK'Šc08f^p`^8Xq8_O)r[\c?:oǚQu 7'>yĪxʆg;wM&" !4i\Q0`ھ:#}7lx^ݓidt ƶ~k;; vD+ l4 Uע:Ϊ i t޾CjZ5ߞmk|yWn }+ εd4v^s߿cql?wٓqGkM/̷o:ƼہLxa}{q(:|[` ~h؃g!]0.(HT:Ș_l[E =]CSi>^8 {̑ wu:1@Ûڹ4."%^v̰>]he$(~wMDW^To0 0C,B+/x!Mdךo \0"ƀ ň!5<)Ɗz8Ӵ~1'Lq ɸzJ b*lP W"Ҙ]Daט*γ?'Z7`$?9>}Zh=3U9Jտȳ#qٴ{q؟yjIbϵdn ,FE˿qԔz-7{Y >]8_'3+vzQv_nx0,F:t eٕP&? g<:fXڿaWL RNⱎn˗b0̆q8 #P !,G@PhD68xP-?:6F[8[m Fdk#y7go6./nb眿} ;9 {@NdN߷ß>C,:8oYz8o 5zx%XAdc`&[vȗ>Gz}K:2E^m6gga3i }ߗM8Nrk{ls ۢ&$snǫ|uјŐPJV-3IJ`C>MN''jEƠ$ CZ@]S Kȑ+i4hս{>]@-FQa];hb({ݩȰK#x=.7SVGoA e$pY$%md(]+f g9a@ǏπŰ>6kz?Wþ1tg9y^<l%}Jk2]閭 R\`Rhmٯ?!M"Cwi<'OCt H'չs~̅xbmHj _ORsËHn$Xrr8N pHbEK.kA+ס!-(zd>̀ph!.QzX`ŐOt| :T\'Ub )/oKNdCfb+/*Un0<Ƥ4k40fOƤ֒%Sx}VwN_ð=%ԡDsifs{~Ok}ke.wXuYZzpˢN93גQ)ɶWx<=*=k:avHVQ Yq<0'уpB-S؜Dz\,g@2Wͫr#9;tD+ӿ󴾎7w9P=IE%fZj1!/@Ghd2)51z(;J yɁAxٳP艕r=r=#O:V>K%gR"Qb(zų%=_; 8 ~] V)2q r20Kb滮of{b끺ӳ#}wک\ Ny!O݂>%?/Wɥdٚ7 "@c뗟} 94PIbR? 8 ̯g?t%Q8?na~": ggGn:O``:r-/R?T3B)_Vf_Gg dUU=®|\OO.:{<%d1NEٔ#P=8< 7o+hVYk[}//xSI)g LhXԎ٠(J--%?ptuW/_Z nw>jZ/_yUU95L4&*eʍeyWζ:|L}/:wQPon1IPܻwO @vFIENDB`[ PNG  IHDR@@iq MIDATx^[=%G깏$&NH@MW"hK$$[d+9A-2GFH̻ӇΔJwy-LsTuo7_\Nޜ+^u+PSD}>^6; )`JMW<ӧ"Kh-L̙!Jc @$hѳ3~7Da*}X xWz'w pl |=yo߃N>wu]^Oǯ]o6 HFt',{HF J:?>8~W#Zl06eP{cXFx.*K$_/x||DF4dLs<`"40&Ѡe~G (0/&T@` T0?ib@$bzNȆqKz[KԖXvkP,8y8FO}۝ݢsɹw B ' 5p!0.n s >wL\މ/ƝuQzq+/>{c'G?9|-K5x/wТKt"<zEzI`nuu e@h1A`'1xxَӍ8 pbiNta3c#-]tBA`Y,T a)YLw (/$v ִHwL`m6s]dCt)^Ul;慻?W.jB̩CIo9mbU  2+s.~Rӂc)zg:' di% %1-*Ͼdд{}O׫b=ik6/XdghMfn §=O]:؅&~NlܟSPɑzyI}iB#䤏8ۓHU~G%AV6R<ځPxYHȾ*Kf6^QCfzmğ$@:dYCOȱ7Mie3M#|*=fo=S$jdU 4,6HX*?#exmwg GEu؀%R\\7u_̳B93<'WRpf2-GHа.qM*xJe/j.(CX[x!`"i-\%G2sMi5c\S×IK 3HČ\ZB*+\# %)fMnaS5I2SU-1/y&nn$-qN)A[aoY(TLTV%SY2XHshUTu${=xIENDB`PNG  IHDR2IDATxXcqmضm۶m۶m[Otr6)I*H:muQpNktt7ä/{UM%~!Rpc\\@ 2%}ْ 4x{k/(__5(*PO}DJ9ػhv cę!ŘSI ^ضJ l Cp; N1H8 !]z ԛy."ܼφ$7c`n)oABݑ!;ˇΩ\(1f^pnB$p̀}u}'vA{׌z38rsVop A(GB0L7O\9W>ɏM,[0Dž 2ra&QWpmtx#k{dzVb?@؆@=W oI~Q=Lߗjj ׿Hވ˲1maYX ~ۆa/NꦥVIENDB`1PNG  IHDR>a0IDATxұicXs @@@@@@$KEGAٶ/mmδm]U{rXkt#*s꿋kFTU!<;>N*Ck4@{V,O?w1O[o~۟3@B)$v]]j!h_d^/~CC=Kݺnݺ@A^o2O.?_db端ꡙb2W֬YCZ FvZ-pI$.^xʕ+(??r!~q,/7o޲qӦ-Nrz޼u~KqvỴPzeeM"j-vryx|S|'~ | vt^\\D'M)O`נxWG~/PyD=.CABO0zKi(qPX[r uƾ- i}6EO7 ;Pl蒨vz}{-Xt/[KDg2^:K]exh7.]Pt_76$`GX@&1/ou$l[RAl 'dGXV`U^ y$;e& 䥔s%CyDcvޤ9E74jUѮ7rA5 Ck:"D~w8sڢ~ϵ ]k|=&nPВG>O|6騏| C6d ъAJ!MT!km k@@3C6Sh~>j'^͌C7v:CڞAC>[;2GtԳg__EeאN)'BDž#|nrmk>*iG0D3߉wЭ%o3C&@%^J,LOw;w|4)_P-4ApgR;9qa-h2@6%OTZ;(ҩqJA bŀ_w-6+Ntss5 "!cْ}_ "W%}RJ~oКޅz \a洅݂l7Lv:ܶ'\dr:< B  7kx(]Wv1u̱b@&,Fd90ؒJjemz R=Jhynmq8|*m fKp/SRsgꃓPŘXG/1.Y|=}:?k1-MH;Х~+b$6Ϸu_kk(Z CdHgri0L~~OJ-A/zXD UApyR5[<12Ow`+65f&a`7|je_xGBo5T'B@72}γNFzrMa"f*В/'r^$cW)4 _SB2%!mAUG^Af+@-Llgn3t$z# [9y.o@hwo#!(|]Y )>{[Q'xMj/la @;6X'(lVD8 ,pivL殛O[Y]]p>npMgrjcosl/Iq|"CuyZv]o@QG fu"jvLn$KkxL̻;\f:u AtL4#jIu52J=*b*ˬT& ?5@|9%<wKPx< HC)w6{pرg{c I3 )dGu;<G'l "7I9o3tc-_N t'jAo|ﱦ/a&;_Sp\_#a-Rշ 29ςZż;#jTQ,`eb <͐/`?9XXۭI?nYpyտUr`eAE`i:@XOU(W^yurɟ&'&0>>rAcy4LHLA'/nپv;z+4mm cOW#w<sN) m5AkQlx(h-@+/ l&7J!?=&"J8q) 1bPЁKs97jH/ׁARuV+ ȧM @-D DAQ/п~oaѰT~t TE%l,/%Qjvv3!~ettSS-[N䢆{<_Lmf6UIkf{ Vw{tW<<3 ,X %ie~`-0IF N^lo×PZdͰ$'A%n( w1y4%T٧0jn׻ݭB;Gh4A5l 2z?m $!s5А6(]V꿳}s|p#okƘ"Y1+F.oj[ϧ:/TU -a@A9"|'܆sw+JNw&x֭3"22\:Xjk]uX4jtqڱu:`*J/I~_4h poWC™e@ s1]ڃXkpT,T&vo' YK _*Ps׎Q26!S]k*S ;0E:\`(os4AL$_x#cM:ZHnI0(yEGqbqfs* j] fX'XY|Mz'xKs`yRGZ*IIR݊@=MZ5}ɯrqX@R[1|AI$֣vbo߱EӬLd"dR Hhys“_< $!p\-ʰ-&Uޚu?R{Q?T4?j`653s@U?O=/cB=(JS#)l=wZ @x ,FPi1isMG1,hKl|12ǁp;h@lO7e@Qw M Z&!CY^۪xh=^U-sUKG~α#F.#sPpq+ڵ! $9ϓϾ`#RS:yۑ @x<כK{ڿk)9E <{Z-sgd$v_K>N'HR\?SS!@d~+O!L.iV+B4Ă-'-$m4 Gn̒駟 RD"hU(T1T y*Z`9(8D(@ C4ÿx F(Z 9 M'zp ڝ4 `vQJA?6NyVm8>|r6>0&BWؽ~Kb2  s XÑ >s4 d0`gn#+% վ{C@z^sZOࡇ2hHas()_|%- 2}ΡJka[D9kc @I- 9mHuonp"lkހV1'OHQ^OƬw6Yڡ_b- MFp/} Hą'Φ'[?:j#jqpezYsi p*E5y2zo$\ڎyФ:( 1&bff"U<  { l~y =t`*5̅!| @>1/|Q)=?؁dP0`7\Y:{R~o(<,scAN*Zx}5:w)r8r`P5zowV/V*g;Ao~h\i4_)`[.pF;x9ث_ LO&B4Z8AGG%>Oep6yt)y<&E* ` Ԩi m!#Kjh믿t&$C#hsu̢6 ,|ųhEWx6^[(u›sel9}qt.}E&z]  fuFmnn /xwtmZ}+&Ml/IN>zi 9Hyp!!aXi`lt2W}^H=k jQjC?w>=> kY(]"M (gO"o <&ܺu^sZA S>|fIEgvjVxXs 4|kO< (ڎl6g 1}%/׍ r4yw}gX$B[SD <_=Ɵҧ!Z^706?@`檡mSv9en]ɦ7;t p8X&6u, 7.sq8H*)"3>oC@Mj,#geg[&0MZy+d{ׇboV jȻ'?1SF,ΰR8h82`FJ2 aҭȣB .:q(s@s$|V:nH_LJO>}ǎCHH&fu$BH}=""V O<k7Is!A>&@*`BZ˕o~>D=16& )#1wMӧ&?sosɹPa`o7 \3x67zr@KhWoVk&>jR&U~\GYߢ/=ٴs  (@6ω5-+8?-D2K7W'L쌹)x44D;_KiG LޓkKΫ@3|in\c_}kc k2MBܳ!7@׬[HKYW8 ޿a]h4)BW:ٓ!?P<4PsZr}*0Rn%U@~c#!0:T` jXfk,/b"}V%ׯgҽAJ; ѕ5Pxic DZU_+Oh@ 8˪Q P۬q7R@JMЮ aH,aY,:ӈe3($1ߎM+k[V5\â'3~/$dxrG%H@R  D!_.W .|?ׁ.re*c5SJ(b3&3t %hEbW4UiN됫GT6uNI^8D,աF@`1nΫƦE$-twjͿ o>X /\Y`Gѝf](] 鱫 ?5؀?vn G}g*lu}*u~|70^"TAKw}`R<כ<.{pk ֵO D|\ÙͬRqIa0Kyaw ڸnӮڠ;X^BFFFl/ZR` 鞵T iHQȧn5yHX. ]]E-ss#\bu{q'ʙBpKHA f9|\Bv4OUE96n 0~?9`\AO˞9 [N,o:= >YjH"oh҈W0¾e/x+kW;m1jgJq2\0KV.]ҵ9afy$oxM,o7}='X\%EVX F ո9);p .nր9@Eg&EaA:2)bǏ--0dJ*UT M=g</=?$`cMU@I }@$lqI?N'N1XuH/B@R Th{a|Y,*Xā3QRKZV*]?ijo^9-l %8'Ou š}+ل#U"`%IԐ3ף)T<I)x) 8b}^ q4`C^ݲs#G ?W2D}}:MxP`@)xaᭈe)8A\D˦  yh!_.xC#daցZ̵?2(vѾo)A3g5@ox?S ˰n=U4'灗t)+8G}4 `?u7")pylv:WcB,ox`'5 .Dyw oxA_8oX8 &dA;8v\*zJF1 ?n_QzʟvPG1?ۄ0 X*L!ͮ[h9fS(, %Y :P @8XQPK=Bs6$ozIENDB` PNG  IHDR00WiTXtXML:com.adobe.xmp iCCPsRGB IEC61966-2.1(u+DQ?3C4ƯXXIʈQe&Mc_g~zo&MVQbׂVHš0=59s~={k8~HgrZs;kLtD] T[,fv*bZErjp, jrASD?M¡16 ;8J}̗8bi]$ea'+*O\Ef$HWԼTI`o_TGx톚M(nǁar~vD(k=h\Ӌ݆uhW#Z[[qx99hBg?AxUvvG7.~Qgܵ pHYs  IDATh_fwlfMҵVD+RA2HhE>Ta E-(R B)d|ImAEA`iqfnϯ7cfowK_a{{9E.lFM<[Koy՘"cp(lTqB.YZ$IǙ9:Tʝ"'bLj7]+& v^ܾПfcXbPk\7LwM\1٭s] /݀>Ҧ .+KSLnOf-z$H>i_||Sf^: 4W-֛l=bbJ؋,cCx\IBe@%tKCY=[=ֱUx ~jvsw2'Yg7ЁPzE8U6Iz dse48oڭ.~cJ16Nrn^*LO1SKړS=Klvs1~:ispZWJxPkL^<;s}0a\D/Jy!,;!}32{U"8=҈V]Av:C|06qq@8U֛s_${.v;v$P)7U!nxZt*X"cdk$m.st/yaEA@rLog~0U\S`l̦"s[n)0wT!Ԉ Ж}gݎcUV˘۲Zj=eohfx<3pPVuϪ΁zf@q'kr6j,*òpܓg0]9ytEIeƟ#ꌳ ?^5~Z5x`p <R=Pk܀w :Bs#gqJHr:!vV#IB)etiz*tvPZu, x84t|yqů)LRezmӡߏn7 +K>0>0b|خ U6}K#K#(4Ĵ4'`RRZ^?N4qZB#lY႞3Q[(SU)f\>#qW qa^0h;;`XP;y^ES"s_b(zIENDB`ۉPNG  IHDR szzIDATxikm ؙm;m;=cŃF3wΞ[_lsUU=Oj- yoՀ}G{/ 7td{= û4 >"%1 Y;=,`z&03 Hϭºzih@SB^fƶm--ڪ $Y@8UK`͔2C_o{ bw? VثE@QQB{Mwud߬7"@Mk k55*!1cD ̴vMo= [`byi_gcIPXHH̘dODζ(}wF|Zj)M.u!([C؅d )dVs󁅅Wu5I45X3hu>˺++Ѷ_ǼF|NzĶ8Nn[9LYLU%r`(bF`E,fL~38-׎^ڗo}7 G D1ۡǸZa+1xzlpȺ'u՗]}G}SG$tVM_w)%Fx!JgPT Ʒ3OM% Q֒:Tt38. cIyx4y5 s0uvfqx)'u3| ՝FoY@.X34E\z rnuF-pyX+?TC5:y'H}үh~ VlGpz)H iHJ?=LejOg9se@蘊8e}snu!aJ1d(p9n@$H!q0my/8yⅮӂWwVuH݁";;SWWχ7|3GrzM gfwA˶m.u]pܐuXr "&䣃UVVz$/uH5jhԜ9s v}Co53 kXŞIENDB` PNG  IHDR00WIDATx$I7zvg8g۶m۶m۶QMWW{]15=ODve}Dϼ!ZteWt%Q3J(#)+CekȽo~EYf(;KY0 I PIg4SrD\ \eSCe뫠J*2d(ݻusNt 2Y,J tO&_0z-J^]C9UJN;3bp$b"AH$0mt&M§~J]C=BHtV8h#:Sh `FK,!ݺK3jBQ~ؙ|wGţ#WBرiuץ55 _|1VXvYl`P/> ;v $<|!%_m>zQӡ5V_~}"*s-.ʚkOkoN6; IL_O3~}"ѡcGYk͸8A(E_zo4vygV_sM$! uګd `@ - 2=m_Tlj:tzW;Hcvz8$ o$@l7z36!'ǽz6ְrQQQA.C*D.0%:ȰK;9CpR~c=U̎|U@z$(%D(J\pxtjddJЖ;H)3~vz-GL}ov^zmX~Q"*֗_~' )!fhFC%̇ޔ+B|6G4!ob_i*sj ^$$RbO! z$vO\nt 7m_DsxHc7g%#ITZbIDVޠ@~{VuбS$W=( T)i| EQfp;vH}C=, j[t. 12}4$aAF,-62qDTqA  G 6_ 0"!0vF鹸x~'|8w0I<.|zK\|m?Z985f4uuuac-π<@~eD0I$3ygW1tP fZ5U3x2J$Sl}85"kH09mb}M2#o@+ɻ5`)cBZ)$z ix饗Hc5VwqI5`1PP/Rگ`uҙ.]-**>ZF-$@ `}#^?>t~tE-!ţ\5wѫuW];!ih(9mEg)_yN<4f݁x+Ki֦Elkj-g{ ~[mdOr)Ǧ(/rXAMe/OʰAr h-(8?PBR=jUޏ^mH!BЭOɵ՞,q~j~J5@\ ɁTAD*&Lx#X/XNTr3J6t.-d9=ztɼ.185}+(kk-+GQpQ_쎳W=ʚ5"ב6c L e Xki׾=|Xz@"iD5(C_#Ěƺ%f#)xP0amQ ;a$ddp.E1cF$8pΥ1Dk`4VyN[p.?0RpP54lrflE&TЦ\S齤@ m@sme֬Y2sbj cƠx #66Q0s#aCF\ i#SO?:5 . Jpd w09D:sKU t ɜ19n Lt'i #Nй>J2" U*9r裏p#J%mBK*&WԢkZi, 3* & 阔Vy҂Ϙ\a4R"}\IENDB`1PNG  IHDR szzIDATx,GFg۶g=Vl۶mv[Nɜs3vwUCk#i+"?5rvsp\-('؜% &wJɽ{$=I"85êuɠfbw(܃(Rvk"d"ѧ'<+\+F4sERʿ p9`G/\>WJHj|S@I0"4ί"OJ~>kD< W3j5_8Ȁ.z\@` j\@ip~gly i;@#B. 7"$Y*v͒םoˑ͈ aDD]6; i '^6#ƈ)A)퀌@? J** fD_䌂ߝ[.UƬ#! P!̓*" 9KNԲOaG#Q2(7ễ!"&2®X1]F|<?["3=#҈0Mg& 9!#HmehkD\BZZ!WF_ Sc %;ӈIENDB`,ePNG  IHDR>a,,IDATx\t$]`ckml۶m۶m۶m׭35>̤΢Wk[zbuk\o-[@g.`l0u.O?tNVVV+*|>_\%Zm\W+3i?TH*$: b`yg\F4-#3xG?:LJ Z5Pٖ "Aff&!`%h0⳥.ZQ,}KiSY#K/9eҥѕ~_-UZUF:rD(0##CA5~$A(*ؼd? `J JZ̚5ˎ;e{Y~ۭOgO32/^LbJ[6jt˴LxG@iT|L̙3'lU%qx%K%DpvxYᢧ6#n%ΫhնifFyvڴi$+_k ^~e$DI,Ryi-1@mz’Yni1VH̚LntN`[jMKx@':G++$9^Җj"c0 lmmasY"L"+TX 0&7 Syr}I*# nO+p2z…0D1V{җ@4RIF[M_ϳzJSNNK  Lu{D<$aUTT#}K0AR . OFTf$1U$iժ:wlCt K;> `!)#VW" |޽yѰr(VрOmw@t~E_%XgЀ';Ȱ'a^Ree%t ޛIrĦT%N0pɜ<yi\/6|r$wVi.|Gk80w\p>[.r;޳Icm#!RNd9À\(h!:u*SiM3q!C=:`u (%-QlI9-70}JJJ%/aH0+(s- L'??erFNv%Z*0дiFKN:)&7Lꛔ:V".L)7=@]UO>O?_TMp׮]ѫW/7:}g'Ms,, ~K)Ʉ9tUy̲_|71+--Ցm@gdz/sLp@ 6* yJؑ *To|J='NԘDqsqxEsF|N6E)muk*qS賹PWfϞz ov[9Xp;쀍6,ń۷/U^{ =&~zvۍ!aiL 1d^vNKV+ y}T ɶ[` 7;#;Cs>[kwz,4@3hi,&x&\lN eFϐnƌ1it~%D._:$LX0>\3<# hV3k}$O<NPB,v=P\٭ #-V,]T\(}O33 ͌cƌ6lz+ߡawN!3$Q;NN`hce^3v3r)z%~r(ѶhTl=+3 ~@g păTD῿ä_Š:7m-6`Ώ?a#F0}iaCR9#Lm8q?7.IO)\szJqMWt!JKGe#((>&Al.<H6g4'B(..~z38caq7&iZm%-s ֎ $Hʎ<0cnQ 誫҉xK.0Sy ;-PVQ綴>uM}îlJjnN+M ˪; Sus1{d& {̃܃aZY0 |뭷_HX.$E*4d6O<pfs=Dܹ+晪GIP0 n[m>. p[ E} ڮEUu|{8餓+81C'G_~ Ȕn0U :K=ZC[:K3oý1pݐ`h`U?Xt$>Yݏs+߈r;Ct7L<Ж+֒O-,_yΖvmb9*_R,20+O>$/PX&M0!nꩧjF!;3BwnVϖ+VEH6 S9<5F$Oxg; /rdײ7Ұs<:"3ö>Eeb~Zv!+VAc@$,%D5fŎG-qk$B=^v `yg9Pӑ|:XNfr7rInz K+9=*tA jY#HHz~z`=԰!}Dr2pLWQk L/QcKlLz97?9i&(kݙeOk&G}ZNpCTqS5o,DI>Br=$-saY)E*7yɬ{Juu.pw߭QQugtmx_ hmy@c`K Dڃ<[b<2cSrȈ#Pڶ-?BGn13+*zpZsYXfY' !h`NҔ&zh?\}=!dke`LO=sF%uy}mU.^#eo %a4XBpVD ;$7Snۅ~Cqg ؜* *zBs}%cHPX/ׯ]͋4E4O:bmO7)#<=2aA垻V4q¦uӽň?ZQI y5/ JN)nܖocY?}k%*@s@۩V/=1ŽN%}ɠO F\@'qHp̭w)!`E~tݼ[[[6+8[%Mc =|Obσ_fI".]j0N Tc( 8yY _##O!6]?Y\8N>B:owh`z 0PrGS HNYs^ 8ziF[i6jkhМۼ-N ?u˄OY0J@SOnnmJ51k~9E$A05}au ˷ti *9M2ͅ?r%)?<.f y̑@bD _h5~۷o{&%IXq xjn-9 z#b [sKŽ_ZUPnRD dql> W?Q: ^’$Y!3Q&\\AojAo4c.qZHLØW85M̰xm)p4"ECi.Yu(x ^Sb't8D)YN% y*OB'XY@ٛ>jyB *Zяz]xq\@LnQ 6pkDH ZC_C9rؒ^_%}_=L{E+sfT9ÐEAA2㫯yK^jmx%el3%@*+P$fJ?rI#wYr ;o%>YZv P$lJg]DouOy<6(E<]a^x|b(sNTZ):S=f"ߺK vWv^xQKcs9Yd NL` @Yuw4pef~w޹xWB@rIY,Zu̅vdfl,H8t| s~7. ˁ3)Ьxٽ~Ts:H+_2B#o7QLp,)I!dVQ "Q;͠O?4K1n^N"Z?]g|}_ `oʣ v#EAN L`hI{$7X]?xn& y1%4}7'8;(hHpJp yb4hڗ^n<%T*˷+"hRS+>6I(>14 p]nW/ LjC+/B"Rf0KČw Yy$=h=hvGu#gs4qw h;x9Y/Yv^Y,})1=ffffffffff~/fffC&Yd,ɪNufv%STY-ZXgz u-s>Ftđ} !Fڲ& E(z밗-P.T j\C7lԞ ؃B1Ȝ`OlXsD8-N9}6ˇ_k2q>8wn_HrB~FC8/]ba/} K@~;uh*r)Pʦ8r^}h=׵/ yaP!jn(/xLO=)n]wd#3X5.˜B<-oyX3_wt! xLO|ȇLA]*ws=˫xJ0JyƇeWj,u ~~72am|X5 61ƒgs[D!S V9z.Xk0Z@rEP_&{s^wodG-j]zW.$a6$\CJ[׿5mo}23J6V-8QC~#q Ͼe/{ԧ>|7ɕIo•Z>G#6pp) Ag -[[Gwoy}Iys!?[8cCJհG?ўMHM:yV'?pO! a:[zn:mI`9t=/| P>cՂ/| v u" Y|'^D2hؽC53$ 9,W(`6^ ja-enFߺ`"X|'$'>P5q І/SjI2y Z(|JN;Aۛ?L|tZDU NrT[Cĵ^n(ٲfFx{18SA(bz QD{Ll_TVi&$zawwݺ6M 9]s^F gY5mтyڼ]+0!11~gzGcׅ!S8POz9k9i ,=2, @P;To>',̑pۧP!`'Pڸa{h:uv;3"\ ]TV\ }{me|׫ ExV(|bo|ܠہ@o8J#kſt y1]]v)b ЅOzP(o ]ŮesF_;[:Kr˕PfM9C low)A,\y'FpÈ25M;c20XI)NqVp8Ka& MTw `i'dZ1 xԔ8kFջ*6# j$U`y=e ?5zq)*K]#^8` GF΁OO pO&f. #w^uQRox.7.{' m6|x[oCk !?4}J )Yig2씻[կ0^zի~;xot#z:4z}eM@7S;G<)^[%=#\⦁倂yӟ\xV-P" /ߙޅA/dU\ȱ @+q<$y#z+ِQ+8@<V ?:~y/y'> #§V;hS?&~Ը;XJF?ac1g g!:u g'񝜊 rD}be'2eS9\fu>-@"{N"]褱?-h+6C6w-S!脴^<~hߗq>718y/ʅdSog[6)/iV7ܴ؆rU!% oS"y|xߐ5 ix+ N>S7 WEŇSTV @0`] 0G._xH F{Kk{!B̤&%OmR_&@LCcyAdcβ Ӫg ׾s4z5nnjz?ELVG>Y=ǗkR<Ҭf=,jxDF!h CJvf.w{ \ b>x΃5rzW!`rQ({x532- \J}5m3~X]ڰUe"\4re;RR5g =0Oeu;5ND}MC pM@+_j=-?uR`}{YfHX\_̋edr"D㵸[{a]`@Ǽ'zoA Uw SXP>j E4N,c 10m oz X}=M ZU28r c)w_"sľ >eM=*j6@. !rI7L=mS&5>0U*'b&g F` DhHG~=jгk Z!h! ~* |вqՊ]o_OyJo;r3:QI9< vrA#P=wK"vXє^w9onkub:;x4=MJPߑFBzwƔjBqO[?yyDc)~dqk43o8b xZ0 pp! J;oqsFu:gǜ ?M@&&^iz3m{r;q{zy+. rfKt_lxEm&VRՎ=' CXQ.ݭ[ٵ(2ǔ9ClƷ)j'ЗncmX/'n0 y, !˯&ˎb+km&̋[Ln1aUC`hq ) \~Et$25O3  Kӝi־\vjߗ\T>A zEմٶV3[MՄj%ڣnÍLYPNCM.qK5c0{;Oꏟy"hz3g(JFެ6oc׫KP_FKI=RP{JпT.r?kZ}L[o%9Z ۛ=Ե 0\{j /τ І?37uMxWb :DI~lꭄeBTb9-,Ղ5Zikd&̆RR8q"@t3im7> 8뷞[{o.TY@*pW:22c6[4Nlo6p= E{Qh{98(=`PE,'ozekU hj/]ܦ躵 S[.+~4Pe r ;,cFbf4P[ JOu=tz's% jΜ9?bUحjSV+W^7uPgI۾V/2i-N1̈́@U<]7x#qkFr*_/Z$ Tچ%d;Ecʦ mw>,q7X`H 2[3$m@vM}sS,[1uU\҇{m\\*>/YIENDB`kPNG  IHDR(>]PLTE#)9IDATxcF%00qrbF$sIENDB`bsV W#>_->\/ډϥ|;+*bR77+<>g>>? u /뛟V1'e m$DžG=0 {<]=햅b&-?o{׆IENDB`!PNG  IHDR>a!mIDATxS#Y߷ti'k!k[kfcmc۶=f\ubC h-F ph-F y;w, R B( ]7@9="Ĭ{euu> ZNodI @\xF9mamŻms,ˈf, R}5E?w|^:[^sbpWI5a!3n[oⰐ_)_Y E븝_7jg+IDBFi0@i~aa+zc3FF S(&Ωo;K|12\3x͝@c&sCV`DS @( ;oyԒoO"R#$tFi <|r)PD ٱݰ5O?_S,'YTFM믽 &c17lVoJJ>-(HvkEzTa[f.> YH&X9+y=FB(68o[ҵ$w 3 >tl):E!v~hxg(%0Xa@-@g𷷁f`t %#B(3*FL`;?wz]'@CG {[޾A~q/lP oK xM@s&#lڑD ,3&efez\ff2icb'^ޝwǕۿDxc43uI^'Fb\DtfEaP(#$Y2O2M!ː{;?OC=Hg?Pǯ<`nØlg IlV!z%`lv27F)rd>TMhKMݦN$܇"-H䚨.\k_JQXqqa(gl_r0ech\Ѥ\ln IQyd+whS7]D;9lH6f<?+P\ ͏O񗨡pfbfN@xBwKmaknc䜙4<IDNM҈@P c )uD>tMyf+[㏖N*e :ts5GM5L);qWL;R܁0-kfhbn@Wz4꠲jAUXoѕNcqEy}upyѧ5\ %%D:%ErMK'CI%L`yzt^Mg??5}͂aI99`tq"L,73'|Io]:!,(nֈeNrWAV6>qca+JJUV2+@^yp@T\͚p( '䙄eʹaf^[A|X}*Z8D/ά 8daSM|w O?f]ϡaδ6s`ggBɏ ۼ޷GGIW d/Aff^AɃNq%F5(qF93>`^[O X AMNxYPO0.68^T*t" ɀg%@w ʆƟPpo9q\Ӛj8VqS_y.?ȱH{o T$0"}QQ`S>,WRA;:\DP p 7PiND~SM-;]tiW_Ji B) 7NElKԱ`x*Ve6s 65Dd+oﶴJ/#r¹CF3Q=`w/ϛlwPz=x4IG\ry# Aikm+=$cs7KJh ݤδ ~[7#v[D%Gct!`aGRnܥ{>>o ;k_xylǀz@K  RMg|>CQ׏7"o[`B g.~\f4{-|_9iNfHoD*~z )G@zi~kjsAm5T 9geN8 ʁĨn*8cIKl6.A%7B3`py#R{5mi6&pp\$6W|xBvl5z>;҆_ Z=O|>盶m TA!8BaNIS;o?" g#[m<[!Q`n4J1oFOܯ9^7kQwZ]B; ώ98bN.ˍ-1k%NiqzCO s>3!Cx񧶑p-Eu-,YA: i@]@`>3;[XE9 ]Lpw7]_!.o.*v?r#6A: A&, e~Bc1#H?c܈cj ߸9'=aK[!{\jR_v(ҍG;ˌoy6{3[Q_Wj[S$_Ncl1ЮQYѴ~7eՂz>@@1`0  /BGcPm=u.6bohGL"OXqyvd:dӼ^_g0cr_B66d5?;|AwHI]#g<޸gSjPO2=8eO}>J77~"R5xI4!"ꉏ 44 ,\C֑Cj|̀@*Hmwpz =)UWNeIE'ѽ@@c@Uqze?\WYpϑs7fz˳Uذ0a2=RT^}ryH$xL 3%h#7 G*0%Иh'TD2&ζK4 +~QDH\JXh%i^-4턦6(>~|U'o=SZʰL$NصFj Pr1Dg'`iCW[ ePWIB/G^^PZ.w-TԥH~ >~fR'e{yx NzHm՜n 6~AҶCh,bbFƁ@1.ܞ(_f=Hv?eq{|$S h;2g/wWݷ^́%͹Sb[;{Pn6+* DJDG~~gAV gu䣾b]Z[ಞH~ ˾cVˆ?Kuvf lh@=Zܰ[Jּjc@ DKp]zﯘRO}O:egXMqǔ36 edk:>UUn Bh+w ogmYZ}y/\`pp&ɫ\9~\o@6 8pEXWp|sqxh}z4j[^Z l!.>x)F`&_ދhG8X <Űm{;bb?F$Ѳ*"  & ~krޏBTmZC@(uUo{[>~:~=f`a Z "΢4`qcT\K$'>$ۑe -5)fs!J>w l֮^*L>i>~+ Bku$im`WqHUvkaKf.ŝZiɎ]WZ P2U.<L,_z_QuqCrƭb5crrɖ.{7YǏ8c'o[<on\h0_pѷJFκŹAN>G9䄵ÕUKg9]1e5cW+*j!^#Ye=6Y6c9bjG?_^c+MT `Xy]|yӚ hӵmOOV-zfF` fGp!q;8d|g'\kwFJ 4s2_p;ƾTP5[@ & %tÕ'rtR88@y_~}BQkt{>Ն!-^' gT^3wYcɸ"D7  tqNd9K[ϾqGԳ֝^:fJhi$Q$^Aeq0ΞԐ:4FACz̀~/?lAϓ:f_ LUc/UzneU+Y-lKY-7$ #a7"d3+xuv>b|=W1 |-8amdG3H-&w6r?$m򪂕/.BluY|0@Rzwhg}"הz!LJT [QU uۆԀ%<+ΆpK=]68ܳ{}zq7ȶm! |(& >K9_>bD!t@-D_QV!FlmoC ldInU'=ze[㿴ngn-T WsF  /cn:ZML*J>g\Y\pk[OxE9IJmcQl@Ls @Nz#F:$5x"E}Q~~2qgt5/{! h([gܨxb8 I^G\Ŵ96YpY??0mdl=#1f&åtN(C?[W3H]RRDC*dUdbwHve-y=Z/:z>=r0E"1Ѐj]$6@~00A j $f>[+N:K 3I[9HN9yh{ 'O^,:?6Ke|ц-U饓ݗ2YaajluL6@3O 0Bpn9uܶYrtӀ'g6Pq RQ 6)&p\b|0)Et;]|?`?4y. l=1&=68H_-hRԐ#eꎑY NjqU l˫f*JET"Xbشkp~ZGǛ 7Sv`F ӌ6^z$*h& Iy*_gΩ>$A f nKH 0JV @eUpqx®9hSϧzNf`FR V&lV HȢbgͩ9Gb]4[`TϧNz{nX";# #\#z/9d#ۧ# &9d[LWΝ^8NEmuۀ+8-b(*J>W1Wp姗ם8k" Kᴫ@:n$5I!T C:=B(0\PCy?sd{35m&0O}:6c3.'}_' C`x1F24Fn  =|]\  F9T_Ff@8y>:0QB辚 C2}acdõ Bx9z'6c1mSrlJdBݺ!>"51,@1`PPF5 K͓GyC>=EEfy7b IQD %(n %áJcDA0'1Y: ); }0.Q%uGK0J:rĐ\}Iߗ#_a 4kkꩀȍS`aiV}ς7KEl`=306WO&@TpG# qlG8};#uO]a=_6ޝmN{`gGܼ ~ڸ5~kX[]=y C@R?x;e9_S5=p} >_, OHR$@R$@R$@z1pbJ:IENDB`PNG  IHDR@@`UIDATx^혿n]EgDBO ) HА )5H^AE'H$Z T 0@nh>|4Wo=~>Q>Ȼ״G$krZ{$t/ns~"xPAK<^Cخ>x_Ed 3ϐgp"w껣&}.2E\ʮqN_/-@r=ƟO\z{,>\#q8D 1\9k,p禙f_w^q%Qȍ i4**=x;ODo*qծWI B}M*󃟋%t AJJGi@Ł}h,;r ̘p{ L꨻`{ﹼIGCͺ77R= Qh#-M W"2gzyagJYsx^(ţ#XCmKIn+(K$KO;u}!bq  t])r 1f5V8DU/9C(tf>imYѥ).D]$׫՜#lE z`_%JA`\odtNd:0SNRi ͬ6*8[MgvY/;e 4oӀ8!TMޤ@݀a[O(]zxgEwǶ+ 4t _D[>{M4Jt3~ƛs~&xi D. &;&.th2dOv?mvH[x'6I6׵l&?⣸@۫R47%ȃAm=w K:,~q/g?0_K%-IENDB`PNG  IHDR(( H_$PLTEEY2o tRNS `0@pͤIDATxӱ0 EoT*!2t ^%sq֎r(I'r w;絖}|msf$-?y9.R HA A )R HAA HA Yޡ=gF>shUTu${=xIENDB` FPNG  IHDR@@iq IDATxZܸ=ef0{̌:7ӝN&gkOMҽuM~G;0.puTó뒭7]zx#7!g`fd{?^W=vܟhDoZhiio ˛WRPJsk)%?; 0h6ƘYOem4ХKWl[vo!=~|{7c,w޹hP6knzۘ\,X<Ya+/!v3ocF]6D.:^׺E֨l&J[qk÷J-Ͽv\%M*"(@JT%S*~L"AqRP?gWVqXg"l(Bւ;wen@daQ :h&m kHl3rhP 5Vл#PFY!b%~I c'g1eVAcVH6* ،i*`Se 0IacYpƍ0S_T ^;Ab,gdYgpԳJ!) B@B{cy Pxn|]MOh hcf1vm-`y@X .i%M)@/x гHrSe4~.N>x!7ιrx}hɅ2~kL,9֦<:ىXwrvj(HR1@OlfTQ ^sś4țf&u¨4Cӟ5/__kY mMPI7T{`n3<{uϽ-Yaʙu+ gb-•΄JBzoq;J L@(mr/AN* \栤}B&k7 [ύsgx OHk!8Y(#B]``a*. !g߭PT/`OBTئSv%QiF% CR|R"!NǨf~+r^7H@ o)B9*Wks1LBFmTY) hK*7)em.ȀM`ܳU)Iȩqrh *+Ĵ)&6#p&X >#eߩ!ҚɉZ[{yP(@ ?"k)FCP#k &D)* Q) <@|bdZw.a#l+GNL[e[[ɥmF-=RD2UpeQ u֖fKea4FQH*QҰs7qdp:u"3=b4._* dl>|DzZ3 _]gUੀ#a&Gy0x*_Dv6OѧMK#" K_J0p69@ '!_$ V S-P}+*1k(XW&!,_{ 4]B֠n2ٯJ7'?K,;@{t1p]^Mi˚5I@Z0 <  xo @FpW\gmGlmk%MKS`^ีO‰n6:n+*Ll1J6<,Z0-gvc?O}s66^th^>|=W+jxچ&~d4t؇An] oH[t2c &X}6ט1hjj:Kn>cY>dPдt[FC{#]?|&-}|.bx\* q9mw-߆hb ͏rbFeһgwW_ou|p)' ߲ p M|zj+BkBy-6irXsՕg,2}Ǔ@3f%+˰ѭK;HQB0d`ԹΤKC- гGhRmڛoo*%7B=#P$zҫoXL2)UOWGB4NZ&t`f1o<{wLDT 3پbo_nxH0l٧IENDB`PNG  IHDRw=IDATx|w:jx[۶m۶m6wk[1kLI~I;$;/޳yk{3ޑ{l1ˆ@tzXb/ǡFm+h!]ϙ+8 1䴦^PvDO57L:k!a }#q UQZc<{w?ILɳAϚA -BobcGȹQ!h[o|f- )Լ:+V%̻uIy/-z.0tjKOrF`\4 vs{@8VeSpop_8ƭAh:Iu4c|n M! ~xzo7F2ܳ3NOσN"6[Z::1/@ِ=żJ7Tm6o~v{OY*me\oY,nv!|ܻPyQ**f[u'ܵQo'yOxx/x4/c-e'[2HI#lPqZ#}IENDB`PNG  IHDR(( H_$PLTE-x tRNS `0@pͤIDATxӱ0 EoT*!2t ^%sq֎r(I'r w;絖}|msf$-?y9.R HA A )R HAA HA Yޡ=gF>shUTu${=xIENDB`#PNG  IHDR>a#sIDATxG3e308 s3S3]/i$;Cܾ{RM{F2E-jQZԢE-jQZԢE-jkQ#M A2_!&)@(x9W$*RT,,1lU'dU~8d@yz"w#m0΀ F(=ZG֭[yBUBuDrTJRQĀvئL1C&w͙#j8K"ߟUX%K"]PWZJoj P `l50&51ADv$9;~8âs,$U*˞d@qճʼn¹0s79@H,Zt`k` R8I]qؼ* n ndAx:Zb!ivտlD鞽Wڇ?+_=y5_ I5HsC[.8sK B02Db Ɛ1i%L$ݗtn `2::/|9~tePڡ;>vڱ?[/]-)k3:sos^"(?|hO K[ʕʘ+T=b(6 c,9G9p"r BV@IJ6+Q@Ш6s>p׿ 02K_9sz6B} f$ ۦ'L_lK+.`rr\*CJD#4܌4a-Lvfd '궁^!K|#BE5Ѩ͡ZSiߍLOkw1_ߝ GL\3ydfx4 Y`7~ښJr)' ϗYZSkhb-,ݣ}~g|!Fk^B/,%KF 43jXIiP U/F D))"`0;{*aفrΌ Kf[k^c6p>G8)q 7oX0]U," )rT\R/y _8R#C˗,J#3!$ԟTMN<"$!jNݍ0; sY3@ )$OTm8"lN︺zk^TV>% Oˆ)ϕWI"?r `*f5[~ecڟ ؐx\m -#LŜB\lj|“|!(G쿜'\`AinDm1[i-H5 F7] nx^@'I\4r(?Z$֜׊Wƻ! ~{[Ҳ2@ t@Bi\LHFן*4~˼9u2e䅤jwԙOy쵒#hL1}v]՗5+jȍNA4^O}{oy[Z*_T((r06kFbBm+Kׯڋ_= '(qY)34G>e:zK=@lU4TĝWܐs+Ipɰs @uSukffJ!4s#4bxJ `<|}D 2g Gۦ"ʀ#{2vѶ=R+Ç9nw [39u K.2 _x؁5~g8ojM@W@>*ësGH\}zr|h%_DMWNoF{vfq0iLN%aaA ϓuZꡁanP~erڷydtb @ X0Qu:=`2?6zѫ[N'[)AмA 6(=aL @)??H*_Z,Lu4@8Aϥn:{1A?.֑YYl){t̲#ч~ ^A$TJ+RQXLG>[p?sCk>'WnGOAqٲerCBv&R#^,+ z̶ޠ>Jm^"k?YĐ%l( c9Z]%Ix廮 Try!X;4<o!r;xAvV |~·{̗'2++{-Tfkt #Mq~7xn޸gl6c~lqQYyXsj+4CcSuN٘xzf݌p;xDe 6@bSBֶh A o[P Cmld 8eAt(CgKzv`_וKjP*Cws8px2e_o#{ԣgz'}:1nGWٳ?̋gFd^ߵ4Yk^Aiް~d8w;bj:Ďc;]O@<7{?ep p<7قæ6Gebo&CMkXpB)RR}OUG9mᎯP?8Tp<͙#vY: % f퐰pX # q1ٶPzκ8+^t-6H:1i2pcl`lm$#8V.28"!r yQ0G] hW^]+18E)"8+vnYlF $Rvrζxrg@.y8umZ߿$wd6xL4HI1 >5cpZwrMo 'z϶w ,}]8E)"8~jMD✉T TGHPR̗RcKٶJ9dk ]GwG{F|c2lVYB]|.B\./(BaBDa8EQ#I c: L]c>lU{gWWg@ʿR l4qs97\L V?+G N{AkT_"sf>Ӌ,?,гY(eK!uEVwL @ 10?H/}ˮEk/mxbN'tz4񔸊vB:8<%|_]cǎ8Sm$us釾Ź+k/ 7$8wW\q W!E?LsS499ѥKjS;@^q)[҄t@Wn:p/aCIFg-ǹ;/[+}j35 RXG&l}{m+$Mkv@% ݝ]tV o;o\g6M[H3Gfv\yß: KCkWrik曤WUq8K\(JoG>}?SgZcnvU1!_38[ڂe}_˗o ۍ1R| >6O Lj<')0JdIgBq}03_Q a.8f 333srʶt|d[[oǵLIbP#wD|^'k!_h?vGLV_o0'Idɒ%;3hmMލ/x?@}4Mz=̃+a1z1ف+(sxZ>+P0Qߵk[hbc<h*c|y=s .@kQlѾa<)t].LCZ;;-ހZ*3hR]FN[;꽛K Yp,LԁͤPkH+ &h-o۶m`ҤIcaN,gȠ3>d5Z",{᪫&T={F^&۱VB6Zϣ*':V J$,MZ λ 90ƀOk* (SK_H!|[Xi.~k̓˖-fhn|Ryq2zA1ܳ(Yr&mP$>t!@LNZ}:<$iN(!8֐) YM_5F' ,~_G Nc!KBsQh$8_] M"^~@Gȉ*Xk}_n__Zd"LHk]'Q4MߪŵFk{OJQ#G۹iF!?8@h5Fd?`FTf'OZĐ^=@36_zc(6Bsӆ]eM\~ x D;Rflލ8">y1`$u2-'W\q֘GB!?7)%di qjMgA{0@:3M7*%ZוʡT)~%@'68+|9=v:{$I2&,VpΥ`W O<-cm\r8˲MJ>h{ޅ C6` a0lxCIENDB`/PNG  IHDR>a/[IDATxpc8Lc,|W񘙙/XW˹|l7 5l6hkФ@fM:((,tRXd4ɴk.Ylb"@?ß&6xGFF 0#P~|e^o&i&nhiijkk;I 4QlѢEF%$$23&[l|-N|22|n D"RhppPhll'K+!4?$;TPX)/ ǝ]lZࠂח7?P(W?44\]Uu:|؁jnq{__p;nD[^ݺ+|it`nZ$&&MƷx Ee㝛c0p8LEqM^,*Mlvx+/??vbkfOs:]degCzz:_$ ƨ DZ[[6/r!yҔ&M-rLHGp3 `@{*<.2ե656޻o_ sW3"wyꯪ6L2\z`f0ɅDtq @#@}]{%%0+hZ*Eih˟Q0hlN1c$c5q'Q {洗}i8ӊ{$3߈'S).{zz8J8 g_ =ib[nK[o217Kٹy. G3Tt 10!FF)i7@e%%_ՊJ#x-+;RfI 0Mϻ /=n J( tu=.;Pֆd6x>}#>|}BIdq.@1Rž>=vX4Y3gBRqQ=n*f>˵3T`2R|C1] Ea0hjj/d4E44&`X7[m;\s D#X`_)2_Y1.) (1i7@1?Lh4$Cmh^(B L?yP ύ ϊ z=|2 "xꊊ {<u7J XZ`^nFfHHIIN10 MNCbwߖМ54*l6.OI+bJXXd1 r$QPb uQnEEE<h^pRV`;L@w>Ln)(Fx La`ku変͝{SM?|ߗw`!FRaj'-!>Н3,A ⋋44V[n XJwMZ4~ 3c, "P)B4|Uc!lIXxr'd> r& nC4\WۋhB( Hz For11 Wc`e4,IA!*d r&w~{nѰWlWqxɴlTXCCÜ  0kyYiG ^IϼqndIII7p aҎp@c|…کaPN\/,yƌY` 1@Fd*vPXyL O i7@dphl*!1@Kh)VNSCh'G vʊ344<Zp8t^{/}-v2N^ K1p4y@u 7~GPL1kF5yK-; $V@Ü ,0on_}WYYNEP& ;z>=[R (hXwkC4 hDfG4\qGI'A ">~ {^HؕhD O]AK pG`(+-ijj:~*`|P -=2Ҭh k=(BϜ PP "F0 @0Tu#\ QE13%QESvv# !4q1Lqpw 544#x Pu7#e˖DYϬֶF\8v9լX}Mhb +w,.𰡽 7d7 4aG5*e 0 \L  +dA a[Gޞ၁E^w~j"чmk;wkCu8)g4 u==K( ~ZUXX(w§1 D, C01n*<R7*HxB8B_o >~w '4hV"࿉#Qa32祧ieխ|nadyrcA 126>J]G׃F%8܃3A}t}-%KZe6 9; XffzK_L5̉a53nmc|w-hKե< d_ S~Wr1tj@@ f0`&''Hs_җ# *`g,/_\n:=X V̞UZÒְ", 0wcvff --.o~}HTx#T!)Q 봆| 2D2333$)=ҿoEcG>rPjw?LG@G1Dpau($o zQŀ퀴EssY'tcժQgⱸRJ(QIAa+{nRA?q+쟞3޹CaRw.Iok]>r]O 7)$c :(Y@} k\Agܜy % YAN QzԀgfp>yq\M\,*IצpY W[O#zFT@ B-WRQ] ?{ddpb@>k** vqjmۡo*iGHK޿fv_WAw:uE9gʴ # y4K-ziV^:BfW -_@^S\)u, CuKty9% ,~kZV p,10Ph/v_@ia.ޥ%N ߖϘY|׼: ~s(ۿR8UĹ.qZÒjA Q@p`x`G@5ful(}`Ih,Mrj;wN!i* TfaA8+_^^8 o!T tZk/.??X nfzgpviܖF3mY.`sk  6)5;o,𐚞bỻ(@MNrtgY@<>M Cߘ5,Z2ְJ1W@@a8})).u)-X<ann\1-uj 'ksGӢWr? b+ְ0A, qE Oy{g\KSjwc݁:}ٹ[!/~ua s *j ~ 0+"Q~v jGBP΁SWLN0Yr[ܘ5YY PӜSD c ~qFs;; (_j4>4Mh d{a9E Q.r }vXaQ)R>RZ֊AF/@릨?7ۇfA1W ]+0Z=dBVq 6ω{ c^D϶:{'O^ݥҏoXl 5,_5zk18ص 0c p^/` ?Cl!l O|g>a.3tF׾~^cӻ孶iZY`O)$ `<5?FHQx 4L^L?6xž_~ ~O8m,-)КxFBpְ%wfYkX@}(` (BP!qEu{Mt`41˖;X@Ko_P~\t$͞M|(DY(;@d<ê)lXrVps81Jrq/, `1(^lr/n8p3zGNO31Vx͟?)@= lfik( T N"Ppz /wˋ+6_'4 goj?fl2$Hρk^[ZU5 hxe}i(^(c1IgZ ɋOD'H̋?UCk.bp/@LZsupQxKְT!D m{@l /r*0mͬ0?x_f;w66fW|=i{l7o30'>rtt$ ?19Sf闐8;\&bؓKoǕ4dcE0F e)ucj4rO~i!{zKK{= ~V׹h~_=A},XQn9Q뱆o W`}ְh%螃.$&A l cfffežɼ&-XjW}yv{7fRP9]נīh/GuQ)nݾ+.7 4~#m9c?_{Ϲ$*JZb\G0}10Etӟ bs]>Y ;לr᠏{`b0iZ6kU]|J;R>Xb㽏g%hd%\G9cw' nQGEF:7# IjM2ڂm{{`A$1G3j a:<,4?pXwL|guT?n0}?fP|4l a+M?>pZojmlw:eG&OcWhcZ8rF4 !dY^iuZW|bp3$O=+B).ghP arG }!S q:[*;p5r#軃 5 zQi!jпVCt8,"KXO߀^_z#W;H7J 2 1vh%x0F: #HAp@o6`Bx}?A w.2 !)V&r,,/?w4緺J[$1ni m>G1vnFú#v>t*Mͭ-@MU`oP_`T8:Zւk+M.Iu˘ /5]ZU_Iu"`x04wHՙD_y!~* ߂C q=:09AA@V$RR! RVyP0P{g_$8H Ldqj-?!}@o! Lz. (oCê?74W#ϓ$*۬(.2nPO8(Ɏ=Ǹ:)0s;t>Y^ Uz0V~h"Fk~ AcYQڶR+fz0V0l[CJ$@ F xM )"))Q"B'_$\ Js ~ ]xq"& yD}hg\~w:ß]Vߞ&ϗ Yi2 R3On4|[,[O"I ,=_`j4j7jz>$2N@}^#]K# @\h;5mY5oT{u1Qu| p?'N>c*lu q p4߯kV$zKpU1I9s{0H2m(e^69=$^2F)6hRCOJԕ~n2\tmQ.6ɤe$s߾3(ĝDTkYoY2Hk$>T{qF&ՔQ6\ujEG }~аIk SwkpR1[7 ++ 54sNuc0lLت GEbgo)s,F/!Ň*>Ds?'qӕ7|B2PrmЪ?hx]՟x)z 6ZETy~201.ScA[uj-S~nV uǢ }3XI~_Fp;B 0 Iw*.,\ ŭI`-qOp "a<Y,zZ(]_hT h|/rQopn8K z/׃UwPR$ bt`$l t eATB7(DE)vGAWmX_O% 2?P -X0!PqN?7l.bg;"M<̽zY*ZeL|qEY򯲍-闥dN)@uuRJASjN9`cM?G# &s!!0)ly ނjas&6.\6%cDUB t,HLm  :g˴}?aP;̗A=rWd&?8.7O8kzr$|W;{+MVХX p( JE͒dnic9WMЛcacj6V5%zƲ:YDF3VaXoho(Ou^p9i1t:͙r!QC~{c"eK=ԋ/DY.qr_PfٷUY/*Ҵ+X;\@Iնh~j,!z%Aqncg6fն enxocr4\K|M46,*gl{IebܝtWl:(J>RN"ίN;OL~_R4 ~hgPdI`uZJ^-{m'mHAw܆*һ}~4CKiDV(謱[om(7nfe~hv rP- &P3@awg!;&hxyߎt]J*q9϶򿹱c棿O- ڍJ zOzQ/(;rE]{0FoapY ՄllhPnhTQX :'gba)]id:]3T NdBs3&BieN}썔:)ʒ" "v4iOPH[*Vd{=sŋob4MvѝyF ST4(0*M4.u2,M s-`tűe1RKIE^Y$~?xr4ɕ4 {wC׿~w7~;f/<Ƚ7(A^qK9t^Ѷl^ 09^` shSZ?*ʁcqOU<>P瀆^t F b*%IYtRb2~}o@cU}DA%wөWR~}d+JR YF3>ȓ~)^Iaaꈫ V+PXAgn? e. v)Nm]:1KYV0eEH=O]K2Yr|^o3M3Oi.>.廰m}1e^O yBQ߂5\ͩ3 :M޾Vq]>T $g+49#[ЮM~HK 6S[F<L2Ի7x]<ؼΑM~? DWI]c;bij-#yI`U̍&I|Qkp:_4hygky'hgZk&.*;nr)af{Q 4Yԛ,ȿyt y{pyiPr`xůeEv~ oïn+HmfJ-ۡӰVu /`jqi[70@FmąkᢺmrdE;ҹc22ɵDƱyۜ?&9*>{&zU>=c h&u@C:_v8IypIױ<*;OV$ ʏfknWeө(v|pC UJCcC{]ŋm[U"垗𻳀ubn! $ɮMjdWLo'@&Npu [/Po(eqR:ks5$:]U9*^jWpa^xiA[>^( w4{g'Ðe^;Bgk`Nwi7,6` cbWWx^[\Y!~n)w'e^1#DQ,0Y~oZeA|L^?[ WR* ^on?`;,q8 5tN]E|e&i?߸5Н |2)(s?5ySy"''(w*ƅJVɾkZ*F/o-v\RBYIYXll<8N|e!{az)Nōcz5ghG4T n`UзxC]ep1!m31ZtBI{eBٛqZ|yU:ges~m/{^جíO 91oywb,Os8nT y?Cqh[?[>2;pIy} Gp5LKi.9nY^zTP+83wBW/lݨӭiFPQp世[`yן 235纈4c.H'%fu׿y" dChHJCIJ|4\eiϔ,w+&qR77]O*=Gb3| jq9Μ \*,zX/< Ts좏v^Er7>;7N[)GnW"F[ws::·E+st4@꣕5rY'Ouȃ;yp2.u^LkM<< pVJ~A>=vOE3ˆIgA=?ȇ8׽ǏqÊQRzL= !Q،Inmd1^G.4wr -;w#F1<=qDV$رI,shюG?mk+9 W *>U~Z80+9] wYY&E^`!["6r汎}sNgl&7 3x{pt3X{ΠG<DaD;Iouc9$Ξ GB"UC-E"f4~:>`ZaB}D3 k ut eyIENDB`GPNG  IHDR szzIDATxpI]!q89 33!\}}V^5շ&k&Ԇ=a/`QgIJuu&kܽG#(_B0n?Zx2'Vxv8أ:^cQ'jcE[-Հ%Bz!+x'o#gt#J]>eʤ;LkUx|7xxU]Ɔ謾'mpAVf&kGD*D-2Na"R_iVֲ6Ҏlb?|fX\ح @ `3/Cf$>zy%VuPXm 8xԤX] :7ȴp,@  J.Pn˾db[+βO&PL5@ۢw>&}+X .[ON. ҧn#ݬ &Mh\ ?|K [-XȗY-H FӒAcv3ҋ5xoN+,^)`0_l.-;J 4nY-nGF5\C'A<#vLm2T^OZG}H,W|G*UYSHbC* BzA_Ӄ-^uIlk@um+o R~yT'"4RTA\*db)P$ UjS~ d>UKWJ:%|-__ 7\&;Y.t#[&@pQހ嚨 D9o*0]wgJhq_3UjPrlZ8~/Mxm.x珮L)A)(u HL|eE %GbmXu9_H4*qI^h\ ѷ_c着]8cW٨s>tHp%AëV (Za+XaA/(jVuuUC4> 7u!WxY¢"$]XwL %Ӏ0\BkTWF)/*~pSgE) %TE N@\X 5Vr@MJp<)2c6^ $.$zDbAm(as&ǀ*cu?<* oy_y0b aB;8 "#Ve1 kp:wIs4 =>[Oލo}z{z.os9?B8 ua*}E>7@TmNzI5LmDkiе6Mm]e\;n``@ w5@:65;[l .7ߠa.5?niֹZcAQ ts[ l!IENDB`LPNG  IHDR@?PIDATx1n1Ega()rr RPrK\ ()#H!BY_Γ,eǶ`A    K`6}IUUv\33~ F#{|fy@Y( ׫>Pf0pp|y]];e31P@۽ul\ZjeMN L$ɧ I-@:%z= @6T@A +NT}C ;m X ,k- tWR YMSH(ߍOS]&-scm= >$ay+Tʌs|] E;A@ )j >vGg{?ky!U%}& NJag_AAA7Gw%IENDB`̉PNG  IHDR\rfIDATx @3;c8!/Y? @ @ @ @ @@qIWvgWp$8f&13'1#zF 09;@@[62owPPE?DToӹDSzmsK TX]ïdߐ1XWXL cS5?R$)PG-"Z22*~Cd\X> oeUT$?hllU Y.Ểy2VVV~K!Gs7MSSSjk$cdE l`kŞd\^^ ym~!ҩBo\ ؏WzL`QOdTW#`txGKOu,H:Ѕ !3Z~= <;ezzj!6?'~vc yf0tA'GeF w/?6-Dt<7x Rwq@1$Fow7h?j~~~Bxc tDQ:/߭Qr++g~vg<{#XZZZQGU;qP0ַ ={#LسV|]|G_S掠)un`? lw5$BZ~7gB '  hB{_N|gxxt{%C m(nq.V FduE# I]!% S4&G` .tuKzbN,z7]=|GJ/ ι8%^W6a$Ƙz$!1a&H EBQ4ESy@1s9 v? C?㎡s@ь(7|j|FfnZƁƂOI69Hs7R-?ub)-czsčm܍i :q;D,rN)`B))P6Ī &tO[b[:1•⑄ȕ3%v`zA(F @e"xQ!8K%-?O0Kn|y9M$v 2N;PI чX!1?S8ZQy8[7 )_l;q !D_> GkN gL̔Xb(Ϩ ur;d/HE$ O<JO_Va֟ᅯrXBUYS>S< ''ɥmC?܌kG76n2Q<&N H0~cL3831I'22kS2oXxg׫_;+^ˊ ^Z+UY{q{2˴̙D`œ>Iɺ|쓣,G9r$s<9g"Kr23UZLkGKR[}zEL}~85=B|֙Gl?\VWop(#Aй:l$wq(/jg85U- EdfzZx}=RvڕZigÿ~䏣=[G޴f-|4[9j:g$d˟}uDj"A&nnh߃>n^1F܉9d\ҡ8JAPكg%w2_Fw>>p||+|'~y$y/1(\Lԇ6΢A'w'?_go@:/r}(>;=j$]F{_磆*:-u^ (`V-~¦Yn-Su2"@2 }88M,0& |gnzы^yz^z(Ựnz2Gѭ0v jrHF@E$߾yU bo'EZ^8vb0 l _8W_wx_}#z?_!rϒE9O`߽!jzc2騉E&<ϭ;X  *-q HI}WzXFQ! wGb%q'ty_hhwS,yﻁ49RF|LIЂp@䏭`-Y\]KɊݑ$dheXA(`wZK8@}vZ~|:T_>]\{"g({i CCs+jK` _2C .r ,_~HC,-pENx N,C(ذ@)ޑ:ve9B~1XC~o{=5jJfIu7[^ Cg$F CYۭݻ[;0(_]fukMkhm4wԗњ<v(p!a P,Ԋq_;d뮻x ^t/{ߤiڌc\eaԓ?uo`(G,|ly94vD`*ժב@Pn!_9K(<  ӷ,d,5Nv%'W\ɺUB_6 km Y.{_2Q7˘3-W_E,}oQ@?Ơ{r1fBP857((lk,*u }}b=Gsʡ.s7DФxu\/| >v4MGB/\CE}|g}ddhc!;vۃ}|5_VwNUJYn[ֈZRV]+bpVUהGsoT/@ [̰P8u2˰r3`w@,.$>c&9K#˲Q?( I@ mq./oc6OGNITƂKaTJ:v,Ju&4fA."xOaN^ ˟'%U0p<ʢ~%- Qpέ Z +/ _ǂ?lmS Y3( JEK-C{c (cW6BGc,Poz(ѶcQv?HRL{hm!#ؠ/HO9cq⶞'>L|jbN<\Q?QkkFh={ C4m&GiPaןOr}8cd^6q wsV=%_j(Y:XN9p6K3((P}B[lN=i:Jn|@)C( Ŀc6~cXB 2w34T"#~՜ @ rĀjF|ZgM7wދn1?E9'll}!qp w`Dy8jPtmn͖ss34`e P`[ocC{ɱ4-, 4}L勴tƢFah4EUMoUMs=z2^Gc^_F Gُg7TRvQEzçQ,Yra.+ ˡ(?D!$\(ۯè.2Tx󵴽ˀuï;'p^$?w jE$cR{$IiwO1}zz?#ICUMdX Kwc`KS?>GPޜ^Ob#9VSh׿웷Rl]ڟ5Xк(!h) u1eѧ9N|nrqά`]Bg~Ǫ9~jZmwi,JuP~5gB-SǢB_>(䠹KUO(_^V"Rx3冖0T<@2"Aۧ嵘H.u/}CT HBcG?b1Qd6eYgG ڱԆey;|{ c9˺KOP\-M=zCNA|{H'O 5BwD5Pdh+ҞiyXptyQA t蒤J!H ˘1{v`Z H֮|.RLc#1p, ?Yk l@O֣_̽,q''j$1&5MK"B.ĽgP;c4=йVL?Eb@r#`5ࡢ^q5 C"{ ;Ns.v#xA֨} 0Xn5.`=[OǀCDFRL]VFϸ)jfݱy #4px!зh%/1>Rق.Eea1 #&'PQJ+4!bK5w^ E<ףģ,_QKBmP=xH[M=>dWOtt|;A:g}/ọ] pPaZZtB/zOZ5cHw?,i,4B<@ U ?ֺZCD`jKf x/In 1u~~n-xxsϋb *iA~ #LAK>J A,]]B"W8=^[gXk|ˇOy [CP=uD`PqA_$ҤOA/}UzAF: X_46΂vtћr tZ,U)0Lyv5o8D8G#<^.!XohxkNJ_s^LuW= E>yޟCO;W߂{/ $ y[2/BC ᦥްԢ]Bv}_HPIji6,͂,z={2c=#ݲ):<蕅BGVQª܆2> XCcx}?s?y\YAkMk6Ƽg֔r~ՉJ; ү=,JuН32Ȱ*Hʀ-b=zaѮ.b*NN <_g¡Ccw Gz$ m5UT\#h<j)X5s },߰87 dL z@|M A܇J,P2~ױux|EZ)ikIgbraaM ` U踁 8} uLڜ;8oē^/Otp7_o 0]S rie uq Ij~"wW(f郄Uʹ?^{֧VR"Ku=,4Ǹ vmXGn*ܷ򞊢X_N~k.Y\(/зJ܀ȕ{cZEѕn5&:xofV|P]@(͠ |a>lqҕ^ n\U][7n.Ei.r]F v ( ot-xK`]B@k~SȖ-NR*@y.uBxՁ2Ydz'͠Xt)\Ȃ<Лoz>r1qsF3FAbA9W;V@pudE)y/}H=g^H *&w&Z ]l!7.J *0I0^;yY,?YE֟Nng5b @Dz|Sf(Nx= *$ ԯcx_7nA_7.@k.]F<ЛeمEQlC jc(rΡQE"zu!(d?X/Oj~X:xÕcMiK (SLF_$c .$&";2Kܿv C[+Y\'`/y %>ڋf~J(pDXQ@,E=:SCk~\imw2y KǸs֡4?J4#ù|nσ ^I|rꂗ4C_>!F%=@_(}ϻס3"Y ͠X(Q`Kҋ=;~U?FcqU@/~#!]T[aQvH J˧RBE#( } Ϡ\W¼&a(6+fK/TnZƏJ_vC߼ w/,&֭eZ_^C{"2KEP Y;ko,F?4{1FįО8/IH  A,\-gθPSJ!`]2,+o"]@H4I_<sK'Ϲ2:g9(= `ý6yz|p' 6Tv濒`+XiGwϻ* +?JsYj >MF]0C WiF.׋}RHFey/yڳ^o'o{ӫB(J(ӯlgN~Y*Zd8]Z’J_Q씇E>g"Zb}L_W@ +iM.z1UCi_giꌾZ;ű;2H|=cz/dg#WFX$¦a&v:wk6nOYb07 33 8*k/ZuAM)Fc~S(:8!,S4 `3Bo› {(-}=m iѢB*sP֒!`!.aY3/SyO2xPڏ+aL -H()e@ӿI,swD=C0##-uԏDPYsL]sD庄@@24yK;.$k;\A@{>/~-K?9O~G-u(S}4)8ZGԾq26i Z V!W O8Ax`lFxSHV hp:&ץ7;G 6Y,csmӾII6⌛o&fӲMpԞIk{,pA e)t/ q~sç Kyt ȎZ`ο^.X腰  CKM(y[dM f*bd@π8"f+CC>}%^~?{.j%I*~ZD!]A²her_z!vwi4HԋȜ ^*xׯHH_@O=}o|$3nQ.|8.3 H(s.ׁ< Yj WK+ >(cZAM93ew )Ũ\az\j-QfpPax(')]$V5;p_k#WFzȿ0yQZ),AT FY:/x-{bWFj%SLz$%|gHȣ#RQ?<E DG^,a Bvh~r6XPSB:S@ |􊇆䐏B L\鿄Ԅܿ mHQ)5!-[ /ZV[(W`3g◦y*ڄ*~y?J/!Gh 1=V#G͡cF!-:h`-9'Fr'v8-)MB E'9Pf"r-M"X?>7fDb xIVrVhIr"?6֗u(&wbx/}btAX@<^ XZxZSęumWzbr FG#DĉeL@x( YaYm nAqpT8#ƅhpx͆݁q` 5IhdN/B*?\kT >>QQp@! @3{Q;sP9x}CVV=}pDD_vU*qPgSFc@O\|36-Jvkkvpkѳ!K@f#556جq%?DV!q` מxtU!ܰpEj V J>5_;"}[ݕbK _Ms'SA|S_>Iμ`Y\ߓG)48 >wg]XR`J `Vh$ƆvΙIWCZ 2\⺈1ZcuRa F+aE LʶfƣpY~|H*~|W>?*5=2QE T9E|<{&X+Ǣt :P >kqaZO;6:H(-83@/(*SZc=N[Dk )$"EADJkfw䎫V O zl9@vc!ҽ,-g20+gqBPjPka~ Q<[e΂`+^z19DX*:.5 nH:5(W@;&zj{xM?jy!04UI~iQɺH+"::;E2f]Ciڣб ր¡P cuK@8@Njb5= + 3TAdОe*EVy 0[pxG9Q}';G6TB`Ic~OHϾ %+)D-*Rk QZ+?"ZgƧ *TTe5789ГAuhT-Ym@LXDky2?-5"tf!oZ0\DhFS=ؽCz,|9= -K&/V\rDQg[Pg[جN*zM\p\Q1ʵ`3Bo› `yd=PF7S ˖EAJRH"Ҡ{kRQt7ׇ(3l<p߄_'e!aFヤ8EfϤ&ۃ׬"Wo⼰kfmJU6S16qh;V^ lhz|}DfU"WA/άOO 'BB嵼tB[Gvq^LZc}ݔ 9O ۽%P.uL!\%0=* ƚe;Z끤ci&"y 8ȵ&m0(][SJ-|=X+ A5Ȕ- >aX s 5fI}!di΢%~Cy?һ^){ˢ#G腇~Q20GP%T|b_rSQJ |n :\6%DCk)E2ZuW- [= Jtl S΋B$4j`8^21p?=dbR C $ lwc/pdg[7`҅ؿ jMF7,l^d42>Z, |tCHa}> pHRGH\sJy&@'8t@Z;.66JjR3ƺ=(b‡FeJX[אά xgO:AQĝh%}t Y*]Rs!/aa7 Jx$\^^f~~Oo~-#1p2dК;/CC̏{!pܾ,b> ( LCbT1zI"4JnŨ@EJiNзUO?})t~l@NIc!zJc\DphHXLD5?׾y#翔n6ISQcE*J(IBokNbEb&yLMZ;#r?^oz%G qeA]k1{K*!_ =wg?zLVKCleDWUXf08 gWfx7MLlRU $'XFcV6T@SztXS/|=˦Eh (@U,TLt ?s}I SKL/l.x?7о}+I! B` BT]j) )9|iS/ lЏyI;ַ?@X7k&^<366z3lYTJ[+Td):[YVB`xZ(YpR+ɟ|XS­ S\z8Wu$IQ{- dsTR#1IV5g >̶0cZ@hh8~;+Bq)%@G>!svJX{HDT#Z>gIRki)syȕbYkvTTe6Z `z hc2 uN`M=j?;}W$)*A~? q_O|sqabKIFI,QôJ!ptn])9?̍^!@"cgqڑvӸjMHRPiRp!,uR@)"q4ֈ5 2[k]?‡$k=pc`&@Z|N9kAQXĨ"'(؂h_<،UN#QWiM>y'/غ&&9 ._'0 h‰K B1 ߗ [Ծ}AH}F7vUuOdי>7~F &`Ѻ}5E@Ql gjz$kg_u|lP?JLCTs$m4 l*DZ%~c-;k6-Iku LA92S)ԫ2&I*K4xoɩVW},F^jAB` N<^z_,,aj->}!Pz#"Wb\#<7 ]GIx?\X)Ф'NQpu@-pZ{8`3Boz{91zt wCv PxoXe< c1AFfI[FG#s.9Oɿà Ј&]0u?Mߡ{BŠ$dl儺9̜.[iWz/FI\Gh5^m0 %ZۼVN' Lz͖1l6<،Лƀ!4Z@բy)a蠱vP9\ %|`^` :a<9*i'5ЯyP84wnnn埧yؓkI($\BC{}t"?IЕu'SBHt^nC/B^WY'֚W cy"|QoZ73LV枸mEXkR}/И[k-SjJT­?Fѻ;kk{& iDQXtOy7% XfqnVz 87Zq K@h_'#'"P 17\`BoHdVU7Ip3'`#)$"«5k%Lh|ol( V5ux}-wya k髏l-%)I+±4C`#kwO?5Cm&ǡ58du^cb_?V^?]hǨB:QVkVd(!ݳ ]`~ޝ]`8\ n`Yf 6RA:yi̩x@j-%-D$)L>:{﮲"D1| i_v3pװHRhzKܓ#>kdpQQGJhЦVKP 1ص+ep-04IоH.ȿvOS~!HpÔZiL_;jͬJ:t,áhݕbjn`Bo \A8Ƙ:fswV!p*1YVڟ(cC,´ai|a}wL]p$uhyKA/s\5'6zT*f_'tw5W@><?K7O{_L~ſ$q0 O6#U!Z( P[AG?WjkC'qdͶZ@&=13F 68=UITX@I,y+[+wZ.i `3D.-W3Oj0~Dlg\yW?DcFU1 ah}a8 C1jg4TAɏ&O>i=جЛͨi#ژyY])'Br*A~ u~ XQJլG*a-Lp#_/)kbӿ[^fcʰcl n"P濦zX2r`:cc~}8=*?>_r_q,X`Z)%<^O6dvg0MJ墷nƨh{1D, v`QV z4RXADOI>@0]x8%Q, A'gտTE5*9/{jfsGtqJµJC[Ee]jocZZ뻒$y (CDznuiqo]q:̆c+ )Cu2s>. E􌓙&VdjTDM) dmO:|- v# to9_@&lc]hQOxEϫwUFK֟/Z+;*JZCǏ$O5ZXf:*ݎ; _?̒R;{qz1ookx١7 7[1WuՐxƤ`j/fat6\b kQt Sv:Z ½I!0_}x@=ñTΕa+~& WXS/}?λ7}thkIO29#`R e&?ڧ:1×,K!4\ԒˈをG^JXN!r _wp[_ǯ 4j8xnRW5 !,/=(ha;涳AtVrEk&I۷z١7 -y$pR*K"q0$#Cs쌎кc@hy)[Y V (8pT$Qa>s+\8,5 1%{Y4w"A HbHbKXW!(n?C/Ot҈GؿP2!_Je$BR*2*nJX aq8g_FBt]?X{|s}f,NNN>Q~1+C,pc&ĜsӱEʊ:' B\Y?)*A5e/;XM7v\F ׳thSt9cb:A^Db;= 0zw8/KOw+ #.۟dd>G ȄJȒ)k:NsH;٠'tU/+k{ߒq\X=55_ֶCnhi 2M2W=y;s*%C㔂" *r%9@2aQK2UPo ?1?s8hZ_J\H'4'[|0dNV F/B#,]7z`'dMާ Bggoml c⦕Y Vv٧E\HN/"g+J7:RGMyvVݻqf-ͱT7PڌI@X5ݤg]br*#(:6 yh7@9 _ٟd3+Dpu$qbbNwth^Gcp؂ ĿŶһ3 u'N,֦<3O>l1HSQ6/ѱ_8#} \yha&s/F5wC2ҵy$~TJTcM$[۶m{ڏ{(!+h8Hm3`c>bC5DQXVS峮?5][xogeSiq5c @j')ovng0 bڏb ޜs@kImBz N7P=Bsx"};W: %e)v(c֦= ]]{bS搫.>3^biݒy0ǏzZ?r49H8FOk}D\m#ė]Y$^nmu8gHf U&UDmB_:ځЀu }{(NCCCxsul $ b듘~<>C7`X|mj?48[ߎj[aD%~>5yTɱKw;?f8DNNE6V֑9);9j;$~X#3>>$I\8-~g>KE V$s%I7Im܎S<'h~ ʑXW &EyY>  <_~( uM`߁&]+BkD 7r]Ѫfx7O̊'y.&ė'\eȇ0w* H]b-ѺU &W8 ,لEKH&){B\+R]v=C`ٓc[_r]a "eZ0=2zU>7|Z+a(GL ~ Ԛ06b9|yjJϸ|X X?,g??+"N?z7 F0&`T"ׯA(p%~' p5+ߧL~1U[k+} r cw,ܹ_dk+GHX@Rkw2tYO`pW, N*5UcGɶSz5NVoœq4$ 8qZf>&.~~$MP@6LƘsnM?qT?ki~L_0YϘdF(}֕sEUquе.e>vH0+u ͑m?.li,x!G}5EQB>e'{66zspxn48RP9͝l?܆*ӡ^J+V7cقHks1{yw AS?a 1.wŦK| {ï1blF[jc(~4d*w_KCQ 9}N3gkq3)$4ER!Ĩ"~8Sҟy?X|kq5]l/kSr۠<.}ap5{$ T( .BV l0mY jF_6(El\(N҈2 hmQbWnsӵib19A #24 D$"UAX8^G7߁2kp4]=Rmvj.zO4 `tGԯՄO Tj|6E?*.8._(\5l٧1v`Ѧ1>1%C[l9 C98ƇF 0vwDQJ?S9h` Yxu.ٻh9&{fFb1ơ'zҒu74"V*T.>W@Rǣ WQz̉Wz',@, +>݊}~kp|4k04&4PA$AǬ9QoK!4xυ#%fdv ]Z؅X aLM~*{eLce?$;lL q `O'zꩫxe9ePܺsurd/3})M,PZ2Jp,¹.ՙ\H$uiε,ZnD<v^:dYhc Gl n[d#{.34;HJv@Q4-̀()$UR% ;i^R_assh̟:#AeqP* ¹sj/1mzf?[ !B}o.ؚJw5@`N6d3Dy}r'ȖsA;|26 #'ʖ'Jf,=$Ѭ@cju'I< (=cѕ3+ ./M\s5ٱ_J2yۆJIz ⢟gwsw:g(7/?I<$ $~TsY= SW3u[u)P vv 9P(gUճ/Zr6ʅl=?[[*#υdC>a#I=ʀdbs e#T#yH#H2WB_SYOsxv ]We'&GcVw!$~py%c^veq [kX_ߙw/5ZkyXAWEBs8F]w^sw^;-ۡ>j5p* :((=js- Uu&&p(x=ᤴrLJ%!ꀟˠ(4wPދ{ǓeF `M;?~$rCCsU1/>_+aa!cHJGay;whl yp0[s0e3'RXasNԊf5EF:RJA4j{$) =lUQAZ/#IYB>08oXhyB yY.?ꗼܓJzjLRFoX+Ovt|S*985Ƈ?aWj8뮻~(I<!M&JeD< \+qtgYfH6+,]P."NhTz$N Qo'?!pZzZV@Z*z%ĎG,@Ld#ZYU>* MyD>"4y~ۤ}.|j2~Q!]o}{G?Y]wX{(=_5 >=gEQ\SQZ,N~U* _&: 3cktr< c59RC2% =Lp J$ vz Z"C<2+lh.FtTIpNGxj`_'35T#,_t#F/XN$4Vs߈$If=$F'.mO[d4@}H_M7} _4t=_\Y:,MKTRz )|&|Ci(-LD֭>J! f@ėd/vցnePdfqP(=YWϠpz$I*4/z9<@z{oRUY:I6UKUׅ侂K{WsmkU#qp!Vې&XS#b,^3M!TwH,JkyƭH7@yLvM4ܪV!RuFH|i=6"5.oœyg\'W(B ? |}/jʧf ?6xMm:r)|g[o?QV@Hy JK(24.<@1?b 5cI "AO%uxyml B }OpOM/78H {4θd򜕀SgƚZ@L0{<__uXǬXL|5<[ֺ/J}^;MO*K,[Ю1M]El=F _B1o p[<{AYge7}nל懯8"޴Vf`@L@9(2 $e29$؀)n /HK˼~ RO'ѧMˡq"S8=R5IQA?`͈''fggsm=twt?I?xM#oz ?z6v({/['sakfS5)CO7Zm8l04xR9iaE%ee+"* ɔa 4."Cݣ$} Y z(&"a֥ JLI),nƛy2y5<#z ujdfԳ=Xlggm%^L?~1F D%[q|"fm5Oaz{nx1F5:#U.@[iIaB wYupn_\g]B_>m N=)NIr75L zzEXQ緌|W?|I{wg^)T?U6xZg{ו*`dttT/=^H! ]xDU< mVx26Αi<~<3 i1CMY pRX[q:S=Y,:d'O2q"W(‘uy֯輖Ѝ"'җ$`@0 v -7RKىN{nZՎTxӧ ?Mӆa cY sA,0[G(KAFUarZ&'U$e#iW_ЬwHW/@>EyNHX$awoC P͝LCPϟ0Ϸ:[|:v^ۿߓq|IOR)q, 8F67A9M? ZLj%>XHį%&4~il?3oKdD6sZZ~k*eZ"e9OGӤgMWT9qa,hcA9)H)l)4~VdN\$,+˶v"y͝P0A $~j}x]珂 n᯾X`<`K`s g.zXPHx$??O?gƩZk[k %Za!<ȡXƨ[Bt=B~ICˠ jRsC#]J¯|u2=gْ֐ `$fr+m'Rڃ5cjhi J{jj0쏏]yϗ~kÅaQEdtןE`gK~1$&ց^+Op .ق_$I%\UF?\hqˮFpm\o}PΡfI]ڒs?kggeQ80F 5k\VǍ0S$۩OOPmb0IG+7̯ٔlFKȀHe޷?? ¿>'i_,JU &~#@Gj4M;p_.Qq訖@+R Hxd((:(͓ [.y,arP+׊VA CPnaZ$##[P(V5p]ZPځŤ]Wvd4 Fټ~yxPTrM`#nEeտGOOn;Bz56(}-b.-?̱>t<ԋ^moy[[@@$ $#Y{GI|PPjlPk5MI>1K{k~W_}@)wKr@.aZ 3333<>>ſd%WWhB]!y pNnZ~bxlZ: -)NW_E "hEK6Yz!,9 3!6B20 7`< B e W$>l=tw whE t;%I?C,\:O*@I :thWp }2rm|~^c|]LZvww?.?!NTU[(a@rx- !:_;vM6m0a*%M. ,3 MA>!`_z駟[-KM܂4`e@ՠs@:Dx7`H'?Pcǎ~ȑe+V3OH@LW1k_q--Oy睯'3 95^dG'r7G`z t۷oŋ׋f""=I`w=:95xC='05@ τ9H}&1`0x/;$ٞ]v-U"dU @8ySz=׷] ;/?o?1X0^OH ~^'8'XPHУs-Z\a T6Ըb#{|gVTOe'|W^yg P B(B G$ _j#p{3 $A,١U[X'Î*5P^kaA D\^@e9%oKf,ɱ4'|NND( a@_cDD -WEM6S{  j tU{{>Kڦ|[?'IC0yfI?%>υR,xocnkkF$c֮];U`3 | dL1s,oZq}_ȎkyV 'ʒ?8!.&PW=$DRY}00dQTMIGh*"M9ؐ}cǏ/Uz|\LEq=(<""ӚLZ'ˠO5RԿ0-y⡮@eSfϞ=Ed0IgHh .뙶\_~VG}uTz۠}Zsf=̇nIΒP]*`J{qS?8¸:j~A&p{?_ϟJ >}4wMD0 ș`eEMJR-!62P0Ry"7Ad1_:F넓QgݟQ唱&s/"4,BQ}s =6A1?@n4.g۩I)tڤ:::F+8jlL2\ յC:d, >/Ϝ)AwRM4OȻ)8rY/@EnDZK-H$-Ɠ2"k6BE/I>a+S{Yѯ6-mUp .40gP< Ƚ-?ccP >D9m9Y >xv6o?a{؟X|<daMH`_/ ݿq(Ot ym 0Ě9׋  J&m]V?XR9qhAu$}S0C?KM@z#D\'\ b'~lNۃm w cq>g&˙ϋly @c_Xe}zQQ~~Bi<'-KNdO[nDz}Ob  VaLl"_pgq |QPEo?wVcoc,rBOI$9~ ͟ Rc  ETW ˇ~@Ky (Pc+̭?af}) 1Gı,'aG@ tTB>8lIlMzpd{f]Pcs6{;G`LtN"tX^˜9? u# Pr=p- 传'ڤ Ó雅no7TȾ|r }~. L *bsPI=9b;зSP}3h}z#,@Dj ~yazv@`ގaio( QRz/@GHpI̊=*qN_Z۳>tң+ k³+b.xoiQmo?Lvyt0|~gBd'<'3=*F@|Ɩ6$yف4)}֛IS0B@x/yζ"9^obO oo^i/j@a uYI46눿Lw;LM!^ QΥOa `uNLcIL"P!@ $i.r(~Q@&! (x0< 3*2.\>*hE:&r.~ 8pqp *q~͹z;G 0<'Tq?,RދF+6وpn8@#ƒp As/8,@A\&9#/|TZ|h){|-1Ԡȣ~iDV_ב?R=6"w=컄|_iӧ:Ah A @ ^e"8IENDB`‰PNG  IHDR\rfIDATxG r֘6($"r_ @ @ @ @e_铝9Q@f&a98 03333/gv|3-~'=Uu-{U=le핕q|(.o$q'v` ƒ,0{12F89nwۻLW_$\ lzK/,,ܱܴj] _xqG*`)R^ 0 F $I~ i L, "k _{i#fBojc(݁Ft?/0t*hIb,·esDxJ7u(>f 22 + }$m=VU~.zhOUS5 @f#g1O–.У_JoﹹQ񗭵mT{^o.]Ae^31pa&?0QE---ݘ1C*E_ k);a^I @ƕAͳW~-Gy L` .#@wW[]]}Vu/ ~@@1rp)I 8ĻhDo|o cLho0lkk0\ @3G+ ?]#7ǀdY&ͱ57*f/R [u__4I'P5HTtÍ1I 8?@{BOp\P38k8#ޥ#F:I_W|W@3 H,P%>N :*SH 3x-$M~_f*\I"N+TCv&"ɻd(7o+3GI},)RBӁ]yrEƹ9D yxE(s}WT_J`f&@~Яmp62q^VTfF3}@9AֈVPH#Gң-?]J7eF[2@ '4&F(eeO.9aK^.SGA;'d\Jq{|A%͜EI`f'E7@X~BT/|A'z׻^ĕh|ׂRߠm}=ra"?il7io=Tm"We⋑JTnEK䋒]}tmI$>}y#0`u;Ehme/]^R\ZQ {&Bn,} ğaكk t׽u̒OAOV?խ`]( (嶌v`C.tOYD=xtu1|9uYe?C|76??q `obi{zk\NGfY,TFpڜb$F,FJ`@$tkTUͬjfI;; K໇pEOЫ(;Kɦ$-x35=xB9We <|ӟkyMog}MY}_(Z+ \GS0n(_yN>A}W5(14kimwl1H3 ̂:maCA_=k){,"IfÔG@vy)ladU RXa_/{3@oEj nd,k  ?kp>9^:yN~$ #_>}+Y?BݣwGiy-ɋ k9POx}|gC z~fVnx1?$ʨ`Vy$"-]U@ ?ZϞ_Ͽ@[Mk5GGKKA/Cka?l.! _ ^F0pFY#I?=:{mDk Px8~}NQ\NѝMUtߌ;f0HBF8!P!_k-3 _+. TXkxBLwpj9|0sF>OfJhoA6_ e+Ԧ<O\w/g)^am=2ر Av :s!~={=0o|ǃaɼ)Qcďu+,| 8,c YH{ й pC2x0 aD5+yoƺ|2J4r69 p=[bqodlՈ345`BK8/Fu]|WyH`<)S=W_Aqg۩Nq] +`z&hX55H怗?hG(qT H+gxGtMVq[^Gy}@`-P6<_q|5[ofcsq^c/D6K#"R"MAY[ Y{ Ϯ'W$[ MjTzkINe^\ßA tݝ3~;iN_8&I `9(WoNRG+P`dtSBo"'7= :F#Iu_ aS9պ`k J;eԽ&IARR@ha=.x1)MHGYuqWhoID0n&vf^}?W;3׼<"?D %_k(adx ,?gtf^d<#:.6VLSՓ!(.m y-~k|} fJpE`di׼ΖpfG iwF*+p,l &\7r0~肟zK@`YzOD>Gf m]oEkM|XuZZ]٫{!$pj0,8,p*KQX 6a0fمg2L4  ɑ#G>x@iiE1 rYpFL}jzW h4ӟ^UwoٲJ| />3/EfCaq1_x7p"fWR )rtɬ H-JKHp=,PfG τ,i!pSF rux@h\^^WWsK}hVЯ;Jw c:g2[$7Fܪ5ywvV_so5ꅀ[Oڤ+!Q3a00n3yeDg- #}k- ! ς+p:tιk{=ito}Xoq\Yf#/>D@.= nU뉇ka(4I__p3QZ&5%2`tS?{clf %P87d5zװ!,afK{\{ e0T00%OHI?"|) la~1fj p3pÏ!sb6`/$q ##\O?  =XcTq;6brh+ 9֙ %݅^eyVwy/ϲXkۉX~ 8}l8u񼋕 :r- &._|wI$?Tn8kYcl ~u=E:Z:#ozKK_tg p.Q~w&Z .;ěΉ PVA1Nɣ~4&јj$Z>R+ ~?a;)Y-s#ЬH[cꯦ֋ȖHN(u:w|/Sz5\Fd^q?Gxw(qP`,DsXq,Շ6^3s; :O!'d &%ր$q-{v5$ir_2,?'7~ۆ 4iJx9!5xS ~l /qBmƐaa>)f,ђ#um*uV1@΁Z0:>bw`<8lF]?lKm+:8iA$O-x5! ,x9[9Akα|pŻR.0,18n~c:yUR@ &~ӥp_G&!O((fS(ȉزGn 0c I.DtZYȝsP;羹hDxCdpۨ LxZoloъV@֭UP9E |>lNg9%M2 *>bݚ" x0(hmg z y`ST! 0kuoTULKs@ڋFt]Co (ǾIg2e{Q Msuf:e6Ƌ,_c9%wӔV ;$ռX3G5Ss hX A4(eڲ~|ƁX Wi܃񫮁a#L'1 c5d(t?!SUUH֠Zʮ{9 PV. O@5ڭI_w_Kx_$ Y]s6=l0H设3d'z4Cri 3B9zB^ w7!׾W73w4 A|yDVsf*KRN6FE(%@;TƱA¼ )p$yeAXNbP()emԿMKoB_xYOcc<$>`\c5Z #H'!hΟ'ݢxSJ􃂥N&qRd{$ uv\xKVJ?r ιΚ3y_pj!})Wш5N'$E$KMijގ^M:,KS4C*<N\p`-?W 7D}7d2C?j<@;JPu8@> I{'>Ny]p^:ni[kk%0zYi{ ~t}ޛ_,ak2[P'AŸJU j7~#fl*M: |jX)j[{L`$"D" Jjv`T}+غꆯEBUYkKKPg(ָt=SyܾN `xWXZM7$(e h7Ÿ6+M5*09X(cH|ErUB>A:ɏ6u B'fzjeF$s=W&DRral_zV:) yX p.뭺ԥS25s0<ž?0B@ Bj>7>X4 ^ QUծ35 R[ԓ_t4Y_{P=羪*T1t0]?0U5K >" čGהAu`Z)sXOŅڀ,Ǽ]rT=-lpr3P,ΈMQ6:BX3% *- `¬re=1ְ/V]_x#׾ UTC!p jrE o` ej1ȍ2QEEHR^1Tyzn3n h˅l!\:)u,8tTVXYu;Pz#;dBE_pk!f1+z}#GH_ 4-RU,P}RR P jqf5Q8&Z:{am'}#fU}jȮZZ?ODPAIt AA7=x[^"\c cLa~*?sj{5yʳ V揂_q5ϲ+ٕzYp|z_-1cds+ǦA?Ou(`TvI5}PۨV?Α*-UsM0E@*jXB@ HI?^=gI9V)>TD0Q'>$. t  8HƘs=c}~PUU}P_dvߋlO# 0dSIhlE7]&Lv1ƭ!ݏãzH _ZZ\2>O=SH49zHW#$'& ŏQuZߧ@y̨ĸ!yZ᩷ A2sl}2Zt`OeewnKRc+SY[FKB_%c;L9jaa,.tv8@$4adLV# +5E OAgBx!w`3MTMЬ RRj&B_ \נvU<Ȱ8uy .ڔ7}43Ȣ;6{ JYyN Z@"} {CֺX9ko~z(1ؗ3.58E҃$'̟72^?C[MCg8&I\&2׺'9HPW#HBWţڝ&s%ZJ`z$OP1կdeTE `8V$\(F=_:P|#Ӗw;N>, sYat.88770\ؚD8 44}Wwa؝r5)9dp%IIkh %H3t"Ԥ:p;(U j:Wu} FxV&փf=ALEʗ>Oce9  i''9Ucy(. 뇱DYkÞ=А(I;:}4V Z&FRW6 UjA ůCBSjLH4:@_<0z {XDu8&TG KofC_H2 D$m>= 0$p}ʅT"׾v\C{?${̦Aw7@Vڊl _Y{}.DAzvkW6l;,{g>&!4htKhU5{_uq0 #C:y\`:cUUMgv _3L (s :6V,~~9DsEqo7|soO̕6M;#foc4!mHE:5\*LwbnEr|fZ]_"Y쇱R`iDt7Q⩃$>*@esQW>Q qS <"HG緲NYfItƽkr{X*(N-c#FiKQKn-Jj]W+=J&hO|hoaגnѪ(˒ +^C-?M\V穦$Im? onț螄H>tcNc4=X9қowTZJg׃g~_coŰ'1&8l$ =WPVRONw֟4މD*EnTs@g6ι4V#YޕT+4Dk!zv]/=IKր(?DQ`w#{1$' ShFy>h:qMȝ?G0&6,7 ›! f< "_> "B󺷲0wvJt +_g^|^/QG6m};(~w2Ncz34%Q؄gu]G<5JaIEgo0AZɬf xzKuMg6ι1FG[SO/zB}QZjkUXjSՁgatOCG]kACiÿC,o2ZX|2~yqsXϓKE#-[[c~~|͕ydfhԴ7pwۘ޾o2'E3Ia\=^꡻iXd'⺷ XI͊ph *v(tSKN]yw2C!{(@qBԮ;`86H}Q[]U"-dީ 1|rhTӳ2 YI#b)g&>kP{3K#I?I Ϧqm$?:|'YړD{#w1}O?i-!Bӭ\I/|Qb`4I__IwU3Y!?p9:|NVVxcz,&]Y~렳-7=6a,|YUy>H]|'0Ifa`0\ ^]Fhs\䩖_ZCᱣ @$AJS˩-CVffYo&EC a ư~?{ݿO/'?E ($kzۯyN UIܳef,X%{г42T(_zemO}7CRAì?eAi@rh64 Cϝ9lcFЭƧp2jU>- ̃Nx pZL]s[ zﳵѺw%OB2 Y K}J$3yf5Hk=) Bn d,3{oGI=C[)2ZהL'Zj_Eoyot /ΑG/0o#l*6W܂\JYˍm@?Wyr?cÊz6 (CKgtTreNO>Qyuo[.1;F ȍo`{?FoU粀YXY20U17(5/CI!GŨ~\W3X[&1fג,e$]œP,Ai]pc=vo 82o .&iʘ2;:$vL] m{g>B77%[?;?ÇA3ǣZ,|f\ '9w[DǦ\tXK3®H!w3W|T/Wrz@8 -'L*]LIsɺaP ,W`v m]캙H[iLLyYl[XgȔrŊ.EŴǐc n錣+D+qC%HZYŶ'~G>ܞ[Ul4[uM<[YOޕW,`UDF}j|kk@EQFF pf#nh" Ұ2enBD((K!1,m2Y%mwܳ/`y( X,XYal,=s;p(^.^[N'FN쾙]X8" 5> %O`;F;ȓ~N2̟h}|Bpk)o~SĬB7-f?d1XI+WݍM@JbI-7vlO}&h(M3\3%K]} Ȩ"M?_N^^Es\u c΀[̃': ;Ӟ}-w_w,MlS< g&8@;Ϙ!l@ {nӈS?6o4L{6Mxv-lq{0ŷW-  F#!75yvv&3b&uTf3{wk\wkzD_`91vN5+?^pޯ^k-n*jSfioK.t Ⱥ̼_c}/َh?I ȇFBg+O._@o՗ΊwT24~YM#[ԑfK7ꔝ|=acl hd([ $+JLnfeyv1LBH~&c$]SIvoA *i[}бt9s/҈C0dMw3ȯF.'৶<,MqP.Q,PnC u_KO=4|<}ˠS,PpƑ xr mRl,401-<Q.]z^ `=¬LJz"~~ X iQ~5Ra!h;K5{<> g+'Y^TWX]t3 ZpI=$44e]G~ozG+`"l8eߠ24 FI鰍3fbon_KOقf@km$Wj֡z>V;<ƀhbT+Q@hl56}8Z`9)z"T)R͐D$#Ww%ĬEk5U};#6Tv /f[VMUU43w 'ioK_zQse-^[}xxIgrMT 7Oܭ?0M9 hMX cb c.8=W3ŁgԽۥw52I!>՗I@d햞9`=̚{Q37`477#E "B rYwѵ8cN%@,L.>}o[dթ;e90WXi< LLXl!ƫ#Tw}/,yK9v}b?DLfLO@ eDUa37_Ӛ܂NO!c|zV$K4& C'di͛&"#5xxoOAkT>#g6z#$riМĜ1H})A8sMW0dElba$݉݇r⼿R0͎W Y#(?M]~3 oԘY^ο_lEkT7rsdƚ`2<`ܟ1;8o0Md[.WBkyT| ɍ0ق\f>[Ŧݘ; L2NzKdP9aY lFlȽv @Dg6yOI? H s榝 2[wpE](dK؁8]kW(ϻj xM]D,964h K/}t$.X>Ѱ<6ٰ5`NæEv@|8|,? ny,"3жhFh5I/ELE3wl`ddyzfdҝ; K5D*Uvވ1&tNa?E>֐[e$x4E(rڛv , FYbȟcPk VG`b^`d)8*ҫY;9+/ T.`ȍru9YdY=2Y},rI9W `O9a 0G{ 6ZisB#>̓߿!Nja܂< *o L$\JJ4:z׼<ˢ`k#.3C$l q]y4W?̳>׭.@hKu8X SiEmߚ4*J8Ug x˪_)>Kub d YJ~^UP'ȍTEW٢j&ю&u8h?@Ti;!LrjQ7crƩg? f(coi&Q<#VT^\ <p,[kD4k19&[Xgkkjd8@ l_MS5_<+Ea8͗PO$݄P2X38 (ۋ>vLL5YEZ4IP[uhàQFrX};P@vnK ČlCs ƘY0a8`ZάZb2*bCo>ӓbj*l$(bh\}!`_tKIf(C ȁ9)4T[n'04l|};D, ?wWh 3;@#ks6[sȁzcOIȓਁ]l󏒟xfkZY eGä[vzaCgnT,{)Jy3Frcl^ʩ6+C kϣ#n]DQQҹ},$eT"~UY$[!-DQpgM  {sF4C٦z|HL11ʄ]k*ZC4J Ex5"Smw]+dK:~>nf=>̌·%Ì46cwmd CAQ__V! @ ?;}m{]p+J ?|33_W"^o֎DVnx>{;D$YF ܬ , Wшm<YP7+W}=D4,cZЈiO!Ꙓ_cx !?o&*.圐Ƙ:.X0Y $/V@ 58d-Jߡ{;KRF7?RL0qACOMhT@Yuqvi Xi >. ${FC7jm>U,^a6Nj /-&߳9  ɝA,`? `ci-tKu)7N=$d~ꂌzIGMM@٬U@  ZMDy G YX7G.¼46iEDq ]\ pyd J)a,u~k 31t4?Fc5[l^aX ఈ<_0Xۤr﹒r$K҅Q~vI v'0>v7н;Y){ ye"VU.EJ.SO!0ߪI7Ġf|>U*7zҫ=vy~O(cNEBHW)ߛjLEĬ)Nٱ瀒u< {,ZkOZFZG끜8c2ϳ &,"; szEz:p$e$H9@'Ja+obR+u`O>9WoD0d.Њ?BIL3ad4.ٍmohzZƘG|b. p:\yt`ɐ){/c4芡{7T$; lt` ,1~75$_Y{S3&Lbz0ٞު{MBBϬ=Y) !PUNG+oEd}>S5D9x]^netF'I,..2LC0ZRm ůO(0̐ӸBS{f߈ub0?ٯaF7 X'׹>I`mI)\|,a)_#%* oqv>,p>9=$eɑ hFQ*%~|mI4~z;0c[nfC|OX(YPqU(2P3yU{^_q.@x @Y0 gX pH\=X!I'hm {^NS``|Q PV-,;,|Yy^wXp({)a} CJu넛Wz}E U P)8ptgbt@g|2ա/g71ۣp hod 19jZ]eo۶@;YQ/"ԙ^H6뙝kYUf6鬁7Ŧ @1Sl;b?OjZ{>;)@J > I/6J^7B=r"¨\ qj*o ؆O}Q}{lu0 vrOfu8CR_K"jz%M33f lu:GW\)DtB`刵;ZĔ`hn 9. z^ZᵨEm2G;@v[mX 1o.%z@̫Ar ĨJtx_thw#| guqd|w?wY?N&6NB &j ]sS~{-i_}1mW diH$kП^rE,gz<ۀ#u(ZJإ7yyh(!TicK' PT=`达׆ZUz*^&W<8P*bQ ᜲ R$1.~C@R (|CZ3ii:- ~ѧI~?'C/̓eo4v0&_S珆tGCI_qgEFUX@hl{eɊ3C$~sEEީ {gc0@ö6zO@00),G}^BHk{JXԾ*7${92~N(S%_8/K]GgOgd|_8I؀x6fM,tVo]uMd_so=,pҦMIiRs?"-A@BV{1+9/SXYm,c ,[_'a=c}?Bv5e(#J?lQC$?S sV &}o:O|S0`Yj1I*IOtC(P_tUگwv&/-%[ƘNaJ1\KFws7*`)Y_>_Lq@rL@{7erԎ,Sp%P'^ H@1;̶ OqƶiYY)q@/)u?D$[U遗2M!I;rb>]l2$zU0'ah4}~x`[6+Cڻ!FLc|II'9NH\積 >'.,ѝd,ɷc M_{12XsN( %iP~?ի6~l=u- c'` ֦; m@&ƀUK@>HMA CBM]ƆE%1tljje|%| pN|y9*vi ?bCP YGX8q2MI#굤"-f#) x3oi8y{|_ŝ3`G|Bx\RRjJã?S:qp7!M~fďQ~gOa7Ll h`,D( *^ 'ZTPVs@:dWᲝ<GFnE],˖Y6{Y8 ^$G1̲qBzn=6GY $m=amV%NJ4؃>̓싏|fXA|,vD7_K|L*"Յ[x鷱G/ MEbFE%'Fm 7![^ 7:Ź/݉^yo7VoPHJ[䪪pHmz=~ӭoC6C$|G,#?K>41*G_R5I'J% p,A6Ȉ'm꿷st9 +li7`|̔ӭh򣣤 Ara^21+}tي1Dl\ ##N@is@3`y%"YDZ!e@Sb728ˡNU $qh]}S8AqJxo+N'YVvxzւ.Z h4ܿ>YxhIӥՀssՐ^.:?w:ا^+}@,Y+-H6 }G ƘwNӍNPdƪvQ] Zj.;\83Kq$Pƈ$>fZ%Vvx/>mƃ @fÄ[,=,T,O^KwFjXkV115f ~{H@> L+D@#IOtD>9_D\Jul@$TR6+_oco;MMw֨߉\ @ۓDza\g" _Pe2?K_(^|mwX,It _mv Zʊ ;=6K]0~sm`/ADVMݓ0,Cb#[F> {N 5.<)3Jkzʼy(*!Hf=tn|'2 ݎ:X{m,~誫Ӏ|d'˷nG!(xkUUoI~wq!nA4IUB6M^AefOad_@^k""$~uqD Q_F0cCQ.SUOP.>A1!(*j2$!C:pIʓ{o~ٯȯ54A?[3vо +)eP`Gja3ϭ( ԩ_ (WWUMDb@6aTSVѼIwr[*%"qK%.n5OфDAT_us lI5 -= Ꚍפe҈F.3Q׆VՒ 9~'jwa$?*v/Wri8[ھ o x-ߊddY3=ۏ GU:gsZɲ,k`XFEBꁛ{wt([ m[!^Z!69z }~nC߉{kY.H͵h6@g^$&>* JW !WfS3غ Utفͧc] Q>|EkO|?eP|gP *|?ip( LГ4wB~8mG}%gJP"MׅFH}h&[` ӭrt |jלLjj@Y J]XE|'?"UϰT}7wO~:ؙ &4}򯬓9 5~zaY܁6-a$+k o䎝,;KY TfkєBR{ΨW:K@*d( lyX G 0B@nG >D%X t{ P(2X߿\r.7)U}!fÈM7HwEV?xeh-Y/?z|C2o}[ڇz蛪Op .54|+jG)w0>6ĺ5%L ;W gSI5 >=a 2 ^fʤg/wBY G6صdžM!Sk_yh6uZBW8ß ~H>j}wuW/jda9rҪh@⡺eeI߼B&n0 ϱ]$4abPPO iٯEC9Sd{;hҫ]$|$5*QV}n}Zǯ4}lpBQʌ#ҥyś+( f<_W}_ HxmG v/e]X˩g>$?#? !]3҃TUZ-CgHdʵW=+N`5]R#:5GZbWaN#|t6\L~oe8پt%HhG? +T`L|UL0yM_{![ QE?w-翜e٩@n6N͐Fޱp@رc7eKfHJ.-M6#u~ GVd})?:~[h^%~IϷ{fX/G #eH|PWQ:[ZN MLc+DWvP1>/zE|Z?? ??X /LZsEzԸ}}k^#y!t,JiD +>s;Xcy! cT ީ `ܷ3P¨b"]%r|&HOI?bn;e}\(aZAWubdY3FGkQ{xnXG.kiB~klz.[M[fY{~c̿βlZ G[Y -ŧY~ǟe_bZz ) 69BFgS^i' *( 3Uc2Fu%/lśqĴȲ\w>c{|OO}ѺRhdgG.Lݿ*Pe?ޏ#ut!b678 0u6't8j d䎑~A$f*"zMvC:@xYk 6*q/Dbn&2}ɭM=l@6ΈI_ _ٞ۷ )2ᐵ+z֓U ?W=?y޽|z4-gV@L⨵Prԓt }k`hXGf`I0k(XC2ZPC$}O~@C4̺]~K^I~&iEs@/7~;+w}w*kl&@~--P$A<&!iu*qUNҔ,yguMf1@ ׂ >kq&= = R wn#_p =Ri Y9G$Z?BEp?c/x [|˚_e]f4Cn^F8-[c(+ pd8;RsO2qrjcKY*4ҧIF[rK->א>}ݓ^%,Y?}:as]t Σ`L cl܈ |gxٟ)_u:Wv|O^ 箽 [3ݱ'V[G{ιoqRU/ia]j??=U :H$= $)3MvC2g.r3ۙD.דmpL"nIk6"Tg_ Zfzk{ϭg/_}[/ ?_gH@mKUP bL9A^|^xy&m)H 7=@HBVpF_]i|C__p9s1>\Wo͔~l1 mĸL$Zz%XUI}cO߿=EP ~y{_Uױ8s?gFޗ/ Ǎ7 ^0fZD`6bT (KX7K.')O=ʾi8ŴXxĵgQ@{7>ZpGz=oX2fiL}9=WmoIČ1&弈H*t%tu_ s?O>j]y :g~~@ oMNGZjV.+4󼥅@j(?tdpfa}d/`ecT#I2Nɘ-őe N[$~ՍaCnIWq/KEɓ>;}nQR|5k'h+A zA ր Lk{e.} m;%~:;}?6N/ RD(0F 뵿Z  Hd|Vu1Fk`dp 5B>ec"{y!OXZ[-hG#96d`q%|૫ @)yK I,l݈ݸhlgC' 1RB|_YYy>X(DՉ'ptUKdHac@|ym:Ab&h~J(.d ;~\G ĹX_hA,nCX~ ;EʙT3'3YK8r'f c>"" hRwO#S ȦxJ(]'8d-< o̯ٔmG+耟N'__y0*ܻO3{/`4Gg( gܪZ <7oIqh%. :F9!V B9ʹ3ـEu {ulY@n<&4aô;رi |'-}f%VIA ߼@b@Eu䠹[uk&[_OD:45?Bw=OW7kozuWVYg}Hlr||DP<h:Yy)P5̺] $P͙3 +(o(T5$0Dd`H y_4O N-fi߱i9< ?-/|Bqہ^g= k=0iw2Af"DM۷o>mڴ#/rhiBj0bd`Al'B0z i AAo|?+;vR(W8΀{$A?H_a]JJ` CHEC׮];W{ V)yCY~7K !6_m{uw1QzW^D]O!ϗI0ҕ"€.1;ۧ5@쀞^ۺu먹s.ݻT%;J Xqӫ|obد?z1YK,Sz&Q/ Qg *! {E@8>du@ 1yʕǍ7KD0hBA` ~UNy\:~Tai:"x3A /xȾgI ;D0h?v!Iݖ.]:N; 4x<‰onI]7|  [j``Bb3 \ $ /j"kݴxرc')Lx@jCo;Nuڥ-?|G' @y13dwv{K !줧`N Hpy{`>>tϨ9NYYj} [Z<@b>'!5} 0 k=+9$ȃ̺-m 8px#x7Dխ=ڦ_yv* B[3ȳ's"@  K"CՈ3;Gݙ>&_9NU+䂶ޠm|.?u"" O&ȶb\{zIznL=@x!e$ʓ8 h^APΠg3I7ߔGU~اN<ܻ!S| {Hw?D>,35)r…6!tS{]$.dY[uѹNdO %˥:︡>| f0>_#<_ "rϚڀ?H@4.߀v*)t)tСSNhlFZ"i{Z$ J:InJdoW$%J]R͋s9Kn;NaLtdu *9cfI yE"پmDє(~ [@AŠ O%:ѧq]&˄.8C ?@׀fe:Iym@F6cFY:w@`>Qfs[!c>u |d>)-:qMsX%4__tz1+,=9ǿ$,0OZ7#$Vr5 ̭s<<1$3z)/  Vkߦ7mIDs ~<w/l*O/n-ץt;xfOn l~p0|m0*Ҷ{+`ރl| \z k.gnE2mRi]?vPuATNJgvIc\$}tߜ~ .lm!>Lx^\j!W@y5xINwj' ~!hw\l@>*Lvx)@sX-zD~>@xGFm O/ r rP `|WCցߓ@c?ء׃YZYJ 3NUj^v:FwZ &ԫ9>Te`-e˃z'v  ;0D zyy/@`O oy(k {-S M k-4~ pج<0YO`*gՑ.^SxzUY M{i-. Fw `a%u?4x1> S@.Zp !hik؀EyBW؃^S>@ H@QƵVx}$(IF7u1rX+ (bK9]t7{{?!=@X.U1rHL;&OH'\󭗖X.'_/Dkk:ONƔkI 2FKн?@e΃܃I@ps˪! /u^e)sV/b~P; @!^v { x Nfk01`Ny0AR.)MH: hP5ەӜu9@G3J;{3jMH?=`z5Co_۩A 5 @sǑ]IENDB`PNG  IHDR@@iqtIDATxpȺݒ<8ef3{̓Lέk?ߟKRS(#Hڔm] *VwE{6k䭵t%$?ڀ- 9[l&W$v^+{z OEg216# ƞ h:"X ޽`ϵ5")nn\So>wKaOy,4JLy@¢ k(cPQY[D{B.pϯ:$Wep_4کbED;J(VҜfHqĒHP-E5DcI[azjFK!$j>t|9ԙWMĉrO|QG;zҍL1汩eo6m!cJI"etlK\mCծ z 6ƞ^WLm!..;o+G>!fxdb,0с:{w 1Z/;V#,X\{:4#˨losA+$颂 >$ }nuR3ƒVт;Vy|z% n*}e"!xoZ "-m/S-pXGwjn{ q"}E=+~זW̌ ZzWV ARƲʸ)ns4@_5!%Fں{CA%ؿqݣ5[\[ʆWc i^l.N&'&l#Ę^{1ԼmlQ1#QA@h:2dN,HQh޸=—~:p]{? 鵶gCs -CnNNFt;BN1lh#p`lJ_pކ )GR'F!@D듈'H=NV .2 "Y,ZkO>16t8͕G+x@Â1c <2{k%g Ť(H7J|4ZbRO@[<9)/+>H뎥V0۱2iCHK׀* Nc3$<@] }B!W<1+o2]FoSxA vT {3-~U6Wo/ӟ&7V8rkh[xl+e>Q@z#<{) k?n UβednIx`^뀓Ԍ]Dimi斶6k&f^V^pñ/lZwWT$&tRp-7%;F)  >ې`-ks{pHG--EB8vҭ70=^5ś#J.T RZ7 [G~D Zo8ЄKԫeMC,BZ@T @ `,ˆ#WbW/qd2jO GX(GnXVJ=~`4O+-ZkH3EVG_(Z@ ˉ$%iƗ쯳MQb!N{!} ƚX/Z [jRľ]}vEV`i+wPnո{0­#?~ϑmXC[a!G|:RrJ"i+CmжX׿ |mQF*QO-$ "Xji>*ܺ#)d .RRрkE~E`f5%Ib8+/@/HywԅFD@iZdcNˎZde f.U}@$O% @:HD`4Rʱw2]w.=wEP|Ti{#{]@%KGJ\[Ut6eI$ ֞1Ȋ!yBq.e!(I FbD(! F&Hlt|HwAQP q/IxݮZ7itKX RA@|r+y"hl/{I{K;WXb2YƊ-1BG0ݱE:rn`Xȉмbw>OΧK]p(eܗEpR b,r7x*@B2j1K5_iUӋ6GJ=@pt{fvVIDc-ȴ(CYvwMJj|mHqJ@<ٓ( q["V^<`(Wma"giȴ$KŻR *Ic΁xW3c6W|U[}HF5ژ`VkGP<,'z) ; az4DFݿ$?" s)nP;1\%OS޷' ܸsʕFJJ o=(ٌk,w4[+~ bv 0 YO9TdJA H|PMb^͎"s,|K䎤o{:;sr&TksGVrS>,gYo@TM!ĆnԪ0=&넫A: tXb X+3mXF$u$^gXZ_V\6Tq"̷-Nhʀj,@+O/gG݇#5iJE"< :. ϥH[$$Eh{.wyj^Ĺ"q!}jz E^t-vO8%@85*ˏMN/[l2`rR"EZ!a=+Be-fɁr%C]p۴iCnE@A"!ҏ~TJ9z<͇t5MkalfɴRZjqi3HGeXh*%Qs9d{ks҂[kq(K41=Syıw|cOEGP+P$ό@ Q2Ȏ]#}juRcɴE=}P/w1RD)$Vfw;jV|mTsb(rϴ8tL=$ZOb"4` D4 CrDa1Ń8E#܉<½kڪYTcG9vl>9Huiݜ:JuSS1R/8vB{C|7~Q뫩ZCjG?v*QLOgccM^2!Ntk g!?P="hJ3uk诔bx";d]OgݐW4a1IDATx Pa6PZ3A${ݗ6f =eA*#դs[IMDWK*9.r]C g̃ȟ~Soٸ>{Î 6| Uglpx_02Ewe*Yw93"VŻSݿzɲuB\gr]4ުXDc-hb   ?DT'kR#+u7*u5(Ydщzu~HEoH_vƺ\E\럿a`iz0\/ D'9uRǪJ;\A?`kRܢ$c2&\3#`BOĥ7'{GJy?eVks]W7~\h{i+Ţb EB7TH}TH݁|/Φ<ˡNo:ͦY'5dcYtÏZ~O]+|q`֮]vWz܂P>K{@ʵ{_ogbUy;;w eۣ+P =|=mMt:Z˪2 fUBLhp I4C*'3^~̍n|pϗ>$-] SRR`͙JSK׸eONT#Y88כн58{1^<]i%ݳ[ø881ؤt Jq H깂sDK_OR܂פ(%eTKQ޸`lRm]3cX%"O+|QFA@H ԯ'R,PʺqZh&ŵ|1`q.Q||M|dG@ ȷ!^10Bo2{ߘz\TĜ95dis dتrzX`B^;\Tl$kY)n~}dO9~~&gxMU~*Nk_;xe(xexkժzSVD?yK#^G@훝 j*Ma~`*ɘ{MZI#5+@LC9GLYYHKճ#BgƱxbS5'katFɑhlE>CKx&0bT<dMZAQ3u?SǨ&M X@|gf[jHJ1^g3V׳+1FxrE6+hLuzr,ѯxp|Jej*X0NMsuh%B%qČzMSBjJdb0AOMaO`'nY6>| ߀}D{vԻ0_#<"7h<׿CvSf&+8Ea+~x-dv5UPOt4 FL_tʶ /ݻF8Ks5H}#kpQhʑ_O^p#5`]/Ѐܘs qz M 09AlrȾ}۾*m*-u{wig];0v'߆kt%,SoE;x*ҳ rٙgqQzG%SҋN;#P">Ɇ2g2">FX>FX: *y(FH1/;`SDjk{M`0`ܖSw1u u% Kt}~d]t]{d>{[սD=tN٣]w{[u6clD7ȋG)P7l1O'!\k,/Z£7- 4Cd7k eNn3T/8w7s.t}VLP/}{t. T śn Ȇx?mRw9sjvad{'nUS200wrACLn3@d0J\\zڡz Ɣvo5 s'xo] )ŷpWvȝgeE}Hq #iϡ}N`_+Pg !ޯs:]pq{_rܹnȺ9b+u>xm j$$12?]X`y{G#(H>ì 'g7-<ŜFJ˴1#>ON:H\q56bǐ~3:[AtQ1̈G|gP@|OLH8}J]D M/k\ް4>}z 4v̼8K/o=zD<Y^ wě^{(AZ뵯NX53w#N##|΃LAi;"ʹi&QgGCi;+i*`^aU#X9LC:S'~ey?Ccww7G??`B|S@}哞"@6#(% 0:|pA8q!CE!Վ[e{O̰XvcH nA܏qbF@}`ܵf޽vv{̳BS+N _g]CP*w DoPHA#) (VzkʘkFV|E0}S= G'"'QQ4z7W 8#{T{Vm| |Oc X+>" ]9 > ߕo"l×0wq0T~>rb p%T 1 "HcB>,(ģxAXBm WXȀ<+pFz (ŧ#ڭgݜꫴ'wo5ԣbm*"&Ɇ`gQoQv{GT΂'+zO穹܀C:/͕SXM.`L; &yô&Z S7(E2I &ʹHyu󬧰I Ϲ?]1G 3ЎKŷT}O[] cyfic~ rYgDQ/ h7  Ёs]3b8i[Yn{[yP<*wJ!,@@W<7hE{,Y֭E~"O"{1@,nOɓa( >UIPƲBa~Y,c|&b,`, y?B7`2cQ|‚EroP"X?pH1ٿs}:v,ݣs ot`"Cҳ >qİ gC?0~3N AQ^Ղ>&sA0~=&uX#q Elg# 03ag-@w tC a!At}IW:GcEZhrb|EG?L^>2QS<3¦S&~ .u!گ/D|*cNysi("f:m7 mw @L 1ѧ&+l&"n=+O\r)! fE|z3wWçv?d-1!3|&hd# 0b(` 0&*d6+)!?B,@oktx3Obܸ !K.yW|%}i*i(,xAu_#G?O9q,d'1's1@9F#pkc@dg}?E%LMx@،BΪg1ߏZ>s wWYP|8b6.D[? h&$ J0q o!{uFN@:Pu/ SOo[JuxYu0JxSa]/(}{}}}>y`ў,JܵCG 51µ ۴VQ MF" $2= GA PuD 6NJ h z"A2~3¹d 0o=$v0,~ԣxW<$ LGF37 ٷa,k`tD b [Ciq4UNE? فG _ @W\Bi =dW]=c$I3Y̬cfffff[] -醎̸d$f)Rń)g-2wϚуDЏpp{Q.'l9 !5nY:5|w}ϟo/{87ye.sR40o&tD~C4;߭ L=DM@ճTk\KmDA̿tpK A U0МRg {wo!;ѓcӉBA ),\vsg@''` yH:w^o87¤< MRWO#}+_%F[nJ&OY/H%J/4_X!?5kجO"'޿QWqt='uӻ!*gC|P݇"'!9?*#KgAo_4OʗpG>/ cXȭ9<}5BFi~ % ӱxy`V}l@OE!.Z5?hdxAwl4PFo!CKӳo1 ;'OԾ!=|@ r? p崙l CrpQf[!(^C"rO$kɩdNYUhd۩嫟!H# 留=Nkh_A|c| \էyVqoõR-G 0g&C@jge盺LeQ!~`|G_^3 v6I?}f fPZT8C IdA4F\K7_Nɟ=5sG7Tᔯ5-Yybõ/ Bq׃gi{sݽC|0?=_끤F&s"dK`$LvT<LuWŻv;7JͶƌ܊ZO1tF_{W +!~eU"zSHk].v+C9O}L\;8M*αXoZ<+ 0/'W< 0ou&8]ZyiO He nxzy7<^u`vPjHspPc?Ijy"4 982իhC~Ƈ s!~ZyUA|j27,l)h7Ōyӛ!ފ鐟s߳< 0=?=Fѥ[]9'P+g~ɘ ՄANʑ\l>?rOuDU1 A Avl< @~n}v>Qm7u_Q{Z$eh"s]gW(ۨ6EG O, Ϝi_{5pwTy l#\i Lx>/c7g ZB>;ce`͛*< ٫-]l=C|S14x4 ŭpJx+c:*hۚK޽O@H 4|DG"u~z ͇j\CO.??+985WA߸:N~AAW{Oy=}ߡ9_}#G, @}K!SN`­U y,tu&WTHd> Hv ?drB#\AiϨiףlͻ`Yō%f6 Yo 6ux4so33wlP_'̊z;(wkNx. D wy{С>PH'9)#G8j  iא木DQm$DczU/䏤Oǽ("'o.} }">xO;$)x+g>s&=|7&sl;LJ/cf;%5Vg5m8tcģZi&=qD)쾹gvsGvj{;On,goyhp @6oۄN m =jsF66kYjI,yõO $>"Sb'L-BZ?#o50'pgu_>xT@<}cLBE (ƫj~ؽg"i*OӾMK&z |@16[ U޾TݘOpR xGwsj <&`~EǾ}p l{Lw?Q|UiQEN&7BSW3Q#>QoOQk~ӱu k3_o>N.aàdx.۪Ko=p_9Sսw}_ccyx_O7ÙǼ0 7^}@Z !Ϊ[tA|zϻoPx5/-]k#j{wo#Zܗ\&p:V@wO<[z>rd6ӰZOv,i{͎u_ ǓFWb-> s1~.{OU<;+&+?1̟xԿum)L rځ҄ 8CZ2 B=K?z g`d8= V^]m>~#_wo9\zYþK@uqSo"ɳ*IRN-HyW3Sa+`|ǰ@BZ?B<[^3/][}SԬBV)S9j o)ӈ_xVN Z,}Hf59ׄc+| iqS7?Q@=-ȟF4'u9xºO+w7ԫm6zďP$?z^t~[GӱC-TdiL@b'uWط8rl𸷽𘷿jKP/)}jӇc[^\$ #c5ߵL^D_xjF?FRk~2zǤ.dz9n87k׆n={{:hĕg?DeC4txt}~|~wQZ[g;]l:A֬C(E9`9EVt`hӪuݻ+a>B7cYM/i~>k.O!>k*g`c-8>+Ygg1YBM4f׿gڨ SPyMt>G|z^ 1%B#~Y9 Lʕ mQT׶̝5VQE3$$a 2Y\#"|HD::|Vc0uKΫ ]^>ϓ"ސ |y Od{H=ï]Kڼvny.:ωu%Ltbxpls@dpSOf۷:wxwR:݋xDuA$<^Iޟ ^xKNawω^+ Ds <'*^ɻݍ# 2tPWS ˆ׽}+n!u|W?BݽÝM- OWw?S/m:U=χXwpo`CU8>QEI- DA@K9b۶mUZ_7˰P6{Vdx뤠\GEyY4<ț3<ü.8aޯtI׆`NրkJbZqu3,ʪWzEY-&q> v# 칫%u{;31unvrbT@:㸅Yr})4` D499u|$^(ȷG?C;9UM+~MBZ hLN }ecu^޴N.~uUUlЇD4c9ydr^N٤w׉h1?;1g1 !^'w|Z?QwOkIENDB`]dPNG  IHDR>a]+IDATxY$ݒ{3m>m>hm߶iLO[.Wn3c=ܳQ'* }HWy^x͡!(dihx= y}fUS%@u4˺oWl&3)yf}m-3W-0MUC;GGDcD$~*qx1Bh.Z6, jVT2B&* ǶscKKGWWΦr@ʍuttl< v 861ykK[PgOOs0iРVBZC @0 ,T@5Ƙtyp _&EgpEI/j~eyizuy)l/..NK_5?}}}m|mع֎ٕb*2z A$n+* @ ٜs 9;@F `&NEK$֢iC9aeq!xnҿ=t:u:+;v嶩ST~o׍Q>JP؊] @brA,TՃ'diWUh(șWU PP`4 2?H0? N(PoE0jDBmmgf߷w+p;e> ew#}@@̣?Yk&AW$(iBR?Z PF"Q "S43KH( aBe8wz*<ir4XRXY8p$ d)+@.vΑcH;lܙųuD`?r||hl|˼R)PqP8\@E.u,`1M@MVf ô+(lp1@wd`uo  ȡ3ara[zE*,x" êR@lH*M85Z :0T p)#᷽y[2cTyuTyF- MͭVRAjU.S4bp.}]YȨҐ@EX|),fU˼Z+jQF ?!r 13؉,V!&Ѱ6ln6dk "9HM_ D ?h// ohjb}RxlHl?Јqg+Jp] fن|?WFꙦf=C/<',O2".}b*4 ^{5YU k, m@ةY~u1wLj9D`u-|; 2PRйH#s)3w0]N!"טHLfV+K6/Bo~;?яMi )K/@sۥuUnXB%2h8{LwEg٥#H!Iа,SgkvB, 1{M'\W㜏OQDY!8=`8ogP RI&EX|M. *W?௡re]d!}?aY`c+/3a|bLtkٲI% G/rXk2~^zHp(_~5h] n=~WH8]bɊDp sa 7XJ#OXYߤ%7TTM ̜?35McWrY9j㼫XP0 se&p0EgM~G?{E`8B/ϋ~j&z(PIs4-T/=;7!1:t^k9.8@|.͘\FҐsPOv/_>dPO$3@(lLLzO2 AR-Gse"Mcx~_޷wPЩ:<z͢i egGϣR=+1^%u5:g6@g`_x)KBSCsWxݥek ;PvUW=,or@^fB"=!j Be%H=ߟD # V Z"@$~.nG|@4'a}K~Rehܣ,Ӥc}B"7'ajf;GD4f$yp%>1Y~#Sl p!FW m}QVwC}}O=ov=H s. d8֠cS'"rH$Hln)ܴVB ]?:1nws8ˡROGypS)ZUݐ%2G(cC> *~zٓ/:>//Z_[G:sq8{;LP;bUz>yȥcn;_] ;lEAJܹ^Fu4ǔ6ސl4MDM̦ӝ\Z],¹?]~w. R)xG`xd[k+U3 p[E~hY<$aG3{&Fu;/b Bp>]F^D+C{,cy됿CuǓJ|quu5VKQ!}AFW,ʱrtUi;zKoO:Åp%L<=}ˡ~˽|LcɃt^@'A;z?}I'1Y> Ix1VklHpΝ^ p2zNW紀rf}4!$ 5tB._^;p({7'aݷ *nO%!r@28 Sۺ{x4\& 6"44|?0֯}?o}UxIFV [-Fx4f߳ecf{㻧cfeff33ISWEFgZk*} pZ^K~ky,} U51'Jhds7лmѡRJu vM,xye}gƅ8@LÂc>*A9&>$j:MfAyɖ]{BAN'n(:W._\y-!DRyG½?;>9[q/ǯ"C2J%*;z;:~` P;㶉1LEIjVr34n !La]YYo<;ۙba)jB@T Fo&dGՁDgHB%f\jTG8[ٵ{_t)D|=[lm7߸}wȽT*=ҍ׻~Ou'tc 1;Z[6[+KM<}?e󢳗4ڵKkN*?K |AVH}H9f1|gNc4 ?kG$c&\w]z}@N;)t큹n`Bra_@yىޅH,sA'}-[38| |G>K~Z[[ `8<ԹbIӜ.0q%D f ,u>TP<>F.-R`*7._]jE=GHS|m"ǼȽz( v9OssyŹ'K8PJmieON,0+NH~ ȀaTzuADOoT*D} x/9|Y=%d5 DH.ԀP'giR*x4~:KN2%S\ jYUr\dMhݽwkg1{17p)3=1E'.]{Ԧ*}<5ptJ=bd.8_:%'^eY#䄏(f@|+qZ0W 8:ɊZE" UZ[ۨtr_rID70VWxtq D̮"7@LؾW5?H 5>2T[vܳUx?jdcETz|#1 5H|hcԈ1)&Զ _C&͞ĺ1@kVS)N/Ăj˞KgN;\K[+GF{&!"䛝-[ʼnW{vN>1G n}lw9Eܘ쉡qU<gkQW+zያ [)R[J+k=NGǢZ&; qT&`{)<*vGijtJ3T""#5^q8?@QS}FFvuv;;`rGI <G!oOPᅷ?Oq(`p#[jsK8]O|rz}1+[𙴽f`A>LnF jQQ҉ZhQ3GZ hESBJ29 waB07N{DSpvzj-ct.x/ᤃ==_~1Z:weܱcW9_rۨᣀ6E/WP/:=ltc<#Rl~~dm40_tUx9xm 3W[W ߓ/]ݫ7_kq=VgsZ\XB5_9 GzUC=|ѶĶ0!Kl_`n}X{,H]N" / ƘlV`)ճBJۡX1ؗI y,xO;Vo]4A.FF' r#&'7/R/X#՟ =>g0ACoTlBdA*Ulhz:Nx #:y5lR?.bCsxn~Hلo`Xk KˎFƍ(~ 9s rݻ!N9LXX.,C͏m~]gjQ3p Խ_Eg/ P(%Z rrU)&Ik[Л%@ {H^%uc 8PL@R7]~ZQ1ډ\3W2s5i>g@e}yi+ u/CFtf ;1xz m@uMO&A[R41oF iC)2TYHD-GCS~:*_җ^<6>1k߾yB>Њ]LO׽ࣳaOD#^Zi][|D|tr QF d0QwD^o$AJԀ@KX5nV9\'$a~{GlQ.8tO$_'Z|qHf@GRU`W-i#/a \T ie]@Y <4a;]^ cCc i3HV{!om'S6`: N>oy7Eu ӆaMK~(4yr*ʩgȒ{ݕRx63}ZN 7FۘAZGI+-HyIQʳD $kP_@o~O iꐰopxbkq|yJ8s?Izamq |V8:S?9`4}}4!C9rngD}mɌkjQڌzn5m5PP@;˨ZrCnau͵uS>@[k&nZ?19<::+x Lb/:bxʳωq6vjު}{]i $#๞bwvY2D=D- bHgH&俪R! *R"-]յMB(l^67.ENЊ`/\ݲʣG ̖Z0Cc׉u9ضo@kI=_S7ܟQIl"Fk;BP~8[WC=מ]h4Mm1ՆI)W`G<(ň^[fXVi ºk6ˠ)H9^皃v범idhA˛7o!g.mm{(kqfU2L=}(עi?H0;~^ڜQ~+إ5#.\b)ICV&A.C#t 7t+`7`k&&QH= )b_.%cGb&p2$i}1dWͧd\qc@>'#JKOFI}ٖE&@qH׃qR䤎mX۔QmRkdc,ΚTOarqA 1t" @G$HϞlL0 AJ348&q?46Ӯ@4bkߵsRXFϑԄY9#H!d C"P?9C #(u ()7Rt1cdX]~z" K|e(v|>sG\: 9|5F2]˾ pŦ*Z$LK|^F!=qZ{qMM&b QG53r9C?HU]JmK,IPp.I|}rڟGZY1;q{ӧew-|bW)P$Z{L֕9Q%f5pIx@Z*TtC "VСڶŠMmc\_07=VTah߆6C\h9y#PPR(CC(4uG;?ҭW>w{V!k~;5Vl7w)3hEwm#"}x=w>ͬZ$>p;9T'1\$cޭ7) si|漤,#֤]7J`.[VWQ|$IWW},\v3f8-c;ˀa4\uz'M=]/@?DT{880<.u(s*p%bE*FcDt=u?s$:>9q$? ΪyϞ=tǿe6EU)SfR8 ykʵZcc趉Qf/ h?APrcyQav⻟}ݽ3j$;~! 8l{P4h, B2cff>9 sNllG0#vR3Ql/9_5ݲ:so{A7,K|mJB)Jv@,QoZlCoGk]UUI+HNV6ʝjm~oskW0),\dr̶ɮDA;Sy/f¯aeTN=l:tX`JL_3 dm].! qBrǝ!>*AH|#C p:)IdSk l?Ꚙ@iS3mm RWe6CZl,r.y@H`! #FyՈ$BEg乍S.sc!]/W9:. 7 d39[xҶʘ-uhoj ]Z5,8|'>ןa-عz%7yCFx|k U *xQ3GS=빠bPViD6PzozyI\7 [p$"c,Ӆee9 !PΗiYgY$}u:>{5vJ]J~!]*m8E9U1!Rpͥ-^vӴ Y]fg]wvҽ> j> R '<_2mr :!k /~ۛ0(-;ЗWP7ķ"~S[kP,6 [N]5j#1 YVBO+[]lp .˿Cu&ȳ݈ ;we8 ׾VmBн8RymQO {^gy o԰ԱTKW~{OpóVs/he- ȇ?:8^eT@  Zl3?|o/[h_שOeDo<0G6?Џ-bip ;aCp̢m{Ze:p=!,\>7%]񲗾i}$qnLI$Mh~>cHJ%Ei$_wGq⯮"53~nNsfjAyjK[ÝoV9>sa0>9܂`2C?Z垝fa6ݝuL ?tW;׹b?\o,1y_֝{p96Uߑ#HgXk8u͇<.ܰlX8K.%H (j,UrzigT3/!ǖ(ՠ 瞩?Fֹ iqG?x[%e?s㓐c0g@' W]R}x۸9:R.#YuA{RQ.i3KJq9(r8̕,-ZJǶHB OqWqM,9-i4C.q|ήa:tv DIJuGA@%6,7@8b{2èYMZ:\L_?[ϖ~6]E~lH  2c%D>ɧJWy 7q~tO s4{Yrx~ յ(QbeFc|a9n ah eئ[o&&nq2L+v)RQsZy>SX{Y_ WөtòB|ִ>{WW>w ~oepye)Ä4/\O ";6 Ig;*lƘ" C" =|O=˲>X]czvUCI0`%_Դl=gN!e8(@$U[[d2Y\h@(vZ'h`EzcK0Gq2'u'= ֣WM|_6셉oϫ6s\;ˎ;{;Xʲ#ud!L 9OPgȥ%hj_I6 GGϲGX "`マ % %Y1\{$o\<cHYг} ? 56bյ!tzSEjFL3N)*iYs#u,_ \8Δ/{o8 E7}٤mI*ŮShE+xX%'tؼ I˴@V.'J#Ut9p i5*s0$_7>"O@uX8bU569L h@V˼oܲcoaBV^,;|-;Uz.[ic ׽ d@3BB^$%$4wϡJ}H&d{RI ,Nejjԣ1tr$JJRR3[yK1o\'TOTVX ~'WkE<8ɮUXeF!L@,R/ !?u SM7ho n@ݿmY݇oyjH(]pFc N_+'[$5t~# KZ96unl& 0ԛ!r//̋X])桹p=.'pJ(x蓪Ax^[bFg*8p҆'q|* Nfp8k:\. z |iR4؍!67Ea,C ?ăX 39W LgNt -' sy(L]s h ÅZ2  ˡ sKJVj?oa-|B|O Wx @W]Npy_8b Qc&Gzжs7vGqo˲ + c2%(jH< Z[`er rr zS,,JCa1 ,yS)'cf(-*ےPs,GL#X>E {^ܿB Okş9 r,H Jg2bf@/4@RT02yfoYRn eQv#O'llKGBz)VZ4{os' R 'ږsPQU, \jO ЉmYdDE| rC&`' fXLw|]YDJJ@_2|ݿL> ŠUץ꯭Ӱ˥S21- NHM<}ۢu/LTWKt/?窟k`);OIm8QPHuHI2'1AvaRyc‡ : oC3 ֛oF `dߐ`pɳٞt*mbШ[He}#+m[ N9D=}Q \*R\](e{V UԻnBF;xm"?yZE Qp$Hl n݅$P4SZPR@8H:4PBjQJď45W^&8/mjp9Uq16838?j2 9H W(==5z]W;cs/~=wrgg9GE FζXQI%)PA*1$4Y~"~)I* G ڹu.SD3Z>R&WiY>9A=k[󹬝ePc66ӭ1Q`N0t_/߳~>Wb\ yVzΚ!;R!L&&Yݨ2D^H'1M28xJ 1j1Ja5Tt3|MPVYǟx!SA m=k>08045&~ ٪vQ*;zu Th0N-q$ g`$U# h#@7.#" ߳ҴI- Ug,\a^|:NO~@[>㨮't10> B^qX#PW{҄e`ل>f{}ǭXGfx'IG>O}3)M@^'Ndh?!,sˆ`}{ݯi"#)a8oՕϼU!)FKt9B_KȽ@xP\ŭYˌ .Ɨ\ 'FH`@@IHK恦J߁c~7% VؾR{0:1 @lCX]pgU KħIn `:@:D`hڻȣSv[.ڶmAF&0r9INK_]BdI )jPPvUI gyBus2vAȽY:^ѯ0.7gXǾW@(U/#3{}czSJ`r-[a}NS(4&WfhOd.9UaSw2EVi.} ȟtS=}k=BQ!`@B:h#'/ ce~RʒL奙]E.k. <_hl۸SmP2Ro=]:g$da4΍P ɝY혊ϳg29 n!&q \| .="~n+@?j!{5|Y| [t"3Ϭy aЎ Xq UHp-#$h_/lcML&}uR/vFH5Ҳ+.ozW8s,>{LKE$%>{"G" ωV~v`0v id=+{WyQ{)FK 3X "L*FWk]X @ XYhtjX+c,&Va} 63C1u+B{㇏-%{wHZQ#^K^ d=ַ-!P?-Cbq]FkŤ(L!YG*,Gj1 AL kAXy76gv횜'weY6w&HnȦŅyVZVah.B92gy0ٍ/LTWV~'^5uK۶83D`l1B #_Cc4 ghKXM:>e = je  jpq:\a}=>RۀZ:kmxY,*4U# įhls>tkoljka;A7$wTCK̯2V½g)WdDu{44k,ø:/]X\>gͺot!vL>J0Tqs˶09vv ,DsD*Sѳ#PaH5u<7{%Ŀֱq+׀m8N{ݻy#@$kc'xGeA8rdh16`)|C! :1=P r C f #\PBwKʖ]LpJZ_y$4޳]3d F5D׷k#,c)@HSF$~_r~S X0YW-0Oh[?}‘0giPt~1SWgfGu_r)&y)Ry᷼ڶ$s޿0300K1UT@X> #zlLDXF R:*z4(M9i>hՁ.~"KR %S=]O|0:k75sOOGeh\{63cȂJ(|V?d>/CM7'?f<$#c$ ayx/ X ~ x+0y׏I;1{%-FǏ.q]cS?Zs~4-0۷SXne1&PMB(E0ܓyaLs?c+Cfq+?N/Wb3´z״( Bth#117TL%fK?(7>6IU\.[:LAƦm 8eN3LKG'ϰĽwԑ`l݉e!B%+8K/̝!:Jf,'fgr>Йg9cOJ˞C' qhX"Nǧ}_WeQ,aH"l #oSUӅlވ3 9dRn\$b]=gNtfZd]ˆ`M}5q i&&1زif SG$ eNK²DUv @NGG0silۍ}j^V?GWs\;}N^u8:;С|:LOod8΁ 1$CaY O R*pW*ԣcTY a$tĩSAcVyV& _#]e^׀,gF6'76pmttMsfYYrҵf3Ų٫5`gJ3fQ>8zK!bn0Ȟ{a,f&ó zSGKcFRriouhz'1CR:eo$7),\68V՞K˰A ~ fhܲ )wf,*CaCH9d}UYՕ()陫8:ZW?0H*f ?0N!|в@W,!H2 g;> Vr9aGL 8sW27cv9Ll2 :oP$ZhmZ>\^QɉY 1S rVCb-ܮ^4046B?UcðR+/c@5GO=adaZjT0xbɾҲwg \S-]&T7"Lq@F)m@mq,e2 doY8nH;{6o汚Ij% hf`-P2-訙S#< mۜBK ΞOJD۶+Gg(*+9*knȦ`r 3Q\ؔk3$b 7!<4 @ m<4+!yV8C8f)+; O7mjjjHyT*2kM˪LVd4(*-VNBM~k\it:K0XL !|D:tZaGjQrV/R VhoCG߄i;y,9<":x(Tj!A>wSO?e !C[kGZ+7hW)ѩIC b2BX4I)*0aBH ?ܭMYHbdS<"PН0xi'O= +[ |>pK7|V.. H:Ț00w23)%ómIt[ICWo|mrB`r"F퍍SѪ(AO "^R2H MJA;Plɤ{^׵V|'Fx됻®qilŁ)9~?+T=M;3KwV;Ł> d/*jߙWE4eAy ;6Bl &{ܮ=pm'r<sz<.2o[p @/}A&,*2%8=e<>?t38cq^Fgz|jB`j0 83pX0wf ky0mbG?ۑtik, BᷰJIKeʁ1̯E|>`#%A̴d|Z<-sQHW IstqmVLn3NT"gtGM`;>_p"?ɍ%_ t3@Mk !n $ʒiXGX26#C^\IENDB`?PNG  IHDRw=IDATxb44000X+W(ڶm뛵mk۶m۶c'k$;y3 L/2y/ ࣫}B?nCp0i؟l=ߛ+@We! bsst|z|`ոAi#N^\1b%fgdNtpC[W0Phc˷ҵ$|/V .l Z3.Pŀ}* UP%Ԅ AUlܾeafU9ûc@& G i n |OzF"󱾤vGv w @5rA0!3cf Wte!' '%?p@)X5u?Z=𲲈b׊9E8ˑ=&s!1\.)rKr'm6)2Į3 TM{DfD3XcI0Pd+B>Ws|׈Yjdn >X 3^23ǝv="fÓ56AGU Ӵl!5-[ n 㗙fsCI8[-sGS6'`kVD09f!"zg~q;#',R*V jYe7qA}AدfSx)a>N[Y8 _ =%ae``EUؼ̂W 'O 2? <N'64Udreأ3}gϝP <0>T8EV.fH<3Ge V8zQ~?Ym '6| ~Awm Дͮ߭l<ÿ@7Kҋ;wz dנ1㇓!Gxϻy\t/?ly+u'Bho=ϳضm^JqFAe)w)jHƒ dU?=rJIENDB`PNG  IHDR00WbKGDIDATh1JAF x4bvSz鬼dAw.O" 9m 6i\ EHw3YyefL>:X=a$RBð ,IւI`* k! mc5+dP"7-N`CxaĜ? KށSop̹bCOZР |yόu,LЍ; tsg$)-5Z>l7X H`H:Dj<`(QJ`9-i>7}3/V1J)"/KW뒅uQIENDB`QPNG  IHDRNFIDATxH'9k۶mlsm^۶m۶m$ΙZU*Ojذa_ᯧV^/|`c0C15A>|WD2d@E1 ݀9l0K]UG9: 'Z@2s4ma֗ŷ"( );,抈$iQ}곻ju1 h0pD_Sj]sD;X!A; zEſWi}$P1ۚkGrmҠ8/D$=i9=̽"5ײPêR%@U߰f} 4C K5[_>Pg,=Ew/)@]1WXd\dtƄpnADL"yCTl,Azu訸+`#,Oy!/5H8xn9ybx@ \Mhݴ9F?>ȡ=FlLy) %y/Ӫq $4LɲOK&]ٴ_Һ6W݂lyd{ D~7|WD HΧrqFD-ɒ+4WZ;ENYٛ0uCEYLYl7_vZ+o}6u:fgO~IMv5*b(Nƍ6w*{R)ʹ >.lV'kƓj,!` 4>?W&(]x,_iX>@ͪ\\^r;i+lWϢl@8';c#%IENDB`~PNG  IHDR>aEIDATx  gG! @@@@@@@@g׮$701$ff;1E#oMȗ'cYskIWں啶[Z /[O^~ȣ}KƇ+# y/. ;Q/ZG6dWΪ}2(qۀpZíT`$7HhNl"T{bYRvEzzG{Z#6Pk{M  BEqYFK"^j(UqHhPt6*C3BVۭAqc̐!\[3S:Movԃ gx Ԡȸm@!$01\x8߫z\xw?AqKɶ~}֌3$\DzȞhPT6tA=Eg7AQqۀ ȡio߾zaR* +7ku [f~1Z:Pk SP"҃ v`]xEFϟz> d"ݨ M6CtPUO=NpjwkP6p\  $A9rs^AD_]p &L8V#O zm `Ξ?݄Ht_+~@~HܨJFvbS}JAmN&uD]m֐] nP2FgOA8''Hhd$ 9n@ Jaie  cˌ0`B|,6ր.>nipq⤦O,Аӆ{!cqm@!B(! 'KwxQJ$]xg+CC(!m1|ܨBZdo7${+hMX(㖍cMԚ$]QAָmf/{v,,IwIft =?s&p&\N.H6U-hr$77`KBA+!k2[6Ljg 1S 80t_w!$яn > $390o=n!p cᶁlePƾ~ ?_1Q){1LrX=2sʍ0 @vFBe7Ir"TŗDX]Rcgo{Ku:@ Kb*GfY 䆰m,!鰂qZ'*a A D Ľ(AMr}@Bd/gJ)%wb 1!rKYR0IX'4Ş0@hИ( py`dW)x/?R vnA1{%͠0-YHp@,׭` Kt `Y2%v01֡toaT0 PbPpBhwe%Y VAt({Ac]VA[ 񛀭{?\=w&vøa(\J$h%O.@^ծ{*CبD.:gyΈ s/+kAD &>N rwQ%bv:IRMӢbP7rbűO ݎ_}%gp3lAUlD| J R\9b͠tQMBÍ8 -zڥA@@@@@@@@ +^IIENDB`, PNG  IHDR>a+IDATxA0D 5`˰Z    2EDsnR8+UQ%! M@#C m1` 1 */u3w|ι;r:>ฮGX6N3NYw@%p'Lb+Ƙ|>82L&={|l7̾ KR(0Gq|'H`SRyf9t]Bн\.G<GW{sT*mf'bk٤jn9(a zht:(GZ{8Giyrh4mvW21~VZlP"@_$/|~IcVa|rLw>D"0P.) X, ~s@,[k{m۶m۶m|m۶m2D1olʈʪ?AVuϞ=޽{W駟~A%v]80O O4y"q'?s@O\ ꫯR S߿(ޯ_?@k}*b5G{D`2@W ,_~(̧|d(5PF䫯9 i|c~7R &y䑋OǪ rXOIw\Kyg9Ʃg&[0:.$a٢~>v衇F}Ȑ~/_|!V@b 'yH>Rji1U 5 oa;]/ܟ!+F<PV=ұ QvX8$p{{8)^)=(~R`G[oZK:X3}C _ns[j:@ML[$-KG|̑a$?&>z0 \%9"J} z˿:p{X$Q+H3|Oc Qճʽ"~zAqT1OI>1|otoq(:2i$$-I6 , ;9?+Wy]0P$^qM(?$:]v\ ~>rn|;bLBzטjL8Ybm H@z%2̖J"7 _ it_17&rj :jR,iP֯Bxb ٶXR΀ drǺ^a L4KRj:BZEk,>%2(Le=$ֈ м. _ T_y~Ē\-БDŽ Y16kǚiI.$:1#T3$LK^DIn6; r#r}` 8(@"@4T7wɻ Hii&wf`I1HmFp|ݾƂN쵥9&'Il#X dH*glc5&JL-8C F#ߗ$Bgc/4n3=öbtIkŐs[, Wz^ +9\Vg-=1O{%3O5K K}*B"[)<tmdtE;CJ$y޿xiײ|e\' C#U"!i1쎖#F2~.FtFʇA0n!x< :Xf0qX !@߰w#N828|TuL@+$Z)om)S2"}ט!T/wy!$~>_m+a{Fڶd uA>$U2 E2S{1~.Eeq7߼-/GBW-qx%+h5:7k.?3ns=ܳ:餓axp,Y$(q~91/V%~o[nՖ]vMbYA| cZ?)B&(gYu>1/>[M_~x,| )Yg[WW]ukI'Ԁ*Y~@f^ƵQ@} ~פ뮻Z7[^~S:˧xjMPZM7)Kĕ-CijVYeM^xUÿC;lA`'J G $FmTuQjc{+8O8NVNhn|6!˄x|T~ 7Ek@$y tkvک}~nC-/ã'\|=0 'uUW]uEB{D;kX?5`@A$Z:rH&Pt 9"~mj2,L7t+1>3h-~`[~Q>" (rzMn|}u*8}%ʘ?; 6dZ-09q3XR`wg3303R8Cu8maKWuǙl8SU[u?{o[]-~ZvT "27dd.CuRx%@r`cҥ*xo?:ٛ=?C^:v[^Y=閈⑺d/ʕ+ml5DUѨz}%PS.dj5UCx5}'xbԎ4yh[X}iVѨ,^*'8ʘF7a.7Ps-muX ͖X_&ZI4_x_]jSj9g̗L*X.`?@֧|[|zwˆ]iHc/e؀=Ĕ: MQ VAٌ}XBk~#kࡣy=4M *fvȚ9PlMnTctV#n)+353^:dԄOʤ1-SGCAQgОs)nb1}AydLK _a>!BK#rl Ƕ֥@#or_*2/~szOS{9y77w]]6*bWUbЉ97s)HensjYHw2`ݸ;i1FWGgW<g}vZnoTXȧk=x>qXhl"Ҷ΀Put Z(5xB%K)aVM0M ]`ᡧ7j5OgȆ7k/U:[tL|Go?K&c ˗ hR%2${:wt3hsG@sY#iuyjr?螩`y>/nIb|1 B^J"~ZAI_c`X==IJJ 4 M]Iz2`;3tގ 3WJi6.;QF﫟u6RRH2K($b8W{zM[qcܠOcPA~Y;J$'ɁxН_-ުUV2 EHT=f+Ig;2M@GWO-ׇvѫnb U$L L$ 8g 4k:$\>/9SȒ Qy~ C>n@iFxss]_]#J*G|b翡Xo1EɉD3m$ê 8ד#3erKG*Wed*d <^Fnjw^D^ޢ0eha8o>$A|xu w->s䡿Ѐ0]c)VT0t !L5ӆz9݂Ю#dw{-xdZ=ߕ7oi)YE&|O2k3EaDqc#HNˣ~Fz=q]?)̼ԀuXnnܪ&,L!Lʖ޾^_ٵ_N[,i\#e?=oDl8 6nUQeĈS#_݉ܛ@U!ANbˎcQ][I2GŚvlf㤍8ycy.R{^8-؎,Yt]@r KBlNZI^43e{|x&*+ɉ yW-~Ɵ` u&28o1SIdڿ*|Tij#4k%7LJy,2~lw˙S@XI f͟%Bq(`leE>?1U0Zy QcIqcrroM_]x o xC 0`"ӌXU2 fK>I{TCP_h`{ ZpKڈ`Χ4oܔLgbY໳ǀ`i'kz⬕F"iuYѲD }-sKfgɴt$k3,|Bןd /K8=?\%ȿs.TL,7#$׀1AFmd > :hϾ6И]IT4`j&@ݘcYoߓ8tQ+Ś=K |@A!Pzuj% t D 3kG󉅣м:he2f8&7ef޶)y̯LWEՖnEvUux )s4j 09 gJOι#)R !RY<"Lydžäb}` ^>߼Db \rT^qާOv 5D(,,U4c|kĒ$Z;H?1L-`Z2WCyyֿсnl$s1~KK'`qW7Ns , W&dP ZT᝼Z>!!ʈ P7ϔN49H$(Ҫy2fS4HgD&V|n5N?0r)&MRhԝw|\`@Pv! ;Q.Hҿ4/( 3gۻϟ6Yu=Įct@%ntBޝi9uhǁfO )p7jRDpا1lܬŁkBQ X*_a J0R)ǝCpw}rceCt%p6RW 2@B%6U i1D:h:xï4rS<ZR` ^D-N/򑅙ˊZfRnN͔:/X(eѯ+ Zu`MM0qI7p l9Cp"򾤖@6JKp]wxb8E-}vvw5~>lt@DvۚMt8]<Ȼv[j s 4^1f≳n~PS͒åwȐ! PF>JE[Lq*N pAաv_bTmS?1_"[BǕ制׾}q2㮗~($qW 2333f33FY3,Su)8f3칍u&ϧs}y9(u'.>;hw0UH@jJ=ݛ/ 1=xIP|> BhƄ ܵWZutTMx'uuu^Uicq.} 1S㧧C \Ǐٳgdpv!^+M|]>LI>%dӧOxXY]:0K#1o#TUUM`P { `pt08|!ux ߶AIL]XWhHTMR]¥~FP5u۟?{dsF&%H&^/*?h:(aQ:F'qQSx2+x0kF8f|x|::&; ?Gľ72>6{` qMDd@[46 j|@+?-hO0W7߬S}jΒ6(ox\7XeWYO OށGa9L >Ng˛1Α퍵n7bw^\&y w lg/pamogvLT3N vc yF _;pVUVMnO Pa1xX'H:Q%UH"2y-?asP`~k`g9 9M>6.$>{FZ?6𪴄 JEEO r PUjff?wqdсթюLFE%/pS`kb߁dz_j =O [ǝ)OSu~rzu ~}1u?{73p<;TsN Н U#, YZ I3\􏪉e;)4/z'ז@VJAt$X*ϟ|E /~ /% BvۤĆFGwRO8([Afw5-.WbWcc#g x ::: 2q׏ݵ&e &<:VjFʟ(;Z7jx*iFJ"V=$[鱯Efe'S%9:DYjM}c*I%_[ %sXou眉$OUSzN`"oζ6{E5sў7dxKh (@s*'= yU&!î)6249>>)RS⎛BvЀ$]HbId2mls$?=:@Nv$O@SKP)9PF9:4hN-05p5nthМjU%)Oh Рv@!t"y:@$E⁛5nth tj Q 2u/@ ‘vIENDB`aPNG  IHDR(> PLTE<2~~IDATxc V1VHS`$aIENDB`PNG  IHDR>a IDATx1 `u첽|e4(p b2 ajbeU̎ˬ2*s[V}NBXݫ/;x̙v.#-;/cVoeed%Xq#wz FIG;nuϭ_q3q9/iΒk YzlKNz~r =!J쁳z/3+_-:y 㮢0q/슁%WCЭ_LXƞ᫱RE?@ݸN3pWpϼ"#gHcUCw~{ qzo twBxRӜ~z>=NOq>q<~-󈅘|Լ1[gd"e\9[00bGZ8|w}?܅V&L-;}4qz!:'cm؜/GL1`|q;)رh(xIQЪd'X"ͮria"eD,( woM?Vg>%Q8P(D |b.=_{MW"HԷht}ڂuݦ|&2nkeB;5 ", /[G;nMuU*L om4]N/^z?).uQ{ z0wLʿӼ1[OGU.bOSCݷ`ץQuAjmfq|!6=|CjtI%bmd1WJ5c m8o0G3,swNUB<ń^h6pjͭԿlnIwQrm5 MF;v((G0l14P$}/vV0}jw &1U\lK6o4L򿇱Z8\jHY>j2]uMw`-'C5Q- QOTH'{S_ɪc1q>(J]ia%^j5n0vp zYM%3=S7w+7W'9U%YG˥5,2& g:R8jDS**#^h/1Z$?qvuB,`g9P&Q]_[Q"F  y|&UM>]e 1!x.ca,q#y끩` iP/S-1.깆AdcҔe(|I.|q0„4 ZݖNnzL]L\ *dUtZ"(@GpjݘS"xROf UU_z=j Lh)+*[roo%3O5ƮB* 0q)aa%W}Buk.<RV4g+sSE}BUSntŗ2věE5&`?Gܟ[jE}-`fѺ!޼t,h΁0ZJ{@';x&A(拡> n&Eō7oؙ'Us ʄ1hpNkyQ1Pw &҅cYy?wBEh)K7K7nwQp&E$*:cAua7H%N`SJ=cъfo"r%zn !G ~` !9QʣyfRLׅqt!R#9蠎0L  GL]msGyu L;8cAMD9J琂ϡ<{63i\6:-~)޻z+u\%3s(rB}trL{S-xIi?b"~JMe:/(V<;QM fL]뼯YlrX| !bCͿ@W;QuvՈW_*c7CzQֲye抸  Q`Wt cv!џ̋)dXcS 7)ŕV"g&-6brF0dܧVR@Q\/ڭ qS̛*_p#ApFq]A8Tfz6|W gn b,3( ԊPB5clƵb% ̠6̫-Cd"6HGqM f!2!4/y_7C0Ϭ>̖7- mvk5ݥbìj ;UlWF⪕ Fq5ɢ+7 F~L{@C0ٝ-Ln5d"O_YX탈:u Bq nM_R`n.@ct]gRIӷ$]{s_R6i2X=sk0覛n馛n馛n&$sB`ӆHYn8dFl A _S}O{H' L;(EXrWWVj0'֒Uq\lXS p' $ Eee%=Α󳜺<х^R&yZRץ{B4<;K*Q'eFã02v[]*,)s΅diSSDWs//ANylAM H}pwPbd嗒57"\.r$B]EjnR0c=d񥆜Y b,39,_rQ*;3=^ķ^RN=M 9BkL_KR`͟CN17߈IUџ;'qt@6<{W? HTmiiYFH{ |Og<22_ENr~S:޹v-+x$eZƪ `RcH#7CY]=gW*[ dvXq & xeffe*NACn9w,fϑ/@W{'_oxK^N L2_ "Gnwhxwpxx$ϒ9\-wF ~*@GА<)3 8Bol*~cy $큌 zVF2΍ 7]DOD&k&QopQ+8l \4?h(9rxA~e/B<[ 7^o kD1DQ*G[¿ >E* k87$/[$3YU)#M^r̭ڐC?#oUUFXIk_gN+MA2O7(@{/Uw/XkBϔXNx6Ra{ǣ+b ֜!;뮻ȑk_Iye\ 6FD(bDx{ Q^cCĘ Y1dm&T L7u跁7ѨK/}D=2s|9)8K`یZMmb1&y[\mtE>NMQ,ᴆP|1ha5Lǀɑ fuE-]_c 7$;gSՁUUlkMAT]2Pl*FN4b4E_=b!/X\kߕ Δ;!Hوj Q&410?)+Ν;XYţ^-=vkbi`\PED) \kILk cxfcb1BxrKk!m8YdqAaH>G L;oL N1k-jj J'?Ban6w+zBgɿ~?]:1n~Ayč7`8f$^X|kmUqgg )\4.NBt gX` J[<f@Ù~K/ff&Հ=#G^d[R/-i#˯ι۶𨃝0[I7':4"-p'SQkp7w` ֨O@,#C $򇠼_f ę E_D{DZ]׺9Zdߥo@}m5/Q_rΥAم\04a434%q#SX>)Cap;Ս&Z< GpCkظDqO,3, C8Ӌ1hMs/E(U[2ȑrػwG0 eORLtgm0vFq:IsU\Ui$|0ƫ)s@~ nn8J``"hp՗a[2O3 g[qfKE!YʔCAkm\wuZqrt@\%2uG|9OWg1fH}ky+ x-ʹsxVt+ӻ.[XxW}j4"c"a.; HA t5~090wq7|9t͚LR}K>5dԇƸ1Z7%a% IBo? 1"ei*=ۀ sߥ>TUQ|22Z0|=8Fpސb9i i5"S^`" x7Ç:;_'3u9΋$|MY'"4a/^Am,MR߰>pY_6aU{7ې%#p4í0r *{qF@ v;&L*?256i61̽fu]g9k?=>kbS( `ǟP5 ; \>0iw˸>yoaQBRc8A\;Lm)s^30#7Q'\އb.tPjW? 'Cqv^He `cҚL =TDG{ZY6 6 n^+ܢsˉ>AF'K%?'y. ӄ^ϴй7=g-^J0D,u4k wv' gV3q̽B`-'&53cn2|1X 0meB_*~MAW_UO>50v߼z(%oo1PvyIRѬW-n 1)/;iq'q'E^F-PL嘘ď O _%ヌk֓?X,8dMğČs :[{:~F\a iH[۱>XN{!srihN/;Q@#0k`μ ?3[T uJm0ycjqԩ75B_o+LOH9;IT}W &( &o7H>fLl_K~BJ@TW*]8Y`0=2k0va9\ȑ#?41oR[*t7gyv&g!kcy~׀Ӹc-C@,9s;/qNMTXz{eJiHe5G'ʼ'RJ ߇c>rgQuEB6 RO+|߼J[ ۛzX_ &غ$+/'cZN<{vO#@BnhƮUZKA'Eh1qmKy_~jp=w%4X(ѦPf,v]C0P%c{B(} ?+πw)E8b[,92@P5`>`?-u]J`"oMп-Y6tv }Łtos\o ݝt[m}vb\+?4 -p]r6L57q ~9=ڙߓ܍Oܣё8毝F\PFv`g.՗|[.NU]WtwǏYUկO k\/Csl.=Ʌ({ϟfd_  t[v.y$zͯuXԵhI ;0>F9 Cc Ke' 8$ԁ<@)^#s ;~aDS6=hs'JYߚ܁Np1rraBv]gAlГ՜,C?}-!hks0>ea|4:pH\ˁf2@Ս Mq N%n8W(p%rOZZkoo8 cX'_2j)A^[3)l !8fEAscc|vcsw}r[.*Fu\@v42-K4e  P@ꗤ.1W"W+'YU{+++0I-<5 lR3s BVIi9ƊnjՎ 5L`rN'l "5KI@";Ύ]Ҙfa(.@idQX{wAkC F;\ /1+T)wΕFc)wm{GD6pSO$'+ HS#ۢ @ӂVKt\ɨ#w` dQBw4sry+&?%\S}覛@Ƀy,dD~r>\aThgSs;sߨgD#0%Vc2 8) H#LRz[5Wzs9}Q@Yuaev([}b#E架+QM@GPfq. ݇^$HTb~Q9-ůy{oQ6@Oq ?JWXCz9P~2:s1 F -M ˂ֺ hyyj݁L)Ĭ)݆gz [ O+":dK/r{d8%ޑ;0r{$Ns|[eSA\fėxQ՛u,+b>%9n_cmQ5j8lKGLϲ114hR2-U,Re*F-V>y|2(M " u]H̕WT!?ArٱʯG@XG =)wy_SAo%qG௫gNo'aJ gic!>AV"@^!|A*9|ǸnA/uP@BK(7pR.gG|)!} h&v5K_cAB.p__m>bEmv,LE1iνY^ uÐ?%.%C PL.)})R@3R_|^U}Xb#z:U}sʁTv;jzhdlc~q &;ڄ_e`!6@*"71'&Fqi>%@#0gYQ6(& O 6k$׎Fc3\!q%pjCˊ?/ ? #v& (_>Y{'rϟlK~9v=|Z \jxyHe6ﯭ0)*oC A}a꧟‰'!^hbk9 {u)&IW׉TUsB_i'?\!f Ms8 @,oCNO'wTu\dDzKn\2S x(3e72nm[`_ƥjQBFYÙ&0hV [r@#Ppو+TUuߋ~}g`=/P-DA6lɮ;IO蕢\`9mQ5o῰L`s!P"Y/y|Cf=cSny6f׺Ru_7 O点n]uv25֠8Rs|񲄰e݀U85 \VoW&AYV{kˆ|ͭ@=k6 ]t[IiDXmZ,((hЅҌu9s(!/8Gq?O(Ӏ\)8FB$Wß8qޔ^߶s? ˩ӌ:ɢ Yؚ Z*Ҭc1Ky'~C~\WH`Dv? hs 1YT({N>Yq5ə3gnLV7j]k4.s^DtoiSHt\QyC(N6k<뷓{ @h:ԶzRArE ^a6(4O~syۭ݋Rs|.zI(kWKIF!Cd4y|f+r1l N`!+Z}91D-ݵWy_'}&~ĬȖL;1lL5V^B@s%2x_ 9 &tɪnVUv1UbJw_yaz4k?2שҋe٩Q:dѮ4+ W.>(+3)Aua9QG3ϣ x K0w\M+\u T x8g]F@{U܏YDށscW@UƍX_*2,v ~y=!ZJ@ ι{mjR!\AX~8{E \]_9S@ BQKo@ȸ&Sc u ov jlٯzg_{# @d|l>{D 8AܳƦ{skKP.-;Y&@kbK9RE&H61T&'[̞E+Yӌ'.=Ffvjތ!FiζѪN <˸]:4 +KLrUAua{MTk'0BxiU˱)Ƹ/p7/>qq%fX][n--= qy, A}ͽ_sB`I_?'5Bf MQUK]sɉQfUys5Q'Вs݁'qt0IOиV5Tq~gRy@6Tk's mG#eRUBlln, Ҷ+lն@4(3*ۆ8Q 0+ ޓ7$f7\P th?&k@sĔVIvlF %װvpWۅj߹)9{}XBȕFa J1b5'[PXH72{/!/L7@)7l~3$yI'&(3Aqz\/3}TmR1UA4 yĎ n`9: /dVPdK,@_`MM@>Jq ٍ\_{ t2S(Nl3,O yPJ\vo)Meم'-ܢ![ $hkGy5fϺ҆$d@N#2JP3WۂOLasVtQ,1r0& N 0v4bUʬgK␿d/Y6֛[f]l;'=6h N/ֹ#Tp^kZD]ESVqqu(^t'h~6meRR䩮퀠S?>&mW4"hv X[N|\s`KmdՄZܦJ`I׬"9_]<Mg[=gƚI_?o2ۖ\X TП FbQ #ꂀW؎Gm/GV')-2 QuƠ+ ]1ƙhk &eLBgZ(X 1V}SSp@ X;S'xR^ױH;k2XjAeÙommG뭶2+ޢ#{E)ԫ[@D V$о=̳Ki=U.XijƈJcTp6e ekp]YA>: PYzAPnXN6F{0γ3nAK-[bV(f.FO!$;O6tULZ|OCj\.#~vX -T\}&{a[Ռtߔ _s. FP(,=͵cKQyYΌ;"~ (xg~H6bΝY=Ec&/rU0yU:Ctw8&/gdP+ j!K [ Du'-]JkuX~o/YW@ =KmsXGuN\ZVU^!#2 FU09Uڵ3Zј{.?9fni\9\aj4^Ň7֮rJ k&<n@lB 26Vwg}²cN%ͳYJ&V<*wZ&M.kGUa({LE1*Ca0 UVPV;`\ll1Ԁ+mft^@s[ 5Z݌[C,~~ 09՜ 4Btm ]Ɋz)|%[_M߰ 5LπLh4<+|w"z|H@!̢hP\f@yQ9A*Bw ]9`8t 6qE{bmMtPSZ3ˍ0!'LCo:p%oww錮Gcуrs/i)ʉmlw`_ +dcxh e;6t ;T/{c}ULF50TՙLv}үm^Ky`#b'[W]QpYI}4ՖώBhSM0OhoUGka Jbx}\9*l$_!`Fo~^9 0&`eP:Vc޵!*Uݭ `ÔPv\p=²|P5<;aHl@vP6A FKW|{e{Y@ݙ Hz 7wHb(q'7p30 ,+i[53=@@<& n21]EK͏jDpTY (r9v)Ae@_lY CY\7A6@]u>g朼~8`( :VҘTY=̱5.QQjqP<"SdU0 Edt#Y*# K݁Cص+71p.t[O,>+l-KA#1@7ikc 2f%ӣm#5 $β.Q d|N.j\oFHj~=Eym3rLFCJv '-2BP$Ǧraj`˛Aټ;GB@Gs6_&yp/d[IQPEE?s?A@C p yZ0BWֈ|Ddhɂ8/.2!XQmg-+X9K^)[mpZ:dd4FF,{F0pO#>ǣ4<2R-.Zkwz]Jn*yU,hoPZtv)MlMm3t':0XB!-*mV Q꺾au+UC =::صMĤN%l)::`>5t9s#d4ޟmը2E`~.8GX(hܜLQHV +8¶H#K\Uι* `w+Dx)'m [ P pB†8Qe3Dq[L98$lm3w=L tWl/QtXP_\\<.*}9v!mxWEeRo݀Kc 9Ȇ|[u!S-7btU%zT9 09 mf$k!lQe[L;T*ovι.duK!fm%\E`kcW!n|m XA X"@M… c_j[H)^A9JزA2QMoZibrEkιbVW1ݚ2Z&h+L0sF-N2d.Lh-R[Jv)8?.54uvs? 뼿 {Q,v^+/ Z,ng/R2Ȏ~^|{ӧAli殹 djT6r%"%7{j `ZZZ +KU+P{&@TT3cGHIIK# +f s6gmjYmFFTk`Gۑ]at5Yɖڅ@uv%H -{ FM `?Ӹ}PIhUXѻn?t"s9tǻ/[,[7Tu:G9[LD2qhGXK^eV &cƌNJ) T8*Yc+;X@{H\p_̵1;*v)cZH?6k`U@aX@kl~1==XݫҗczBgs_Q{KPcMN PfFyM"TYȟH*ԈdAB]RKk9m PA B"zPeM@$\ klhyaXcoEeU4_8s8+ιgB|D\Ag?wKG8ż Vp۱$|/@wz^V[ʓئ͜ v Fτݏ9u q, &b_=X+8VfxlظEfqh'݁,H*E%E˛bdRUU~M )w.8~j\ T[+ gJ 4tT; zkFX k*-2JֺzSDS_+bv j1qPgMm+ %.SN9j0XNEXqp gp509i P^HA'cNܚhߗ#~@`na3O#zwd[ bޖX^5 jDp.8D34V1R 2?RaAjP>/ȎAI\ExRFZ[?z9bn%2oѤEnY?}-v1U KINpٳdG!1ߣ$$}^²v-~Af@64}饗"٭t%7_cdt`j1?[2J"ډUAfuJ8鈱}Q.\5&EA{M)wQۀ s/AƟL@~b wjV;QPay{P27;QKev9%٥Wն9;87 , 77zjwQcIZw.t@M\.lcY GiFqq[8b#%ufOBĎdWeJ >PLQWlI3X 漠 SmɸS.]mq*ÈyQ>TfTcUUv99v?m`4 :[9q~Z0˃lúf6tJb۲#4ˣdMw7)i/E탶زWRȀtdp|)<EqgP*U,6 Z^^vH|8nV:#8m7p-> 3 Rp\1H}Zh Y៰۽Qgjұ)a6P5Z%+gF8ѿf7n;>9evl܀z.͹!px? + 㩳=":'I%8,vٶ[Ĥ^LFFr:K![W%5~1/BVX=;IŹ^qa 2̽S)]*7Vt`34c H46CK5XMiؚr >!|ePcVe+DJbv8X hCq]w~WnUlUTiSswT?[v}:Y/C"Ixq=Y5-h�H&}lpe1¡"LPBYUЮ,ĉ2Y{ ;XҢtTl~|t2r4aGD~Ûp9iYa1?~GRK^Uo`=--60VH(0}-;a5z*bwknNtZT{F[PeR@}+<[iBr0ҾO5)UOF&/6Gt|aU=4DjR|mRxQC^M1n4(so2Mo{z->Phfi)գ5Ѹ3K P ](}țd )(~M 6b?WUFm!A`V y9UHq9wQ _``9`{#3s绸p ˱HLj5VMץN&k%Ws%`+Y4`HI!9vm˂_K9{9KU@;\&@jTFXrE?6Vc={~7_U bW<6n|JCO{8gXuthh!z-Blj:tsfZxo,G*nYi'-XQ7ː)0>B >[ѣ46mjٝO,[ϾZ!PJ 6KbSmn-Lܣʢ\Wи[s;?@p@f6߿fK *76=z"BX{if4QG^c + h֨tk_0f)H&ԔQx RhfV-6q ͠A;RWD"`+Kǵa0"36.ι4>sU1 XIJGEmJTk>A8u6j\XCw紭2k(c]kl;̵2[h=WQ.+/eΩUqi+Rn޶XKǩ{߅[4chE/s3)%}i}**74G1s (((tlI,;B3%t [bsUYb!: @4Bbw7)F`,-,)Ԓ)V h`$Gpv7FΏfϡz*]DieT՟ !hF$nWZHH\(˃~v/I#c|~b௪]@F})iii{gj9Gz>(Sޝ&ۇ;pa1fJZ4Ku暔ˠ r2 KJm%YjQ&uK\Fc0x&%%W;U9l7JTg.l{\̕EB7|7>c*{9i܁Lp8G5.|,C~Y T=wd{$Ui1]~]ݵ1bRN@Kpˤ-=>صyM(ԣK>_Fl,2lsplj;͹ϰҫMf!Wt 1W٘wFG5]rB%N`4X+4YT?_?Rz/]W9Jw1u;(*lmhD-/|ɭ4 Htܷ,ɟO準BaI{~P׵W#UUi-AA:`d@&.&> kOǩ~+uȐh3ς NC"[@{`P3Ү$bac}m(AՎ;އFpP74m&햿=՗|IUj:O=?x/})wr;t FTP])(!T咠h [UuƔZ"B#"Bi:Sϲì,|O?3역4PEnձgA"{: JY%)%R鞖jK Gckas6Lq~Ge/fpIF3_l{3&Hw*ǟ;&ܓo[ o d|'H Z/їbO|XtC>R9x@"wm0IbSr7 Qi-5a43;ob*uku)2n=kۑZ ϭao?쳯6?OƎ']_GTW7Y_k~  R"#)6 ĹO-5a֟,31I!=I@@츰LʤַvߋѱU +Yq0խ3w0?{ODZշJ qLןxϿ?á[7Y(o.~:;w| v-RE%@gL B5 U< _f=})-5*\؀{%& vX`#+ VWҧz'3| L]LjG=6in'/|Gyd~n>85Jz_&=;Nz;>+-!ok}n bAG<* 晹 ;YyaV}ŵ #fWFR$Ձ:>6)D'cL0Ln7%-B.pcT bI{,. 7MQ!knOmf_'O:> p!Z%Oi݂u]\|ng;=Pw{r@:v4@^ 0^#8Z 8S ?gae?b΍61 W&deH=g+W1jǗm_=.\yx?}SsZO#}D$SʾkZ2}JoГ/R|G(9~}Qf0o]'/)+ic*m7>ݚz ~ʕ@涸@05t9ϰqϞgV}x(; v MsތڲYvy$XX YOP_{ ͠pjys?&Ÿsѿ?O|zee%՗:qI5 Mu =.tR~{ソ5 q LJm '!DTEByte6_zҳT/fAf$RU 1GFإ$ىc2j(f B_lU*.ڃkof죖K=U? w~`ldi^}/\IvSǘqv[ܪ>6Ż=7)SЧI;p8U!UU7J O&n]E؅h&kNqe_yщ;Ģ1iyU|\!Gg=4W6X;#HP!R:ot`9z[>z',RMߠ-NkVwԧÏH?;wNBVy1MۻJg l''.5E'4!sG~A: /rPLm*w 2ǮAD&T > ȩSKI͌ LK;œ�a@)(א !XoMDLz|+ȹvYnqN$~R,'T$W7Ư[OjqsN,hIv)ۆhbjxY.,u93/%>9G}i LI"4P\dHHQu3kPd߶C Xg47:o&EteP!.]n׮4=RqKe?}8{lX^^%!Lp.P/- lA)、¡S෤着gkZ@3ˈc͘*#CMol}za,,Rmm1pRbEq@#莠BtֽGG{=f:`/Af4Q戱P*$ϦXߜMe<7J}oͿy4)c eō1ǔ_x@*g!^Y$ _8ICmHZuF4 !q/D' N1ZY"n,'^#p 6ĭR0 ;}<ҫ4g3{қ?22*3AzB[ض.[?.%?#-="'`!Q$7A=F.E  ]BrNwO1X[E֟`D=d8gO[zߨTC,*8OG# Y&{jPz@PHoB5>D̗h0UR# hz޼y㴷`-E/(fSDN:!G9mZ|}/HG@ TE20i #KSH;(ø͟4aF@[lYqMlӦ0Km-s 8d] |[n۾}d\"1?ˀ(R_ rg: i8e˖,Y2hȐ!z>H7)m:p!\8}jcU@ +sɗ> k (5k$9ZD-Z@DDk"".'? hA^C6lذiӦa"dY"uA'9{d'N_~cp'`]ÝO$= ,pzd^+%V4K&5|R@\m3m#R_:]Ж[n=u2x\gp \; Wk}S A,YY[_'vòԀ,sWL8h#58|Tտ܏R<%ܕsDp~  !5p"~N A-mZ wԩtxR2  9sWV\g왶辣m|>>Hw  h1O@_"p/ "Z)ifRݴĸȠzTpM6k;sgϞ=U-ٽh^iF<sT<)j @ƀq'; a_[7hqݻw Y?z-RΝWՆ6p)A~$J? &»T@}-1n%*vPjD|^&pVN[yÇ_Q'*S/>}^}D/3̊BLet-EUjo^Y!REswuHG@u懲wWEy'×5)E@{*-A 5^JtfB HKЈv*&D %R %eeeUhlTD&igeJ, ,^HN~+~%{)Sh>Wt*?Q$,#s/{gs Ba;}Gn\-]~'zR46pNsb H ~8@A@{C ` YO8tPz=&Me(Va9ǀ|-' \O7`Fg \'<5\K<2Wv]W +?e1O餮y¯g(yt9_q#qKPY'u8C<"lj#!X}sPO.dc}BVҝ IL 7Ro ,Ƞz87Oz}LJWA;AxB{moM\!)p*ۇum &lAF=Ouo HA63B_E(=~ꦛ 3> >> nwe`k";MpLr]v_!Ù@@yl %lf={}8k~`/& 1_! >iWљߧ?OaI@\/O/Q4>wA/N 3csy;j "{s;G]wcG'$;Eu*6L!"_"7eσC`}|x UKPHt0QLT:\mtn@Ú"O^YEg.~< ucQ6Z?@]`s.'!o 0 p9Xef~HAɴޓ_vB>@J:'Z K 'y'{{l{0牠^7Esy<.uz w&))g}ЀƝpG ~ g$#՟#L>Kws":o} Z @SL_IENDB`PNG  IHDR;< IDATx5|E 3{74H-wo$|!``ww##;M䏈<<|GMztl ߁9S0l,403Ow9i8h :w޹~ewwqꩧ* u]l ;01LS^snoxe֠s>Ѳ moo~ u}V*;7| 4j5?N ԧeoeFS/juXZJh6l;e{{э^eP>{~kgh4hkkKm^ Q`KQ[X`)QMZ"I&:")YCK:(eUԭ-Ξ)WՕk}ُW_108x^4M7G_cφBg8kHzpeePں]o 8B@DUAXO=cW`QE}ܰcV+Gb'Z ć vGUUi^bVi1ݹ2Y+jc܍QVj_}9@tAM֫XDhc)#/,y09VT9XG<y`+y1LY@Ս3-[2`oWuMZueZ%j ˰.Ybn^̶9}]e;!.kpR lM7+Ve m}w'IAI0`c ߊd^~.m3*`s+/a23SjK0Fw^x~HQdƧKM@:,K9'jNawگ`2x7׮Y<3P.Nly.XBg'd˜^yx`3OvMֲxV Wf0t[4Fz8ާ}o,@L5Նx OJ@ Nrrc liy1u6i Ԁp09!6cRq0 8}~ՔGb 4NM+!2s=5:R)Gf@/` `Nc=O殝1h&tT3@DX&k '}@ δ:TDͣk6ZZ& f>9DZ7@ݔVL50M 3=2( ?8񃭁V6vaͶ$oMK@WX,|'eTjȶ7U23; ,,նCp0z`)ͫ(LS@ͳ^S`mj-$NtP`YjMT!ŨT'5bVl 2}&l4*gמYZ 'I߂-X d <ūzxTt+\m` O"\M UDZ9`OU1=4?ЏG[&5=_km΀ل 9I#[|lǏ)M5 F68f`<1tZ<=9/Y<7}uB0M$M](ȉh]q6,;dlƮڷX(:mAmq갌FvQm~ݷwO ˓g3gh;Yt*jjj>=y69)F8~BCZ9"1ӕ{4&}^*K $Q:BHj,H=Q! o;vkڴI^ViI>7Fm\)R1%ȡsm|ѳ$&Y5yyyo|WK,IjKHpik+u`u1{~zH 8̜93-+++GO(h޼ ~SH[ǻw>}Eiٲ 6E9rd9Ű]soo_ Ȧ={Zf-ɨ ,c1y7%cpzr^rڵeA6&@4wxo# UN̟$IENDB`PNG  IHDRIDATxbـ(( ׯo9996t̙rrrxxxD}СC 5555qVUUfdd."$%%+ Y0:>>>fVVVy...i!@K/PPPP>å&M500, ,b 0s.m2ɽf63alv{2듪q%>M7=ai4o :?VJ%rmA[݌WggiDé4Te&*SNXHN8Ni> zsP g&3A*vs$,olw4X"*|C ɮj o6VeP` {n El@EpX8hJR7GѾeYOOO9%Hmج7\-؇mLg&!kC>>;;}0GGGg|+0{in*$GIENDB` PNG  IHDR00WJiTXtXML:com.adobe.xmp Ò&iCCPsRGB IEC61966-2.1(u+DQ?# EYLBQe& 5i 63ϛ5?^IUS/`"R&69Ld{sN)ijSȼ ibh`~+bvqZj(PQ+gӌ pHYs  hIDATh?hQ?xI:< J$'\XGgWuktQ\:5zD-9JDB1pI=sE/i>Kޟ}w@"HD BT%g|ރdkk|ELi jFi jy71z =h>R̊fe ]NV?׎}?V*5'~uC1t YQt~z) vΏxxӤҙV뀫qnD*Uy-=u 4iMv\"4#O&XaB3cqqB.%fG,T4SnIs2Ly/$'AH.$͘`dx(I4c k4f#Ntni>c.i-dz#xG r,ϑ2iЏiGfE]T;~fWU+?vJ" ,D\C$Mڸd^^qP˞ՐLëT/!)ah/SFRҚP)'cQARTzrthkH50 up3;z9[)us>D >pC~Ԙc8<k"?΃W/iabt|.Ef#颭s`d2WyċCQ8YnTUXaDAB#Gs-h Fm:GFҧƲD+醤 Zpk'|ʷKX1xyqFJxx hz[mw.Ph_P4 UO俙Co.=Qpj6R<$>b})D~Z\( H}PB^c$G +je,IxaPC-A.Wm.G||n7+8ߠE {yƹņZ6t4f/#Q8jWps 6OѠ $ߐL34Nw[bab͌|Lw6j|ؗ E‹>: -<☟ʒ]SƊ%8cT6[[Д|YmmMwlGEvkALG2i[s1 It$$vFv1; l!ϝw?2wr>+KʣIENDB` WPNG  IHDR@@iq IDATx^ Uy[{sD6QD$&ѨQ4IΈ1UV+iqرHԱhbiM NHF@* ;>{L! 3Y9{}ow}{}pgz|rE"[]YثӬ<29Z&4CՈgOGUMP,Q2{f0C-٥^~3hX>dPx7xF[T::7|Y܈ˀ+~&ѭG79k.1Ğ>z^J߶5i]| N|zYw+ +$Û؛Tw߄gsb{[&ne(Ef3o~h ri~1SdDofJ'OĀ)ZsiloW$)tkTi)3}}G|AOT6ӳ~}+?rE{̀Yoy[㹌㙡C(?NƎͺy $҃⛙Y|QSݭ|ts}b̀h3-j4&/9ӇO=؛.7}s`*J /1_k}&/Vj?cYQ)!sbIZlpw~0p轴qSľ`NQ1nPtH eB洏aˁPT糿NA|:n ! /gZR^ٺStJu@ʮÏ=C-$MC8p+A@萪0PZwp݀ HJ%ɐUI 8_#k6]Ge< C1bmW (oٛC'~yN '᪭!5p DcHGy)iVq`iC,ysƈC1|_d" PY͵ $r2p0 <7649m(C(ox@!oƒ1C1,5vɆ3 mI>O\H_O,sd !ȑ"R!:ڰIK:I{р_x卋T6%pBdq&A9K\…Il0oz%BrH ܡd(@r #.v r2AF\_^Η_} ]AM 8vƯ6/{ցB59 Vz$OԬ$pDZP #uHsl6i[W l^'lja$Y}ll<pBxں6!եwtB}D$Ǭ^|a`b?L P{^俼oTwF@o$s<pG T'BNVΐDVw8Rt.b_%ڃp1+*U*b@x=pa 8 $3d8Pv$b? ( 2|JY(k4H»3釥c?bGwxAU@ j9Aw'T 8ì5"rT!Ɛ=+Wl+>~ Arpˊ\8rCJSDO} 6O ~ o?}ײMĪ#pɕ\`.P>6r%Epó$,2m5?&+KhFQ#EAW ,8JxFsN9Wi 7TVǧ?x)~]^GAtx!(aQڤzO7Cndy6g|3K*4S2cšeq 8C\E{; ܈?<, _A.5nIENDB`lPNG  IHDR@@iqiCCPsRGB IEC61966-2.1(u+Q? 3Mͅbi\mbJ(F-i 7k?6oﻥVU낿[Z)"%W.\7ڒ=<=y:9`dnl.\t ;Mt)::=}QgYy)+P([5jFB's݌PqN0]+Ъ?06ViD2ନAK\\{d4wѳY3LLPK㜚1BB4u[=W[u$hbegS`R":t.bƞI\#5) Ppv|6d2f6?nezVV5bAǓ덍o++ɜu|1|ֽb=~Ͼ8-fŐ0L%5zi _U')7h|}$a],.sO߶Q00[<+Hc=utĕllnkg/aչ]v_xnd0=OשbTB$I uݼt˪b= `O9e3(3j0QqU*X fɦ$CfkRzu\:h4ATzSC+KcТ&\ɀ hÁP)ֽbT0& jh,H #dN@@?"tbg_ϹO鼠BIYOh2 PL &6n=Dd%Єɔ2FfLqo߿LLW3xX-'(S.w-k0JmLL`Ĥ^QH!P /r'hhm[AKj2_ 3F_=?* !crXMhIŬH&78 (F4X)pK,bFL.C@$\M4Mm~|ryTé$ &LK oV+nFu(dMLJiȍ}~BX(Vm*m&DY9G=Ort%>#>~ϸhޫ;q (T)ZǫTf[JwXw=-/Vir@t%d=Ck͇΋Buᘗgt?J)[>UxCeLZԒωՓɵ !{Yq̛9Vje*W@KH>a&'HIXp6mu?Fgr%W>+yxDx g˭Lӄ*dv|>o2DT j7i5G`Ba>ՎOpǿSsQvdG^{yBv=5d6K$?~6Q7.ZnE4ݿ / W^ʃ@1^9JzS5x~7k@hncpyﯛ}QIJԆo@&Tr")L\B;950Z>p^eI s PgB-r2SkTwOKg;eihZ |`>a>9X;ѢPoSSB+`+P(:!*n9|УNtRXKWx݂_7)iI"3*Zז&T! AG;8]#o}> >[| /b.pVeHhj2!ȝ^An\<)/p9Dj-Чr 2 * 'CeYeYeYe?KCIENDB`zPNG  IHDR@@iqiCCPsRGB IEC61966-2.1(u+Q? 3Mͅbi\mbJ(F-i 7k?6oﻥVU낿[Z)"%W.\7ڒ=<=y:9`dnl.\t ;Mt)::=}QgYy)+P({ |쵺oݪ]`]v_7s3plD:@7b@'N',={y#p/2ܙ"a2"8"8p 2aKEXOq,q i?^-`g! G#p!.BEb8ì Z%"|S;zwZw:n1%#9爢pbu?կxzP5Ty 8,=evzֻXa|qg#HvG8#p.kf^' p΁+A8Q1<$)xe`k>&[7%Wq8pQn2 UӺ YPD"ATRl 83H0*OAվ%?ߵpN>/fv 8՘15Ԃ!) qֱ3˗&"Ŏ -mЂUBSq|Es)zsf|sKgv1E5gѹտ s@Uq)Z2U3Ҕ7S~<6Bq\D8gፌ 1)J=c}ȱ E1G$h `j$)]U&^lB oA"قUF2H ߳c[05ՔJB_BOb$@ɌV ],}ifxa 8>bH"\\E%"0q2eoIY'(uF5[qr0bA`I="'!Zrj׿l_䈸Fx>DYeح$zbz-T ' }=F(2LzTA7>6̾P Kr*<E &1)b8S#ay.1ZpJz*zaЃ3#]ij.sf6B471^9NۯKOdTH`5ji@BYeWaUiBfߛeD # ujssi6ba2k >$Մ~R 뉂v0sͬq50l_ʆ*} -ΉsZ`l}J00^Ce\0!t`Y*&.*?{JeW}g>~\`O /F- S$TZ e̎:g]טy?8Ì+DHTB)}aqYe5zc7'/trc?W=UjY-o`=Z9-S8jvhٓmC>@-# %J^D^ YڽWt2/QE#C$TFK Tk;٥7,K+.M=U~r+#R~ˬ^?Nؓ(50oh%TQ$dɇ^8_<&b-\B-h*ӷxߐIcOn^b?XR//:iuV9^xy[5n (!7Hˊ4?\XGAE05pYrHkqf^1L t&|5,}fSatI5g[ٰ=7R1-<*Q`TxljS zk5+Ca`"WלI?'w```ٜv⵾f6׎;3g=F6\FVwUj iQub`Nq*.s !=.@'݃ĝOoy8mތ{`VwWjO>d=k{R%5nVn[핔